Esempio n. 1
0
/*!
  Read a data sector
  
  @param p_cdio object to read from

  @param p_buf place to read data into.  The caller should make sure
  this location can store at least ISO_BLOCKSIZE, M2RAW_SECTOR_SIZE,
  or M2F2_SECTOR_SIZE depending on the kind of sector getting read. If
  you don't know whether you have a Mode 1/2, Form 1/ Form 2/Formless
  sector best to reserve space for the maximum, M2RAW_SECTOR_SIZE.

  @param i_lsn sector to read

  @param i_blocksize size of block. Should be either ISO_BLOCKSIZE
  M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under
  p_buf.
  */
driver_return_code_t 
read_data_sectors_image ( void *p_user_data, void *p_buf, 
			  lsn_t i_lsn,  uint16_t i_blocksize,
			  uint32_t i_blocks )
{
  const _img_private_t *p_env = p_user_data;

  if (!p_env || !p_env->gen.cdio) return DRIVER_OP_UNINIT;
  
  {
    CdIo_t *p_cdio                = p_env->gen.cdio;
    track_t i_track               = cdio_get_track(p_cdio, i_lsn);
    track_format_t e_track_format = cdio_get_track_format(p_cdio, i_track);

    switch(e_track_format) {
    case TRACK_FORMAT_PSX:
    case TRACK_FORMAT_AUDIO:
    case TRACK_FORMAT_ERROR:
      return DRIVER_OP_ERROR;
    case TRACK_FORMAT_DATA:
      return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
    case TRACK_FORMAT_CDI:
    case TRACK_FORMAT_XA:
      return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
    }
  }
  return DRIVER_OP_ERROR;
}
Esempio n. 2
0
static DB_playItem_t *
insert_single_track (CdIo_t* cdio, ddb_playlist_t *plt, DB_playItem_t *after, const char* file, int track_nr, int discid)
{
    char tmp[file ? strlen (file) + 20 : 20];
    if (file)
        snprintf (tmp, sizeof (tmp), "%s#%d.cda", file, track_nr);
    else
        snprintf (tmp, sizeof (tmp), "#%d.cda", track_nr);

    if (TRACK_FORMAT_AUDIO != cdio_get_track_format (cdio, track_nr))
    {
        trace ("Not an audio track (%d)\n", track_nr);
        return NULL;
    }

    int sector_count = cdio_get_track_sec_count (cdio, track_nr);

    DB_playItem_t *it = deadbeef->pl_item_alloc_init (tmp, plugin.plugin.id);
    deadbeef->pl_add_meta (it, ":FILETYPE", "cdda");
    deadbeef->plt_set_item_duration (plt, it, (float)sector_count / 75.0);

    snprintf (tmp, sizeof (tmp), "CD Track %02d", track_nr);
    deadbeef->pl_add_meta (it, "title", tmp);
    snprintf (tmp, sizeof (tmp), "%02d", track_nr);
    deadbeef->pl_add_meta (it, "track", tmp);

    deadbeef->pl_set_meta_int (it, ":CDIO_DISCID", discid);

    after = deadbeef->plt_insert_item (plt, after, it);

    return after;
}
Esempio n. 3
0
static PyObject*
CDImage_track_type(cdio_CDImage* self, PyObject *args) {
    int tracknum;

    if (!PyArg_ParseTuple(args, "i", &tracknum))
        return NULL;

        return Py_BuildValue("i",
                             cdio_get_track_format(self->image,
                                                   (track_t)tracknum));
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
static PyObject*
CDDA_track_type(cdio_CDDAObject* self, PyObject *args)
{
    int tracknum;

    if (!PyArg_ParseTuple(args, "i", &tracknum))
        return NULL;

    return Py_BuildValue("i",
                         cdio_get_track_format(self->cdrom_drive->p_cdio,
                                               (track_t)tracknum));
}
Esempio n. 6
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);
  }
}
Esempio n. 7
0
/*!
  Read the Primary Volume Descriptor for of CD.
*/
bool 
iso9660_fs_read_pvd(const CdIo_t *p_cdio, /*out*/ iso9660_pvd_t *p_pvd)
{
  /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/
  bool b_mode2;
  char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
  int i_rc;

  switch(cdio_get_track_format(p_cdio, 1)) {
  case TRACK_FORMAT_CDI:
  case TRACK_FORMAT_XA:
    b_mode2 = true;
    break;
  case TRACK_FORMAT_DATA:
    b_mode2 = false;
    break;
  case TRACK_FORMAT_AUDIO: 
  case TRACK_FORMAT_PSX: 
  case TRACK_FORMAT_ERROR: 
  default:
    return false;
  }
  
  i_rc = b_mode2 
      ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR, false)
      : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR, false);
  
  if (i_rc) {
    cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR);
    return false;
  }
  
  /* The size of a PVD or SVD is smaller than a sector. So we
     allocated a bigger block above (buf) and now we'll copy just
     the part we need to save.
   */
  cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t));
  memcpy(p_pvd, buf, sizeof(iso9660_pvd_t));
  
  return check_pvd(p_pvd);
}
Esempio n. 8
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;
}
Esempio n. 9
0
QList< Playlist::Entry > AudioCDDemux::getTracks( const QString &_device )
{
	QList< Playlist::Entry > tracks;
	Playlist::Entry entry;
	device = _device;
	cdio_close_tray( device.toLocal8Bit(), NULL );
	if ( ( cdio = cdio_open( device.toLocal8Bit(), DRIVER_UNKNOWN ) ) )
	{
		numTracks = cdio_get_num_tracks( cdio );
		if ( cdio_get_discmode( cdio ) != CDIO_DISC_MODE_ERROR && numTracks > 0 && numTracks != CDIO_INVALID_TRACK )
		{
			cddb_disc_t *cddb_disc = NULL;
			bool cddb_ok = useCDDB;
			for ( trackNo = 1 ; trackNo <= numTracks ; ++trackNo )
			{
				chn = cdio_get_track_channels( cdio, trackNo );
				if ( chn != 2 && chn != 4 )
					continue;

				if ( useCDTEXT )
					readCDText( trackNo );
				isData = cdio_get_track_format( cdio, trackNo ) != TRACK_FORMAT_AUDIO;
				duration = CD_BLOCKSIZE / chn / ( double )srate;
				numSectors = cdio_get_track_last_lsn( cdio, trackNo ) - cdio_get_track_lsn( cdio, trackNo );

				if ( cddb_ok && ( cddb_disc || ( Title.isEmpty() && ( cddb_ok = freedb_query( cddb_disc ) ) ) ) )
					freedb_get_track_info( cddb_disc );

				entry.name = title();
				entry.url = AudioCDName"://" + QString::number( trackNo ) + "?device=" + device;
				entry.length = length();

				tracks += entry;
			}
			cddb_disc_destroy( cddb_disc );
		}
	}
	return tracks;
}
Esempio n. 10
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;
}
Esempio n. 11
0
bool AudioCDDemux::open( const QString &_url )
{
#ifdef Q_OS_WIN
	if ( _url.toLower().contains( QRegExp( "file://\\D:/track\\d\\d.cda" ) ) )
	{
		QString url = _url;
		url.remove( "file://" );
		device = url.mid( 0, url.indexOf( '/' ) );
		trackNo = url.mid( url.toLower().indexOf( "track" ) + 5, 2 ).toUInt();
	}
	else
#endif
	{
		if ( _url.left( 10 ) != "AudioCD://" )
			return false;
		QUrl url( _url.mid( 10 ) );
		device = QUrlQuery( url ).queryItemValue( "device" );
		trackNo = url.path().toUInt();
	}
	if ( trackNo > 0 && trackNo < CDIO_INVALID_TRACK )
	{
		cdio = destroyTimer.getInstance( device, discID );
		if ( cdio || ( cdio = cdio_open( device.toLocal8Bit(), DRIVER_UNKNOWN ) ) )
		{
			cdio_set_speed( cdio, 1 );
			numTracks = cdio_get_num_tracks( cdio );
			if ( cdio_get_discmode( cdio ) != CDIO_DISC_MODE_ERROR && numTracks > 0 && numTracks != CDIO_INVALID_TRACK )
			{
				chn = cdio_get_track_channels( cdio, trackNo );
				if ( numTracks >= trackNo && ( chn == 2 || chn == 4 ) )
				{
					if ( useCDTEXT )
					{
						readCDText( 0 );
						readCDText( trackNo );
					}
					isData = cdio_get_track_format( cdio, trackNo ) != TRACK_FORMAT_AUDIO;
					duration = CD_BLOCKSIZE / chn / ( double )srate;
					startSector = cdio_get_track_lsn( cdio, trackNo );
					numSectors = cdio_get_track_last_lsn( cdio, trackNo ) - startSector;

					if ( useCDDB && Title.isEmpty() )
					{
						cddb_disc_t *cddb_disc;
						if ( freedb_query( cddb_disc ) )
						{
							if ( cdTitle.isEmpty() && cdArtist.isEmpty() )
								freedb_get_disc_info( cddb_disc );
							freedb_get_track_info( cddb_disc );
							cddb_disc_destroy( cddb_disc );
						}
					}

					StreamInfo *streamInfo = new StreamInfo;
					streamInfo->type = QMPLAY2_TYPE_AUDIO;
					streamInfo->is_default = true;
					streamInfo->sample_rate = srate;
					streamInfo->channels = chn;
					streams_info += streamInfo;

					return true;
				}
				else
					QMPlay2Core.log( tr( "Błąd odczytu ścieżki" ) );
			}
			else
				QMPlay2Core.log( tr( "Brak płyty w napędzie" ) );
		}
		else
			QMPlay2Core.log( tr( "Nieprawidłowa ścieżka do napędu CD" ) );
	}
	else //dodawanie do listy ścieżek AudioCD
	{
#ifndef Q_OS_WIN
		device = QUrl( _url ).path();
#else
		device = _url.mid( strlen( AudioCDName"://" ), 2 );
#endif
#ifndef Q_OS_WIN
		if ( !QFileInfo( device ).isDir() )
#endif
			if ( !device.isEmpty() )
			{
				emit QMPlay2Core.processParam( "DelPlaylistEntries", _url );
				QList< Playlist::Entry > entries = getTracks( device );
				if ( !entries.isEmpty() && Playlist::write( entries, "file://" + AudioCDPlaylist ) )
				{
					emit QMPlay2Core.processParam( "open", AudioCDPlaylist );
					return true;
				}
			}
	}
	return false;
}
Esempio n. 12
0
/*
   Try to determine what kind of CD-image and/or filesystem we
   have at track i_track. Return information about the CD image
   is returned in cdio_analysis and the return value.
*/
cdio_fs_anal_t
cdio_guess_cd_type(const CdIo_t *p_cdio, int start_session, track_t i_track,
		   /*out*/ cdio_iso_analysis_t *iso_analysis)
{
  int ret = CDIO_FS_UNKNOWN;
  bool sector0_read_ok;

  if (TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i_track))
    return CDIO_FS_AUDIO;

  if ( DRIVER_OP_SUCCESS !=
       _cdio_read_block(p_cdio, ISO_PVD_SECTOR, start_session, 0, i_track) )
    return CDIO_FS_UNKNOWN;

  if ( _cdio_is_it(INDEX_XISO) )
    return CDIO_FS_ANAL_XISO;

  if ( DRIVER_OP_SUCCESS != _cdio_read_block(p_cdio, ISO_SUPERBLOCK_SECTOR,
					     start_session, 0, i_track) )
    return ret;

  if ( _cdio_is_it(INDEX_UDF) ) {
    /* Detect UDF version
       Test if we have a valid version of UDF the xbox can read natively */
    if (_cdio_read_block(p_cdio, 35, start_session, 5, i_track) < 0)
      return CDIO_FS_UNKNOWN;

     iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240];
     iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241];
     /*	Read disc label */
     if (_cdio_read_block(p_cdio, 32, start_session, 5, i_track) < 0)
       return CDIO_FS_UDF;

     strncpy(iso_analysis->iso_label, buffer[5]+25, 33);
     iso_analysis->iso_label[32] = '\0';
     return CDIO_FS_UDF;
   }

  /* We have something that smells of a filesystem. */
  if (_cdio_is_it(INDEX_CD_I) && _cdio_is_it(INDEX_CD_RTOS)
      && !_cdio_is_it(INDEX_BRIDGE) && !_cdio_is_it(INDEX_XA)) {
    return (CDIO_FS_INTERACTIVE | CDIO_FS_ANAL_ISO9660_ANY);
  } else {
    /* read sector 0 ONLY, when NO greenbook CD-I !!!! */

    sector0_read_ok =
      _cdio_read_block(p_cdio, 0, start_session, 1, i_track) == 0;

    if (_cdio_is_it(INDEX_HS))
      ret |= CDIO_FS_HIGH_SIERRA;
    else if (_cdio_is_it(INDEX_ISOFS)) {
      if (_cdio_is_it(INDEX_CD_RTOS) && _cdio_is_it(INDEX_BRIDGE))
	ret = (CDIO_FS_ISO_9660_INTERACTIVE | CDIO_FS_ANAL_ISO9660_ANY);
      else if (_cdio_is_hfs())
	ret = CDIO_FS_ISO_HFS;
      else
	ret = (CDIO_FS_ISO_9660 | CDIO_FS_ANAL_ISO9660_ANY);
      iso_analysis->isofs_size = _cdio_get_iso9660_fs_sec_count();
      strncpy(iso_analysis->iso_label, buffer[0]+40,33);
      iso_analysis->iso_label[32] = '\0';

      if ( _cdio_read_block(p_cdio, UDF_ANCHOR_SECTOR, start_session, 5,
			    i_track) < 0)
	return ret;

      /* Maybe there is an UDF anchor in IOS session
	 so its ISO/UDF session and we prefere UDF */
      if ( _cdio_is_UDF() ) {
	/* Detect UDF version.
	   Test if we have a valid version of UDF the xbox can read natively */
	if ( _cdio_read_block(p_cdio, 35, start_session, 5, i_track) < 0)
	  return ret;

	  iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240];
	  iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241];
#if 0
	  /*  We are using ISO/UDF cd's as iso,
	      no need to get UDF disc label */
	  if (_cdio_read_block(p_cdio, 32, start_session, 5, i_track) < 0)
	    return ret;
	  stnrcpy(iso_analysis->iso_label, buffer[5]+25, 33);
	  iso_analysis->iso_label[32] = '\0';
#endif
	  ret=CDIO_FS_ISO_UDF;
	}

#if 0
      if (_cdio_is_rockridge())
	ret |= CDIO_FS_ANAL_ROCKRIDGE;
#endif

      if (_cdio_read_block(p_cdio, BOOT_SECTOR, start_session, 3, i_track) < 0)
	return ret;

      if (_cdio_is_joliet()) {
	iso_analysis->joliet_level = _cdio_get_joliet_level();
	ret |= (CDIO_FS_ANAL_JOLIET | CDIO_FS_ANAL_ISO9660_ANY);
      }
      if (_cdio_is_it(INDEX_BOOTABLE))
	ret |= CDIO_FS_ANAL_BOOTABLE;

      if ( _cdio_is_it(INDEX_XA) && _cdio_is_it(INDEX_ISOFS)
	  && !(sector0_read_ok && _cdio_is_it(INDEX_PHOTO_CD)) ) {

        if ( _cdio_read_block(p_cdio, VCD_INFO_SECTOR, start_session, 4,
			     i_track) < 0 )
	  return ret;

	if (_cdio_is_it(INDEX_BRIDGE) && _cdio_is_it(INDEX_CD_RTOS)) {
	  ret |= CDIO_FS_ANAL_ISO9660_ANY;
	  if (_cdio_is_it(INDEX_VIDEO_CD))  ret |= CDIO_FS_ANAL_VIDEOCD;
	  else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_SVCD;
	} else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_CVD;

      }
    }
    else if (_cdio_is_hfs())          ret |= CDIO_FS_HFS;
    else if (sector0_read_ok && _cdio_is_it(INDEX_EXT2))
      ret |= (CDIO_FS_EXT2 | CDIO_FS_ANAL_ISO9660_ANY);
    else if (_cdio_is_3do())          ret |= CDIO_FS_3DO;
    else {
      if ( _cdio_read_block(p_cdio, UFS_SUPERBLOCK_SECTOR, start_session, 2,
			    i_track) < 0 )
	return ret;

      if (sector0_read_ok && _cdio_is_it(INDEX_UFS))
	ret |= CDIO_FS_UFS;
      else
	ret |= CDIO_FS_UNKNOWN;
    }
  }

  /* other checks */
  if (_cdio_is_it(INDEX_XA))
    ret |= (CDIO_FS_ANAL_XA | CDIO_FS_ANAL_ISO9660_ANY);
  if (_cdio_is_it(INDEX_PHOTO_CD))
    ret |= (CDIO_FS_ANAL_PHOTO_CD | CDIO_FS_ANAL_ISO9660_ANY);
  if (_cdio_is_it(INDEX_CDTV))
    ret |= CDIO_FS_ANAL_CDTV;
  return ret;
}
Esempio n. 13
0
/*! Here we fix up a couple of things that will never happen.  yeah,
   right.  

   The multisession stuff is from Hannu code; it assumes it knows the
   leadout/leadin size.  [I think Hannu refers to Hannu Savolainen
   from GNU/Linux Kernel code.]

   @return -1 if we can't get multisession info, 0 if there is one
   session only or the last session LBA is the same as the first audio
   track and 1 if the multi-session lba is higher than first audio track
*/
int 
FixupTOC(cdrom_drive_t *d, track_t i_tracks)
{
  int j;
  
  /* First off, make sure the 'starting sector' is >=0 */
  
  for( j=0; j<i_tracks; j++){
    if (d->disc_toc[j].dwStartSector<0 ) {
      cdmessage(d,"\n\tTOC entry claims a negative start offset: massaging"
		".\n");
      d->disc_toc[j].dwStartSector=0;
    }
    if( j<i_tracks-1 && d->disc_toc[j].dwStartSector>
       d->disc_toc[j+1].dwStartSector ) {
      cdmessage(d,"\n\tTOC entry claims an overly large start offset: massaging"
		".\n");
      d->disc_toc[j].dwStartSector=0;
    }

  }
  /* Make sure the listed 'starting sectors' are actually increasing.
     Flag things that are blatant/stupid/wrong */
  {
    lsn_t last=d->disc_toc[0].dwStartSector;
    for ( j=1; j<i_tracks; j++){
      if ( d->disc_toc[j].dwStartSector<last ) {
	cdmessage(d,"\n\tTOC entries claim non-increasing offsets: massaging"
		  ".\n");
	 d->disc_toc[j].dwStartSector=last;
	
      }
      last=d->disc_toc[j].dwStartSector;
    }
  }

  d->audio_last_sector = CDIO_INVALID_LSN;
  
  {
    lsn_t last_ses_lsn;
    if (cdio_get_last_session (d->p_cdio, &last_ses_lsn) < 0)
      return -1;
    
    /* A Red Book Disc must have only one session, otherwise this is a 
     * CD Extra */
    if (last_ses_lsn > d->disc_toc[0].dwStartSector) {
      /* CD Extra discs have two session, the first one ending after 
       * the last audio track 
       * Thus the need to fix the length of the the audio data portion to 
       * not cross the lead-out of this session */
      for (j = i_tracks-1; j > 1; j--) {
	if (cdio_get_track_format(d->p_cdio, j+1) != TRACK_FORMAT_AUDIO && 
	    cdio_get_track_format(d->p_cdio, j) == TRACK_FORMAT_AUDIO) {
	  /* First session lead-out is 1:30
	   * Lead-ins are 1:00
	   * Every session's first track have a 0:02 pregap
	   *
	   * That makes a control data section of (90+60+2)*75 sectors in the 
	   * last audio track */
	  const int gap = ((90+60+2) * CDIO_CD_FRAMES_PER_SEC);
	  
	  if ((last_ses_lsn - gap >= d->disc_toc[j-1].dwStartSector) &&
	      (last_ses_lsn - gap < d->disc_toc[j].dwStartSector)) {
	    d->audio_last_sector = last_ses_lsn - gap - 1;
	    break;
	  }
	}
      }
      return 1;
    }
  }
    
  return 0;
}
Esempio n. 14
0
/* 
   Try to determine what kind of CD-image and/or filesystem we
   have at track track_num. Return information about the CD image
   is returned in cdio_analysis and the return value.
*/
cdio_fs_anal_t
cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, 
		   /*out*/ cdio_analysis_t *cdio_analysis)
{
  int ret = 0;
  bool sector0_read_ok;
  
  if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, track_num))
    return CDIO_FS_AUDIO;

  if ( _cdio_read_block(cdio, ISO_PVD_SECTOR, start_session, 
			0, track_num) < 0 )
    return CDIO_FS_UNKNOWN;
  
  /* We have something that smells of a filesystem. */
  if (_cdio_is_it(INDEX_CD_I) && _cdio_is_it(INDEX_CD_RTOS) 
      && !_cdio_is_it(INDEX_BRIDGE) && !_cdio_is_it(INDEX_XA)) {
    return CDIO_FS_INTERACTIVE;
  } else {	
    /* read sector 0 ONLY, when NO greenbook CD-I !!!! */

    sector0_read_ok = 
      _cdio_read_block(cdio, 0, start_session, 1, track_num) == 0;
    
    if (_cdio_is_it(INDEX_HS))
      ret |= CDIO_FS_HIGH_SIERRA;
    else if (_cdio_is_it(INDEX_ISOFS)) {
      if (_cdio_is_it(INDEX_CD_RTOS) && _cdio_is_it(INDEX_BRIDGE))
	ret = CDIO_FS_ISO_9660_INTERACTIVE;
      else if (_cdio_is_hfs())
	ret = CDIO_FS_ISO_HFS;
      else
	ret = CDIO_FS_ISO_9660;
      cdio_analysis->isofs_size = _cdio_get_iso9660_fs_sec_count();
      sprintf(cdio_analysis->iso_label, buffer[0]+40);
      
#if 0
      if (_cdio_is_rockridge())
	ret |= CDIO_FS_ANAL_ROCKRIDGE;
#endif

      if (_cdio_read_block(cdio, BOOT_SECTOR, start_session, 3, track_num) < 0)
	return ret;
      
      if (_cdio_is_joliet()) {
	cdio_analysis->joliet_level = _cdio_get_joliet_level();
	ret |= CDIO_FS_ANAL_JOLIET;
      }
      if (_cdio_is_it(INDEX_BOOTABLE))
	ret |= CDIO_FS_ANAL_BOOTABLE;
      
      if ( _cdio_is_it(INDEX_XA) && _cdio_is_it(INDEX_ISOFS) 
	  && !(sector0_read_ok && _cdio_is_it(INDEX_PHOTO_CD)) ) {

        if ( _cdio_read_block(cdio, VCD_INFO_SECTOR, start_session, 4, 
			     track_num) < 0 )
	  return ret;
	
	if (_cdio_is_it(INDEX_BRIDGE) && _cdio_is_it(INDEX_CD_RTOS)) {
	  if (_cdio_is_it(INDEX_VIDEO_CD))  ret |= CDIO_FS_ANAL_VIDEOCD;
	  else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_SVCD;
	} else if (_cdio_is_it(INDEX_SVCD)) ret |= CDIO_FS_ANAL_CVD;

      }
    } 
    else if (_cdio_is_hfs())          ret |= CDIO_FS_HFS;
    else if (sector0_read_ok && _cdio_is_it(INDEX_EXT2)) ret |= CDIO_FS_EXT2;
    else if (_cdio_is_3do())          ret |= CDIO_FS_3DO;
    else {
      if ( _cdio_read_block(cdio, UFS_SUPERBLOCK_SECTOR, start_session, 2, 
			    track_num) < 0 )
	return ret;
      
      if (sector0_read_ok && _cdio_is_it(INDEX_UFS)) 
	ret |= CDIO_FS_UFS;
      else
	ret |= CDIO_FS_UNKNOWN;
    }
  }
  
  /* other checks */
  if (_cdio_is_it(INDEX_XA))       ret |= CDIO_FS_ANAL_XA;
  if (_cdio_is_it(INDEX_PHOTO_CD)) ret |= CDIO_FS_ANAL_PHOTO_CD;
  if (_cdio_is_it(INDEX_CDTV))     ret |= CDIO_FS_ANAL_CDTV;
  return ret;
}
Esempio n. 15
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);
}
Esempio n. 16
0
static int
cda_init (DB_fileinfo_t *_info, DB_playItem_t *it)
{
    deadbeef->pl_lock();
    const char *uri = deadbeef->pl_find_meta(it, ":URI");
    const char *nr = uri ? strchr(uri, '#') : NULL;
    if (!nr || nr == uri) {
        deadbeef->pl_unlock();
        trace ("cdda: bad name: %s\n", uri);
        return -1;
    }

    trace ("cdda: init %s\n", uri);
    const int track_nr = atoi(nr+1);
    const size_t device_length = nr - uri;
    char device[device_length+1];
    strncpy(device, uri, device_length);
    device[device_length] = '\0';
    deadbeef->pl_unlock();

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

    const int need_bitrate = info->hints & DDB_DECODER_HINT_NEED_BITRATE;
    const int drive_speed = deadbeef->conf_get_int("cdda.drive_speed", 2);
    cdio_set_speed(info->cdio, need_bitrate && drive_speed < 5 ? 1<<drive_speed : -1);

    cddb_disc_t *disc = create_disc(info->cdio);
    if (!disc) {
        return -1;
    }

    const unsigned long discid = cddb_disc_get_discid(disc);
    cddb_disc_destroy(disc);

    deadbeef->pl_lock();
    const char *discid_hex = deadbeef->pl_find_meta(it, CDDB_DISCID_TAG);
    const unsigned long trk_discid = discid_hex ? strtoul(discid_hex, NULL, 16) : 0;
    deadbeef->pl_unlock();
    if (trk_discid != discid) {
        trace ("cdda: the track belongs to another disc (%x vs %x), skipped\n", trk_discid, discid);
        return -1;
    }

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

    info->first_sector = cdio_get_track_lsn(info->cdio, track_nr);
    info->current_sector = info->first_sector;
    info->last_sector = info->first_sector + cdio_get_track_sec_count(info->cdio, track_nr) - 1;
    trace("cdio nchannels (should always be 2 for an audio track): %d\n", cdio_get_track_channels (info->cdio, track_nr));
    if (info->first_sector == CDIO_INVALID_LSN || info->last_sector <= info->first_sector) {
        trace ("cdda: invalid track\n");
        return -1;
    }

#if USE_PARANOIA
    if (cdio_get_driver_id(info->cdio) != DRIVER_NRG) {
        info->cdrom = cdda_identify(device, CDDA_MESSAGE_FORGETIT, NULL);
        if (info->cdrom) {
            cdda_open(info->cdrom);
            info->paranoia = paranoia_init(info->cdrom);
        }
        if (!info->paranoia) {
            trace ("cdda: cannot re-open %s for paranoia\n", device);
            return -1;
        }
        const int no_paranoia = need_bitrate || !deadbeef->conf_get_int("cdda.paranoia", 0);
        if (no_paranoia) {
            paranoia_cachemodel_size(info->paranoia, 100);
        }
        paranoia_modeset(info->paranoia, no_paranoia ? PARANOIA_MODE_DISABLE : PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);
        paranoia_seek(info->paranoia, info->first_sector, SEEK_SET);
    }
#endif
    return 0;
}
Esempio n. 17
0
/*!
  Read the Super block of an ISO 9660 image. This is the 
  Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume 
  Descriptor if (Joliet) extensions are acceptable.
*/
bool 
iso9660_fs_read_superblock (CdIo_t *p_cdio, 
			    iso_extension_mask_t iso_extension_mask)
{
  if (!p_cdio) return false;
  
  {
    generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env;
    iso9660_pvd_t         *p_pvd = &(p_env->pvd);
    iso9660_svd_t         *p_svd = &(p_env->svd);
    char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
    bool                   b_mode2;
    int i_rc;

    /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/
    switch(cdio_get_track_format(p_cdio, 1)) {
    case TRACK_FORMAT_CDI:
    case TRACK_FORMAT_XA:
      b_mode2 = true;
      break;
    case TRACK_FORMAT_DATA:
      b_mode2 = false;
      break;
    case TRACK_FORMAT_AUDIO: 
    case TRACK_FORMAT_PSX: 
    case TRACK_FORMAT_ERROR: 
    default:
      return false;
    }
  
    if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) )
      return false;
    
    p_env->i_joliet_level = 0;
    
    i_rc = (b_mode2)
      ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false)
      : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false);

    if (0 == i_rc) {
      /* The size of a PVD or SVD is smaller than a sector. So we
	 allocated a bigger block above (buf) and now we'll copy just
	 the part we need to save.
      */
      cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t));
      memcpy(p_svd, buf, sizeof(iso9660_svd_t));
  
      if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) {
	if (p_svd->escape_sequences[0] == 0x25 
	    && p_svd->escape_sequences[1] == 0x2f) {
	  switch (p_svd->escape_sequences[2]) {
	  case 0x40:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) 
	      p_env->i_joliet_level = 1;
	    break;
	  case 0x43:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) 
	      p_env->i_joliet_level = 2;
	    break;
	  case 0x45:
	    if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) 
	      p_env->i_joliet_level = 3;
	    break;
	  default:
	    cdio_info("Supplementary Volume Descriptor found, but not Joliet");
	  }
	  if (p_env->i_joliet_level > 0) {
	    cdio_info("Found Extension: Joliet Level %d", 
		      p_env->i_joliet_level);
	  }
	}
      }
    }
  }

  return true;
}
Esempio n. 18
0
//virtual
Metadata *CdDecoder::getMetadata()
{
    QString artist, album, compilation_artist, title, genre;
    int year = 0;
    unsigned long length = 0;
    track_t tracknum = 0;

    if (-1 == m_settracknum)
        tracknum = getFilename().toUInt();
    else
    {
        tracknum = m_settracknum;
        setFilename(QString("%1" CDEXT).arg(tracknum));
    }

    QMutexLocker lock(&getCdioMutex());

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

    const track_t lastTrack = cdio_get_last_track_num(cdio);
    if (CDIO_INVALID_TRACK == lastTrack)
        return NULL;

    if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum))
        return NULL;

    // Assume disc changed if max LSN different
    bool isDiscChanged = false;
    static lsn_t s_totalSectors;
    lsn_t totalSectors = cdio_get_track_lsn(cdio, CDIO_CDROM_LEADOUT_TRACK);
    if (s_totalSectors != totalSectors)
    {
        s_totalSectors = totalSectors;
        isDiscChanged = true;
    }

    // NB cdio_get_track_last_lsn is unreliable for the last audio track
    // of discs with data tracks beyond
    lsn_t end = cdio_get_track_last_lsn(cdio, tracknum);
    if (isDiscChanged)
    {
        const track_t audioTracks = getNumCDAudioTracks();
        s_lastAudioLsn = cdio_get_track_last_lsn(cdio, audioTracks);

        if (audioTracks < lastTrack)
        {
            cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0, NULL);
            if (NULL != dev)
            {
                if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev))
                {
                    // NB this can be S L O W  but is reliable
                    lsn_t end2 = cdio_cddap_track_lastsector(dev,
                        getNumCDAudioTracks());
                    if (CDIO_INVALID_LSN != end2)
                        s_lastAudioLsn = end2;
                }
                cdio_cddap_close_no_free_cdio(dev);
            }
        }
    }

    if (s_lastAudioLsn && s_lastAudioLsn < end)
        end = s_lastAudioLsn;

    const lsn_t start = cdio_get_track_lsn(cdio, tracknum);
    if (CDIO_INVALID_LSN != start && CDIO_INVALID_LSN != end)
    {
        length = ((end - start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) /
            CDIO_CD_FRAMES_PER_SEC;
    }

    bool isCompilation = false;

#define CDTEXT 0 // Disabled - cd-text access on discs without it is S L O W
#if CDTEXT
    static int s_iCdtext;
    if (isDiscChanged)
        s_iCdtext = -1;

    if (s_iCdtext)
    {
        // cdio_get_cdtext can't take >5 seconds on some CD's without cdtext
        if (s_iCdtext < 0)
            LOG(VB_MEDIA, LOG_INFO,
                QString("Getting cdtext for track %1...").arg(tracknum));
        cdtext_t * cdtext = cdio_get_cdtext(m_cdio, tracknum);
        if (NULL != cdtext)
        {
            genre = cdtext_get_const(CDTEXT_GENRE, cdtext);
            artist = cdtext_get_const(CDTEXT_PERFORMER, cdtext);
            title = cdtext_get_const(CDTEXT_TITLE, cdtext);
            const char* isrc = cdtext_get_const(CDTEXT_ISRC, cdtext);
            /* ISRC codes are 12 characters long, in the form CCXXXYYNNNNN
             * CC = country code
             * XXX = registrant e.g. BMG
             * CC = year withou century
             * NNNNN = unique ID
             */
            if (isrc && strlen(isrc) >= 7)
            {
                year = (isrc[5] - '0') * 10 + (isrc[6] - '0');
                year += (year <= 30) ? 2000 : 1900;
            }

            cdtext_destroy(cdtext);

            if (!title.isNull())
            {
                if (s_iCdtext < 0)
                    LOG(VB_MEDIA, LOG_INFO, "Found cdtext track title");
                s_iCdtext = 1;

                // Get disc info
                cdtext = cdio_get_cdtext(cdio, 0);
                if (NULL != cdtext)
                {
                    compilation_artist = cdtext_get_const(
                        CDTEXT_PERFORMER, cdtext);
                    if (!compilation_artist.isEmpty() &&
                            artist != compilation_artist)
                        isCompilation = true;

                    album = cdtext_get_const(CDTEXT_TITLE, cdtext);

                    if (genre.isNull())
                        genre = cdtext_get_const(CDTEXT_GENRE, cdtext);

                    cdtext_destroy(cdtext);
                }
            }
            else
            {
                if (s_iCdtext < 0)
                    LOG(VB_MEDIA, LOG_INFO, "No cdtext title for track");
                s_iCdtext = 0;
            }
        }
        else
        {
            if (s_iCdtext < 0)
                LOG(VB_MEDIA, LOG_INFO, "No cdtext");
            s_iCdtext = 0;
        }
    }

    if (title.isEmpty() || artist.isEmpty() || album.isEmpty())
#endif // CDTEXT
    {
        // CDDB lookup
        Cddb::Toc toc;
        Cddb::Matches r;
        if (Cddb::Query(r, GetToc(cdio, toc)))
        {
            Cddb::Matches::match_t::const_iterator select = r.matches.begin();

            if (r.matches.size() > 1)
            {
                // TODO prompt user to select one
                // In the meantime, select the first non-generic genre
                for (Cddb::Matches::match_t::const_iterator it = select;
                    it != r.matches.end(); ++it)
                {
                    QString g = it->genre.toLower();
                    if (g != "misc" && g != "data")
                    {
                        select = it;
                        break;
                    }
                }
            }

            Cddb::Album info;
            if (Cddb::Read(info, select->genre, select->discID))
            {
                isCompilation = info.isCompilation;
                if (info.genre.toLower() != "misc")
                    genre = info.genre;
                album = info.title;
                compilation_artist = info.artist;
                year = info.year;
                if (info.tracks.size() >= tracknum)
                {
                    const Cddb::Track& track = info.tracks[tracknum - 1];
                    title = track.title;
                    artist = track.artist;
                }

                // Create a temporary local alias for future lookups
                if (r.discID != info.discID)
                    Cddb::Alias(info, r.discID);
            }
        }
    }

    if (compilation_artist.toLower().left(7) == "various")
        compilation_artist = QObject::tr("Various Artists");

    if (artist.isEmpty())
    {
        artist = compilation_artist;
        compilation_artist.clear();
    }

    if (title.isEmpty())
        title = QObject::tr("Track %1").arg(tracknum);

    Metadata *m = new Metadata(getFilename(), artist, compilation_artist,
        album, title, genre, year, tracknum, length);
    if (m)
        m->setCompilation(isCompilation);

    return m;
}
Esempio n. 19
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;
}
Esempio n. 20
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);
}
Esempio n. 21
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;
}
Esempio n. 22
0
void cued_rip_disc(rip_context_t *rip)
{
    cued_rip_prologue(rip);

    if (ripToOneFile) {

        // TODO:  broken for cd-extra;  stop at first data track?  in cued.c?

        if (TRACK_FORMAT_AUDIO != cdio_get_track_format(rip->cdObj, rip->firstTrack)) {
            cdio2_abort("track %02d is not an audio track", rip->firstTrack);
        }

        if (rip->firstTrack > 1) {
            rip->firstSector = cdio_get_track_lsn(rip->cdObj, rip->firstTrack);
            if (CDIO_INVALID_LSN == rip->firstSector) {
                cdio2_abort("failed to get first sector number for track %02d", rip->firstTrack);
            }
        } else {
            rip->firstSector = 0;
        }

        rip->lastSector = cdio_get_track_last_lsn(rip->cdObj, rip->lastTrack); // , rip->discLastTrack);
        if (CDIO_INVALID_LSN == rip->lastSector) {
            cdio2_abort("failed to get last sector number for track %02d", rip->lastTrack);
        }

        rip->channels = cdio2_get_track_channels(rip->cdObj, rip->firstTrack);

        if (ripVerbose) {
            printf("progress: reading sectors from %d to %d\n", rip->firstSector, rip->lastSector);
        }

        rip->currentTrack = 0;
        cued_rip_to_file(rip);

    } else {

        rip_fn_t ripfn;
        track_format_t format;
        track_t track;

        for (track = rip->firstTrack;  track <= rip->lastTrack;  ++track) {

            rip->firstSector = cdio_get_track_lsn(rip->cdObj, track);
            if (CDIO_INVALID_LSN == rip->firstSector) {
                cdio2_abort("failed to get first sector number for track %02d", track);
            }

            format = cdio_get_track_format(rip->cdObj, track);
            switch (format) {

                case TRACK_FORMAT_AUDIO:
                    rip->channels = cdio2_get_track_channels(rip->cdObj, track);

                    // rip first track pregap to track 00 file
                    if (1 == track && rip->firstSector > 0) {

                        lsn_t saveFirstSector = rip->firstSector;

                        if (ripVerbose) {
                            printf("progress: reading track %02d\n", 0);
                        }

                        rip->lastSector = rip->firstSector - 1;
                        rip->firstSector = 0;
                        rip->currentTrack = 0;
                        cued_rip_to_file(rip);

                        if (ripSilentPregap && ripExtract) {
                            if (unlink(rip->fileNameBuffer)) {
                                cdio2_unix_error("unlink", rip->fileNameBuffer, 1);
                            }
                        }

                        rip->firstSector = saveFirstSector;
                    }
                    ripfn = cued_rip_to_file;
                    break;

                case TRACK_FORMAT_DATA:
                    //ripfn = cued_rip_data_track;
                    //break;

                default:
                    cdio_warn("track %02d is not an audio track; skipping track", track);
                    continue;
            }

            rip->lastSector = cdio_get_track_last_lsn(rip->cdObj, track); // , rip->discLastTrack);
            if (CDIO_INVALID_LSN == rip->lastSector) {
                cdio2_abort("failed to get last sector number for track %02d", track);
            } else {
                //cdio_debug("track %02d last sector is %d", track, rip->lastSector);
            }

            if (ripVerbose) {
                printf("progress: reading track %02d\n", track);
            }

            rip->currentTrack = track;
            ripfn(rip);
        }
    }

    cued_rip_epilogue(rip);
}
Esempio n. 23
0
/*!  
  Get the format (audio, mode2, mode1) of track. 
*/
track_format_t getFormat()
{
  return cdio_get_track_format(p_cdio, i_track);
}
Esempio n. 24
0
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;
}
Esempio n. 25
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);
    }
}