|
MythTV
0.26-pre
|
00001 #define DO_NOT_WANT_PARANOIA_COMPATIBILITY 00002 #include "cddecoder.h" 00003 00004 // C 00005 #include <cstdlib> 00006 #include <cstring> 00007 00008 #include <unistd.h> 00009 00010 // Qt 00011 #include <QIODevice> 00012 #include <QFile> 00013 #include <QObject> 00014 #include <QString> 00015 00016 // libcdio 00017 #include <cdio/cdda.h> 00018 #include <cdio/logging.h> 00019 00020 // MythTV 00021 #include <audiooutput.h> 00022 #include <mythcontext.h> 00023 00024 extern "C" { 00025 #include <libavcodec/avcodec.h> 00026 } 00027 00028 // MythMusic 00029 #include "constants.h" 00030 #include "metadata.h" 00031 #include "cddb.h" 00032 00033 #define CDEXT ".cda" 00034 const unsigned kSamplesPerSec = 44100; 00035 00036 // Handle cdio log output 00037 static void logger(cdio_log_level_t level, const char message[]) 00038 { 00039 switch (level) 00040 { 00041 case CDIO_LOG_DEBUG: 00042 break; 00043 case CDIO_LOG_INFO: 00044 LOG(VB_MEDIA, LOG_DEBUG, QString("INFO cdio: %1").arg(message)); 00045 break; 00046 case CDIO_LOG_WARN: 00047 LOG(VB_MEDIA, LOG_DEBUG, QString("WARN cdio: %1").arg(message)); 00048 break; 00049 case CDIO_LOG_ERROR: 00050 case CDIO_LOG_ASSERT: 00051 LOG(VB_GENERAL, LOG_ERR, QString("ERROR cdio: %1").arg(message)); 00052 break; 00053 } 00054 } 00055 00056 // Open a cdio device 00057 static CdIo_t * openCdio(const QString& name) 00058 { 00059 // Setup log handler 00060 static int s_logging; 00061 if (!s_logging) 00062 { 00063 s_logging = 1; 00064 cdio_log_set_handler(&logger); 00065 } 00066 00067 CdIo_t *cdio = cdio_open(name.toAscii(), DRIVER_DEVICE); 00068 if (!cdio) 00069 { 00070 LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: cdio_open(%1) failed"). 00071 arg(name)); 00072 } 00073 return cdio; 00074 } 00075 00076 // Stack-based cdio device open 00077 class StCdioDevice 00078 { 00079 CdIo_t* m_cdio; 00080 00081 void* operator new(std::size_t); // Stack only 00082 // No copying 00083 StCdioDevice(const StCdioDevice&); 00084 StCdioDevice& operator =(const StCdioDevice&); 00085 00086 public: 00087 StCdioDevice(const QString& dev) : m_cdio(openCdio(dev)) { } 00088 ~StCdioDevice() { if (m_cdio) cdio_destroy(m_cdio); } 00089 00090 operator CdIo_t*() const { return m_cdio; } 00091 }; 00092 00093 00094 CdDecoder::CdDecoder(const QString &file, DecoderFactory *d, QIODevice *i, 00095 AudioOutput *o) : 00096 Decoder(d, i, o), 00097 m_inited(false), m_user_stop(false), 00098 m_devicename(""), 00099 m_stat(DecoderEvent::Error), 00100 m_output_buf(NULL), 00101 m_output_at(0), m_bks(0), 00102 m_bksFrames(0), m_decodeBytes(0), 00103 m_finish(false), 00104 m_freq(0), m_bitrate(0), 00105 m_chan(0), 00106 m_seekTime(-1.), 00107 m_settracknum(-1), m_tracknum(0), 00108 m_cdio(0), m_device(0), m_paranoia( 0), 00109 m_start(CDIO_INVALID_LSN), 00110 m_end(CDIO_INVALID_LSN), 00111 m_curpos(CDIO_INVALID_LSN) 00112 { 00113 setFilename(file); 00114 } 00115 00116 // virtual 00117 CdDecoder::~CdDecoder() 00118 { 00119 if (m_inited) 00120 deinit(); 00121 } 00122 00123 void CdDecoder::setDevice(const QString &dev) 00124 { 00125 m_devicename = dev; 00126 #ifdef WIN32 00127 // libcdio needs the drive letter with no path 00128 if (m_devicename.endsWith('\\')) 00129 m_devicename.chop(1); 00130 #endif 00131 } 00132 00133 // pure virtual 00134 void CdDecoder::stop() 00135 { 00136 m_user_stop = true; 00137 } 00138 00139 // private 00140 void CdDecoder::writeBlock() 00141 { 00142 while (m_seekTime <= +0.) 00143 { 00144 if(output()->AddFrames(m_output_buf, m_bksFrames, -1)) 00145 { 00146 if (m_output_at >= m_bks) 00147 { 00148 m_output_at -= m_bks; 00149 std::memmove(m_output_buf, m_output_buf + m_bks, 00150 m_output_at); 00151 } 00152 break; 00153 } 00154 else 00155 ::usleep(output()->GetAudioBufferedTime()<<9); 00156 } 00157 } 00158 00159 //static 00160 QMutex& CdDecoder::getCdioMutex() 00161 { 00162 static QMutex mtx(QMutex::Recursive); 00163 return mtx; 00164 } 00165 00166 // pure virtual 00167 bool CdDecoder::initialize() 00168 { 00169 if (m_inited) 00170 return true; 00171 00172 m_inited = m_user_stop = m_finish = false; 00173 m_freq = m_bitrate = 0L; 00174 m_stat = DecoderEvent::Error; 00175 m_chan = 0; 00176 m_seekTime = -1.; 00177 00178 if (output()) 00179 output()->PauseUntilBuffered(); 00180 00181 QFile* file = dynamic_cast< QFile* >(input()); // From QIODevice* 00182 if (file) 00183 { 00184 setFilename(file->fileName()); 00185 m_tracknum = getFilename().section('.', 0, 0).toUInt(); 00186 } 00187 00188 QMutexLocker lock(&getCdioMutex()); 00189 00190 m_cdio = openCdio(m_devicename); 00191 if (!m_cdio) 00192 return false; 00193 00194 m_start = cdio_get_track_lsn(m_cdio, m_tracknum); 00195 m_end = cdio_get_track_last_lsn(m_cdio, m_tracknum); 00196 if (CDIO_INVALID_LSN == m_start || 00197 CDIO_INVALID_LSN == m_end) 00198 { 00199 LOG(VB_MEDIA, LOG_INFO, "CdDecoder: No tracks on " + m_devicename); 00200 cdio_destroy(m_cdio), m_cdio = 0; 00201 return false; 00202 } 00203 00204 LOG(VB_MEDIA, LOG_DEBUG, QString("CdDecoder track=%1 lsn start=%2 end=%3") 00205 .arg(m_tracknum).arg(m_start).arg(m_end)); 00206 m_curpos = m_start; 00207 00208 m_device = cdio_cddap_identify_cdio(m_cdio, 0, NULL); 00209 if (NULL == m_device) 00210 { 00211 LOG(VB_GENERAL, LOG_ERR, 00212 QString("Error: CdDecoder: cdio_cddap_identify(%1) failed") 00213 .arg(m_devicename)); 00214 cdio_destroy(m_cdio), m_cdio = 0; 00215 return false; 00216 } 00217 00218 cdio_cddap_verbose_set(m_device, 00219 VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_ANY) ? CDDA_MESSAGE_PRINTIT : 00220 CDDA_MESSAGE_FORGETIT, 00221 VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_DEBUG) ? CDDA_MESSAGE_PRINTIT : 00222 CDDA_MESSAGE_FORGETIT); 00223 00224 if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device)) 00225 { 00226 // cdio_get_track_last_lsn is unreliable on discs with data at end 00227 lsn_t end2 = cdio_cddap_track_lastsector(m_device, m_tracknum); 00228 if (end2 < m_end) 00229 { 00230 LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: trim last lsn from %1 to %2") 00231 .arg(m_end).arg(end2)); 00232 m_end = end2; 00233 } 00234 00235 m_paranoia = cdio_paranoia_init(m_device); 00236 if (NULL != m_paranoia) 00237 { 00238 cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE); 00239 (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET); 00240 } 00241 else 00242 { 00243 LOG(VB_GENERAL, LOG_ERR, "Warn: CD reading with paranoia is disabled"); 00244 } 00245 } 00246 else 00247 { 00248 LOG(VB_GENERAL, LOG_ERR, 00249 QString("Warn: drive '%1' is not cdda capable"). 00250 arg(m_devicename)); 00251 } 00252 00253 int chnls = cdio_get_track_channels(m_cdio, m_tracknum); 00254 m_chan = chnls > 0 ? chnls : 2; 00255 m_freq = kSamplesPerSec; 00256 00257 if (output()) 00258 { 00259 const AudioSettings settings(FORMAT_S16, m_chan, 00260 CODEC_ID_PCM_S16LE, m_freq, false /* AC3/DTS passthru */); 00261 output()->Reconfigure(settings); 00262 output()->SetSourceBitrate(m_freq * m_chan * 16); 00263 } 00264 00265 // 20ms worth 00266 m_bks = (m_freq * m_chan * 2) / 50; 00267 m_bksFrames = m_freq / 50; 00268 // decode 8 bks worth of samples each time we need more 00269 m_decodeBytes = m_bks << 3; 00270 00271 m_output_buf = reinterpret_cast< char* >( 00272 ::av_malloc(m_decodeBytes + CDIO_CD_FRAMESIZE_RAW * 2)); 00273 m_output_at = 0; 00274 00275 setCDSpeed(2); 00276 00277 m_inited = true; 00278 00279 return m_inited; 00280 } 00281 00282 // pure virtual 00283 void CdDecoder::seek(double pos) 00284 { 00285 m_seekTime = pos; 00286 if (output()) 00287 output()->PauseUntilBuffered(); 00288 } 00289 00290 // private 00291 void CdDecoder::deinit() 00292 { 00293 setCDSpeed(-1); 00294 00295 QMutexLocker lock(&getCdioMutex()); 00296 00297 if (m_paranoia) 00298 cdio_paranoia_free(m_paranoia), m_paranoia = 0; 00299 if (m_device) 00300 cdio_cddap_close(m_device), m_device = 0, m_cdio = 0; 00301 if (m_cdio) 00302 cdio_destroy(m_cdio), m_cdio = 0; 00303 00304 if (m_output_buf) 00305 ::av_free(m_output_buf), m_output_buf = NULL; 00306 00307 m_inited = m_user_stop = m_finish = false; 00308 m_freq = m_bitrate = 0L; 00309 m_stat = DecoderEvent::Finished; 00310 m_chan = 0; 00311 setInput(0); 00312 setOutput(0); 00313 } 00314 00315 // private virtual 00316 void CdDecoder::run() 00317 { 00318 RunProlog(); 00319 00320 if (!m_inited) 00321 { 00322 RunEpilog(); 00323 return; 00324 } 00325 00326 m_stat = DecoderEvent::Decoding; 00327 // NB block scope required to prevent re-entrancy 00328 { 00329 DecoderEvent e(m_stat); 00330 dispatch(e); 00331 } 00332 00333 // account for possible frame expansion in aobase (upmix, float conv) 00334 const std::size_t thresh = m_bks * 6; 00335 00336 while (!m_finish && !m_user_stop) 00337 { 00338 if (m_seekTime >= +0.) 00339 { 00340 m_curpos = m_start + static_cast< lsn_t >( 00341 (m_seekTime * kSamplesPerSec) / CD_FRAMESAMPLES); 00342 if (m_paranoia) 00343 { 00344 QMutexLocker lock(&getCdioMutex()); 00345 cdio_paranoia_seek(m_paranoia, m_curpos, SEEK_SET); 00346 } 00347 00348 m_output_at = 0; 00349 m_seekTime = -1.; 00350 } 00351 00352 if (m_output_at < m_bks) 00353 { 00354 while (m_output_at < m_decodeBytes && 00355 !m_finish && !m_user_stop && m_seekTime <= +0.) 00356 { 00357 if (m_curpos < m_end) 00358 { 00359 QMutexLocker lock(&getCdioMutex()); 00360 if (m_paranoia) 00361 { 00362 int16_t *cdbuffer = cdio_paranoia_read_limited( 00363 m_paranoia, 0, 10); 00364 if (cdbuffer) 00365 memcpy(&m_output_buf[m_output_at], 00366 cdbuffer, CDIO_CD_FRAMESIZE_RAW); 00367 } 00368 else 00369 { 00370 driver_return_code_t c = cdio_read_audio_sector( 00371 m_cdio, &m_output_buf[m_output_at], 00372 m_curpos); 00373 if (DRIVER_OP_SUCCESS != c) 00374 { 00375 LOG(VB_MEDIA, LOG_DEBUG, 00376 QString("cdio_read_audio_sector(%1) error %2"). 00377 arg(m_curpos).arg(c)); 00378 memset( &m_output_buf[m_output_at], 00379 0, CDIO_CD_FRAMESIZE_RAW); 00380 } 00381 } 00382 00383 m_output_at += CDIO_CD_FRAMESIZE_RAW; 00384 ++(m_curpos); 00385 } 00386 else 00387 { 00388 m_finish = true; 00389 } 00390 } 00391 } 00392 00393 if (!output()) 00394 continue; 00395 00396 // Wait until we need to decode or supply more samples 00397 uint fill = 0, total = 0; 00398 while (!m_finish && !m_user_stop && m_seekTime <= +0.) 00399 { 00400 output()->GetBufferStatus(fill, total); 00401 // Make sure we have decoded samples ready and that the 00402 // audiobuffer is reasonably populated 00403 if (fill < (thresh << 6)) 00404 break; 00405 else 00406 { 00407 // Wait for half of the buffer to drain 00408 ::usleep(output()->GetAudioBufferedTime()<<9); 00409 } 00410 } 00411 00412 // write a block if there's sufficient space for it 00413 if (!m_user_stop && 00414 m_output_at >= m_bks && 00415 fill <= total - thresh) 00416 { 00417 writeBlock(); 00418 } 00419 } 00420 00421 if (m_user_stop) 00422 m_inited = false; 00423 else if (output()) 00424 { 00425 // Drain our buffer 00426 while (m_output_at >= m_bks) 00427 writeBlock(); 00428 00429 // Drain ao buffer 00430 output()->Drain(); 00431 } 00432 00433 if (m_finish) 00434 m_stat = DecoderEvent::Finished; 00435 else if (m_user_stop) 00436 m_stat = DecoderEvent::Stopped; 00437 else 00438 m_stat = DecoderEvent::Error; 00439 00440 // NB block scope required to step onto next track 00441 { 00442 DecoderEvent e(m_stat); 00443 dispatch(e); 00444 } 00445 00446 deinit(); 00447 00448 RunEpilog(); 00449 } 00450 00451 //public 00452 void CdDecoder::setCDSpeed(int speed) 00453 { 00454 QMutexLocker lock(&getCdioMutex()); 00455 00456 StCdioDevice cdio(m_devicename); 00457 if (cdio) 00458 { 00459 driver_return_code_t c = cdio_set_speed(cdio, speed >= 0 ? speed : 1); 00460 if (DRIVER_OP_SUCCESS != c) 00461 { 00462 LOG(VB_MEDIA, LOG_INFO, 00463 QString("Error: cdio_set_speed('%1',%2) failed"). 00464 arg(m_devicename).arg(speed)); 00465 } 00466 } 00467 } 00468 00469 //public 00470 int CdDecoder::getNumTracks() 00471 { 00472 QMutexLocker lock(&getCdioMutex()); 00473 00474 StCdioDevice cdio(m_devicename); 00475 if (!cdio) 00476 return 0; 00477 00478 track_t tracks = cdio_get_num_tracks(cdio); 00479 if (CDIO_INVALID_TRACK != tracks) 00480 LOG(VB_MEDIA, LOG_DEBUG, QString("getNumTracks = %1").arg(tracks)); 00481 else 00482 tracks = -1; 00483 00484 return tracks; 00485 } 00486 00487 //public 00488 int CdDecoder::getNumCDAudioTracks() 00489 { 00490 QMutexLocker lock(&getCdioMutex()); 00491 00492 StCdioDevice cdio(m_devicename); 00493 if (!cdio) 00494 return 0; 00495 00496 int nAudio = 0; 00497 const track_t last = cdio_get_last_track_num(cdio); 00498 if (CDIO_INVALID_TRACK != last) 00499 { 00500 for (track_t t = cdio_get_first_track_num(cdio) ; t <= last; ++t) 00501 { 00502 if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, t)) 00503 ++nAudio; 00504 } 00505 LOG(VB_MEDIA, LOG_DEBUG, QString("getNumCDAudioTracks = %1").arg(nAudio)); 00506 } 00507 00508 return nAudio; 00509 } 00510 00511 //public 00512 Metadata* CdDecoder::getMetadata(int track) 00513 { 00514 m_settracknum = track; 00515 return getMetadata(); 00516 } 00517 00518 //public 00519 Metadata *CdDecoder::getLastMetadata() 00520 { 00521 for(int i = getNumTracks(); i > 0; --i) 00522 { 00523 Metadata *m = getMetadata(i); 00524 if(m) 00525 return m; 00526 } 00527 return NULL; 00528 } 00529 00530 // Create a TOC 00531 static lsn_t s_lastAudioLsn; 00532 static Cddb::Toc& GetToc(CdIo_t *cdio, Cddb::Toc& toc) 00533 { 00534 // Get lead-in 00535 const track_t firstTrack = cdio_get_first_track_num(cdio); 00536 lsn_t lsn0 = 0; 00537 msf_t msf; 00538 if (cdio_get_track_msf(cdio, firstTrack, &msf)) 00539 lsn0 = (msf.m * 60 + msf.s) * CDIO_CD_FRAMES_PER_SEC + msf.f; 00540 00541 const track_t lastTrack = cdio_get_last_track_num(cdio); 00542 for (track_t t = firstTrack; t <= lastTrack + 1; ++t) 00543 { 00544 #if 0 // This would be better but the msf's returned are way off in libcdio 0.81 00545 if (!cdio_get_track_msf(cdio, t, &msf)) 00546 break; 00547 #else 00548 lsn_t lsn = cdio_get_track_lsn(cdio, t); 00549 if (s_lastAudioLsn && lsn > s_lastAudioLsn) 00550 lsn = s_lastAudioLsn; 00551 lsn += lsn0; // lead-in 00552 00553 std::div_t d = std::div(lsn, CDIO_CD_FRAMES_PER_SEC); 00554 msf.f = d.rem; 00555 d = std::div(d.quot, 60); 00556 msf.s = d.rem; 00557 msf.m = d.quot; 00558 #endif 00559 //LOG(VB_MEDIA, LOG_INFO, QString("Track %1 msf: %2:%3:%4"). 00560 // arg(t,2).arg(msf.m,2).arg(msf.s,2).arg(msf.f,2) ); 00561 toc.push_back(Cddb::Msf(msf.m, msf.s, msf.f)); 00562 00563 if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, t)) 00564 break; 00565 } 00566 return toc; 00567 } 00568 00569 //virtual 00570 Metadata *CdDecoder::getMetadata() 00571 { 00572 QString artist, album, compilation_artist, title, genre; 00573 int year = 0; 00574 unsigned long length = 0; 00575 track_t tracknum = 0; 00576 00577 if (-1 == m_settracknum) 00578 tracknum = getFilename().toUInt(); 00579 else 00580 { 00581 tracknum = m_settracknum; 00582 setFilename(QString("%1" CDEXT).arg(tracknum)); 00583 } 00584 00585 QMutexLocker lock(&getCdioMutex()); 00586 00587 StCdioDevice cdio(m_devicename); 00588 if (!cdio) 00589 return NULL; 00590 00591 const track_t lastTrack = cdio_get_last_track_num(cdio); 00592 if (CDIO_INVALID_TRACK == lastTrack) 00593 return NULL; 00594 00595 if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum)) 00596 return NULL; 00597 00598 // Assume disc changed if max LSN different 00599 bool isDiscChanged = false; 00600 static lsn_t s_totalSectors; 00601 lsn_t totalSectors = cdio_get_track_lsn(cdio, CDIO_CDROM_LEADOUT_TRACK); 00602 if (s_totalSectors != totalSectors) 00603 { 00604 s_totalSectors = totalSectors; 00605 isDiscChanged = true; 00606 } 00607 00608 // NB cdio_get_track_last_lsn is unreliable for the last audio track 00609 // of discs with data tracks beyond 00610 lsn_t end = cdio_get_track_last_lsn(cdio, tracknum); 00611 if (isDiscChanged) 00612 { 00613 const track_t audioTracks = getNumCDAudioTracks(); 00614 s_lastAudioLsn = cdio_get_track_last_lsn(cdio, audioTracks); 00615 00616 if (audioTracks < lastTrack) 00617 { 00618 cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0, NULL); 00619 if (NULL != dev) 00620 { 00621 if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev)) 00622 { 00623 // NB this can be S L O W but is reliable 00624 lsn_t end2 = cdio_cddap_track_lastsector(dev, 00625 getNumCDAudioTracks()); 00626 if (CDIO_INVALID_LSN != end2) 00627 s_lastAudioLsn = end2; 00628 } 00629 cdio_cddap_close_no_free_cdio(dev); 00630 } 00631 } 00632 } 00633 00634 if (s_lastAudioLsn && s_lastAudioLsn < end) 00635 end = s_lastAudioLsn; 00636 00637 const lsn_t start = cdio_get_track_lsn(cdio, tracknum); 00638 if (CDIO_INVALID_LSN != start && CDIO_INVALID_LSN != end) 00639 { 00640 length = ((end - start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) / 00641 CDIO_CD_FRAMES_PER_SEC; 00642 } 00643 00644 bool isCompilation = false; 00645 00646 #define CDTEXT 0 // Disabled - cd-text access on discs without it is S L O W 00647 #if CDTEXT 00648 static int s_iCdtext; 00649 if (isDiscChanged) 00650 s_iCdtext = -1; 00651 00652 if (s_iCdtext) 00653 { 00654 // cdio_get_cdtext can't take >5 seconds on some CD's without cdtext 00655 if (s_iCdtext < 0) 00656 LOG(VB_MEDIA, LOG_INFO, 00657 QString("Getting cdtext for track %1...").arg(tracknum)); 00658 cdtext_t * cdtext = cdio_get_cdtext(m_cdio, tracknum); 00659 if (NULL != cdtext) 00660 { 00661 genre = cdtext_get_const(CDTEXT_GENRE, cdtext); 00662 artist = cdtext_get_const(CDTEXT_PERFORMER, cdtext); 00663 title = cdtext_get_const(CDTEXT_TITLE, cdtext); 00664 const char* isrc = cdtext_get_const(CDTEXT_ISRC, cdtext); 00665 /* ISRC codes are 12 characters long, in the form CCXXXYYNNNNN 00666 * CC = country code 00667 * XXX = registrant e.g. BMG 00668 * CC = year withou century 00669 * NNNNN = unique ID 00670 */ 00671 if (isrc && strlen(isrc) >= 7) 00672 { 00673 year = (isrc[5] - '0') * 10 + (isrc[6] - '0'); 00674 year += (year <= 30) ? 2000 : 1900; 00675 } 00676 00677 cdtext_destroy(cdtext); 00678 00679 if (!title.isNull()) 00680 { 00681 if (s_iCdtext < 0) 00682 LOG(VB_MEDIA, LOG_INFO, "Found cdtext track title"); 00683 s_iCdtext = 1; 00684 00685 // Get disc info 00686 cdtext = cdio_get_cdtext(cdio, 0); 00687 if (NULL != cdtext) 00688 { 00689 compilation_artist = cdtext_get_const( 00690 CDTEXT_PERFORMER, cdtext); 00691 if (!compilation_artist.isEmpty() && 00692 artist != compilation_artist) 00693 isCompilation = true; 00694 00695 album = cdtext_get_const(CDTEXT_TITLE, cdtext); 00696 00697 if (genre.isNull()) 00698 genre = cdtext_get_const(CDTEXT_GENRE, cdtext); 00699 00700 cdtext_destroy(cdtext); 00701 } 00702 } 00703 else 00704 { 00705 if (s_iCdtext < 0) 00706 LOG(VB_MEDIA, LOG_INFO, "No cdtext title for track"); 00707 s_iCdtext = 0; 00708 } 00709 } 00710 else 00711 { 00712 if (s_iCdtext < 0) 00713 LOG(VB_MEDIA, LOG_INFO, "No cdtext"); 00714 s_iCdtext = 0; 00715 } 00716 } 00717 00718 if (title.isEmpty() || artist.isEmpty() || album.isEmpty()) 00719 #endif // CDTEXT 00720 { 00721 // CDDB lookup 00722 Cddb::Toc toc; 00723 Cddb::Matches r; 00724 if (Cddb::Query(r, GetToc(cdio, toc))) 00725 { 00726 Cddb::Matches::match_t::const_iterator select = r.matches.begin(); 00727 00728 if (r.matches.size() > 1) 00729 { 00730 // TODO prompt user to select one 00731 // In the meantime, select the first non-generic genre 00732 for (Cddb::Matches::match_t::const_iterator it = select; 00733 it != r.matches.end(); ++it) 00734 { 00735 QString g = it->genre.toLower(); 00736 if (g != "misc" && g != "data") 00737 { 00738 select = it; 00739 break; 00740 } 00741 } 00742 } 00743 00744 Cddb::Album info; 00745 if (Cddb::Read(info, select->genre, select->discID)) 00746 { 00747 isCompilation = info.isCompilation; 00748 if (info.genre.toLower() != "misc") 00749 genre = info.genre; 00750 album = info.title; 00751 compilation_artist = info.artist; 00752 year = info.year; 00753 if (info.tracks.size() >= tracknum) 00754 { 00755 const Cddb::Track& track = info.tracks[tracknum - 1]; 00756 title = track.title; 00757 artist = track.artist; 00758 } 00759 00760 // Create a temporary local alias for future lookups 00761 if (r.discID != info.discID) 00762 Cddb::Alias(info, r.discID); 00763 } 00764 } 00765 } 00766 00767 if (compilation_artist.toLower().left(7) == "various") 00768 compilation_artist = QObject::tr("Various Artists"); 00769 00770 if (artist.isEmpty()) 00771 { 00772 artist = compilation_artist; 00773 compilation_artist.clear(); 00774 } 00775 00776 if (title.isEmpty()) 00777 title = QObject::tr("Track %1").arg(tracknum); 00778 00779 Metadata *m = new Metadata(getFilename(), artist, compilation_artist, 00780 album, title, genre, year, tracknum, length); 00781 if (m) 00782 m->setCompilation(isCompilation); 00783 00784 return m; 00785 } 00786 00787 // virtual 00788 void CdDecoder::commitMetadata(Metadata *mdata) 00789 { 00790 QMutexLocker lock(&getCdioMutex()); 00791 00792 StCdioDevice cdio(m_devicename); 00793 if (!cdio) 00794 return; 00795 00796 Cddb::Toc toc; 00797 GetToc(cdio, toc); 00798 00799 unsigned secs; 00800 Cddb::discid_t discID = Cddb::Discid(secs, toc.data(), toc.size() - 1); 00801 00802 Cddb::Album album(discID, mdata->Genre().toLower().toUtf8()); 00803 if (!Cddb::Read(album, album.genre, discID)) 00804 album.toc = toc; 00805 00806 album.isCompilation = mdata->Compilation(); 00807 if (!mdata->Compilation()) 00808 album.artist = mdata->Artist(); 00809 else if (mdata->CompilationArtist() != album.artist) 00810 album.artist = mdata->CompilationArtist(); 00811 00812 album.title = mdata->Album(); 00813 album.year = mdata->Year(); 00814 00815 if (album.tracks.size() < m_tracknum) 00816 album.tracks.resize(m_tracknum); 00817 00818 Cddb::Track& track = album.tracks[m_tracknum - 1]; 00819 track.title = mdata->Title(); 00820 track.artist = mdata->Artist(); 00821 00822 Cddb::Write(album); 00823 } 00824 00825 00826 // pure virtual 00827 bool CdDecoderFactory::supports(const QString &source) const 00828 { 00829 return (source.right(extension().length()).toLower() == extension()); 00830 } 00831 00832 // pure virtual 00833 const QString &CdDecoderFactory::extension() const 00834 { 00835 static QString ext(CDEXT); 00836 return ext; 00837 } 00838 00839 // pure virtual 00840 const QString &CdDecoderFactory::description() const 00841 { 00842 static QString desc(QObject::tr("Audio CD parser")); 00843 return desc; 00844 } 00845 00846 // pure virtual 00847 Decoder *CdDecoderFactory::create(const QString &file, QIODevice *input, 00848 AudioOutput *output, bool deletable) 00849 { 00850 if (deletable) 00851 return new CdDecoder(file, this, input, output); 00852 00853 static CdDecoder *decoder; 00854 if (! decoder) { 00855 decoder = new CdDecoder(file, this, input, output); 00856 } else { 00857 decoder->setInput(input); 00858 decoder->setFilename(file); 00859 decoder->setOutput(output); 00860 } 00861 00862 return decoder; 00863 } 00864
1.7.6.1