diff --git a/THANKS b/THANKS index 8bd83b86..87b9dfb6 100644 --- a/THANKS +++ b/THANKS @@ -52,3 +52,7 @@ xboxmediacenter team (www.xboxmediacenter.de) Daniel Schwarz 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. diff --git a/configure.ac b/configure.ac index 9c7e7d8d..fdeb3370 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,5 @@ -dnl Copyright (C) 2003, 2004, 2005, 2006, 2007 Rocky Bernstein +dnl Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 +dnl Rocky Bernstein dnl 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 @@ -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 02110-1301 USA. -define(RELEASE_NUM, 80) -define(CDIO_VERSION_STR, 0.$1) +define(RELEASE_NUM, 81) +define(CDIO_VERSION_STR, 0.$1cvs) 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_CONFIG_SRCDIR(src/cd-info.c) diff --git a/doc/libcdio.texi b/doc/libcdio.texi index 20a6087e..560ef632 100644 --- a/doc/libcdio.texi +++ b/doc/libcdio.texi @@ -46,7 +46,7 @@ development.'' @titlepage @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. @page @@ -876,18 +876,20 @@ editor. @menu * Tracks:: Tracks * Sectors:: Block addressing (MSF, LSN, LBA) +* Pre-gaps:: Track pre-gaps @end menu @node Tracks @section tracks --- disc subdivisions @cindex track +@cindex gaps In this section we describe CD properties and terms that we make use of in @value{libcdio}. 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 -@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 with no ``data'' similar to the space between tracks on an old 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'' @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 -gaps and their equipment can read this, violating the standards but -allowing a CD to store more data. +People have discovered that they can put useful data in the @term{lead-in} +and @term{lead-out} gaps, and their equipment can read this, violating +the standards but allowing a CD to store more data. 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} @@ -922,7 +924,7 @@ largest legal track position. In @value{libcdio}, @cindex frames 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 @value{libcdio} the block size constant is defined using @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, 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 @chapter How to use diff --git a/include/cdio/track.h b/include/cdio/track.h index 75332400..87b94dea 100644 --- a/include/cdio/track.h +++ b/include/cdio/track.h @@ -1,5 +1,5 @@ /* -*- 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 @@ -196,6 +196,28 @@ extern "C" { @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); + + /*! + 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 diff --git a/lib/driver/Makefile.am b/lib/driver/Makefile.am index 1378e2fb..5e87a1fc 100644 --- a/lib/driver/Makefile.am +++ b/lib/driver/Makefile.am @@ -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 # @@ -43,9 +43,9 @@ # public release, then set AGE to 0. A changed interface means an # incompatibility with previous versions. -libcdio_la_CURRENT = 8 -libcdio_la_REVISION = 1 -libcdio_la_AGE = 1 +libcdio_la_CURRENT = 9 +libcdio_la_REVISION = 0 +libcdio_la_AGE = 2 EXTRA_DIST = image/Makefile FreeBSD/Makefile MSWindows/Makefile \ libcdio.sym diff --git a/lib/driver/cdio_private.h b/lib/driver/cdio_private.h index 78791f37..ad0bbe17 100644 --- a/lib/driver/cdio_private.h +++ b/lib/driver/cdio_private.h @@ -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 @@ -260,6 +260,13 @@ extern "C" { CDIO_INVALID_LBA is returned on error. */ 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. diff --git a/lib/driver/image.h b/lib/driver/image.h index 30d976db..582f3353 100644 --- a/lib/driver/image.h +++ b/lib/driver/image.h @@ -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 @@ -48,7 +48,8 @@ typedef struct { msf_t start_msf; lba_t start_lba; 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 include pregap */ int num_indices; diff --git a/lib/driver/image/bincue.c b/lib/driver/image/bincue.c index 8968ba8a..c101b9be 100644 --- a/lib/driver/image/bincue.c +++ b/lib/driver/image/bincue.c @@ -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 Rocky Bernstein @@ -27,7 +27,7 @@ (*.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 "cdio_assert.h" @@ -632,7 +632,7 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) goto err_exit; } if (cd) { - cd->tocent[i].pregap = lba; + cd->tocent[i].silence = lba; } } else { goto format_error; @@ -672,7 +672,14 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name) track_info_t *this_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) { lba += CDIO_PREGAP_SECTORS; 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++; + break; + + default: + break; } } #endif @@ -1163,6 +1174,7 @@ cdio_open_cue (const char *psz_cue_name) _funcs.get_track_lba = _get_lba_track_bincue; _funcs.get_track_msf = _get_track_msf_image; _funcs.get_track_preemphasis = get_track_preemphasis_image, + _funcs.get_track_pregap_lba = get_track_pregap_lba_image; _funcs.lseek = _lseek_bincue; _funcs.read = _read_bincue; _funcs.read_audio_sectors = _read_audio_sectors_bincue; diff --git a/lib/driver/image/cdrdao.c b/lib/driver/image/cdrdao.c index a50c32b6..f31ad6f5 100644 --- a/lib/driver/image/cdrdao.c +++ b/lib/driver/image/cdrdao.c @@ -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 toc reading routine adapted from cuetools @@ -25,7 +25,7 @@ (*.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 "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"))) { /* todo: line is too long! */ if (NULL != cd) { + cd->tocent[i].pregap = cd->tocent[i].start_lba; cd->tocent[i].start_lba += cdio_mmssff_to_lba (psz_field); cdio_lba_to_msf(cd->tocent[i].start_lba, &(cd->tocent[i].start_msf)); @@ -843,7 +844,7 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name) if (0 <= i) { if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { if (NULL != cd) - cd->tocent[i].pregap = cdio_mmssff_to_lba (psz_field); + cd->tocent[i].silence = cdio_mmssff_to_lba (psz_field); } else { 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_msf = _get_track_msf_image; _funcs.get_track_preemphasis = get_track_preemphasis_image, + _funcs.get_track_pregap_lba = get_track_pregap_lba_image; _funcs.lseek = _lseek_cdrdao; _funcs.read = _read_cdrdao; _funcs.read_audio_sectors = _read_audio_sectors_cdrdao; diff --git a/lib/driver/image/nrg.c b/lib/driver/image/nrg.c index ba1f777b..5606ffb4 100644 --- a/lib/driver/image/nrg.c +++ b/lib/driver/image/nrg.c @@ -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 Copyright (C) 2001, 2003 Herbert Valerio Riedel @@ -46,7 +46,7 @@ #include "_cdio_stdio.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_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 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; - int disc_mode; + int i; /* 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) { - _daox_array_t *_entries = (void *) chunk->data; - disc_mode = _entries->_unknown[1]; - 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'; + _xentries = (void *) chunk->data; + p_env->dtyp = _xentries->track_info[0].common.unknown[0]; } else { - _daoi_array_t *_entries = (void *) chunk->data; - disc_mode = _entries->_unknown[1]; - 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'; + _ientries = (void *) chunk->data; + p_env->dtyp = _ientries->track_info[0].common.unknown[0]; } 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; } if (0 == disc_mode) { - int i; for (i=0; igen.i_tracks; i++) { cdtext_init (&(p_env->gen.cdtext_track[i])); 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) { - int i; for (i=0; igen.i_tracks; i++) { cdtext_init (&(p_env->gen.cdtext_track[i])); 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", disc_mode); } + + for (i=0; igen.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; } case NERO_ID: @@ -1243,13 +1255,14 @@ cdio_open_nrg (const char *psz_source) _funcs.get_media_changed = get_media_changed_image; _funcs.get_mcn = _get_mcn_image; _funcs.get_num_tracks = _get_num_tracks_image; - _funcs.get_track_channels = get_track_channels_generic, - _funcs.get_track_copy_permit = get_track_copy_permit_image, + _funcs.get_track_channels = get_track_channels_generic; + _funcs.get_track_copy_permit = get_track_copy_permit_image; _funcs.get_track_format = get_track_format_nrg; _funcs.get_track_green = _get_track_green_nrg; _funcs.get_track_lba = NULL; /* Will use generic routine via msf */ _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.read = _read_nrg; _funcs.read_audio_sectors = _read_audio_sectors_nrg; diff --git a/lib/driver/image/nrg.h b/lib/driver/image/nrg.h index ea22134f..e5b223e6 100644 --- a/lib/driver/image/nrg.h +++ b/lib/driver/image/nrg.h @@ -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 Copyright (C) 2001, 2003 Herbert Valerio Riedel @@ -71,18 +71,47 @@ typedef struct { uint32_t lsn GNUC_PACKED; } _cuex_array_t; +/* New DAO[XI] Information from http://en.wikipedia.org/wiki/NRG_(file_format) +*/ + typedef struct { - uint32_t _unknown1 GNUC_PACKED; - char psz_mcn[CDIO_MCN_SIZE]; - uint8_t _unknown[64-CDIO_MCN_SIZE-sizeof(uint32_t)]; + uint8_t zero[10]; + uint32_t sector_size GNUC_PACKED; + 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; typedef struct { - uint32_t _unknown1 GNUC_PACKED; - char psz_mcn[CDIO_MCN_SIZE]; - uint8_t _unknown[64-CDIO_MCN_SIZE-sizeof(uint32_t)]; + _dao_array_common_t common; + uint32_t index0 GNUC_PACKED; + uint32_t index1 GNUC_PACKED; + uint32_t end_of_track GNUC_PACKED; } _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 { uint32_t id GNUC_PACKED; uint32_t len GNUC_PACKED; diff --git a/lib/driver/image_common.c b/lib/driver/image_common.c index 6321aac9..6e3d51f3 100644 --- a/lib/driver/image_common.c +++ b/lib/driver/image_common.c @@ -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 @@ -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; } +/*! 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 diff --git a/lib/driver/image_common.h b/lib/driver/image_common.h index b5011140..02922114 100644 --- a/lib/driver/image_common.h +++ b/lib/driver/image_common.h @@ -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 @@ -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_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 diff --git a/lib/driver/libcdio.sym b/lib/driver/libcdio.sym index 43fbdcb5..0e2f0468 100644 --- a/lib/driver/libcdio.sym +++ b/lib/driver/libcdio.sym @@ -80,6 +80,8 @@ cdio_get_track_format cdio_get_track_green cdio_get_track_last_lsn cdio_get_track_lba +cdio_get_track_pregap_lba +cdio_get_track_pregap_lsn cdio_get_track_lsn cdio_get_track_msf cdio_get_track_preemphasis diff --git a/lib/driver/track.c b/lib/driver/track.c index d3b67731..16cf71d9 100644 --- a/lib/driver/track.c +++ b/lib/driver/track.c @@ -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 Copyright (C) 2001 Herbert Valerio Riedel @@ -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. The "leadout" track is specified either by 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 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 i_track in cdio. CDIO_INVALID_LSN is returned on error.