aboutsummaryrefslogtreecommitdiff
path: root/amixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'amixer.c')
-rw-r--r--amixer.c743
1 files changed, 743 insertions, 0 deletions
diff --git a/amixer.c b/amixer.c
new file mode 100644
index 0000000..b159664
--- /dev/null
+++ b/amixer.c
@@ -0,0 +1,743 @@
+/******************************************************
+ *
+ * amixer - ALSA sequencer connection manager
+ * Copyright (C) 1999-2000 Jaroslav Kysela
+ *
+ *
+ *
+ * ported from alsa-1.0.9a to pd by:
+ * copyleft (c) 2005 IOhannes m zmölnig
+ *
+ * forum::für::umläute
+ *
+ * institute of electronic music and acoustics (iem)
+ *
+ *
+ ******************************************************
+ *
+ * license: GNU General Public License v.2
+ *
+ ******************************************************/
+#include "m_pd.h"
+
+/* amixer :: allows control of the mixer (controls) for the ALSA soundcard driver */
+
+#ifdef HAVE_ALSA
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <getopt.h>
+# include <stdarg.h>
+# include <ctype.h>
+# include <math.h>
+# include <errno.h>
+# include <assert.h>
+# include <alsa/asoundlib.h>
+# include <sys/poll.h>
+
+#define LEVEL_BASIC (1<<0)
+#define LEVEL_INACTIVE (1<<1)
+#define LEVEL_ID (1<<2)
+
+#endif /* ALSA */
+
+
+static t_class *amixer_class;
+
+typedef struct _amixer
+{
+ t_object x_obj;
+ t_outlet*x_error;
+
+ char card[64];
+} t_amixer;
+
+
+#ifdef HAVE_ALSA
+
+static const char *control_iface(snd_ctl_elem_id_t *id)
+{
+ return snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(id));
+}
+
+static const char *control_type(snd_ctl_elem_info_t *info)
+{
+ return snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info));
+}
+
+static const char *control_access(snd_ctl_elem_info_t *info)
+{
+ static char result[10];
+ char *res = result;
+
+ *res++ = snd_ctl_elem_info_is_readable(info) ? 'r' : '-';
+ *res++ = snd_ctl_elem_info_is_writable(info) ? 'w' : '-';
+ *res++ = snd_ctl_elem_info_is_inactive(info) ? 'i' : '-';
+ *res++ = snd_ctl_elem_info_is_volatile(info) ? 'v' : '-';
+ *res++ = snd_ctl_elem_info_is_locked(info) ? 'l' : '-';
+ *res++ = '\0';
+ return result;
+}
+
+
+static int check_range(int val, int min, int max)
+{
+ if (val < min)
+ return min;
+ if (val > max)
+ return max;
+ return val;
+}
+
+#if 0
+static int convert_range(int val, int omin, int omax, int nmin, int nmax)
+{
+ int orange = omax - omin, nrange = nmax - nmin;
+
+ if (orange == 0)
+ return 0;
+ return rint((((double)nrange * ((double)val - (double)omin)) + ((double)orange / 2.0)) / ((double)orange + (double)nmin));
+}
+#endif
+
+#if 0
+static int convert_db_range(int val, int omin, int omax, int nmin, int nmax)
+{
+ int orange = omax - omin, nrange = nmax - nmin;
+
+ if (orange == 0)
+ return 0;
+ return rint((((double)nrange * ((double)val - (double)omin)) + ((double)orange / 2.0)) / (double)orange + (double)nmin);
+}
+#endif
+
+/* Fuction to convert from volume to percentage. val = volume */
+
+static int convert_prange(int val, int min, int max)
+{
+ int range = max - min;
+ int tmp;
+
+ if (range == 0)
+ return 0;
+ val -= min;
+ tmp = rint((double)val/(double)range * 100);
+ return tmp;
+}
+
+/* Function to convert from percentage to volume. val = percentage */
+
+static int convert_prange1(int val, int min, int max)
+{
+ int range = max - min;
+ int tmp;
+
+ if (range == 0)
+ return 0;
+
+ tmp = rint((double)range * ((double)val*.01)) + min;
+ return tmp;
+}
+
+static const char *get_percent(int val, int min, int max)
+{
+ static char str[32];
+ int p;
+
+ p = convert_prange(val, min, max);
+ sprintf(str, "%i [%i%%]", val, p);
+ return str;
+}
+
+#if 0
+static const char *get_percent1(int val, int min, int max, int min_dB, int max_dB)
+{
+ static char str[32];
+ int p, db;
+
+ p = convert_prange(val, min, max);
+ db = convert_db_range(val, min, max, min_dB, max_dB);
+ sprintf(str, "%i [%i%%] [%i.%02idB]", val, p, db / 100, abs(db % 100));
+ return str;
+}
+#endif
+
+static long get_integer(char **ptr, long min, long max)
+{
+ int tmp, tmp1, tmp2;
+
+ if (**ptr == ':')
+ (*ptr)++;
+ if (**ptr == '\0' || (!isdigit(**ptr) && **ptr != '-'))
+ return min;
+ tmp = strtol(*ptr, ptr, 10);
+ tmp1 = tmp;
+ tmp2 = 0;
+ if (**ptr == '.') {
+ (*ptr)++;
+ tmp2 = strtol(*ptr, ptr, 10);
+ }
+ if (**ptr == '%') {
+ tmp1 = convert_prange1(tmp, min, max);
+ (*ptr)++;
+ }
+ tmp1 = check_range(tmp1, min, max);
+ if (**ptr == ',')
+ (*ptr)++;
+ return tmp1;
+}
+
+static long get_integer64(char **ptr, long long min, long long max)
+{
+ long long tmp, tmp1, tmp2;
+
+ if (**ptr == ':')
+ (*ptr)++;
+ if (**ptr == '\0' || (!isdigit(**ptr) && **ptr != '-'))
+ return min;
+ tmp = strtol(*ptr, ptr, 10);
+ tmp1 = tmp;
+ tmp2 = 0;
+ if (**ptr == '.') {
+ (*ptr)++;
+ tmp2 = strtol(*ptr, ptr, 10);
+ }
+ if (**ptr == '%') {
+ tmp1 = convert_prange1(tmp, min, max);
+ (*ptr)++;
+ }
+ tmp1 = check_range(tmp1, min, max);
+ if (**ptr == ',')
+ (*ptr)++;
+ return tmp1;
+}
+
+static int get_volume_simple(char **ptr, int min, int max, int orig)
+{
+ int tmp, tmp1, tmp2;
+
+ if (**ptr == ':')
+ (*ptr)++;
+ if (**ptr == '\0' || (!isdigit(**ptr) && **ptr != '-'))
+ return min;
+ tmp = atoi(*ptr);
+ if (**ptr == '-')
+ (*ptr)++;
+ while (isdigit(**ptr))
+ (*ptr)++;
+ tmp1 = tmp;
+ tmp2 = 0;
+ if (**ptr == '.') {
+ (*ptr)++;
+ tmp2 = atoi(*ptr);
+ while (isdigit(**ptr))
+ (*ptr)++;
+ }
+ if (**ptr == '%') {
+ tmp1 = convert_prange1(tmp, min, max);
+ (*ptr)++;
+ }
+ if (**ptr == '+') {
+ tmp1 = orig + tmp1;
+ (*ptr)++;
+ } else if (**ptr == '-') {
+ tmp1 = orig - tmp1;
+ (*ptr)++;
+ }
+ tmp1 = check_range(tmp1, min, max);
+ if (**ptr == ',')
+ (*ptr)++;
+ return tmp1;
+}
+
+static int get_bool_simple(char **ptr, char *str, int invert, int orig)
+{
+ if (**ptr == ':')
+ (*ptr)++;
+ if (!strncasecmp(*ptr, str, strlen(str))) {
+ orig = 1 ^ (invert ? 1 : 0);
+ while (**ptr != '\0' && **ptr != ',' && **ptr != ':')
+ (*ptr)++;
+ }
+ if (**ptr == ',' || **ptr == ':')
+ (*ptr)++;
+ return orig;
+}
+
+static int parse_control_id(const char *str, snd_ctl_elem_id_t *id)
+{
+ int c, size;
+ char *ptr;
+
+ while (*str == ' ' || *str == '\t')
+ str++;
+ if (!(*str))
+ return -EINVAL;
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); /* default */
+ while (*str) {
+ if (!strncasecmp(str, "numid=", 6)) {
+ str += 6;
+ snd_ctl_elem_id_set_numid(id, atoi(str));
+ while (isdigit(*str))
+ str++;
+ } else if (!strncasecmp(str, "iface=", 6)) {
+ str += 6;
+ if (!strncasecmp(str, "card", 4)) {
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
+ str += 4;
+ } else if (!strncasecmp(str, "mixer", 5)) {
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+ str += 5;
+ } else if (!strncasecmp(str, "pcm", 3)) {
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
+ str += 3;
+ } else if (!strncasecmp(str, "rawmidi", 7)) {
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_RAWMIDI);
+ str += 7;
+ } else if (!strncasecmp(str, "timer", 5)) {
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_TIMER);
+ str += 5;
+ } else if (!strncasecmp(str, "sequencer", 9)) {
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_SEQUENCER);
+ str += 9;
+ } else {
+ return -EINVAL;
+ }
+ } else if (!strncasecmp(str, "name=", 5)) {
+ char buf[64];
+ str += 5;
+ ptr = buf;
+ size = 0;
+ if (*str == '\'' || *str == '\"') {
+ c = *str++;
+ while (*str && *str != c) {
+ if (size < (int)sizeof(buf)) {
+ *ptr++ = *str;
+ size++;
+ }
+ str++;
+ }
+ if (*str == c)
+ str++;
+ } else {
+ while (*str && *str != ',') {
+ if (size < (int)sizeof(buf)) {
+ *ptr++ = *str;
+ size++;
+ }
+ str++;
+ }
+ *ptr = '\0';
+ }
+ snd_ctl_elem_id_set_name(id, buf);
+ } else if (!strncasecmp(str, "index=", 6)) {
+ str += 6;
+ snd_ctl_elem_id_set_index(id, atoi(str));
+ while (isdigit(*str))
+ str++;
+ } else if (!strncasecmp(str, "device=", 7)) {
+ str += 7;
+ snd_ctl_elem_id_set_device(id, atoi(str));
+ while (isdigit(*str))
+ str++;
+ } else if (!strncasecmp(str, "subdevice=", 10)) {
+ str += 10;
+ snd_ctl_elem_id_set_subdevice(id, atoi(str));
+ while (isdigit(*str))
+ str++;
+ }
+ if (*str == ',') {
+ str++;
+ } else {
+ if (*str)
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int parse_simple_id(const char *str, snd_mixer_selem_id_t *sid)
+{
+ int c, size;
+ char buf[128];
+ char *ptr = buf;
+
+ while (*str == ' ' || *str == '\t')
+ str++;
+ if (!(*str))
+ return -EINVAL;
+ size = 1; /* for '\0' */
+ if (*str != '"' && *str != '\'') {
+ while (*str && *str != ',') {
+ if (size < (int)sizeof(buf)) {
+ *ptr++ = *str;
+ size++;
+ }
+ str++;
+ }
+ } else {
+ c = *str++;
+ while (*str && *str != c) {
+ if (size < (int)sizeof(buf)) {
+ *ptr++ = *str;
+ size++;
+ }
+ str++;
+ }
+ if (*str == c)
+ str++;
+ }
+ if (*str == '\0') {
+ snd_mixer_selem_id_set_index(sid, 0);
+ *ptr = 0;
+ goto _set;
+ }
+ if (*str != ',')
+ return -EINVAL;
+ *ptr = 0; /* terminate the string */
+ str++;
+ if (!isdigit(*str))
+ return -EINVAL;
+ snd_mixer_selem_id_set_index(sid, atoi(str));
+ _set:
+ snd_mixer_selem_id_set_name(sid, buf);
+ return 0;
+}
+static void show_control_id(snd_ctl_elem_id_t *id)
+{
+ unsigned int index, device, subdevice;
+ printf("numid=%u,iface=%s,name='%s'",
+ snd_ctl_elem_id_get_numid(id),
+ control_iface(id),
+ snd_ctl_elem_id_get_name(id));
+ index = snd_ctl_elem_id_get_index(id);
+ device = snd_ctl_elem_id_get_device(id);
+ subdevice = snd_ctl_elem_id_get_subdevice(id);
+ if (index)
+ printf(",index=%i", index);
+ if (device)
+ printf(",device=%i", device);
+ if (subdevice)
+ printf(",subdevice=%i", subdevice);
+}
+
+static int show_control(const char* card, const char *space, snd_hctl_elem_t *elem,
+ int level)
+{
+ int err;
+ unsigned int item, idx;
+ unsigned int count;
+ snd_ctl_elem_type_t type;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_value_t *control;
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_value_alloca(&control);
+ if ((err = snd_hctl_elem_info(elem, info)) < 0) {
+ error("Control %s snd_hctl_elem_info error: %s\n", card, snd_strerror(err));
+ return err;
+ }
+ if (level & LEVEL_ID) {
+ snd_hctl_elem_get_id(elem, id);
+ show_control_id(id);
+ printf("\n");
+ }
+ count = snd_ctl_elem_info_get_count(info);
+ type = snd_ctl_elem_info_get_type(info);
+ printf("%s; type=%s,access=%s,values=%i", space, control_type(info), control_access(info), count);
+ switch (type) {
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ printf(",min=%li,max=%li,step=%li\n",
+ snd_ctl_elem_info_get_min(info),
+ snd_ctl_elem_info_get_max(info),
+ snd_ctl_elem_info_get_step(info));
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER64:
+ printf(",min=%Li,max=%Li,step=%Li\n",
+ snd_ctl_elem_info_get_min64(info),
+ snd_ctl_elem_info_get_max64(info),
+ snd_ctl_elem_info_get_step64(info));
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED:
+ {
+ unsigned int items = snd_ctl_elem_info_get_items(info);
+ printf(",items=%u\n", items);
+ for (item = 0; item < items; item++) {
+ snd_ctl_elem_info_set_item(info, item);
+ if ((err = snd_hctl_elem_info(elem, info)) < 0) {
+ error("Control %s element info error: %s\n", card, snd_strerror(err));
+ return err;
+ }
+ printf("%s; Item #%u '%s'\n", space, item, snd_ctl_elem_info_get_item_name(info));
+ }
+ break;
+ }
+ default:
+ printf("\n");
+ break;
+ }
+ if (level & LEVEL_BASIC) {
+ if ((err = snd_hctl_elem_read(elem, control)) < 0) {
+ error("Control %s element read error: %s\n", card, snd_strerror(err));
+ return err;
+ }
+ printf("%s: values=", space);
+ for (idx = 0; idx < count; idx++) {
+ if (idx > 0)
+ printf(",");
+ switch (type) {
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
+ printf("%s", snd_ctl_elem_value_get_boolean(control, idx) ? "on" : "off");
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ printf("%li", snd_ctl_elem_value_get_integer(control, idx));
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER64:
+ printf("%Li", snd_ctl_elem_value_get_integer64(control, idx));
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED:
+ printf("%u", snd_ctl_elem_value_get_enumerated(control, idx));
+ break;
+ case SND_CTL_ELEM_TYPE_BYTES:
+ printf("0x%02x", snd_ctl_elem_value_get_byte(control, idx));
+ break;
+ default:
+ printf("?");
+ break;
+ }
+ }
+ printf("\n");
+ }
+ return 0;
+}
+
+
+
+static void amixer_bang(t_amixer *x)
+{
+
+
+
+}
+static int amixer_control(t_amixer *x, int argc, t_atom *argv, int roflag)
+{
+ int err;
+ snd_ctl_t *handle;
+ snd_ctl_elem_info_t *info;
+ snd_ctl_elem_id_t *id;
+ snd_ctl_elem_value_t *control;
+ char *ptr;
+ unsigned int idx, count;
+ long tmp;
+ snd_ctl_elem_type_t type;
+ snd_ctl_elem_info_alloca(&info);
+ snd_ctl_elem_id_alloca(&id);
+ snd_ctl_elem_value_alloca(&control);
+
+ if (argc < 1) {
+ error("Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n");
+ return -EINVAL;
+ }
+ if(A_FLOAT==argv->a_type){
+ snd_ctl_elem_id_set_numid(id, atom_getint(argv));
+ if(0)
+ {
+ error("Wrong control identifier: %d\n", atom_getint(argv));
+ return -EINVAL;
+ }
+ } else {
+ if (parse_control_id(atom_getsymbol(argv)->s_name, id)) {
+ error("Wrong control identifier: %s\n", atom_getsymbol(argv)->s_name);
+ return -EINVAL;
+ }
+ }
+ if ((err = snd_ctl_open(&handle, x->card, 0)) < 0) {
+ error("Control %s open error: %s\n", x->card, snd_strerror(err));
+ return err;
+ }
+ snd_ctl_elem_info_set_id(info, id);
+ if ((err = snd_ctl_elem_info(handle, info)) < 0) {
+ error("Control %s cinfo error: %s\n", x->card, snd_strerror(err));
+ return err;
+ }
+
+ snd_ctl_elem_info_get_id(info, id); /* FIXME: Remove it when hctl find works ok !!! */
+ type = snd_ctl_elem_info_get_type(info);
+ count = snd_ctl_elem_info_get_count(info);
+ snd_ctl_elem_value_set_id(control, id);
+
+ if (!roflag) {
+ t_float atom_float = atom_getfloat(argv+1);
+ int atom_isfloat = (A_FLOAT==(argv+1)->a_type);
+ post("now setting");
+ ptr = atom_getsymbol(argv+1)->s_name;
+ for (idx = 0; idx < count && idx < 128 && ptr && *ptr; idx++) {
+ switch (type) {
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
+ tmp = 0;
+ if(atom_isfloat){
+ tmp=(atom_float>0)?1:0;
+ } else if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) {
+ tmp = 1;
+ ptr += 2;
+ } else if (!strncasecmp(ptr, "yes", 3)) {
+ tmp = 1;
+ ptr += 3;
+ } else if (!strncasecmp(ptr, "toggle", 6)) {
+ tmp = snd_ctl_elem_value_get_boolean(control, idx);
+ tmp = tmp > 0 ? 0 : 1;
+ ptr += 6;
+ } else if (isdigit(*ptr)) {
+ tmp = atoi(ptr) > 0 ? 1 : 0;
+ while (isdigit(*ptr))
+ ptr++;
+ } else {
+ while (*ptr && *ptr != ',')
+ ptr++;
+ }
+ snd_ctl_elem_value_set_boolean(control, idx, tmp);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ tmp = atom_isfloat?((int)atom_float):get_integer(&ptr,
+ snd_ctl_elem_info_get_min(info),
+ snd_ctl_elem_info_get_max(info));
+ snd_ctl_elem_value_set_integer(control, idx, tmp);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER64:
+ tmp = atom_isfloat?((int)atom_float):get_integer64(&ptr,
+ snd_ctl_elem_info_get_min64(info),
+ snd_ctl_elem_info_get_max64(info));
+ snd_ctl_elem_value_set_integer64(control, idx, tmp);
+ break;
+ case SND_CTL_ELEM_TYPE_ENUMERATED:
+ tmp = atom_isfloat?((int)atom_float):get_integer(&ptr, 0, snd_ctl_elem_info_get_items(info) - 1);
+ snd_ctl_elem_value_set_enumerated(control, idx, tmp);
+ break;
+ case SND_CTL_ELEM_TYPE_BYTES:
+ tmp = atom_isfloat?((int)atom_float):get_integer(&ptr, 0, 255);
+ snd_ctl_elem_value_set_byte(control, idx, tmp);
+ break;
+ default:
+ break;
+ }
+ if (!strchr(atom_getsymbol(argv+1)->s_name, ','))
+ ptr = atom_getsymbol(argv+1)->s_name;
+ else if (*ptr == ',')
+ ptr++;
+ }
+ if ((err = snd_ctl_elem_write(handle, control)) < 0) {
+ error("Control %s element write error: %s\n", x->card, snd_strerror(err));
+ return err;
+ }
+ }
+ snd_ctl_close(handle);
+
+
+ if (1) {
+ snd_hctl_t *hctl;
+ snd_hctl_elem_t *elem;
+ if ((err = snd_hctl_open(&hctl, x->card, 0)) < 0) {
+ error("Control %s open error: %s\n", x->card, snd_strerror(err));
+ return err;
+ }
+ if ((err = snd_hctl_load(hctl)) < 0) {
+ error("Control %s load error: %s\n", x->card, snd_strerror(err));
+ return err;
+ }
+ elem = snd_hctl_find_elem(hctl, id);
+ if (elem)
+ show_control(x->card, " ", elem, LEVEL_BASIC | LEVEL_ID);
+ else
+ printf("Could not find the specified element\n");
+ snd_hctl_close(hctl);
+ }
+}
+static void amixer_cget(t_amixer *x, t_symbol *s, int argc, t_atom *argv)
+{
+ amixer_control(x, argc, argv, 1);
+}
+static void amixer_cset(t_amixer *x, t_symbol *s, int argc, t_atom *argv)
+{
+ amixer_control(x, argc, argv, 0);
+}
+
+static void amixer_sget(t_amixer *x, t_symbol *s, int argc, t_atom *argv)
+{
+}
+static void amixer_sset(t_amixer *x, t_symbol *s, int argc, t_atom *argv)
+{
+}
+static void amixer_card(t_amixer *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if(1==argc){
+ int id=-1;
+ if(A_FLOAT==argv->a_type)id=atom_getint(argv);
+ else id=snd_card_get_index(atom_getsymbol(argv)->s_name);
+ if (id >= 0 && id < 32)
+ sprintf(x->card, "hw:%i", id);
+ else {
+ pd_error(x, "invalid card %d", id);
+ return;
+ }
+
+
+ } else error("amixer: can only be integer of symbol");
+}
+
+#endif /* ALSA */
+
+static void amixer_free(t_amixer *x){
+#ifdef HAVE_ALSA
+
+
+#endif /* ALSA */
+}
+
+
+static void *amixer_new(void)
+{
+ t_amixer *x = (t_amixer *)pd_new(amixer_class);
+ outlet_new(&x->x_obj, 0);
+ x->x_error=outlet_new(&x->x_obj, 0);
+
+#ifndef HAVE_ALSA
+ error("amixer: compiled without ALSA-suppor !!");
+ error("amixer: no functionality enabled!");
+#else
+ sprintf(x->card, "default");
+
+#endif /* !ALSA */
+
+ return (x);
+}
+
+
+void amixer_setup(void)
+{
+ post("amixer: ALSA soundcard control");
+ post(" Copyright (C) 1999-2000 Jaroslav Kysela");
+ post(" ported to pure-data by IOhannes m zmölnig 2005");
+ post(" institute of electronic music and acoustics (iem)");
+ post(" published under the GNU General Public License version 2");
+#ifdef AMIXER_VERSION
+ startpost(" version:"AMIXER_VERSION);
+#endif
+ post("\tcompiled: "__DATE__"");
+
+ amixer_class = class_new(gensym("amixer"), (t_newmethod)amixer_new, (t_method)amixer_free,
+ sizeof(t_amixer), 0, 0);
+#ifdef HAVE_ALSA
+ class_addmethod(amixer_class, (t_method)amixer_card,gensym("card"), A_GIMME, 0);
+ class_addmethod(amixer_class, (t_method)amixer_cget,gensym("get"), A_GIMME, 0);
+ class_addmethod(amixer_class, (t_method)amixer_cset,gensym("set"), A_GIMME, 0);
+ class_addmethod(amixer_class, (t_method)amixer_cget,gensym("cget"), A_GIMME, 0);
+ class_addmethod(amixer_class, (t_method)amixer_cset,gensym("cset"), A_GIMME, 0);
+ class_addmethod(amixer_class, (t_method)amixer_sget,gensym("sget"), A_GIMME, 0);
+ class_addmethod(amixer_class, (t_method)amixer_sset,gensym("sset"), A_GIMME, 0);
+
+ // class_addmethod(amixer_class, (t_method)amixer_listdevices,gensym(""), A_DEFSYM, 0);
+ class_addbang(amixer_class, (t_method)amixer_bang);
+#endif /* ALSA */
+}
+