oss: cleanup and unification

Audio and record initializations are unified by providing helper functions for
opening the audio device and for setting the device parameters. The ioctl calls
are properly checked for errors and log an appropriate error message. The init
fails if the requested parameters are not supported by the device, i.e. 44.1kHz
16bit stereo for playback. This provides consistent behavior with all the other
audio backends.
This commit is contained in:
Stefan Schlosser 2024-11-14 02:36:20 +01:00 committed by flyinghead
parent c4d77165a6
commit 7531f5df20
1 changed files with 76 additions and 41 deletions

View File

@ -10,29 +10,87 @@ class OSSAudioBackend : public AudioBackend
int audioFD = -1;
int recordFD = -1;
static int openDevice(int flags)
{
const char* path = "/dev/dsp";
int fd = open(path, flags);
if (fd < 0)
ERROR_LOG(AUDIO, "OSS: open(%s) failed: %s", path, strerror(errno));
return fd;
}
static bool setRate(int fd, int rate)
{
int tmp = rate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &tmp) < 0)
{
ERROR_LOG(AUDIO, "OSS: ioctl(SNDCTL_DSP_SPEED) failed: %s", strerror(errno));
return false;
}
if (tmp != rate)
{
ERROR_LOG(AUDIO, "OSS: sample rate unsupported: %d => %d", rate, tmp);
return false;
}
return true;
}
static bool setChannels(int fd, int channels)
{
int tmp = channels;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &tmp) < 0)
{
ERROR_LOG(AUDIO, "OSS: ioctl(SNDCTL_DSP_CHANNELS) failed: %s", strerror(errno));
return false;
}
if (tmp != channels)
{
ERROR_LOG(AUDIO, "OSS: channels unsupported: %d => %d", channels, tmp);
return false;
}
return true;
}
static bool setFormat(int fd, int format)
{
int tmp = format;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &tmp) < 0)
{
ERROR_LOG(AUDIO, "OSS: ioctl(SNDCTL_DSP_SETFMT) failed: %s", strerror(errno));
return false;
}
if (tmp != format)
{
ERROR_LOG(AUDIO, "OSS: sample format unsupported: %#.8x => %#.8x", format, tmp);
return false;
}
return true;
}
public:
OSSAudioBackend()
: AudioBackend("oss", "Open Sound System") {}
bool init() override
{
audioFD = open("/dev/dsp", O_WRONLY);
if (audioFD < 0)
audioFD = openDevice(O_WRONLY);
if (audioFD < 0 || !setRate(audioFD, 44100) || !setChannels(audioFD, 2) || !setFormat(audioFD, AFMT_S16_LE))
{
WARN_LOG(AUDIO, "Couldn't open /dev/dsp.");
term();
return false;
}
INFO_LOG(AUDIO, "sound enabled, dsp opened for write");
int tmp=44100;
int err_ret;
err_ret=ioctl(audioFD,SNDCTL_DSP_SPEED,&tmp);
INFO_LOG(AUDIO, "set Frequency to %i, return %i (rate=%i)", 44100, err_ret, tmp);
int channels=2;
err_ret=ioctl(audioFD, SNDCTL_DSP_CHANNELS, &channels);
INFO_LOG(AUDIO, "set dsp to stereo (%i => %i)", channels, err_ret);
int format=AFMT_S16_LE;
err_ret=ioctl(audioFD, SNDCTL_DSP_SETFMT, &format);
INFO_LOG(AUDIO, "set dsp to %s audio (%i/%i => %i)", "16bits signed", AFMT_S16_LE, format, err_ret);
return true;
}
@ -54,34 +112,11 @@ public:
bool initRecord(u32 sampling_freq) override
{
recordFD = open("/dev/dsp", O_RDONLY);
if (recordFD < 0)
recordFD = openDevice(O_RDONLY);
if (recordFD < 0 || !setRate(recordFD, sampling_freq) || !setChannels(recordFD, 1) || !setFormat(recordFD, AFMT_S16_NE /* Native 16 bits */ ))
{
INFO_LOG(AUDIO, "OSS: can't open default audio capture device");
return false;
}
int tmp = AFMT_S16_NE; // Native 16 bits
if (ioctl(recordFD, SNDCTL_DSP_SETFMT, &tmp) == -1 || tmp != AFMT_S16_NE)
{
INFO_LOG(AUDIO, "OSS: can't set sample format");
close(recordFD);
recordFD = -1;
return false;
}
tmp = 1;
if (ioctl(recordFD, SNDCTL_DSP_CHANNELS, &tmp) == -1)
{
INFO_LOG(AUDIO, "OSS: can't set channel count");
close(recordFD);
recordFD = -1;
return false;
}
tmp = sampling_freq;
if (ioctl(recordFD, SNDCTL_DSP_SPEED, &tmp) == -1)
{
INFO_LOG(AUDIO, "OSS: can't set sample rate");
close(recordFD);
recordFD = -1;
termRecord();
return false;
}