static int
CDDAReader_track_last_lsn_image(cdio_CDDAReader *self, int track_num)
{
    const lsn_t lsn = cdio_get_track_last_lsn(self->_.image.image,
                                              (track_t)track_num);
    return (int)lsn;
}
Пример #2
0
void RipCD::ThreadClickedRipButton() {

  temporary_directory_ = Utilities::MakeTempDir() + "/";

  finished_success_ = 0;
  finished_failed_ = 0;
  ui_->progress_bar->setMaximum(NumTracksToRip() * 2 * 100);

  // Set up progress bar
  emit(SignalUpdateProgress());

  for (int i = 1; i <= i_tracks_; i++) {
    if (!checkboxes_.value(i - 1)->isChecked()) {
      continue;
    }
    tracks_to_rip_.append(i);

    QString filename = temporary_directory_ +
                       ParseFileFormatString(ui_->format_filename->text(), i) +
                       ".wav";
    QFile* destination_file = new QFile(filename);
    destination_file->open(QIODevice::WriteOnly);

    lsn_t i_first_lsn = cdio_get_track_lsn(cdio_, i);
    lsn_t i_last_lsn = cdio_get_track_last_lsn(cdio_, i);
    WriteWAVHeader(destination_file,
                   (i_last_lsn - i_first_lsn + 1) * CDIO_CD_FRAMESIZE_RAW);

    QByteArray buffered_input_bytes(CDIO_CD_FRAMESIZE_RAW, '\0');
    for (lsn_t i_cursor = i_first_lsn; i_cursor <= i_last_lsn; i_cursor++) {
      if (cdio_read_audio_sector(cdio_, buffered_input_bytes.data(),
                                 i_cursor) == DRIVER_OP_SUCCESS) {
        destination_file->write(buffered_input_bytes.data(),
                                buffered_input_bytes.size());
      } else {
        qLog(Error) << "CD read error";
        break;
      }
    }
    finished_success_++;
    emit(SignalUpdateProgress());
    TranscoderPreset preset = ui_->format->itemData(ui_->format->currentIndex())
                                  .value<TranscoderPreset>();

    QString outfilename = GetOutputFileName(filename, preset);
    transcoder_->AddJob(filename, preset, outfilename);
  }
  emit(RippingComplete());
}
Пример #3
0
static PyObject*
CDImage_track_offsets(cdio_CDImage* self, PyObject *args) {
    /* track_t tracknum; */
    int tracknum;
    lsn_t first_sector;
    lsn_t last_sector;

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

    first_sector = cdio_get_track_lsn(self->image, (track_t)tracknum);
    last_sector = cdio_get_track_last_lsn(self->image, (track_t)tracknum);

    return Py_BuildValue("(i,i)", (int)first_sector, (int)last_sector);
}
Пример #4
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;
}
Пример #5
0
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;
  }
Пример #6
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;
}
Пример #7
0
/*!  
  Return the ending LSN. CDIO_INVALID_LSN is returned on error.
*/
lsn_t getLastLsn() 
{
  return cdio_get_track_last_lsn(p_cdio, i_track);
}
Пример #8
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);
}
Пример #9
0
static PyObject*
CDImage_last_sector(cdio_CDImage* self, PyObject *args) {
    return Py_BuildValue("i",
                         cdio_get_track_last_lsn(self->image,
                             cdio_get_last_track_num(self->image)));
}
static int
CDDAReader_last_sector_image(cdio_CDDAReader *self)
{
    return cdio_get_track_last_lsn(self->_.image.image,
                                   self->last_track_num(self));
}
static struct input_stream *
input_cdio_open(const char *uri,
		GMutex *mutex, GCond *cond,
		GError **error_r)
{
	struct input_cdio_paranoia *i;

	struct cdio_uri parsed_uri;
	if (!parse_cdio_uri(&parsed_uri, uri, error_r))
		return NULL;

	i = g_new(struct input_cdio_paranoia, 1);
	input_stream_init(&i->base, &input_plugin_cdio_paranoia, uri,
			  mutex, cond);

	/* initialize everything (should be already) */
	i->drv = NULL;
	i->cdio = NULL;
	i->para = NULL;
	i->trackno = parsed_uri.track;
	pcm_buffer_init(&i->conv_buffer);

	/* get list of CD's supporting CD-DA */
	char *device = parsed_uri.device[0] != 0
		? g_strdup(parsed_uri.device)
		: cdio_detect_device();
	if (device == NULL) {
		g_set_error(error_r, cdio_quark(), 0,
			    "Unable find or access a CD-ROM drive with an audio CD in it.");
		input_cdio_close(&i->base);
		return NULL;
	}

	/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in the list. */
	i->cdio = cdio_open(device, DRIVER_UNKNOWN);
	g_free(device);

	i->drv = cdio_cddap_identify_cdio(i->cdio, 1, NULL);

	if ( !i->drv ) {
		g_set_error(error_r, cdio_quark(), 0,
			    "Unable to identify audio CD disc.");
		input_cdio_close(&i->base);
		return NULL;
	}

	cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);

	if ( 0 != cdio_cddap_open(i->drv) ) {
		g_set_error(error_r, cdio_quark(), 0, "Unable to open disc.");
		input_cdio_close(&i->base);
		return NULL;
	}

	i->endian = data_bigendianp(i->drv);
	switch (i->endian) {
	case -1:
		g_debug("cdda: drive returns unknown audio data, assuming Little Endian");
		i->endian = 0;
		break;
	case 0:
		g_debug("cdda: drive returns audio data Little Endian.");
		break;
	case 1:
		g_debug("cdda: drive returns audio data Big Endian.");
		break;
	default:
		g_set_error(error_r, cdio_quark(), 0,
			    "Drive returns unknown data type %d", i->endian);
		input_cdio_close(&i->base);
		return NULL;
	}

	i->lsn_relofs = 0;

	if (i->trackno >= 0) {
		i->lsn_from = cdio_get_track_lsn(i->cdio, i->trackno);
		i->lsn_to = cdio_get_track_last_lsn(i->cdio, i->trackno);
	} else {
		i->lsn_from = 0;
		i->lsn_to = cdio_get_disc_last_lsn(i->cdio);
	}

	i->para = cdio_paranoia_init(i->drv);

	/* Set reading mode for full paranoia, but allow skipping sectors. */
	paranoia_modeset(i->para, PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP);

	/* seek to beginning of the track */
	cdio_paranoia_seek(i->para, i->lsn_from, SEEK_SET);

	i->base.ready = true;
	i->base.seekable = true;
	i->base.size = (i->lsn_to - i->lsn_from + 1) * CDIO_CD_FRAMESIZE_RAW;

	/* hack to make MPD select the "pcm" decoder plugin */
	i->base.mime = g_strdup("audio/x-mpd-cdda-pcm");

	return &i->base;
}
Пример #12
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;
}
Пример #13
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;
}
Пример #14
0
// pure virtual
bool CdDecoder::initialize()
{
    if (m_inited)
        return true;

    m_inited = m_user_stop = m_finish = false;
    m_freq = m_bitrate = 0L;
    m_stat = DecoderEvent::Error;
    m_chan = 0;
    m_seekTime = -1.;

    if (output())
        output()->PauseUntilBuffered();

    QFile* file = dynamic_cast< QFile* >(input()); // From QIODevice*
    if (file)
    {
        setFilename(file->fileName());
        m_tracknum = getFilename().section('.', 0, 0).toUInt();
    }

    QMutexLocker lock(&getCdioMutex());

    m_cdio = openCdio(m_devicename);
    if (!m_cdio)
        return false;

    m_start = cdio_get_track_lsn(m_cdio, m_tracknum);
    m_end = cdio_get_track_last_lsn(m_cdio, m_tracknum);
    if (CDIO_INVALID_LSN  == m_start ||
        CDIO_INVALID_LSN  == m_end)
    {
        LOG(VB_MEDIA, LOG_INFO, "CdDecoder: No tracks on " + m_devicename);
        cdio_destroy(m_cdio), m_cdio = 0;
        return false;
    }

    LOG(VB_MEDIA, LOG_DEBUG, QString("CdDecoder track=%1 lsn start=%2 end=%3")
            .arg(m_tracknum).arg(m_start).arg(m_end));
    m_curpos = m_start;

    m_device = cdio_cddap_identify_cdio(m_cdio, 0, NULL);
    if (NULL == m_device)
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Error: CdDecoder: cdio_cddap_identify(%1) failed")
                .arg(m_devicename));
        cdio_destroy(m_cdio), m_cdio = 0;
        return false;
    }

    cdio_cddap_verbose_set(m_device,
        VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_ANY) ? CDDA_MESSAGE_PRINTIT :
            CDDA_MESSAGE_FORGETIT,
        VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_DEBUG) ? CDDA_MESSAGE_PRINTIT :
            CDDA_MESSAGE_FORGETIT);

    if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device))
    {
        // cdio_get_track_last_lsn is unreliable on discs with data at end
        lsn_t end2 = cdio_cddap_track_lastsector(m_device, m_tracknum);
        if (end2 < m_end)
        {
            LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: trim last lsn from %1 to %2")
                .arg(m_end).arg(end2));
            m_end = end2;
        }

        m_paranoia = cdio_paranoia_init(m_device);
        if (NULL != m_paranoia)
        {
            cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE);
            (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET);
        }
        else
        {
            LOG(VB_GENERAL, LOG_ERR, "Warn: CD reading with paranoia is disabled");
        }
    }
    else
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("Warn: drive '%1' is not cdda capable").
            arg(m_devicename));
    }

    int chnls = cdio_get_track_channels(m_cdio, m_tracknum);
    m_chan = chnls > 0 ? chnls : 2;
    m_freq = kSamplesPerSec;

    if (output())
    {
        const AudioSettings settings(FORMAT_S16, m_chan,
            CODEC_ID_PCM_S16LE, m_freq, false /* AC3/DTS passthru */);
        output()->Reconfigure(settings);
        output()->SetSourceBitrate(m_freq * m_chan * 16);
    }

    // 20ms worth
    m_bks = (m_freq * m_chan * 2) / 50;
    m_bksFrames = m_freq / 50;
    // decode 8 bks worth of samples each time we need more
    m_decodeBytes = m_bks << 3;

    m_output_buf = reinterpret_cast< char* >(
        ::av_malloc(m_decodeBytes + CDIO_CD_FRAMESIZE_RAW * 2));
    m_output_at = 0;

    setCDSpeed(2);
    m_inited = true;

    return m_inited;
}
Пример #15
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);
    }
}