/*! reads TOC via libcdio and returns the number of tracks in the disc.
    0 is returned if there was an error.
*/
static int
cddap_readtoc (cdrom_drive_t *d)
{
  int i;
  track_t i_track;

  /* Save TOC Entries */
  d->tracks = cdio_get_num_tracks(d->p_cdio) ;

  if (CDIO_INVALID_TRACK == d->tracks) return 0;

  i_track   = cdio_get_first_track_num(d->p_cdio);

  for ( i=0; i < d->tracks; i++) {
    d->disc_toc[i].bTrack = i_track;
    d->disc_toc[i].dwStartSector = cdio_get_track_lsn(d->p_cdio, i_track);
    i_track++;
  }

  d->disc_toc[i].bTrack = i_track;
  d->disc_toc[i].dwStartSector = cdio_get_track_lsn(d->p_cdio,
						    CDIO_CDROM_LEADOUT_TRACK);

  d->cd_extra=FixupTOC(d, d->tracks+1); /* fixup includes lead-out */
  return d->tracks;  /* number of tracks returned does not include lead-out */
}
示例#2
0
文件: track.c 项目: Crome/libcdio
/*! Find the track which contans lsn.
    CDIO_INVALID_TRACK is returned if the lsn outside of the CD or
    if there was some error. 
    
    If the lsn is before the pregap of the first track 0 is returned.
    Otherwise we return the track that spans the lsn.
*/
track_t
cdio_get_track(const CdIo_t *p_cdio, lsn_t lsn)
{
  if (!p_cdio) return CDIO_INVALID_TRACK;
  
  {
    track_t i_low_track   = cdio_get_first_track_num(p_cdio);
    track_t i_high_track  = cdio_get_last_track_num(p_cdio)+1; /* LEADOUT */

    if (CDIO_INVALID_TRACK == i_low_track 
	|| CDIO_INVALID_TRACK == i_high_track ) return CDIO_INVALID_TRACK;
    
    if (lsn < cdio_get_track_lsn(p_cdio, i_low_track))
      return 0; /* We're in the pre-gap of first track */

    if (lsn > cdio_get_track_lsn(p_cdio, i_high_track))
      return CDIO_INVALID_TRACK; /* We're beyond the end. */

    do {
      const track_t i_mid = (i_low_track + i_high_track) / 2;
      const lsn_t i_mid_lsn = cdio_get_track_lsn(p_cdio, i_mid);
      if (lsn <= i_mid_lsn) i_high_track = i_mid - 1;
      if (lsn >= i_mid_lsn) i_low_track  = i_mid + 1;
    } while ( i_low_track <= i_high_track );

    return (i_low_track > i_high_track + 1) 
      ? i_high_track + 1 : i_high_track;
  }
}
示例#3
0
文件: cdda.c 项目: Gardenya/deadbeef
static cddb_disc_t *
create_disc(CdIo_t *cdio)
{
    cddb_disc_t *disc = cddb_disc_new();
    if (disc) {
        const lba_t leadout_lba = cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK);
        cddb_disc_set_length(disc, leadout_lba / CDIO_CD_FRAMES_PER_SEC);
        const track_t first_track = cdio_get_first_track_num(cdio);
        const track_t num_tracks = cdio_get_num_tracks(cdio);
        if (leadout_lba == CDIO_INVALID_LBA || first_track == CDIO_INVALID_TRACK || num_tracks == CDIO_INVALID_TRACK) {
            trace("cda: create_disc failed, invalid CD disc format\n");
            cddb_disc_destroy(disc);
            return NULL;
        }

        const track_t last_track = first_track + num_tracks;
        for (track_t i = first_track; i < last_track; i++) {
            cddb_track_t *track = cddb_track_new();
            if (!track) {
                cddb_disc_destroy(disc);
                return NULL;
            }
            const lba_t offset = cdio_get_track_lba(cdio, i);
            cddb_track_set_frame_offset(track, offset);
            cddb_disc_add_track(disc, track);
        }
        cddb_disc_calc_discid(disc);
    }

    return disc;
}
static int
verify_read_command(cdrom_drive_t *d)
{
  int i;
  int16_t *buff=malloc(CDIO_CD_FRAMESIZE_RAW);
  int audioflag=0;
  int i_test_flags = d->i_test_flags;
  int first_track = cdio_get_first_track_num(d->p_cdio);

  d->i_test_flags = 0;

  cdmessage(d,"Verifying drive can read CDDA...\n");

  d->enable_cdda(d,1);

  for(i=first_track; i<first_track+d->tracks; i++){
    if(cdda_track_audiop(d,i)==1){
      long firstsector=cdda_track_firstsector(d,i);
      long lastsector=cdda_track_lastsector(d,i);
      long sector=(firstsector+lastsector)>>1;
      audioflag=1;

      if(d->read_audio(d,buff,sector,1)>0){
	cdmessage(d,"\tExpected command set reads OK.\n");
	d->enable_cdda(d,0);
	free(buff);
	d->i_test_flags = i_test_flags;
	return(0);
      }
    }
  }
示例#5
0
int
main(int argc, const char *argv[])
{
    CdIo_t *p_cdio = cdio_open ("/dev/cdrom", DRIVER_LINUX);
    track_t i_first_track;
    track_t i_tracks;
    int j, i;


    if (NULL == p_cdio) {
        printf("Couldn't find a driver.. leaving.\n");
        return 1;
    }

    printf("Disc last LSN: %d\n", cdio_get_disc_last_lsn(p_cdio));

    i_tracks      = cdio_get_num_tracks(p_cdio);
    i_first_track = i = cdio_get_first_track_num(p_cdio);

    printf("CD-ROM Track List (%i - %i)\n", i_first_track,
           i_first_track+i_tracks-1);

    printf("  #:  LSN\n");

    for (j = 0; j < i_tracks; i++, j++) {
        lsn_t lsn = cdio_get_track_lsn(p_cdio, i);
        if (CDIO_INVALID_LSN != lsn)
            printf("%3d: %06lu\n", (int) i, (long unsigned int) lsn);
    }
    printf("%3X: %06lu  leadout\n", CDIO_CDROM_LEADOUT_TRACK,
           (long unsigned int) cdio_get_track_lsn(p_cdio,
                                                  CDIO_CDROM_LEADOUT_TRACK));
    cdio_destroy(p_cdio);
    return 0;
}
示例#6
0
文件: access.c 项目: BtbN/vlc
/*****************************************************************************
  VCDEntryPoints: Reads the information about the entry points on the disc
  and initializes area information with that.
  Before calling this track information should have been read in.
 *****************************************************************************/
static bool
VCDEntryPoints( access_t * p_access )
{
    if (!p_access || !p_access->p_sys) return false;
 
    vcdplayer_t       *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
    const unsigned int i_entries   = vcdinfo_get_num_entries(p_vcdplayer->vcd);
    const track_t      i_last_track
           = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcdplayer->vcd))
           + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcdplayer->vcd));
    unsigned int i;
 
    if (0 == i_entries) {
        LOG_ERR ("no entires found -- something is wrong" );
        return false;
    }
 
    p_vcdplayer->p_entries  = malloc( sizeof( lsn_t ) * i_entries );
 
    if( p_vcdplayer->p_entries == NULL )
    {
        LOG_ERR ("not enough memory for entry points treatment" );
        return false;
    }
 
    p_vcdplayer->i_entries = i_entries;
 
    for( i = 0 ; i < i_entries ; i++ )
    {
        const track_t i_track = vcdinfo_get_track(p_vcdplayer->vcd, i);
        if( i_track <= i_last_track )
        {
            seekpoint_t *s = vlc_seekpoint_New();
            char psz_entry[100];
    
            snprintf(psz_entry, sizeof(psz_entry), "%s %02d", _("Entry"), i );

            p_vcdplayer->p_entries[i] =
                                   vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i);
    
            s->psz_name      = strdup(psz_entry);
            s->i_byte_offset = (p_vcdplayer->p_entries[i]
                             - vcdinfo_get_track_lsn(p_vcdplayer->vcd,i_track))
                             * M2F2_SECTOR_SIZE;
    
            dbg_print( INPUT_DBG_MRL, "%s, lsn %d,  byte_offset %"PRId64"",
                       s->psz_name, p_vcdplayer->p_entries[i],
                       s->i_byte_offset);
            TAB_APPEND( p_vcdplayer->p_title[i_track-1]->i_seekpoint,
                        p_vcdplayer->p_title[i_track-1]->seekpoint, s );

        } else
            msg_Warn( p_access, "wrong track number found in entry points" );
    }
    p_vcdplayer->b_valid_ep = true;
    return true;
}
示例#7
0
文件: cdda.c 项目: AriaAsuka/deadbeef
static DB_playItem_t *
insert_disc (ddb_playlist_t *plt, DB_playItem_t *after, const char *path, const track_t single_track, CdIo_t* cdio)
{
    struct cddb_thread_params *p = calloc(1, sizeof(struct cddb_thread_params));
    if (!p) {
        return NULL;
    }

    p->disc = create_disc(cdio);
    if (!p->disc) {
        cleanup_thread_params(p);
        return NULL;
    }

    const track_t tracks = single_track ? 1 : cddb_disc_get_track_count(p->disc);
    p->items = calloc(tracks+1, sizeof(*p->items));
    if (!p->items) {
        cleanup_thread_params(p);
        return NULL;
    }

    const unsigned long discid = cddb_disc_get_discid(p->disc);
    DB_playItem_t *inserted = NULL;
    const track_t first_track = single_track ? single_track : cdio_get_first_track_num(cdio);
    track_t item_count = 0;
    for (track_t i = 0; i < tracks; i++) {
        if (cdio_get_track_format(cdio, first_track+i) == TRACK_FORMAT_AUDIO) {
            trace("inserting track %d from %s\n", first_track+i, path);
            inserted = insert_track(plt, after, path, first_track+i, cdio, discid);
            p->items[item_count++] = inserted;
            after = inserted;
        }
    }

    intptr_t tid = 0;
    if (item_count) {
        const int got_cdtext = read_disc_cdtext(cdio, p->items, tracks);
        const int prefer_cdtext = deadbeef->conf_get_int("cdda.prefer_cdtext", DEFAULT_PREFER_CDTEXT);
        const int enable_cddb = deadbeef->conf_get_int("cdda.freedb.enable", DEFAULT_USE_CDDB);
        if (!(got_cdtext && prefer_cdtext) && enable_cddb) {
            trace("cdda: querying freedb...\n");
            tid = deadbeef->thread_start(cddb_thread, p);
            if (tid) {
                deadbeef->thread_detach(tid);
            }
        }
    }

    if (!tid) {
        cleanup_thread_params(p);
    }

    return inserted;
}
示例#8
0
文件: track.c 项目: AaronDnz/xbmc
/*!
  Return the last track number.
  CDIO_INVALID_TRACK is returned on error.
*/
track_t
cdio_get_last_track_num (const CdIo_t *p_cdio)
{
  if (NULL == p_cdio) return CDIO_INVALID_TRACK;
  {
    const track_t i_first_track = cdio_get_first_track_num(p_cdio);
    if ( CDIO_INVALID_TRACK != i_first_track ) {
      const track_t i_tracks = cdio_get_num_tracks(p_cdio);
      if ( CDIO_INVALID_TRACK != i_tracks ) 
	return i_first_track + i_tracks - 1;
    }
    return CDIO_INVALID_TRACK;
  }
}
示例#9
0
void CddaImpl::open()
{
   driver_id_t driver_id = DRIVER_UNKNOWN;

   if (_device.empty())
   {
   char **ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL,  
                                                         CDIO_FS_AUDIO, 
                                                         false,
                                                         &driver_id);
   if (ppsz_cd_drives && *ppsz_cd_drives)
      _device = ppsz_cd_drives[0];

   cdio_free_device_list(ppsz_cd_drives);
   }

   _cdio = cdio_open(_device.c_str(), driver_id);

   if (_cdio == NULL) 
   {
      THROW_EXCEPTION(CddaException, "Could not open device.");
   }

   // Detect empty drive   
   if (cdio_get_first_track_num(_cdio) == CDIO_INVALID_TRACK) 
   {
      close();
      return;
   }

   _cdrom = cdio_cddap_identify_cdio(_cdio, CDDA_MESSAGE_LOGIT, NULL);

   if (_cdrom == NULL) 
   {
      THROW_EXCEPTION(CddaException, "Could not read cdrom structure.");
   }

   cdio_cddap_verbose_set(_cdrom, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT);

   int ret = cdio_cddap_open(_cdrom);
   if (ret != 0) 
   {
      THROW_EXCEPTION(CddaException, cdda_error_message(ret));
   }

   _is_open = true;

   read_toc();
   //read_cddb();
}
示例#10
0
文件: cdda.c 项目: vadmium/deadbeef
cddb_disc_t*
resolve_disc (CdIo_t *cdio)
{
    track_t first_track = cdio_get_first_track_num (cdio);
    track_t tracks = cdio_get_num_tracks (cdio);
    track_t i;
    cddb_track_t *track;

    cddb_disc_t *disc = cddb_disc_new();

    cddb_disc_set_length (disc, cdio_get_track_lba (cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC);

    for (i = 0; i < tracks; i++)
    {
        lsn_t offset = cdio_get_track_lba (cdio, i+first_track);
        track = cddb_track_new();
        cddb_track_set_frame_offset (track, offset);
        cddb_disc_add_track (disc, track);
    }
    cddb_conn_t *conn = NULL;

    conn = cddb_new();

    deadbeef->conf_lock ();
    cddb_set_server_name (conn, deadbeef->conf_get_str_fast ("cdda.freedb.host", DEFAULT_SERVER));
    cddb_set_server_port (conn, deadbeef->conf_get_int ("cdda.freedb.port", DEFAULT_PORT));

    if (!deadbeef->conf_get_int ("cdda.protocol", DEFAULT_PROTOCOL))
    {
        cddb_http_enable (conn);
        if (deadbeef->conf_get_int ("network.proxy", 0))
        {
            cddb_set_server_port(conn, deadbeef->conf_get_int ("network.proxy.port", 8080));
            cddb_set_server_name(conn, deadbeef->conf_get_str_fast ("network.proxy.address", ""));
        }
    }
    deadbeef->conf_unlock ();

    int matches = cddb_query (conn, disc);
    if (matches == -1)
    {
        cddb_disc_destroy (disc);
        cddb_destroy (conn);
        return NULL;
    }
    cddb_read (conn, disc);
    cddb_destroy (conn);
    return disc;
}
示例#11
0
文件: cdda.c 项目: vadmium/deadbeef
static int
read_disc_cdtext (struct cddb_thread_params *params)
{
    DB_playItem_t **items = params->items;
    cdtext_t *cdtext = cdio_get_cdtext (params->cdio, 0);
    if (!cdtext)
        return 0;

    track_t first_track = cdio_get_first_track_num (params->cdio);
    track_t tracks = cdio_get_num_tracks (params->cdio);
    track_t i;
    for (i = 0; i < tracks; i++)
        read_track_cdtext (params->cdio, i + first_track, params->items[i]);

    return 1;
}
示例#12
0
/*! Read CD TOC  and set CD information. */
static void
read_toc(CdIo_t *p_cdio)
{
  track_t i;

  i_first_track       = cdio_get_first_track_num(p_cdio);
  i_last_track        = cdio_get_last_track_num(p_cdio);
  i_tracks            = cdio_get_num_tracks(p_cdio);
  i_first_audio_track = i_first_track;
  i_last_audio_track  = i_last_track;


  if ( CDIO_INVALID_TRACK == i_first_track ||
       CDIO_INVALID_TRACK == i_last_track ) {
    xperror("read toc header");
    b_cd = false;
    b_record = false;
  } else {
    b_cd = true;
    i_data = 0;
    for (i = i_first_track; i <= i_last_track+1; i++) {
      if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) )
      {
	xperror("read toc entry");
	b_cd = false;
	return;
      }
      if ( TRACK_FORMAT_AUDIO != cdio_get_track_format(p_cdio, i) ) {
	if ((i != i_last_track+1) ) {
	  i_data++;
	  if (i == i_first_track) {
	    if (i == i_last_track)
	      i_first_audio_track = CDIO_CDROM_LEADOUT_TRACK;
	    else
	      i_first_audio_track++;
	  }
	}
      }
    }
    b_record = true;
    read_subchannel(p_cdio);
    if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY)
      play_track(1, CDIO_CDROM_LEADOUT_TRACK);
  }
}
示例#13
0
//public
int CdDecoder::getNumCDAudioTracks()
{
    QMutexLocker lock(&getCdioMutex());

    StCdioDevice cdio(m_devicename);
    if (!cdio)
        return 0;

    int nAudio = 0;
    const track_t last = cdio_get_last_track_num(cdio);
    if (CDIO_INVALID_TRACK != last)
    {
        for (track_t t = cdio_get_first_track_num(cdio) ; t <= last; ++t)
        {
            if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, t))
                ++nAudio;
        }
        LOG(VB_MEDIA, LOG_DEBUG, QString("getNumCDAudioTracks = %1").arg(nAudio));
    }

    return nAudio;
}
static void
display_toc(cdrom_drive_t *d)
{
  long audiolen=0;
  track_t i;

  report("\nTable of contents (audio tracks only):\n"
         "track        length               begin        copy pre ch\n"
         "===========================================================");

  for( i=cdio_get_first_track_num(d->p_cdio);
       i<=cdio_get_last_track_num(d->p_cdio); i++)
    if ( cdda_track_audiop(d,i) > 0 ) {

      lsn_t sec=cdda_track_firstsector(d,i);
      lsn_t off=cdda_track_lastsector(d,i)-sec+1;

      report("%3d.  %7ld [%02d:%02d.%02d]  %7ld [%02d:%02d.%02d]  %s %s %s",
	     i,
	     (long int) off,
             (int) (off/(CDIO_CD_FRAMES_PER_MIN)),
             (int) ((off/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
             (int) (off % CDIO_CD_FRAMES_PER_SEC),
	     (long int) sec,
             (int) (sec/(CDIO_CD_FRAMES_PER_MIN)),
             (int) ((sec/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
             (int) (sec % CDIO_CD_FRAMES_PER_SEC),
	     cdda_track_copyp(d,i)?"  OK":"  no",
	     cdda_track_preemp(d,i)?" yes":"  no",
	     cdda_track_channels(d,i)==2?" 2":" 4");
      audiolen+=off;
    }
  report("TOTAL %7ld [%02d:%02d.%02d]    (audio only)",
	 audiolen,
         (int) (audiolen/(CDIO_CD_FRAMES_PER_MIN)),
         (int) ((audiolen/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
	 (int) (audiolen % CDIO_CD_FRAMES_PER_SEC));
  report(" ");
}
示例#15
0
static Cddb::Toc& GetToc(CdIo_t *cdio, Cddb::Toc& toc)
{
    // Get lead-in
    const track_t firstTrack = cdio_get_first_track_num(cdio);
    lsn_t lsn0 = 0;
    msf_t msf;
    if (cdio_get_track_msf(cdio, firstTrack, &msf))
        lsn0 = (msf.m * 60 + msf.s) * CDIO_CD_FRAMES_PER_SEC + msf.f;

    const track_t lastTrack = cdio_get_last_track_num(cdio);
    for (track_t t = firstTrack; t <= lastTrack + 1; ++t)
    {
#if 0 // This would be better but the msf's returned are way off in libcdio 0.81
        if (!cdio_get_track_msf(cdio, t, &msf))
            break;
#else
        lsn_t lsn = cdio_get_track_lsn(cdio, t);
        if (s_lastAudioLsn && lsn > s_lastAudioLsn)
            lsn = s_lastAudioLsn;
        lsn += lsn0; // lead-in

        std::div_t d = std::div(lsn, CDIO_CD_FRAMES_PER_SEC);
        msf.f = d.rem;
        d = std::div(d.quot, 60);
        msf.s = d.rem;
        msf.m = d.quot;
#endif
        //LOG(VB_MEDIA, LOG_INFO, QString("Track %1 msf: %2:%3:%4").
        //    arg(t,2).arg(msf.m,2).arg(msf.s,2).arg(msf.f,2) );
        toc.push_back(Cddb::Msf(msf.m, msf.s, msf.f));

        if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, t))
            break;
    }
    return toc;
}
static long
parse_offset(cdrom_drive_t *d, char *offset, int begin)
{
  track_t i_track= CDIO_INVALID_TRACK;
  long hours   = -1;
  long minutes = -1;
  long seconds = -1;
  long sectors = -1;
  char *time   = NULL;
  char *temp   = NULL;
  long ret;

  if (!offset) return -1;

  /* separate track from time offset */
  temp=strchr(offset,']');
  if(temp){
    *temp='\0';
    temp=strchr(offset,'[');
    if(temp==NULL){
      report("Error parsing span argument");
      exit(1);
    }
    *temp='\0';
    time=temp+1;
  }

  /* parse track */
  {
    int chars=strspn(offset,"0123456789");
    if(chars>0){
      offset[chars]='\0';
      i_track=atoi(offset);
      if (i_track >= cdio_get_first_track_num(d->p_cdio) + d->tracks) {
        /*take track i_first_track-1 as pre-gap of 1st track*/
	report("Track #%d does not exist.",i_track);
        exit(1);
      }
    }
  }

  while(time){
    long val,chars;
    char *sec=strrchr(time,'.');
    if(!sec)sec=strrchr(time,':');
    if(!sec)sec=time-1;

    chars=strspn(sec+1,"0123456789");
    if(chars)
      val=atoi(sec+1);
    else
      val=0;

    switch(*sec){
    case '.':
      if(sectors!=-1){
        report("Error parsing span argument");
        exit(1);
      }
      sectors=val;
      break;
    default:
      if(seconds==-1)
        seconds=val;
      else
        if(minutes==-1)
          minutes=val;
        else
          if(hours==-1)
            hours=val;
          else{
            report("Error parsing span argument");
            exit(1);
          }
      break;
    }

    if (sec<=time) break;
    *sec='\0';
  }

  if (i_track == CDIO_INVALID_TRACK) {
    if (seconds==-1 && sectors==-1) return -1;
    if (begin==-1) {
      ret=cdda_disc_firstsector(d);
    } else
      ret = begin;
  } else {
    if ( seconds==-1 && sectors==-1 ) {
      if (begin==-1){
        /* first half of a span */
        return(cdda_track_firstsector(d, i_track));
      }else{
        return(cdda_track_lastsector(d, i_track));
      }
    } else {
      /* relative offset into a track */
      ret=cdda_track_firstsector(d, i_track);
    }
  }

  /* OK, we had some sort of offset into a track */

  if (sectors != -1) ret += sectors;
  if (seconds != -1) ret += seconds*CDIO_CD_FRAMES_PER_SEC;
  if (minutes != -1) ret += minutes*CDIO_CD_FRAMES_PER_MIN;
  if (hours   != -1) ret += hours  *60*CDIO_CD_FRAMES_PER_MIN;

  /* We don't want to outside of the track; if it's relative, that's OK... */
  if( i_track != CDIO_INVALID_TRACK ){
    if (cdda_sector_gettrack(d,ret) != i_track) {
      report("Time/sector offset goes beyond end of specified track.");
      exit(1);
    }
  }

  /* Don't pass up end of session */

  if( ret>cdda_disc_lastsector(d) ) {
    report("Time/sector offset goes beyond end of disc.");
    exit(1);
  }

  return(ret);
}
示例#17
0
static int cdpa_get_tracks(rnc_dev_t *dev, rnc_track_t *buf, size_t size)
{
    cdpa_t       *cdpa = dev->data;
    cdpa_track_t *tracks, *trk;
    int           ntrack, base, naudio;
    rnc_track_t  *t;
    int           id, i;

    mrp_debug("getting tracks");

    base = cdio_get_first_track_num(cdpa->cdio);

    if (cdpa->ntrack == 0) {
        ntrack = cdio_get_num_tracks(cdpa->cdio);

        if (ntrack == 0)
            return 0;

        tracks = mrp_allocz_array(typeof(*tracks), ntrack);

        if (tracks == NULL)
            return -1;

        naudio = 0;
        trk    = tracks;
        for (i = 0; i < ntrack; i++) {
            id = base + i;

            if (cdio_get_track_format(cdpa->cdio, id) != TRACK_FORMAT_AUDIO)
                continue;
            trk->id  = id;
            trk->idx = i;
            trk->fblk = cdio_get_track_lsn(cdpa->cdio, id);
            trk->lblk = cdio_get_track_last_lsn(cdpa->cdio, id);

            naudio++;
            trk++;
        }

        cdpa->tracks = tracks;
        cdpa->ntrack = naudio;
    }
    else
        ntrack = cdpa->ntrack;

    if ((int)size > cdpa->ntrack)
        size = cdpa->ntrack;

    for (i = 0, t = buf, trk = cdpa->tracks; i < (int)size; i++, t++, trk++) {
        t->idx    = trk - cdpa->tracks;
        t->id     = base + i;
        t->fblk   = trk->fblk;
        t->nblk   = trk->lblk - trk->fblk + 1;
        t->length = 1.0 * t->nblk / 75.0;
    }

    if (cdpa->ctrack < 0) {
        cdio_paranoia_modeset(cdpa->cdpa, PARANOIA_MODE_FULL);
        cdpa->ctrack = 0;
        seek_track(cdpa, 0, 0);
    }

    return ntrack;
}
示例#18
0
CDRFile *cdrfile_open(const char *path)
{
 CDRFile *ret = (CDRFile *)calloc(1, sizeof(CDRFile));
 struct stat stat_buf;

 if(path == NULL || stat(path, &stat_buf) || !S_ISREG(stat_buf.st_mode))
 {
  CdIo *p_cdio;
  char **devices;
  char **parseit;
  cdio_init();

  GetFileBase("cdrom");

  devices = cdio_get_devices(DRIVER_DEVICE);
  parseit = devices;
  if(parseit)
  {
   MDFN_printf(_("Connected physical devices:\n"));
   MDFN_indent(1);
   while(*parseit)
   {
    MDFN_printf("%s\n", *parseit);
    parseit++;
   }
   MDFN_indent(-1);
  }
  if(!parseit || parseit == devices)
  {
   MDFN_PrintError(_("No CDROM drives detected(or no disc present)."));
   if(devices)
    cdio_free_device_list(devices);
   free(ret);
   return(NULL);
  }

  if(devices)
   cdio_free_device_list(devices);

  p_cdio = cdio_open_cd(path); //, DRIVER_UNKNOWN); //NULL, DRIVER_UNKNOWN);

  if(!p_cdio) 
  {
   free(ret);
   return(NULL);
  }
  ret->p_cdio = p_cdio;

  ret->FirstTrack = cdio_get_first_track_num(ret->p_cdio);
  ret->NumTracks = cdio_get_num_tracks(ret->p_cdio);
  ret->total_sectors = cdio_stat_size(ret->p_cdio);

  if(ret->FirstTrack > 99)
  {
   MDFN_PrintError(_("Invalid first track: %d\n"), ret->FirstTrack);
   free(ret);
   cdio_destroy(p_cdio);
   return(NULL);
  }

  if(ret->NumTracks > 100)
  {
   MDFN_PrintError(_("Invalid track count: %d\n"), ret->NumTracks);
   free(ret);
   cdio_destroy(p_cdio);
   return(NULL);
  }

  for(track_t track = ret->FirstTrack; track < (ret->FirstTrack + ret->NumTracks); track++)
  {
   memset(&ret->Tracks[track], 0, sizeof(CDRFILE_TRACK_INFO));

   ret->Tracks[track].sectors = cdio_get_track_sec_count(ret->p_cdio, track);
   ret->Tracks[track].LSN = cdio_get_track_lsn(ret->p_cdio, track);
   ret->Tracks[track].Format = cdio_get_track_format(ret->p_cdio, track);
  }

  return(ret);
 }

  FILE *fp = fopen(path, "rb");
  bool IsTOC = FALSE;

  // Assign opposite maximum values so our tests will work!
  int FirstTrack = 99;
  int LastTrack = 0;

  if(!fp)
  {
   MDFN_PrintError(_("Error opening CUE sheet/TOC \"%s\": %m\n"), path, errno);
   free(ret);
   return(NULL);
  }
  GetFileBase(path);

  char linebuf[512];
  int32 active_track = -1;
  int32 AutoTrackInc = 1; // For TOC
  CDRFILE_TRACK_INFO TmpTrack;
  memset(&TmpTrack, 0, sizeof(TmpTrack));

  while(fgets(linebuf, 512, fp) > 0)
  {
   char cmdbuf[512], raw_args[512], args[4][512];
   int argcount = 0;

   raw_args[0] = 0;
   cmdbuf[0] = 0;

   args[0][0] = args[1][0] = args[2][0] = args[3][0] = 0;

   if(!strncasecmp(linebuf, "CD_ROM", 6) || !strncasecmp(linebuf, "CD_DA", 5) || !strncasecmp(linebuf, "CD_ROM_XA", 9))
   {
    IsTOC = TRUE;
    puts("TOC file detected.");
   }

   if(IsTOC)
   {
    char *ss_loc = strstr(linebuf, "//");
    if(ss_loc)
    {
     ss_loc[0] = '\n'; // For consistency!
     ss_loc[1] = 0;
    }
   }

   trio_sscanf(linebuf, "%s %[^\r\n]", cmdbuf, raw_args);
   
   if(!strcasecmp(cmdbuf, "CD_ROM") || !strcasecmp(cmdbuf, "CD_DA"))
    IsTOC = TRUE;

   UnQuotify(UnQuotify(UnQuotify(UnQuotify(raw_args, args[0]), args[1]), args[2]), args[3]);
   if(args[0][0])
   {
    argcount++;
    if(args[1][0])
    {
     argcount++;
     if(args[2][0])
     {
      argcount++;
      if(args[3][0])
      {
       argcount++;
      }
     }
    } 
   }

   if(IsTOC)
   {
    if(!strcasecmp(cmdbuf, "TRACK"))
    {
     if(active_track >= 0)
     {
      memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
      memset(&TmpTrack, 0, sizeof(TmpTrack));
      active_track = -1;
     }
 
     if(AutoTrackInc > 99)
     {
      MDFN_printf(_("Invalid track number: %d\n"), AutoTrackInc);
      free(ret);
      return(NULL);
     }

     active_track = AutoTrackInc++;
     if(active_track < FirstTrack)
      FirstTrack = active_track;
     if(active_track > LastTrack)
      LastTrack = active_track;

     if(!strcasecmp(args[0], "AUDIO"))
     {
      TmpTrack.Format = TRACK_FORMAT_AUDIO;
      TmpTrack.RawAudioMSBFirst = TRUE; // Silly cdrdao...
     }
     else if(!strcasecmp(args[0], "MODE1"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 0;
     }
     else if(!strcasecmp(args[0], "MODE1_RAW"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 1;
     }
    
     if(!strcasecmp(args[1], "RW"))
     {
      TmpTrack.SubchannelMode = CDRF_SUBM_RW;
      MDFN_printf(_("\"RW\" format subchannel data not supported, only \"RW_RAW\" is!\n"));
      free(ret);
      return(0);
     }
     else if(!strcasecmp(args[1], "RW_RAW"))
      TmpTrack.SubchannelMode = CDRF_SUBM_RW_RAW;

    } // end to TRACK
    else if(!strcasecmp(cmdbuf, "SILENCE"))
    {

    }
    else if(!strcasecmp(cmdbuf, "ZERO"))
    {

    }
    else if(!strcasecmp(cmdbuf, "FILE") || !strcasecmp(cmdbuf, "AUDIOFILE"))
    {
     const char *binoffset = NULL;
     const char *msfoffset = NULL;
     const char *length = NULL;

     if(args[1][0] == '#')
     {
      binoffset = args[1] + 1;
      msfoffset = args[2];
      length = args[3];
     }
     else
     {
      msfoffset = args[1];
      length = args[2];
     }
     //printf("%s, %s, %s, %s\n", args[0], binoffset, msfoffset, length);
     if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, msfoffset, length))
     {
      free(ret);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "DATAFILE"))
    {
     const char *binoffset = NULL;
     const char *length = NULL;
  
     if(args[1][0] == '#') 
     {
      binoffset = args[1] + 1;
      length = args[2];
     }
     else
      length = args[1];

     if(!ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, NULL, length))
     {
      free(ret);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "INDEX"))
    {

    }
    else if(!strcasecmp(cmdbuf, "PREGAP"))
    {
     if(active_track < 0)
     {
      MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf);
      free(ret);
      return(NULL);
     }
     int m,s,f;
     trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f);
     TmpTrack.pregap = (m * 60 + s) * 75 + f;
    } // end to PREGAP
    else if(!strcasecmp(cmdbuf, "START"))
    {
     if(active_track < 0)
     {
      MDFN_printf(_("Command %s is outside of a TRACK definition!\n"), cmdbuf);
      free(ret);
      return(NULL);
     }
     int m,s,f;
     trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f);
     TmpTrack.pregap = (m * 60 + s) * 75 + f;
    }
   } /*********** END TOC HANDLING ************/
   else // now for CUE sheet handling
   {
    if(!strcasecmp(cmdbuf, "FILE"))
    {
     if(active_track >= 0)
     {
      memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
      memset(&TmpTrack, 0, sizeof(TmpTrack));
      active_track = -1;
     }
     std::string efn = MDFN_MakeFName(MDFNMKF_AUX, 0, args[0]);
     if(NULL == (TmpTrack.fp = fopen(efn.c_str(), "rb")))
     {
      MDFN_printf(_("Could not open referenced file \"%s\": %m\n"), efn.c_str(), errno);
      free(ret);
      return(0);
     }
     TmpTrack.FirstFileInstance = 1;
     if(!strcasecmp(args[1], "BINARY"))
     {
      //TmpTrack.Format = TRACK_FORMAT_DATA;
      //struct stat stat_buf;
      //fstat(fileno(TmpTrack.fp), &stat_buf);
      //TmpTrack.sectors = stat_buf.st_size; // / 2048;
     }
     else if(!strcasecmp(args[1], "OGG") || !strcasecmp(args[1], "VORBIS") || !strcasecmp(args[1], "WAVE") || !strcasecmp(args[1], "WAV") || !strcasecmp(args[1], "PCM")
	|| !strcasecmp(args[1], "MPC") || !strcasecmp(args[1], "MP+"))
     {
      TmpTrack.ovfile = (OggVorbis_File *) calloc(1, sizeof(OggVorbis_File));

      if((TmpTrack.sf = sf_open_fd(fileno(TmpTrack.fp), SFM_READ, &TmpTrack.sfinfo, 0)))
      {
       free(TmpTrack.ovfile);
       TmpTrack.ovfile = NULL;
      }
      else if(!lseek(fileno(TmpTrack.fp), 0, SEEK_SET) && !ov_open(TmpTrack.fp, TmpTrack.ovfile, NULL, 0))
      {
       //TmpTrack.Format = TRACK_FORMAT_AUDIO;
       //TmpTrack.sectors = ov_pcm_total(&TmpTrack.ovfile, -1) / 588;
      }
      else
      {      
       free(TmpTrack.ovfile);
       TmpTrack.ovfile = NULL;

       fseek(TmpTrack.fp, 0, SEEK_SET);

       TmpTrack.MPCReaderFile = (mpc_reader_file *)calloc(1, sizeof(mpc_reader_file));
       TmpTrack.MPCStreamInfo = (mpc_streaminfo *)calloc(1, sizeof(mpc_streaminfo));
       TmpTrack.MPCDecoder = (mpc_decoder *)calloc(1, sizeof(mpc_decoder));
       TmpTrack.MPCBuffer = (MPC_SAMPLE_FORMAT *)calloc(MPC_DECODER_BUFFER_LENGTH, sizeof(MPC_SAMPLE_FORMAT));

       mpc_streaminfo_init(TmpTrack.MPCStreamInfo);

       mpc_reader_setup_file_reader(TmpTrack.MPCReaderFile, TmpTrack.fp);

       if(mpc_streaminfo_read(TmpTrack.MPCStreamInfo, &TmpTrack.MPCReaderFile->reader) != ERROR_CODE_OK)
       {
        MDFN_printf(_("Unsupported audio track file format: %s\n"), args[0]);
        free(TmpTrack.MPCReaderFile);
        free(TmpTrack.MPCStreamInfo);
        free(TmpTrack.MPCDecoder);
        free(TmpTrack.MPCBuffer);
        free(ret);
        return(0);
       }

       mpc_decoder_setup(TmpTrack.MPCDecoder, &TmpTrack.MPCReaderFile->reader);
       if(!mpc_decoder_initialize(TmpTrack.MPCDecoder, TmpTrack.MPCStreamInfo))
       {
        MDFN_printf(_("Error initializing MusePack decoder: %s!\n"), args[0]);
        free(TmpTrack.MPCReaderFile);
        free(TmpTrack.MPCStreamInfo);
        free(TmpTrack.MPCDecoder);
        free(TmpTrack.MPCBuffer);
        free(ret);
        return(0);
       }
      }
     }
     else
     {
      MDFN_printf(_("Unsupported track format: %s\n"), args[1]);
      free(ret);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "TRACK"))
    {
     if(active_track >= 0)
     {
      memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
      TmpTrack.FirstFileInstance = 0;
      TmpTrack.pregap = 0;
     }
     active_track = atoi(args[0]);

     if(active_track < FirstTrack)
      FirstTrack = active_track;
     if(active_track > LastTrack)
      LastTrack = active_track;

     if(!strcasecmp(args[1], "AUDIO"))
      TmpTrack.Format = TRACK_FORMAT_AUDIO;
     else if(!strcasecmp(args[1], "MODE1/2048"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 0;
     }
     else if(!strcasecmp(args[1], "MODE1/2352"))
     {
      TmpTrack.Format = TRACK_FORMAT_DATA;
      TmpTrack.IsData2352 = 1;
     }
     TmpTrack.sectors = GetSectorCount(&TmpTrack);
     if(active_track < 0 || active_track > 99)
     {
      MDFN_printf(_("Invalid track number: %d\n"), active_track);
      return(0);
     }
    }
    else if(!strcasecmp(cmdbuf, "INDEX"))
    {
     if(active_track >= 0 && (!strcasecmp(args[0], "01") || !strcasecmp(args[0], "1")))
     {
      int m,s,f;
      trio_sscanf(args[1], "%d:%d:%d", &m, &s, &f);
      TmpTrack.index = (m * 60 + s) * 75 + f;
     }
    }
    else if(!strcasecmp(cmdbuf, "PREGAP"))
    {
     if(active_track >= 0)
     {
      int m,s,f;
      trio_sscanf(args[0], "%d:%d:%d", &m, &s, &f);
      TmpTrack.pregap = (m * 60 + s) * 75 + f;
     }
    }
   } // end of CUE sheet handling
  } // end of fgets() loop

 if(ferror(fp))
 {
  if(IsTOC)
   MDFN_printf(_("Error reading TOC file: %m\n"), errno);
  else
   MDFN_printf(_("Error reading CUE sheet: %m\n"), errno);
  return(0);
 }

 if(active_track >= 0)
  memcpy(&ret->Tracks[active_track], &TmpTrack, sizeof(TmpTrack));
 
 if(FirstTrack > LastTrack)
 {
  MDFN_printf(_("No tracks found!\n"));
  return(0);
 }

 ret->FirstTrack = FirstTrack;
 ret->NumTracks = 1 + LastTrack - FirstTrack;

 lsn_t RunningLSN = 0;
 lsn_t LastIndex = 0;
 long FileOffset = 0;

 for(int x = ret->FirstTrack; x < (ret->FirstTrack + ret->NumTracks); x++)
 {
  if(IsTOC)
  {
   RunningLSN += ret->Tracks[x].pregap;
   ret->Tracks[x].LSN = RunningLSN;
   RunningLSN += ret->Tracks[x].sectors;
  }
  else // else handle CUE sheet...
  {
   if(ret->Tracks[x].FirstFileInstance) 
   {
    LastIndex = 0;
    FileOffset = 0;
   }
   RunningLSN += ret->Tracks[x].pregap;

   ret->Tracks[x].LSN = RunningLSN;

   // Make sure this is set before the call to GetSectorCount() for the last track sector count fix.
   ret->Tracks[x].FileOffset = FileOffset;

   if((x + 1) >= (ret->FirstTrack + ret->NumTracks))
   {
    if(!(ret->Tracks[x].FirstFileInstance))
    {
     // This will fix the last sector count for CUE+BIN
     ret->Tracks[x].sectors = GetSectorCount(&ret->Tracks[x]);
    }
   }
   else if(ret->Tracks[x+1].FirstFileInstance)
   {
    //RunningLSN += ret->Tracks[x].sectors;
   }
   else
   { 
    // Fix the sector count if we're CUE+BIN
    ret->Tracks[x].sectors = ret->Tracks[x + 1].index - ret->Tracks[x].index;
   }

   //printf("Poo: %d %d\n", x, ret->Tracks[x].sectors);
   RunningLSN += ret->Tracks[x].sectors;

   //printf("%d, %ld %d %d %d %d\n", x, FileOffset, ret->Tracks[x].index, ret->Tracks[x].pregap, ret->Tracks[x].sectors, ret->Tracks[x].LSN);

   if(ret->Tracks[x].Format == TRACK_FORMAT_AUDIO || TmpTrack.IsData2352)
    FileOffset += ret->Tracks[x].sectors * 2352;
   else
    FileOffset += ret->Tracks[x].sectors * 2048;
  } // end to cue sheet handling
 } // end to track loop

 LEC_Eval = MDFN_GetSettingB("cdrom.lec_eval");
 if(LEC_Eval)
 {
  Init_LEC_Correct();
 }
 MDFN_printf(_("Raw rip data correction using L-EC: %s\n\n"), LEC_Eval ? _("Enabled") : _("Disabled"));

 ret->total_sectors = RunningLSN; // Running LBA?  Running LSN? arghafsdf...LSNBAN!#!$ -_-
 return(ret);
}
示例#19
0
文件: in_vcd.c 项目: Jheengut/gmerlin
static int read_toc(vcd_priv * priv, char ** iso_label)
  {
  int i, j;
  cdio_iso_analysis_t iso;
  cdio_fs_anal_t fs;
  int first_track;
  
  priv->num_tracks = cdio_get_last_track_num(priv->cdio);
  if(priv->num_tracks == CDIO_INVALID_TRACK)
    {
    return 0;
    }
  /* VCD needs at least 2 tracks */
  if(priv->num_tracks < 2)
    return 0;
  
  priv->tracks = calloc(priv->num_tracks, sizeof(*(priv->tracks)));

  priv->num_video_tracks = 0;
  first_track = cdio_get_first_track_num(priv->cdio);
  
  if(iso_label)
    {
    fs = cdio_guess_cd_type(priv->cdio, 0, first_track,
                            &iso);
    
    /* Remove trailing spaces */
    j = strlen(iso.iso_label)-1;
    while(j)
      {
      if(!isspace(iso.iso_label[j]))
        break;
      j--;
      }
    if(!j && isspace(iso.iso_label[j]))
      iso.iso_label[j] = '\0';
    else
      iso.iso_label[j+1] = '\0';
    
    *iso_label = gavl_strdup(iso.iso_label);
    
    priv->tracks[first_track - 1].mode = TRACK_OTHER;
    }
  /* Actually it's (first_track - 1) + 1 */
  for(i = first_track; i < priv->num_tracks; i++)
    {
    priv->tracks[i].start_sector = cdio_get_track_lsn(priv->cdio, i+1);
    priv->tracks[i].end_sector = cdio_get_track_last_lsn(priv->cdio, i+1);

    fs = cdio_guess_cd_type(priv->cdio, 0, i+1, &iso);

    if(fs & CDIO_FS_ANAL_VIDEOCD)
      {
      priv->num_video_tracks++;
      priv->tracks[i].mode = TRACK_VCD;
      }
    else if(fs & CDIO_FS_ANAL_SVCD)
      {
      priv->num_video_tracks++;
      priv->tracks[i].mode = TRACK_SVCD;
      }
    else if(fs & CDIO_FS_ANAL_CVD)
      {
      priv->tracks[i].mode = TRACK_CVD;
      priv->num_video_tracks++;
      }
    else if(fs & CDIO_FS_ANAL_ISO9660_ANY)
      {
      priv->tracks[i].mode = TRACK_VCD;
      priv->num_video_tracks++;
      }

    }
  if(!priv->num_video_tracks)
    {
    free(priv->tracks);
    priv->tracks = NULL;
    return 0;
    }
  return 1;
  }
示例#20
0
/** Read CD TOC and set CD information. */
static void
read_toc(CdIo_t *p_cdio)
{
  track_t i;

  action("read toc...");

  memset(cd_info, 0, sizeof(cd_info));
  title[0] = artist[0] = genre[0] = category[0] = year[0] = '\0';

  i_first_track       = cdio_get_first_track_num(p_cdio);
  i_last_track        = cdio_get_last_track_num(p_cdio);
  i_tracks            = cdio_get_num_tracks(p_cdio);
  i_first_audio_track = i_first_track;
  i_last_audio_track  = i_last_track;


  cdio_audio_get_volume(p_cdio, &audio_volume);
  for (i_vol_port=0; i_vol_port<4; i_vol_port++) {
    if (audio_volume.level[i_vol_port] > 0) break;
  }
  
  if ( CDIO_INVALID_TRACK == i_first_track ||
       CDIO_INVALID_TRACK == i_last_track ) {
    xperror("read toc header");
    b_cd = false;
    b_record = false;
    i_last_display_track = CDIO_INVALID_TRACK;
  } else {
    b_cd = true;
    i_data = 0;
    get_disc_info(p_cdio);
    for (i = i_first_track; i <= i_last_track+1; i++) {
      int s;
      if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) )
      {
        xperror("read toc entry");
        b_cd = false;
        return;
      }
      if ( TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i) ) {
        
        if (i != i_first_track) 
          {
            s = cdio_audio_get_msf_seconds(&toc[i]) 
              - cdio_audio_get_msf_seconds(&toc[i-1]);
            snprintf(cd_info[i-1].length, sizeof(cd_info[0].length), 
                     "%02d:%02d",
                     s / CDIO_CD_SECS_PER_MIN,  s % CDIO_CD_SECS_PER_MIN);
          }
      } else {
        if ((i != i_last_track+1) ) {
          i_data++;
          if (i == i_first_track) {
            if (i == i_last_track)
              i_first_audio_track = CDIO_CDROM_LEADOUT_TRACK;
            else
              i_first_audio_track++;
          }
        }
      }
      get_track_info(i);
    }
    b_record = true;
    read_subchannel(p_cdio);
    if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY)
      play_track(1, CDIO_CDROM_LEADOUT_TRACK);
  }
  action("");
  if (!b_all_tracks)
    display_cdinfo(p_cdio, i_tracks, i_first_track);
}
示例#21
0
int
main(int argc, const char *argv[])
{
  CdIo_t *p_cdio;
  cdio_fs_anal_t fs=0;

  track_t num_tracks;
  track_t first_track_num;
  lsn_t start_track;          /* first sector of track */
  lsn_t data_start =0;        /* start of data area */

  int first_data = -1;        /* # of first data track */
  int first_audio = -1;       /* # of first audio track */
  unsigned int num_data  = 0; /* # of data tracks */
  unsigned int num_audio = 0; /* # of audio tracks */
  unsigned int i;
  char *cd_image_name = NULL;

  if (argc > 1)
    cd_image_name = strdup(argv[1]);

  cdio_log_set_handler (log_handler);

  p_cdio = cdio_open (cd_image_name, DRIVER_UNKNOWN);

  if (NULL == p_cdio) {
    printf("-- Problem in trying to find a driver.\n\n");
    free(cd_image_name);
    return 77;
  }

  first_track_num = cdio_get_first_track_num(p_cdio);
  num_tracks      = cdio_get_num_tracks(p_cdio);

  /* Count the number of data and audio tracks. */
  for (i = first_track_num; i <= num_tracks; i++) {
    if (TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i)) {
      num_audio++;
      if (-1 == first_audio) first_audio = i;
    } else {
      num_data++;
      if (-1 == first_data)  first_data = i;
    }
  }

  /* try to find out what sort of CD we have */
  if (0 == num_data) {
    printf("-- Audio CD\n");
  } else {
    /* we have data track(s) */
    cdio_iso_analysis_t cdio_iso_analysis;

    memset(&cdio_iso_analysis, 0, sizeof(cdio_iso_analysis));

    for (i = first_data; i <= num_tracks; i++) {
      lsn_t lsn;
      track_format_t track_format = cdio_get_track_format(p_cdio, i);

      lsn = cdio_get_track_lsn(p_cdio, i);

      switch ( track_format ) {
      case TRACK_FORMAT_AUDIO:
      case TRACK_FORMAT_ERROR:
	break;
      case TRACK_FORMAT_CDI:
      case TRACK_FORMAT_XA:
      case TRACK_FORMAT_DATA:
      case TRACK_FORMAT_PSX:
	;
      }

      start_track = (i == 1) ? 0 : lsn;

      /* save the start of the data area */
      if (i == first_data)
	data_start = start_track;

      /* skip tracks which belong to the current walked session */
      if (start_track < data_start + cdio_iso_analysis.isofs_size)
	continue;

      fs = cdio_guess_cd_type(p_cdio, start_track, i, &cdio_iso_analysis);

      print_analysis(cdio_iso_analysis, fs, first_data, num_audio);

      if ( !(CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660 ||
	     CDIO_FSTYPE(fs) == CDIO_FS_ISO_HFS  ||
	     CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660_INTERACTIVE) )
	/* no method for non-ISO9660 multisessions */
	break;
    }
  }
  free(cd_image_name);
  cdio_destroy(p_cdio);
  return 0;
}
示例#22
0
static PyObject*
CDImage_first_sector(cdio_CDImage* self, PyObject *args) {
    return Py_BuildValue("i",
                         cdio_get_track_lsn(self->image,
                             cdio_get_first_track_num(self->image)));
}
示例#23
0
/* mutex must be locked */
static void scan_cd (void)
{
    AUDDBG ("Scanning CD drive.\n");
    g_return_if_fail (pcdrom_drive != NULL);
    g_return_if_fail (trackinfo == NULL);

    gint trackno;

    /* general track initialization */

    /* skip endianness detection (because it only affects cdda_read, and we use
     * cdio_read_audio_sectors instead) */
    pcdrom_drive->bigendianp = 0;

    /* finish initialization of drive/disc (performs disc TOC sanitization) */
    if (cdda_open (pcdrom_drive) != 0)
    {
        cdaudio_error ("Failed to finish initializing opened CD drive.");
        goto ERR;
    }

    if (cdda_speed_set (pcdrom_drive, cdng_cfg.disc_speed) != DRIVER_OP_SUCCESS)
        warn ("Cannot set drive speed.\n");

    firsttrackno = cdio_get_first_track_num (pcdrom_drive->p_cdio);
    lasttrackno = cdio_get_last_track_num (pcdrom_drive->p_cdio);
    if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK)
    {
        cdaudio_error ("Failed to retrieve first/last track number.");
        goto ERR;
    }
    AUDDBG ("first track is %d and last track is %d\n", firsttrackno,
           lasttrackno);

    trackinfo = (trackinfo_t *) g_new (trackinfo_t, (lasttrackno + 1));

    cdaudio_set_fullinfo (&trackinfo[0],
                          cdda_track_firstsector (pcdrom_drive, 0),
                          cdda_track_lastsector (pcdrom_drive, lasttrackno),
                          "", "", "");

    n_audio_tracks = 0;

    for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
    {
        cdaudio_set_fullinfo (&trackinfo[trackno],
                              cdda_track_firstsector (pcdrom_drive, trackno),
                              cdda_track_lastsector (pcdrom_drive, trackno),
                              "", "", "");

        if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN
            || trackinfo[trackno].endlsn == CDIO_INVALID_LSN)
        {
            cdaudio_error ("Cannot read start/end LSN for track %d.", trackno);
            goto ERR;
        }

        /* count how many tracks are audio tracks */
        if (cdda_track_audiop (pcdrom_drive, trackno))
            n_audio_tracks++;
    }

    /* get trackinfo[0] cdtext information (the disc) */
    if (cdng_cfg.use_cdtext)
    {
        AUDDBG ("getting cd-text information for disc\n");
        cdtext_t *pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, 0);
        if (pcdtext == NULL || pcdtext->field[CDTEXT_TITLE] == NULL)
        {
            AUDDBG ("no cd-text available for disc\n");
        }
        else
        {
            cdaudio_set_strinfo (&trackinfo[0],
                                 pcdtext->field[CDTEXT_PERFORMER] ? pcdtext->
                                 field[CDTEXT_PERFORMER] : "",
                                 pcdtext->field[CDTEXT_TITLE] ? pcdtext->
                                 field[CDTEXT_TITLE] : "",
                                 pcdtext->field[CDTEXT_GENRE] ? pcdtext->
                                 field[CDTEXT_GENRE] : "");
        }
    }

    /* get track information from cdtext */
    gboolean cdtext_was_available = FALSE;
    for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
    {
        cdtext_t *pcdtext = NULL;
        if (cdng_cfg.use_cdtext)
        {
            AUDDBG ("getting cd-text information for track %d\n", trackno);
            pcdtext = cdio_get_cdtext (pcdrom_drive->p_cdio, trackno);
            if (pcdtext == NULL || pcdtext->field[CDTEXT_PERFORMER] == NULL)
            {
                AUDDBG ("no cd-text available for track %d\n", trackno);
                pcdtext = NULL;
            }
        }

        if (pcdtext != NULL)
        {
            cdaudio_set_strinfo (&trackinfo[trackno],
                                 pcdtext->field[CDTEXT_PERFORMER] ? pcdtext->
                                 field[CDTEXT_PERFORMER] : "",
                                 pcdtext->field[CDTEXT_TITLE] ? pcdtext->
                                 field[CDTEXT_TITLE] : "",
                                 pcdtext->field[CDTEXT_GENRE] ? pcdtext->
                                 field[CDTEXT_GENRE] : "");
            cdtext_was_available = TRUE;
        }
        else
        {
            cdaudio_set_strinfo (&trackinfo[trackno], "", "", "");
            snprintf (trackinfo[trackno].name, DEF_STRING_LEN,
                      "Track %d", trackno);
        }
    }

    if (!cdtext_was_available)
    {
        /* initialize de cddb subsystem */
        cddb_conn_t *pcddb_conn = NULL;
        cddb_disc_t *pcddb_disc = NULL;
        cddb_track_t *pcddb_track = NULL;
        lba_t lba;              /* Logical Block Address */

        if (cdng_cfg.use_cddb)
        {
            pcddb_conn = cddb_new ();
            if (pcddb_conn == NULL)
                cdaudio_error ("Failed to create the cddb connection.");
            else
            {
                AUDDBG ("getting CDDB info\n");

                cddb_cache_enable (pcddb_conn);
                // cddb_cache_set_dir(pcddb_conn, "~/.cddbslave");

                if (cdng_cfg.use_proxy)
                {
                    cddb_http_proxy_enable (pcddb_conn);
                    cddb_set_http_proxy_server_name (pcddb_conn,
                                                     cdng_cfg.proxy_host);
                    cddb_set_http_proxy_server_port (pcddb_conn,
                                                     cdng_cfg.proxy_port);
                    cddb_set_http_proxy_username (pcddb_conn,
                                                  cdng_cfg.proxy_username);
                    cddb_set_http_proxy_password (pcddb_conn,
                                                  cdng_cfg.proxy_password);
                    cddb_set_server_name (pcddb_conn, cdng_cfg.cddb_server);
                    cddb_set_server_port (pcddb_conn, cdng_cfg.cddb_port);
                }
                else if (cdng_cfg.cddb_http)
                {
                    cddb_http_enable (pcddb_conn);
                    cddb_set_server_name (pcddb_conn, cdng_cfg.cddb_server);
                    cddb_set_server_port (pcddb_conn, cdng_cfg.cddb_port);
                    cddb_set_http_path_query (pcddb_conn, cdng_cfg.cddb_path);
                }
                else
                {
                    cddb_set_server_name (pcddb_conn, cdng_cfg.cddb_server);
                    cddb_set_server_port (pcddb_conn, cdng_cfg.cddb_port);
                }

                pcddb_disc = cddb_disc_new ();

                lba = cdio_get_track_lba (pcdrom_drive->p_cdio,
                                          CDIO_CDROM_LEADOUT_TRACK);
                cddb_disc_set_length (pcddb_disc, FRAMES_TO_SECONDS (lba));

                for (trackno = firsttrackno; trackno <= lasttrackno; trackno++)
                {
                    pcddb_track = cddb_track_new ();
                    cddb_track_set_frame_offset (pcddb_track,
                                                 cdio_get_track_lba (
                                                     pcdrom_drive->p_cdio,
                                                     trackno));
                    cddb_disc_add_track (pcddb_disc, pcddb_track);
                }

                cddb_disc_calc_discid (pcddb_disc);

#if DEBUG
                guint discid = cddb_disc_get_discid (pcddb_disc);
                AUDDBG ("CDDB disc id = %x\n", discid);
#endif

                gint matches;
                if ((matches = cddb_query (pcddb_conn, pcddb_disc)) == -1)
                {
                    if (cddb_errno (pcddb_conn) == CDDB_ERR_OK)
                        cdaudio_error ("Failed to query the CDDB server");
                    else
                        cdaudio_error ("Failed to query the CDDB server: %s",
                                       cddb_error_str (cddb_errno
                                                       (pcddb_conn)));

                    cddb_disc_destroy (pcddb_disc);
                    pcddb_disc = NULL;
                }
                else
                {
                    if (matches == 0)
                    {
                        AUDDBG ("no cddb info available for this disc\n");

                        cddb_disc_destroy (pcddb_disc);
                        pcddb_disc = NULL;
                    }
                    else
                    {
                        AUDDBG ("CDDB disc category = \"%s\"\n",
                               cddb_disc_get_category_str (pcddb_disc));

                        cddb_read (pcddb_conn, pcddb_disc);
                        if (cddb_errno (pcddb_conn) != CDDB_ERR_OK)
                        {
                            cdaudio_error ("failed to read the cddb info: %s",
                                           cddb_error_str (cddb_errno
                                                           (pcddb_conn)));
                            cddb_disc_destroy (pcddb_disc);
                            pcddb_disc = NULL;
                        }
                        else
                        {
                            cdaudio_set_strinfo (&trackinfo[0],
                                                 cddb_disc_get_artist
                                                 (pcddb_disc),
                                                 cddb_disc_get_title
                                                 (pcddb_disc),
                                                 cddb_disc_get_genre
                                                 (pcddb_disc));

                            gint trackno;
                            for (trackno = firsttrackno; trackno <= lasttrackno;
                                 trackno++)
                            {
                                cddb_track_t *pcddb_track =
                                    cddb_disc_get_track (pcddb_disc,
                                                         trackno - 1);
                                cdaudio_set_strinfo (&trackinfo[trackno],
                                                     cddb_track_get_artist
                                                     (pcddb_track),
                                                     cddb_track_get_title
                                                     (pcddb_track),
                                                     cddb_disc_get_genre
                                                     (pcddb_disc));
                            }
                        }
                    }
                }
            }
        }

        if (pcddb_disc != NULL)
            cddb_disc_destroy (pcddb_disc);

        if (pcddb_conn != NULL)
            cddb_destroy (pcddb_conn);
    }

    return;

  ERR:
    g_free (trackinfo);
    trackinfo = NULL;
}
示例#24
0
文件: cdda.c 项目: menghun3/aqualung
/* return 0 if OK, -1 if drive is apparently not available */
int
cdda_scan_drive(char * device_path, cdda_drive_t * cdda_drive) {

	track_t tracks;
	track_t first_track;
	track_t last_track;
	track_t skipped = 0;
	int i, n = 0;
	cdrom_drive_t * d;

	if (cdda_drive->cdio == NULL) {
		cdda_drive->cdio = cdio_open(device_path, DRIVER_DEVICE);
		if (!cdda_drive->cdio) {
			return -1;
		}		
		strncpy(cdda_drive->device_path, device_path, CDDA_MAXLEN-1);
	}
	
	cdda_drive->disc.n_tracks = 0;
	tracks = cdio_get_num_tracks(cdda_drive->cdio);

	if (tracks < 1 || tracks >= 100) {
		cdda_drive->disc.hash_prev = cdda_drive->disc.hash;
		cdda_drive->disc.hash = 0L;
		return 0;
	}

	d = cdio_cddap_identify_cdio(cdda_drive->cdio, 0, NULL);
	if (d == NULL) {
		return -1;
	}
		
	first_track = cdio_get_first_track_num(cdda_drive->cdio);
	last_track = cdio_get_last_track_num(cdda_drive->cdio);

	for (i = first_track; i <= last_track; i++) {
		if (!cdio_cddap_track_audiop(d, i)) {
			skipped = i;
			last_track = i-1;
			break;
		}
	}

	cdio_cddap_close_no_free_cdio(d);
	
	if (last_track < first_track) {
		return 0;
	}

	cdda_drive->disc.n_tracks = last_track - first_track + 1;
	for (i = first_track; i <= last_track; i++) {
		lsn_t lsn = cdio_get_track_lsn(cdda_drive->cdio, i);
		if (lsn != CDIO_INVALID_LSN) {
			cdda_drive->disc.toc[n++] = lsn;
		}
	}
	if (skipped == 0) {
		cdda_drive->disc.toc[n] = cdio_get_track_lsn(cdda_drive->cdio, CDIO_CDROM_LEADOUT_TRACK);
	} else {
		cdda_drive->disc.toc[n] = cdio_get_track_lsn(cdda_drive->cdio, skipped);
		if ((cdda_drive->disc.toc[n] - cdda_drive->disc.toc[n-1]) >= 11400) {
			/* compensate end of track with multisession offset */
			cdda_drive->disc.toc[n] -= 11400;
		}
	}

	cdda_drive->disc.hash_prev = cdda_drive->disc.hash;
	cdda_drive->disc.hash = calc_cdda_hash(&cdda_drive->disc);

	if (cdda_drive->disc.hash != cdda_drive->disc.hash_prev) {
		strncpy(cdda_drive->disc.artist_name, _("Unknown Artist"), MAXLEN-1);
		strncpy(cdda_drive->disc.record_name, _("Unknown Record"), MAXLEN-1);

		cdda_drive->swap_bytes = -1; /* unknown */
	}

	return 0;
}
示例#25
0
void
cdda_disc_info(cdda_drive_t * drive) {

	CdIo_t * cdio;
	track_t itrack;
	track_t ntracks;
	track_t track_last;
	cdtext_field_t i;
	gchar * text;

        GtkWidget * dialog;
	GtkWidget * table;
	GtkWidget * label;
	GtkWidget * vbox;
	GtkWidget * hbox;

	GtkListStore * list;
	GtkWidget * view;
	GtkWidget * viewport;
	GtkWidget * scrolled_win;
	GtkCellRenderer * cell;

	GType types[MAX_CDTEXT_FIELDS + 1];
	GtkTreeViewColumn * columns[MAX_CDTEXT_FIELDS + 1];
	int visible[MAX_CDTEXT_FIELDS + 1];
	int has_some_cdtext = 0;


        dialog = gtk_dialog_new_with_buttons(_("Disc info"),
					     GTK_WINDOW(browser_window),
					     GTK_DIALOG_DESTROY_WITH_PARENT |
					     GTK_DIALOG_NO_SEPARATOR,
					     GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
					     NULL);

	gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
	gtk_widget_set_size_request(GTK_WIDGET(dialog), 500, 400);

	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
			   vbox, TRUE, TRUE, 4);


	cdio = cdio_open(drive->device_path, DRIVER_UNKNOWN);

	table = gtk_table_new(MAX_CDTEXT_FIELDS, 2, FALSE);
	gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 2);
	for (i = 0; i < MAX_CDTEXT_FIELDS; i++) {
		text = cdda_get_cdtext(cdio, i, 0);
		if (text && *text != '\0') {
			has_some_cdtext = 1;

			hbox = gtk_hbox_new(FALSE, 0);
			label = gtk_label_new(cdtext_field2str(i));
			gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
			gtk_table_attach(GTK_TABLE(table), hbox, 0, 1, i, i + 1, GTK_FILL, GTK_FILL, 4, 1);

			hbox = gtk_hbox_new(FALSE, 0);
			label = gtk_label_new(text);
			gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
			gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, i, i + 1, GTK_FILL, GTK_FILL, 4, 1);
		}
		g_free(text);
	}


	types[0] = G_TYPE_INT;
	for (i = 1; i <= MAX_CDTEXT_FIELDS; i++) {
		types[i] = G_TYPE_STRING;
		visible[i] = 0;
	}

	list = gtk_list_store_newv(MAX_CDTEXT_FIELDS + 1,
				   types);

        view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list));
        viewport = gtk_viewport_new(NULL, NULL);
        scrolled_win = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win),
                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_box_pack_start(GTK_BOX(vbox), viewport, TRUE, TRUE, 2);
        gtk_container_add(GTK_CONTAINER(viewport), scrolled_win);
        gtk_container_add(GTK_CONTAINER(scrolled_win), view);

        cell = gtk_cell_renderer_text_new();
	g_object_set((gpointer)cell, "xalign", 1.0, NULL);
        columns[0] = gtk_tree_view_column_new_with_attributes(_("No."), cell, "text", 0, NULL);
        gtk_tree_view_append_column(GTK_TREE_VIEW(view), GTK_TREE_VIEW_COLUMN(columns[0]));

	for (i = 0; i < MAX_CDTEXT_FIELDS; i++) {

		cell = gtk_cell_renderer_text_new();
		columns[i + 1] = gtk_tree_view_column_new_with_attributes(cdtext_field2str(i),
									  cell, "text", i + 1, NULL);
		gtk_tree_view_append_column(GTK_TREE_VIEW(view), GTK_TREE_VIEW_COLUMN(columns[i + 1]));
	}

	itrack = cdio_get_first_track_num(cdio);
	ntracks = cdio_get_num_tracks(cdio);
	track_last = itrack + ntracks;

	for (; itrack < track_last; itrack++) {

		GtkTreeIter iter;

		gtk_list_store_append(list, &iter);
		gtk_list_store_set(list, &iter, 0, itrack, -1);

		for (i = 0; i < MAX_CDTEXT_FIELDS; i++) {
			text = cdda_get_cdtext(cdio, i, itrack);
			if (text && *text != '\0') {
				gtk_list_store_set(list, &iter, i + 1, text, -1);
				visible[i + 1] = 1;
				has_some_cdtext = 1;
			}
			g_free(text);
		}
	}

	for (i = 1; i <= MAX_CDTEXT_FIELDS; i++) {
		gtk_tree_view_column_set_visible(columns[i], visible[i]);
	}

	cdio_destroy(cdio);

	gtk_widget_show_all(dialog);

	if (has_some_cdtext) {
		aqualung_dialog_run(GTK_DIALOG(dialog));
		gtk_widget_destroy(dialog);
	} else {
		gtk_widget_destroy(dialog);

		message_dialog(_("Disc info"),
			       browser_window,
			       GTK_MESSAGE_INFO,
			       GTK_BUTTONS_OK,
			       NULL,
			       _("This CD does not contain CD-Text information."));
	}
}
int
main(int argc,char *argv[])
{
  int   toc_bias             =  0;
  int   force_cdrom_endian   = -1;
  int   output_type          =  1; /* 0=raw, 1=wav, 2=aifc */
  int   output_endian        =  0; /* -1=host, 0=little, 1=big */
  int   query_only           =  0;
  int   batch                =  0;
  int   run_cache_test       =  0;
  long int force_cdrom_overlap  = -1;
  long int force_cdrom_sectors  = -1;
  long int force_cdrom_speed    =  0;
  long int force_overread       =  0;
  long int sample_offset        =  0;
  long int test_flags           =  0;
  long int toc_offset           =  0;
  long int max_retries          = 20;

  char *logfile_name=NULL;
  char *reportfile_name=NULL;

  /* full paranoia, but allow skipping */
  int paranoia_mode=PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP;

  int out;

  int c,long_option_index;

  atexit(cleanup);

  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
    switch(c){
    case 'a':
      output_type=2;
      output_endian=1;
      break;
    case 'B':
      batch=1;
      break;
    case 'c':
      force_cdrom_endian=0;
      break;
    case 'C':
      force_cdrom_endian=1;
      break;
    case 'e':
      callscript=1;
      fprintf(stderr,
              "Sending all callback output to stderr for wrapper script\n");
      break;
    case 'f':
      output_type=3;
      output_endian=1;
      break;
    case 'F':
      paranoia_mode&=~(PARANOIA_MODE_FRAGMENT);
      break;
    case 'g':
    case 'k':
    case 'd':
      if (force_cdrom_device) {
        fprintf(stderr,
                "Multiple cdrom devices given. Previous device %s ignored\n",
                force_cdrom_device);
        free(force_cdrom_device);
      }
      force_cdrom_device=strdup(optarg);
      break;
    case 'h':
      usage(stdout);
      exit(0);
    case 'l':
      if(logfile_name)free(logfile_name);
      logfile_name=NULL;
      if(optarg)
	logfile_name=strdup(optarg);
      logfile_open=1;
      break;
    case 'L':
      if(reportfile_name)free(reportfile_name);
      reportfile_name=NULL;
      if(optarg)
	reportfile_name=strdup(optarg);
      reportfile_open=1;
      break;
    case 'm':
      {
        long int mmc_timeout_sec;
        if (get_int_arg(c, &mmc_timeout_sec)) {
          mmc_timeout_ms = 1000*mmc_timeout_sec;
        }
      }
      break;
    case 'n':
      get_int_arg(c, &force_cdrom_sectors);
      break;
    case 'o':
      get_int_arg(c, &force_cdrom_overlap);
      break;
    case 'O':
      get_int_arg(c, &sample_offset);
      break;
    case 'p':
      output_type=0;
      output_endian=-1;
      break;
    case 'r':
      output_type=0;
      output_endian=0;
      break;
    case 'q':
      verbose=CDDA_MESSAGE_FORGETIT;
      quiet=1;
      break;
    case 'Q':
      query_only=1;
      break;
    case 'R':
      output_type=0;
      output_endian=1;
      break;
    case 'S':
      get_int_arg(c, &force_cdrom_speed);
      break;
    case 't':
      get_int_arg(c, &toc_offset);
      break;
    case 'T':
      toc_bias=-1;
      break;
    case 'v':
      verbose=CDDA_MESSAGE_PRINTIT;
      quiet=0;
      break;
    case 'V':
      fprintf(stderr,PARANOIA_VERSION);
      fprintf(stderr,"\n");
      exit(0);
      break;
    case 'w':
      output_type=1;
      output_endian=0;
      break;
    case 'W':
      paranoia_mode&=~PARANOIA_MODE_REPAIR;
      break;
    case 'x':
      get_int_arg(c, &test_flags);
      break;
    case 'X':
      /*paranoia_mode&=~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR);*/
      abort_on_skip=1;
      break;
    case 'Y':
      paranoia_mode|=PARANOIA_MODE_OVERLAP; /* cdda2wav style overlap
                                                check only */
      paranoia_mode&=~PARANOIA_MODE_VERIFY;
      break;
    case 'Z':
      paranoia_mode=PARANOIA_MODE_DISABLE;
      break;
    case 'A':
      run_cache_test=1;
      query_only=1;
      reportfile_open=1;
      verbose=CDDA_MESSAGE_PRINTIT;
      break;
    case 'z':
      if (optarg) {
        get_int_arg(c, &max_retries);
        paranoia_mode&=~PARANOIA_MODE_NEVERSKIP;
      } else {
        paranoia_mode|=PARANOIA_MODE_NEVERSKIP;
      }
      break;
    case 'E':
      force_overread=1;
      break;
    default:
      usage(stderr);
      exit(1);
    }
  }

  if(logfile_open){
    if(logfile_name==NULL)
      logfile_name=strdup("cdparanoia.log");
    if(!strcmp(logfile_name,"-")){
      logfile=stdout;
      logfile_open=0;
    }else{
      logfile=fopen(logfile_name,"w");
      if(logfile==NULL){
	report("Cannot open log summary file %s: %s",logfile_name,
	       strerror(errno));
	exit(1);
      }
    }
  }
  if(reportfile_open){
    if(reportfile_name==NULL)
      reportfile_name=strdup("cdparanoia.log");
    if(!strcmp(reportfile_name,"-")){
      reportfile=stdout;
      reportfile_open=0;
    }else{
      if(logfile_name && !strcmp(reportfile_name,logfile_name)){
	reportfile=logfile;
	reportfile_open=0;
      }else{
	reportfile=fopen(reportfile_name,"w");
	if(reportfile==NULL){
	  report("Cannot open debug log file %s: %s",reportfile_name,
		 strerror(errno));
	  exit(1);
	}
      }
    }
  }

  if(logfile){
    /* log command line and version */
    int i;
    for (i = 0; i < argc; i++)
      fprintf(logfile,"%s ",argv[i]);
    fprintf(logfile,"\n");

    if(reportfile!=logfile){
      fprintf(logfile,VERSION);
      fprintf(logfile,"\n");
      fprintf(logfile,"Using cdda library version: %s\n",cdda_version());
      fprintf(logfile,"Using paranoia library version: %s\n",paranoia_version());
    }
    fflush(logfile);
  }

  if(reportfile && reportfile!=logfile){
    /* log command line */
    int i;
    for (i = 0; i < argc; i++)
      fprintf(reportfile,"%s ",argv[i]);
    fprintf(reportfile,"\n");
    fflush(reportfile);
  }

  if(optind>=argc && !query_only){
    if(batch)
      span=NULL;
    else{
      /* D'oh.  No span. Fetch me a brain, Igor. */
      usage(stderr);
      exit(1);
    }
  }else
    if (argv[optind]) span=strdup(argv[optind]);

  report(PARANOIA_VERSION);
  if(verbose){
    report("Using cdda library version: %s",cdda_version());
    report("Using paranoia library version: %s",paranoia_version());
  }

  /* Query the cdrom/disc; we may need to override some settings */

  if(force_cdrom_device)
    d=cdda_identify(force_cdrom_device,verbose,NULL);
  else {
    driver_id_t driver_id;
    char **ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL,
                                                          CDIO_FS_AUDIO,
                                                          false,
                                                          &driver_id);
    if (ppsz_cd_drives && *ppsz_cd_drives) {
      d=cdda_identify(*ppsz_cd_drives,verbose, NULL);
    } else {
      report("\nUnable find or access a CD-ROM drive with an audio CD"
             " in it.");
      report("\nYou might try specifying the drive, especially if it has"
             " mixed-mode (and non-audio) format tracks");
      exit(1);
    }

    cdio_free_device_list(ppsz_cd_drives);
  }

  if(!d){
    if(!verbose)
      report("\nUnable to open cdrom drive; -v might give more information.");
    exit(1);
  }

  if(verbose)
    cdda_verbose_set(d,CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_PRINTIT);
  else
    cdda_verbose_set(d,CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_FORGETIT);

  /* possibly force hand on endianness of drive, sector request size */
  if(force_cdrom_endian!=-1){
    d->bigendianp=force_cdrom_endian;
    switch(force_cdrom_endian){
    case 0:
      report("Forcing CDROM sense to little-endian; ignoring preset and autosense");
      break;
    case 1:
      report("Forcing CDROM sense to big-endian; ignoring preset and autosense");
      break;
    }
  }
  if (force_cdrom_sectors!=-1) {
    if(force_cdrom_sectors<0 || force_cdrom_sectors>100){
      report("Default sector read size must be 1<= n <= 100\n");
      cdda_close(d);
      d=NULL;
      exit(1);
    }
    report("Forcing default to read %ld sectors; "
	   "ignoring preset and autosense",force_cdrom_sectors);
    d->nsectors=force_cdrom_sectors;
  }
  if (force_cdrom_overlap!=-1) {
    if (force_cdrom_overlap<0 || force_cdrom_overlap>CDIO_CD_FRAMES_PER_SEC) {
      report("Search overlap sectors must be 0<= n <=75\n");
      cdda_close(d);
      d=NULL;
      if(logfile && logfile != stdout)
        fclose(logfile);
      exit(1);
    }
    report("Forcing search overlap to %ld sectors; "
	   "ignoring autosense",force_cdrom_overlap);
  }

  switch( cdda_open(d) ) {
  case -2:case -3:case -4:case -5:
    report("\nUnable to open disc.  Is there an audio CD in the drive?");
    exit(1);
  case -6:
    report("\nCdparanoia could not find a way to read audio from this drive.");
    exit(1);
  case 0:
    break;
  default:
    report("\nUnable to open disc.");
    exit(1);
  }

  d->i_test_flags = test_flags;

  if (force_cdrom_speed == 0) force_cdrom_speed = -1;

  if (force_cdrom_speed != -1) {
    report("\nAttempting to set speed to %ldx... ", force_cdrom_speed);
  } else {
    if (verbose)
      report("\nAttempting to set cdrom to full speed... ");
  }

  if (cdda_speed_set(d, force_cdrom_speed)) {
    if (verbose || force_cdrom_speed != -1)
      report("\tCDROM speed set FAILED. Continuing anyway...");
  } else {
    if (verbose)
      report("\tdrive returned OK.");
  }

  if(run_cache_test){
    int warn=analyze_cache(d, stderr, reportfile, force_cdrom_speed);

    if(warn==0){
      reportC("\nDrive tests OK with Paranoia.\n\n");
      return 0;
    }

    if(warn==1)
      reportC("\nWARNING! PARANOIA MAY NOT BE TRUSTWORTHY WITH THIS DRIVE!\n"
	      "\nThe Paranoia library may not model this CDROM drive's cache"
	      "\ncorrectly according to this analysis run. Analysis is not"
	      "\nalways accurate (it can be fooled by machine load or random"
	      "\nkernel latencies), but if a failed result happens more often"
	      "\nthan one time in twenty on an unloaded machine, please mail"
	      "\nthe %s file produced by this failed analysis to"
	      "\[email protected] to assist developers in extending"
	      "\nParanoia to handle this CDROM properly.\n\n",reportfile_name);
    return 1;
  }


  /* Dump the TOC */
  if (query_only || verbose ) display_toc(d);

  if (query_only) exit(0);

  /* bias the disc.  A hack.  Of course. this is never the default. */
  /*
     Some CD-ROM/CD-R drives will add an offset to the position on
     reading audio data. This is usually around 500-700 audio samples
     (ca. 1/75 second) on reading. So when this program queries a
     specific sector, it might not receive exactly that sector, but
     shifted by some amount.

     Note that if ripping includes the end of the CD, this will this
     cause this program to attempt to read partial sectors before or
     past the known user data area of the disc, probably causing read
     errors on most drives and possibly even hard lockups on some
     buggy hardware.

     [Note to libcdio driver hackers: make sure all CD-drivers don't
     try to read outside of the stated disc boundaries.]
  */
  if(sample_offset){
    toc_offset+=sample_offset/588;
    sample_offset%=588;
    if(sample_offset<0){
      sample_offset+=588;
      toc_offset--;
    }
  }

  if (toc_bias) {
    toc_offset = -cdda_track_firstsector(d,1);
  }

  {
    int i;
    for( i=0; i < d->tracks+1; i++ )
      d->disc_toc[i].dwStartSector+=toc_offset;
  }

  if (d->nsectors==1) {
    report("WARNING: The autosensed/selected sectors per read value is\n"
           "         one sector, making it very unlikely Paranoia can \n"
           "         work.\n\n"
           "         Attempting to continue...\n\n");
  }

  /* parse the span, set up begin and end sectors */

  {
    long i_first_lsn;
    long i_last_lsn;
    long batch_first;
    long batch_last;
    int batch_track;

    if (span) {
      /* look for the hyphen */
      char *span2=strchr(span,'-');
      if(strrchr(span,'-')!=span2){
        report("Error parsing span argument");
        exit(1);
      }

      if (span2!=NULL) {
        *span2='\0';
        span2++;
      }

      i_first_lsn=parse_offset(d, span, -1);

      if(i_first_lsn==-1)
        i_last_lsn=parse_offset(d, span2, cdda_disc_firstsector(d));

      else
        i_last_lsn=parse_offset(d, span2, i_first_lsn);

      if (i_first_lsn == -1) {
        if (i_last_lsn == -1) {
          report("Error parsing span argument");
          exit(1);
        } else {
          i_first_lsn=cdda_disc_firstsector(d);
        }
      } else {
        if (i_last_lsn==-1) {
          if (span2) { /* There was a hyphen */
            i_last_lsn=cdda_disc_lastsector(d);
          } else {
            i_last_lsn=
              cdda_track_lastsector(d,cdda_sector_gettrack(d, i_first_lsn));
          }
        }
      }
    } else {
      i_first_lsn = cdda_disc_firstsector(d);
      i_last_lsn  = cdda_disc_lastsector(d);
    }

    {
      int track1 = cdda_sector_gettrack(d, i_first_lsn);

      int track2 = cdda_sector_gettrack(d, i_last_lsn);
      long off1  = i_first_lsn - cdda_track_firstsector(d, track1);
      long off2  = i_last_lsn  - cdda_track_firstsector(d, track2);
      int i;

      for( i=track1; i<=track2; i++ ) {
        if(i != 0 && !cdda_track_audiop(d,i)){
	  report("Selected span contains non audio track at track %02d.  Aborting.\n\n", i);
          exit(1);
          if (i == 0)
            i = cdio_get_first_track_num(d->p_cdio) - 1;
        }
      }

      report("Ripping from sector %7ld (track %2d [%d:%02d.%02d])\n"
	     "\t  to sector %7ld (track %2d [%d:%02d.%02d])\n",
	     i_first_lsn,
	     track1,
	     (int) (off1/(CDIO_CD_FRAMES_PER_MIN)),
	     (int) ((off1/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
	     (int)(off1 % CDIO_CD_FRAMES_PER_SEC),
	     i_last_lsn,
	     track2,
	     (int) (off2/(CDIO_CD_FRAMES_PER_MIN)),
	     (int) ((off2/CDIO_CD_FRAMES_PER_SEC) % CDIO_CD_SECS_PER_MIN),
	     (int)(off2 % CDIO_CD_FRAMES_PER_SEC));

    }

    if (toc_offset && !force_overread) {
	d->disc_toc[d->tracks].dwStartSector -= toc_offset;
	if (i_last_lsn > cdda_track_lastsector(d, d->tracks))
		i_last_lsn -= toc_offset;
    }
    {
      long cursor;
      int16_t offset_buffer[1176];
      int offset_buffer_used=0;
      int offset_skip=sample_offset*4;
      off_t sectorlen;

#if defined(HAVE_GETUID) && (defined(HAVE_SETEUID) || defined(HAVE_SETEGID))
      int dummy __attribute__((unused));
#endif
      p=paranoia_init(d);
      paranoia_modeset(p,paranoia_mode);
      if(force_cdrom_overlap!=-1)paranoia_overlapset(p,force_cdrom_overlap);

      if(verbose) {
        cdda_verbose_set(d,CDDA_MESSAGE_LOGIT,CDDA_MESSAGE_LOGIT);
        cdio_loglevel_default = CDIO_LOG_INFO;
      } else
        cdda_verbose_set(d,CDDA_MESSAGE_FORGETIT,CDDA_MESSAGE_FORGETIT);

      paranoia_seek(p,cursor=i_first_lsn,SEEK_SET);

      /* this is probably a good idea in general */
#if defined(HAVE_GETUID) && defined(HAVE_SETEUID)
      dummy = seteuid(getuid());
#endif
#if defined(HAVE_GETGID) && defined(HAVE_SETEGID)
      dummy = setegid(getgid());
#endif

      /* we'll need to be able to read one sector past user data if we
         have a sample offset in order to pick up the last bytes.  We
         need to set the disc length forward here so that the libs are
         willing to read past, assuming that works on the hardware, of
         course */
      if(sample_offset && force_overread)
        d->disc_toc[d->tracks].dwStartSector++;

      while(cursor<=i_last_lsn){
        char outfile_name[PATH_MAX];
        if ( batch ){
          batch_first = cursor;
          batch_track = cdda_sector_gettrack(d,cursor);
          batch_last  = cdda_track_lastsector(d, batch_track);
          if (batch_last>i_last_lsn) batch_last=i_last_lsn;
        } else {
          batch_first = i_first_lsn;
          batch_last  = i_last_lsn;
          batch_track = -1;
        }

        callbegin=batch_first;
        callend=batch_last;

        /* argv[optind] is the span, argv[optind+1] (if exists) is outfile */

        if (optind+1<argc) {
          if (!strcmp(argv[optind+1],"-") ){
            out = dup(fileno(stdout));
            if(out==-1){
              report("Cannot dupplicate stdout: %s",
                     strerror(errno));
              exit(1);
            }
            if(batch)
              report("Are you sure you wanted 'batch' "
                     "(-B) output with stdout?");
            report("outputting to stdout\n");
            if(logfile){
              fprintf(logfile,"outputting to stdout\n");
              fflush(logfile);
            }
            outfile_name[0]='\0';
          } else {
            char dirname[PATH_MAX];
            char *basename=split_base_dir(argv[optind+1], dirname,
					  PATH_MAX);

	    if (NULL == basename) {
	      report("Output filename too long");
	      exit(1);
	    }

            if(batch) {
	      if (strlen(argv[optind+1]) - 10 > PATH_MAX) {
		report("Output filename too long");
		exit(1);
	      }
              snprintf(outfile_name, PATH_MAX,
		       " %strack%02d.%s", dirname,
                       batch_track, basename);
            } else
              snprintf(outfile_name, PATH_MAX, "%s%s", dirname, basename);

            if(basename[0]=='\0'){
              switch (output_type) {
              case 0: /* raw */
                strncat(outfile_name, "cdda.raw", sizeof("cdda.raw"));
                break;
              case 1:
                strncat(outfile_name, "cdda.wav", sizeof("cdda.wav"));
                break;
              case 2:
                strncat(outfile_name, "cdda.aifc", sizeof("cdda.aifc"));
                break;
              case 3:
                strncat(outfile_name, "cdda.aiff", sizeof("cdda.aiff"));
                break;
              }
            }

            out=open(outfile_name,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,0666);
            if(out==-1){
              report("Cannot open specified output file %s: %s",
                      outfile_name, strerror(errno));
              exit(1);
            }
            report("outputting to %s\n", outfile_name);
            if(logfile){
              fprintf(logfile,"outputting to %s\n",outfile_name);
              fflush(logfile);
            }
          }
        } else {
          /* default */
          if (batch)
            sprintf(outfile_name,"track%02d.", batch_track);
          else
            outfile_name[0]='\0';

          switch(output_type){
          case 0: /* raw */
            strncat(outfile_name, "cdda.raw", sizeof("cdda.raw"));
            break;
          case 1:
            strncat(outfile_name, "cdda.wav", sizeof("cdda.wav"));
            break;
          case 2:
            strncat(outfile_name, "cdda.aifc", sizeof("cdda.aifc"));
            break;
          case 3:
            strncat(outfile_name, "cdda.aiff", sizeof("cdda.aiff"));
            break;
          }

          out = open(outfile_name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666);
          if(out==-1){
            report("Cannot open default output file %s: %s", outfile_name,
                    strerror(errno));
            exit(1);
          }
          report("outputting to %s\n", outfile_name);
          if(logfile){
            fprintf(logfile,"outputting to %s\n",outfile_name);
            fflush(logfile);
          }

        }

	sectorlen = batch_last - batch_first + 1;
	if (cdda_sector_gettrack(d, cursor) == d->tracks &&
		toc_offset > 0 && !force_overread){
		sectorlen += toc_offset;
	}
        switch(output_type) {
        case 0: /* raw */
          break;
        case 1: /* wav */
	  WriteWav(out, sectorlen * CD_FRAMESIZE_RAW);
          break;
        case 2: /* aifc */
	  WriteAifc(out, sectorlen * CD_FRAMESIZE_RAW);
          break;
        case 3: /* aiff */
	  WriteAiff(out, sectorlen * CD_FRAMESIZE_RAW);
          break;
        }

        /* Off we go! */

        if(offset_buffer_used){
          /* partial sector from previous batch read */
          cursor++;
          if (buffering_write(out,
                              ((char *)offset_buffer)+offset_buffer_used,
                              CDIO_CD_FRAMESIZE_RAW-offset_buffer_used)){
            report("Error writing output: %s", strerror(errno));
            exit(1);
          }
        }

        skipped_flag=0;
        while(cursor<=batch_last){
          /* read a sector */
          int16_t *readbuf=paranoia_read_limited(p, callback, max_retries);
          char *err=cdda_errors(d);
          char *mes=cdda_messages(d);

          if(mes || err)
            fprintf(stderr,"\r                               "
                    "                                           \r%s%s\n",
                    mes?mes:"",err?err:"");

          if (err) free(err);
          if (mes) free(mes);
          if( readbuf==NULL) {
	    if(errno==EBADF || errno==ENOMEDIUM){
	      report("\nparanoia_read: CDROM drive unavailable, bailing.\n");
	      exit(1);
	    }
            skipped_flag=1;
            report("\nparanoia_read: Unrecoverable error, bailing.\n");
            break;
          }
          if(skipped_flag && abort_on_skip){
            cursor=batch_last+1;
            break;
          }

          skipped_flag=0;
          cursor++;

          if (output_endian!=bigendianp()) {
            int i;
            for (i=0; i<CDIO_CD_FRAMESIZE_RAW/2; i++)
              readbuf[i]=UINT16_SWAP_LE_BE_C(readbuf[i]);
          }

          callback(cursor*(CD_FRAMEWORDS)-1, PARANOIA_CB_WROTE);

          if (buffering_write(out,((char *)readbuf)+offset_skip,
                             CDIO_CD_FRAMESIZE_RAW-offset_skip)){
            report("Error writing output: %s", strerror(errno));
            exit(1);
          }
          offset_skip=0;

          if (output_endian != bigendianp()){
            int i;
            for (i=0; i<CDIO_CD_FRAMESIZE_RAW/2; i++)
              readbuf[i] = UINT16_SWAP_LE_BE_C(readbuf[i]);
          }

          /* One last bit of silliness to deal with sample offsets */
          if(sample_offset && cursor>batch_last){
	    if (cdda_sector_gettrack(d, batch_last) < d->tracks || force_overread) {
	      int i;

	      /* Need to flush the buffer when overreading into the leadout */
	      if (cdda_sector_gettrack(d, batch_last) == d->tracks)
		paranoia_seek(p, cursor, SEEK_SET);

	      /* read a sector and output the partial offset.  Save the
		 rest for the next batch iteration */
	      readbuf=paranoia_read_limited(p,callback,max_retries);
	      err=cdda_errors(d);mes=cdda_messages(d);

	      if(mes || err)
		fprintf(stderr,"\r                               "
			"                                           \r%s%s\n",
			mes?mes:"",err?err:"");

	      if(err)free(err);if(mes)free(mes);
	      if(readbuf==NULL){
		skipped_flag=1;
		report("\nparanoia_read: Unrecoverable error reading through "
		       "sample_offset shift\n\tat end of track, bailing.\n");
		break;
	      }
	      if (skipped_flag && abort_on_skip) break;
	      skipped_flag=0;
	      /* do not move the cursor */

	      if(output_endian!=bigendianp())
		for(i=0;i<CD_FRAMESIZE_RAW/2;i++)
		  offset_buffer[i]=UINT16_SWAP_LE_BE_C(readbuf[i]);
	      else
		memcpy(offset_buffer,readbuf,CD_FRAMESIZE_RAW);
	      offset_buffer_used=sample_offset*4;
	      callback(cursor* (CD_FRAMEWORDS), PARANOIA_CB_WROTE);
	    } else {
	      memset(offset_buffer, 0, sizeof(offset_buffer));
	      offset_buffer_used = sample_offset * 4;
	    }

	    if(buffering_write(out,(char *)offset_buffer,
			       offset_buffer_used)){
	      report("Error writing output: %s", strerror(errno));
	      exit(1);
	    }
	  }
        }

	/* Write sectors of silent audio to compensate for
	   missing samples that would be in the leadout */
	if (cdda_sector_gettrack(d, batch_last) == d->tracks &&
		toc_offset > 0 && !force_overread)
	{
		char *silence;
		size_t missing_sector_bytes = CD_FRAMESIZE_RAW * toc_offset;

		silence = calloc(toc_offset, CD_FRAMESIZE_RAW);
		if (!silence || buffering_write(out, silence, missing_sector_bytes)) {
		      report("Error writing output: %s", strerror(errno));
		      exit(1);
		}
		free(silence);
	}

        callback(cursor* (CDIO_CD_FRAMESIZE_RAW/2)-1,
		 PARANOIA_CB_FINISHED);
        buffering_close(out);
        if(skipped_flag){
          /* remove the file */
          report("\nRemoving aborted file: %s", outfile_name);
          unlink(outfile_name);
          /* make the cursor correct if we have another track */
          if(batch_track!=-1){
            batch_track++;
            cursor=cdda_track_firstsector(d,batch_track);
            paranoia_seek(p,cursor, SEEK_SET);
            offset_skip=sample_offset*4;
            offset_buffer_used=0;
          }
        }
        report("\n");
      }

      paranoia_free(p);
      p=NULL;
    }
  }

  report("Done.\n\n");

  return 0;
}
static int
CDDAReader_first_track_num_image(cdio_CDDAReader *self)
{
    return cdio_get_first_track_num(self->_.image.image);
}
示例#28
0
文件: cdda.c 项目: vadmium/deadbeef
static DB_playItem_t *
cda_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
    trace ("CDA insert: %s\n", fname);
    CdIo_t* cdio = NULL;
    int track_nr;
    DB_playItem_t *res;

    const char* shortname = strrchr (fname, '/');
    if (shortname) {
        shortname++;
    }
    else {
        shortname = fname;
    }
    const char *ext = strrchr (shortname, '.') + 1;
    int is_image = ext && (0 == strcmp (ext, "nrg"));
    if (is_image && !deadbeef->conf_get_int ("cdda.enable_nrg", 0)) {
        return NULL;
    }

    if (0 == strcmp (ext, "cda")) {
        cdio = cdio_open (NULL, DRIVER_UNKNOWN);
    }
    else if (is_image) {
        cdio = cdio_open (fname, DRIVER_NRG);
    }

    if (!cdio) {
        trace ("not an audio disc/image, or file not found (%s)\n", fname);
        return NULL;
    }


    // calculate discid
    track_t first_track = cdio_get_first_track_num (cdio);
    if (first_track == 0xff) {
        trace ("cdda: no medium found\n");
        cdio_destroy (cdio);
        return NULL;
    }
    track_t tracks = cdio_get_num_tracks (cdio);
    track_t i;
    cddb_track_t *track;

    cddb_disc_t *disc = cddb_disc_new();

    cddb_disc_set_length (disc, cdio_get_track_lba (cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC);

    for (i = 0; i < tracks; i++)
    {
        lsn_t offset = cdio_get_track_lba (cdio, i+first_track);
        track = cddb_track_new();
        cddb_track_set_frame_offset (track, offset);
        cddb_disc_add_track (disc, track);
    }
    cddb_disc_calc_discid (disc);
    int discid = cddb_disc_get_discid (disc);

    if (0 == strcasecmp (shortname, "all.cda") || is_image)
    {
        track_t i;
        res = after;
        struct cddb_thread_params *p = malloc (sizeof (struct cddb_thread_params));
        memset (p, 0, sizeof (struct cddb_thread_params));
        p->cdio = cdio;

        int enable_cddb = deadbeef->conf_get_int ("cdda.freedb.enable", DEFAULT_USE_CDDB);

        for (i = 0; i < tracks; i++)
        {
            trace ("inserting track %d\n", i);
            res = insert_single_track (cdio, plt, res, is_image ? fname : NULL, i+first_track, discid);
            if (res) {
                p->items[i] = res;
            }
        }

        int got_cdtext = read_disc_cdtext (p);
        int prefer_cdtext = deadbeef->conf_get_int ("cdda.prefer_cdtext", DEFAULT_PREFER_CDTEXT);

        if ((!got_cdtext || !prefer_cdtext) && enable_cddb)
        {
            trace ("cdda: querying freedb...\n");
            intptr_t tid = deadbeef->thread_start (cddb_thread, p); //will destroy cdio
            deadbeef->thread_detach (tid);
        }
        else
            cleanup_thread_params (p);
    }
    else
    {
        track_nr = atoi (shortname);
        res = insert_single_track (cdio, plt, after, NULL, track_nr, discid);
        if (res) {
            read_track_cdtext (cdio, track_nr, res);
            deadbeef->pl_item_unref (res);
        }
        cdio_destroy (cdio);
    }
    cddb_disc_destroy (disc);
    return res;
}
示例#29
0
文件: cdda.c 项目: vadmium/deadbeef
static int
cda_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
    cdda_info_t *info = (cdda_info_t *)_info;

    trace ("cdda: init %s\n", deadbeef->pl_find_meta (it, ":URI"));

    size_t l = strlen (deadbeef->pl_find_meta (it, ":URI"));
    char location[l+1];
    memcpy (location, deadbeef->pl_find_meta (it, ":URI"), l+1);

    char *nr = strchr (location, '#');
    if (nr) {
        *nr = 0; nr++;
    }
    else {
        trace ("cdda: bad name: %s\n", deadbeef->pl_find_meta (it, ":URI"));
        return -1;
    }
    int track_nr = atoi (nr);
    char *fname = (*location) ? location : NULL; //NULL if empty string; means pysical CD drive

    info->cdio = cdio_open (fname, DRIVER_UNKNOWN);
    if  (!info->cdio)
    {
        trace ("cdda: Could not open CD\n");
        return -1;
    }

    track_t first_track = cdio_get_first_track_num (info->cdio);
    if (first_track == 0xff) {
        trace ("cdda: no medium found\n");
        return -1;
    }
    track_t tracks = cdio_get_num_tracks (info->cdio);
    track_t i;
    cddb_track_t *track;

    cddb_disc_t *disc = cddb_disc_new();

    cddb_disc_set_length (disc, cdio_get_track_lba (info->cdio, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC);

    for (i = 0; i < tracks; i++)
    {
        lsn_t offset = cdio_get_track_lba (info->cdio, i+first_track);
        track = cddb_track_new();
        cddb_track_set_frame_offset (track, offset);
        cddb_disc_add_track (disc, track);
    }
    cddb_disc_calc_discid (disc);
    int discid = cddb_disc_get_discid (disc);

    int trk_discid = deadbeef->pl_find_meta_int (it, ":CDIO_DISCID", 0);
    if (trk_discid != discid) {
        cddb_disc_destroy (disc);
        trace ("cdda: the track belongs to another disc, skipped\n");
        return -1;
    }
    cddb_disc_destroy (disc);


    if (TRACK_FORMAT_AUDIO != cdio_get_track_format (info->cdio, track_nr))
    {
        trace ("cdda: Not an audio track (%d)\n", track_nr);
        return -1;
    }

    int channels = cdio_get_track_channels (info->cdio, track_nr);
    trace ("cdio nchannels: %d\n", channels);

    _info->plugin = &plugin;
    _info->fmt.bps = 16;
    _info->fmt.channels = 2;
    _info->fmt.samplerate = 44100;
    _info->fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT;
    _info->readpos = 0;

    info->first_sector = cdio_get_track_lsn (info->cdio, track_nr);
    info->sector_count = cdio_get_track_sec_count (info->cdio, track_nr);
    info->current_sector = info->first_sector;
    info->tail_len = 0;
    info->current_sample = 0;
    return 0;
}
示例#30
0
static void get_track_info(ripncode_t *r)
{
    rip_track_t *t;
    int          i, base;
    char         file[1024], *msg;
    int16_t     *samples;
    int          fd, n, l, total;

    base      = cdio_get_first_track_num(r->cdio);
    r->ntrack = cdio_get_num_tracks(r->cdio);
    r->tracks = mrp_allocz_array(rip_track_t, r->ntrack);

    if (r->tracks == NULL && r->ntrack > 0)
        ripncode_fatal(r, "failed to allocate track info");

    cdio_paranoia_modeset(r->cdpa, PARANOIA_MODE_FULL);

    for (i = 0, t = r->tracks; i < r->ntrack; i++, t++) {
        if (i >= r->last)
            break;
        t->id      = base + i;
        t->format  = cdio_get_track_format(r->cdio, base + i);
        t->lsn_beg = cdio_get_track_lsn(r->cdio, base + i);
        t->lsn_end = cdio_get_track_last_lsn(r->cdio, base + i);
        t->lba     = cdio_get_track_lba(r->cdio, base + i);

        printf("track #%d (id %d): lsn: %u - %u (lba %u), format: %s\n",
               i, base + i, t->lsn_beg, t->lsn_end, t->lba,
               track_format_name(t->format));

        if (r->dryrun)
            continue;

        snprintf(file, sizeof(file), "track-%d.raw", i);
        if ((fd = open(file, O_WRONLY|O_CREAT, 0644)) < 0)
            ripncode_fatal(r, "failed to open '%s' (%d: %s)", file,
                           errno, strerror(errno));

        cdio_paranoia_seek(r->cdpa, t->lsn_beg * CDIO_CD_FRAMESIZE_RAW,
                           SEEK_SET);

        total = t->lsn_end - t->lsn_beg + 1;
        for (l = 0; l <= total; l++) {
            printf("\rreading track sector %d/%d (#%d)...", l, total,
                   t->lsn_beg + l);
            fflush(stdout);

            samples = cdio_paranoia_read(r->cdpa, read_status);

            if (samples == NULL) {
                msg = cdio_cddap_errors(r->cdda);
                ripncode_fatal(r, "failed to seek to LSN %d (%s)", t->lsn_beg,
                               msg ? msg : "unknown error");
            }

            n = write(fd, samples, CDIO_CD_FRAMESIZE_RAW);

            if (n < 0)
                ripncode_fatal(r, "failed to write sector data (%d: %s)",
                               errno, strerror(errno));
        }

        close(fd);
    }
}