X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=oss_mix.c;h=7fbdba5b770923988e646b96e74582f8ff4e8a1f;hp=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391;hb=8d106ca317a2c42f35a86ba244f843688f6939e6;hpb=7024574d05fe8571c763d11c61626a9ac4980267 diff --git a/oss_mix.c b/oss_mix.c index e69de29b..7fbdba5b 100644 --- a/oss_mix.c +++ b/oss_mix.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 1998 Andre Noll + * + * Licensed under the GPL v2. For licencing details see COPYING. + */ + +/** \file oss_mix.c The OSS mixer plugin. */ + +#include +#include +#include + +#include "para.h" +#include "error.h" +#include "mix.h" +#include "fd.h" +#include "string.h" + +struct oss_mixer_channel { + const char *name; + int id; +}; + +static const struct oss_mixer_channel channels[] = { + {.name = "volume", .id = SOUND_MIXER_VOLUME}, + {.name = "bass", .id = SOUND_MIXER_BASS}, + {.name = "treble", .id = SOUND_MIXER_TREBLE}, + {.name = "synth", .id = SOUND_MIXER_SYNTH}, + {.name = "pcm", .id = SOUND_MIXER_PCM}, + {.name = "speaker", .id = SOUND_MIXER_SPEAKER}, + {.name = "line", .id = SOUND_MIXER_LINE}, + {.name = "mic", .id = SOUND_MIXER_MIC}, + {.name = "cd", .id = SOUND_MIXER_CD}, + {.name = "imix", .id = SOUND_MIXER_IMIX}, + {.name = "altpcm", .id = SOUND_MIXER_ALTPCM}, + {.name = "reclev", .id = SOUND_MIXER_RECLEV}, + {.name = "igain", .id = SOUND_MIXER_IGAIN}, + {.name = "ogain", .id = SOUND_MIXER_OGAIN}, +}; + +/** Iterate over all defined mixer channels. */ +#define FOR_EACH_CHANNEL(i) for ((i) = 0; (i) < ARRAY_SIZE(channels); (i)++) + +struct mixer_handle { + int fd; + int id; +}; + +static int oss_mix_open(const char *dev, struct mixer_handle **handle) +{ + int ret; + struct mixer_handle *h; + + *handle = NULL; + if (!dev) + dev = "/dev/mixer"; + PARA_INFO_LOG("opening %s\n", dev); + ret = para_open(dev, O_RDWR, 42); + if (ret < 0) { + PARA_ERROR_LOG("could not open %s\n", dev); + return ret; + } + h = para_malloc(sizeof(*h)); + h->fd = ret; + *handle = h; + return 1; +} + +static char *oss_mix_get_channels(__a_unused struct mixer_handle *handle) +{ + int i; + char *list = NULL; + + FOR_EACH_CHANNEL(i) { + const char *name = channels[i].name; + char *tmp = list; + list = make_message("%s%s%s", + list? list : "", + list? ", " : "", + name); + free(tmp); + } + return list; +} + +static int oss_mix_set_channel(struct mixer_handle *handle, + const char *mixer_channel) +{ + int i; + + if (!mixer_channel) { + handle->id = SOUND_MIXER_VOLUME; /* default */ + return 0; + } + FOR_EACH_CHANNEL(i) { + if (strcasecmp(channels[i].name, mixer_channel)) + continue; + handle->id = i; + return 1; + } + return -E_BAD_CHANNEL; +} + +static int oss_mix_get(struct mixer_handle *handle) +{ + int val, fd = handle->fd, id = handle->id; + + if (ioctl(fd, MIXER_READ(id), &val) < 0) + return -ERRNO_TO_PARA_ERROR(errno); + /* take the mean value of left and right */ + return (val % 256 + (val >> 8)) / 2; +} + +static int oss_mix_set(struct mixer_handle *handle, int val) +{ + int fd = handle->fd, id = handle->id, tmp = (val << 8) + val; + + if (ioctl(fd, MIXER_WRITE(id), &tmp) < 0) + return -ERRNO_TO_PARA_ERROR(errno); + return 1; +} + +static void oss_mix_close(struct mixer_handle **handle) +{ + struct mixer_handle *h; + + if (!handle) + return; + h = *handle; + if (h) { + if (h->fd >= 0) + close(h->fd); + free(h); + } + *handle = NULL; +} + +/** The mixer operations for the OSS mixer. */ +const struct mixer oss_mixer = { + .name = "oss", + .open = oss_mix_open, + .get_channels = oss_mix_get_channels, + .set_channel = oss_mix_set_channel, + .close = oss_mix_close, + .get = oss_mix_get, + .set = oss_mix_set +};