Introducing mixer api
This patch tryes to introduce pluggable mixer (struct mixer_plugin) along with some basic infrastructure (mixer_* functions). Instance of mixer (struct mixer) is used in alsa and oss output plugin
This commit is contained in:
parent
8ebe7bfb25
commit
11c29cccb3
|
@ -128,6 +128,7 @@ mpd_SOURCES = \
|
||||||
main.c \
|
main.c \
|
||||||
event_pipe.c \
|
event_pipe.c \
|
||||||
daemon.c \
|
daemon.c \
|
||||||
|
mixer_api.c \
|
||||||
normalize.c \
|
normalize.c \
|
||||||
compress.c \
|
compress.c \
|
||||||
pipe.c \
|
pipe.c \
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct alsa_mixer {
|
||||||
int volume_set;
|
int volume_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alsa_mixer *
|
static struct mixer_data *
|
||||||
alsa_mixer_init(void)
|
alsa_mixer_init(void)
|
||||||
{
|
{
|
||||||
struct alsa_mixer *am = g_malloc(sizeof(struct alsa_mixer));
|
struct alsa_mixer *am = g_malloc(sizeof(struct alsa_mixer));
|
||||||
|
@ -29,18 +29,20 @@ alsa_mixer_init(void)
|
||||||
am->volume_min = 0;
|
am->volume_min = 0;
|
||||||
am->volume_max = 0;
|
am->volume_max = 0;
|
||||||
am->volume_set = -1;
|
am->volume_set = -1;
|
||||||
return am;
|
return (struct mixer_data *)am;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
alsa_mixer_finish(struct alsa_mixer *am)
|
alsa_mixer_finish(struct mixer_data *data)
|
||||||
{
|
{
|
||||||
|
struct alsa_mixer *am = (struct alsa_mixer *)data;
|
||||||
g_free(am);
|
g_free(am);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
alsa_mixer_configure(struct alsa_mixer *am, ConfigParam *param)
|
alsa_mixer_configure(struct mixer_data *data, ConfigParam *param)
|
||||||
{
|
{
|
||||||
|
struct alsa_mixer *am = (struct alsa_mixer *)data;
|
||||||
BlockParam *bp;
|
BlockParam *bp;
|
||||||
|
|
||||||
if ((bp = getBlockParam(param, "mixer_device")))
|
if ((bp = getBlockParam(param, "mixer_device")))
|
||||||
|
@ -49,16 +51,18 @@ alsa_mixer_configure(struct alsa_mixer *am, ConfigParam *param)
|
||||||
am->control = bp->value;
|
am->control = bp->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
alsa_mixer_close(struct alsa_mixer *am)
|
alsa_mixer_close(struct mixer_data *data)
|
||||||
{
|
{
|
||||||
|
struct alsa_mixer *am = (struct alsa_mixer *)data;
|
||||||
if (am->handle) snd_mixer_close(am->handle);
|
if (am->handle) snd_mixer_close(am->handle);
|
||||||
am->handle = NULL;
|
am->handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
alsa_mixer_open(struct alsa_mixer *am)
|
alsa_mixer_open(struct mixer_data *data)
|
||||||
{
|
{
|
||||||
|
struct alsa_mixer *am = (struct alsa_mixer *)data;
|
||||||
int err;
|
int err;
|
||||||
snd_mixer_elem_t *elem;
|
snd_mixer_elem_t *elem;
|
||||||
const char *control_name = VOLUME_MIXER_ALSA_CONTROL_DEFAULT;
|
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) {
|
if ((err = snd_mixer_attach(am->handle, device)) < 0) {
|
||||||
g_warning("problems attaching alsa mixer: %s\n",
|
g_warning("problems attaching alsa mixer: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,14 +89,14 @@ alsa_mixer_open(struct alsa_mixer *am)
|
||||||
NULL)) < 0) {
|
NULL)) < 0) {
|
||||||
g_warning("problems snd_mixer_selem_register'ing: %s\n",
|
g_warning("problems snd_mixer_selem_register'ing: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = snd_mixer_load(am->handle)) < 0) {
|
if ((err = snd_mixer_load(am->handle)) < 0) {
|
||||||
g_warning("problems snd_mixer_selem_register'ing: %s\n",
|
g_warning("problems snd_mixer_selem_register'ing: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
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);
|
g_warning("can't find alsa mixer control \"%s\"\n", control_name);
|
||||||
|
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
|
alsa_mixer_control(struct mixer_data *data, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
|
struct alsa_mixer *am = (struct alsa_mixer *)data;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case AC_MIXER_CONFIGURE:
|
case AC_MIXER_CONFIGURE:
|
||||||
alsa_mixer_configure(am, (ConfigParam *)arg);
|
alsa_mixer_configure(data, (ConfigParam *)arg);
|
||||||
if (am->handle)
|
if (am->handle)
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return true;
|
return true;
|
||||||
case AC_MIXER_GETVOL:
|
case AC_MIXER_GETVOL:
|
||||||
{
|
{
|
||||||
|
@ -141,20 +146,20 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
|
||||||
int ret, *volume = arg;
|
int ret, *volume = arg;
|
||||||
long level;
|
long level;
|
||||||
|
|
||||||
if (!am->handle && !alsa_mixer_open(am)) {
|
if (!am->handle && !alsa_mixer_open(data)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((err = snd_mixer_handle_events(am->handle)) < 0) {
|
if ((err = snd_mixer_handle_events(am->handle)) < 0) {
|
||||||
g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
|
g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
|
||||||
snd_strerror(err), "handle_events");
|
snd_strerror(err), "handle_events");
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((err = snd_mixer_selem_get_playback_volume(am->elem,
|
if ((err = snd_mixer_selem_get_playback_volume(am->elem,
|
||||||
SND_MIXER_SCHN_FRONT_LEFT, &level)) < 0) {
|
SND_MIXER_SCHN_FRONT_LEFT, &level)) < 0) {
|
||||||
g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
|
g_warning("problems getting alsa volume: %s (snd_mixer_%s)\n",
|
||||||
snd_strerror(err), "selem_get_playback_volume");
|
snd_strerror(err), "selem_get_playback_volume");
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ret = ((am->volume_set / 100.0) * (am->volume_max - am->volume_min)
|
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 *volume = arg;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!am->handle && !alsa_mixer_open(am)) {
|
if (!am->handle && !alsa_mixer_open(data)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
vol = *volume;
|
vol = *volume;
|
||||||
|
@ -193,7 +198,7 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
|
||||||
level)) < 0) {
|
level)) < 0) {
|
||||||
g_warning("problems setting alsa volume: %s\n",
|
g_warning("problems setting alsa volume: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
alsa_mixer_close(am);
|
alsa_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -204,3 +209,12 @@ alsa_mixer_control(struct alsa_mixer *am, int cmd, void *arg)
|
||||||
}
|
}
|
||||||
return false;
|
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
|
||||||
|
};
|
||||||
|
|
|
@ -25,14 +25,7 @@ struct oss_mixer {
|
||||||
int volume_control;
|
int volume_control;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct oss_mixer *oss_mixer_init(void);
|
static struct mixer_data *
|
||||||
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 *
|
|
||||||
oss_mixer_init(void)
|
oss_mixer_init(void)
|
||||||
{
|
{
|
||||||
struct oss_mixer *om = g_malloc(sizeof(struct oss_mixer));
|
struct oss_mixer *om = g_malloc(sizeof(struct oss_mixer));
|
||||||
|
@ -40,18 +33,20 @@ oss_mixer_init(void)
|
||||||
om->control = NULL;
|
om->control = NULL;
|
||||||
om->device_fd = -1;
|
om->device_fd = -1;
|
||||||
om->volume_control = SOUND_MIXER_PCM;
|
om->volume_control = SOUND_MIXER_PCM;
|
||||||
return om;
|
return (struct mixer_data *)om;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
oss_mixer_finish(struct oss_mixer *om)
|
oss_mixer_finish(struct mixer_data *data)
|
||||||
{
|
{
|
||||||
|
struct oss_mixer *om = (struct oss_mixer *) data;
|
||||||
g_free(om);
|
g_free(om);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
oss_mixer_configure(struct oss_mixer *om, ConfigParam *param)
|
oss_mixer_configure(struct mixer_data *data, ConfigParam *param)
|
||||||
{
|
{
|
||||||
|
struct oss_mixer *om = (struct oss_mixer *) data;
|
||||||
BlockParam *bp;
|
BlockParam *bp;
|
||||||
bp = getBlockParam(param, "mixer_device");
|
bp = getBlockParam(param, "mixer_device");
|
||||||
if (bp) {
|
if (bp) {
|
||||||
|
@ -63,9 +58,10 @@ oss_mixer_configure(struct oss_mixer *om, ConfigParam *param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
oss_mixer_close(struct oss_mixer *om)
|
oss_mixer_close(struct mixer_data *data)
|
||||||
{
|
{
|
||||||
|
struct oss_mixer *om = (struct oss_mixer *) data;
|
||||||
if (om->device_fd != -1)
|
if (om->device_fd != -1)
|
||||||
while (close(om->device_fd) && errno == EINTR) ;
|
while (close(om->device_fd) && errno == EINTR) ;
|
||||||
om->device_fd = -1;
|
om->device_fd = -1;
|
||||||
|
@ -86,9 +82,10 @@ oss_find_mixer(const char *name)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
oss_mixer_open(struct oss_mixer *om)
|
oss_mixer_open(struct mixer_data *data)
|
||||||
{
|
{
|
||||||
|
struct oss_mixer *om = (struct oss_mixer *) data;
|
||||||
const char *device = VOLUME_MIXER_OSS_DEFAULT;
|
const char *device = VOLUME_MIXER_OSS_DEFAULT;
|
||||||
|
|
||||||
if (om->device) {
|
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) {
|
if (ioctl(om->device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {
|
||||||
g_warning("errors getting read_devmask for oss mixer\n");
|
g_warning("errors getting read_devmask for oss mixer\n");
|
||||||
oss_mixer_close(om);
|
oss_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
i = oss_find_mixer(om->control);
|
i = oss_find_mixer(om->control);
|
||||||
|
@ -114,12 +111,12 @@ oss_mixer_open(struct oss_mixer *om)
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
g_warning("mixer control \"%s\" not found\n",
|
g_warning("mixer control \"%s\" not found\n",
|
||||||
om->control);
|
om->control);
|
||||||
oss_mixer_close(om);
|
oss_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
} else if (!((1 << i) & devmask)) {
|
} else if (!((1 << i) & devmask)) {
|
||||||
g_warning("mixer control \"%s\" not usable\n",
|
g_warning("mixer control \"%s\" not usable\n",
|
||||||
om->control);
|
om->control);
|
||||||
oss_mixer_close(om);
|
oss_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
om->volume_control = i;
|
om->volume_control = i;
|
||||||
|
@ -127,14 +124,15 @@ oss_mixer_open(struct oss_mixer *om)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
|
oss_mixer_control(struct mixer_data *data, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
|
struct oss_mixer *om = (struct oss_mixer *) data;
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case AC_MIXER_CONFIGURE:
|
case AC_MIXER_CONFIGURE:
|
||||||
oss_mixer_configure(om, (ConfigParam *)arg);
|
oss_mixer_configure(data, (ConfigParam *)arg);
|
||||||
//if (om->device_fd >= 0)
|
if (om->device_fd >= 0)
|
||||||
oss_mixer_close(om);
|
oss_mixer_close(data);
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case AC_MIXER_GETVOL:
|
case AC_MIXER_GETVOL:
|
||||||
|
@ -142,12 +140,12 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
|
||||||
int left, right, level;
|
int left, right, level;
|
||||||
int *ret;
|
int *ret;
|
||||||
|
|
||||||
if (om->device_fd < 0 && !oss_mixer_open(om)) {
|
if (om->device_fd < 0 && !oss_mixer_open(data)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(om->device_fd, MIXER_READ(om->volume_control), &level) < 0) {
|
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");
|
g_warning("unable to read oss volume\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +167,7 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
|
||||||
int level;
|
int level;
|
||||||
int *value = arg;
|
int *value = arg;
|
||||||
|
|
||||||
if (om->device_fd < 0 && !oss_mixer_open(om)) {
|
if (om->device_fd < 0 && !oss_mixer_open(data)) {
|
||||||
return false;
|
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) {
|
if (ioctl(om->device_fd, MIXER_WRITE(om->volume_control), &level) < 0) {
|
||||||
g_warning("unable to set oss volume\n");
|
g_warning("unable to set oss volume\n");
|
||||||
oss_mixer_close(om);
|
oss_mixer_close(data);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -195,3 +193,12 @@ oss_mixer_control(struct oss_mixer *om, int cmd, void *arg)
|
||||||
}
|
}
|
||||||
return false;
|
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
|
||||||
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -4,30 +4,58 @@
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* alsa mixer
|
* list of currently implemented mixers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct alsa_mixer;
|
extern struct mixer_plugin alsa_mixer;
|
||||||
|
extern struct mixer_plugin oss_mixer;
|
||||||
|
|
||||||
struct alsa_mixer *alsa_mixer_init(void);
|
struct mixer_data;
|
||||||
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);
|
|
||||||
|
|
||||||
/**
|
struct mixer_plugin {
|
||||||
* oss mixer
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct oss_mixer;
|
/**
|
||||||
|
* Allocate and initialize mixer data
|
||||||
|
*/
|
||||||
|
struct mixer_data *(*init)(void);
|
||||||
|
|
||||||
struct oss_mixer *oss_mixer_init(void);
|
/**
|
||||||
void oss_mixer_finish(struct oss_mixer *am);
|
* Finish and free mixer data
|
||||||
void oss_mixer_configure(struct oss_mixer *am, ConfigParam *param);
|
*/
|
||||||
bool oss_mixer_open(struct oss_mixer *am);
|
void (*finish)(struct mixer_data *data);
|
||||||
bool oss_mixer_control(struct oss_mixer *am, int cmd, void *arg);
|
|
||||||
void oss_mixer_close(struct oss_mixer *am);
|
/**
|
||||||
|
* 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
|
#endif
|
||||||
|
|
|
@ -52,7 +52,7 @@ typedef struct _AlsaData {
|
||||||
int sampleSize;
|
int sampleSize;
|
||||||
int useMmap;
|
int useMmap;
|
||||||
|
|
||||||
struct alsa_mixer *mixer;
|
struct mixer mixer;
|
||||||
|
|
||||||
} AlsaData;
|
} AlsaData;
|
||||||
|
|
||||||
|
@ -74,7 +74,8 @@ static AlsaData *newAlsaData(void)
|
||||||
ret->buffer_time = MPD_ALSA_BUFFER_TIME_US;
|
ret->buffer_time = MPD_ALSA_BUFFER_TIME_US;
|
||||||
ret->period_time = 0;
|
ret->period_time = 0;
|
||||||
|
|
||||||
ret->mixer = alsa_mixer_init();
|
//use alsa mixer by default
|
||||||
|
mixer_init(&ret->mixer, &alsa_mixer);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +83,7 @@ static AlsaData *newAlsaData(void)
|
||||||
static void freeAlsaData(AlsaData * ad)
|
static void freeAlsaData(AlsaData * ad)
|
||||||
{
|
{
|
||||||
g_free(ad->device);
|
g_free(ad->device);
|
||||||
alsa_mixer_finish(ad->mixer);
|
mixer_finish(&ad->mixer);
|
||||||
free(ad);
|
free(ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ static void *alsa_initDriver(G_GNUC_UNUSED struct audio_output *ao,
|
||||||
|
|
||||||
if (param) {
|
if (param) {
|
||||||
alsa_configure(ad, param);
|
alsa_configure(ad, param);
|
||||||
alsa_mixer_configure(ad->mixer, param);
|
mixer_configure(&ad->mixer, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ad;
|
return ad;
|
||||||
|
@ -189,7 +190,7 @@ static bool alsa_openDevice(void *data, struct audio_format *audioFormat)
|
||||||
unsigned int period_time, period_time_ro;
|
unsigned int period_time, period_time_ro;
|
||||||
unsigned int buffer_time;
|
unsigned int buffer_time;
|
||||||
|
|
||||||
alsa_mixer_open(ad->mixer);
|
mixer_open(&ad->mixer);
|
||||||
|
|
||||||
if ((bitformat = get_bitformat(audioFormat)) == SND_PCM_FORMAT_UNKNOWN)
|
if ((bitformat = get_bitformat(audioFormat)) == SND_PCM_FORMAT_UNKNOWN)
|
||||||
g_warning("ALSA device \"%s\" doesn't support %u bit audio\n",
|
g_warning("ALSA device \"%s\" doesn't support %u bit audio\n",
|
||||||
|
@ -413,7 +414,7 @@ static void alsa_closeDevice(void *data)
|
||||||
snd_pcm_close(ad->pcmHandle);
|
snd_pcm_close(ad->pcmHandle);
|
||||||
ad->pcmHandle = NULL;
|
ad->pcmHandle = NULL;
|
||||||
}
|
}
|
||||||
alsa_mixer_close(ad->mixer);
|
mixer_close(&ad->mixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -451,7 +452,7 @@ static bool
|
||||||
alsa_control(void *data, int cmd, void *arg)
|
alsa_control(void *data, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
AlsaData *ad = data;
|
AlsaData *ad = data;
|
||||||
return alsa_mixer_control(ad->mixer, cmd, arg);
|
return mixer_control(&ad->mixer, cmd, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct audio_output_plugin alsaPlugin = {
|
const struct audio_output_plugin alsaPlugin = {
|
||||||
|
|
|
@ -55,7 +55,7 @@ typedef struct _OssData {
|
||||||
int numSupported[3];
|
int numSupported[3];
|
||||||
int *unsupported[3];
|
int *unsupported[3];
|
||||||
int numUnsupported[3];
|
int numUnsupported[3];
|
||||||
struct oss_mixer *mixer;
|
struct mixer mixer;
|
||||||
} OssData;
|
} OssData;
|
||||||
|
|
||||||
enum oss_support {
|
enum oss_support {
|
||||||
|
@ -276,7 +276,7 @@ static OssData *newOssData(void)
|
||||||
supportParam(ret, SNDCTL_DSP_CHANNELS, 2);
|
supportParam(ret, SNDCTL_DSP_CHANNELS, 2);
|
||||||
supportParam(ret, SNDCTL_DSP_SAMPLESIZE, 16);
|
supportParam(ret, SNDCTL_DSP_SAMPLESIZE, 16);
|
||||||
|
|
||||||
ret->mixer = oss_mixer_init();
|
mixer_init( &ret->mixer, &oss_mixer);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ static void freeOssData(OssData * od)
|
||||||
g_free(od->unsupported[OSS_CHANNELS]);
|
g_free(od->unsupported[OSS_CHANNELS]);
|
||||||
g_free(od->unsupported[OSS_BITS]);
|
g_free(od->unsupported[OSS_BITS]);
|
||||||
|
|
||||||
oss_mixer_finish(od->mixer);
|
mixer_finish(&od->mixer);
|
||||||
|
|
||||||
free(od);
|
free(od);
|
||||||
}
|
}
|
||||||
|
@ -355,7 +355,7 @@ static void *oss_open_default(ConfigParam *param)
|
||||||
if (ret[i] == 0) {
|
if (ret[i] == 0) {
|
||||||
OssData *od = newOssData();
|
OssData *od = newOssData();
|
||||||
od->device = default_devices[i];
|
od->device = default_devices[i];
|
||||||
oss_mixer_configure(od->mixer, param);
|
mixer_configure(&od->mixer, param);
|
||||||
return od;
|
return od;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ static void *oss_initDriver(G_GNUC_UNUSED struct audio_output *audioOutput,
|
||||||
if (bp) {
|
if (bp) {
|
||||||
OssData *od = newOssData();
|
OssData *od = newOssData();
|
||||||
od->device = bp->value;
|
od->device = bp->value;
|
||||||
oss_mixer_configure(od->mixer, param);
|
mixer_configure(&od->mixer, param);
|
||||||
return od;
|
return od;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,7 +522,7 @@ oss_openDevice(void *data, struct audio_format *audioFormat)
|
||||||
od->audio_format.bits, od->audio_format.channels,
|
od->audio_format.bits, od->audio_format.channels,
|
||||||
od->audio_format.sample_rate);
|
od->audio_format.sample_rate);
|
||||||
|
|
||||||
oss_mixer_open(od->mixer);
|
mixer_open(&od->mixer);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -532,7 +532,7 @@ static void oss_closeDevice(void *data)
|
||||||
OssData *od = data;
|
OssData *od = data;
|
||||||
|
|
||||||
oss_close(od);
|
oss_close(od);
|
||||||
oss_mixer_close(od->mixer);
|
mixer_close(&od->mixer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void oss_dropBufferedAudio(void *data)
|
static void oss_dropBufferedAudio(void *data)
|
||||||
|
@ -575,7 +575,7 @@ static bool
|
||||||
oss_control(void *data, int cmd, void *arg)
|
oss_control(void *data, int cmd, void *arg)
|
||||||
{
|
{
|
||||||
OssData *od = data;
|
OssData *od = data;
|
||||||
return oss_mixer_control(od->mixer, cmd, arg);
|
return mixer_control(&od->mixer, cmd, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct audio_output_plugin ossPlugin = {
|
const struct audio_output_plugin ossPlugin = {
|
||||||
|
|
Loading…
Reference in New Issue