Blame lib/cdda_interface/toc.c

Packit cb6d3d
/*
Packit cb6d3d
  Copyright (C) 2005, 2008, 2013 Rocky Bernstein <rocky@gnu.org>
Packit cb6d3d
  Copyright (C) 1998-2008 Monty xiphmont@mit.edu
Packit cb6d3d
  derived from code (C) 1994-1996 Heiko Eissfeldt
Packit cb6d3d
Packit cb6d3d
  This program is free software: you can redistribute it and/or modify
Packit cb6d3d
  it under the terms of the GNU General Public License as published by
Packit cb6d3d
  the Free Software Foundation, either version 3 of the License, or
Packit cb6d3d
  (at your option) any later version.
Packit cb6d3d
Packit cb6d3d
  This program is distributed in the hope that it will be useful,
Packit cb6d3d
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit cb6d3d
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit cb6d3d
  GNU General Public License for more details.
Packit cb6d3d
Packit cb6d3d
  You should have received a copy of the GNU General Public License
Packit cb6d3d
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit cb6d3d
*/
Packit cb6d3d
/******************************************************************
Packit cb6d3d
 * Table of contents convenience functions
Packit cb6d3d
 ******************************************************************/
Packit cb6d3d
Packit cb6d3d
#ifdef HAVE_CONFIG_H
Packit cb6d3d
# include "config.h"
Packit cb6d3d
# define __CDIO_CONFIG_H__ 1
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
#include "low_interface.h"
Packit cb6d3d
#include "utils.h"
Packit cb6d3d
Packit cb6d3d
/*! Return the lsn for the start of track i_track or CDIO_LEADOUT_TRACK */
Packit cb6d3d
lsn_t
Packit cb6d3d
cdda_track_firstsector(cdrom_drive_t *d, track_t i_track)
Packit cb6d3d
{
Packit cb6d3d
  if(!d->opened){
Packit cb6d3d
    cderror(d,"400: Device not open\n");
Packit cb6d3d
    return(-400);
Packit cb6d3d
  } else {
Packit cb6d3d
    const track_t i_first_track = cdio_get_first_track_num(d->p_cdio);
Packit cb6d3d
    const track_t i_last_track  =
Packit cb6d3d
	cdio_get_last_track_num(d->p_cdio) + 1; /* include leadout */
Packit cb6d3d
Packit cb6d3d
    if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = i_last_track;
Packit cb6d3d
    if (i_track == 0) {
Packit cb6d3d
      if (d->disc_toc[0].dwStartSector == 0) {
Packit cb6d3d
	/* first track starts at lba 0 -> no pre-gap */
Packit cb6d3d
	cderror(d,"402: No initial pregap\n");
Packit cb6d3d
	return(-402);
Packit cb6d3d
      }
Packit cb6d3d
      else {
Packit cb6d3d
	return 0; /* pre-gap of first track always starts at lba 0 */
Packit cb6d3d
      }
Packit cb6d3d
    } else if (i_track < i_first_track || i_track > i_last_track) {
Packit cb6d3d
      char buf[100];
Packit cb6d3d
      snprintf(buf, sizeof(buf), "401: Invalid track number %02d\n", i_track);
Packit cb6d3d
      cderror(d, buf);
Packit cb6d3d
      return(-401);
Packit cb6d3d
    }
Packit cb6d3d
    return(d->disc_toc[i_track-i_first_track].dwStartSector);
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Get first lsn of the first audio track. -1 is returned on error. */
Packit cb6d3d
lsn_t
Packit cb6d3d
cdda_disc_firstsector(cdrom_drive_t *d)
Packit cb6d3d
{
Packit cb6d3d
  int i;
Packit cb6d3d
  if(!d->opened){
Packit cb6d3d
    cderror(d,"400: Device not open\n");
Packit cb6d3d
    return(-400);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* look for an audio track */
Packit cb6d3d
  for ( i=0; i<d->tracks; i++ )
Packit cb6d3d
    if( cdda_track_audiop(d, i+1)==1 ) {
Packit cb6d3d
      if (i == 0) /* disc starts at lba 0 if first track is an audio track */
Packit cb6d3d
       return 0;
Packit cb6d3d
      else
Packit cb6d3d
       return cdda_track_firstsector(d, i+1);
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
  cderror(d,"403: No audio tracks on disc\n");
Packit cb6d3d
  return(-403);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Get last lsn of the track. The lsn is generally one less than the
Packit cb6d3d
  start of the next track. -1 is returned on error. */
Packit cb6d3d
lsn_t
Packit cb6d3d
cdda_track_lastsector(cdrom_drive_t *d, track_t i_track)
Packit cb6d3d
{
Packit cb6d3d
  if(!d->opened){
Packit cb6d3d
    cderror(d,"400: Device not open\n");
Packit cb6d3d
    return(-400);
Packit cb6d3d
  } else {
Packit cb6d3d
    const track_t i_first_track = cdio_get_first_track_num(d->p_cdio);
Packit cb6d3d
    const track_t i_last_track  = cdio_get_last_track_num(d->p_cdio);
Packit cb6d3d
Packit cb6d3d
    if (i_track == 0) {
Packit cb6d3d
      if (d->disc_toc[0].dwStartSector == 0) {
Packit cb6d3d
	/* first track starts at lba 0 -> no pre-gap */
Packit cb6d3d
	cderror(d,"402: No initial pregap\n");
Packit cb6d3d
	return(-402);
Packit cb6d3d
      }
Packit cb6d3d
      else {
Packit cb6d3d
	return d->disc_toc[0].dwStartSector-1;
Packit cb6d3d
      }
Packit cb6d3d
    } else if (i_track < i_first_track || i_track > i_last_track) {
Packit cb6d3d
      char buf[100];
Packit cb6d3d
      snprintf(buf, sizeof(buf), "401: Invalid track number %02d\n", i_track);
Packit cb6d3d
      cderror(d, buf);
Packit cb6d3d
      return(-401);
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* CD Extra have their first session ending at the last audio track */
Packit cb6d3d
    if (d->cd_extra > 0 && i_track-i_first_track+2 <= d->tracks) {
Packit cb6d3d
      if (d->audio_last_sector >= d->disc_toc[i_track-i_first_track].dwStartSector &&
Packit cb6d3d
          d->audio_last_sector < d->disc_toc[i_track-i_first_track+1].dwStartSector) {
Packit cb6d3d
        return d->audio_last_sector;
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* Index safe because we always have the leadout at
Packit cb6d3d
     * disc_toc[tracks] */
Packit cb6d3d
    return(d->disc_toc[i_track-i_first_track+1].dwStartSector-1);
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Get last lsn of the last audio track. The last lssn generally one
Packit cb6d3d
  less than the start of the next track after the audio track. -1 is
Packit cb6d3d
  returned on error. */
Packit cb6d3d
lsn_t
Packit cb6d3d
cdda_disc_lastsector(cdrom_drive_t *d)
Packit cb6d3d
{
Packit cb6d3d
  if (!d->opened) {
Packit cb6d3d
    cderror(d,"400: Device not open\n");
Packit cb6d3d
    return -400;
Packit cb6d3d
  } else {
Packit cb6d3d
    /* look for an audio track */
Packit cb6d3d
    const track_t i_first_track = cdio_get_first_track_num(d->p_cdio);
Packit cb6d3d
    track_t i = cdio_get_last_track_num(d->p_cdio);
Packit cb6d3d
    for ( ; i >= i_first_track; i-- )
Packit cb6d3d
      if ( cdda_track_audiop(d,i) )
Packit cb6d3d
	return (cdda_track_lastsector(d,i));
Packit cb6d3d
  }
Packit cb6d3d
  cderror(d,"403: No audio tracks on disc\n");
Packit cb6d3d
  return -403;
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Return the number of tracks on the or 300 if error. */
Packit cb6d3d
track_t
Packit cb6d3d
cdda_tracks(cdrom_drive_t *d)
Packit cb6d3d
{
Packit cb6d3d
  if (!d->opened){
Packit cb6d3d
    cderror(d,"400: Device not open\n");
Packit cb6d3d
    return CDIO_INVALID_TRACK;
Packit cb6d3d
  }
Packit cb6d3d
  return(d->tracks);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Return the track containing the given LSN. If the LSN is before
Packit cb6d3d
    the first track (in the pregap), 0 is returned. If there was an
Packit cb6d3d
    error or the LSN after the LEADOUT (beyond the end of the CD), then
Packit cb6d3d
    CDIO_INVALID_TRACK is returned.
Packit cb6d3d
 */
Packit cb6d3d
int
Packit cb6d3d
cdda_sector_gettrack(cdrom_drive_t *d, lsn_t lsn)
Packit cb6d3d
{
Packit cb6d3d
  if (!d->opened) {
Packit cb6d3d
    cderror(d,"400: Device not open\n");
Packit cb6d3d
    return CDIO_INVALID_TRACK;
Packit cb6d3d
  } else {
Packit cb6d3d
    if (lsn < d->disc_toc[0].dwStartSector)
Packit cb6d3d
      return 0; /* We're in the pre-gap of first track */
Packit cb6d3d
Packit cb6d3d
    return cdio_get_track(d->p_cdio, lsn);
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Return the number of channels in track: 2 or 4; -2 if not
Packit cb6d3d
  implemented or -1 for error.
Packit cb6d3d
  Not meaningful if track is not an audio track.
Packit cb6d3d
*/
Packit cb6d3d
int
Packit cb6d3d
cdda_track_channels(cdrom_drive_t *d, track_t i_track)
Packit cb6d3d
{
Packit cb6d3d
  return(cdio_get_track_channels(d->p_cdio, i_track));
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Return 1 is track is an audio track, 0 otherwise. */
Packit cb6d3d
int
Packit cb6d3d
cdda_track_audiop(cdrom_drive_t *d, track_t i_track)
Packit cb6d3d
{
Packit cb6d3d
  track_format_t track_format = cdio_get_track_format(d->p_cdio, i_track);
Packit cb6d3d
  return TRACK_FORMAT_AUDIO == track_format ? 1 : 0;
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Return 1 is track is an audio track, 0 otherwise. */
Packit cb6d3d
int
Packit cb6d3d
cdda_track_copyp(cdrom_drive_t *d, track_t i_track)
Packit cb6d3d
{
Packit cb6d3d
  track_flag_t track_flag = cdio_get_track_copy_permit(d->p_cdio, i_track);
Packit cb6d3d
  return CDIO_TRACK_FLAG_TRUE == track_flag ? 1 : 0;
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*! Return 1 is audio track has linear preemphasis set, 0 otherwise.
Packit cb6d3d
    Only makes sense for audio tracks.
Packit cb6d3d
 */
Packit cb6d3d
int
Packit cb6d3d
cdda_track_preemp(cdrom_drive_t *d, track_t i_track)
Packit cb6d3d
{
Packit cb6d3d
  track_flag_t track_flag = cdio_get_track_preemphasis(d->p_cdio, i_track);
Packit cb6d3d
  return CDIO_TRACK_FLAG_TRUE == track_flag ? 1 : 0;
Packit cb6d3d
}