MythTV  master
cddecoder.cpp
Go to the documentation of this file.
1 #define DO_NOT_WANT_PARANOIA_COMPATIBILITY
2 #include "cddecoder.h"
3 
4 // C
5 #include <cstdlib>
6 #include <cstring>
7 #include <unistd.h>
8 
9 // Qt
10 #include <QFile>
11 #include <QIODevice>
12 #include <QObject>
13 #include <QString>
14 
15 // libcdio
16 // cdda already included via cddecoder.h
17 #include <cdio/logging.h>
18 
19 // MythTV
21 #include <libmyth/mythcontext.h>
23 
24 extern "C" {
25 #include <libavcodec/avcodec.h>
26 }
27 
28 // MythMusic
29 #include "constants.h"
30 static constexpr const char* CDEXT { ".cda" };
31 static constexpr long kSamplesPerSec { 44100 };
32 
33 // Handle cdio log output
34 static void logger(cdio_log_level_t level, const char *message)
35 {
36  switch (level)
37  {
38  case CDIO_LOG_DEBUG:
39  break;
40  case CDIO_LOG_INFO:
41  LOG(VB_MEDIA, LOG_DEBUG, QString("INFO cdio: %1").arg(message));
42  break;
43  case CDIO_LOG_WARN:
44  LOG(VB_MEDIA, LOG_DEBUG, QString("WARN cdio: %1").arg(message));
45  break;
46  case CDIO_LOG_ERROR:
47  case CDIO_LOG_ASSERT:
48  LOG(VB_GENERAL, LOG_ERR, QString("ERROR cdio: %1").arg(message));
49  break;
50  }
51 }
52 
53 // Open a cdio device
54 static CdIo_t * openCdio(const QString& name)
55 {
56  // Setup log handler
57  static int s_logging;
58  if (!s_logging)
59  {
60  s_logging = 1;
61  cdio_log_set_handler(&logger);
62  }
63 
64  CdIo_t *cdio = cdio_open(name.toLatin1(), DRIVER_DEVICE);
65  if (!cdio)
66  {
67  LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: cdio_open(%1) failed").
68  arg(name));
69  }
70  return cdio;
71 }
72 
73 // Stack-based cdio device open
75 {
76  CdIo_t* m_cdio {nullptr};
77 
78  void* operator new(std::size_t); // Stack only
79  // No copying
80  StCdioDevice(const StCdioDevice&);
82 
83 public:
84  explicit StCdioDevice(const QString& dev) : m_cdio(openCdio(dev)) { }
85  ~StCdioDevice() { if (m_cdio) cdio_destroy(m_cdio); }
86 
87  operator CdIo_t*() const { return m_cdio; } // NOLINT(google-explicit-constructor)
88 };
89 
90 
92  Decoder(d, o)
93 {
94  setURL(file);
95 }
96 
97 // virtual
99 {
100  if (m_inited)
101  deinit();
102 }
103 
104 void CdDecoder::setDevice(const QString &dev)
105 {
106  m_deviceName = dev;
107 #ifdef WIN32
108  // libcdio needs the drive letter with no path
109  if (m_deviceName.endsWith('\\'))
110  m_deviceName.chop(1);
111 #endif
112 }
113 
114 // pure virtual
116 {
117  m_userStop = true;
118 }
119 
120 // private
122 {
123  while (m_seekTime <= +0.)
124  {
125  if(output()->AddFrames(m_outputBuf, m_bksFrames, -1ms))
126  {
127  if (m_outputAt >= m_bks)
128  {
129  m_outputAt -= m_bks;
130  std::memmove(m_outputBuf, m_outputBuf + m_bks, m_outputAt);
131  }
132  break;
133  }
134  ::usleep(output()->GetAudioBufferedTime().count()<<9);
135  }
136 }
137 
138 //static
139 QRecursiveMutex& CdDecoder::getCdioMutex()
140 {
141  static QRecursiveMutex s_mtx;
142  return s_mtx;
143 }
144 
145 // pure virtual
147 {
148  if (m_inited)
149  return true;
150 
151  m_inited = m_userStop = m_finish = false;
152  m_freq = m_bitrate = 0L;
154  m_chan = 0;
155  m_seekTime = -1.;
156 
157  if (output())
159 
160  m_trackNum = getURL().section('.', 0, 0).toUInt();
161 
162  QMutexLocker lock(&getCdioMutex());
163 
164  m_cdio = openCdio(m_deviceName);
165  if (!m_cdio)
166  return false;
167 
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)
172  {
173  LOG(VB_MEDIA, LOG_INFO, "CdDecoder: No tracks on " + m_deviceName);
174  cdio_destroy(m_cdio), m_cdio = nullptr;
175  return false;
176  }
177 
178  LOG(VB_MEDIA, LOG_DEBUG, QString("CdDecoder track=%1 lsn start=%2 end=%3")
179  .arg(m_trackNum).arg(m_start).arg(m_end));
180  m_curPos = m_start;
181 
182  m_device = cdio_cddap_identify_cdio(m_cdio, 0, nullptr);
183  if (nullptr == m_device)
184  {
185  LOG(VB_GENERAL, LOG_ERR,
186  QString("Error: CdDecoder: cdio_cddap_identify(%1) failed")
187  .arg(m_deviceName));
188  cdio_destroy(m_cdio), m_cdio = nullptr;
189  return false;
190  }
191 
192  cdio_cddap_verbose_set(m_device,
193  VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_ANY) ? CDDA_MESSAGE_PRINTIT :
194  CDDA_MESSAGE_FORGETIT,
195  VERBOSE_LEVEL_CHECK(VB_MEDIA, LOG_DEBUG) ? CDDA_MESSAGE_PRINTIT :
196  CDDA_MESSAGE_FORGETIT);
197 
198  if (DRIVER_OP_SUCCESS == cdio_cddap_open(m_device))
199  {
200  // cdio_get_track_last_lsn is unreliable on discs with data at end
201  lsn_t end2 = cdio_cddap_track_lastsector(m_device, m_trackNum);
202  if (end2 < m_end)
203  {
204  LOG(VB_MEDIA, LOG_INFO, QString("CdDecoder: trim last lsn from %1 to %2")
205  .arg(m_end).arg(end2));
206  m_end = end2;
207  }
208 
209  // FIXME can't use cdio_paranoia until we find a way to cleanly
210  // detect when the user has ejected a CD otherwise we enter a
211  // recursive loop in cdio_paranoia_read_limited()
212  //m_paranoia = cdio_paranoia_init(m_device);
213  if (nullptr != m_paranoia)
214  {
215  cdio_paranoia_modeset(m_paranoia, PARANOIA_MODE_DISABLE);
216  (void)cdio_paranoia_seek(m_paranoia, m_start, SEEK_SET);
217  }
218  else
219  {
220  LOG(VB_GENERAL, LOG_WARNING, "CD reading with paranoia is disabled");
221  }
222  }
223  else
224  {
225  LOG(VB_GENERAL, LOG_ERR,
226  QString("Warn: drive '%1' is not cdda capable").
227  arg(m_deviceName));
228  }
229 
230  int chnls = cdio_get_track_channels(m_cdio, m_trackNum);
231  m_chan = chnls > 0 ? chnls : 2;
233 
234  if (output())
235  {
236  const AudioSettings settings(FORMAT_S16, m_chan,
237  AV_CODEC_ID_PCM_S16LE, m_freq, false /* AC3/DTS passthru */);
238  output()->Reconfigure(settings);
240  }
241 
242  // 20ms worth
243  m_bks = (m_freq * m_chan * 2) / 50;
244  m_bksFrames = m_freq / 50;
245  // decode 8 bks worth of samples each time we need more
246  m_decodeBytes = m_bks << 3;
247 
248  m_outputBuf = reinterpret_cast< char* >(
249  ::av_malloc(m_decodeBytes + CDIO_CD_FRAMESIZE_RAW * 2));
250  m_outputAt = 0;
251 
252  setCDSpeed(2);
253 
254  m_inited = true;
255 
256  return m_inited;
257 }
258 
259 // pure virtual
260 void CdDecoder::seek(double pos)
261 {
262  m_seekTime = pos;
263  if (output())
265 }
266 
267 // private
269 {
270  setCDSpeed(-1);
271 
272  QMutexLocker lock(&getCdioMutex());
273 
274  if (m_paranoia)
275  cdio_paranoia_free(m_paranoia), m_paranoia = nullptr;
276  if (m_device)
277  cdio_cddap_close(m_device), m_device = nullptr, m_cdio = nullptr;
278  if (m_cdio)
279  cdio_destroy(m_cdio), m_cdio = nullptr;
280 
281  if (m_outputBuf)
282  ::av_free(m_outputBuf), m_outputBuf = nullptr;
283 
284  m_inited = m_userStop = m_finish = false;
285  m_freq = m_bitrate = 0L;
287  m_chan = 0;
288  setOutput(nullptr);
289 }
290 
291 // private virtual
293 {
294  RunProlog();
295 
296  if (!m_inited)
297  {
298  RunEpilog();
299  return;
300  }
301 
303  // NB block scope required to prevent re-entrancy
304  {
305  DecoderEvent e(m_stat);
306  dispatch(e);
307  }
308 
309  // account for possible frame expansion in aobase (upmix, float conv)
310  const std::size_t thresh = m_bks * 6;
311 
312  while (!m_finish && !m_userStop)
313  {
314  if (m_seekTime >= +0.)
315  {
316  m_curPos = m_start + static_cast< lsn_t >(
317  (m_seekTime * kSamplesPerSec) / CD_FRAMESAMPLES);
318  if (m_paranoia)
319  {
320  QMutexLocker lock(&getCdioMutex());
321  cdio_paranoia_seek(m_paranoia, m_curPos, SEEK_SET);
322  }
323 
324  m_outputAt = 0;
325  m_seekTime = -1.;
326  }
327 
328  if (m_outputAt < m_bks)
329  {
330  while (m_outputAt < m_decodeBytes &&
331  !m_finish && !m_userStop && m_seekTime <= +0.)
332  {
333  if (m_curPos < m_end)
334  {
335  QMutexLocker lock(&getCdioMutex());
336  if (m_paranoia)
337  {
338  int16_t *cdbuffer = cdio_paranoia_read_limited(
339  m_paranoia, nullptr, 10);
340  if (cdbuffer)
341  memcpy(&m_outputBuf[m_outputAt],
342  cdbuffer, CDIO_CD_FRAMESIZE_RAW);
343  }
344  else
345  {
346  driver_return_code_t c = cdio_read_audio_sector(
347  m_cdio, &m_outputBuf[m_outputAt], m_curPos);
348  if (DRIVER_OP_SUCCESS != c)
349  {
350  LOG(VB_MEDIA, LOG_DEBUG,
351  QString("cdio_read_audio_sector(%1) error %2").
352  arg(m_curPos).arg(c));
353  memset( &m_outputBuf[m_outputAt],
354  0, CDIO_CD_FRAMESIZE_RAW);
355 
356  // stop if we got an error
357  m_userStop = true;
358  }
359  }
360 
361  m_outputAt += CDIO_CD_FRAMESIZE_RAW;
362  ++(m_curPos);
363  }
364  else
365  {
366  m_finish = true;
367  }
368  }
369  }
370 
371  if (!output())
372  continue;
373 
374  // Wait until we need to decode or supply more samples
375  uint fill = 0;
376  uint total = 0;
377  while (!m_finish && !m_userStop && m_seekTime <= +0.)
378  {
379  output()->GetBufferStatus(fill, total);
380  // Make sure we have decoded samples ready and that the
381  // audiobuffer is reasonably populated
382  if (fill < (thresh << 6))
383  break;
384  // Wait for half of the buffer to drain
385  ::usleep(output()->GetAudioBufferedTime().count()<<9);
386  }
387 
388  // write a block if there's sufficient space for it
389  if (!m_userStop &&
390  m_outputAt >= m_bks &&
391  fill <= total - thresh)
392  {
393  writeBlock();
394  }
395  }
396 
397  if (m_userStop)
398  m_inited = false;
399  else if (output())
400  {
401  // Drain our buffer
402  while (m_outputAt >= m_bks)
403  writeBlock();
404 
405  // Drain ao buffer
406  output()->Drain();
407  }
408 
409  if (m_finish)
411  else if (m_userStop)
413  else
415 
416  // NB block scope required to step onto next track
417  {
418  DecoderEvent e(m_stat);
419  dispatch(e);
420  }
421 
422  deinit();
423 
424  RunEpilog();
425 }
426 
427 //public
428 void CdDecoder::setCDSpeed(int speed)
429 {
430  QMutexLocker lock(&getCdioMutex());
431 
433  if (cdio)
434  {
435  driver_return_code_t c = cdio_set_speed(cdio, speed >= 0 ? speed : 1);
436  if (DRIVER_OP_SUCCESS != c)
437  {
438  LOG(VB_MEDIA, LOG_INFO,
439  QString("Error: cdio_set_speed('%1',%2) failed").
440  arg(m_deviceName).arg(speed));
441  }
442  }
443 }
444 
445 //public
447 {
448  QMutexLocker lock(&getCdioMutex());
449 
451  if (!cdio)
452  return 0;
453 
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));
457  else
458  tracks = -1;
459 
460  return tracks;
461 }
462 
463 //public
465 {
466  QMutexLocker lock(&getCdioMutex());
467 
469  if (!cdio)
470  return 0;
471 
472  int nAudio = 0;
473  const track_t last = cdio_get_last_track_num(cdio);
474  if (CDIO_INVALID_TRACK != last)
475  {
476  for (track_t t = cdio_get_first_track_num(cdio) ; t <= last; ++t)
477  {
478  if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, t))
479  ++nAudio;
480  }
481  LOG(VB_MEDIA, LOG_DEBUG, QString("getNumCDAudioTracks = %1").arg(nAudio));
482  }
483 
484  return nAudio;
485 }
486 
487 //public
489 {
490  m_setTrackNum = track;
491  return getMetadata();
492 }
493 
494 
495 // Create a TOC
496 static lsn_t s_lastAudioLsn;
497 
498 //virtual
500 {
501  QString artist;
502  QString album;
503  QString compilation_artist;
504  QString title;
505  QString genre;
506  int year = 0;
507  std::chrono::milliseconds length = 0s;
508  track_t tracknum = 0;
509 
510  if (-1 == m_setTrackNum)
511  tracknum = getURL().toUInt();
512  else
513  {
514  tracknum = m_setTrackNum;
515  setURL(QString("%1%2").arg(tracknum).arg(CDEXT));
516  }
517 
518  QMutexLocker lock(&getCdioMutex());
519 
521  if (!cdio)
522  return nullptr;
523 
524  const track_t lastTrack = cdio_get_last_track_num(cdio);
525  if (CDIO_INVALID_TRACK == lastTrack)
526  return nullptr;
527 
528  if (TRACK_FORMAT_AUDIO != cdio_get_track_format(cdio, tracknum))
529  return nullptr;
530 
531  // Assume disc changed if max LSN different
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)
536  {
537  s_totalSectors = totalSectors;
538  isDiscChanged = true;
539  }
540 
541  // NB cdio_get_track_last_lsn is unreliable for the last audio track
542  // of discs with data tracks beyond
543  lsn_t end = cdio_get_track_last_lsn(cdio, tracknum);
544  if (isDiscChanged)
545  {
546  const track_t audioTracks = getNumCDAudioTracks();
547  s_lastAudioLsn = cdio_get_track_last_lsn(cdio, audioTracks);
548 
549  if (audioTracks < lastTrack)
550  {
551  cdrom_drive_t *dev = cdio_cddap_identify_cdio(cdio, 0, nullptr);
552  if (nullptr != dev)
553  {
554  if (DRIVER_OP_SUCCESS == cdio_cddap_open(dev))
555  {
556  // NB this can be S L O W but is reliable
557  lsn_t end2 = cdio_cddap_track_lastsector(dev,
559  if (CDIO_INVALID_LSN != end2)
560  s_lastAudioLsn = end2;
561  }
562  cdio_cddap_close_no_free_cdio(dev);
563  }
564  }
565  }
566 
567  if (s_lastAudioLsn && s_lastAudioLsn < end)
568  end = s_lastAudioLsn;
569 
570  const lsn_t start = cdio_get_track_lsn(cdio, tracknum);
571  if (CDIO_INVALID_LSN != start && CDIO_INVALID_LSN != end)
572  {
573  length = std::chrono::milliseconds(((end - start + 1) * 1000 + CDIO_CD_FRAMES_PER_SEC/2) /
574  CDIO_CD_FRAMES_PER_SEC);
575  }
576 
577  bool isCompilation = false;
578 
579 // Disabled - cd-text access on discs without it is S L O W
580 #define CDTEXT 0 // NOLINT(cppcoreguidelines-macro-usage)
581 #if CDTEXT
582  static int s_iCdtext;
583  if (isDiscChanged)
584  s_iCdtext = -1;
585 
586  if (s_iCdtext)
587  {
588  // cdio_get_cdtext can't take >5 seconds on some CD's without cdtext
589  if (s_iCdtext < 0)
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)
594  {
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);
599  /* ISRC codes are 12 characters long, in the form CCXXXYYNNNNN
600  * CC = country code
601  * XXX = registrant e.g. BMG
602  * CC = year withou century
603  * NNNNN = unique ID
604  */
605  if (isrc && strlen(isrc) >= 7)
606  {
607  year = (isrc[5] - '0') * 10 + (isrc[6] - '0');
608  year += (year <= 30) ? 2000 : 1900;
609  }
610 
611  cdtext_destroy(cdtext);
612 
613  if (!title.isNull())
614  {
615  if (s_iCdtext < 0)
616  LOG(VB_MEDIA, LOG_INFO, "Found cdtext track title");
617  s_iCdtext = 1;
618 
619  // Get disc info
620  cdtext = cdio_get_cdtext(cdio, 0);
621  if (nullptr != cdtext)
622  {
623  compilation_artist = cdtext_get_const(
624  CDTEXT_PERFORMER, cdtext);
625  if (!compilation_artist.isEmpty() &&
626  artist != compilation_artist)
627  isCompilation = true;
628 
629  album = cdtext_get_const(CDTEXT_TITLE, cdtext);
630 
631  if (genre.isNull())
632  genre = cdtext_get_const(CDTEXT_GENRE, cdtext);
633 
634  cdtext_destroy(cdtext);
635  }
636  }
637  else
638  {
639  if (s_iCdtext < 0)
640  LOG(VB_MEDIA, LOG_INFO, "No cdtext title for track");
641  s_iCdtext = 0;
642  }
643  }
644  else
645  {
646  if (s_iCdtext < 0)
647  LOG(VB_MEDIA, LOG_INFO, "No cdtext");
648  s_iCdtext = 0;
649  }
650  }
651 
652  if (title.isEmpty() || artist.isEmpty() || album.isEmpty())
653 #endif // CDTEXT
654  {
655 #ifdef HAVE_MUSICBRAINZ
656  if (isDiscChanged)
657  {
658  // lazy load whole CD metadata
659  getMusicBrainz().queryForDevice(m_deviceName);
660  }
661  if (getMusicBrainz().hasMetadata(m_setTrackNum))
662  {
663  auto *metadata = getMusicBrainz().getMetadata(m_setTrackNum);
664  if (metadata)
665  {
666  metadata->setFilename(getURL());
667  return metadata;
668  }
669  }
670 #endif // HAVE_MUSICBRAINZ
671  }
672 
673  if (compilation_artist.toLower().left(7) == "various")
674  compilation_artist = tr("Various Artists");
675 
676  if (artist.isEmpty())
677  {
678  artist = compilation_artist;
679  compilation_artist.clear();
680  }
681 
682  if (title.isEmpty())
683  title = tr("Track %1").arg(tracknum);
684 
685  auto *m = new MusicMetadata(getURL(), artist, compilation_artist, album,
686  title, genre, year, tracknum, length);
687  if (m)
688  m->setCompilation(isCompilation);
689 
690  return m;
691 }
692 
693 #ifdef HAVE_MUSICBRAINZ
694 
695 MusicBrainz & CdDecoder::getMusicBrainz()
696 {
697  static MusicBrainz s_musicBrainz;
698  return s_musicBrainz;
699 }
700 
701 #endif // HAVE_MUSICBRAINZ
702 
703 
704 // pure virtual
705 bool CdDecoderFactory::supports(const QString &source) const
706 {
707  return (source.right(extension().length()).toLower() == extension());
708 }
709 
710 // pure virtual
711 const QString &CdDecoderFactory::extension() const
712 {
713  static QString s_ext(CDEXT);
714  return s_ext;
715 }
716 
717 // pure virtual
718 const QString &CdDecoderFactory::description() const
719 {
720  static QString s_desc(tr("Audio CD parser"));
721  return s_desc;
722 }
723 
724 // pure virtual
725 Decoder *CdDecoderFactory::create(const QString &file, AudioOutput *output, bool deletable)
726 {
727  if (deletable)
728  return new CdDecoder(file, this, output);
729 
730  static CdDecoder *s_decoder;
731  if (! s_decoder)
732  {
733  s_decoder = new CdDecoder(file, this, output);
734  }
735  else
736  {
737  s_decoder->setURL(file);
738  s_decoder->setOutput(output);
739  }
740 
741  return s_decoder;
742 }
743 
CdDecoder::getMetadata
MusicMetadata * getMetadata(void)
Definition: cddecoder.cpp:499
CdDecoder::m_setTrackNum
int m_setTrackNum
Definition: cddecoder.h:76
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
CdDecoder::m_seekTime
double m_seekTime
Definition: cddecoder.h:74
CdDecoder::m_bitrate
long m_bitrate
Definition: cddecoder.h:72
CdDecoder::m_decodeBytes
std::size_t m_decodeBytes
Definition: cddecoder.h:69
MusicBrainz
Definition: musicbrainz.h:13
s_mtx
static QMutex s_mtx
Definition: netstream.cpp:52
CdDecoderFactory::description
const QString & description() const override
Definition: cddecoder.cpp:718
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:27
CdDecoder::deinit
void deinit()
Definition: cddecoder.cpp:268
CdDecoder::getCdioMutex
static QRecursiveMutex & getCdioMutex()
Definition: cddecoder.cpp:139
CdDecoderFactory::create
Decoder * create(const QString &file, AudioOutput *output, bool deletable) override
Definition: cddecoder.cpp:725
MThread::usleep
static void usleep(std::chrono::microseconds time)
Definition: mthread.cpp:335
CdDecoder::writeBlock
void writeBlock()
Definition: cddecoder.cpp:121
VERBOSE_LEVEL_CHECK
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
CdDecoder::initialize
bool initialize() override
Definition: cddecoder.cpp:146
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:196
StCdioDevice::StCdioDevice
StCdioDevice(const QString &dev)
Definition: cddecoder.cpp:84
MusicMetadata
Definition: musicmetadata.h:80
DecoderFactory
Definition: decoder.h:117
build_compdb.file
file
Definition: build_compdb.py:55
StCdioDevice::StCdioDevice
StCdioDevice(const StCdioDevice &)
MythObservable::dispatch
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
Definition: mythobservable.cpp:73
StCdioDevice::m_cdio
CdIo_t * m_cdio
Definition: cddecoder.cpp:76
AudioOutput::Drain
virtual void Drain(void)=0
AudioSettings
Definition: audiosettings.h:28
cddecoder.h
StCdioDevice::operator=
StCdioDevice & operator=(const StCdioDevice &)
StCdioDevice
Definition: cddecoder.cpp:74
AudioOutput
Definition: audiooutput.h:26
CdDecoder::m_userStop
volatile bool m_userStop
Definition: cddecoder.h:57
Decoder
Definition: decoder.h:70
CdDecoder::seek
void seek(double pos) override
Definition: cddecoder.cpp:260
kSamplesPerSec
static constexpr long kSamplesPerSec
Definition: cddecoder.cpp:31
CdDecoder
Definition: cddecoder.h:24
CdDecoder::setCDSpeed
void setCDSpeed(int speed)
Definition: cddecoder.cpp:428
s_lastAudioLsn
static lsn_t s_lastAudioLsn
Definition: cddecoder.cpp:496
hardwareprofile.i18n.t
t
Definition: i18n.py:36
AudioOutput::SetSourceBitrate
virtual void SetSourceBitrate(int)
Definition: audiooutput.h:146
DecoderEvent
Definition: decoder.h:29
CdDecoder::m_outputAt
std::size_t m_outputAt
Definition: cddecoder.h:65
CdDecoder::m_bksFrames
std::size_t m_bksFrames
Definition: cddecoder.h:68
StCdioDevice::~StCdioDevice
~StCdioDevice()
Definition: cddecoder.cpp:85
CdDecoder::m_inited
volatile bool m_inited
Definition: cddecoder.h:56
CDEXT
static constexpr const char * CDEXT
Definition: cddecoder.cpp:30
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:209
CdDecoder::m_freq
long m_freq
Definition: cddecoder.h:71
Decoder::getURL
QString getURL(void) const
Definition: decoder.h:91
DecoderEvent::kStopped
static const Type kStopped
Definition: decoder.h:46
uint
unsigned int uint
Definition: compat.h:81
CdDecoder::~CdDecoder
~CdDecoder() override
Definition: cddecoder.cpp:98
CdDecoder::setDevice
void setDevice(const QString &dev)
Definition: cddecoder.cpp:104
Decoder::setURL
void setURL(const QString &url)
Definition: decoder.h:83
CdDecoder::getNumTracks
int getNumTracks()
Definition: cddecoder.cpp:446
CdDecoderFactory::supports
bool supports(const QString &source) const override
Definition: cddecoder.cpp:705
CdDecoder::CdDecoder
CdDecoder(const QString &file, DecoderFactory *d, AudioOutput *o)
Definition: cddecoder.cpp:91
AudioOutput::Reconfigure
virtual void Reconfigure(const AudioSettings &settings)=0
DecoderEvent::kFinished
static const Type kFinished
Definition: decoder.h:47
CdDecoder::m_stat
DecoderEvent::Type m_stat
Definition: cddecoder.h:63
CdDecoder::getNumCDAudioTracks
int getNumCDAudioTracks()
Definition: cddecoder.cpp:464
DecoderEvent::kDecoding
static const Type kDecoding
Definition: decoder.h:45
CdDecoder::run
void run() override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
Definition: cddecoder.cpp:292
CdDecoder::m_deviceName
QString m_deviceName
Definition: cddecoder.h:59
AudioOutput::GetBufferStatus
virtual void GetBufferStatus(uint &fill, uint &total)
Definition: audiooutput.h:151
constants.h
audiooutput.h
Decoder::setOutput
void setOutput(AudioOutput *o)
Definition: decoder.cpp:45
CdDecoder::m_bks
std::size_t m_bks
Definition: cddecoder.h:67
logger
static void logger(cdio_log_level_t level, const char *message)
Definition: cddecoder.cpp:34
mythcontext.h
CdDecoder::m_chan
int m_chan
Definition: cddecoder.h:73
Decoder::lock
virtual void lock(void)
Definition: decoder.h:85
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
Decoder::output
AudioOutput * output()
Definition: decoder.h:81
CdDecoderFactory::extension
const QString & extension() const override
Definition: cddecoder.cpp:711
CdDecoder::stop
void stop() override
Definition: cddecoder.cpp:115
output
#define output
Definition: synaesthesia.cpp:223
CdDecoder::m_trackNum
int m_trackNum
Definition: cddecoder.h:77
DecoderEvent::kError
static const Type kError
Definition: decoder.h:48
AudioOutput::PauseUntilBuffered
virtual void PauseUntilBuffered(void)=0
musicmetadata.h
CdDecoder::m_outputBuf
char * m_outputBuf
Definition: cddecoder.h:64
openCdio
static CdIo_t * openCdio(const QString &name)
Definition: cddecoder.cpp:54
CdDecoder::m_finish
bool m_finish
Definition: cddecoder.h:70