21#define LOC QString("AOOSS: ")
48 QString message {
LOC + QString(
"Error opening audio device (%1").arg(
m_mainDevice) +
": " +
ENO};
50 LOG(VB_GENERAL, LOG_ERR, message);
56 while (
int rate = settings->GetNextRate())
59 if(ioctl(
m_audioFd, SNDCTL_DSP_SPEED, &rate2) >= 0
61 settings->AddSupportedRate(rate);
66 QString message {
LOC +
"Error retrieving formats" +
": " +
ENO};
68 LOG(VB_GENERAL, LOG_ERR, message);
74 int ofmt = AFMT_QUERY;
84 settings->AddSupportedFormat(fmt);
90 settings->setPassthrough(
static_cast<int>((
formats & AFMT_AC3) != 0) - 1);
93 for (
int i = 1; i <= 2; i++)
97 if (ioctl(
m_audioFd, SNDCTL_DSP_CHANNELS, &channel) >= 0 &&
100 settings->AddSupportedChannels(i);
117 LOG(VB_AUDIO, LOG_INFO,
LOC + QString(
"Opening OSS audio device '%1'.").arg(
m_mainDevice));
122 m_audioFd = open(device.constData(), O_WRONLY);
123 if (
m_audioFd < 0 && errno != EAGAIN && errno != EINTR)
127 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Something is currently using: %1.")
131 QString message {
LOC + QString(
"Error opening audio device (%1)")
134 LOG(VB_GENERAL, LOG_ERR, message);
138 std::this_thread::sleep_for(50us);
143 QString message {QCoreApplication::translate(
"AudioOutputOSS",
"Error opening audio device (%1)")
146 LOG(VB_GENERAL, LOG_ERR, message);
147 message =
LOC + QString(
"Error opening audio device (%1)").arg(
m_mainDevice) +
": " +
ENO;
149 LOG(VB_GENERAL, LOG_ERR, message);
155 QString message {
LOC + QString(
"Error removing the O_NONBLOCK flag from audio device FD (%1)")
158 LOG(VB_GENERAL, LOG_ERR, message);
162 int format = AFMT_QUERY;
175#if defined(AFMT_AC3) && defined(SNDCTL_DSP_GETFMTS)
178 int format_support = 0;
179 if (!ioctl(
m_audioFd, SNDCTL_DSP_GETFMTS, &format_support) &&
180 (format_support & AFMT_AC3))
191 ioctl(
m_audioFd, SNDCTL_DSP_SETFMT, &format) < 0)
197 if (ioctl(
m_audioFd, SNDCTL_DSP_STEREO, &stereo) < 0 ||
199 ioctl(
m_audioFd, SNDCTL_DSP_SETFMT, &format) < 0)
205 QString message {
LOC + QString(
"Unable to set audio device (%1) to %2 kHz, %3 bits, %4 channels")
213 LOG(VB_GENERAL, LOG_ERR, message);
223 QString message {
LOC +
"Error retrieving card buffer size" +
": " +
ENO};
225 LOG(VB_GENERAL, LOG_ERR, message);
234 if (ioctl(
m_audioFd, SNDCTL_DSP_GETCAPS, &caps) == 0)
236 if (!(caps & DSP_CAP_REALTIME))
237 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"The audio device cannot report buffer state "
238 "accurately! audio/video sync will be bad, continuing...");
242 QString message {
LOC +
"Unable to get audio card capabilities" +
": " +
ENO};
244 LOG(VB_GENERAL, LOG_ERR, message);
274 uchar *tmpbuf = aubuf;
276 while ((written < size) &&
285 QString message {
LOC + QString(
"Error writing to audio device (%1)")
288 LOG(VB_GENERAL, LOG_ERR, message);
296 int soundcard_buffer=0;
298#ifdef SNDCTL_DSP_GETODELAY
299 if(ioctl(
m_audioFd, SNDCTL_DSP_GETODELAY, &soundcard_buffer) < 0)
300 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Error retrieving buffering delay" +
": " +
ENO);
302 return soundcard_buffer;
310 if (device.toLower() ==
"software")
313 QByteArray dev = device.toLatin1();
314 m_mixerFd = open(dev.constData(), O_RDONLY);
318 if (controlLabel ==
"Master")
325 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unable to open mixer: '%1'").arg(device));
332 int tmpVol = (volume << 8) + volume;
333 int ret = ioctl(
m_mixerFd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);
335 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error Setting initial Master Volume") +
ENO);
338 tmpVol = (volume << 8) + volume;
339 ret = ioctl(
m_mixerFd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);
341 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error setting initial PCM Volume") +
ENO);
365 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error reading volume for channel %1").arg(channel));
370 volume = tmpVol & 0xff;
371 else if (channel == 1)
372 volume = (tmpVol >> 8) & 0xff;
374 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid channel. Only stereo volume supported");
384 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error setting channel %1. Only 2 ch volume supported")
401 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Error setting volume on channel %1").arg(channel));
static const std::array< const std::string, 8 > formats
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.
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)