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; }
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; }
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; }
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; }
/*! 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); }
// 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; }