From: Kővágó, Zoltán <dirty.ice.hu(a)gmail.com>
Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu(a)gmail.com>
Message-id:
31c899f2f78e40fbc01f563ee4829c98debb68db.1552083282.git.DirtY.iCE.hu(a)gmail.com
Signed-off-by: Gerd Hoffmann <kraxel(a)redhat.com>
---
audio/audio_legacy.c | 32 +++++++++
audio/ossaudio.c | 161 ++++++++++++++-----------------------------
2 files changed, 83 insertions(+), 110 deletions(-)
diff --git a/audio/audio_legacy.c b/audio/audio_legacy.c
index bf326bd36060..94f95bbc7318 100644
--- a/audio/audio_legacy.c
+++ b/audio/audio_legacy.c
@@ -219,6 +219,34 @@ static void handle_dsound(Audiodev *dev)
dev->u.dsound.in);
}
+/* OSS */
+static void handle_oss_per_direction(
+ AudiodevOssPerDirectionOptions *opdo, const char *try_poll_env,
+ const char *dev_env)
+{
+ get_bool(try_poll_env, &opdo->try_poll, &opdo->has_try_poll);
+ get_str(dev_env, &opdo->dev, &opdo->has_dev);
+
+ get_bytes_to_usecs("QEMU_OSS_FRAGSIZE",
+ &opdo->buffer_length, &opdo->has_buffer_length,
+ qapi_AudiodevOssPerDirectionOptions_base(opdo));
+ get_int("QEMU_OSS_NFRAGS", &opdo->buffer_count,
+ &opdo->has_buffer_count);
+}
+
+static void handle_oss(Audiodev *dev)
+{
+ AudiodevOssOptions *oopt = &dev->u.oss;
+ handle_oss_per_direction(oopt->in, "QEMU_AUDIO_ADC_TRY_POLL",
+ "QEMU_OSS_ADC_DEV");
+ handle_oss_per_direction(oopt->out, "QEMU_AUDIO_DAC_TRY_POLL",
+ "QEMU_OSS_DAC_DEV");
+
+ get_bool("QEMU_OSS_MMAP", &oopt->try_mmap,
&oopt->has_try_mmap);
+ get_bool("QEMU_OSS_EXCLUSIVE", &oopt->exclusive,
&oopt->has_exclusive);
+ get_int("QEMU_OSS_POLICY", &oopt->dsp_policy,
&oopt->has_dsp_policy);
+}
+
/* general */
static void handle_per_direction(
AudiodevPerDirectionOptions *pdo, const char *prefix)
@@ -272,6 +300,10 @@ static AudiodevListEntry *legacy_opt(const char *drvname)
handle_dsound(e->dev);
break;
+ case AUDIODEV_DRIVER_OSS:
+ handle_oss(e->dev);
+ break;
+
default:
break;
}
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index e0cadbef29df..fc28981a3972 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -37,16 +37,6 @@
#define USE_DSP_POLICY
#endif
-typedef struct OSSConf {
- int try_mmap;
- int nfrags;
- int fragsize;
- const char *devpath_out;
- const char *devpath_in;
- int exclusive;
- int policy;
-} OSSConf;
-
typedef struct OSSVoiceOut {
HWVoiceOut hw;
void *pcm_buf;
@@ -56,7 +46,7 @@ typedef struct OSSVoiceOut {
int fragsize;
int mmapped;
int pending;
- OSSConf *conf;
+ Audiodev *dev;
} OSSVoiceOut;
typedef struct OSSVoiceIn {
@@ -65,12 +55,12 @@ typedef struct OSSVoiceIn {
int fd;
int nfrags;
int fragsize;
- OSSConf *conf;
+ Audiodev *dev;
} OSSVoiceIn;
struct oss_params {
int freq;
- AudioFormat fmt;
+ int fmt;
int nchannels;
int nfrags;
int fragsize;
@@ -262,19 +252,25 @@ static int oss_get_version (int fd, int *version, const char *typ)
}
#endif
-static int oss_open (int in, struct oss_params *req,
- struct oss_params *obt, int *pfd, OSSConf* conf)
+static int oss_open(int in, struct oss_params *req, audsettings *as,
+ struct oss_params *obt, int *pfd, Audiodev *dev)
{
+ AudiodevOssOptions *oopts = &dev->u.oss;
+ AudiodevOssPerDirectionOptions *opdo = in ? oopts->in : oopts->out;
int fd;
- int oflags = conf->exclusive ? O_EXCL : 0;
+ int oflags = (oopts->has_exclusive && oopts->exclusive) ? O_EXCL : 0;
audio_buf_info abinfo;
int fmt, freq, nchannels;
int setfragment = 1;
- const char *dspname = in ? conf->devpath_in : conf->devpath_out;
+ const char *dspname = opdo->has_dev ? opdo->dev : "/dev/dsp";
const char *typ = in ? "ADC" : "DAC";
+#ifdef USE_DSP_POLICY
+ int policy = oopts->has_dsp_policy ? oopts->dsp_policy : 5;
+#endif
/* Kludge needed to have working mmap on Linux */
- oflags |= conf->try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
+ oflags |= (oopts->has_try_mmap && oopts->try_mmap) ?
+ O_RDWR : (in ? O_RDONLY : O_WRONLY);
fd = open (dspname, oflags | O_NONBLOCK);
if (-1 == fd) {
@@ -285,6 +281,9 @@ static int oss_open (int in, struct oss_params *req,
freq = req->freq;
nchannels = req->nchannels;
fmt = req->fmt;
+ req->nfrags = opdo->has_buffer_count ? opdo->buffer_count : 4;
+ req->fragsize = audio_buffer_bytes(
+ qapi_AudiodevOssPerDirectionOptions_base(opdo), as, 23220);
if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
oss_logerr2 (errno, typ, "Failed to set sample size %d\n",
req->fmt);
@@ -308,18 +307,18 @@ static int oss_open (int in, struct oss_params *req,
}
#ifdef USE_DSP_POLICY
- if (conf->policy >= 0) {
+ if (policy >= 0) {
int version;
if (!oss_get_version (fd, &version, typ)) {
trace_oss_version(version);
if (version >= 0x040000) {
- int policy = conf->policy;
- if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
+ int policy2 = policy;
+ if (ioctl(fd, SNDCTL_DSP_POLICY, &policy2)) {
oss_logerr2 (errno, typ,
"Failed to set timing policy to %d\n",
- conf->policy);
+ policy);
goto err;
}
setfragment = 0;
@@ -502,17 +501,16 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
int fd;
AudioFormat effective_fmt;
struct audsettings obt_as;
- OSSConf *conf = drv_opaque;
+ Audiodev *dev = drv_opaque;
+ AudiodevOssOptions *oopts = &dev->u.oss;
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
- req.fragsize = conf->fragsize;
- req.nfrags = conf->nfrags;
- if (oss_open (0, &req, &obt, &fd, conf)) {
+ if (oss_open(0, &req, as, &obt, &fd, dev)) {
return -1;
}
@@ -539,7 +537,7 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
oss->mmapped = 0;
- if (conf->try_mmap) {
+ if (oopts->has_try_mmap && oopts->try_mmap) {
oss->pcm_buf = mmap (
NULL,
hw->samples << hw->info.shift,
@@ -597,7 +595,7 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as,
}
oss->fd = fd;
- oss->conf = conf;
+ oss->dev = dev;
return 0;
}
@@ -605,16 +603,12 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
int trig;
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+ AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out;
switch (cmd) {
case VOICE_ENABLE:
{
- va_list ap;
- int poll_mode;
-
- va_start (ap, cmd);
- poll_mode = va_arg (ap, int);
- va_end (ap);
+ bool poll_mode = opdo->try_poll;
ldebug ("enabling voice\n");
if (poll_mode) {
@@ -669,16 +663,14 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void
*drv_opaque)
int fd;
AudioFormat effective_fmt;
struct audsettings obt_as;
- OSSConf *conf = drv_opaque;
+ Audiodev *dev = drv_opaque;
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
- req.fragsize = conf->fragsize;
- req.nfrags = conf->nfrags;
- if (oss_open (1, &req, &obt, &fd, conf)) {
+ if (oss_open(1, &req, as, &obt, &fd, dev)) {
return -1;
}
@@ -712,7 +704,7 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void
*drv_opaque)
}
oss->fd = fd;
- oss->conf = conf;
+ oss->dev = dev;
return 0;
}
@@ -803,16 +795,12 @@ static int oss_read (SWVoiceIn *sw, void *buf, int size)
static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
OSSVoiceIn *oss = (OSSVoiceIn *) hw;
+ AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out;
switch (cmd) {
case VOICE_ENABLE:
{
- va_list ap;
- int poll_mode;
-
- va_start (ap, cmd);
- poll_mode = va_arg (ap, int);
- va_end (ap);
+ bool poll_mode = opdo->try_poll;
if (poll_mode) {
oss_poll_in (hw);
@@ -832,82 +820,36 @@ static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
return 0;
}
-static OSSConf glob_conf = {
- .try_mmap = 0,
- .nfrags = 4,
- .fragsize = 4096,
- .devpath_out = "/dev/dsp",
- .devpath_in = "/dev/dsp",
- .exclusive = 0,
- .policy = 5
-};
+static void oss_init_per_direction(AudiodevOssPerDirectionOptions *opdo)
+{
+ if (!opdo->has_try_poll) {
+ opdo->try_poll = true;
+ opdo->has_try_poll = true;
+ }
+}
static void *oss_audio_init(Audiodev *dev)
{
- OSSConf *conf = g_malloc(sizeof(OSSConf));
- *conf = glob_conf;
+ AudiodevOssOptions *oopts;
+ assert(dev->driver == AUDIODEV_DRIVER_OSS);
- if (access(conf->devpath_in, R_OK | W_OK) < 0 ||
- access(conf->devpath_out, R_OK | W_OK) < 0) {
- g_free(conf);
+ oopts = &dev->u.oss;
+ oss_init_per_direction(oopts->in);
+ oss_init_per_direction(oopts->out);
+
+ if (access(oopts->in->has_dev ? oopts->in->dev : "/dev/dsp",
+ R_OK | W_OK) < 0 ||
+ access(oopts->out->has_dev ? oopts->out->dev : "/dev/dsp",
+ R_OK | W_OK) < 0) {
return NULL;
}
- return conf;
+ return dev;
}
static void oss_audio_fini (void *opaque)
{
- g_free(opaque);
}
-static struct audio_option oss_options[] = {
- {
- .name = "FRAGSIZE",
- .tag = AUD_OPT_INT,
- .valp = &glob_conf.fragsize,
- .descr = "Fragment size in bytes"
- },
- {
- .name = "NFRAGS",
- .tag = AUD_OPT_INT,
- .valp = &glob_conf.nfrags,
- .descr = "Number of fragments"
- },
- {
- .name = "MMAP",
- .tag = AUD_OPT_BOOL,
- .valp = &glob_conf.try_mmap,
- .descr = "Try using memory mapped access"
- },
- {
- .name = "DAC_DEV",
- .tag = AUD_OPT_STR,
- .valp = &glob_conf.devpath_out,
- .descr = "Path to DAC device"
- },
- {
- .name = "ADC_DEV",
- .tag = AUD_OPT_STR,
- .valp = &glob_conf.devpath_in,
- .descr = "Path to ADC device"
- },
- {
- .name = "EXCLUSIVE",
- .tag = AUD_OPT_BOOL,
- .valp = &glob_conf.exclusive,
- .descr = "Open device in exclusive mode (vmix won't work)"
- },
-#ifdef USE_DSP_POLICY
- {
- .name = "POLICY",
- .tag = AUD_OPT_INT,
- .valp = &glob_conf.policy,
- .descr = "Set the timing policy of the device, -1 to use fragment
mode",
- },
-#endif
- { /* End of list */ }
-};
-
static struct audio_pcm_ops oss_pcm_ops = {
.init_out = oss_init_out,
.fini_out = oss_fini_out,
@@ -925,7 +867,6 @@ static struct audio_pcm_ops oss_pcm_ops = {
static struct audio_driver oss_audio_driver = {
.name = "oss",
.descr = "OSS
http://www.opensound.com",
- .options = oss_options,
.init = oss_audio_init,
.fini = oss_audio_fini,
.pcm_ops = &oss_pcm_ops,
--
2.18.1