Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
/*! Return number of channels in track: 2 or 4; -2 if not
  implemented or -1 for error.
  Not meaningful if track is not an audio track.
*/
int getChannels()
{
  return cdio_get_track_channels(p_cdio, i_track);
}
Beispiel #6
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;
}