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