1#include "libmythbase/mythconfig.h"
34#if CONFIG_AUDIO_PULSEOUTPUT
46#include "libavcodec/avcodec.h"
51#define LOC QString("AO: ")
61 const QString &main_device,
const QString &passthru_device,
62 AudioFormat format,
int channels, AVCodecID codec,
int samplerate,
67 main_device, passthru_device, format, channels, codec, samplerate,
68 source, set_initial_vol, passthru, upmixer_startup, custom);
74 const QString &main_device,
const QString &passthru_device,
79 return OpenAudio(settings, willsuspendpa);
83 [[maybe_unused]]
bool willsuspendpa)
90 willsuspendpa =
false;
93 bool pulsestatus =
false;
96 static bool warned =
false;
100 LOG(VB_GENERAL, LOG_WARNING,
101 "WARNING: ***Pulse Audio is running***");
108 if (main_device.startsWith(
"PulseAudio:"))
110#if CONFIG_AUDIO_PULSEOUTPUT
113 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to PulseAudio "
114 "but PulseAudio support is not compiled in!");
118 if (main_device.startsWith(
"NULL"))
123#if CONFIG_AUDIO_PULSE
126 bool ispulse =
false;
130 if (main_device.startsWith(
"ALSA:"))
132 QString device_name = main_device;
134 device_name.remove(0, 5);
135 QMap<QString, QString> *alsadevs =
137 if (!alsadevs->empty() && alsadevs->contains(device_name))
139 if (alsadevs->value(device_name).contains(
"pulse",
140 Qt::CaseInsensitive))
148 if (main_device.contains(
"pulse", Qt::CaseInsensitive))
159 if (main_device.startsWith(
"ALSA:"))
165 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to an ALSA device "
166 "but ALSA support is not compiled in!");
169 else if (main_device.startsWith(
"JACK:"))
175 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to a JACK device "
176 "but JACK support is not compiled in!");
179 else if (main_device.startsWith(
"DirectX:"))
184 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to DirectX device "
185 "but DirectX support is not compiled in!");
188 else if (main_device.startsWith(
"Windows:"))
193 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to a Windows "
194 "device but Windows support is not compiled "
198 else if (main_device.startsWith(
"OpenSLES:"))
203 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to a OpenSLES "
204 "device but Android support is not compiled "
208 else if (main_device.startsWith(
"AudioTrack:"))
213 LOG(VB_GENERAL, LOG_ERR,
"Audio output device is set to AudioTrack "
214 "device but Android support is not compiled "
223#elif defined(Q_OS_DARWIN)
232 LOG(VB_GENERAL, LOG_CRIT,
"No useable audio output driver found.");
233 LOG(VB_GENERAL, LOG_ERR,
"Don't disable OSS support unless you're "
234 "not running on Linux.");
235#if CONFIG_AUDIO_PULSE
241#if CONFIG_AUDIO_PULSE
249#if CONFIG_AUDIO_PULSE
294 LOG(VB_GENERAL, LOG_WARNING,
"AudioOutput Warning: " +
m_lastWarn);
308 QString &name,
const QString &desc,
bool willsuspendpa)
322 QString msg = tr(
"Invalid or unuseable audio device");
326 QString capabilities = desc;
332 capabilities += tr(
" (%1 connected to %2)")
338 capabilities += tr(
" (No connection detected)");
343 switch (max_channels)
356 capabilities += tr(
"\nDevice supports up to %1")
371 (
static_cast<int>(aosettings.
canLPCM()) << 0) |
372 (
static_cast<int>(aosettings.
canAC3()) << 1) |
373 (
static_cast<int>(aosettings.
canDTS()) << 2);
374 static const std::array<const std::string,3> s_typeNames {
"LPCM",
"AC3",
"DTS" };
378 capabilities += QObject::tr(
" (guessing: ");
379 bool found_one =
false;
380 for (
unsigned int i = 0; i < 3; i++)
382 if ((mask & (1 << i)) != 0)
385 capabilities +=
", ";
386 capabilities += QString::fromStdString(s_typeNames[i]);
390 capabilities += QString(
")");
394 LOG(VB_AUDIO, LOG_INFO, QString(
"Found %1 (%2)") .arg(name, capabilities));
396 adc->m_settings = aosettings;
404 QFileInfoList entries = dir.entryInfoList();
405 for (
const auto& fi : std::as_const(entries))
407 QString name = fi.absoluteFilePath();
408 QString desc = AudioOutput::tr(
"OSS device");
423#if CONFIG_AUDIO_PULSE
430 if (!alsadevs->empty())
432 for (
auto i = alsadevs->cbegin(); i != alsadevs->cend(); ++i)
434 const QString& key = i.key();
435 const QString& desc = i.value();
436 QString devname = QString(
"ALSA:%1").arg(key);
449 QDir dev(
"/dev",
"dsp*", QDir::Name, QDir::System);
451 dev.setNameFilters(QStringList(
"adsp*"));
454 dev.setPath(
"/dev/sound");
457 dev.setNameFilters(QStringList(
"dsp*"));
459 dev.setNameFilters(QStringList(
"adsp*"));
466 QString name =
"JACK:";
467 QString desc = tr(
"Use JACK default sound server.");
482 for (QMap<QString, QString>::const_iterator i = devs->begin();
483 i != devs->end(); ++i)
485 QString key = i.key();
486 QString desc = i.value();
487 QString devname = QString(
"CoreAudio:%1").arg(key);
497 QString name =
"CoreAudio:Default Output Device";
498 QString desc = tr(
"CoreAudio default output");
509 QString name =
"Windows:";
510 QString desc =
"Windows default output";
520 if (!dxdevs->empty())
522 for (QMap<int, QString>::const_iterator i = dxdevs->begin();
523 i != dxdevs->end(); ++i)
525 QString devdesc = i.value();
526 QString devname = QString(
"DirectX:%1").arg(devdesc);
539#if CONFIG_AUDIO_PULSE
544#if CONFIG_AUDIO_PULSEOUTPUT
546 QString name =
"PulseAudio:default";
547 QString desc = tr(
"PulseAudio default sound server.");
559 QString name =
"OpenSLES:";
560 QString desc = tr(
"OpenSLES default output. Stereo support only.");
569 QString name =
"AudioTrack:";
570 QString desc = tr(
"Android AudioTrack output. Supports surround sound.");
580 QString name =
"NULL";
581 QString desc =
"NULL device";
599 uint8_t *buffer,
int &data_size,
602 bool got_frame =
false;
610 return AVERROR(ENOMEM);
624 int ret = avcodec_receive_frame(ctx,
m_frame);
627 if (ret == AVERROR(EAGAIN))
630 ret = avcodec_send_packet(ctx, pkt);
631 if (ret == AVERROR(EAGAIN))
636 LOG(VB_AUDIO, LOG_ERR,
LOC +
637 QString(
"audio decode error: %1 (%2)")
649 LOG(VB_AUDIO, LOG_DEBUG,
LOC +
650 QString(
"audio decode, no frame decoded (%1)").arg(ret));
654 auto format = (AVSampleFormat)
m_frame->format;
658 data_size =
m_frame->nb_samples *
m_frame->ch_layout.nb_channels * av_get_bytes_per_sample(format);
662 uint8_t* src =
nullptr;
664 if (av_sample_fmt_is_planar(format))
669 (
const uint8_t **)
m_frame->extended_data,
675 src =
m_frame->extended_data[0];
678 uint8_t* transit = buffer;
684 transit = (uint8_t*)av_malloc(data_size * av_get_bytes_per_sample(ctx->sample_fmt)
688 LOG(VB_AUDIO, LOG_ERR,
LOC +
689 QString(
"audio decode, out of memory"));
696 data_size = converter.
Process(transit, src, data_size,
true);
698 if (transit != buffer)
void InterleaveSamples(int channels, uint8_t *output, const uint8_t *const *input, int data_size)
int Process(void *out, const void *in, int bytes, bool noclip=false)
Process Parameters: out : destination buffer where converted samples will be copied in : source buffe...
static QMap< QString, QString > * GetDevices(const char *type)
Implements Core Audio (Mac OS X Hardware Abstraction Layer) output.
static QMap< QString, QString > * GetDevices(const char *type=nullptr)
static QMap< int, QString > * GetDXDevices(void)
eld & getELD(void)
retrieve ELD data
static int SampleSize(AudioFormat format)
bool canLPCM() const
return true if device supports multichannels PCM (deprecated, see canFeature())
bool canAC3() const
return true if device can or may support AC3 (deprecated, see canFeature())
int BestSupportedChannelsELD()
Reports best supported channel number, restricted to ELD range.
bool hasELD() const
get the ELD flag
static AudioFormat AVSampleFormatToFormat(AVSampleFormat format, int bits=0)
Return AVSampleFormat closest equivalent to AudioFormat.
bool canDTS() const
return true if device can or may support DTS (deprecated, see canFeature())
int canPassthrough() const
bool IsInvalid() const
return true if class instance is marked invalid.
static AudioOutput * OpenAudio(const QString &main_device, const QString &passthru_device, AudioFormat format, int channels, AVCodecID codec, int samplerate, AudioOutputSource source, bool set_initial_vol, bool passthru, int upmixer_startup=0, AudioOutputSettings *custom=nullptr)
static ADCVect * GetOutputList(void)
virtual AudioOutputSettings * GetOutputSettingsUsers(bool digital=true)
QVector< AudioDeviceConfig > ADCVect
void SilentError(const QString &msg)
void Error(const QString &msg)
virtual int DecodeAudio(AVCodecContext *ctx, uint8_t *buffer, int &data_size, const AVPacket *pkt)
Utility routine.
virtual bool CanPassthrough(int samplerate, int channels, AVCodecID codec, int profile) const
static AudioDeviceConfig * GetAudioDeviceConfig(QString &name, const QString &desc, bool willsuspendpa=false)
virtual AudioOutputSettings * GetOutputSettingsCleaned(bool digital=true)
void Warn(const QString &msg)
virtual uint32_t CanProcess(void)
virtual void SetStretchFactor(float factor)
static void Cleanup(void)
void TrimDeviceType(void)
void FixPassThrough(void)
void error(const QString &e)
static bool Suspend(enum PulseAction action)
QString codecs_desc() const
QString connection_name() const
QString product_name() const
char * av_make_error_stdstring(std::string &errbuf, int errnum)
A C++ equivalent to av_make_error_string.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
bool IsPulseAudioRunning(void)
Is A/V Sync destruction daemon is running on this host?
uint fillSelectionsFromDir(const QDir &dir, uint minor_min, uint minor_max, const QString &card, const QRegularExpression &driver, bool allow_duplicates, V2CaptureDeviceList *pList, const QString &cardType)