get_track_pregap_lba, get_track_pregap_lsn. Section on "CD-DA pregap" in libcdio manual.

All changes from Robert William Fuller.
This commit is contained in:
rocky
2008-03-16 00:12:42 +00:00
parent d995e59785
commit 51d9652c82
15 changed files with 341 additions and 55 deletions

4
THANKS
View File

@@ -52,3 +52,7 @@ xboxmediacenter team (www.xboxmediacenter.de)
Daniel Schwarz Daniel Schwarz
log-summary option in cd-paranoia. log-summary option in cd-paranoia.
Robert William Fuller
get_track_pregap_lba, get_track_pregap_lsn. Section on "CD-DA pregap"
in libcdio manual.

View File

@@ -1,4 +1,5 @@
dnl Copyright (C) 2003, 2004, 2005, 2006, 2007 Rocky Bernstein <rocky@gnu.org> dnl Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
dnl Rocky Bernstein <rocky@gnu.org>
dnl dnl
dnl This program is free software; you can redistribute it and/or modify dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by dnl it under the terms of the GNU General Public License as published by
@@ -15,11 +16,11 @@ dnl along with this program; if not, write to the Free Software
dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
dnl 02110-1301 USA. dnl 02110-1301 USA.
define(RELEASE_NUM, 80) define(RELEASE_NUM, 81)
define(CDIO_VERSION_STR, 0.$1) define(CDIO_VERSION_STR, 0.$1cvs)
AC_PREREQ(2.52) AC_PREREQ(2.52)
AC_REVISION([$Id: configure.ac,v 1.221 2008/03/15 17:45:17 rocky Exp $])dnl AC_REVISION([$Id: configure.ac,v 1.222 2008/03/16 00:12:42 rocky Exp $])dnl
AC_INIT(libcdio, CDIO_VERSION_STR(RELEASE_NUM)) AC_INIT(libcdio, CDIO_VERSION_STR(RELEASE_NUM))
AC_CONFIG_SRCDIR(src/cd-info.c) AC_CONFIG_SRCDIR(src/cd-info.c)

View File

@@ -46,7 +46,7 @@ development.''
@titlepage @titlepage
@title GNU libcdio library @title GNU libcdio library
@subtitle $Id: libcdio.texi,v 1.53 2007/12/10 10:08:46 rocky Exp $ @subtitle $Id: libcdio.texi,v 1.54 2008/03/16 00:12:42 rocky Exp $
@author Rocky Bernstein et al. @author Rocky Bernstein et al.
@page @page
@@ -876,18 +876,20 @@ editor.
@menu @menu
* Tracks:: Tracks * Tracks:: Tracks
* Sectors:: Block addressing (MSF, LSN, LBA) * Sectors:: Block addressing (MSF, LSN, LBA)
* Pre-gaps:: Track pre-gaps
@end menu @end menu
@node Tracks @node Tracks
@section tracks --- disc subdivisions @section tracks --- disc subdivisions
@cindex track @cindex track
@cindex gaps
In this section we describe CD properties and terms that we make use In this section we describe CD properties and terms that we make use
of in @value{libcdio}. of in @value{libcdio}.
A CD is formated into a number of @term{tracks}, and a CD can hold at A CD is formated into a number of @term{tracks}, and a CD can hold at
most 99 such tracks. This is defined by @code{CDIO_CD_MAX_TRACKS} in most 99 such tracks. This is defined by @code{CDIO_CD_MAX_TRACKS} in
@file{cdio/sector.h}. Between the tracks CD specifications require a @file{cdio/sector.h}. Between some tracks CD specifications require a
``2 second'' in gap (called a @term{lead-in gap}. This is unused space ``2 second'' in gap (called a @term{lead-in gap}. This is unused space
with no ``data'' similar to the space between tracks on an old with no ``data'' similar to the space between tracks on an old
phonograph. The word ``second'' here really refers to a measure of phonograph. The word ``second'' here really refers to a measure of
@@ -900,9 +902,9 @@ The beginning (or inner edge) of the CD is supposed to have a ``2
second'' lead-in gap and there is supposed to be another ``2 second'' second'' lead-in gap and there is supposed to be another ``2 second''
@term{lead-out} gap at the end (or outer edge) of the CD. @term{lead-out} gap at the end (or outer edge) of the CD.
People have discovered that they can put useful data in the various People have discovered that they can put useful data in the @term{lead-in}
gaps and their equipment can read this, violating the standards but and @term{lead-out} gaps, and their equipment can read this, violating
allowing a CD to store more data. the standards but allowing a CD to store more data.
In order to determine the number of tracks on a CD and where they In order to determine the number of tracks on a CD and where they
start, commands are used to get this table-of-contents or @term{TOC} start, commands are used to get this table-of-contents or @term{TOC}
@@ -922,7 +924,7 @@ largest legal track position. In @value{libcdio},
@cindex frames @cindex frames
A track is broken up into a number of 2352-byte @emph{blocks} which we A track is broken up into a number of 2352-byte @emph{blocks} which we
sometimes call @emph{sectors} or @emph{frames}. Whereas tracks have to sometimes call @emph{sectors} or @emph{frames}. Whereas tracks may
have a gap between them, a block or sector does not. (In have a gap between them, a block or sector does not. (In
@value{libcdio} the block size constant is defined using @value{libcdio} the block size constant is defined using
@code{CDIO_CD_FRAMESIZE_RAW}). @code{CDIO_CD_FRAMESIZE_RAW}).
@@ -981,6 +983,138 @@ lead-in is are not counted. So to convert a LBA into an LSN you just
add 150. Why the distinction between LBA and LSN? I don't know, add 150. Why the distinction between LBA and LSN? I don't know,
perhaps this has something to do with ``multisession'' CDs. perhaps this has something to do with ``multisession'' CDs.
@node Pre-gaps
@section track pre-gaps -- @acronym{CD-DA} discs and gaps
@cindex CD-DA
@cindex gaps
@cindex lead in
@cindex lead out
@cindex pre-gap
@cindex Q sub-channel
Gaps are possibly one of the least understood topics in audio discs.
In the case of @acronym{CD-DA} discs, standards require a silent 2
second gap before the first audio track and after the last audio track
(in each session.) These are respectively referred to as
@term{lead-in} and @term{lead-out} gaps. No other gaps are required.
It is important not to confuse the required @term{lead-in} and
@term{lead-out} gaps with the optional track @term{pre-gap}s. Track
@term{pre-gap}s are the gaps that may occur between audio tracks.
Typically, track @term{pre-gap}s are filled with silence so that the
listener knows that one song has ended, and the next will soon begin.
However, track @term{pre-gap}s do not have to contain silence. One
exception is an audio disc of a live performance. Because the
performer may seamlessly move from one piece of the performance to the
next, it would be unnatural for the disc to contain silence between
the two pieces. Instead, the track number updates with no
interruption in the performance. This allows the listener to either
hear the entire performance without unnatural interruptions, or to
conveniently skip to certain pieces of the performance. Finally, some
@acronym{CD-DA} discs--whose behavior will be described below--lack
track @term{pre-gap}s altogether although they must still include the
@term{lead-in} and @term{lead-out} gaps.
In order to understand the track @term{pre-gap}s that occur between
audio tracks, it is necessary to understand how CD players display the
track number and time. Embedded in each block of audio data is
non-audio information known as the @term{Q sub-channel}. The
@term{Q sub-channel} data tells the CD player what track number and time
it should display while it is playing the block of audio data in which
the @term{Q sub-channel} data is embedded. Near the end of some
tracks, the @term{Q sub-channel} may instruct the CD player to update
the track number to the next track, and display a count down to the
next track, often starting at -2 seconds and proceeding to zero. This
is known as an audio track @term{pre-gap}. It may either contain
silence, or as previously discussed--in the case of live
performances--it may contain audio. Almost as often as not, there is
no @term{pre-gap} whatsoever. Regardless, an audio track
@term{pre-gap} is purely determined by the contents of the
@term{Q sub-channel}, which is embedded in each audio sector. This has
some interesting implications for the track forward button.
When the track forward button is pressed on a CD player, the CD player
advances to the next track, skipping that track's @term{pre-gap}.
This is because the CD player uses the starting address of the track
from the disc's table of contents (TOC) to determine where to start
playing a track when either the track forward or track backward
buttons are pressed. So to hear a @term{pre-gap} for track 4, the
listener must either listen to track 3 first, or use the track forward
or backward buttons to go to track 4, then use the seek backward
button to back up into track 4's @term{pre-gap}, which is really part
of track 3, at least according to the TOC. Track 1 @term{pre-gap}s
are especially interesting because some commercial discs have audio
hidden before the beginning of the first track! The only way to hear
this hidden audio with a standard player is to use the seek backward
button as soon as track 1 begins playing!
Audio track @term{pre-gap}s may be specified in a couple of different
ways in the popular cue file format. The first way of specifying a
@term{pre-gap} is to use the @command{PREGAP} command. This will
place a @term{pre-gap} containing silence before a track. The second
way of specifying a @term{pre-gap} is to give a track an
@command{INDEX 00} as well as the more normal @command{INDEX 01}.
@command{INDEX 01} will be used to specify the start of the track in
the disc's TOC, while @command{INDEX 00} will be used to specify the
start of the track's @term{pre-gap} as recorded in the @term{Q sub-channel}.
@command{INDEX 00} is ordinarily used for specifying
track @term{pre-gap}s that contain audio rather than silence. Thus,
the cue file format may be used to specify track @term{pre-gap}s with
silence or audio, depending on whether the @command{PREGAP} or
@command{INDEX 00} commands are specified. If neither type of
@term{pre-gap} is specified for a track, no @term{pre-gap} is created
for that track, which merely means the absence of @term{pre-gap}
information in the @term{Q sub-channel}, and the lack of a short count
down to the next track.
Various @acronym{CD-DA} ripping programs take various approaches to
track @term{pre-gap}s. Some ripping programs ignore track
@term{pre-gap}s altogether, relying solely on the disc's TOC to
determine where tracks begin and end. If a disc is ripped with such a
program, then re-burned later, the resulting disc will lack track
@term{pre-gap}s, and thereby lack the playback behavior of counting
down to the next track. Other ripping programs detect track
@term{pre-gap}s and record them in the popular cue file format among
others. Such ripping programs sometimes allow the user to determine
whether track @term{pre-gap}s will be appended to the prior track or
pre-pended to the track to which they "belong". Note that if a
ripping program is ignorant of track @term{pre-gap}s, the track
@term{pre-gap}s will be appended to the prior track, because that is
where the disc's TOC puts them. Thus, there are many different ways
an application may chose to deal with track @term{pre-gap}s.
Consequently, @kbd{libcdio} does not dictate the policy a ripping
program should use in dealing with track @term{pre-gap}s. Hence,
@kbd{libcdio} provides the @code{cdio_get_track_pregap_[lba|lsn]()}
interfaces to allow the application to deal with track @term{pre-gap}s
as it sees fit.
Note that the @code{cdio_get_track_pregap_[lba|lsn]()} interfaces
currently only provide information for CDRDAO TOC, CDRWIN BIN/CUE, and
NRG images. Getting the track @term{pre-gap}s from a CD drive is a
more complicated problem because not all CD drives support reading the
@term{Q sub-channel} DIRECTLY at @emph{high} speed, and there is no
interface to determine whether or not a drive supports this optional
feature, aside from trying to read the @term{Q sub-channel}, and
possibly incurring IO errors. However, all drives DO support reading
the @term{Q sub-channel} INDIRECTLY while playing an audio disc by
asking the drive for the current position. Unfortunately, this occurs
at normal playback speed, and requires a certain settling time after
the disc starts playing. Thus, using this @emph{slow} interface
requires a more sophisticated algorithm, such as binary search or some
heuristic, like backing up progressively from the end of the prior
track to look for the next track's @term{pre-gap}. Note that CD
drives seek @emph{slow}ly, so it is better to simply use a drive that
can read the @term{Q sub-channel} directly at @emph{high} speed, and
avoid complicated software solutions. (Not to mention that if the
user has an older system with an analog audio cable hooked up between
their soundboard and their drive, and a ripping program uses the
@emph{slow} interface, the user will hear bits of the audio on the
disc!) Consequently, because there is no good universal solution to
the problem of reading the @term{Q sub-channel} from a drive,
@kbd{libcdio} currently leaves this problem up to the application, a
problem which is readily approachable through either @kbd{libcdio}'s
MMC interface or @kbd{libcdio}'s cdda interface. For an example of
one such application, see @url{https://gna.org/projects/cued/}.
@node How to use @node How to use
@chapter How to use @chapter How to use

View File

@@ -1,5 +1,5 @@
/* -*- c -*- /* -*- c -*-
$Id: track.h,v 1.11 2006/01/23 20:30:28 rocky Exp $ $Id: track.h,v 1.12 2008/03/16 00:12:42 rocky Exp $
Copyright (C) 2005, 2006 Rocky Bernstein <rocky@panix.com> Copyright (C) 2005, 2006 Rocky Bernstein <rocky@panix.com>
@@ -196,6 +196,28 @@ extern "C" {
@return the starting LSN or CDIO_INVALID_LSN on error. @return the starting LSN or CDIO_INVALID_LSN on error.
*/ */
lsn_t cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track); lsn_t cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track);
/*!
Return the starting LBA for the pregap for track number
i_track in p_cdio. Track numbers usually start at something
greater than 0, usually 1.
@param p_cdio object to get information from
@param i_track the track number we want the LBA for
@return the starting LBA or CDIO_INVALID_LBA on error.
*/
lba_t cdio_get_track_pregap_lba(const CdIo_t *p_cdio, track_t i_track);
/*!
Return the starting LSN for the pregap for track number
i_track in p_cdio. Track numbers usually start at something
greater than 0, usually 1.
@param p_cdio object to get information from
@param i_track the track number we want the LSN for
@return the starting LSN or CDIO_INVALID_LSN on error.
*/
lsn_t cdio_get_track_pregap_lsn(const CdIo_t *p_cdio, track_t i_track);
/*! /*!
Return the starting MSF (minutes/secs/frames) for track number Return the starting MSF (minutes/secs/frames) for track number

View File

@@ -1,4 +1,4 @@
# $Id: Makefile.am,v 1.21 2007/10/15 04:53:59 rocky Exp $ # $Id: Makefile.am,v 1.22 2008/03/16 00:12:42 rocky Exp $
# #
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Rocky Bernstein <rocky@gnu.org> # Copyright (C) 2003, 2004, 2005, 2006, 2007 Rocky Bernstein <rocky@gnu.org>
# #
@@ -43,9 +43,9 @@
# public release, then set AGE to 0. A changed interface means an # public release, then set AGE to 0. A changed interface means an
# incompatibility with previous versions. # incompatibility with previous versions.
libcdio_la_CURRENT = 8 libcdio_la_CURRENT = 9
libcdio_la_REVISION = 1 libcdio_la_REVISION = 0
libcdio_la_AGE = 1 libcdio_la_AGE = 2
EXTRA_DIST = image/Makefile FreeBSD/Makefile MSWindows/Makefile \ EXTRA_DIST = image/Makefile FreeBSD/Makefile MSWindows/Makefile \
libcdio.sym libcdio.sym

View File

@@ -1,5 +1,5 @@
/* /*
$Id: cdio_private.h,v 1.31 2006/01/23 20:48:11 rocky Exp $ $Id: cdio_private.h,v 1.32 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -260,6 +260,13 @@ extern "C" {
CDIO_INVALID_LBA is returned on error. CDIO_INVALID_LBA is returned on error.
*/ */
lba_t (*get_track_lba) ( void *p_env, track_t i_track ); lba_t (*get_track_lba) ( void *p_env, track_t i_track );
/*!
Return the starting LBA for the pregap for track number
i_track in p_env. Tracks numbers start at 1.
CDIO_INVALID_LBA is returned on error.
*/
lba_t (*get_track_pregap_lba) ( const void *p_env, track_t i_track );
/*! /*!
Get format of track. Get format of track.

View File

@@ -1,5 +1,5 @@
/* /*
$Id: image.h,v 1.7 2005/02/17 04:57:21 rocky Exp $ $Id: image.h,v 1.8 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -48,7 +48,8 @@ typedef struct {
msf_t start_msf; msf_t start_msf;
lba_t start_lba; lba_t start_lba;
int start_index; int start_index;
lba_t pregap; /**< pre-gap with zero audio data */ lba_t pregap; /**< pre-gap */
lba_t silence; /**< pre-gap with zero audio data */
int sec_count; /**< Number of sectors in this track. Does not int sec_count; /**< Number of sectors in this track. Does not
include pregap */ include pregap */
int num_indices; int num_indices;

View File

@@ -1,5 +1,5 @@
/* /*
$Id: bincue.c,v 1.19 2006/02/13 11:00:53 rocky Exp $ $Id: bincue.c,v 1.20 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2002, 2003, 2004, 2005, 2006 Copyright (C) 2002, 2003, 2004, 2005, 2006
Rocky Bernstein <rocky@panix.com> Rocky Bernstein <rocky@panix.com>
@@ -27,7 +27,7 @@
(*.cue). (*.cue).
*/ */
static const char _rcsid[] = "$Id: bincue.c,v 1.19 2006/02/13 11:00:53 rocky Exp $"; static const char _rcsid[] = "$Id: bincue.c,v 1.20 2008/03/16 00:12:43 rocky Exp $";
#include "image.h" #include "image.h"
#include "cdio_assert.h" #include "cdio_assert.h"
@@ -632,7 +632,7 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name)
goto err_exit; goto err_exit;
} }
if (cd) { if (cd) {
cd->tocent[i].pregap = lba; cd->tocent[i].silence = lba;
} }
} else { } else {
goto format_error; goto format_error;
@@ -672,7 +672,14 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name)
track_info_t *this_track= track_info_t *this_track=
&(cd->tocent[cd->gen.i_tracks - cd->gen.i_first_track]); &(cd->tocent[cd->gen.i_tracks - cd->gen.i_first_track]);
if (start_index != 0) { switch (start_index) {
case 0:
lba += CDIO_PREGAP_SECTORS;
this_track->pregap = lba;
break;
case 1:
if (!b_first_index_for_track) { if (!b_first_index_for_track) {
lba += CDIO_PREGAP_SECTORS; lba += CDIO_PREGAP_SECTORS;
cdio_lba_to_msf(lba, &(this_track->start_msf)); cdio_lba_to_msf(lba, &(this_track->start_msf));
@@ -709,6 +716,10 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name)
} }
} }
this_track->num_indices++; this_track->num_indices++;
break;
default:
break;
} }
} }
#endif #endif
@@ -1163,6 +1174,7 @@ cdio_open_cue (const char *psz_cue_name)
_funcs.get_track_lba = _get_lba_track_bincue; _funcs.get_track_lba = _get_lba_track_bincue;
_funcs.get_track_msf = _get_track_msf_image; _funcs.get_track_msf = _get_track_msf_image;
_funcs.get_track_preemphasis = get_track_preemphasis_image, _funcs.get_track_preemphasis = get_track_preemphasis_image,
_funcs.get_track_pregap_lba = get_track_pregap_lba_image;
_funcs.lseek = _lseek_bincue; _funcs.lseek = _lseek_bincue;
_funcs.read = _read_bincue; _funcs.read = _read_bincue;
_funcs.read_audio_sectors = _read_audio_sectors_bincue; _funcs.read_audio_sectors = _read_audio_sectors_bincue;

View File

@@ -1,5 +1,5 @@
/* /*
$Id: cdrdao.c,v 1.23 2007/03/05 11:49:24 rocky Exp $ $Id: cdrdao.c,v 1.24 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2004, 2005, 2006, 2007 Rocky Bernstein <rocky@gnu.org> Copyright (C) 2004, 2005, 2006, 2007 Rocky Bernstein <rocky@gnu.org>
toc reading routine adapted from cuetools toc reading routine adapted from cuetools
@@ -25,7 +25,7 @@
(*.cue). (*.cue).
*/ */
static const char _rcsid[] = "$Id: cdrdao.c,v 1.23 2007/03/05 11:49:24 rocky Exp $"; static const char _rcsid[] = "$Id: cdrdao.c,v 1.24 2008/03/16 00:12:43 rocky Exp $";
#include "image.h" #include "image.h"
#include "cdio_assert.h" #include "cdio_assert.h"
@@ -825,6 +825,7 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
/* todo: line is too long! */ /* todo: line is too long! */
if (NULL != cd) { if (NULL != cd) {
cd->tocent[i].pregap = cd->tocent[i].start_lba;
cd->tocent[i].start_lba += cdio_mmssff_to_lba (psz_field); cd->tocent[i].start_lba += cdio_mmssff_to_lba (psz_field);
cdio_lba_to_msf(cd->tocent[i].start_lba, cdio_lba_to_msf(cd->tocent[i].start_lba,
&(cd->tocent[i].start_msf)); &(cd->tocent[i].start_msf));
@@ -843,7 +844,7 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
if (0 <= i) { if (0 <= i) {
if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) {
if (NULL != cd) if (NULL != cd)
cd->tocent[i].pregap = cdio_mmssff_to_lba (psz_field); cd->tocent[i].silence = cdio_mmssff_to_lba (psz_field);
} else { } else {
goto format_error; goto format_error;
} }
@@ -1295,6 +1296,7 @@ cdio_open_cdrdao (const char *psz_cue_name)
_funcs.get_track_lba = _get_lba_track_cdrdao; _funcs.get_track_lba = _get_lba_track_cdrdao;
_funcs.get_track_msf = _get_track_msf_image; _funcs.get_track_msf = _get_track_msf_image;
_funcs.get_track_preemphasis = get_track_preemphasis_image, _funcs.get_track_preemphasis = get_track_preemphasis_image,
_funcs.get_track_pregap_lba = get_track_pregap_lba_image;
_funcs.lseek = _lseek_cdrdao; _funcs.lseek = _lseek_cdrdao;
_funcs.read = _read_cdrdao; _funcs.read = _read_cdrdao;
_funcs.read_audio_sectors = _read_audio_sectors_cdrdao; _funcs.read_audio_sectors = _read_audio_sectors_cdrdao;

View File

@@ -1,5 +1,5 @@
/* /*
$Id: nrg.c,v 1.24 2006/02/27 10:23:52 flameeyes Exp $ $Id: nrg.c,v 1.25 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2003, 2004, 2005, 2006 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005, 2006 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>
@@ -46,7 +46,7 @@
#include "_cdio_stdio.h" #include "_cdio_stdio.h"
#include "nrg.h" #include "nrg.h"
static const char _rcsid[] = "$Id: nrg.c,v 1.24 2006/02/27 10:23:52 flameeyes Exp $"; static const char _rcsid[] = "$Id: nrg.c,v 1.25 2008/03/16 00:12:43 rocky Exp $";
nero_id_t nero_id; nero_id_t nero_id;
nero_dtype_t nero_dtype; nero_dtype_t nero_dtype;
@@ -371,24 +371,24 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name,
case DAOX_ID: /* "DAOX" */ case DAOX_ID: /* "DAOX" */
case DAOI_ID: /* "DAOI" */ case DAOI_ID: /* "DAOI" */
{ {
_daox_t *_xentries = NULL;
_daoi_t *_ientries = NULL;
_dao_common_t *_dao_common = (void *) chunk->data;
int disc_mode = _dao_common->unknown[1];
track_format_t track_format; track_format_t track_format;
int disc_mode; int i;
/* We include an extra 0 byte so these can be used as C strings.*/ /* We include an extra 0 byte so these can be used as C strings.*/
p_env->psz_mcn = calloc(1, CDIO_MCN_SIZE+1); p_env->psz_mcn = calloc(1, CDIO_MCN_SIZE+1);
memcpy(p_env->psz_mcn, &(_dao_common->psz_mcn), CDIO_MCN_SIZE);
p_env->psz_mcn[CDIO_MCN_SIZE] = '\0';
if (DAOX_ID == opcode) { if (DAOX_ID == opcode) {
_daox_array_t *_entries = (void *) chunk->data; _xentries = (void *) chunk->data;
disc_mode = _entries->_unknown[1]; p_env->dtyp = _xentries->track_info[0].common.unknown[0];
p_env->dtyp = _entries->_unknown[19];
memcpy(p_env->psz_mcn, &(_entries->psz_mcn), CDIO_MCN_SIZE);
p_env->psz_mcn[CDIO_MCN_SIZE] = '\0';
} else { } else {
_daoi_array_t *_entries = (void *) chunk->data; _ientries = (void *) chunk->data;
disc_mode = _entries->_unknown[1]; p_env->dtyp = _ientries->track_info[0].common.unknown[0];
p_env->dtyp = _entries->_unknown[19];
memcpy(p_env->psz_mcn, &(_entries->psz_mcn), CDIO_MCN_SIZE);
p_env->psz_mcn[CDIO_MCN_SIZE] = '\0';
} }
p_env->is_dao = true; p_env->is_dao = true;
@@ -430,7 +430,6 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name,
track_format = TRACK_FORMAT_AUDIO; track_format = TRACK_FORMAT_AUDIO;
} }
if (0 == disc_mode) { if (0 == disc_mode) {
int i;
for (i=0; i<p_env->gen.i_tracks; i++) { for (i=0; i<p_env->gen.i_tracks; i++) {
cdtext_init (&(p_env->gen.cdtext_track[i])); cdtext_init (&(p_env->gen.cdtext_track[i]));
p_env->tocent[i].track_format= track_format; p_env->tocent[i].track_format= track_format;
@@ -446,7 +445,6 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name,
} }
} }
} else if (2 == disc_mode) { } else if (2 == disc_mode) {
int i;
for (i=0; i<p_env->gen.i_tracks; i++) { for (i=0; i<p_env->gen.i_tracks; i++) {
cdtext_init (&(p_env->gen.cdtext_track[i])); cdtext_init (&(p_env->gen.cdtext_track[i]));
p_env->tocent[i].track_green = true; p_env->tocent[i].track_green = true;
@@ -473,6 +471,20 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name,
"Don't know if mode 1, mode 2 or mixed: %x\n", "Don't know if mode 1, mode 2 or mixed: %x\n",
disc_mode); disc_mode);
} }
for (i=0; i<p_env->gen.i_tracks; i++) {
if (!p_env->tocent[i].datasize) {
continue;
}
if (DAOX_ID == opcode) {
p_env->tocent[i].pregap = (uint64_from_be
(_xentries->track_info[i].index0)) / (p_env->tocent[i].datasize);
} else {
p_env->tocent[i].pregap = (uint32_from_be
(_ientries->track_info[i].index0)) / (p_env->tocent[i].datasize);
}
}
break; break;
} }
case NERO_ID: case NERO_ID:
@@ -1243,13 +1255,14 @@ cdio_open_nrg (const char *psz_source)
_funcs.get_media_changed = get_media_changed_image; _funcs.get_media_changed = get_media_changed_image;
_funcs.get_mcn = _get_mcn_image; _funcs.get_mcn = _get_mcn_image;
_funcs.get_num_tracks = _get_num_tracks_image; _funcs.get_num_tracks = _get_num_tracks_image;
_funcs.get_track_channels = get_track_channels_generic, _funcs.get_track_channels = get_track_channels_generic;
_funcs.get_track_copy_permit = get_track_copy_permit_image, _funcs.get_track_copy_permit = get_track_copy_permit_image;
_funcs.get_track_format = get_track_format_nrg; _funcs.get_track_format = get_track_format_nrg;
_funcs.get_track_green = _get_track_green_nrg; _funcs.get_track_green = _get_track_green_nrg;
_funcs.get_track_lba = NULL; /* Will use generic routine via msf */ _funcs.get_track_lba = NULL; /* Will use generic routine via msf */
_funcs.get_track_msf = _get_track_msf_image; _funcs.get_track_msf = _get_track_msf_image;
_funcs.get_track_preemphasis = get_track_preemphasis_generic, _funcs.get_track_preemphasis = get_track_preemphasis_generic;
_funcs.get_track_pregap_lba = get_track_pregap_lba_image;
_funcs.lseek = _lseek_nrg; _funcs.lseek = _lseek_nrg;
_funcs.read = _read_nrg; _funcs.read = _read_nrg;
_funcs.read_audio_sectors = _read_audio_sectors_nrg; _funcs.read_audio_sectors = _read_audio_sectors_nrg;

View File

@@ -1,5 +1,5 @@
/* /*
$Id: nrg.h,v 1.3 2006/01/14 09:45:44 rocky Exp $ $Id: nrg.h,v 1.4 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2004, 2006 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004, 2006 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>
@@ -71,18 +71,47 @@ typedef struct {
uint32_t lsn GNUC_PACKED; uint32_t lsn GNUC_PACKED;
} _cuex_array_t; } _cuex_array_t;
/* New DAO[XI] Information from http://en.wikipedia.org/wiki/NRG_(file_format)
*/
typedef struct { typedef struct {
uint32_t _unknown1 GNUC_PACKED; uint8_t zero[10];
char psz_mcn[CDIO_MCN_SIZE]; uint32_t sector_size GNUC_PACKED;
uint8_t _unknown[64-CDIO_MCN_SIZE-sizeof(uint32_t)]; uint8_t unknown[4];
} _dao_array_common_t;
typedef struct {
_dao_array_common_t common;
uint64_t index0 GNUC_PACKED;
uint64_t index1 GNUC_PACKED;
uint64_t end_of_track GNUC_PACKED;
} _daox_array_t; } _daox_array_t;
typedef struct { typedef struct {
uint32_t _unknown1 GNUC_PACKED; _dao_array_common_t common;
char psz_mcn[CDIO_MCN_SIZE]; uint32_t index0 GNUC_PACKED;
uint8_t _unknown[64-CDIO_MCN_SIZE-sizeof(uint32_t)]; uint32_t index1 GNUC_PACKED;
uint32_t end_of_track GNUC_PACKED;
} _daoi_array_t; } _daoi_array_t;
typedef struct {
uint32_t chunk_size_le GNUC_PACKED;
char psz_mcn[CDIO_MCN_SIZE];
uint8_t unknown[3];
uint8_t first_track;
uint8_t last_track;
} _dao_common_t;
typedef struct {
_dao_common_t common;
_daox_array_t track_info[EMPTY_ARRAY_SIZE];
} _daox_t;
typedef struct {
_dao_common_t common;
_daoi_array_t track_info[EMPTY_ARRAY_SIZE];
} _daoi_t;
typedef struct { typedef struct {
uint32_t id GNUC_PACKED; uint32_t id GNUC_PACKED;
uint32_t len GNUC_PACKED; uint32_t len GNUC_PACKED;

View File

@@ -1,5 +1,5 @@
/* /*
$Id: image_common.c,v 1.12 2005/02/17 07:03:37 rocky Exp $ $Id: image_common.c,v 1.13 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -246,6 +246,30 @@ get_track_preemphasis_image(const void *p_user_data, track_t i_track)
& PRE_EMPHASIS ) ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE; & PRE_EMPHASIS ) ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
} }
/*! Return the starting LBA for the pregap for track number i_track.
Track numbers start at 1.
CDIO_INVALID_LBA is returned on error.
*/
lba_t
get_track_pregap_lba_image(const void *p_user_data, track_t i_track)
{
const _img_private_t *p_env = p_user_data;
lba_t pregap, start_lba;
pregap = p_env->tocent[i_track-p_env->gen.i_first_track].pregap;
start_lba = p_env->tocent[i_track-p_env->gen.i_first_track].start_lba;
/* avoid initializing pregap to CDIO_INVALID_LBA by letting calloc
do the work. also, nero files have the pregap set equal
to the start of the track when there is no pregap
*/
if (!pregap || pregap == start_lba) {
pregap = CDIO_INVALID_LBA;
}
return pregap;
}
/*! /*!
Read a data sector Read a data sector

View File

@@ -1,5 +1,5 @@
/* /*
$Id: image_common.h,v 1.10 2005/02/17 07:03:37 rocky Exp $ $Id: image_common.h,v 1.11 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
@@ -150,6 +150,13 @@ track_flag_t get_track_copy_permit_image(void *p_user_data, track_t i_track);
*/ */
track_flag_t get_track_preemphasis_image(const void *p_user_data, track_flag_t get_track_preemphasis_image(const void *p_user_data,
track_t i_track); track_t i_track);
/*! Return the starting LBA for the pregap for track number i_track.
Track numbers start at 1.
CDIO_INVALID_LBA is returned on error.
*/
lba_t get_track_pregap_lba_image(const void *p_user_data, track_t i_track);
/*! /*!
Read a data sector Read a data sector

View File

@@ -80,6 +80,8 @@ cdio_get_track_format
cdio_get_track_green cdio_get_track_green
cdio_get_track_last_lsn cdio_get_track_last_lsn
cdio_get_track_lba cdio_get_track_lba
cdio_get_track_pregap_lba
cdio_get_track_pregap_lsn
cdio_get_track_lsn cdio_get_track_lsn
cdio_get_track_msf cdio_get_track_msf
cdio_get_track_preemphasis cdio_get_track_preemphasis

View File

@@ -1,5 +1,5 @@
/* /*
$Id: track.c,v 1.4 2005/02/06 04:20:25 rocky Exp $ $Id: track.c,v 1.5 2008/03/16 00:12:43 rocky Exp $
Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
@@ -229,7 +229,7 @@ cdio_get_track_lba(const CdIo_t *p_cdio, track_t i_track)
i_track in cdio. Tracks numbers start at 1. i_track in cdio. Tracks numbers start at 1.
The "leadout" track is specified either by The "leadout" track is specified either by
using i_track LEADOUT_TRACK or the total tracks+1. using i_track LEADOUT_TRACK or the total tracks+1.
CDIO_INVALID_LBA is returned on error. CDIO_INVALID_LSN is returned on error.
*/ */
lsn_t lsn_t
cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track) cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track)
@@ -246,6 +246,34 @@ cdio_get_track_lsn(const CdIo_t *p_cdio, track_t i_track)
} }
} }
/*!
Return the starting LBA for the pregap for track number
i_track in cdio. Track numbers start at 1.
CDIO_INVALID_LBA is returned on error.
*/
lba_t
cdio_get_track_pregap_lba(const CdIo_t *p_cdio, track_t i_track)
{
if (p_cdio == NULL) return CDIO_INVALID_LBA;
if (p_cdio->op.get_track_pregap_lba) {
return p_cdio->op.get_track_pregap_lba (p_cdio->env, i_track);
} else {
return CDIO_INVALID_LBA;
}
}
/*!
Return the starting LSN for the pregap for track number
i_track in cdio. Track numbers start at 1.
CDIO_INVALID_LSN is returned on error.
*/
lsn_t
cdio_get_track_pregap_lsn(const CdIo_t *p_cdio, track_t i_track)
{
return cdio_lba_to_lsn(cdio_get_track_pregap_lba(p_cdio, i_track));
}
/*! /*!
Return the ending LSN for track number Return the ending LSN for track number
i_track in cdio. CDIO_INVALID_LSN is returned on error. i_track in cdio. CDIO_INVALID_LSN is returned on error.