1 #define DO_NOT_WANT_PARANOIA_COMPATIBILITY
17 #include <cdio/logging.h>
25 #include <libavcodec/avcodec.h>
30 static constexpr
const char*
CDEXT {
".cda" };
34 static void logger(cdio_log_level_t level,
const char *message)
41 LOG(VB_MEDIA, LOG_DEBUG, QString(
"INFO cdio: %1").arg(message));
44 LOG(VB_MEDIA, LOG_DEBUG, QString(
"WARN cdio: %1").arg(message));
48 LOG(VB_GENERAL, LOG_ERR, QString(
"ERROR cdio: %1").arg(message));
61 cdio_log_set_handler(&
logger);
64 CdIo_t *cdio = cdio_open(name.toLatin1(), DRIVER_DEVICE);
67 LOG(VB_MEDIA, LOG_INFO, QString(
"CdDecoder: cdio_open(%1) failed").
78 void*
operator new(std::size_t);
87 operator CdIo_t*()
const {
return m_cdio; }
141 static QRecursiveMutex
s_mtx;
168 m_start = cdio_get_track_lsn(m_cdio,
m_trackNum);
169 m_end = cdio_get_track_last_lsn(m_cdio,
m_trackNum);
170 if (CDIO_INVALID_LSN == m_start ||
171 CDIO_INVALID_LSN == m_end)
174 cdio_destroy(m_cdio), m_cdio =
nullptr;
178 LOG(VB_MEDIA, LOG_DEBUG, QString(
"CdDecoder track=%1 lsn start=%2 end=%3")
182 m_device = cdio_cddap_identify_cdio(m_cdio, 0,
nullptr);
183 if (
nullptr == m_device)
185 LOG(VB_GENERAL, LOG_ERR,
186 QString(
"Error: CdDecoder: cdio_cddap_identify(%1) failed")
188 cdio_destroy(m_cdio), m_cdio =
nullptr;
192 cdio_cddap_verbose_set(m_device,
194 CDDA_MESSAGE_FORGETIT,
196 CDDA_MESSAGE_FORGETIT);
198 if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device))
201 lsn_t end2 = cdio_cddap_track_lastsector(m_device,
m_trackNum);
204 LOG(VB_MEDIA, LOG_INFO, QString(
"CdDecoder: trim last lsn from %1 to %2")
205 .arg(m_end).arg(end2));
213 if (
nullptr != m_paranoia)
215 cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE);
216 (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET);
220 LOG(VB_GENERAL, LOG_WARNING,
"CD reading with paranoia is disabled");
225 LOG(VB_GENERAL, LOG_ERR,
226 QString(
"Warn: drive '%1' is not cdda capable").
230 int chnls = cdio_get_track_channels(m_cdio,
m_trackNum);
231 m_chan = chnls > 0 ? chnls : 2;
237 AV_CODEC_ID_PCM_S16LE,
m_freq,
false );
275 cdio_paranoia_free(m_paranoia), m_paranoia =
nullptr;
277 cdio_cddap_close(m_device), m_device =
nullptr, m_cdio =
nullptr;
279 cdio_destroy(m_cdio), m_cdio =
nullptr;
310 const std::size_t thresh =
m_bks * 6;
316 m_curPos = m_start +
static_cast< lsn_t
>(
321 cdio_paranoia_seek(m_paranoia, m_curPos, SEEK_SET);
333 if (m_curPos < m_end)
338 int16_t *cdbuffer = cdio_paranoia_read_limited(
339 m_paranoia,
nullptr, 10);
342 cdbuffer, CDIO_CD_FRAMESIZE_RAW);
346 driver_return_code_t c = cdio_read_audio_sector(
348 if (DRIVER_OP_SUCCESS != c)
350 LOG(VB_MEDIA, LOG_DEBUG,
351 QString(
"cdio_read_audio_sector(%1) error %2").
352 arg(m_curPos).arg(c));
354 0, CDIO_CD_FRAMESIZE_RAW);
382 if (fill < (thresh << 6))
391 fill <= total - thresh)
435 driver_return_code_t c = cdio_set_speed(cdio, speed >= 0 ? speed : 1);
436 if (DRIVER_OP_SUCCESS != c)
438 LOG(VB_MEDIA, LOG_INFO,
439 QString(
"Error: cdio_set_speed('%1',%2) failed").
454 track_t tracks = cdio_get_num_tracks(cdio);
455 if (CDIO_INVALID_TRACK != tracks)
456 LOG(VB_MEDIA, LOG_DEBUG, QString(
"getNumTracks = %1").arg(tracks));
473 const track_t last = cdio_get_last_track_num(cdio);
474 if (CDIO_INVALID_TRACK != last)
476 for (track_t
t = cdio_get_first_track_num(cdio) ;
t <= last; ++
t)
478 if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio,
t))
481 LOG(VB_MEDIA, LOG_DEBUG, QString(
"getNumCDAudioTracks = %1").arg(nAudio));
503 QString compilation_artist;
507 std::chrono::milliseconds length = 0s;
508 track_t tracknum = 0;
511 tracknum =
getURL().toUInt();
524 const track_t lastTrack = cdio_get_last_track_num(cdio);
525 if (CDIO_INVALID_TRACK == lastTrack)
528 if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum))
532 bool isDiscChanged =
false;
533 static lsn_t s_totalSectors;
534 lsn_t totalSectors = cdio_get_track_lsn(cdio, CDIO_CDROM_LEADOUT_TRACK);
535 if (s_totalSectors != totalSectors)
537 s_totalSectors = totalSectors;
538 isDiscChanged =
true;
543 lsn_t end = cdio_get_track_last_lsn(cdio, tracknum);
549 if (audioTracks < lastTrack)
551 cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0,
nullptr);
554 if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev))
557 lsn_t end2 = cdio_cddap_track_lastsector(dev,
559 if (CDIO_INVALID_LSN != end2)
562 cdio_cddap_close_no_free_cdio(dev);
570 const lsn_t
start = cdio_get_track_lsn(cdio, tracknum);
571 if (CDIO_INVALID_LSN !=
start && CDIO_INVALID_LSN != end)
573 length = std::chrono::milliseconds(((end -
start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) /
574 CDIO_CD_FRAMES_PER_SEC);
577 bool isCompilation =
false;
580 #define CDTEXT 0 // NOLINT(cppcoreguidelines-macro-usage)
582 static int s_iCdtext;
590 LOG(VB_MEDIA, LOG_INFO,
591 QString(
"Getting cdtext for track %1...").arg(tracknum));
592 cdtext_t * cdtext = cdio_get_cdtext(m_cdio, tracknum);
593 if (
nullptr != cdtext)
595 genre = cdtext_get_const(CDTEXT_GENRE, cdtext);
596 artist = cdtext_get_const(CDTEXT_PERFORMER, cdtext);
597 title = cdtext_get_const(CDTEXT_TITLE, cdtext);
598 const char* isrc = cdtext_get_const(CDTEXT_ISRC, cdtext);
605 if (isrc && strlen(isrc) >= 7)
607 year = (isrc[5] -
'0') * 10 + (isrc[6] -
'0');
608 year += (year <= 30) ? 2000 : 1900;
611 cdtext_destroy(cdtext);
616 LOG(VB_MEDIA, LOG_INFO,
"Found cdtext track title");
620 cdtext = cdio_get_cdtext(cdio, 0);
621 if (
nullptr != cdtext)
623 compilation_artist = cdtext_get_const(
624 CDTEXT_PERFORMER, cdtext);
625 if (!compilation_artist.isEmpty() &&
626 artist != compilation_artist)
627 isCompilation =
true;
629 album = cdtext_get_const(CDTEXT_TITLE, cdtext);
632 genre = cdtext_get_const(CDTEXT_GENRE, cdtext);
634 cdtext_destroy(cdtext);
640 LOG(VB_MEDIA, LOG_INFO,
"No cdtext title for track");
647 LOG(VB_MEDIA, LOG_INFO,
"No cdtext");
652 if (title.isEmpty() || artist.isEmpty() || album.isEmpty())
655 #ifdef HAVE_MUSICBRAINZ
663 auto *metadata = getMusicBrainz().getMetadata(
m_setTrackNum);
666 metadata->setFilename(
getURL());
670 #endif // HAVE_MUSICBRAINZ
673 if (compilation_artist.toLower().left(7) ==
"various")
674 compilation_artist = tr(
"Various Artists");
676 if (artist.isEmpty())
678 artist = compilation_artist;
679 compilation_artist.clear();
683 title = tr(
"Track %1").arg(tracknum);
686 title, genre, year, tracknum, length);
688 m->setCompilation(isCompilation);
693 #ifdef HAVE_MUSICBRAINZ
698 return s_musicBrainz;
701 #endif // HAVE_MUSICBRAINZ
713 static QString s_ext(
CDEXT);
720 static QString s_desc(tr(
"Audio CD parser"));