Move base64 implementation to own file.
[paraslash.git] / oss_mix.c
index e69de29..8e87452 100644 (file)
--- a/oss_mix.c
+++ b/oss_mix.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 1998 Andre Noll <maan@tuebingen.mpg.de>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file oss_mix.c The OSS mixer plugin. */
+
+#include <sys/soundcard.h>
+#include <sys/ioctl.h>
+#include <regex.h>
+
+#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 init function of the OSS mixer.
+ *
+ * \param self The structure to initialize.
+ *
+ * \sa struct \ref mixer, \ref alsa_mix_init().
+ */
+void oss_mix_init(struct mixer *self)
+{
+       self->open = oss_mix_open;
+       self->get_channels = oss_mix_get_channels;
+       self->set_channel = oss_mix_set_channel;
+       self->get = oss_mix_get;
+       self->set = oss_mix_set;
+       self->close = oss_mix_close;
+}