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