12#include "libmythbase/mythconfig.h"
20#define LOC QString("AOOSS: ")
47 QString message {
LOC + QString(
"Error opening audio device (%1").arg(
m_mainDevice) +
": " +
ENO};
49 LOG(VB_GENERAL, LOG_ERR, message);
55 while (
int rate = settings->GetNextRate())
58 if(ioctl(
m_audioFd, SNDCTL_DSP_SPEED, &rate2) >= 0
60 settings->AddSupportedRate(rate);
65 QString message {
LOC +
"Error retrieving formats" +
": " +
ENO};
67 LOG(VB_GENERAL, LOG_ERR, message);
73 int ofmt = AFMT_QUERY;
83 settings->AddSupportedFormat(fmt);
89 settings->setPassthrough(
static_cast<int>((
formats & AFMT_AC3) != 0) - 1);
92 for (
int i = 1; i <= 2; i++)
96 if (ioctl(
m_audioFd, SNDCTL_DSP_CHANNELS, &channel) >= 0 &&
99 settings->AddSupportedChannels(i);
116 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Opening OSS audio device '%1'.").arg(
m_mainDevice));
121 m_audioFd = open(device.constData(), O_WRONLY);
122 if (
m_audioFd < 0 && errno != EAGAIN && errno != EINTR)
126 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Something is currently using: %1.")
130 QString message {
LOC + QString(
"Error opening audio device (%1)")
133 LOG(VB_GENERAL, LOG_ERR, message);
142 QString message {QCoreApplication::translate(
"AudioOutputOSS",
"Error opening audio device (%1)")
145 LOG(VB_GENERAL, LOG_ERR, message);
146 message =
LOC + QString(
"Error opening audio device (%1)").arg(
m_mainDevice) +
": " +
ENO;
148 LOG(VB_GENERAL, LOG_ERR, message);
154 QString message {
LOC + QString(
"Error removing the O_NONBLOCK flag from audio device FD (%1)")
157 LOG(VB_GENERAL, LOG_ERR, message);
161 int format = AFMT_QUERY;
174#if defined(AFMT_AC3) && defined(SNDCTL_DSP_GETFMTS)
177 int format_support = 0;
178 if (!ioctl(
m_audioFd, SNDCTL_DSP_GETFMTS, &format_support) &&
179 (format_support & AFMT_AC3))
190 ioctl(
m_audioFd, SNDCTL_DSP_SETFMT, &format) < 0)
196 if (ioctl(
m_audioFd, SNDCTL_DSP_STEREO, &stereo) < 0 ||
198 ioctl(
m_audioFd, SNDCTL_DSP_SETFMT, &format) < 0)
204 QString message {
LOC + QString(
"Unable to set audio device (%1) to %2 kHz, %3 bits, %4 channels")
212 LOG(VB_GENERAL, LOG_ERR, message);
222 QString message {
LOC +
"Error retrieving card buffer size" +
": " +
ENO};
224 LOG(VB_GENERAL, LOG_ERR, message);
233 if (ioctl(
m_audioFd, SNDCTL_DSP_GETCAPS, &caps) == 0)
235 if (!(caps & DSP_CAP_REALTIME))
236 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"The audio device cannot report buffer state "
237 "accurately! audio/video sync will be bad, continuing...");
241 QString message {
LOC +
"Unable to get audio card capabilities" +
": " +
ENO};
243 LOG(VB_GENERAL, LOG_ERR, message);
273 uchar *tmpbuf = aubuf;
275 while ((written < size) &&
284 QString message {
LOC + QString(
"Error writing to audio device (%1)")
287 LOG(VB_GENERAL, LOG_ERR, message);
295 int soundcard_buffer=0;
297#ifdef SNDCTL_DSP_GETODELAY
298 if(ioctl(
m_audioFd, SNDCTL_DSP_GETODELAY, &soundcard_buffer) < 0)
299 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error retrieving buffering delay" +
": " +
ENO);
301 return soundcard_buffer;
309 if (device.toLower() ==
"software")
312 QByteArray dev = device.toLatin1();
313 m_mixerFd = open(dev.constData(), O_RDONLY);
317 if (controlLabel ==
"Master")
324 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unable to open mixer: '%1'").arg(device));
331 int tmpVol = (volume << 8) + volume;
332 int ret = ioctl(
m_mixerFd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);
334 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error Setting initial Master Volume") +
ENO);
337 tmpVol = (volume << 8) + volume;
338 ret = ioctl(
m_mixerFd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);
340 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error setting initial PCM Volume") +
ENO);
364 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error reading volume for channel %1").arg(channel));
369 volume = tmpVol & 0xff;
370 else if (channel == 1)
371 volume = (tmpVol >> 8) & 0xff;
373 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid channel. Only stereo volume supported");
383 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error setting channel %1. Only 2 ch volume supported")
400 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error setting volume on channel %1").arg(channel));
void KillAudio(void)
Kill the output thread and cleanup.
void Reconfigure(const AudioSettings &settings) override
(Re)Configure AudioOutputBase
AudioFormat m_outputFormat
int m_outputBytesPerFrame
long m_soundcardBufferSize
void InitSettings(const AudioSettings &settings)
void WriteAudio(unsigned char *aubuf, int size) override
~AudioOutputOSS() override
int GetVolumeChannel(int channel) const override
void CloseDevice(void) override
int GetBufferedOnSoundcard(void) const override
Return the size in bytes of frames currently in the audio buffer adjusted with the audio playback lat...
AudioOutputOSS(const AudioSettings &settings)
bool OpenDevice(void) override
void SetVolumeChannel(int channel, int volume) override
AudioOutputSettings * GetOutputSettings(bool digital) override
static int FormatToBits(AudioFormat format)
void dispatchError(const QString &e)
bool m_init
If set to false, AudioOutput instance will not try to initially open the audio device.
static void usleep(std::chrono::microseconds time)
QString GetSetting(const QString &key, const QString &defaultval="")
int GetNumSetting(const QString &key, int defaultval=0)
A QElapsedTimer based timer to replace use of QTime as a timer.
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
void start(void)
starts measuring elapsed time.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define ENO
This can be appended to the LOG args with "+".
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
def write(text, progress=True)
static eu8 clamp(eu8 value, eu8 low, eu8 high)
const std::array< const std::string, 8 > formats