1 #define DO_NOT_WANT_PARANOIA_COMPATIBILITY
17 #include <cdio/logging.h>
25 #include <libavcodec/avcodec.h>
31 static constexpr
const char*
CDEXT {
".cda" };
35 static void logger(cdio_log_level_t level,
const char *message)
42 LOG(VB_MEDIA, LOG_DEBUG, QString(
"INFO cdio: %1").arg(message));
45 LOG(VB_MEDIA, LOG_DEBUG, QString(
"WARN cdio: %1").arg(message));
49 LOG(VB_GENERAL, LOG_ERR, QString(
"ERROR cdio: %1").arg(message));
62 cdio_log_set_handler(&
logger);
65 CdIo_t *cdio = cdio_open(name.toLatin1(), DRIVER_DEVICE);
68 LOG(VB_MEDIA, LOG_INFO, QString(
"CdDecoder: cdio_open(%1) failed").
79 void*
operator new(std::size_t);
88 operator CdIo_t*()
const {
return m_cdio; }
140 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
143 static QMutex
s_mtx(QMutex::Recursive);
149 static QRecursiveMutex
s_mtx;
177 m_start = cdio_get_track_lsn(m_cdio,
m_trackNum);
178 m_end = cdio_get_track_last_lsn(m_cdio,
m_trackNum);
179 if (CDIO_INVALID_LSN == m_start ||
180 CDIO_INVALID_LSN == m_end)
183 cdio_destroy(m_cdio), m_cdio =
nullptr;
187 LOG(VB_MEDIA, LOG_DEBUG, QString(
"CdDecoder track=%1 lsn start=%2 end=%3")
191 m_device = cdio_cddap_identify_cdio(m_cdio, 0,
nullptr);
192 if (
nullptr == m_device)
194 LOG(VB_GENERAL, LOG_ERR,
195 QString(
"Error: CdDecoder: cdio_cddap_identify(%1) failed")
197 cdio_destroy(m_cdio), m_cdio =
nullptr;
201 cdio_cddap_verbose_set(m_device,
203 CDDA_MESSAGE_FORGETIT,
205 CDDA_MESSAGE_FORGETIT);
207 if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device))
210 lsn_t end2 = cdio_cddap_track_lastsector(m_device,
m_trackNum);
213 LOG(VB_MEDIA, LOG_INFO, QString(
"CdDecoder: trim last lsn from %1 to %2")
214 .arg(m_end).arg(end2));
222 if (
nullptr != m_paranoia)
224 cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE);
225 (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET);
229 LOG(VB_GENERAL, LOG_WARNING,
"CD reading with paranoia is disabled");
234 LOG(VB_GENERAL, LOG_ERR,
235 QString(
"Warn: drive '%1' is not cdda capable").
239 int chnls = cdio_get_track_channels(m_cdio,
m_trackNum);
240 m_chan = chnls > 0 ? chnls : 2;
246 AV_CODEC_ID_PCM_S16LE,
m_freq,
false );
284 cdio_paranoia_free(m_paranoia), m_paranoia =
nullptr;
286 cdio_cddap_close(m_device), m_device =
nullptr, m_cdio =
nullptr;
288 cdio_destroy(m_cdio), m_cdio =
nullptr;
319 const std::size_t thresh =
m_bks * 6;
325 m_curPos = m_start +
static_cast< lsn_t
>(
330 cdio_paranoia_seek(m_paranoia, m_curPos, SEEK_SET);
342 if (m_curPos < m_end)
347 int16_t *cdbuffer = cdio_paranoia_read_limited(
348 m_paranoia,
nullptr, 10);
351 cdbuffer, CDIO_CD_FRAMESIZE_RAW);
355 driver_return_code_t c = cdio_read_audio_sector(
357 if (DRIVER_OP_SUCCESS != c)
359 LOG(VB_MEDIA, LOG_DEBUG,
360 QString(
"cdio_read_audio_sector(%1) error %2").
361 arg(m_curPos).arg(c));
363 0, CDIO_CD_FRAMESIZE_RAW);
391 if (fill < (thresh << 6))
400 fill <= total - thresh)
444 driver_return_code_t c = cdio_set_speed(cdio, speed >= 0 ? speed : 1);
445 if (DRIVER_OP_SUCCESS != c)
447 LOG(VB_MEDIA, LOG_INFO,
448 QString(
"Error: cdio_set_speed('%1',%2) failed").
463 track_t tracks = cdio_get_num_tracks(cdio);
464 if (CDIO_INVALID_TRACK != tracks)
465 LOG(VB_MEDIA, LOG_DEBUG, QString(
"getNumTracks = %1").arg(tracks));
482 const track_t last = cdio_get_last_track_num(cdio);
483 if (CDIO_INVALID_TRACK != last)
485 for (track_t
t = cdio_get_first_track_num(cdio) ;
t <= last; ++
t)
487 if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio,
t))
490 LOG(VB_MEDIA, LOG_DEBUG, QString(
"getNumCDAudioTracks = %1").arg(nAudio));
512 QString compilation_artist;
516 std::chrono::milliseconds length = 0s;
517 track_t tracknum = 0;
520 tracknum =
getURL().toUInt();
533 const track_t lastTrack = cdio_get_last_track_num(cdio);
534 if (CDIO_INVALID_TRACK == lastTrack)
537 if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum))
541 bool isDiscChanged =
false;
542 static lsn_t s_totalSectors;
543 lsn_t totalSectors = cdio_get_track_lsn(cdio, CDIO_CDROM_LEADOUT_TRACK);
544 if (s_totalSectors != totalSectors)
546 s_totalSectors = totalSectors;
547 isDiscChanged =
true;
552 lsn_t end = cdio_get_track_last_lsn(cdio, tracknum);
558 if (audioTracks < lastTrack)
560 cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0,
nullptr);
563 if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev))
566 lsn_t end2 = cdio_cddap_track_lastsector(dev,
568 if (CDIO_INVALID_LSN != end2)
571 cdio_cddap_close_no_free_cdio(dev);
579 const lsn_t
start = cdio_get_track_lsn(cdio, tracknum);
580 if (CDIO_INVALID_LSN !=
start && CDIO_INVALID_LSN != end)
582 length = std::chrono::milliseconds(((end -
start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) /
583 CDIO_CD_FRAMES_PER_SEC);
586 bool isCompilation =
false;
589 #define CDTEXT 0 // NOLINT(cppcoreguidelines-macro-usage)
591 static int s_iCdtext;
599 LOG(VB_MEDIA, LOG_INFO,
600 QString(
"Getting cdtext for track %1...").arg(tracknum));
601 cdtext_t * cdtext = cdio_get_cdtext(m_cdio, tracknum);
602 if (
nullptr != cdtext)
604 genre = cdtext_get_const(CDTEXT_GENRE, cdtext);
605 artist = cdtext_get_const(CDTEXT_PERFORMER, cdtext);
606 title = cdtext_get_const(CDTEXT_TITLE, cdtext);
607 const char* isrc = cdtext_get_const(CDTEXT_ISRC, cdtext);
614 if (isrc && strlen(isrc) >= 7)
616 year = (isrc[5] -
'0') * 10 + (isrc[6] -
'0');
617 year += (year <= 30) ? 2000 : 1900;
620 cdtext_destroy(cdtext);
625 LOG(VB_MEDIA, LOG_INFO,
"Found cdtext track title");
629 cdtext = cdio_get_cdtext(cdio, 0);
630 if (
nullptr != cdtext)
632 compilation_artist = cdtext_get_const(
633 CDTEXT_PERFORMER, cdtext);
634 if (!compilation_artist.isEmpty() &&
635 artist != compilation_artist)
636 isCompilation =
true;
638 album = cdtext_get_const(CDTEXT_TITLE, cdtext);
641 genre = cdtext_get_const(CDTEXT_GENRE, cdtext);
643 cdtext_destroy(cdtext);
649 LOG(VB_MEDIA, LOG_INFO,
"No cdtext title for track");
656 LOG(VB_MEDIA, LOG_INFO,
"No cdtext");
661 if (title.isEmpty() || artist.isEmpty() || album.isEmpty())
667 if (compilation_artist.toLower().left(7) ==
"various")
668 compilation_artist = tr(
"Various Artists");
670 if (artist.isEmpty())
672 artist = compilation_artist;
673 compilation_artist.clear();
677 title = tr(
"Track %1").arg(tracknum);
680 title, genre, year, tracknum, length);
682 m->setCompilation(isCompilation);
696 static QString s_ext(
CDEXT);
703 static QString s_desc(tr(
"Audio CD parser"));