aboutsummaryrefslogtreecommitdiffstats
path: root/src/mixer
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mixer/alsa_mixer.c60
-rw-r--r--src/mixer/oss_mixer.c65
-rw-r--r--src/mixer_api.c45
-rw-r--r--src/mixer_api.h74
4 files changed, 169 insertions, 75 deletions
diff --git a/src/mixer/alsa_mixer.c b/src/mixer/alsa_mixer.c
index c1331993b..6930fa8a0 100644
--- a/src/mixer/alsa_mixer.c
+++ b/src/mixer/alsa_mixer.c
@@ -18,7 +18,7 @@ struct alsa_mixer {
int volume_set;
};
-struct alsa_mixer *
+static struct mixer_data *
alsa_mixer_init(void)
{
struct alsa_mixer *am = g_malloc(sizeof(struct alsa_mixer));
@@ -29,18 +29,20 @@ alsa_mixer_init(void)
am->volume_min = 0;
am->volume_max = 0;
am->volume_set = -1;
- return am;
+ return (struct mixer_data *)am;
}
-void
-alsa_mixer_finish(struct alsa_mixer *am)
+static void
+alsa_mixer_finish(struct mixer_data *data)
{
+ struct alsa_mixer *am = (struct alsa_mixer *)data;
g_free(am);
}
-void
-alsa_mixer_configure(struct alsa_mixer *am, ConfigParam *param)
+static void
+alsa_mixer_configure(struct mixer_data *data, ConfigParam *param)
{
+ struct alsa_mixer *am = (struct alsa_mixer *)data;
BlockParam *bp;
if ((bp = getBlockParam(param, "mixer_device")))
@@ -49,16 +51,18 @@ alsa_mixer_configure(struct alsa_mixer *am, ConfigParam *param)
am->control = bp->value;
}
-void
-alsa_mixer_close(struct alsa_mixer *am)
+static void
+alsa_mixer_close(struct mixer_data *data)
{
+ struct alsa_mixer *am = (struct alsa_mixer *)data;
if (am->handle) snd_mixer_close(am->handle);
am->handle = NULL;
}
-bool
-alsa_mixer_open(struct alsa_mixer *am)
+static bool
+alsa_mixer_open(struct mixer_data *data)
{
+ struct alsa_mixer *am = (struct alsa_mixer *)data;
int err;
snd_mixer_elem_t *elem;
const char *control_name = VOLUME_MIXER_ALSA_CONTROL_DEFAULT;
@@ -77,7 +81,7 @@ alsa_mixer_open(struct alsa_mixer *am)
if ((err = snd_mixer_attach(am->handle, device)) < 0) {
g_warning("problems attaching alsa mixer: %s\n",
snd_strerror(err));
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
@@ -85,14 +89,14 @@ alsa_mixer_open(struct alsa_mixer *am)
NULL)) < 0) {
g_warning("problems snd_mixer_selem_register'ing: %s\n",
snd_strerror(err));
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
if ((err = snd_mixer_load(am->handle)) < 0) {
g_warning("problems snd_mixer_selem_register'ing: %s\n",
snd_strerror(err));
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
@@ -122,18 +126,19 @@ alsa_mixer_open(struct alsa_mixer *am)
g_warning("can't find alsa mixer control \"%s\"\n", control_name);
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
-bool
-alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
+static bool
+alsa_mixer_control(struct mixer_data *data, int cmd, void *arg)
{
+ struct alsa_mixer *am = (struct alsa_mixer *)data;
switch (cmd) {
case AC_MIXER_CONFIGURE:
- alsa_mixer_configure(am, (ConfigParam *)arg);
+ alsa_mixer_configure(data, (ConfigParam *)arg);
if (am->handle)
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return true;
case AC_MIXER_GETVOL:
{
@@ -141,20 +146,20 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
int ret, *volume = arg;
long level;
- if (!am->handle && !alsa_mixer_open(am)) {
+ if (!am->handle && !alsa_mixer_open(data)) {
return false;
}
if ((err = snd_mixer_handle_events(am->handle)) < 0) {
g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
snd_strerror(err), "handle_events");
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
if ((err = snd_mixer_selem_get_playback_volume(am->elem,
SND_MIXER_SCHN_FRONT_LEFT, &level)) < 0) {
g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
snd_strerror(err), "selem_get_playback_volume");
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
ret = ((am->volume_set / 100.0) * (am->volume_max - am->volume_min)
@@ -175,7 +180,7 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
int *volume = arg;
int err;
- if (!am->handle && !alsa_mixer_open(am)) {
+ if (!am->handle && !alsa_mixer_open(data)) {
return false;
}
vol = *volume;
@@ -193,7 +198,7 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
level)) < 0) {
g_warning("problems setting alsa volume: %s\n",
snd_strerror(err));
- alsa_mixer_close(am);
+ alsa_mixer_close(data);
return false;
}
return true;
@@ -204,3 +209,12 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
}
return false;
}
+
+struct mixer_plugin alsa_mixer = {
+ .init = alsa_mixer_init,
+ .finish = alsa_mixer_finish,
+ .configure = alsa_mixer_configure,
+ .open = alsa_mixer_open,
+ .control = alsa_mixer_control,
+ .close = alsa_mixer_close
+};
diff --git a/src/mixer/oss_mixer.c b/src/mixer/oss_mixer.c
index b4b2ed7c6..db8431ab9 100644
--- a/src/mixer/oss_mixer.c
+++ b/src/mixer/oss_mixer.c
@@ -25,14 +25,7 @@ struct oss_mixer {
int volume_control;
};
-struct oss_mixer *oss_mixer_init(void);
-void oss_mixer_finish(struct oss_mixer *am);
-void oss_mixer_configure(struct oss_mixer *am, ConfigParam *param);
-bool oss_mixer_open(struct oss_mixer *am);
-bool oss_mixer_control(struct oss_mixer *am, int cmd, void *arg);
-void oss_mixer_close(struct oss_mixer *am);
-
-struct oss_mixer *
+static struct mixer_data *
oss_mixer_init(void)
{
struct oss_mixer *om = g_malloc(sizeof(struct oss_mixer));
@@ -40,18 +33,20 @@ oss_mixer_init(void)
om->control = NULL;
om->device_fd = -1;
om->volume_control = SOUND_MIXER_PCM;
- return om;
+ return (struct mixer_data *)om;
}
-void
-oss_mixer_finish(struct oss_mixer *om)
+static void
+oss_mixer_finish(struct mixer_data *data)
{
+ struct oss_mixer *om = (struct oss_mixer *) data;
g_free(om);
}
-void
-oss_mixer_configure(struct oss_mixer *om, ConfigParam *param)
+static void
+oss_mixer_configure(struct mixer_data *data, ConfigParam *param)
{
+ struct oss_mixer *om = (struct oss_mixer *) data;
BlockParam *bp;
bp = getBlockParam(param, "mixer_device");
if (bp) {
@@ -63,9 +58,10 @@ oss_mixer_configure(struct oss_mixer *om, ConfigParam *param)
}
}
-void
-oss_mixer_close(struct oss_mixer *om)
+static void
+oss_mixer_close(struct mixer_data *data)
{
+ struct oss_mixer *om = (struct oss_mixer *) data;
if (om->device_fd != -1)
while (close(om->device_fd) && errno == EINTR) ;
om->device_fd = -1;
@@ -86,9 +82,10 @@ oss_find_mixer(const char *name)
return -1;
}
-bool
-oss_mixer_open(struct oss_mixer *om)
+static bool
+oss_mixer_open(struct mixer_data *data)
{
+ struct oss_mixer *om = (struct oss_mixer *) data;
const char *device = VOLUME_MIXER_OSS_DEFAULT;
if (om->device) {
@@ -106,7 +103,7 @@ oss_mixer_open(struct oss_mixer *om)
if (ioctl(om->device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {
g_warning("errors getting read_devmask for oss mixer\n");
- oss_mixer_close(om);
+ oss_mixer_close(data);
return false;
}
i = oss_find_mixer(om->control);
@@ -114,12 +111,12 @@ oss_mixer_open(struct oss_mixer *om)
if (i < 0) {
g_warning("mixer control \"%s\" not found\n",
om->control);
- oss_mixer_close(om);
+ oss_mixer_close(data);
return false;
} else if (!((1 << i) & devmask)) {
g_warning("mixer control \"%s\" not usable\n",
om->control);
- oss_mixer_close(om);
+ oss_mixer_close(data);
return false;
}
om->volume_control = i;
@@ -127,14 +124,15 @@ oss_mixer_open(struct oss_mixer *om)
return true;
}
-bool
-oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
+static bool
+oss_mixer_control(struct mixer_data *data, int cmd, void *arg)
{
+ struct oss_mixer *om = (struct oss_mixer *) data;
switch (cmd) {
case AC_MIXER_CONFIGURE:
- oss_mixer_configure(om, (ConfigParam *)arg);
- //if (om->device_fd >= 0)
- oss_mixer_close(om);
+ oss_mixer_configure(data, (ConfigParam *)arg);
+ if (om->device_fd >= 0)
+ oss_mixer_close(data);
return true;
break;
case AC_MIXER_GETVOL:
@@ -142,12 +140,12 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
int left, right, level;
int *ret;
- if (om->device_fd < 0 && !oss_mixer_open(om)) {
+ if (om->device_fd < 0 && !oss_mixer_open(data)) {
return false;
}
if (ioctl(om->device_fd, MIXER_READ(om->volume_control), &level) < 0) {
- oss_mixer_close(om);
+ oss_mixer_close(data);
g_warning("unable to read oss volume\n");
return false;
}
@@ -169,7 +167,7 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
int level;
int *value = arg;
- if (om->device_fd < 0 && !oss_mixer_open(om)) {
+ if (om->device_fd < 0 && !oss_mixer_open(data)) {
return false;
}
@@ -184,7 +182,7 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
if (ioctl(om->device_fd, MIXER_WRITE(om->volume_control), &level) < 0) {
g_warning("unable to set oss volume\n");
- oss_mixer_close(om);
+ oss_mixer_close(data);
return false;
}
return true;
@@ -195,3 +193,12 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
}
return false;
}
+
+struct mixer_plugin oss_mixer = {
+ .init = oss_mixer_init,
+ .finish = oss_mixer_finish,
+ .configure = oss_mixer_configure,
+ .open = oss_mixer_open,
+ .control = oss_mixer_control,
+ .close = oss_mixer_close
+};
diff --git a/src/mixer_api.c b/src/mixer_api.c
new file mode 100644
index 000000000..f77f764cf
--- /dev/null
+++ b/src/mixer_api.c
@@ -0,0 +1,45 @@
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "mixer_api.h"
+
+void mixer_init(struct mixer *mixer, struct mixer_plugin *plugin)
+{
+ assert(plugin != NULL);
+ assert(mixer != NULL);
+ mixer->plugin = plugin;
+ mixer->data = mixer->plugin->init();
+}
+
+void mixer_finish(struct mixer *mixer)
+{
+ assert(mixer != NULL && mixer->plugin != NULL);
+ mixer->plugin->finish(mixer->data);
+ mixer->data = NULL;
+ mixer->plugin = NULL;
+}
+
+void mixer_configure(struct mixer *mixer, ConfigParam *param)
+{
+ assert(mixer != NULL && mixer->plugin != NULL);
+ mixer->plugin->configure(mixer->data, param);
+}
+
+bool mixer_open(struct mixer *mixer)
+{
+ assert(mixer != NULL && mixer->plugin != NULL);
+ return mixer->plugin->open(mixer->data);
+}
+
+bool mixer_control(struct mixer *mixer, int cmd, void *arg)
+{
+ assert(mixer != NULL && mixer->plugin != NULL);
+ return mixer->plugin->control(mixer->data, cmd, arg);
+}
+
+void mixer_close(struct mixer *mixer)
+{
+ assert(mixer != NULL && mixer->plugin != NULL);
+ mixer->plugin->close(mixer->data);
+}
diff --git a/src/mixer_api.h b/src/mixer_api.h
index 43dc3299d..67d08427c 100644
--- a/src/mixer_api.h
+++ b/src/mixer_api.h
@@ -4,30 +4,58 @@
#include "conf.h"
-/**
- * alsa mixer
+/*
+ * list of currently implemented mixers
*/
-struct alsa_mixer;
-
-struct alsa_mixer *alsa_mixer_init(void);
-void alsa_mixer_finish(struct alsa_mixer *am);
-void alsa_mixer_configure(struct alsa_mixer *am, ConfigParam *param);
-bool alsa_mixer_open(struct alsa_mixer *am);
-bool alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg);
-void alsa_mixer_close(struct alsa_mixer *am);
-
-/**
- * oss mixer
- */
-
-struct oss_mixer;
-
-struct oss_mixer *oss_mixer_init(void);
-void oss_mixer_finish(struct oss_mixer *am);
-void oss_mixer_configure(struct oss_mixer *am, ConfigParam *param);
-bool oss_mixer_open(struct oss_mixer *am);
-bool oss_mixer_control(struct oss_mixer *am, int cmd, void *arg);
-void oss_mixer_close(struct oss_mixer *am);
+extern struct mixer_plugin alsa_mixer;
+extern struct mixer_plugin oss_mixer;
+
+struct mixer_data;
+
+struct mixer_plugin {
+
+ /**
+ * Allocate and initialize mixer data
+ */
+ struct mixer_data *(*init)(void);
+
+ /**
+ * Finish and free mixer data
+ */
+ void (*finish)(struct mixer_data *data);
+
+ /**
+ * Setup and configure mixer
+ */
+ void (*configure)(struct mixer_data *data, ConfigParam *param);
+
+ /**
+ * Open mixer device
+ */
+ bool (*open)(struct mixer_data *data);
+
+ /**
+ * Control mixer device.
+ */
+ bool (*control)(struct mixer_data *data, int cmd, void *arg);
+
+ /**
+ * Close mixer device
+ */
+ void (*close)(struct mixer_data *data);
+};
+
+struct mixer {
+ struct mixer_plugin *plugin;
+ struct mixer_data *data;
+};
+
+void mixer_init(struct mixer *mixer, struct mixer_plugin *plugin);
+void mixer_finish(struct mixer *mixer);
+void mixer_configure(struct mixer *mixer, ConfigParam *param);
+bool mixer_open(struct mixer *mixer);
+bool mixer_control(struct mixer *mixer, int cmd, void *arg);
+void mixer_close(struct mixer *mixer);
#endif