]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Completed control and mixer API
authorAbramo Bagnara <abramo@alsa-project.org>
Fri, 9 Feb 2001 11:20:31 +0000 (11:20 +0000)
committerAbramo Bagnara <abramo@alsa-project.org>
Fri, 9 Feb 2001 11:20:31 +0000 (11:20 +0000)
23 files changed:
aserver/aserver.c
include/Makefile.am
include/aserver.h
include/control.h
include/control_m4.h
include/local.h
include/mixer.h
include/mixer_m4.h [new file with mode: 0644]
src/conf.c
src/control/Makefile.am
src/control/control.c
src/control/control_hw.c
src/control/control_local.h
src/control/control_m4.c
src/control/control_shm.c
src/control/controls.c
src/control/hcontrol.c [new file with mode: 0644]
src/mixer/Makefile.am
src/mixer/bag.c [moved from src/control/bag.c with 59% similarity]
src/mixer/mixer.c
src/mixer/mixer_local.h
src/mixer/mixer_m4.c [new file with mode: 0644]
src/mixer/simple.c

index 95233071497de0b923b4b2f00c986c8b8dfe19be..90f186505f46126c05fb33564b6bd90f83a280c6 100644 (file)
@@ -555,8 +555,6 @@ int ctl_shm_close(client_t *client)
        return 0;
 }
 
-extern int snd_ctl_read1(snd_ctl_t *ctl, snd_ctl_event_t *event);
-
 int ctl_shm_cmd(client_t *client)
 {
        snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
@@ -571,28 +569,31 @@ int ctl_shm_cmd(client_t *client)
        ctrl->cmd = 0;
        ctl = client->device.control.handle;
        switch (cmd) {
+       case SND_CTL_IOCTL_ASYNC:
+               ctrl->result = snd_ctl_async(ctl, ctrl->u.async.sig, ctrl->u.async.pid);
+               break;
        case SNDRV_CTL_IOCTL_INFO:
                ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.hw_info);
                break;
-       case SNDRV_CTL_IOCTL_ELEMENT_LIST:
+       case SNDRV_CTL_IOCTL_ELEM_LIST:
        {
                size_t maxsize = CTL_SHM_DATA_MAXLEN;
-               if (ctrl->u.clist.space * sizeof(*ctrl->u.clist.pids) > maxsize) {
+               if (ctrl->u.element_list.space * sizeof(*ctrl->u.element_list.pids) > maxsize) {
                        ctrl->result = -EFAULT;
                        break;
                }
-               ctrl->u.clist.pids = (snd_ctl_element_id_t*) ctrl->data;
-               ctrl->result = snd_ctl_clist(ctl, &ctrl->u.clist);
+               ctrl->u.element_list.pids = (snd_ctl_elem_id_t*) ctrl->data;
+               ctrl->result = snd_ctl_elem_list(ctl, &ctrl->u.element_list);
                break;
        }
-       case SNDRV_CTL_IOCTL_ELEMENT_INFO:
-               ctrl->result = snd_ctl_element_info(ctl, &ctrl->u.cinfo);
+       case SNDRV_CTL_IOCTL_ELEM_INFO:
+               ctrl->result = snd_ctl_elem_info(ctl, &ctrl->u.element_info);
                break;
-       case SNDRV_CTL_IOCTL_ELEMENT_READ:
-               ctrl->result = snd_ctl_element_read(ctl, &ctrl->u.cread);
+       case SNDRV_CTL_IOCTL_ELEM_READ:
+               ctrl->result = snd_ctl_elem_read(ctl, &ctrl->u.element_read);
                break;
-       case SNDRV_CTL_IOCTL_ELEMENT_WRITE:
-               ctrl->result = snd_ctl_element_write(ctl, &ctrl->u.cwrite);
+       case SNDRV_CTL_IOCTL_ELEM_WRITE:
+               ctrl->result = snd_ctl_elem_write(ctl, &ctrl->u.element_write);
                break;
        case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
                ctrl->result = snd_ctl_hwdep_next_device(ctl, &ctrl->u.device);
@@ -619,7 +620,7 @@ int ctl_shm_cmd(client_t *client)
                ctrl->result = snd_ctl_rawmidi_prefer_subdevice(ctl, ctrl->u.rawmidi_prefer_subdevice);
                break;
        case SND_CTL_IOCTL_READ:
-               ctrl->result = snd_ctl_read1(ctl, &ctrl->u.read);
+               ctrl->result = snd_ctl_read(ctl, &ctrl->u.read);
                break;
        case SND_CTL_IOCTL_CLOSE:
                client->ops->close(client);
index c0d741ca66c17577cbdc59d9ff64c7afdf9572db..7a5ca8ccd02335b8089842e1eddb5a8cd51106a8 100644 (file)
@@ -3,9 +3,10 @@ sysinclude_HEADERS = asoundlib.h
 
 # This is the order they will be concatenated into asoundlib.h!
 #
-header_files=header.h version.h global.h input.h output.h error.h mixer.h \
+header_files=header.h version.h global.h input.h output.h error.h \
             pcm.h pcm_m4.h rawmidi.h rawmidi_m4.h timer.h \
             hwdep.h hwdep_m4.h control.h control_m4.h \
+            mixer.h mixer_m4.h \
             seq.h seqmid.h seq_midi_event.h \
              conv.h instr.h conf.h footer.h
 
index cfa99d429e184d4409b074156285759043c6183f..b564ecc021201e60ba40886b01ad039e25b72acb 100644 (file)
@@ -83,17 +83,22 @@ typedef struct {
 #define SND_CTL_IOCTL_READ             _IOR('U', 0xf1, snd_ctl_event_t)
 #define SND_CTL_IOCTL_CLOSE            _IO ('U', 0xf2)
 #define SND_CTL_IOCTL_POLL_DESCRIPTOR  _IO ('U', 0xf3)
+#define SND_CTL_IOCTL_ASYNC            _IO ('U', 0xf4)
 
 typedef struct {
        int result;
        int cmd;
        union {
+               struct {
+                       int sig;
+                       pid_t pid;
+               } async;
                int device;
                snd_ctl_card_info_t hw_info;
-               snd_ctl_element_list_t clist;
-               snd_ctl_element_info_t cinfo;
-               snd_ctl_element_t cread;
-               snd_ctl_element_t cwrite;
+               snd_ctl_elem_list_t element_list;
+               snd_ctl_elem_info_t element_info;
+               snd_ctl_elem_t element_read;
+               snd_ctl_elem_t element_write;
                snd_hwdep_info_t hwdep_info;
                snd_pcm_info_t pcm_info;
                int pcm_prefer_subdevice;
index 5174563f82e7ad6a3a6362935c0e0ae75cda215a..05fc27b52c9e5bb35e3267e74aa26dacc0fd14bc 100644 (file)
@@ -7,21 +7,21 @@
 
 typedef struct sndrv_aes_iec958 snd_aes_iec958_t;
 typedef struct _snd_ctl_card_info snd_ctl_card_info_t;
-typedef struct _snd_ctl_element_id snd_ctl_element_id_t;
-typedef struct _snd_ctl_element_list snd_ctl_element_list_t;
-typedef struct _snd_ctl_element_info snd_ctl_element_info_t;
-typedef struct _snd_ctl_element snd_ctl_element_t;
+typedef struct _snd_ctl_elem_id snd_ctl_elem_id_t;
+typedef struct _snd_ctl_elem_list snd_ctl_elem_list_t;
+typedef struct _snd_ctl_elem_info snd_ctl_elem_info_t;
+typedef struct _snd_ctl_elem snd_ctl_elem_t;
 typedef struct _snd_ctl_event snd_ctl_event_t;
 
 #ifdef SND_ENUM_TYPECHECK
 typedef struct __snd_card_type *snd_card_type_t;
-typedef struct __snd_ctl_element_type *snd_ctl_element_type_t;
-typedef struct __snd_ctl_element_iface *snd_ctl_element_iface_t;
+typedef struct __snd_ctl_elem_type *snd_ctl_elem_type_t;
+typedef struct __snd_ctl_elem_iface *snd_ctl_elem_iface_t;
 typedef struct __snd_ctl_event_type *snd_ctl_event_type_t;
 #else
 typedef enum sndrv_card_type snd_card_type_t;
-typedef enum sndrv_ctl_element_type snd_ctl_element_type_t;
-typedef enum sndrv_ctl_element_iface snd_ctl_element_iface_t;
+typedef enum sndrv_ctl_elem_type snd_ctl_elem_type_t;
+typedef enum sndrv_ctl_elem_iface snd_ctl_elem_iface_t;
 typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
 #endif
 
@@ -95,22 +95,22 @@ typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
 #define SND_CARD_TYPE_VIA8233 ((snd_card_type_t) SNDRV_CARD_TYPE_VIA8233)
 #define SND_CARD_TYPE_LAST ((snd_card_type_t) SNDRV_CARD_TYPE_LAST)
 
-#define SND_CTL_ELEMENT_TYPE_NONE ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_NONE)
-#define SND_CTL_ELEMENT_TYPE_BOOLEAN ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_BOOLEAN)
-#define SND_CTL_ELEMENT_TYPE_INTEGER ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_INTEGER)
-#define SND_CTL_ELEMENT_TYPE_ENUMERATED ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_ENUMERATED)
-#define SND_CTL_ELEMENT_TYPE_BYTES ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_BYTES)
-#define SND_CTL_ELEMENT_TYPE_IEC958 ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_IEC958)
-#define SND_CTL_ELEMENT_TYPE_LAST ((snd_ctl_element_type_t) SNDRV_CTL_ELEMENT_TYPE_LAST)
-
-#define SND_CTL_ELEMENT_IFACE_CARD ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_CARD)
-#define SND_CTL_ELEMENT_IFACE_HWDEP ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_HWDEP)
-#define SND_CTL_ELEMENT_IFACE_MIXER ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_MIXER)
-#define SND_CTL_ELEMENT_IFACE_PCM ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_PCM)
-#define SND_CTL_ELEMENT_IFACE_RAWMIDI ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_RAWMIDI)
-#define SND_CTL_ELEMENT_IFACE_TIMER ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_TIMER)
-#define SND_CTL_ELEMENT_IFACE_SEQUENCER ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_SEQUENCER)
-#define SND_CTL_ELEMENT_IFACE_LAST ((snd_ctl_element_iface_t) SNDRV_CTL_ELEMENT_IFACE_LAST)
+#define SND_CTL_ELEM_TYPE_NONE ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_NONE)
+#define SND_CTL_ELEM_TYPE_BOOLEAN ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_BOOLEAN)
+#define SND_CTL_ELEM_TYPE_INTEGER ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_INTEGER)
+#define SND_CTL_ELEM_TYPE_ENUMERATED ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_ENUMERATED)
+#define SND_CTL_ELEM_TYPE_BYTES ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_BYTES)
+#define SND_CTL_ELEM_TYPE_IEC958 ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_IEC958)
+#define SND_CTL_ELEM_TYPE_LAST ((snd_ctl_elem_type_t) SNDRV_CTL_ELEM_TYPE_LAST)
+
+#define SND_CTL_ELEM_IFACE_CARD ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_CARD)
+#define SND_CTL_ELEM_IFACE_HWDEP ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_HWDEP)
+#define SND_CTL_ELEM_IFACE_MIXER ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_MIXER)
+#define SND_CTL_ELEM_IFACE_PCM ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_PCM)
+#define SND_CTL_ELEM_IFACE_RAWMIDI ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_RAWMIDI)
+#define SND_CTL_ELEM_IFACE_TIMER ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_TIMER)
+#define SND_CTL_ELEM_IFACE_SEQUENCER ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_SEQUENCER)
+#define SND_CTL_ELEM_IFACE_LAST ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_LAST)
 
 #define SND_CTL_EVENT_REBUILD ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_REBUILD)
 #define SND_CTL_EVENT_VALUE ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_VALUE)
@@ -136,7 +136,6 @@ typedef enum _snd_ctl_type snd_ctl_type_t;
 #define SND_CTL_TYPE_INET ((snd_ctl_type_t) SND_CTL_TYPE_INET)
 
 typedef struct _snd_ctl snd_ctl_t;
-typedef struct _snd_ctl_callbacks snd_ctl_callbacks_t;
 
 #ifdef __cplusplus
 extern "C" {
@@ -155,35 +154,37 @@ int snd_defaults_pcm_device(void);
 int snd_defaults_rawmidi_card(void);
 int snd_defaults_rawmidi_device(void);
 
-snd_ctl_type_t snd_ctl_type(snd_ctl_t *handle);
-int snd_ctl_open(snd_ctl_t **handle, char *name);
-int snd_ctl_close(snd_ctl_t *handle);
-int snd_ctl_card(snd_ctl_t *handle);
-int snd_ctl_poll_descriptor(snd_ctl_t *handle);
-int snd_ctl_card_info(snd_ctl_t *handle, snd_ctl_card_info_t *info);
-int snd_ctl_clist(snd_ctl_t *handle, snd_ctl_element_list_t * list);
-int snd_ctl_element_info(snd_ctl_t *handle, snd_ctl_element_info_t * sw);
-int snd_ctl_element_read(snd_ctl_t *handle, snd_ctl_element_t * control);
-int snd_ctl_element_write(snd_ctl_t *handle, snd_ctl_element_t * control);
-int snd_ctl_hwdep_next_device(snd_ctl_t *handle, int * device);
-int snd_ctl_hwdep_info(snd_ctl_t *handle, snd_hwdep_info_t * info);
-int snd_ctl_pcm_next_device(snd_ctl_t *handle, int *device);
-int snd_ctl_pcm_info(snd_ctl_t *handle, snd_pcm_info_t * info);
-int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *handle, int subdev);
-int snd_ctl_rawmidi_next_device(snd_ctl_t *handle, int * device);
-int snd_ctl_rawmidi_info(snd_ctl_t *handle, snd_rawmidi_info_t * info);
-int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *handle, int subdev);
-
-int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks);
-
-void snd_ctl_element_set_bytes(snd_ctl_element_t *obj, void *data, size_t size);
-
-const char *snd_ctl_element_type_name(snd_ctl_element_type_t type);
-const char *snd_ctl_element_iface_name(snd_ctl_element_iface_t iface);
+snd_ctl_type_t snd_ctl_type(snd_ctl_t *ctl);
+int snd_ctl_open(snd_ctl_t **ctl, char *name);
+int snd_ctl_close(snd_ctl_t *ctl);
+int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock);
+int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid);
+int snd_ctl_poll_descriptor(snd_ctl_t *ctl);
+int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info);
+int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t * list);
+int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info);
+int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_t *value);
+int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_t *value);
+int snd_ctl_hwdep_next_device(snd_ctl_t *ctl, int * device);
+int snd_ctl_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info);
+int snd_ctl_pcm_next_device(snd_ctl_t *ctl, int *device);
+int snd_ctl_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info);
+int snd_ctl_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev);
+int snd_ctl_rawmidi_next_device(snd_ctl_t *ctl, int * device);
+int snd_ctl_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info);
+int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev);
+
+int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_event_t *event);
+int snd_ctl_wait(snd_ctl_t *ctl, int timeout);
+
+void snd_ctl_elem_set_bytes(snd_ctl_elem_t *obj, void *data, size_t size);
+
+const char *snd_ctl_elem_type_name(snd_ctl_elem_type_t type);
+const char *snd_ctl_elem_iface_name(snd_ctl_elem_iface_t iface);
 const char *snd_ctl_event_type_name(snd_ctl_event_type_t type);
 
-int snd_ctl_element_list_alloc_space(snd_ctl_element_list_t *obj, unsigned int entries);
-void snd_ctl_element_list_free_space(snd_ctl_element_list_t *obj);
+int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries);
+void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj);
 
 #ifdef __cplusplus
 }
@@ -193,41 +194,35 @@ void snd_ctl_element_list_free_space(snd_ctl_element_list_t *obj);
  *  Highlevel API for controls
  */
 
-typedef struct _snd_hctl_element_list snd_hctl_element_list_t;
-typedef struct _snd_hctl_element snd_hctl_element_t;
+typedef struct _snd_hctl_elem snd_hctl_elem_t;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef int (*snd_ctl_hsort_t)(const snd_hctl_element_t *c1, const snd_hctl_element_t *c2);
-typedef void (*snd_ctl_hcallback_rebuild_t)(snd_ctl_t *handle, void *private_data);
-typedef void (*snd_ctl_hcallback_add_t)(snd_ctl_t *handle, void *private_data, snd_hctl_element_t *helem);
-typedef void (*snd_hctl_element_callback_t)(snd_ctl_t *handle, snd_hctl_element_t *helem);
-typedef void (*snd_hctl_element_private_free_t)(snd_hctl_element_t *helem);
-
-int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t csort);
-int snd_ctl_hfree(snd_ctl_t *handle);
-snd_hctl_element_t *snd_ctl_hfirst(snd_ctl_t *handle);
-snd_hctl_element_t *snd_ctl_hlast(snd_ctl_t *handle);
-snd_hctl_element_t *snd_ctl_hnext(snd_ctl_t *handle, snd_hctl_element_t *helem);
-snd_hctl_element_t *snd_ctl_hprev(snd_ctl_t *handle, snd_hctl_element_t *helem);
-int snd_ctl_hcount(snd_ctl_t *handle);
-snd_hctl_element_t *snd_ctl_hfind(snd_ctl_t *handle, snd_ctl_element_id_t *id);
-int snd_ctl_hlist(snd_ctl_t *handle, snd_hctl_element_list_t *hlist);
-int snd_ctl_hsort(const snd_hctl_element_t *c1, const snd_hctl_element_t *c2);
-int snd_ctl_hresort(snd_ctl_t *handle, snd_ctl_hsort_t csort);
-int snd_ctl_hcallback_rebuild(snd_ctl_t *handle, snd_ctl_hcallback_rebuild_t callback, void *private_data);
-int snd_ctl_hcallback_add(snd_ctl_t *handle, snd_ctl_hcallback_add_t callback, void *private_data);
-int snd_ctl_hevent(snd_ctl_t *handle);
-
-int snd_ctl_hbag_create(void **bag);
-int snd_ctl_hbag_destroy(void **bag, void (*hctl_element_free)(snd_hctl_element_t *helem));
-int snd_ctl_hbag_add(void **bag, snd_hctl_element_t *helem);
-int snd_ctl_hbag_del(void **bag, snd_hctl_element_t *helem);
-snd_hctl_element_t *snd_ctl_hbag_find(void **bag, snd_ctl_element_id_t *id);
-int snd_hctl_element_list_alloc_space(snd_hctl_element_list_t *obj, unsigned int entries);
-void snd_hctl_element_list_free_space(snd_hctl_element_list_t *obj);
+typedef int (*snd_hctl_compare_t)(const snd_hctl_elem_t *e1,
+                                 const snd_hctl_elem_t *e2);
+typedef int (*snd_hctl_callback_t)(snd_ctl_t *ctl,
+                                  snd_ctl_event_type_t event,
+                                  snd_hctl_elem_t *elem);
+typedef int (*snd_hctl_elem_callback_t)(snd_hctl_elem_t *elem,
+                                          snd_ctl_event_type_t event);
+
+int snd_hctl_build(snd_ctl_t *ctl);
+snd_hctl_elem_t *snd_hctl_first_elem(snd_ctl_t *ctl);
+snd_hctl_elem_t *snd_hctl_last_elem(snd_ctl_t *ctl);
+snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem);
+snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem);
+int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t *info);
+int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_t * value);
+int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_t * value);
+unsigned int snd_hctl_get_count(snd_ctl_t *ctl);
+snd_hctl_elem_t *snd_hctl_find_elem(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id);
+void snd_hctl_set_callback(snd_ctl_t *ctl, snd_hctl_callback_t callback);
+void snd_hctl_set_callback_private(snd_ctl_t *ctl, void *private);
+void *snd_hctl_get_callback_private(snd_ctl_t *ctl);
+int snd_hctl_event(snd_ctl_t *ctl, snd_ctl_event_t *event);
+int snd_hctl_events(snd_ctl_t *ctl);
 
 #ifdef __cplusplus
 }
index 650936f8dab361dcdb0149bc45c6226ac8ab86d2..c9abc114d33cc07b1668ea9dbd82e0bd5a5b7e76 100644 (file)
@@ -2,35 +2,35 @@
 extern "C" {
 #endif
 
-size_t snd_ctl_element_id_sizeof();
-#define snd_ctl_element_id_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_element_id_t *) alloca(snd_ctl_element_id_sizeof()); memset(*ptr, 0, snd_ctl_element_id_sizeof()); 0; })
-int snd_ctl_element_id_malloc(snd_ctl_element_id_t **ptr);
-void snd_ctl_element_id_free(snd_ctl_element_id_t *obj);
-void snd_ctl_element_id_copy(snd_ctl_element_id_t *dst, const snd_ctl_element_id_t *src);
+size_t snd_ctl_elem_id_sizeof();
+#define snd_ctl_elem_id_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_elem_id_t *) alloca(snd_ctl_elem_id_sizeof()); memset(*ptr, 0, snd_ctl_elem_id_sizeof()); 0; })
+int snd_ctl_elem_id_malloc(snd_ctl_elem_id_t **ptr);
+void snd_ctl_elem_id_free(snd_ctl_elem_id_t *obj);
+void snd_ctl_elem_id_copy(snd_ctl_elem_id_t *dst, const snd_ctl_elem_id_t *src);
 
-unsigned int snd_ctl_element_id_get_numid(const snd_ctl_element_id_t *obj);
+unsigned int snd_ctl_elem_id_get_numid(const snd_ctl_elem_id_t *obj);
 
-snd_ctl_element_iface_t snd_ctl_element_id_get_interface(const snd_ctl_element_id_t *obj);
+snd_ctl_elem_iface_t snd_ctl_elem_id_get_interface(const snd_ctl_elem_id_t *obj);
 
-unsigned int snd_ctl_element_id_get_device(const snd_ctl_element_id_t *obj);
+unsigned int snd_ctl_elem_id_get_device(const snd_ctl_elem_id_t *obj);
 
-unsigned int snd_ctl_element_id_get_subdevice(const snd_ctl_element_id_t *obj);
+unsigned int snd_ctl_elem_id_get_subdevice(const snd_ctl_elem_id_t *obj);
 
-const char *snd_ctl_element_id_get_name(const snd_ctl_element_id_t *obj);
+const char *snd_ctl_elem_id_get_name(const snd_ctl_elem_id_t *obj);
 
-unsigned int snd_ctl_element_id_get_index(const snd_ctl_element_id_t *obj);
+unsigned int snd_ctl_elem_id_get_index(const snd_ctl_elem_id_t *obj);
 
-void snd_ctl_element_id_set_numid(snd_ctl_element_id_t *obj, unsigned int val);
+void snd_ctl_elem_id_set_numid(snd_ctl_elem_id_t *obj, unsigned int val);
 
-void snd_ctl_element_id_set_interface(snd_ctl_element_id_t *obj, snd_ctl_element_iface_t val);
+void snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t *obj, snd_ctl_elem_iface_t val);
 
-void snd_ctl_element_id_set_device(snd_ctl_element_id_t *obj, unsigned int val);
+void snd_ctl_elem_id_set_device(snd_ctl_elem_id_t *obj, unsigned int val);
 
-void snd_ctl_element_id_set_subdevice(snd_ctl_element_id_t *obj, unsigned int val);
+void snd_ctl_elem_id_set_subdevice(snd_ctl_elem_id_t *obj, unsigned int val);
 
-void snd_ctl_element_id_set_name(snd_ctl_element_id_t *obj, const char *val);
+void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val);
 
-void snd_ctl_element_id_set_index(snd_ctl_element_id_t *obj, unsigned int val);
+void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val);
 
 size_t snd_ctl_card_info_sizeof();
 #define snd_ctl_card_info_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_card_info_t *) alloca(snd_ctl_card_info_sizeof()); memset(*ptr, 0, snd_ctl_card_info_sizeof()); 0; })
@@ -64,9 +64,9 @@ snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj);
 
 unsigned int snd_ctl_event_get_numid(const snd_ctl_event_t *obj);
 
-void snd_ctl_event_get_id(const snd_ctl_event_t *obj, snd_ctl_element_id_t *ptr);
+void snd_ctl_event_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr);
 
-snd_ctl_element_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj);
+snd_ctl_elem_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj);
 
 unsigned int snd_ctl_event_get_device(const snd_ctl_event_t *obj);
 
@@ -76,207 +76,175 @@ const char *snd_ctl_event_get_name(const snd_ctl_event_t *obj);
 
 unsigned int snd_ctl_event_get_index(const snd_ctl_event_t *obj);
 
-size_t snd_ctl_element_list_sizeof();
-#define snd_ctl_element_list_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_element_list_t *) alloca(snd_ctl_element_list_sizeof()); memset(*ptr, 0, snd_ctl_element_list_sizeof()); 0; })
-int snd_ctl_element_list_malloc(snd_ctl_element_list_t **ptr);
-void snd_ctl_element_list_free(snd_ctl_element_list_t *obj);
-void snd_ctl_element_list_copy(snd_ctl_element_list_t *dst, const snd_ctl_element_list_t *src);
+size_t snd_ctl_elem_list_sizeof();
+#define snd_ctl_elem_list_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_elem_list_t *) alloca(snd_ctl_elem_list_sizeof()); memset(*ptr, 0, snd_ctl_elem_list_sizeof()); 0; })
+int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr);
+void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj);
+void snd_ctl_elem_list_copy(snd_ctl_elem_list_t *dst, const snd_ctl_elem_list_t *src);
 
-void snd_ctl_element_list_set_offset(snd_ctl_element_list_t *obj, unsigned int val);
+void snd_ctl_elem_list_set_offset(snd_ctl_elem_list_t *obj, unsigned int val);
 
-unsigned int snd_ctl_element_list_get_used(const snd_ctl_element_list_t *obj);
+unsigned int snd_ctl_elem_list_get_used(const snd_ctl_elem_list_t *obj);
 
-unsigned int snd_ctl_element_list_get_count(const snd_ctl_element_list_t *obj);
+unsigned int snd_ctl_elem_list_get_count(const snd_ctl_elem_list_t *obj);
 
-void snd_ctl_element_list_get_id(const snd_ctl_element_list_t *obj, unsigned int idx, snd_ctl_element_id_t *ptr);
+void snd_ctl_elem_list_get_id(const snd_ctl_elem_list_t *obj, unsigned int idx, snd_ctl_elem_id_t *ptr);
 
-unsigned int snd_ctl_element_list_get_numid(const snd_ctl_element_list_t *obj, unsigned int idx);
+unsigned int snd_ctl_elem_list_get_numid(const snd_ctl_elem_list_t *obj, unsigned int idx);
 
-snd_ctl_element_iface_t snd_ctl_element_list_get_interface(const snd_ctl_element_list_t *obj, unsigned int idx);
+snd_ctl_elem_iface_t snd_ctl_elem_list_get_interface(const snd_ctl_elem_list_t *obj, unsigned int idx);
 
-unsigned int snd_ctl_element_list_get_device(const snd_ctl_element_list_t *obj, unsigned int idx);
+unsigned int snd_ctl_elem_list_get_device(const snd_ctl_elem_list_t *obj, unsigned int idx);
 
-unsigned int snd_ctl_element_list_get_subdevice(const snd_ctl_element_list_t *obj, unsigned int idx);
+unsigned int snd_ctl_elem_list_get_subdevice(const snd_ctl_elem_list_t *obj, unsigned int idx);
 
-const char *snd_ctl_element_list_get_name(const snd_ctl_element_list_t *obj, unsigned int idx);
+const char *snd_ctl_elem_list_get_name(const snd_ctl_elem_list_t *obj, unsigned int idx);
 
-unsigned int snd_ctl_element_list_get_index(const snd_ctl_element_list_t *obj, unsigned int idx);
+unsigned int snd_ctl_elem_list_get_index(const snd_ctl_elem_list_t *obj, unsigned int idx);
 
-size_t snd_ctl_element_info_sizeof();
-#define snd_ctl_element_info_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_element_info_t *) alloca(snd_ctl_element_info_sizeof()); memset(*ptr, 0, snd_ctl_element_info_sizeof()); 0; })
-int snd_ctl_element_info_malloc(snd_ctl_element_info_t **ptr);
-void snd_ctl_element_info_free(snd_ctl_element_info_t *obj);
-void snd_ctl_element_info_copy(snd_ctl_element_info_t *dst, const snd_ctl_element_info_t *src);
+size_t snd_ctl_elem_info_sizeof();
+#define snd_ctl_elem_info_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_elem_info_t *) alloca(snd_ctl_elem_info_sizeof()); memset(*ptr, 0, snd_ctl_elem_info_sizeof()); 0; })
+int snd_ctl_elem_info_malloc(snd_ctl_elem_info_t **ptr);
+void snd_ctl_elem_info_free(snd_ctl_elem_info_t *obj);
+void snd_ctl_elem_info_copy(snd_ctl_elem_info_t *dst, const snd_ctl_elem_info_t *src);
 
-snd_ctl_element_type_t snd_ctl_element_info_get_type(const snd_ctl_element_info_t *obj);
+snd_ctl_elem_type_t snd_ctl_elem_info_get_type(const snd_ctl_elem_info_t *obj);
 
-int snd_ctl_element_info_is_readable(const snd_ctl_element_info_t *obj);
+int snd_ctl_elem_info_is_readable(const snd_ctl_elem_info_t *obj);
 
-int snd_ctl_element_info_is_writable(const snd_ctl_element_info_t *obj);
+int snd_ctl_elem_info_is_writable(const snd_ctl_elem_info_t *obj);
 
-int snd_ctl_element_info_is_volatile(const snd_ctl_element_info_t *obj);
+int snd_ctl_elem_info_is_volatile(const snd_ctl_elem_info_t *obj);
 
-int snd_ctl_element_info_is_inactive(const snd_ctl_element_info_t *obj);
+int snd_ctl_elem_info_is_inactive(const snd_ctl_elem_info_t *obj);
 
-int snd_ctl_element_info_is_locked(const snd_ctl_element_info_t *obj);
+int snd_ctl_elem_info_is_locked(const snd_ctl_elem_info_t *obj);
 
-int snd_ctl_element_info_is_indirect(const snd_ctl_element_info_t *obj);
+int snd_ctl_elem_info_is_indirect(const snd_ctl_elem_info_t *obj);
 
-unsigned int snd_ctl_element_info_get_count(const snd_ctl_element_info_t *obj);
+unsigned int snd_ctl_elem_info_get_count(const snd_ctl_elem_info_t *obj);
 
-long snd_ctl_element_info_get_min(const snd_ctl_element_info_t *obj);
+long snd_ctl_elem_info_get_min(const snd_ctl_elem_info_t *obj);
 
-long snd_ctl_element_info_get_max(const snd_ctl_element_info_t *obj);
+long snd_ctl_elem_info_get_max(const snd_ctl_elem_info_t *obj);
 
-long snd_ctl_element_info_get_step(const snd_ctl_element_info_t *obj);
+long snd_ctl_elem_info_get_step(const snd_ctl_elem_info_t *obj);
 
-unsigned int snd_ctl_element_info_get_items(const snd_ctl_element_info_t *obj);
+unsigned int snd_ctl_elem_info_get_items(const snd_ctl_elem_info_t *obj);
 
-void snd_ctl_element_info_set_item(snd_ctl_element_info_t *obj, unsigned int val);
+void snd_ctl_elem_info_set_item(snd_ctl_elem_info_t *obj, unsigned int val);
 
-const char *snd_ctl_element_info_get_item_name(const snd_ctl_element_info_t *obj);
+const char *snd_ctl_elem_info_get_item_name(const snd_ctl_elem_info_t *obj);
 
-void snd_ctl_element_info_get_id(const snd_ctl_element_info_t *obj, snd_ctl_element_id_t *ptr);
+void snd_ctl_elem_info_get_id(const snd_ctl_elem_info_t *obj, snd_ctl_elem_id_t *ptr);
 
-unsigned int snd_ctl_element_info_get_numid(const snd_ctl_element_info_t *obj);
+unsigned int snd_ctl_elem_info_get_numid(const snd_ctl_elem_info_t *obj);
 
-snd_ctl_element_iface_t snd_ctl_element_info_get_interface(const snd_ctl_element_info_t *obj);
+snd_ctl_elem_iface_t snd_ctl_elem_info_get_interface(const snd_ctl_elem_info_t *obj);
 
-unsigned int snd_ctl_element_info_get_device(const snd_ctl_element_info_t *obj);
+unsigned int snd_ctl_elem_info_get_device(const snd_ctl_elem_info_t *obj);
 
-unsigned int snd_ctl_element_info_get_subdevice(const snd_ctl_element_info_t *obj);
+unsigned int snd_ctl_elem_info_get_subdevice(const snd_ctl_elem_info_t *obj);
 
-const char *snd_ctl_element_info_get_name(const snd_ctl_element_info_t *obj);
+const char *snd_ctl_elem_info_get_name(const snd_ctl_elem_info_t *obj);
 
-unsigned int snd_ctl_element_info_get_index(const snd_ctl_element_info_t *obj);
+unsigned int snd_ctl_elem_info_get_index(const snd_ctl_elem_info_t *obj);
 
-void snd_ctl_element_info_set_id(snd_ctl_element_info_t *obj, const snd_ctl_element_id_t *ptr);
+void snd_ctl_elem_info_set_id(snd_ctl_elem_info_t *obj, const snd_ctl_elem_id_t *ptr);
 
-void snd_ctl_element_info_set_numid(snd_ctl_element_info_t *obj, unsigned int val);
+void snd_ctl_elem_info_set_numid(snd_ctl_elem_info_t *obj, unsigned int val);
 
-void snd_ctl_element_info_set_interface(snd_ctl_element_info_t *obj, snd_ctl_element_iface_t val);
+void snd_ctl_elem_info_set_interface(snd_ctl_elem_info_t *obj, snd_ctl_elem_iface_t val);
 
-void snd_ctl_element_info_set_device(snd_ctl_element_info_t *obj, unsigned int val);
+void snd_ctl_elem_info_set_device(snd_ctl_elem_info_t *obj, unsigned int val);
 
-void snd_ctl_element_info_set_subdevice(snd_ctl_element_info_t *obj, unsigned int val);
+void snd_ctl_elem_info_set_subdevice(snd_ctl_elem_info_t *obj, unsigned int val);
 
-void snd_ctl_element_info_set_name(snd_ctl_element_info_t *obj, const char *val);
+void snd_ctl_elem_info_set_name(snd_ctl_elem_info_t *obj, const char *val);
 
-void snd_ctl_element_info_set_index(snd_ctl_element_info_t *obj, unsigned int val);
+void snd_ctl_elem_info_set_index(snd_ctl_elem_info_t *obj, unsigned int val);
 
-size_t snd_ctl_element_sizeof();
-#define snd_ctl_element_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_element_t *) alloca(snd_ctl_element_sizeof()); memset(*ptr, 0, snd_ctl_element_sizeof()); 0; })
-int snd_ctl_element_malloc(snd_ctl_element_t **ptr);
-void snd_ctl_element_free(snd_ctl_element_t *obj);
-void snd_ctl_element_copy(snd_ctl_element_t *dst, const snd_ctl_element_t *src);
+size_t snd_ctl_elem_sizeof();
+#define snd_ctl_elem_alloca(ptr) ({ assert(ptr); *ptr = (snd_ctl_elem_t *) alloca(snd_ctl_elem_sizeof()); memset(*ptr, 0, snd_ctl_elem_sizeof()); 0; })
+int snd_ctl_elem_malloc(snd_ctl_elem_t **ptr);
+void snd_ctl_elem_free(snd_ctl_elem_t *obj);
+void snd_ctl_elem_copy(snd_ctl_elem_t *dst, const snd_ctl_elem_t *src);
 
-void snd_ctl_element_get_id(const snd_ctl_element_t *obj, snd_ctl_element_id_t *ptr);
+void snd_ctl_elem_get_id(const snd_ctl_elem_t *obj, snd_ctl_elem_id_t *ptr);
 
-unsigned int snd_ctl_element_get_numid(const snd_ctl_element_t *obj);
+unsigned int snd_ctl_elem_get_numid(const snd_ctl_elem_t *obj);
 
-snd_ctl_element_iface_t snd_ctl_element_get_interface(const snd_ctl_element_t *obj);
+snd_ctl_elem_iface_t snd_ctl_elem_get_interface(const snd_ctl_elem_t *obj);
 
-unsigned int snd_ctl_element_get_device(const snd_ctl_element_t *obj);
+unsigned int snd_ctl_elem_get_device(const snd_ctl_elem_t *obj);
 
-unsigned int snd_ctl_element_get_subdevice(const snd_ctl_element_t *obj);
+unsigned int snd_ctl_elem_get_subdevice(const snd_ctl_elem_t *obj);
 
-const char *snd_ctl_element_get_name(const snd_ctl_element_t *obj);
+const char *snd_ctl_elem_get_name(const snd_ctl_elem_t *obj);
 
-unsigned int snd_ctl_element_get_index(const snd_ctl_element_t *obj);
+unsigned int snd_ctl_elem_get_index(const snd_ctl_elem_t *obj);
 
-void snd_ctl_element_set_id(snd_ctl_element_t *obj, const snd_ctl_element_id_t *ptr);
+void snd_ctl_elem_set_id(snd_ctl_elem_t *obj, const snd_ctl_elem_id_t *ptr);
 
-void snd_ctl_element_set_numid(snd_ctl_element_t *obj, unsigned int val);
+void snd_ctl_elem_set_numid(snd_ctl_elem_t *obj, unsigned int val);
 
-void snd_ctl_element_set_interface(snd_ctl_element_t *obj, snd_ctl_element_iface_t val);
+void snd_ctl_elem_set_interface(snd_ctl_elem_t *obj, snd_ctl_elem_iface_t val);
 
-void snd_ctl_element_set_device(snd_ctl_element_t *obj, unsigned int val);
+void snd_ctl_elem_set_device(snd_ctl_elem_t *obj, unsigned int val);
 
-void snd_ctl_element_set_subdevice(snd_ctl_element_t *obj, unsigned int val);
+void snd_ctl_elem_set_subdevice(snd_ctl_elem_t *obj, unsigned int val);
 
-void snd_ctl_element_set_name(snd_ctl_element_t *obj, const char *val);
+void snd_ctl_elem_set_name(snd_ctl_elem_t *obj, const char *val);
 
-void snd_ctl_element_set_index(snd_ctl_element_t *obj, unsigned int val);
+void snd_ctl_elem_set_index(snd_ctl_elem_t *obj, unsigned int val);
 
-long snd_ctl_element_get_boolean(const snd_ctl_element_t *obj, unsigned int idx);
+long snd_ctl_elem_get_boolean(const snd_ctl_elem_t *obj, unsigned int idx);
 
-long snd_ctl_element_get_integer(const snd_ctl_element_t *obj, unsigned int idx);
+long snd_ctl_elem_get_integer(const snd_ctl_elem_t *obj, unsigned int idx);
 
-unsigned int snd_ctl_element_get_enumerated(const snd_ctl_element_t *obj, unsigned int idx);
+unsigned int snd_ctl_elem_get_enumerated(const snd_ctl_elem_t *obj, unsigned int idx);
 
-unsigned char snd_ctl_element_get_byte(const snd_ctl_element_t *obj, unsigned int idx);
+unsigned char snd_ctl_elem_get_byte(const snd_ctl_elem_t *obj, unsigned int idx);
 
-void snd_ctl_element_set_boolean(snd_ctl_element_t *obj, unsigned int idx, long val);
+void snd_ctl_elem_set_boolean(snd_ctl_elem_t *obj, unsigned int idx, long val);
 
-void snd_ctl_element_set_integer(snd_ctl_element_t *obj, unsigned int idx, long val);
+void snd_ctl_elem_set_integer(snd_ctl_elem_t *obj, unsigned int idx, long val);
 
-void snd_ctl_element_set_enumerated(snd_ctl_element_t *obj, unsigned int idx, unsigned int val);
+void snd_ctl_elem_set_enumerated(snd_ctl_elem_t *obj, unsigned int idx, unsigned int val);
 
-void snd_ctl_element_set_byte(snd_ctl_element_t *obj, unsigned int idx, unsigned char val);
+void snd_ctl_elem_set_byte(snd_ctl_elem_t *obj, unsigned int idx, unsigned char val);
 
-const void * snd_ctl_element_get_bytes(const snd_ctl_element_t *obj);
+const void * snd_ctl_elem_get_bytes(const snd_ctl_elem_t *obj);
 
-void snd_ctl_element_get_iec958(const snd_ctl_element_t *obj, snd_aes_iec958_t *ptr);
+void snd_ctl_elem_get_iec958(const snd_ctl_elem_t *obj, snd_aes_iec958_t *ptr);
 
-void snd_ctl_element_set_iec958(snd_ctl_element_t *obj, const snd_aes_iec958_t *ptr);
+void snd_ctl_elem_set_iec958(snd_ctl_elem_t *obj, const snd_aes_iec958_t *ptr);
 
-size_t snd_hctl_element_list_sizeof();
-#define snd_hctl_element_list_alloca(ptr) ({ assert(ptr); *ptr = (snd_hctl_element_list_t *) alloca(snd_hctl_element_list_sizeof()); memset(*ptr, 0, snd_hctl_element_list_sizeof()); 0; })
-int snd_hctl_element_list_malloc(snd_hctl_element_list_t **ptr);
-void snd_hctl_element_list_free(snd_hctl_element_list_t *obj);
-void snd_hctl_element_list_copy(snd_hctl_element_list_t *dst, const snd_hctl_element_list_t *src);
+size_t snd_hctl_elem_sizeof();
+#define snd_hctl_elem_alloca(ptr) ({ assert(ptr); *ptr = (snd_hctl_elem_t *) alloca(snd_hctl_elem_sizeof()); memset(*ptr, 0, snd_hctl_elem_sizeof()); 0; })
+int snd_hctl_elem_malloc(snd_hctl_elem_t **ptr);
+void snd_hctl_elem_free(snd_hctl_elem_t *obj);
+void snd_hctl_elem_copy(snd_hctl_elem_t *dst, const snd_hctl_elem_t *src);
 
-void snd_hctl_element_list_set_offset(snd_hctl_element_list_t *obj, unsigned int val);
+void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr);
 
-unsigned int snd_hctl_element_list_get_used(const snd_hctl_element_list_t *obj);
+unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj);
 
-unsigned int snd_hctl_element_list_get_count(const snd_hctl_element_list_t *obj);
+snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj);
 
-void snd_hctl_element_list_get_id(const snd_hctl_element_list_t *obj, unsigned int idx, snd_ctl_element_id_t *ptr);
+unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj);
 
-unsigned int snd_hctl_element_list_get_numid(const snd_hctl_element_list_t *obj, unsigned int idx);
+unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj);
 
-snd_ctl_element_iface_t snd_hctl_element_list_get_interface(const snd_hctl_element_list_t *obj, unsigned int idx);
+const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj);
 
-unsigned int snd_hctl_element_list_get_device(const snd_hctl_element_list_t *obj, unsigned int idx);
+unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj);
 
-unsigned int snd_hctl_element_list_get_subdevice(const snd_hctl_element_list_t *obj, unsigned int idx);
+void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val);
 
-const char *snd_hctl_element_list_get_name(const snd_hctl_element_list_t *obj, unsigned int idx);
+void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj);
 
-unsigned int snd_hctl_element_list_get_index(const snd_hctl_element_list_t *obj, unsigned int idx);
-
-size_t snd_hctl_element_sizeof();
-#define snd_hctl_element_alloca(ptr) ({ assert(ptr); *ptr = (snd_hctl_element_t *) alloca(snd_hctl_element_sizeof()); memset(*ptr, 0, snd_hctl_element_sizeof()); 0; })
-int snd_hctl_element_malloc(snd_hctl_element_t **ptr);
-void snd_hctl_element_free(snd_hctl_element_t *obj);
-void snd_hctl_element_copy(snd_hctl_element_t *dst, const snd_hctl_element_t *src);
-
-void snd_hctl_element_get_id(const snd_hctl_element_t *obj, snd_ctl_element_id_t *ptr);
-
-unsigned int snd_hctl_element_get_numid(const snd_hctl_element_t *obj);
-
-snd_ctl_element_iface_t snd_hctl_element_get_interface(const snd_hctl_element_t *obj);
-
-unsigned int snd_hctl_element_get_device(const snd_hctl_element_t *obj);
-
-unsigned int snd_hctl_element_get_subdevice(const snd_hctl_element_t *obj);
-
-const char *snd_hctl_element_get_name(const snd_hctl_element_t *obj);
-
-unsigned int snd_hctl_element_get_index(const snd_hctl_element_t *obj);
-
-void snd_hctl_element_set_callback_change(snd_hctl_element_t *obj, snd_hctl_element_callback_t val);
-
-void snd_hctl_element_set_callback_value(snd_hctl_element_t *obj, snd_hctl_element_callback_t val);
-
-void snd_hctl_element_set_callback_remove(snd_hctl_element_t *obj, snd_hctl_element_callback_t val);
-
-void * snd_hctl_element_get_private_data(const snd_hctl_element_t *obj);
-
-void snd_hctl_element_set_private_data(snd_hctl_element_t *obj, void * val);
-
-void snd_hctl_element_set_private_free(snd_hctl_element_t *obj, snd_hctl_element_private_free_t val);
+void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val);
 
 
 #ifdef __cplusplus
index 8fae25b5f292cb7bb36aa3077fb6382522fb2dc4..667fa7aee49d5886e9c291e365f7e31f60020ccb 100644 (file)
 #define _snd_pcm_status sndrv_pcm_status
 
 #define _snd_ctl_card_info sndrv_ctl_card_info
-#define _snd_ctl_element_id sndrv_ctl_element_id
-#define _snd_ctl_element_list sndrv_ctl_element_list
-#define _snd_ctl_element_info sndrv_ctl_element_info
-#define _snd_ctl_element sndrv_ctl_element
+#define _snd_ctl_elem_id sndrv_ctl_elem_id
+#define _snd_ctl_elem_list sndrv_ctl_elem_list
+#define _snd_ctl_elem_info sndrv_ctl_elem_info
+#define _snd_ctl_elem sndrv_ctl_elem
 #define _snd_ctl_event sndrv_ctl_event
 
 #define _snd_rawmidi_info sndrv_rawmidi_info
index ec1e6fda56a4eeb3f9e5621e080c77f90bf22807..1d6faa9ba087f099d8243accc4db47908268f0e7 100644 (file)
@@ -6,15 +6,42 @@
  ****************************************************************************/
 
 typedef struct _snd_mixer snd_mixer_t;
+typedef struct _snd_mixer_info snd_mixer_info_t;
+typedef struct _snd_mixer_elem snd_mixer_elem_t;
+typedef int (*snd_mixer_callback_t)(snd_mixer_t *ctl,
+                                   snd_ctl_event_type_t event,
+                                   snd_mixer_elem_t *elem);
+typedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem,
+                                           snd_ctl_event_type_t event);
+
+enum _snd_mixer_elem_type {
+       SND_MIXER_ELEM_SIMPLE,
+       SND_MIXER_ELEM_LAST = SND_MIXER_ELEM_SIMPLE,
+};
+
+#ifdef SND_ENUM_TYPECHECK
+typedef struct __snd_mixer_elem_type *snd_mixer_elem_type_t;
+#else
+typedef enum _snd_mixer_elem_type snd_mixer_elem_type_t;
+#endif
+
+#define SND_MIXER_ELEM_SIMPLE ((snd_mixer_elem_type_t) SND_MIXER_ELEM_SIMPLE)
+#define SND_MIXER_ELEM_LAST ((snd_mixer_elem_type_t) SND_MIXER_ELEM_LAST)
+
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-int snd_mixer_open(snd_mixer_t **handle, char *name);
-int snd_mixer_close(snd_mixer_t *handle);
-int snd_mixer_card(snd_mixer_t *handle);
-int snd_mixer_poll_descriptor(snd_mixer_t *handle);
+int snd_mixer_open(snd_mixer_t **mixer, char *name);
+int snd_mixer_close(snd_mixer_t *mixer);
+int snd_mixer_poll_descriptor(snd_mixer_t *mixer);
+int snd_mixer_info(snd_mixer_t *mixer, snd_mixer_info_t *info);
+snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer);
+snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer);
+snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem);
+snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *helem);
+int snd_mixer_events(snd_mixer_t *mixer);
 
 #ifdef __cplusplus
 }
@@ -36,6 +63,11 @@ enum _snd_mixer_channel_id {
        SND_MIXER_CHN_MONO = SND_MIXER_CHN_FRONT_LEFT
 };
 
+/* Simple mixer */
+
+typedef struct _snd_mixer_selem snd_mixer_selem_t;
+typedef struct _snd_mixer_selem_id snd_mixer_selem_id_t;
+
 #ifdef SND_ENUM_TYPECHECK
 typedef struct __snd_mixer_channel_id *snd_mixer_channel_id_t;
 #else
@@ -52,79 +84,32 @@ typedef enum _snd_mixer_channel_id snd_mixer_channel_id_t;
 #define SND_MIXER_CHN_LAST ((snd_mixer_channel_id_t) SND_MIXER_CHN_LAST)
 #define SND_MIXER_CHN_MONO ((snd_mixer_channel_id_t) SND_MIXER_CHN_MONO)
 
-#define SND_MIXER_CHN_MASK_MONO                (1<<snd_enum_to_int(SND_MIXER_CHN_MONO))
-#define SND_MIXER_CHN_MASK_FRONT_LEFT  (1<<snd_enum_to_int(SND_MIXER_CHN_FRONT_LEFT))
-#define SND_MIXER_CHN_MASK_FRONT_RIGHT (1<<snd_enum_to_int(SND_MIXER_CHN_FRONT_RIGHT))
-#define SND_MIXER_CHN_MASK_FRONT_CENTER        (1<<snd_enum_to_int(SND_MIXER_CHN_FRONT_CENTER))
-#define SND_MIXER_CHN_MASK_REAR_LEFT   (1<<snd_enum_to_int(SND_MIXER_CHN_REAR_LEFT))
-#define SND_MIXER_CHN_MASK_REAR_RIGHT  (1<<snd_enum_to_int(SND_MIXER_CHN_REAR_RIGHT))
-#define SND_MIXER_CHN_MASK_WOOFER      (1<<snd_enum_to_int(SND_MIXER_CHN_WOOFER))
-#define SND_MIXER_CHN_MASK_STEREO      (SND_MIXER_CHN_MASK_FRONT_LEFT|SND_MIXER_CHN_MASK_FRONT_RIGHT)
-
-#define SND_MIXER_SCTCAP_VOLUME         (1<<0)
-#define SND_MIXER_SCTCAP_JOINTLY_VOLUME (1<<1)
-#define SND_MIXER_SCTCAP_MUTE           (1<<2)
-#define SND_MIXER_SCTCAP_JOINTLY_MUTE   (1<<3)
-#define SND_MIXER_SCTCAP_CAPTURE        (1<<4)
-#define SND_MIXER_SCTCAP_JOINTLY_CAPTURE (1<<5)
-#define SND_MIXER_SCTCAP_EXCL_CAPTURE   (1<<6)
-
-typedef struct _snd_mixer_sid {
-       unsigned char name[60];
-       unsigned int index;
-} snd_mixer_sid_t;
-
-typedef struct _snd_mixer_simple_element_list {
-       unsigned int controls_offset;   /* W: first control ID to get */
-       unsigned int controls_request;  /* W: count of control IDs to get */
-       unsigned int controls_count;    /* R: count of available (set) IDs */
-       unsigned int controls;          /* R: count of all available controls */
-       snd_mixer_sid_t *pids;          /* W: IDs */
-        char reserved[50];
-} snd_mixer_simple_element_list_t;
-
-typedef struct _snd_mixer_simple_element {
-       snd_mixer_sid_t sid;            /* WR: simple control identification */
-       unsigned int caps;              /* RO: capabilities */
-       unsigned int channels;          /* RO: bitmap of active channels */
-       unsigned int mute;              /* RW: bitmap of muted channels */
-       unsigned int capture;           /* RW: bitmap of capture channels */
-       int capture_group;              /* RO: capture group (for exclusive capture) */
-       long min;                       /* RO: minimum value */
-       long max;                       /* RO: maximum value */
-       char reserved[32];
-       union {
-               struct {
-                       long front_left;        /* front left value */
-                       long front_right;       /* front right value */
-                       long front_center;      /* front center */
-                       long rear_left;         /* left rear */
-                       long rear_right;        /* right rear */
-                       long woofer;            /* woofer */
-               } names;
-               long values[32];
-       } volume;                       /* RW */
-} snd_mixer_simple_element_t;
-
-typedef struct _snd_mixer_simple_callbacks {
-       void *private_data;     /* may be used by an application */
-       void (*rebuild) (snd_mixer_t *handle, void *private_data);
-       void (*value) (snd_mixer_t *handle, void *private_data, snd_mixer_sid_t *id);
-       void (*change) (snd_mixer_t *handle, void *private_data, snd_mixer_sid_t *id);
-       void (*add) (snd_mixer_t *handle, void *private_data, snd_mixer_sid_t *id);
-       void (*remove) (snd_mixer_t *handle, void *private_data, snd_mixer_sid_t *id);
-       void *reserved[58];     /* reserved for future use - must be NULL!!! */
-} snd_mixer_simple_callbacks_t;
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-const char *snd_mixer_simple_channel_name(snd_mixer_channel_id_t channel);
-int snd_mixer_simple_element_list(snd_mixer_t *handle, snd_mixer_simple_element_list_t *list);
-int snd_mixer_simple_element_read(snd_mixer_t *handle, snd_mixer_simple_element_t *simple);
-int snd_mixer_simple_element_write(snd_mixer_t *handle, snd_mixer_simple_element_t *simple);
-int snd_mixer_simple_read(snd_mixer_t *handle, snd_mixer_simple_callbacks_t *callbacks);
+const char *snd_mixer_channel_name(snd_mixer_channel_id_t channel);
+int snd_mixer_simple_build(snd_mixer_t *mixer);
+snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer,
+                                      const snd_mixer_selem_id_t *id);
+void snd_mixer_selem_get_id(snd_mixer_elem_t *element,
+                           snd_mixer_selem_id_t *id);
+int snd_mixer_selem_read(snd_mixer_elem_t *element,
+                        snd_mixer_selem_t *simple);
+int snd_mixer_selem_write(snd_mixer_elem_t *element,
+                         const snd_mixer_selem_t *simple);
+
+int snd_mixer_selem_is_mono(const snd_mixer_selem_t *obj);
+int snd_mixer_selem_has_channel(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel);
+long snd_mixer_selem_get_volume(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel);
+void snd_mixer_selem_set_volume(snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel, long value);
+int snd_mixer_selem_get_mute(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel);
+int snd_mixer_selem_get_capture(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel);
+void snd_mixer_selem_set_mute(snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel, int mute);
+void snd_mixer_selem_set_capture(snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel, int capture);
+void snd_mixer_selem_set_mute_all(snd_mixer_selem_t *obj, int mute);
+void snd_mixer_selem_set_capture_all(snd_mixer_selem_t *obj, int capture);
+void snd_mixer_selem_set_volume_all(snd_mixer_selem_t *obj, long value);
 
 #ifdef __cplusplus
 }
diff --git a/include/mixer_m4.h b/include/mixer_m4.h
new file mode 100644 (file)
index 0000000..99252fd
--- /dev/null
@@ -0,0 +1,64 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+size_t snd_mixer_selem_id_sizeof();
+#define snd_mixer_selem_id_alloca(ptr) ({ assert(ptr); *ptr = (snd_mixer_selem_id_t *) alloca(snd_mixer_selem_id_sizeof()); memset(*ptr, 0, snd_mixer_selem_id_sizeof()); 0; })
+int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr);
+void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj);
+void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src);
+
+const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj);
+
+unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj);
+
+void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val);
+
+void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val);
+
+void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val);
+
+void * snd_mixer_get_callback_private(const snd_mixer_t *obj);
+
+void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val);
+
+unsigned int snd_mixer_get_count(const snd_mixer_t *obj);
+
+void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val);
+
+void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *obj);
+
+void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val);
+
+snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *obj);
+
+size_t snd_mixer_selem_sizeof();
+#define snd_mixer_selem_alloca(ptr) ({ assert(ptr); *ptr = (snd_mixer_selem_t *) alloca(snd_mixer_selem_sizeof()); memset(*ptr, 0, snd_mixer_selem_sizeof()); 0; })
+int snd_mixer_selem_malloc(snd_mixer_selem_t **ptr);
+void snd_mixer_selem_free(snd_mixer_selem_t *obj);
+void snd_mixer_selem_copy(snd_mixer_selem_t *dst, const snd_mixer_selem_t *src);
+
+long snd_mixer_selem_get_min(const snd_mixer_selem_t *obj);
+
+long snd_mixer_selem_get_max(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_get_capture_group(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_volume(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_joined_volume(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_mute(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_joined_mute(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_capture(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_joined_capture(const snd_mixer_selem_t *obj);
+
+int snd_mixer_selem_has_exclusive_capture(const snd_mixer_selem_t *obj);
+
+
+#ifdef __cplusplus
+}
+#endif
index a43ea1b31465b72f02a8a7ae6babf5f9c4e8169c..20d6ab0b974ce958c0d7e78f17ad31a47f9933f4 100644 (file)
@@ -808,11 +808,18 @@ void string_print(char *str, int id, snd_output_t *out)
        unsigned char *p = str;
        if (!id) {
                switch (*p) {
+               case 0:
+                       assert(0);
+                       break;
                case '0' ... '9':
                case '-':
                        goto quoted;
                }
        }
+       if (!*p) {
+               snd_output_puts(out, "''");
+               return;
+       }
  loop:
        switch (*p) {
        case 0:
index 1c358b5cf6731e9ef74e42322416460bbde27b71..3c3e32d709f77e37fdbd909be0b787a75a5e6869 100644 (file)
@@ -1,6 +1,6 @@
 EXTRA_LTLIBRARIES = libcontrol.la
 
-libcontrol_la_SOURCES = cards.c controls.c bag.c defaults.c \
+libcontrol_la_SOURCES = cards.c hcontrol.c defaults.c \
                         control.c control_m4.c control_hw.c control_shm.c
 
 all: libcontrol.la
index dfe68d62af2d56680700d3191b97d92b47026546..8ef838addb7700217dd91028ff1bd4b0a963829c 100644 (file)
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <dlfcn.h>
+#include <sys/poll.h>
 #include "control_local.h"
 
 snd_ctl_type_t snd_ctl_type(snd_ctl_t *ctl)
@@ -38,10 +39,28 @@ int snd_ctl_close(snd_ctl_t *ctl)
        int res;
        assert(ctl);
        res = ctl->ops->close(ctl);
+       snd_hctl_free(ctl);
        free(ctl);
        return res;
 }
 
+int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock)
+{
+       int err;
+       assert(ctl);
+       err = ctl->ops->nonblock(ctl, nonblock);
+       if (err < 0)
+               return err;
+       ctl->nonblock = nonblock;
+       return 0;
+}
+
+int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid)
+{
+       assert(ctl);
+       return ctl->ops->async(ctl, sig, pid);
+}
+
 int snd_ctl_poll_descriptor(snd_ctl_t *ctl)
 {
        assert(ctl);
@@ -54,28 +73,29 @@ int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
        return ctl->ops->hw_info(ctl, info);
 }
 
-int snd_ctl_clist(snd_ctl_t *ctl, snd_ctl_element_list_t *list)
+int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list)
 {
        assert(ctl && list);
-       return ctl->ops->clist(ctl, list);
+       assert(list->space == 0 || list->pids);
+       return ctl->ops->element_list(ctl, list);
 }
 
-int snd_ctl_element_info(snd_ctl_t *ctl, snd_ctl_element_info_t *info)
+int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info)
 {
        assert(ctl && info && (info->id.name[0] || info->id.numid));
-       return ctl->ops->cinfo(ctl, info);
+       return ctl->ops->element_info(ctl, info);
 }
 
-int snd_ctl_element_read(snd_ctl_t *ctl, snd_ctl_element_t *control)
+int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_t *control)
 {
        assert(ctl && control && (control->id.name[0] || control->id.numid));
-       return ctl->ops->cread(ctl, control);
+       return ctl->ops->element_read(ctl, control);
 }
 
-int snd_ctl_element_write(snd_ctl_t *ctl, snd_ctl_element_t *control)
+int snd_ctl_elem_write(snd_ctl_t *ctl, snd_ctl_elem_t *control)
 {
        assert(ctl && control && (control->id.name[0] || control->id.numid));
-       return ctl->ops->cwrite(ctl, control);
+       return ctl->ops->element_write(ctl, control);
 }
 
 int snd_ctl_hwdep_next_device(snd_ctl_t *ctl, int *device)
@@ -126,49 +146,22 @@ int snd_ctl_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
        return ctl->ops->rawmidi_prefer_subdevice(ctl, subdev);
 }
 
-int snd_ctl_read1(snd_ctl_t *ctl, snd_ctl_event_t *event)
+int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
 {
        assert(ctl && event);
        return ctl->ops->read(ctl, event);
 }
 
-int snd_ctl_read(snd_ctl_t *ctl, snd_ctl_callbacks_t * callbacks)
+int snd_ctl_wait(snd_ctl_t *ctl, int timeout)
 {
-       int result, count;
-       snd_ctl_event_t r;
-
-       assert(ctl);
-       count = 0;
-       while ((result = snd_ctl_read1(ctl, &r)) > 0) {
-               if (result != sizeof(r))
-                       return -EIO;
-               if (!callbacks)
-                       continue;
-               switch (r.type) {
-               case SND_CTL_EVENT_REBUILD:
-                       if (callbacks->rebuild)
-                               callbacks->rebuild(ctl, callbacks->private_data);
-                       break;
-               case SND_CTL_EVENT_VALUE:
-                       if (callbacks->value)
-                               callbacks->value(ctl, callbacks->private_data, &r.data.id);
-                       break;
-               case SND_CTL_EVENT_CHANGE:
-                       if (callbacks->change)
-                               callbacks->change(ctl, callbacks->private_data, &r.data.id);
-                       break;
-               case SND_CTL_EVENT_ADD:
-                       if (callbacks->add)
-                               callbacks->add(ctl, callbacks->private_data, &r.data.id);
-                       break;
-               case SND_CTL_EVENT_REMOVE:
-                       if (callbacks->remove)
-                               callbacks->remove(ctl, callbacks->private_data, &r.data.id);
-                       break;
-               }
-               count++;
-       }
-       return result >= 0 ? count : -errno;
+       struct pollfd pfd;
+       int err;
+       pfd.fd = snd_ctl_poll_descriptor(ctl);
+       pfd.events = POLLIN;
+       err = poll(&pfd, 1, timeout);
+       if (err < 0)
+               return -errno;
+       return 0;
 }
 
 int snd_ctl_open(snd_ctl_t **ctlp, char *name)
@@ -239,18 +232,18 @@ int snd_ctl_open(snd_ctl_t **ctlp, char *name)
        return open_func(ctlp, name, ctl_conf);
 }
 
-void snd_ctl_element_set_bytes(snd_ctl_element_t *obj, void *data, size_t size)
+void snd_ctl_elem_set_bytes(snd_ctl_elem_t *obj, void *data, size_t size)
 {
        assert(obj);
        assert(size <= sizeof(obj->value.bytes.data));
        memcpy(obj->value.bytes.data, data, size);
 }
 
-#define TYPE(v) [SND_CTL_ELEMENT_TYPE_##v] = #v
-#define IFACE(v) [SND_CTL_ELEMENT_IFACE_##v] = #v
+#define TYPE(v) [SND_CTL_ELEM_TYPE_##v] = #v
+#define IFACE(v) [SND_CTL_ELEM_IFACE_##v] = #v
 #define EVENT(v) [SND_CTL_EVENT_##v] = #v
 
-const char *snd_ctl_element_type_names[] = {
+const char *snd_ctl_elem_type_names[] = {
        TYPE(NONE),
        TYPE(BOOLEAN),
        TYPE(INTEGER),
@@ -259,7 +252,7 @@ const char *snd_ctl_element_type_names[] = {
        TYPE(IEC958),
 };
 
-const char *snd_ctl_element_iface_names[] = {
+const char *snd_ctl_elem_iface_names[] = {
        IFACE(CARD),
        IFACE(HWDEP),
        IFACE(MIXER),
@@ -277,16 +270,16 @@ const char *snd_ctl_event_type_names[] = {
        EVENT(REMOVE),
 };
 
-const char *snd_ctl_element_type_name(snd_ctl_element_type_t type)
+const char *snd_ctl_elem_type_name(snd_ctl_elem_type_t type)
 {
-       assert(type <= SND_CTL_ELEMENT_TYPE_LAST);
-       return snd_ctl_element_type_names[snd_enum_to_int(type)];
+       assert(type <= SND_CTL_ELEM_TYPE_LAST);
+       return snd_ctl_elem_type_names[snd_enum_to_int(type)];
 }
 
-const char *snd_ctl_element_iface_name(snd_ctl_element_iface_t iface)
+const char *snd_ctl_elem_iface_name(snd_ctl_elem_iface_t iface)
 {
-       assert(iface <= SND_CTL_ELEMENT_IFACE_LAST);
-       return snd_ctl_element_iface_names[snd_enum_to_int(iface)];
+       assert(iface <= SND_CTL_ELEM_IFACE_LAST);
+       return snd_ctl_elem_iface_names[snd_enum_to_int(iface)];
 }
 
 const char *snd_ctl_event_type_name(snd_ctl_event_type_t type)
@@ -295,8 +288,10 @@ const char *snd_ctl_event_type_name(snd_ctl_event_type_t type)
        return snd_ctl_event_type_names[snd_enum_to_int(type)];
 }
 
-int snd_ctl_element_list_alloc_space(snd_ctl_element_list_t *obj, unsigned int entries)
+int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries)
 {
+       if (obj->pids)
+               free(obj->pids);
        obj->pids = calloc(entries, sizeof(*obj->pids));
        if (!obj->pids) {
                obj->space = 0;
@@ -306,7 +301,7 @@ int snd_ctl_element_list_alloc_space(snd_ctl_element_list_t *obj, unsigned int e
        return 0;
 }  
 
-void snd_ctl_element_list_free_space(snd_ctl_element_list_t *obj)
+void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj)
 {
        free(obj->pids);
        obj->pids = NULL;
index f6f7c275fc1496fbb18851490ea28bc3a6d37f7b..1f478d268e57fb5013ce733b9ec9f29e6a9678dc 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <signal.h>
 #include <string.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "control_local.h"
 
+#ifndef F_SETSIG
+#define F_SETSIG 10
+#endif
+
 #define SNDRV_FILE_CONTROL     "/dev/snd/controlC%i"
 #define SNDRV_CTL_VERSION_MAX  SNDRV_PROTOCOL_VERSION(2, 0, 0)
 
@@ -45,6 +50,61 @@ static int snd_ctl_hw_close(snd_ctl_t *handle)
        return res;
 }
 
+static int snd_ctl_hw_nonblock(snd_ctl_t *handle, int nonblock)
+{
+       snd_ctl_hw_t *hw = handle->private;
+       long flags;
+       int fd = hw->fd;
+       if ((flags = fcntl(fd, F_GETFL)) < 0) {
+               SYSERR("F_GETFL failed");
+               return -errno;
+       }
+       if (nonblock)
+               flags |= O_NONBLOCK;
+       else
+               flags &= ~O_NONBLOCK;
+       if (fcntl(fd, F_SETFL, flags) < 0) {
+               SYSERR("F_SETFL for O_NONBLOCK failed");
+               return -errno;
+       }
+       return 0;
+}
+
+static int snd_ctl_hw_async(snd_ctl_t *ctl, int sig, pid_t pid)
+{
+       long flags;
+       snd_ctl_hw_t *hw = ctl->private;
+       int fd = hw->fd;
+
+       if ((flags = fcntl(fd, F_GETFL)) < 0) {
+               SYSERR("F_GETFL failed");
+               return -errno;
+       }
+       if (sig >= 0)
+               flags |= O_ASYNC;
+       else
+               flags &= ~O_ASYNC;
+       if (fcntl(fd, F_SETFL, flags) < 0) {
+               SYSERR("F_SETFL for O_ASYNC failed");
+               return -errno;
+       }
+       if (sig < 0)
+               return 0;
+       if (sig == 0)
+               sig = SIGIO;
+       if (fcntl(fd, F_SETSIG, sig) < 0) {
+               SYSERR("F_SETSIG failed");
+               return -errno;
+       }
+       if (pid == 0)
+               pid = getpid();
+       if (fcntl(fd, F_SETOWN, pid) < 0) {
+               SYSERR("F_SETOWN failed");
+               return -errno;
+       }
+       return 0;
+}
+
 static int snd_ctl_hw_poll_descriptor(snd_ctl_t *handle)
 {
        snd_ctl_hw_t *hw = handle->private;
@@ -59,34 +119,34 @@ static int snd_ctl_hw_hw_info(snd_ctl_t *handle, snd_ctl_card_info_t *info)
        return 0;
 }
 
-static int snd_ctl_hw_clist(snd_ctl_t *handle, snd_ctl_element_list_t *list)
+static int snd_ctl_hw_elem_list(snd_ctl_t *handle, snd_ctl_elem_list_t *list)
 {
        snd_ctl_hw_t *hw = handle->private;
-       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEMENT_LIST, list) < 0)
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_LIST, list) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_ctl_hw_cinfo(snd_ctl_t *handle, snd_ctl_element_info_t *info)
+static int snd_ctl_hw_elem_info(snd_ctl_t *handle, snd_ctl_elem_info_t *info)
 {
        snd_ctl_hw_t *hw = handle->private;
-       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEMENT_INFO, info) < 0)
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_INFO, info) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_ctl_hw_cread(snd_ctl_t *handle, snd_ctl_element_t *control)
+static int snd_ctl_hw_elem_read(snd_ctl_t *handle, snd_ctl_elem_t *control)
 {
        snd_ctl_hw_t *hw = handle->private;
-       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEMENT_READ, control) < 0)
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_READ, control) < 0)
                return -errno;
        return 0;
 }
 
-static int snd_ctl_hw_cwrite(snd_ctl_t *handle, snd_ctl_element_t *control)
+static int snd_ctl_hw_elem_write(snd_ctl_t *handle, snd_ctl_elem_t *control)
 {
        snd_ctl_hw_t *hw = handle->private;
-       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEMENT_WRITE, control) < 0)
+       if (ioctl(hw->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, control) < 0)
                return -errno;
        return 0;
 }
@@ -158,17 +218,23 @@ static int snd_ctl_hw_rawmidi_prefer_subdevice(snd_ctl_t *handle, int subdev)
 static int snd_ctl_hw_read(snd_ctl_t *handle, snd_ctl_event_t *event)
 {
        snd_ctl_hw_t *hw = handle->private;
-       return read(hw->fd, event, sizeof(*event));
+       ssize_t res = read(hw->fd, event, sizeof(*event));
+       if (res <= 0)
+               return res;
+       assert(res == sizeof(*event));
+       return 1;
 }
 
 snd_ctl_ops_t snd_ctl_hw_ops = {
        close: snd_ctl_hw_close,
+       nonblock: snd_ctl_hw_nonblock,
+       async: snd_ctl_hw_async,
        poll_descriptor: snd_ctl_hw_poll_descriptor,
        hw_info: snd_ctl_hw_hw_info,
-       clist: snd_ctl_hw_clist,
-       cinfo: snd_ctl_hw_cinfo,
-       cread: snd_ctl_hw_cread,
-       cwrite: snd_ctl_hw_cwrite,
+       element_list: snd_ctl_hw_elem_list,
+       element_info: snd_ctl_hw_elem_info,
+       element_read: snd_ctl_hw_elem_read,
+       element_write: snd_ctl_hw_elem_write,
        hwdep_next_device: snd_ctl_hw_hwdep_next_device,
        hwdep_info: snd_ctl_hw_hwdep_info,
        pcm_next_device: snd_ctl_hw_pcm_next_device,
index b6008aea2acab23d499c4d096b4a6f11e477b7cd..97e873a7306cecb58546bd2ea0478f98d2ef4056 100644 (file)
 
 typedef struct _snd_ctl_ops {
        int (*close)(snd_ctl_t *handle);
+       int (*nonblock)(snd_ctl_t *handle, int nonblock);
+       int (*async)(snd_ctl_t *handle, int sig, pid_t pid);
        int (*poll_descriptor)(snd_ctl_t *handle);
        int (*hw_info)(snd_ctl_t *handle, snd_ctl_card_info_t *info);
-       int (*clist)(snd_ctl_t *handle, snd_ctl_element_list_t *list);
-       int (*cinfo)(snd_ctl_t *handle, snd_ctl_element_info_t *info);
-       int (*cread)(snd_ctl_t *handle, snd_ctl_element_t *control);
-       int (*cwrite)(snd_ctl_t *handle, snd_ctl_element_t *control);
+       int (*element_list)(snd_ctl_t *handle, snd_ctl_elem_list_t *list);
+       int (*element_info)(snd_ctl_t *handle, snd_ctl_elem_info_t *info);
+       int (*element_read)(snd_ctl_t *handle, snd_ctl_elem_t *control);
+       int (*element_write)(snd_ctl_t *handle, snd_ctl_elem_t *control);
        int (*hwdep_next_device)(snd_ctl_t *handle, int *device);
        int (*hwdep_info)(snd_ctl_t *handle, snd_hwdep_info_t * info);
        int (*pcm_next_device)(snd_ctl_t *handle, int *device);
@@ -47,51 +49,30 @@ struct _snd_ctl {
        snd_ctl_type_t type;
        snd_ctl_ops_t *ops;
        void *private;
-       int hcount;
-       int herr;
+       int nonblock;
        struct list_head hlist; /* list of all controls */
-       void *hroot;            /* root of controls */
-       void *hroot_new;        /* new croot */
-       snd_ctl_hsort_t hsort;
-       snd_ctl_hcallback_rebuild_t callback_rebuild;
-       void *callback_rebuild_private_data;
-       snd_ctl_hcallback_add_t callback_add;
-       void *callback_add_private_data;
+       unsigned int halloc;    
+       unsigned int hcount;
+       snd_hctl_elem_t **helems;
+       snd_hctl_compare_t hcompare;
+       snd_hctl_callback_t callback;
+       void *callback_private;
 };
 
-struct _snd_ctl_callbacks {
-       void *private_data;     /* may be used by an application */
-       void (*rebuild) (snd_ctl_t *handle, void *private_data);
-       void (*value) (snd_ctl_t *handle, void *private_data, snd_ctl_element_id_t * id);
-       void (*change) (snd_ctl_t *handle, void *private_data, snd_ctl_element_id_t * id);
-       void (*add) (snd_ctl_t *handle, void *private_data, snd_ctl_element_id_t * id);
-       void (*remove) (snd_ctl_t *handle, void *private_data, snd_ctl_element_id_t * id);
-       void *reserved[58];     /* reserved for the future use - must be NULL!!! */
-};
-
-struct _snd_hctl_element_list {
-       unsigned int offset;    /* W: first control ID to get */
-       unsigned int space;     /* W: count of control IDs to get */
-       unsigned int used;      /* R: count of available (set) controls */
-       unsigned int count;     /* R: count of all available controls */
-       snd_ctl_element_id_t *pids;             /* W: IDs */
-};
-
-struct _snd_hctl_element {
-       snd_ctl_element_id_t id;        /* must be always on top */
-       struct list_head list;  /* links for list of all helems */
-       int change: 1,          /* structure change */
-           value: 1;           /* value change */
-       /* event callbacks */
-       snd_hctl_element_callback_t callback_change;
-       snd_hctl_element_callback_t callback_value;
-       snd_hctl_element_callback_t callback_remove;
-       /* private data */
-       void *private_data;
-       snd_hctl_element_private_free_t private_free;
+struct _snd_hctl_elem {
+       snd_ctl_elem_id_t id;   /* must be always on top */
+       struct list_head list;          /* links for list of all helems */
+       /* event callback */
+       snd_hctl_elem_callback_t callback;
+       void *callback_private;
        /* links */
-       snd_ctl_t *handle;      /* associated handle */
+       snd_ctl_t *ctl;                 /* associated handle */
 };
 
+
 int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card);
 int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *socket, const char *sname);
+int snd_hctl_free(snd_ctl_t *ctl);
+int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
+                            const snd_hctl_elem_t *c2);
+
index bccb7062a3c8772f4e21ce6975f7446ff55e4ca8..fbc1b45b125c9656773bba99a55d29af6a27e94c 100644 (file)
   
 #include "control_local.h"
 
-size_t snd_ctl_element_id_sizeof()
+size_t snd_ctl_elem_id_sizeof()
 {
-       return sizeof(snd_ctl_element_id_t);
+       return sizeof(snd_ctl_elem_id_t);
 }
 
-int snd_ctl_element_id_malloc(snd_ctl_element_id_t **ptr)
+int snd_ctl_elem_id_malloc(snd_ctl_elem_id_t **ptr)
 {
        assert(ptr);
-       *ptr = calloc(1, sizeof(snd_ctl_element_id_t));
+       *ptr = calloc(1, sizeof(snd_ctl_elem_id_t));
        if (!*ptr)
                return -ENOMEM;
        return 0;
 }
 
-void snd_ctl_element_id_free(snd_ctl_element_id_t *obj)
+void snd_ctl_elem_id_free(snd_ctl_elem_id_t *obj)
 {
        free(obj);
 }
 
-void snd_ctl_element_id_copy(snd_ctl_element_id_t *dst, const snd_ctl_element_id_t *src)
+void snd_ctl_elem_id_copy(snd_ctl_elem_id_t *dst, const snd_ctl_elem_id_t *src)
 {
        assert(dst && src);
        *dst = *src;
 }
 
-unsigned int snd_ctl_element_id_get_numid(const snd_ctl_element_id_t *obj)
+unsigned int snd_ctl_elem_id_get_numid(const snd_ctl_elem_id_t *obj)
 {
        assert(obj);
        return obj->numid;
 }
 
-snd_ctl_element_iface_t snd_ctl_element_id_get_interface(const snd_ctl_element_id_t *obj)
+snd_ctl_elem_iface_t snd_ctl_elem_id_get_interface(const snd_ctl_elem_id_t *obj)
 {
        assert(obj);
        return snd_int_to_enum(obj->iface);
 }
 
-unsigned int snd_ctl_element_id_get_device(const snd_ctl_element_id_t *obj)
+unsigned int snd_ctl_elem_id_get_device(const snd_ctl_elem_id_t *obj)
 {
        assert(obj);
        return obj->device;
 }
 
-unsigned int snd_ctl_element_id_get_subdevice(const snd_ctl_element_id_t *obj)
+unsigned int snd_ctl_elem_id_get_subdevice(const snd_ctl_elem_id_t *obj)
 {
        assert(obj);
        return obj->subdevice;
 }
 
-const char *snd_ctl_element_id_get_name(const snd_ctl_element_id_t *obj)
+const char *snd_ctl_elem_id_get_name(const snd_ctl_elem_id_t *obj)
 {
        assert(obj);
        return obj->name;
 }
 
-unsigned int snd_ctl_element_id_get_index(const snd_ctl_element_id_t *obj)
+unsigned int snd_ctl_elem_id_get_index(const snd_ctl_elem_id_t *obj)
 {
        assert(obj);
        return obj->index;
 }
 
-void snd_ctl_element_id_set_numid(snd_ctl_element_id_t *obj, unsigned int val)
+void snd_ctl_elem_id_set_numid(snd_ctl_elem_id_t *obj, unsigned int val)
 {
        assert(obj);
        obj->numid = val;
 }
 
-void snd_ctl_element_id_set_interface(snd_ctl_element_id_t *obj, snd_ctl_element_iface_t val)
+void snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t *obj, snd_ctl_elem_iface_t val)
 {
        assert(obj);
        obj->iface = snd_enum_to_int(val);
 }
 
-void snd_ctl_element_id_set_device(snd_ctl_element_id_t *obj, unsigned int val)
+void snd_ctl_elem_id_set_device(snd_ctl_elem_id_t *obj, unsigned int val)
 {
        assert(obj);
        obj->device = val;
 }
 
-void snd_ctl_element_id_set_subdevice(snd_ctl_element_id_t *obj, unsigned int val)
+void snd_ctl_elem_id_set_subdevice(snd_ctl_elem_id_t *obj, unsigned int val)
 {
        assert(obj);
        obj->subdevice = val;
 }
 
-void snd_ctl_element_id_set_name(snd_ctl_element_id_t *obj, const char *val)
+void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val)
 {
        assert(obj);
        strncpy(obj->name, val, sizeof(obj->name));
 }
 
-void snd_ctl_element_id_set_index(snd_ctl_element_id_t *obj, unsigned int val)
+void snd_ctl_elem_id_set_index(snd_ctl_elem_id_t *obj, unsigned int val)
 {
        assert(obj);
        obj->index = val;
@@ -229,14 +229,14 @@ unsigned int snd_ctl_event_get_numid(const snd_ctl_event_t *obj)
        return obj->data.id.numid;
 }
 
-void snd_ctl_event_get_id(const snd_ctl_event_t *obj, snd_ctl_element_id_t *ptr)
+void snd_ctl_event_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
        *ptr = obj->data.id;
 }
 
-snd_ctl_element_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj)
+snd_ctl_elem_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj)
 {
        assert(obj);
        assert(obj->type != SNDRV_CTL_EVENT_REBUILD);
@@ -271,667 +271,557 @@ unsigned int snd_ctl_event_get_index(const snd_ctl_event_t *obj)
        return obj->data.id.index;
 }
 
-size_t snd_ctl_element_list_sizeof()
+size_t snd_ctl_elem_list_sizeof()
 {
-       return sizeof(snd_ctl_element_list_t);
+       return sizeof(snd_ctl_elem_list_t);
 }
 
-int snd_ctl_element_list_malloc(snd_ctl_element_list_t **ptr)
+int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr)
 {
        assert(ptr);
-       *ptr = calloc(1, sizeof(snd_ctl_element_list_t));
+       *ptr = calloc(1, sizeof(snd_ctl_elem_list_t));
        if (!*ptr)
                return -ENOMEM;
        return 0;
 }
 
-void snd_ctl_element_list_free(snd_ctl_element_list_t *obj)
+void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj)
 {
        free(obj);
 }
 
-void snd_ctl_element_list_copy(snd_ctl_element_list_t *dst, const snd_ctl_element_list_t *src)
+void snd_ctl_elem_list_copy(snd_ctl_elem_list_t *dst, const snd_ctl_elem_list_t *src)
 {
        assert(dst && src);
        *dst = *src;
 }
 
-void snd_ctl_element_list_set_offset(snd_ctl_element_list_t *obj, unsigned int val)
+void snd_ctl_elem_list_set_offset(snd_ctl_elem_list_t *obj, unsigned int val)
 {
        assert(obj);
        obj->offset = val;
 }
 
-unsigned int snd_ctl_element_list_get_used(const snd_ctl_element_list_t *obj)
+unsigned int snd_ctl_elem_list_get_used(const snd_ctl_elem_list_t *obj)
 {
        assert(obj);
        return obj->used;
 }
 
-unsigned int snd_ctl_element_list_get_count(const snd_ctl_element_list_t *obj)
+unsigned int snd_ctl_elem_list_get_count(const snd_ctl_elem_list_t *obj)
 {
        assert(obj);
        return obj->count;
 }
 
-void snd_ctl_element_list_get_id(const snd_ctl_element_list_t *obj, unsigned int idx, snd_ctl_element_id_t *ptr)
+void snd_ctl_elem_list_get_id(const snd_ctl_elem_list_t *obj, unsigned int idx, snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        assert(idx < obj->used);
        *ptr = obj->pids[idx];
 }
 
-unsigned int snd_ctl_element_list_get_numid(const snd_ctl_element_list_t *obj, unsigned int idx)
+unsigned int snd_ctl_elem_list_get_numid(const snd_ctl_elem_list_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < obj->used);
        return obj->pids[idx].numid;
 }
 
-snd_ctl_element_iface_t snd_ctl_element_list_get_interface(const snd_ctl_element_list_t *obj, unsigned int idx)
+snd_ctl_elem_iface_t snd_ctl_elem_list_get_interface(const snd_ctl_elem_list_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < obj->used);
        return snd_int_to_enum(obj->pids[idx].iface);
 }
 
-unsigned int snd_ctl_element_list_get_device(const snd_ctl_element_list_t *obj, unsigned int idx)
+unsigned int snd_ctl_elem_list_get_device(const snd_ctl_elem_list_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < obj->used);
        return obj->pids[idx].device;
 }
 
-unsigned int snd_ctl_element_list_get_subdevice(const snd_ctl_element_list_t *obj, unsigned int idx)
+unsigned int snd_ctl_elem_list_get_subdevice(const snd_ctl_elem_list_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < obj->used);
        return obj->pids[idx].subdevice;
 }
 
-const char *snd_ctl_element_list_get_name(const snd_ctl_element_list_t *obj, unsigned int idx)
+const char *snd_ctl_elem_list_get_name(const snd_ctl_elem_list_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < obj->used);
        return obj->pids[idx].name;
 }
 
-unsigned int snd_ctl_element_list_get_index(const snd_ctl_element_list_t *obj, unsigned int idx)
+unsigned int snd_ctl_elem_list_get_index(const snd_ctl_elem_list_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < obj->used);
        return obj->pids[idx].index;
 }
 
-size_t snd_ctl_element_info_sizeof()
+size_t snd_ctl_elem_info_sizeof()
 {
-       return sizeof(snd_ctl_element_info_t);
+       return sizeof(snd_ctl_elem_info_t);
 }
 
-int snd_ctl_element_info_malloc(snd_ctl_element_info_t **ptr)
+int snd_ctl_elem_info_malloc(snd_ctl_elem_info_t **ptr)
 {
        assert(ptr);
-       *ptr = calloc(1, sizeof(snd_ctl_element_info_t));
+       *ptr = calloc(1, sizeof(snd_ctl_elem_info_t));
        if (!*ptr)
                return -ENOMEM;
        return 0;
 }
 
-void snd_ctl_element_info_free(snd_ctl_element_info_t *obj)
+void snd_ctl_elem_info_free(snd_ctl_elem_info_t *obj)
 {
        free(obj);
 }
 
-void snd_ctl_element_info_copy(snd_ctl_element_info_t *dst, const snd_ctl_element_info_t *src)
+void snd_ctl_elem_info_copy(snd_ctl_elem_info_t *dst, const snd_ctl_elem_info_t *src)
 {
        assert(dst && src);
        *dst = *src;
 }
 
-snd_ctl_element_type_t snd_ctl_element_info_get_type(const snd_ctl_element_info_t *obj)
+snd_ctl_elem_type_t snd_ctl_elem_info_get_type(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return snd_int_to_enum(obj->type);
 }
 
-int snd_ctl_element_info_is_readable(const snd_ctl_element_info_t *obj)
+int snd_ctl_elem_info_is_readable(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       return !!(obj->access & SNDRV_CTL_ELEMENT_ACCESS_READ);
+       return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_READ);
 }
 
-int snd_ctl_element_info_is_writable(const snd_ctl_element_info_t *obj)
+int snd_ctl_elem_info_is_writable(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       return !!(obj->access & SNDRV_CTL_ELEMENT_ACCESS_WRITE);
+       return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_WRITE);
 }
 
-int snd_ctl_element_info_is_volatile(const snd_ctl_element_info_t *obj)
+int snd_ctl_elem_info_is_volatile(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       return !!(obj->access & SNDRV_CTL_ELEMENT_ACCESS_VOLATILE);
+       return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_VOLATILE);
 }
 
-int snd_ctl_element_info_is_inactive(const snd_ctl_element_info_t *obj)
+int snd_ctl_elem_info_is_inactive(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       return !!(obj->access & SNDRV_CTL_ELEMENT_ACCESS_INACTIVE);
+       return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE);
 }
 
-int snd_ctl_element_info_is_locked(const snd_ctl_element_info_t *obj)
+int snd_ctl_elem_info_is_locked(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       return !!(obj->access & SNDRV_CTL_ELEMENT_ACCESS_LOCK);
+       return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_LOCK);
 }
 
-int snd_ctl_element_info_is_indirect(const snd_ctl_element_info_t *obj)
+int snd_ctl_elem_info_is_indirect(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       return !!(obj->access & SNDRV_CTL_ELEMENT_ACCESS_INDIRECT);
+       return !!(obj->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT);
 }
 
-unsigned int snd_ctl_element_info_get_count(const snd_ctl_element_info_t *obj)
+unsigned int snd_ctl_elem_info_get_count(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return obj->count;
 }
 
-long snd_ctl_element_info_get_min(const snd_ctl_element_info_t *obj)
+long snd_ctl_elem_info_get_min(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       assert(obj->type == SNDRV_CTL_ELEMENT_TYPE_INTEGER);
+       assert(obj->type == SNDRV_CTL_ELEM_TYPE_INTEGER);
        return obj->value.integer.min;
 }
 
-long snd_ctl_element_info_get_max(const snd_ctl_element_info_t *obj)
+long snd_ctl_elem_info_get_max(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       assert(obj->type == SNDRV_CTL_ELEMENT_TYPE_INTEGER);
+       assert(obj->type == SNDRV_CTL_ELEM_TYPE_INTEGER);
        return obj->value.integer.max;
 }
 
-long snd_ctl_element_info_get_step(const snd_ctl_element_info_t *obj)
+long snd_ctl_elem_info_get_step(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       assert(obj->type == SNDRV_CTL_ELEMENT_TYPE_INTEGER);
+       assert(obj->type == SNDRV_CTL_ELEM_TYPE_INTEGER);
        return obj->value.integer.step;
 }
 
-unsigned int snd_ctl_element_info_get_items(const snd_ctl_element_info_t *obj)
+unsigned int snd_ctl_elem_info_get_items(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       assert(obj->type == SNDRV_CTL_ELEMENT_TYPE_ENUMERATED);
+       assert(obj->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED);
        return obj->value.enumerated.items;
 }
 
-void snd_ctl_element_info_set_item(snd_ctl_element_info_t *obj, unsigned int val)
+void snd_ctl_elem_info_set_item(snd_ctl_elem_info_t *obj, unsigned int val)
 {
        assert(obj);
        obj->value.enumerated.item = val;
 }
 
-const char *snd_ctl_element_info_get_item_name(const snd_ctl_element_info_t *obj)
+const char *snd_ctl_elem_info_get_item_name(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
-       assert(obj->type == SNDRV_CTL_ELEMENT_TYPE_ENUMERATED);
+       assert(obj->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED);
        return obj->value.enumerated.name;
 }
 
-void snd_ctl_element_info_get_id(const snd_ctl_element_info_t *obj, snd_ctl_element_id_t *ptr)
+void snd_ctl_elem_info_get_id(const snd_ctl_elem_info_t *obj, snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        *ptr = obj->id;
 }
 
-unsigned int snd_ctl_element_info_get_numid(const snd_ctl_element_info_t *obj)
+unsigned int snd_ctl_elem_info_get_numid(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return obj->id.numid;
 }
 
-snd_ctl_element_iface_t snd_ctl_element_info_get_interface(const snd_ctl_element_info_t *obj)
+snd_ctl_elem_iface_t snd_ctl_elem_info_get_interface(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return snd_int_to_enum(obj->id.iface);
 }
 
-unsigned int snd_ctl_element_info_get_device(const snd_ctl_element_info_t *obj)
+unsigned int snd_ctl_elem_info_get_device(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return obj->id.device;
 }
 
-unsigned int snd_ctl_element_info_get_subdevice(const snd_ctl_element_info_t *obj)
+unsigned int snd_ctl_elem_info_get_subdevice(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return obj->id.subdevice;
 }
 
-const char *snd_ctl_element_info_get_name(const snd_ctl_element_info_t *obj)
+const char *snd_ctl_elem_info_get_name(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return obj->id.name;
 }
 
-unsigned int snd_ctl_element_info_get_index(const snd_ctl_element_info_t *obj)
+unsigned int snd_ctl_elem_info_get_index(const snd_ctl_elem_info_t *obj)
 {
        assert(obj);
        return obj->id.index;
 }
 
-void snd_ctl_element_info_set_id(snd_ctl_element_info_t *obj, const snd_ctl_element_id_t *ptr)
+void snd_ctl_elem_info_set_id(snd_ctl_elem_info_t *obj, const snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        obj->id = *ptr;
 }
 
-void snd_ctl_element_info_set_numid(snd_ctl_element_info_t *obj, unsigned int val)
+void snd_ctl_elem_info_set_numid(snd_ctl_elem_info_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.numid = val;
 }
 
-void snd_ctl_element_info_set_interface(snd_ctl_element_info_t *obj, snd_ctl_element_iface_t val)
+void snd_ctl_elem_info_set_interface(snd_ctl_elem_info_t *obj, snd_ctl_elem_iface_t val)
 {
        assert(obj);
        obj->id.iface = snd_enum_to_int(val);
 }
 
-void snd_ctl_element_info_set_device(snd_ctl_element_info_t *obj, unsigned int val)
+void snd_ctl_elem_info_set_device(snd_ctl_elem_info_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.device = val;
 }
 
-void snd_ctl_element_info_set_subdevice(snd_ctl_element_info_t *obj, unsigned int val)
+void snd_ctl_elem_info_set_subdevice(snd_ctl_elem_info_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.subdevice = val;
 }
 
-void snd_ctl_element_info_set_name(snd_ctl_element_info_t *obj, const char *val)
+void snd_ctl_elem_info_set_name(snd_ctl_elem_info_t *obj, const char *val)
 {
        assert(obj);
        strncpy(obj->id.name, val, sizeof(obj->id.name));
 }
 
-void snd_ctl_element_info_set_index(snd_ctl_element_info_t *obj, unsigned int val)
+void snd_ctl_elem_info_set_index(snd_ctl_elem_info_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.index = val;
 }
 
-size_t snd_ctl_element_sizeof()
+size_t snd_ctl_elem_sizeof()
 {
-       return sizeof(snd_ctl_element_t);
+       return sizeof(snd_ctl_elem_t);
 }
 
-int snd_ctl_element_malloc(snd_ctl_element_t **ptr)
+int snd_ctl_elem_malloc(snd_ctl_elem_t **ptr)
 {
        assert(ptr);
-       *ptr = calloc(1, sizeof(snd_ctl_element_t));
+       *ptr = calloc(1, sizeof(snd_ctl_elem_t));
        if (!*ptr)
                return -ENOMEM;
        return 0;
 }
 
-void snd_ctl_element_free(snd_ctl_element_t *obj)
+void snd_ctl_elem_free(snd_ctl_elem_t *obj)
 {
        free(obj);
 }
 
-void snd_ctl_element_copy(snd_ctl_element_t *dst, const snd_ctl_element_t *src)
+void snd_ctl_elem_copy(snd_ctl_elem_t *dst, const snd_ctl_elem_t *src)
 {
        assert(dst && src);
        *dst = *src;
 }
 
-void snd_ctl_element_get_id(const snd_ctl_element_t *obj, snd_ctl_element_id_t *ptr)
+void snd_ctl_elem_get_id(const snd_ctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        *ptr = obj->id;
 }
 
-unsigned int snd_ctl_element_get_numid(const snd_ctl_element_t *obj)
+unsigned int snd_ctl_elem_get_numid(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.numid;
 }
 
-snd_ctl_element_iface_t snd_ctl_element_get_interface(const snd_ctl_element_t *obj)
+snd_ctl_elem_iface_t snd_ctl_elem_get_interface(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return snd_int_to_enum(obj->id.iface);
 }
 
-unsigned int snd_ctl_element_get_device(const snd_ctl_element_t *obj)
+unsigned int snd_ctl_elem_get_device(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.device;
 }
 
-unsigned int snd_ctl_element_get_subdevice(const snd_ctl_element_t *obj)
+unsigned int snd_ctl_elem_get_subdevice(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.subdevice;
 }
 
-const char *snd_ctl_element_get_name(const snd_ctl_element_t *obj)
+const char *snd_ctl_elem_get_name(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.name;
 }
 
-unsigned int snd_ctl_element_get_index(const snd_ctl_element_t *obj)
+unsigned int snd_ctl_elem_get_index(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.index;
 }
 
-void snd_ctl_element_set_id(snd_ctl_element_t *obj, const snd_ctl_element_id_t *ptr)
+void snd_ctl_elem_set_id(snd_ctl_elem_t *obj, const snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        obj->id = *ptr;
 }
 
-void snd_ctl_element_set_numid(snd_ctl_element_t *obj, unsigned int val)
+void snd_ctl_elem_set_numid(snd_ctl_elem_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.numid = val;
 }
 
-void snd_ctl_element_set_interface(snd_ctl_element_t *obj, snd_ctl_element_iface_t val)
+void snd_ctl_elem_set_interface(snd_ctl_elem_t *obj, snd_ctl_elem_iface_t val)
 {
        assert(obj);
        obj->id.iface = snd_enum_to_int(val);
 }
 
-void snd_ctl_element_set_device(snd_ctl_element_t *obj, unsigned int val)
+void snd_ctl_elem_set_device(snd_ctl_elem_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.device = val;
 }
 
-void snd_ctl_element_set_subdevice(snd_ctl_element_t *obj, unsigned int val)
+void snd_ctl_elem_set_subdevice(snd_ctl_elem_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.subdevice = val;
 }
 
-void snd_ctl_element_set_name(snd_ctl_element_t *obj, const char *val)
+void snd_ctl_elem_set_name(snd_ctl_elem_t *obj, const char *val)
 {
        assert(obj);
        strncpy(obj->id.name, val, sizeof(obj->id.name));
 }
 
-void snd_ctl_element_set_index(snd_ctl_element_t *obj, unsigned int val)
+void snd_ctl_elem_set_index(snd_ctl_elem_t *obj, unsigned int val)
 {
        assert(obj);
        obj->id.index = val;
 }
 
-long snd_ctl_element_get_boolean(const snd_ctl_element_t *obj, unsigned int idx)
+long snd_ctl_elem_get_boolean(const snd_ctl_elem_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < sizeof(obj->value.integer.value) / sizeof(obj->value.integer.value[0]));
        return obj->value.integer.value[idx];
 }
 
-long snd_ctl_element_get_integer(const snd_ctl_element_t *obj, unsigned int idx)
+long snd_ctl_elem_get_integer(const snd_ctl_elem_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < sizeof(obj->value.integer.value) / sizeof(obj->value.integer.value[0]));
        return obj->value.integer.value[idx];
 }
 
-unsigned int snd_ctl_element_get_enumerated(const snd_ctl_element_t *obj, unsigned int idx)
+unsigned int snd_ctl_elem_get_enumerated(const snd_ctl_elem_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < sizeof(obj->value.enumerated.item) / sizeof(obj->value.enumerated.item[0]));
        return obj->value.enumerated.item[idx];
 }
 
-unsigned char snd_ctl_element_get_byte(const snd_ctl_element_t *obj, unsigned int idx)
+unsigned char snd_ctl_elem_get_byte(const snd_ctl_elem_t *obj, unsigned int idx)
 {
        assert(obj);
        assert(idx < sizeof(obj->value.bytes.data));
        return obj->value.bytes.data[idx];
 }
 
-void snd_ctl_element_set_boolean(snd_ctl_element_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_set_boolean(snd_ctl_elem_t *obj, unsigned int idx, long val)
 {
        assert(obj);
        obj->value.integer.value[idx] = val;
 }
 
-void snd_ctl_element_set_integer(snd_ctl_element_t *obj, unsigned int idx, long val)
+void snd_ctl_elem_set_integer(snd_ctl_elem_t *obj, unsigned int idx, long val)
 {
        assert(obj);
        obj->value.integer.value[idx] = val;
 }
 
-void snd_ctl_element_set_enumerated(snd_ctl_element_t *obj, unsigned int idx, unsigned int val)
+void snd_ctl_elem_set_enumerated(snd_ctl_elem_t *obj, unsigned int idx, unsigned int val)
 {
        assert(obj);
        obj->value.enumerated.item[idx] = val;
 }
 
-void snd_ctl_element_set_byte(snd_ctl_element_t *obj, unsigned int idx, unsigned char val)
+void snd_ctl_elem_set_byte(snd_ctl_elem_t *obj, unsigned int idx, unsigned char val)
 {
        assert(obj);
        obj->value.bytes.data[idx] = val;
 }
 
-const void * snd_ctl_element_get_bytes(const snd_ctl_element_t *obj)
+const void * snd_ctl_elem_get_bytes(const snd_ctl_elem_t *obj)
 {
        assert(obj);
        return obj->value.bytes.data;
 }
 
-void snd_ctl_element_get_iec958(const snd_ctl_element_t *obj, snd_aes_iec958_t *ptr)
+void snd_ctl_elem_get_iec958(const snd_ctl_elem_t *obj, snd_aes_iec958_t *ptr)
 {
        assert(obj && ptr);
        *ptr = obj->value.iec958;
 }
 
-void snd_ctl_element_set_iec958(snd_ctl_element_t *obj, const snd_aes_iec958_t *ptr)
+void snd_ctl_elem_set_iec958(snd_ctl_elem_t *obj, const snd_aes_iec958_t *ptr)
 {
        assert(obj && ptr);
        obj->value.iec958 = *ptr;
 }
 
-size_t snd_hctl_element_list_sizeof()
+size_t snd_hctl_elem_sizeof()
 {
-       return sizeof(snd_hctl_element_list_t);
+       return sizeof(snd_hctl_elem_t);
 }
 
-int snd_hctl_element_list_malloc(snd_hctl_element_list_t **ptr)
+int snd_hctl_elem_malloc(snd_hctl_elem_t **ptr)
 {
        assert(ptr);
-       *ptr = calloc(1, sizeof(snd_hctl_element_list_t));
+       *ptr = calloc(1, sizeof(snd_hctl_elem_t));
        if (!*ptr)
                return -ENOMEM;
        return 0;
 }
 
-void snd_hctl_element_list_free(snd_hctl_element_list_t *obj)
+void snd_hctl_elem_free(snd_hctl_elem_t *obj)
 {
        free(obj);
 }
 
-void snd_hctl_element_list_copy(snd_hctl_element_list_t *dst, const snd_hctl_element_list_t *src)
+void snd_hctl_elem_copy(snd_hctl_elem_t *dst, const snd_hctl_elem_t *src)
 {
        assert(dst && src);
        *dst = *src;
 }
 
-void snd_hctl_element_list_set_offset(snd_hctl_element_list_t *obj, unsigned int val)
-{
-       assert(obj);
-       obj->offset = val;
-}
-
-unsigned int snd_hctl_element_list_get_used(const snd_hctl_element_list_t *obj)
-{
-       assert(obj);
-       return obj->used;
-}
-
-unsigned int snd_hctl_element_list_get_count(const snd_hctl_element_list_t *obj)
-{
-       assert(obj);
-       return obj->count;
-}
-
-void snd_hctl_element_list_get_id(const snd_hctl_element_list_t *obj, unsigned int idx, snd_ctl_element_id_t *ptr)
-{
-       assert(obj && ptr);
-       assert(idx < obj->used);
-       *ptr = obj->pids[idx];
-}
-
-unsigned int snd_hctl_element_list_get_numid(const snd_hctl_element_list_t *obj, unsigned int idx)
-{
-       assert(obj);
-       assert(idx < obj->used);
-       return obj->pids[idx].numid;
-}
-
-snd_ctl_element_iface_t snd_hctl_element_list_get_interface(const snd_hctl_element_list_t *obj, unsigned int idx)
-{
-       assert(obj);
-       assert(idx < obj->used);
-       return snd_int_to_enum(obj->pids[idx].iface);
-}
-
-unsigned int snd_hctl_element_list_get_device(const snd_hctl_element_list_t *obj, unsigned int idx)
-{
-       assert(obj);
-       assert(idx < obj->used);
-       return obj->pids[idx].device;
-}
-
-unsigned int snd_hctl_element_list_get_subdevice(const snd_hctl_element_list_t *obj, unsigned int idx)
-{
-       assert(obj);
-       assert(idx < obj->used);
-       return obj->pids[idx].subdevice;
-}
-
-const char *snd_hctl_element_list_get_name(const snd_hctl_element_list_t *obj, unsigned int idx)
-{
-       assert(obj);
-       assert(idx < obj->used);
-       return obj->pids[idx].name;
-}
-
-unsigned int snd_hctl_element_list_get_index(const snd_hctl_element_list_t *obj, unsigned int idx)
-{
-       assert(obj);
-       assert(idx < obj->used);
-       return obj->pids[idx].index;
-}
-
-size_t snd_hctl_element_sizeof()
-{
-       return sizeof(snd_hctl_element_t);
-}
-
-int snd_hctl_element_malloc(snd_hctl_element_t **ptr)
-{
-       assert(ptr);
-       *ptr = calloc(1, sizeof(snd_hctl_element_t));
-       if (!*ptr)
-               return -ENOMEM;
-       return 0;
-}
-
-void snd_hctl_element_free(snd_hctl_element_t *obj)
-{
-       free(obj);
-}
-
-void snd_hctl_element_copy(snd_hctl_element_t *dst, const snd_hctl_element_t *src)
-{
-       assert(dst && src);
-       *dst = *src;
-}
-
-void snd_hctl_element_get_id(const snd_hctl_element_t *obj, snd_ctl_element_id_t *ptr)
+void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
 {
        assert(obj && ptr);
        *ptr = obj->id;
 }
 
-unsigned int snd_hctl_element_get_numid(const snd_hctl_element_t *obj)
+unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.numid;
 }
 
-snd_ctl_element_iface_t snd_hctl_element_get_interface(const snd_hctl_element_t *obj)
+snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj)
 {
        assert(obj);
        return snd_int_to_enum(obj->id.iface);
 }
 
-unsigned int snd_hctl_element_get_device(const snd_hctl_element_t *obj)
+unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.device;
 }
 
-unsigned int snd_hctl_element_get_subdevice(const snd_hctl_element_t *obj)
+unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.subdevice;
 }
 
-const char *snd_hctl_element_get_name(const snd_hctl_element_t *obj)
+const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.name;
 }
 
-unsigned int snd_hctl_element_get_index(const snd_hctl_element_t *obj)
+unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj)
 {
        assert(obj);
        return obj->id.index;
 }
 
-void snd_hctl_element_set_callback_change(snd_hctl_element_t *obj, snd_hctl_element_callback_t val)
-{
-       assert(obj);
-       obj->callback_change = val;
-}
-
-void snd_hctl_element_set_callback_value(snd_hctl_element_t *obj, snd_hctl_element_callback_t val)
-{
-       assert(obj);
-       obj->callback_value = val;
-}
-
-void snd_hctl_element_set_callback_remove(snd_hctl_element_t *obj, snd_hctl_element_callback_t val)
-{
-       assert(obj);
-       obj->callback_remove = val;
-}
-
-void * snd_hctl_element_get_private_data(const snd_hctl_element_t *obj)
+void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val)
 {
        assert(obj);
-       return obj->private_data;
+       obj->callback = val;
 }
 
-void snd_hctl_element_set_private_data(snd_hctl_element_t *obj, void * val)
+void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj)
 {
        assert(obj);
-       obj->private_data = val;
+       return obj->callback_private;
 }
 
-void snd_hctl_element_set_private_free(snd_hctl_element_t *obj, snd_hctl_element_private_free_t val)
+void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val)
 {
        assert(obj);
-       obj->private_free = val;
+       obj->callback_private = val;
 }
 
index 3acb148ddda45a34c5cce349e80c6f0be4ca787b..63b0b6307b5b12e79f6d6a369acb7146390a10e0 100644 (file)
@@ -94,6 +94,23 @@ static int snd_ctl_shm_close(snd_ctl_t *ctl)
        return result;
 }
 
+static int snd_ctl_shm_nonblock(snd_ctl_t *handle ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
+{
+       return 0;
+}
+
+static int snd_ctl_shm_async(snd_ctl_t *ctl, int sig, pid_t pid)
+{
+       snd_ctl_shm_t *shm = ctl->private;
+       volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       ctrl->cmd = SND_CTL_IOCTL_ASYNC;
+       ctrl->u.async.sig = sig;
+       if (pid == 0)
+               pid = getpid();
+       ctrl->u.async.pid = pid;
+       return snd_ctl_shm_action(ctl);
+}
+
 static int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl)
 {
        snd_ctl_shm_t *shm = ctl->private;
@@ -120,67 +137,67 @@ static int snd_ctl_shm_hw_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
        return err;
 }
 
-static int snd_ctl_shm_clist(snd_ctl_t *ctl, snd_ctl_element_list_t *list)
+static int snd_ctl_shm_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list)
 {
        snd_ctl_shm_t *shm = ctl->private;
        volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
        size_t maxsize = CTL_SHM_DATA_MAXLEN;
        size_t bytes = list->space * sizeof(*list->pids);
        int err;
-       snd_ctl_element_id_t *pids = list->pids;
+       snd_ctl_elem_id_t *pids = list->pids;
        if (bytes > maxsize)
                return -EINVAL;
-       ctrl->u.clist = *list;
-       ctrl->cmd = SNDRV_CTL_IOCTL_ELEMENT_LIST;
+       ctrl->u.element_list = *list;
+       ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_LIST;
        err = snd_ctl_shm_action(ctl);
        if (err < 0)
                return err;
-       *list = ctrl->u.clist;
+       *list = ctrl->u.element_list;
        list->pids = pids;
        bytes = list->used * sizeof(*list->pids);
        memcpy(pids, (void *)ctrl->data, bytes);
        return err;
 }
 
-static int snd_ctl_shm_cinfo(snd_ctl_t *ctl, snd_ctl_element_info_t *info)
+static int snd_ctl_shm_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info)
 {
        snd_ctl_shm_t *shm = ctl->private;
        volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
-       ctrl->u.cinfo = *info;
-       ctrl->cmd = SNDRV_CTL_IOCTL_ELEMENT_INFO;
+       ctrl->u.element_info = *info;
+       ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_INFO;
        err = snd_ctl_shm_action(ctl);
        if (err < 0)
                return err;
-       *info = ctrl->u.cinfo;
+       *info = ctrl->u.element_info;
        return err;
 }
 
-static int snd_ctl_shm_cread(snd_ctl_t *ctl, snd_ctl_element_t *control)
+static int snd_ctl_shm_elem_read(snd_ctl_t *ctl, snd_ctl_elem_t *control)
 {
        snd_ctl_shm_t *shm = ctl->private;
        volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
-       ctrl->u.cread = *control;
-       ctrl->cmd = SNDRV_CTL_IOCTL_ELEMENT_READ;
+       ctrl->u.element_read = *control;
+       ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_READ;
        err = snd_ctl_shm_action(ctl);
        if (err < 0)
                return err;
-       *control = ctrl->u.cread;
+       *control = ctrl->u.element_read;
        return err;
 }
 
-static int snd_ctl_shm_cwrite(snd_ctl_t *ctl, snd_ctl_element_t *control)
+static int snd_ctl_shm_elem_write(snd_ctl_t *ctl, snd_ctl_elem_t *control)
 {
        snd_ctl_shm_t *shm = ctl->private;
        volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
        int err;
-       ctrl->u.cwrite = *control;
-       ctrl->cmd = SNDRV_CTL_IOCTL_ELEMENT_WRITE;
+       ctrl->u.element_write = *control;
+       ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_WRITE;
        err = snd_ctl_shm_action(ctl);
        if (err < 0)
                return err;
-       *control = ctrl->u.cwrite;
+       *control = ctrl->u.element_write;
        return err;
 }
 
@@ -296,9 +313,14 @@ static int snd_ctl_shm_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev)
 
 static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
 {
-       snd_ctl_shm_t *shm = ctl->private;
-       volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
+       snd_ctl_shm_t *shm;
+       volatile snd_ctl_shm_ctrl_t *ctrl;
        int err;
+       err = snd_ctl_wait(ctl, -1);
+       if (err < 0)
+               return 0;
+       shm = ctl->private;
+       ctrl = shm->ctrl;
        ctrl->u.read = *event;
        ctrl->cmd = SND_CTL_IOCTL_READ;
        err = snd_ctl_shm_action(ctl);
@@ -310,12 +332,14 @@ static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
 
 snd_ctl_ops_t snd_ctl_shm_ops = {
        close: snd_ctl_shm_close,
+       nonblock: snd_ctl_shm_nonblock,
+       async: snd_ctl_shm_async,
        poll_descriptor: snd_ctl_shm_poll_descriptor,
        hw_info: snd_ctl_shm_hw_info,
-       clist: snd_ctl_shm_clist,
-       cinfo: snd_ctl_shm_cinfo,
-       cread: snd_ctl_shm_cread,
-       cwrite: snd_ctl_shm_cwrite,
+       element_list: snd_ctl_shm_elem_list,
+       element_info: snd_ctl_shm_elem_info,
+       element_read: snd_ctl_shm_elem_read,
+       element_write: snd_ctl_shm_elem_write,
        hwdep_next_device: snd_ctl_shm_hwdep_next_device,
        hwdep_info: snd_ctl_shm_hwdep_info,
        pcm_next_device: snd_ctl_shm_pcm_next_device,
index d129072fa5e44d7064d3510fcf3842a174979070..b1862f3f9c6c32c5048c4b19f11353fd6073ca3d 100644 (file)
 #include <search.h>
 #include "control_local.h"
 
-static void snd_ctl_hfree1(snd_hctl_element_t *helem);
+static void snd_ctl_hfree1(snd_hctl_elem_t *helem);
 
 int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
 {
-       snd_ctl_element_list_t list;
-       snd_hctl_element_t *helem, *prev;
+       snd_ctl_elem_list_t list;
+       snd_hctl_elem_t *helem, *prev;
        int err;
        unsigned int idx;
 
@@ -53,7 +53,7 @@ int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
                        return err;
                if (list.count == 0)
                        break;
-               list.pids = (snd_ctl_element_id_t *)calloc(list.count, sizeof(snd_ctl_element_id_t));
+               list.pids = (snd_ctl_elem_id_t *)calloc(list.count, sizeof(snd_ctl_elem_id_t));
                if (list.pids == NULL)
                        return -ENOMEM;
                list.space = list.count;
@@ -61,7 +61,7 @@ int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
                        return err;
        } while (list.count != list.used);
        for (idx = 0, prev = NULL; idx < list.count; idx++) {
-               helem = (snd_hctl_element_t *)calloc(1, sizeof(snd_hctl_element_t));
+               helem = (snd_hctl_elem_t *)calloc(1, sizeof(snd_hctl_elem_t));
                if (helem == NULL)
                        goto __nomem;
                helem->id = list.pids[idx];
@@ -90,7 +90,7 @@ int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
        return 0;
 }
 
-static void snd_ctl_hfree1(snd_hctl_element_t *helem)
+static void snd_ctl_hfree1(snd_hctl_elem_t *helem)
 {
        snd_ctl_t *handle;
        
@@ -202,7 +202,7 @@ static int snd_ctl_hsort_mixer_priority(const char *name)
        return res + res1;
 }
 
-int snd_ctl_hsort(const snd_hctl_element_t *c1, const snd_hctl_element_t *c2)
+int snd_ctl_hsort(const snd_hctl_elem_t *c1, const snd_hctl_elem_t *c2)
 {
        int res, p1, p2;
 
@@ -211,7 +211,7 @@ int snd_ctl_hsort(const snd_hctl_element_t *c1, const snd_hctl_element_t *c2)
        if (c1->id.iface > c2->id.iface)
                return 1;
        if ((res = strcmp(c1->id.name, c2->id.name)) != 0) {
-               if (c1->id.iface != SNDRV_CTL_ELEMENT_IFACE_MIXER)
+               if (c1->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
                        return res;
                p1 = snd_ctl_hsort_mixer_priority(c1->id.name);
                p2 = snd_ctl_hsort_mixer_priority(c2->id.name);
@@ -228,7 +228,7 @@ int snd_ctl_hsort(const snd_hctl_element_t *c1, const snd_hctl_element_t *c2)
        return 0;
 }
 
-static void snd_ctl_hresort_free(snd_hctl_element_t *helem ATTRIBUTE_UNUSED)
+static void snd_ctl_hresort_free(snd_hctl_elem_t *helem ATTRIBUTE_UNUSED)
 {
        /* nothing */
 }
@@ -236,8 +236,8 @@ static void snd_ctl_hresort_free(snd_hctl_element_t *helem ATTRIBUTE_UNUSED)
 int snd_ctl_hresort(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
 {
        struct list_head *list;
-       snd_hctl_element_t *helem;
-       snd_ctl_element_id_t *ids, *pids;
+       snd_hctl_elem_t *helem;
+       snd_ctl_elem_id_t *ids, *pids;
        int idx;
 
        assert(handle != NULL && hsort != NULL);
@@ -246,12 +246,12 @@ int snd_ctl_hresort(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
        if (handle->herr < 0)
                return handle->herr;
        assert(handle->hroot_new == NULL);
-       ids = pids = (snd_ctl_element_id_t *)malloc(sizeof(snd_ctl_element_id_t) * handle->hcount);
+       ids = pids = (snd_ctl_elem_id_t *)malloc(sizeof(snd_ctl_elem_id_t) * handle->hcount);
        if (ids == NULL)
                return -ENOMEM;
        /* first step - update search engine */
        list_for_each(list, &handle->hlist) {
-               helem = list_entry(list, snd_hctl_element_t, list);
+               helem = list_entry(list, snd_hctl_elem_t, list);
                *pids++ = helem->id;
                if (tsearch(helem, &handle->hroot_new, (__compar_fn_t)hsort) == NULL) {
                        if (handle->hroot_new != NULL)
@@ -267,7 +267,7 @@ int snd_ctl_hresort(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
        handle->hroot = handle->hroot_new;
        handle->hroot_new = NULL;
        /* second step - perform qsort and save results */
-       qsort(ids, handle->hcount, sizeof(snd_ctl_element_id_t), (int (*)(const void *, const void *))hsort);
+       qsort(ids, handle->hcount, sizeof(snd_ctl_elem_id_t), (int (*)(const void *, const void *))hsort);
        INIT_LIST_HEAD(&handle->hlist);
        for (idx = 0; idx < handle->hcount; idx++) {
                helem = snd_ctl_hfind(handle, ids + idx);
@@ -277,36 +277,36 @@ int snd_ctl_hresort(snd_ctl_t *handle, snd_ctl_hsort_t hsort)
        return 0;
 }
 
-snd_hctl_element_t *snd_ctl_hfirst(snd_ctl_t *handle)
+snd_hctl_elem_t *snd_ctl_hfirst(snd_ctl_t *handle)
 {
        assert(handle != NULL);
        if (list_empty(&handle->hlist))
                return NULL;
-       return (snd_hctl_element_t *)list_entry(handle->hlist.next, snd_hctl_element_t, list);
+       return (snd_hctl_elem_t *)list_entry(handle->hlist.next, snd_hctl_elem_t, list);
 }
 
-snd_hctl_element_t *snd_ctl_hlast(snd_ctl_t *handle)
+snd_hctl_elem_t *snd_ctl_hlast(snd_ctl_t *handle)
 {
        assert(handle != NULL);
        if (list_empty(&handle->hlist))
                return NULL;
-       return (snd_hctl_element_t *)list_entry(handle->hlist.prev, snd_hctl_element_t, list);
+       return (snd_hctl_elem_t *)list_entry(handle->hlist.prev, snd_hctl_elem_t, list);
 }
 
-snd_hctl_element_t *snd_ctl_hnext(snd_ctl_t *handle, snd_hctl_element_t *helem)
+snd_hctl_elem_t *snd_ctl_hnext(snd_ctl_t *handle, snd_hctl_elem_t *helem)
 {
        assert(handle != NULL && helem != NULL);
        if (helem->list.next == &handle->hlist)
                return NULL;
-       return (snd_hctl_element_t *)list_entry(helem->list.next, snd_hctl_element_t, list);
+       return (snd_hctl_elem_t *)list_entry(helem->list.next, snd_hctl_elem_t, list);
 }
 
-snd_hctl_element_t *snd_ctl_hprev(snd_ctl_t *handle, snd_hctl_element_t *helem)
+snd_hctl_elem_t *snd_ctl_hprev(snd_ctl_t *handle, snd_hctl_elem_t *helem)
 {
        assert(handle != NULL && helem != NULL);
        if (helem->list.prev == &handle->hlist)
                return NULL;
-       return (snd_hctl_element_t *)list_entry(helem->list.prev, snd_hctl_element_t, list);
+       return (snd_hctl_elem_t *)list_entry(helem->list.prev, snd_hctl_elem_t, list);
 }
 
 int snd_ctl_hcount(snd_ctl_t *handle)
@@ -315,7 +315,7 @@ int snd_ctl_hcount(snd_ctl_t *handle)
        return handle->hcount;
 }
 
-snd_hctl_element_t *snd_ctl_hfind(snd_ctl_t *handle, snd_ctl_element_id_t *id)
+snd_hctl_elem_t *snd_ctl_hfind(snd_ctl_t *handle, snd_ctl_elem_id_t *id)
 {
        void *res;
 
@@ -323,13 +323,13 @@ snd_hctl_element_t *snd_ctl_hfind(snd_ctl_t *handle, snd_ctl_element_id_t *id)
        if (handle->hroot == NULL)
                return NULL;
        res = tfind(id, &handle->hroot, (__compar_fn_t)handle->hsort);
-       return res == NULL ? NULL : *(snd_hctl_element_t **)res;
+       return res == NULL ? NULL : *(snd_hctl_elem_t **)res;
 }
 
-int snd_ctl_hlist(snd_ctl_t *handle, snd_hctl_element_list_t *hlist)
+int snd_ctl_hlist(snd_ctl_t *handle, snd_hctl_elem_list_t *hlist)
 {
        struct list_head *list;
-       snd_hctl_element_t *helem;
+       snd_hctl_elem_t *helem;
        unsigned int idx;
 
        assert(hlist != NULL);
@@ -342,7 +342,7 @@ int snd_ctl_hlist(snd_ctl_t *handle, snd_hctl_element_list_t *hlist)
                        return -EINVAL;
                idx = 0;
                list_for_each(list, &handle->hlist) {
-                       helem = list_entry(list, snd_hctl_element_t, list);
+                       helem = list_entry(list, snd_hctl_elem_t, list);
                        if (idx >= hlist->offset + hlist->space)
                                break;
                        if (idx >= hlist->offset) {
@@ -378,9 +378,9 @@ static void callback_rebuild(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNU
                handle->callback_rebuild(handle, handle->callback_rebuild_private_data);
 }
 
-static void callback_change(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_element_id_t *id)
+static void callback_change(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_elem_id_t *id)
 {
-       snd_hctl_element_t *helem;
+       snd_hctl_elem_t *helem;
 
        if (handle->herr < 0)
                return;
@@ -392,9 +392,9 @@ static void callback_change(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUS
        helem->change = 1;
 }
 
-static void callback_value(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_element_id_t *id)
+static void callback_value(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_elem_id_t *id)
 {
-       snd_hctl_element_t *helem;
+       snd_hctl_elem_t *helem;
 
        if (handle->herr < 0)
                return;
@@ -406,13 +406,13 @@ static void callback_value(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSE
        helem->value = 1;
 }
 
-static void callback_add(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_element_id_t *id)
+static void callback_add(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_elem_id_t *id)
 {
-       snd_hctl_element_t *helem, *icontrol;
+       snd_hctl_elem_t *helem, *icontrol;
 
        if (handle->herr < 0)
                return;
-       helem = (snd_hctl_element_t *)calloc(1, sizeof(snd_hctl_element_t));
+       helem = (snd_hctl_elem_t *)calloc(1, sizeof(snd_hctl_elem_t));
        if (helem == NULL) {
                handle->herr = -ENOMEM;
                return;
@@ -434,9 +434,9 @@ static void callback_add(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED,
                handle->callback_add(handle, handle->callback_add_private_data, helem);
 }
 
-static void callback_remove(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_element_id_t *id)
+static void callback_remove(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_ctl_elem_id_t *id)
 {
-       snd_hctl_element_t *helem;
+       snd_hctl_elem_t *helem;
 
        if (handle->herr < 0)
                return;
@@ -461,7 +461,7 @@ int snd_ctl_hevent(snd_ctl_t *handle)
                reserved: { NULL, }
        };
        struct list_head *list;
-       snd_hctl_element_t *helem;
+       snd_hctl_elem_t *helem;
        int res;
 
        assert(handle != NULL);
@@ -472,7 +472,7 @@ int snd_ctl_hevent(snd_ctl_t *handle)
        if (handle->herr < 0)
                return handle->herr;
        list_for_each(list, &handle->hlist) {
-               helem = list_entry(list, snd_hctl_element_t, list);
+               helem = list_entry(list, snd_hctl_elem_t, list);
                if (helem->change && helem->callback_change) {
                        helem->callback_change(helem->handle, helem);
                        helem->change = 0;
@@ -485,7 +485,7 @@ int snd_ctl_hevent(snd_ctl_t *handle)
        return res;
 }
 
-int snd_hctl_element_list_alloc_space(snd_hctl_element_list_t *obj, unsigned int entries)
+int snd_hctl_elem_list_alloc_space(snd_hctl_elem_list_t *obj, unsigned int entries)
 {
        obj->pids = calloc(entries, sizeof(*obj->pids));
        if (!obj->pids) {
@@ -496,7 +496,7 @@ int snd_hctl_element_list_alloc_space(snd_hctl_element_list_t *obj, unsigned int
        return 0;
 }  
 
-void snd_hctl_element_list_free_space(snd_hctl_element_list_t *obj)
+void snd_hctl_elem_list_free_space(snd_hctl_elem_list_t *obj)
 {
        free(obj->pids);
        obj->pids = NULL;
diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c
new file mode 100644 (file)
index 0000000..f458bce
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ *  Control Interface - highlevel API
+ *  Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#define __USE_GNU
+#include "control_local.h"
+
+static int _snd_hctl_find_elem(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, int *dir)
+{
+       unsigned int l, u;
+       int c = 0;
+       int idx = -1;
+       assert(ctl && id);
+       assert(ctl->hcompare);
+       l = 0;
+       u = ctl->hcount;
+       while (l < u) {
+               idx = (l + u) / 2;
+               c = ctl->hcompare((snd_hctl_elem_t *) id, ctl->helems[idx]);
+               if (c < 0)
+                       u = idx;
+               else if (c > 0)
+                       l = idx + 1;
+               else
+                       break;
+       }
+       *dir = c;
+       return idx;
+}
+
+static int snd_hctl_elem_add(snd_ctl_t *ctl, snd_hctl_elem_t *elem)
+{
+       int dir;
+       int idx; 
+       if (ctl->hcount == ctl->halloc) {
+               snd_hctl_elem_t **h;
+               ctl->halloc += 32;
+               h = realloc(ctl->helems, sizeof(*h) * ctl->halloc);
+               if (!h)
+                       return -ENOMEM;
+               ctl->helems = h;
+       }
+       if (ctl->hcount == 0) {
+               list_add_tail(&elem->list, &ctl->hlist);
+               ctl->helems[0] = elem;
+       } else {
+               idx = _snd_hctl_find_elem(ctl, &elem->id, &dir);
+               assert(dir != 0);
+               if (dir > 0) {
+                       list_add(&elem->list, &ctl->helems[idx]->list);
+               } else {
+                       list_add_tail(&elem->list, &ctl->helems[idx]->list);
+                       idx++;
+               }
+               memmove(ctl->helems + idx + 1,
+                       ctl->helems + idx,
+                       ctl->hcount - idx);
+       }
+       ctl->hcount++;
+       if (ctl->callback) {
+               int res = ctl->callback(ctl, SND_CTL_EVENT_ADD, elem);
+               if (res < 0)
+                       return res;
+       }
+       return 0;
+}
+
+
+static void snd_hctl_elem_remove(snd_ctl_t *ctl, unsigned int idx)
+{
+       snd_hctl_elem_t *elem = ctl->helems[idx];
+       unsigned int m;
+       if (elem->callback)
+               elem->callback(elem, SND_CTL_EVENT_REMOVE);
+       list_del(&elem->list);
+       free(elem);
+       ctl->hcount--;
+       m = ctl->hcount - idx;
+       if (m > 0)
+               memmove(ctl->helems + idx, ctl->helems + idx + 1, m);
+}
+
+int snd_hctl_free(snd_ctl_t *ctl)
+{
+       while (ctl->hcount > 0)
+               snd_hctl_elem_remove(ctl, ctl->hcount - 1);
+       free(ctl->helems);
+       ctl->helems = 0;
+       ctl->halloc = 0;
+       INIT_LIST_HEAD(&ctl->hlist);
+       return 0;
+}
+
+static void snd_hctl_sort(snd_ctl_t *ctl)
+{
+       unsigned int k;
+       int compar(const void *a, const void *b) {
+               return ctl->hcompare(*(const snd_hctl_elem_t **) a,
+                                    *(const snd_hctl_elem_t **) b);
+       }
+       assert(ctl);
+       assert(ctl->hcompare);
+       INIT_LIST_HEAD(&ctl->hlist);
+       qsort(ctl->helems, ctl->hcount, sizeof(*ctl->helems), compar);
+       for (k = 0; k < ctl->hcount; k++)
+               list_add_tail(&ctl->helems[k]->list, &ctl->hlist);
+}
+
+void snd_hctl_set_compare(snd_ctl_t *ctl, snd_hctl_compare_t hsort)
+{
+       assert(ctl);
+       ctl->hcompare = hsort;
+       snd_hctl_sort(ctl);
+}
+
+#define NOT_FOUND 1000000000
+
+static int snd_hctl_compare_mixer_priority_lookup(char **name, char * const *names, int coef)
+{
+       int res;
+
+       for (res = 0; *names; names++, res += coef) {
+               if (!strncmp(*name, *names, strlen(*names))) {
+                       *name += strlen(*names);
+                       if (**name == ' ')
+                               (*name)++;
+                       return res;
+               }
+       }
+       return NOT_FOUND;
+}
+
+static int snd_hctl_compare_mixer_priority(const char *name)
+{
+       static char *names[] = {
+               "Master",
+               "Master Digital",
+               "Master Mono",
+               "Hardware Master",
+               "Headphone",
+               "Tone Control",
+               "3D Control",
+               "PCM",
+               "PCM Front",
+               "PCM Rear",
+               "PCM Pan",
+               "Synth",
+               "FM",
+               "Wave",
+               "Music",
+               "DSP",
+               "Line",
+               "CD",
+               "Mic",
+               "Phone",
+               "Video",
+               "PC Speaker",
+               "Aux",
+               "Mono",
+               "Mono Output",
+               "ADC",
+               "Capture Source",
+               "Capture",
+               "Playback",
+               "Loopback",
+               "Analog Loopback",
+               "Digital Loopback",
+               "S/PDIF Input",
+               "S/PDIF Output",
+               NULL
+       };
+       static char *names1[] = {
+               "Switch",
+               "Volume",
+               "Playback",
+               "Capture",
+               "Bypass",
+               NULL
+       };
+       static char *names2[] = {
+               "Switch",
+               "Volume",
+               "Bypass",
+               NULL
+       };
+       int res, res1;
+       
+       if ((res = snd_hctl_compare_mixer_priority_lookup((char **)&name, names, 1000000)) == NOT_FOUND)
+               return NOT_FOUND;
+       if ((res1 = snd_hctl_compare_mixer_priority_lookup((char **)&name, names1, 1000)) == NOT_FOUND)
+               return res;
+       res += res1;
+       if ((res1 = snd_hctl_compare_mixer_priority_lookup((char **)&name, names2, 1)) == NOT_FOUND)
+               return res;
+       return res + res1;
+}
+
+int snd_hctl_compare_fast(const snd_hctl_elem_t *c1,
+                         const snd_hctl_elem_t *c2)
+{
+       return c1->id.numid - c2->id.numid;
+}
+
+int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
+                            const snd_hctl_elem_t *c2)
+{
+       int res, p1, p2;
+       int d = c1->id.iface - c2->id.iface;
+       if (d != 0)
+               return d;
+       if ((res = strcmp(c1->id.name, c2->id.name)) != 0) {
+               if (c1->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
+                       return res;
+               p1 = snd_hctl_compare_mixer_priority(c1->id.name);
+               p2 = snd_hctl_compare_mixer_priority(c2->id.name);
+               d = p1 - p2;
+               if (d != 0)
+                       return d;
+               return res;
+       }
+       d = c1->id.index - c2->id.index;
+       return d;
+}
+
+snd_hctl_elem_t *snd_hctl_first_elem(snd_ctl_t *ctl)
+{
+       assert(ctl);
+       if (list_empty(&ctl->hlist))
+               return NULL;
+       return list_entry(ctl->hlist.next, snd_hctl_elem_t, list);
+}
+
+snd_hctl_elem_t *snd_hctl_last_elem(snd_ctl_t *ctl)
+{
+       assert(ctl);
+       if (list_empty(&ctl->hlist))
+               return NULL;
+       return list_entry(ctl->hlist.prev, snd_hctl_elem_t, list);
+}
+
+snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem)
+{
+       assert(elem);
+       if (elem->list.next == &elem->ctl->hlist)
+               return NULL;
+       return list_entry(elem->list.next, snd_hctl_elem_t, list);
+}
+
+snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem)
+{
+       assert(elem);
+       if (elem->list.prev == &elem->ctl->hlist)
+               return NULL;
+       return list_entry(elem->list.prev, snd_hctl_elem_t, list);
+}
+
+snd_hctl_elem_t *snd_hctl_find_elem(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id)
+{
+       int dir;
+       int res = _snd_hctl_find_elem(ctl, id, &dir);
+       if (res < 0 || dir != 0)
+               return NULL;
+       return ctl->helems[res];
+}
+
+int snd_hctl_build(snd_ctl_t *ctl)
+{
+       snd_ctl_elem_list_t list;
+       int err = 0;
+       unsigned int idx;
+
+       assert(ctl);
+       assert(ctl->hcount == 0);
+       assert(list_empty(&ctl->hlist));
+       memset(&list, 0, sizeof(list));
+       if ((err = snd_ctl_elem_list(ctl, &list)) < 0)
+               goto _end;
+       while (list.count != list.used) {
+               err = snd_ctl_elem_list_alloc_space(&list, list.count);
+               if (err < 0)
+                       goto _end;
+               if ((err = snd_ctl_elem_list(ctl, &list)) < 0)
+                       goto _end;
+       }
+       if (ctl->halloc < list.count) {
+               ctl->halloc = list.count;
+               free(ctl->helems);
+               ctl->helems = malloc(ctl->halloc * sizeof(*ctl->helems));
+               if (!ctl->helems) {
+                       err = -ENOMEM;
+                       goto _end;
+               }
+       }
+       for (idx = 0; idx < list.count; idx++) {
+               snd_hctl_elem_t *elem;
+               elem = calloc(1, sizeof(snd_hctl_elem_t));
+               if (elem == NULL) {
+                       snd_hctl_free(ctl);
+                       err = -ENOMEM;
+                       goto _end;
+               }
+               elem->id = list.pids[idx];
+               elem->ctl = ctl;
+               ctl->helems[idx] = elem;
+               list_add_tail(&elem->list, &ctl->hlist);
+               ctl->hcount++;
+       }
+       if (!ctl->hcompare)
+               ctl->hcompare = snd_hctl_compare_default;
+       snd_hctl_sort(ctl);
+       if (ctl->callback) {
+               for (idx = 0; idx < ctl->hcount; idx++) {
+                       int res = ctl->callback(ctl, SND_CTL_EVENT_ADD,
+                                               ctl->helems[idx]);
+                       if (res < 0)
+                               return res;
+               }
+       }
+ _end:
+       if (list.pids)
+               free(list.pids);
+       return err;
+}
+
+void snd_hctl_set_callback(snd_ctl_t *ctl, snd_hctl_callback_t callback)
+{
+       assert(ctl);
+       ctl->callback = callback;
+}
+
+void snd_hctl_set_callback_private(snd_ctl_t *ctl, void *callback_private)
+{
+       assert(ctl);
+       ctl->callback_private = callback_private;
+}
+
+void *snd_hctl_get_callback_private(snd_ctl_t *ctl)
+{
+       assert(ctl);
+       return ctl->callback_private;
+}
+
+unsigned int snd_hctl_get_count(snd_ctl_t *ctl)
+{
+       return ctl->hcount;
+}
+
+int snd_hctl_event(snd_ctl_t *ctl, snd_ctl_event_t *event)
+{
+       snd_hctl_elem_t *elem;
+       int res;
+
+       assert(ctl);
+       switch (event->type) {
+       case SND_CTL_EVENT_REMOVE:
+       {
+               int dir;
+               res = _snd_hctl_find_elem(ctl, &event->data.id, &dir);
+               assert(res >= 0 && dir == 0);
+               if (res < 0 || dir != 0)
+                       return -ENOENT;
+               snd_hctl_elem_remove(ctl, res);
+               break;
+       }
+       case SND_CTL_EVENT_VALUE:
+       case SND_CTL_EVENT_CHANGE:
+               elem = snd_hctl_find_elem(ctl, &event->data.id);
+               assert(elem);
+               if (!elem)
+                       return -ENOENT;
+               if (elem->callback) {
+                       res = elem->callback(elem, event->type);
+                       if (res < 0)
+                               return res;
+               }
+               break;
+       case SND_CTL_EVENT_ADD:
+               elem = calloc(1, sizeof(snd_hctl_elem_t));
+               if (elem == NULL)
+                       return -ENOMEM;
+               elem->id = event->data.id;
+               elem->ctl = ctl;
+               res = snd_hctl_elem_add(ctl, elem);
+               if (res < 0)
+                       return res;
+               break;
+       case SND_CTL_EVENT_REBUILD:
+               snd_hctl_free(ctl);
+               res = snd_hctl_build(ctl);
+               if (ctl->callback) {
+                       res = ctl->callback(ctl, event->type, NULL);
+                       if (res < 0)
+                               return res;
+               }
+               break;
+       default:
+               assert(0);
+               break;
+       }
+       return 0;
+}
+
+int snd_hctl_events(snd_ctl_t *ctl)
+{
+       snd_ctl_event_t event;
+       int res;
+       while ((res = snd_ctl_read(ctl, &event)) != 0) {
+               if (res < 0)
+                       return res;
+               res = snd_hctl_event(ctl, &event);
+               if (res < 0)
+                       return res;
+       }
+       return 0;
+}
+
+int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t *info)
+{
+       info->id = elem->id;
+       return snd_ctl_elem_info(elem->ctl, info);
+}
+
+int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_t * value)
+{
+       value->id = elem->id;
+       return snd_ctl_elem_read(elem->ctl, value);
+}
+
+int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_t * value)
+{
+       value->id = elem->id;
+       return snd_ctl_elem_write(elem->ctl, value);
+}
+
index 037fcc1e0bcd48f90424b57c702322e4108b07e8..1ba7d41d31614792c0236a1a9267f8c2fff48d50 100644 (file)
@@ -1,6 +1,6 @@
 EXTRA_LTLIBRARIES=libmixer.la
 
-libmixer_la_SOURCES = mixer.c simple.c
+libmixer_la_SOURCES = bag.c mixer.c mixer_m4.c simple.c
 
 all: libmixer.la
 
similarity index 59%
rename from src/control/bag.c
rename to src/mixer/bag.c
index 5eab958b08f98b7d2180a8db72064194ca996982..c941f84f36c32ff630969abc998073b7fce712bc 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Control Interface - highlevel API - helem bag operations
  *  Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
  *
  *
  *   This library is free software; you can redistribute it and/or modify
 #include <sys/ioctl.h>
 #define __USE_GNU
 #include <search.h>
-#include "control_local.h"
+#include "mixer_local.h"
 
-int snd_ctl_hbag_create(void **bag)
-{
-       assert(bag != NULL);
-       *bag = NULL;
-       return 0;
-}
+int snd_hctl_compare_fast(const snd_hctl_elem_t *c1,
+                         const snd_hctl_elem_t *c2);
 
-static void snd_ctl_hbag_free_private(snd_hctl_element_t *helem ATTRIBUTE_UNUSED)
-{
-       /* nothing */
-}
+static void _free(void *ptr ATTRIBUTE_UNUSED) { };
 
-int snd_ctl_hbag_destroy(void **bag, void (*hctl_element_free)(snd_hctl_element_t *helem))
+int snd_hctl_bag_destroy(snd_hctl_bag_t *bag)
 {
        assert(bag != NULL);
-       if (hctl_element_free == NULL)
-               hctl_element_free = snd_ctl_hbag_free_private;
-       tdestroy(*bag, (__free_fn_t)hctl_element_free);
-       *bag = NULL;
+       tdestroy(bag->root, _free);
+       bag->root = NULL;
        return 0;
 }
 
-int snd_ctl_hbag_add(void **bag, snd_hctl_element_t *helem)
+int snd_hctl_bag_add(snd_hctl_bag_t *bag, snd_hctl_elem_t *helem)
 {
        void *res;
-
        assert(bag != NULL && helem != NULL);
-       res = tsearch(helem, bag, (__compar_fn_t)snd_ctl_hsort);
+       res = tsearch(helem, &bag->root, (__compar_fn_t)snd_hctl_compare_fast);
        if (res == NULL)
                return -ENOMEM;
-       if ((snd_hctl_element_t *)res == helem)
+       if ((snd_hctl_elem_t *)res == helem)
                return -EALREADY;
        return 0;
 }
 
-int snd_ctl_hbag_del(void **bag, snd_hctl_element_t *helem)
+int snd_hctl_bag_del(snd_hctl_bag_t *bag, snd_hctl_elem_t *helem)
 {
        assert(bag != NULL && helem != NULL);
-       if (tdelete(helem, bag, (__compar_fn_t)snd_ctl_hsort) == NULL)
+       if (tdelete(helem, &bag->root, (__compar_fn_t)snd_hctl_compare_fast) == NULL)
                return -ENOENT;
        return 0;
 }
 
-snd_hctl_element_t *snd_ctl_hbag_find(void **bag, snd_ctl_element_id_t *id)
+snd_hctl_elem_t *snd_hctl_bag_find(snd_hctl_bag_t *bag, snd_ctl_elem_id_t *id)
 {
        void *res;
-
        assert(bag != NULL && id != NULL);
-       if (*bag == NULL)
+       if (bag->root == NULL)
                return NULL;
-       res = tfind(id, bag, (__compar_fn_t)snd_ctl_hsort);
-       return res == NULL ? NULL : *(snd_hctl_element_t **)res;
+       res = tfind(id, &bag->root, (__compar_fn_t)snd_hctl_compare_fast);
+       return res == NULL ? NULL : *(snd_hctl_elem_t **)res;
+}
+
+int snd_hctl_bag_empty(snd_hctl_bag_t *bag)
+{
+       assert(bag != NULL);
+       return bag->root == NULL;
 }
index 2a8d3b2e3c88dcb88ddda8d9916204a36f96308d..3e5ead6a38c17a8cb92ec3e5f314fae26d44f629 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Mixer Interface - main file
  *  Copyright (c) 1998/1999/2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
  *
  *
  *   This library is free software; you can redistribute it and/or modify
 #include <sys/ioctl.h>
 #include "mixer_local.h"
 
-static void snd_mixer_simple_read_rebuild(snd_ctl_t *ctl_handle, void *private_data);
-static void snd_mixer_simple_read_add(snd_ctl_t *ctl_handle, void *private_data, snd_hctl_element_t *helem);
-
-int snd_mixer_open(snd_mixer_t **r_handle, char *name)
+int snd_mixer_open(snd_mixer_t **mixerp, char *name)
 {
-       snd_mixer_t *handle;
-       snd_ctl_t *ctl_handle;
+       snd_mixer_t *mixer;
+       snd_ctl_t *ctl;
        int err;
-
-       if (r_handle == NULL)
-               return -EINVAL;
-       *r_handle = NULL;
-       if ((err = snd_ctl_open(&ctl_handle, name)) < 0)
+       assert(mixerp);
+       if ((err = snd_ctl_open(&ctl, name)) < 0)
                return err;
-       handle = (snd_mixer_t *) calloc(1, sizeof(snd_mixer_t));
-       if (handle == NULL) {
-               snd_ctl_close(ctl_handle);
+       mixer = calloc(1, sizeof(snd_mixer_t));
+       if (mixer == NULL) {
+               snd_ctl_close(ctl);
                return -ENOMEM;
        }
-       if ((err = snd_ctl_hcallback_rebuild(ctl_handle, snd_mixer_simple_read_rebuild, handle)) < 0) {
-               snd_ctl_close(ctl_handle);
-               free(handle);
-               return err;
-       }
-       if ((err = snd_ctl_hcallback_add(ctl_handle, snd_mixer_simple_read_add, handle)) < 0) {
-               snd_ctl_close(ctl_handle);
-               free(handle);
-               return err;
-       }
-       handle->ctl_handle = ctl_handle;
-       INIT_LIST_HEAD(&handle->simples);
-       *r_handle = handle;
+       mixer->ctl = ctl;
+       INIT_LIST_HEAD(&mixer->elems);
+       *mixerp = mixer;
        return 0;
 }
 
-int snd_mixer_close(snd_mixer_t *handle)
+snd_mixer_elem_t *snd_mixer_elem_add(snd_mixer_t *mixer)
 {
-       int err = 0;
-
-       if (handle == NULL)
-               return -EINVAL;
-       if (handle->simple_valid)
-               snd_mixer_simple_destroy(handle);
-       if (handle->ctl_handle)
-               err = snd_ctl_close(handle->ctl_handle);
-       return err;
+       snd_mixer_elem_t *elem;
+       elem = calloc(1, sizeof(*elem));
+       if (!elem)
+               return NULL;
+       elem->mixer = mixer;
+       list_add_tail(&elem->list, &mixer->elems);
+       mixer->count++;
+       return elem;
 }
 
-int snd_mixer_poll_descriptor(snd_mixer_t *handle)
+void snd_mixer_elem_remove(snd_mixer_elem_t *elem)
 {
-       if (handle == NULL || handle->ctl_handle == NULL)
-               return -EIO;
-       return snd_ctl_poll_descriptor(handle->ctl_handle);
+       snd_mixer_t *mixer = elem->mixer;
+       if (elem->private_free)
+               elem->private_free(elem);
+       if (elem->callback)
+               elem->callback(elem, SND_CTL_EVENT_REMOVE);
+       list_del(&elem->list);
+       free(elem);
+       mixer->count--;
 }
 
-const char *snd_mixer_simple_channel_name(snd_mixer_channel_id_t channel)
+void snd_mixer_free(snd_mixer_t *mixer)
 {
-       static char *array[snd_enum_to_int(SND_MIXER_CHN_LAST) + 1] = {
-               [SND_MIXER_CHN_FRONT_LEFT] = "Front Left",
-               [SND_MIXER_CHN_FRONT_RIGHT] = "Front Right",
-               [SND_MIXER_CHN_FRONT_CENTER] = "Front Center",
-               [SND_MIXER_CHN_REAR_LEFT] = "Rear Left",
-               [SND_MIXER_CHN_REAR_RIGHT] = "Rear Right",
-               [SND_MIXER_CHN_WOOFER] = "Woofer"
-       };
-       char *p;
-       assert(channel <= SND_MIXER_CHN_LAST);
-       p = array[snd_enum_to_int(channel)];
-       if (!p)
-               return "?";
-       return p;
+       while (!list_empty(&mixer->elems))
+               snd_mixer_elem_remove(list_entry(mixer->elems.next, snd_mixer_elem_t, list));
 }
 
-int snd_mixer_simple_element_list(snd_mixer_t *handle, snd_mixer_simple_element_list_t *list)
+int snd_mixer_close(snd_mixer_t *mixer)
 {
-       struct list_head *lh;
-       mixer_simple_t *s;
-       snd_mixer_sid_t *p;
-       int err;
-       unsigned int idx;
-
-       if (handle == NULL || list == NULL)
-               return -EINVAL;
-       if (!handle->simple_valid)
-               if ((err = snd_mixer_simple_build(handle)) < 0)
-                       return err;
-       list->controls_count = 0;
-       p = list->pids;
-       if (list->controls_request > 0 && p == NULL)
-               return -EINVAL;
-       idx = 0;
-       list_for_each(lh, &handle->simples) {
-               if (idx >= list->controls_offset + list->controls_request)
-                       break;
-               if (idx >= list->controls_offset) {
-                       s = list_entry(lh, mixer_simple_t, list);
-                       memcpy(p, &s->sid, sizeof(*p)); p++;
-                       list->controls_count++;
-               }
-               idx++;
-       }
-       list->controls = handle->simple_count;
-       return 0;
+       assert(mixer);
+       snd_mixer_free(mixer);
+       return snd_ctl_close(mixer->ctl);
 }
 
-static mixer_simple_t *look_for_simple(snd_mixer_t *handle, snd_mixer_sid_t *sid)
+int snd_mixer_poll_descriptor(snd_mixer_t *mixer)
 {
-       struct list_head *list;
-       mixer_simple_t *s;
-       
-       list_for_each(list, &handle->simples) {
-               s = list_entry(list, mixer_simple_t, list);
-               if (!strcmp(s->sid.name, sid->name) && s->sid.index == sid->index)
-                       return s;
-       }
-       return NULL;
+       if (mixer == NULL || mixer->ctl == NULL)
+               return -EIO;
+       return snd_ctl_poll_descriptor(mixer->ctl);
 }
 
-int snd_mixer_simple_element_read(snd_mixer_t *handle, snd_mixer_simple_element_t *control)
+snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer)
 {
-       mixer_simple_t *s;
-
-       if (handle == NULL || control == NULL)
-               return -EINVAL;
-       if (!handle->simple_valid)
-               snd_mixer_simple_build(handle);
-       s = look_for_simple(handle, &control->sid);
-       if (s == NULL)
-               return -ENOENT;
-       if (s->get == NULL)
-               return -EIO;
-       return s->get(handle, s, control);
+       assert(mixer);
+       if (list_empty(&mixer->elems))
+               return NULL;
+       return list_entry(mixer->elems.next, snd_mixer_elem_t, list);
 }
 
-int snd_mixer_simple_element_write(snd_mixer_t *handle, snd_mixer_simple_element_t *control)
+snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer)
 {
-       mixer_simple_t *s;
-
-       if (handle == NULL || control == NULL)
-               return -EINVAL;
-       if (!handle->simple_valid)
-               snd_mixer_simple_build(handle);
-       s = look_for_simple(handle, &control->sid);
-       if (s == NULL)
-               return -ENOENT;
-       if (s->put == NULL)
-               return -EIO;
-       return s->put(handle, s, control);
+       assert(mixer);
+       if (list_empty(&mixer->elems))
+               return NULL;
+       return list_entry(mixer->elems.prev, snd_mixer_elem_t, list);
 }
 
-static void snd_mixer_simple_read_rebuild(snd_ctl_t *ctl_handle, void *private_data)
+snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem)
 {
-       snd_mixer_t *handle = (snd_mixer_t *)private_data;
-       if (handle->ctl_handle != ctl_handle)
-               return;
-       handle->callbacks->rebuild(handle, handle->callbacks->private_data);
-       handle->simple_changes++;
+       assert(elem);
+       if (elem->list.next == &elem->mixer->elems)
+               return NULL;
+       return list_entry(elem->list.next, snd_mixer_elem_t, list);
 }
 
-static void snd_mixer_simple_read_add(snd_ctl_t *ctl_handle ATTRIBUTE_UNUSED, void *private_data, snd_hctl_element_t *helem)
+snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem)
 {
-       snd_mixer_t *handle = (snd_mixer_t *)private_data;
-       mixer_simple_t *s;
-       struct list_head *list;
-       
-       list_for_each(list, &handle->simples) {
-               s = list_entry(list, mixer_simple_t, list);
-               if (s->event_add)
-                       s->event_add(handle, helem);
-       }
+       assert(elem);
+       if (elem->list.prev == &elem->mixer->elems)
+               return NULL;
+       return list_entry(elem->list.prev, snd_mixer_elem_t, list);
 }
 
-int snd_mixer_simple_read(snd_mixer_t *handle, snd_mixer_simple_callbacks_t *callbacks)
+int snd_mixer_events(snd_mixer_t *mixer)
 {
-       mixer_simple_t *s;
-       struct list_head *list;
-       int err;
-
-       if (handle == NULL || callbacks == NULL)
-               return -EINVAL;
-       if (!handle->simple_valid)
-               snd_mixer_simple_build(handle);
-       handle->callbacks = callbacks;
-       handle->simple_changes = 0;
-       if ((err = snd_ctl_hevent(handle->ctl_handle)) <= 0) {
-               handle->callbacks = NULL;
-               return err;
-       }
-       handle->callbacks = NULL;
-       list_for_each(list, &handle->simples) {
-               s = list_entry(list, mixer_simple_t, list);
-               if (s->change > 0) {
-                       s->change = 0;
-                       if (callbacks->value)
-                               callbacks->value(handle, callbacks->private_data, &s->sid);
-               }
-       }
-       return handle->simple_changes;
+       return snd_hctl_events(mixer->ctl);
 }
+
index 91d4fe54937613187e5d4bb4256b4db9a6e2ae5a..ffe30aca6578b3f809dd73dee617e45873070a27 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Mixer Interface - local header file
  *  Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
  *
  *
  *   This library is free software; you can redistribute it and/or modify
  *
  */
 
-#include "local.h"
+//#include "../control/control_local.h"
 #include "list.h"
+#include "local.h"
 
-typedef struct _mixer_simple mixer_simple_t;
-typedef struct _mixer_simple_hctl_element_private mixer_simple_hctl_element_private_t;
+typedef struct _snd_hctl_bag {
+       void *root;
+       void *private;
+} snd_hctl_bag_t;
 
-typedef int (mixer_simple_get_t) (snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control);
-typedef int (mixer_simple_put_t) (snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control);
-typedef int (mixer_simple_event_add_t) (snd_mixer_t *handle, snd_hctl_element_t *helem);
+int snd_hctl_bag_destroy(snd_hctl_bag_t *bag);
+int snd_hctl_bag_add(snd_hctl_bag_t *bag, snd_hctl_elem_t *helem);
+int snd_hctl_bag_del(snd_hctl_bag_t *bag, snd_hctl_elem_t *helem);
+snd_hctl_elem_t *snd_hctl_bag_find(snd_hctl_bag_t *bag, snd_ctl_elem_id_t *id);
+int snd_hctl_bag_empty(snd_hctl_bag_t *bag);
 
-#define MIXER_PRESENT_SINGLE_SWITCH    (1<<0)
-#define MIXER_PRESENT_SINGLE_VOLUME    (1<<1)
-#define MIXER_PRESENT_GLOBAL_SWITCH    (1<<2)
-#define MIXER_PRESENT_GLOBAL_VOLUME    (1<<3)
-#define MIXER_PRESENT_GLOBAL_ROUTE     (1<<4)
-#define MIXER_PRESENT_PLAYBACK_SWITCH  (1<<5)
-#define MIXER_PRESENT_PLAYBACK_VOLUME  (1<<6)
-#define MIXER_PRESENT_PLAYBACK_ROUTE   (1<<7)
-#define MIXER_PRESENT_CAPTURE_SWITCH   (1<<8)
-#define MIXER_PRESENT_CAPTURE_VOLUME   (1<<9)
-#define MIXER_PRESENT_CAPTURE_ROUTE    (1<<10)
-#define MIXER_PRESENT_CAPTURE_SOURCE   (1<<11)
+struct _snd_mixer_elem {
+       snd_mixer_elem_type_t type;
+       struct list_head list;          /* links for list of all elems */
+       void *private;
+       void (*private_free)(snd_mixer_elem_t *elem);
+       snd_mixer_elem_callback_t callback;
+       void *callback_private;
+       snd_mixer_t *mixer;
+};
 
-struct _mixer_simple {
-       /* this may be moved to a private area */
-       unsigned int present;           /* present controls */
-       unsigned int global_values;
-       unsigned int gswitch_values;
-       unsigned int pswitch_values;
-       unsigned int cswitch_values;
-       unsigned int gvolume_values;
-       unsigned int pvolume_values;
-       unsigned int cvolume_values;
-       unsigned int groute_values;
-       unsigned int proute_values;
-       unsigned int croute_values;
-       unsigned int ccapture_values;
-       unsigned int capture_item;
-       unsigned int caps;
-       long min;
-       long max;
-       int voices;
-       /* -- */
-       int refs;                       /* number of references */
-       int change;                     /* simple control was changed */
-       snd_mixer_sid_t sid;
-       mixer_simple_get_t *get;
-       mixer_simple_put_t *put;
-       mixer_simple_event_add_t *event_add;
-       struct list_head list;
-       void *helems;           /* bag of associated helems */
-       unsigned long private_value;
+struct _snd_mixer {
+       snd_ctl_t *ctl;
+       struct list_head elems; /* list of all elemss */
+       unsigned int count;
+       snd_mixer_callback_t callback;
+       void *callback_private;
 };
 
-struct _mixer_simple_hctl_element_private {
-       void *simples;                  /* list of associated helems */
+#define SND_MIXER_SCTCAP_VOLUME         (1<<0)
+#define SND_MIXER_SCTCAP_JOIN_VOLUME   (1<<1)
+#define SND_MIXER_SCTCAP_MUTE           (1<<2)
+#define SND_MIXER_SCTCAP_JOIN_MUTE     (1<<3)
+#define SND_MIXER_SCTCAP_CAPTURE        (1<<4)
+#define SND_MIXER_SCTCAP_JOIN_CAPTURE  (1<<5)
+#define SND_MIXER_SCTCAP_EXCL_CAPTURE   (1<<6)
+
+struct _snd_mixer_selem_id {
+       unsigned char name[60];
+       unsigned int index;
 };
-  
-struct _snd_mixer {
-       snd_ctl_t *ctl_handle;
-       int simple_valid;
-       int simple_changes;             /* total number of changes */
-       int simple_count;
-       struct list_head simples;       /* list of all simple controls */
-       snd_mixer_simple_callbacks_t *callbacks;
+
+struct _snd_mixer_selem {
+       unsigned int caps;              /* RO: capabilities */
+       unsigned int channels;          /* RO: bitmap of active channels */
+       unsigned int mute;              /* RW: bitmap of muted channels */
+       unsigned int capture;           /* RW: bitmap of capture channels */
+       int capture_group;              /* RO: capture group (for exclusive capture) */
+       long min;                       /* RO: minimum value */
+       long max;                       /* RO: maximum value */
+       long volume[32];
 };
 
-int snd_mixer_simple_build(snd_mixer_t *handle);
-int snd_mixer_simple_destroy(snd_mixer_t *handle);
+snd_mixer_elem_t *snd_mixer_elem_add(snd_mixer_t *mixer);
+void snd_mixer_free(snd_mixer_t *mixer);
diff --git a/src/mixer/mixer_m4.c b/src/mixer/mixer_m4.c
new file mode 100644 (file)
index 0000000..acfbaa6
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ *  Mixer - Automatically generated functions
+ *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+  
+#include "mixer_local.h"
+
+size_t snd_mixer_selem_id_sizeof()
+{
+       return sizeof(snd_mixer_selem_id_t);
+}
+
+int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
+{
+       assert(ptr);
+       *ptr = calloc(1, sizeof(snd_mixer_selem_id_t));
+       if (!*ptr)
+               return -ENOMEM;
+       return 0;
+}
+
+void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
+{
+       free(obj);
+}
+
+void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src)
+{
+       assert(dst && src);
+       *dst = *src;
+}
+
+const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
+{
+       assert(obj);
+       return obj->name;
+}
+
+unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
+{
+       assert(obj);
+       return obj->index;
+}
+
+void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
+{
+       assert(obj);
+       strncpy(obj->name, val, sizeof(obj->name));
+}
+
+void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
+{
+       assert(obj);
+       obj->index = val;
+}
+
+void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val)
+{
+       assert(obj);
+       obj->callback = val;
+}
+
+void * snd_mixer_get_callback_private(const snd_mixer_t *obj)
+{
+       assert(obj);
+       return obj->callback_private;
+}
+
+void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val)
+{
+       assert(obj);
+       obj->callback_private = val;
+}
+
+unsigned int snd_mixer_get_count(const snd_mixer_t *obj)
+{
+       assert(obj);
+       return obj->count;
+}
+
+void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val)
+{
+       assert(obj);
+       obj->callback = val;
+}
+
+void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *obj)
+{
+       assert(obj);
+       return obj->callback_private;
+}
+
+void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val)
+{
+       assert(obj);
+       obj->callback_private = val;
+}
+
+snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *obj)
+{
+       assert(obj);
+       return obj->type;
+}
+
+size_t snd_mixer_selem_sizeof()
+{
+       return sizeof(snd_mixer_selem_t);
+}
+
+int snd_mixer_selem_malloc(snd_mixer_selem_t **ptr)
+{
+       assert(ptr);
+       *ptr = calloc(1, sizeof(snd_mixer_selem_t));
+       if (!*ptr)
+               return -ENOMEM;
+       return 0;
+}
+
+void snd_mixer_selem_free(snd_mixer_selem_t *obj)
+{
+       free(obj);
+}
+
+void snd_mixer_selem_copy(snd_mixer_selem_t *dst, const snd_mixer_selem_t *src)
+{
+       assert(dst && src);
+       *dst = *src;
+}
+
+long snd_mixer_selem_get_min(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return obj->min;
+}
+
+long snd_mixer_selem_get_max(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return obj->max;
+}
+
+int snd_mixer_selem_get_capture_group(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return obj->capture_group;
+}
+
+int snd_mixer_selem_has_volume(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_VOLUME);
+}
+
+int snd_mixer_selem_has_joined_volume(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_JOIN_VOLUME);
+}
+
+int snd_mixer_selem_has_mute(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_MUTE);
+}
+
+int snd_mixer_selem_has_joined_mute(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_JOIN_MUTE);
+}
+
+int snd_mixer_selem_has_capture(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_CAPTURE);
+}
+
+int snd_mixer_selem_has_joined_capture(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_JOIN_CAPTURE);
+}
+
+int snd_mixer_selem_has_exclusive_capture(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return !!(obj->caps & SND_MIXER_SCTCAP_EXCL_CAPTURE);
+}
+
index 7cee9e2697cb4eb4296ce681ceb934bb25d31604..acdf73c7c81a209234740a24f94519debf9d8468 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Mixer Interface - simple controls
  *  Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>
+ *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
  *
  *
  *   This library is free software; you can redistribute it and/or modify
 #include <string.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include "../control/control_local.h"
 #include "mixer_local.h"
 
+typedef struct _mixer_simple mixer_simple_t;
+
+typedef int (mixer_simple_read_t)(snd_mixer_elem_t *elem,
+                                 snd_mixer_selem_t *value);
+typedef int (mixer_simple_write_t)(snd_mixer_elem_t *elem,
+                                  const snd_mixer_selem_t *control);
+
+#define MIXER_PRESENT_SINGLE_SWITCH    (1<<0)
+#define MIXER_PRESENT_SINGLE_VOLUME    (1<<1)
+#define MIXER_PRESENT_GLOBAL_SWITCH    (1<<2)
+#define MIXER_PRESENT_GLOBAL_VOLUME    (1<<3)
+#define MIXER_PRESENT_GLOBAL_ROUTE     (1<<4)
+#define MIXER_PRESENT_PLAYBACK_SWITCH  (1<<5)
+#define MIXER_PRESENT_PLAYBACK_VOLUME  (1<<6)
+#define MIXER_PRESENT_PLAYBACK_ROUTE   (1<<7)
+#define MIXER_PRESENT_CAPTURE_SWITCH   (1<<8)
+#define MIXER_PRESENT_CAPTURE_VOLUME   (1<<9)
+#define MIXER_PRESENT_CAPTURE_ROUTE    (1<<10)
+#define MIXER_PRESENT_CAPTURE_SOURCE   (1<<11)
+
+typedef struct _selem {
+       snd_mixer_selem_id_t id;
+       unsigned int present;           /* present controls */
+       unsigned int global_values;
+       unsigned int gswitch_values;
+       unsigned int pswitch_values;
+       unsigned int cswitch_values;
+       unsigned int gvolume_values;
+       unsigned int pvolume_values;
+       unsigned int cvolume_values;
+       unsigned int groute_values;
+       unsigned int proute_values;
+       unsigned int croute_values;
+       unsigned int ccapture_values;
+       unsigned int capture_item;
+       unsigned int caps;
+       long min;
+       long max;
+       int voices;
+       /* -- */
+       mixer_simple_read_t *read;
+       mixer_simple_write_t *write;
+       snd_hctl_bag_t helems;          /* bag of associated helems */
+       unsigned long private_value;
+} selem_t;
+
 static struct mixer_name_table {
        const char *longname;
        const char *shortname;
@@ -39,112 +85,99 @@ static struct mixer_name_table {
        {0, 0},
 };
 
-static snd_hctl_element_t *test_mixer_id(snd_mixer_t *handle, const char *name, int index)
+const char *snd_mixer_channel_name(snd_mixer_channel_id_t channel)
+{
+       static char *array[snd_enum_to_int(SND_MIXER_CHN_LAST) + 1] = {
+               [SND_MIXER_CHN_FRONT_LEFT] = "Front Left",
+               [SND_MIXER_CHN_FRONT_RIGHT] = "Front Right",
+               [SND_MIXER_CHN_FRONT_CENTER] = "Front Center",
+               [SND_MIXER_CHN_REAR_LEFT] = "Rear Left",
+               [SND_MIXER_CHN_REAR_RIGHT] = "Rear Right",
+               [SND_MIXER_CHN_WOOFER] = "Woofer"
+       };
+       char *p;
+       assert(channel <= SND_MIXER_CHN_LAST);
+       p = array[snd_enum_to_int(channel)];
+       if (!p)
+               return "?";
+       return p;
+}
+
+static snd_hctl_elem_t *test_mixer_id(snd_mixer_t *mixer, const char *name, int index)
 {
-       snd_ctl_element_id_t id;
-       snd_hctl_element_t *helem;
+       snd_ctl_elem_id_t id;
+       snd_hctl_elem_t *helem;
        
        memset(&id, 0, sizeof(id));
-       id.iface = SNDRV_CTL_ELEMENT_IFACE_MIXER;
+       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(id.name, name);
        id.index = index;
-       helem = snd_ctl_hfind(handle->ctl_handle, &id);
+       helem = snd_hctl_find_elem(mixer->ctl, &id);
        // fprintf(stderr, "Looking for control: '%s', %i (0x%lx)\n", name, index, (long)helem);
        return helem;
 }
 
-static int get_mixer_info(snd_mixer_t *handle, const char *name, int index, snd_ctl_element_info_t *info)
+static int get_mixer_info(snd_mixer_t *mixer, const char *name, int index, snd_ctl_elem_info_t *info)
 {
        memset(info, 0, sizeof(*info));
-       info->id.iface = SNDRV_CTL_ELEMENT_IFACE_MIXER;
+       info->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(info->id.name, name);
        info->id.index = index;
-       return snd_ctl_element_info(handle->ctl_handle, info);
+       return snd_ctl_elem_info(mixer->ctl, info);
 }
 
-static int get_mixer_read(snd_mixer_t *handle, const char *name, int index, snd_ctl_element_t *control)
+static int get_mixer_read(snd_mixer_t *mixer, const char *name, int index, snd_ctl_elem_t *control)
 {
        memset(control, 0, sizeof(*control));
-       control->id.iface = SNDRV_CTL_ELEMENT_IFACE_MIXER;
+       control->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(control->id.name, name);
        control->id.index = index;
-       return snd_ctl_element_read(handle->ctl_handle, control);
+       return snd_ctl_elem_read(mixer->ctl, control);
 }
 
-static int put_mixer_write(snd_mixer_t *handle, const char *name, int index, snd_ctl_element_t *control)
+static int put_mixer_write(snd_mixer_t *mixer, const char *name, int index, snd_ctl_elem_t *control)
 {
        control->id.numid = 0;
-       control->id.iface = SNDRV_CTL_ELEMENT_IFACE_MIXER;
+       control->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(control->id.name, name);
        control->id.device = control->id.subdevice = 0;
        control->id.index = index;
        control->indirect = 0;
        memset(&control->reserved, 0, sizeof(control->reserved));
-       return snd_ctl_element_write(handle->ctl_handle, control);
-}
-
-static mixer_simple_t *simple_new(mixer_simple_t *scontrol)
-{
-       mixer_simple_t *s;
-       
-       if (scontrol == NULL)
-               return NULL;
-       s = (mixer_simple_t *) calloc(1, sizeof(*s));
-       if (s == NULL)
-               return NULL;
-       *s = *scontrol;
-       return s;
-}
-
-static void hctl_element_event_change(snd_ctl_t *ctl_handle ATTRIBUTE_UNUSED, snd_hctl_element_t *helem ATTRIBUTE_UNUSED)
-{
-       /* ignore at this moment */
+       return snd_ctl_elem_write(mixer->ctl, control);
 }
 
-static void hctl_element_event_value(snd_ctl_t *ctl_handle ATTRIBUTE_UNUSED, snd_hctl_element_t *helem)
+static int hctl_elem_event(snd_hctl_elem_t *helem,
+                             snd_ctl_event_type_t type)
 {
-       snd_mixer_t *handle = (snd_mixer_t *)helem->private_data;
-       mixer_simple_t *s;
-       struct list_head *list;
-       list_for_each(list, &handle->simples) {
-               s = list_entry(list, mixer_simple_t, list);
-               if (snd_ctl_hbag_find(&s->helems, &helem->id))
-                       s->change++;
+       switch (type) {
+       case SND_CTL_EVENT_CHANGE:
+       case SND_CTL_EVENT_REMOVE:
+               /* ignore at this moment */
+               break;
+       case SND_CTL_EVENT_VALUE:
+       {
+               snd_hctl_bag_t *bag = snd_hctl_elem_get_callback_private(helem);
+               snd_mixer_elem_t *e = bag->private;
+               if (e->callback) {
+                       int res = e->callback(e, type);
+                       if (res < 0)
+                               return res;
+               }
+               break;
+       }
+       default:
+               assert(0);
+               break;
        }
-}
-
-static void hctl_element_event_remove(snd_ctl_t *ctl_handle ATTRIBUTE_UNUSED, snd_hctl_element_t *helem ATTRIBUTE_UNUSED)
-{
-       /* ignore at this moment */
-}
-
-static void hctl_element_add(snd_mixer_t *handle, void **bag, snd_hctl_element_t *helem)
-{
-       snd_ctl_hbag_add(bag, helem);
-       helem->callback_change = hctl_element_event_change;
-       helem->callback_value = hctl_element_event_value;
-       helem->callback_remove = hctl_element_event_remove;
-       helem->private_data = handle;
-}
-
-static int simple_add(snd_mixer_t *handle, mixer_simple_t *scontrol)
-{
-       if (handle == NULL || scontrol == NULL)
-               return -EINVAL;
-       list_add_tail(&scontrol->list, &handle->simples);
-       handle->simple_count++;
        return 0;
 }
 
-static int simple_remove(snd_mixer_t *handle, mixer_simple_t *scontrol)
+static void hctl_elem_add(snd_hctl_bag_t *bag, snd_hctl_elem_t *helem)
 {
-       if (handle == NULL || scontrol == NULL)
-               return -EINVAL;
-       list_del(&scontrol->list);
-       handle->simple_count--;
-       snd_ctl_hbag_destroy(&scontrol->helems, NULL);
-       free(scontrol);
-       return 0;
+       snd_hctl_bag_add(bag, helem);
+       snd_hctl_elem_set_callback(helem, hctl_elem_event);
+       snd_hctl_elem_set_callback_private(helem, bag);
 }
 
 static const char *get_full_name(const char *sname)
@@ -167,28 +200,28 @@ static const char *get_short_name(const char *lname)
        return lname;
 }
 
-static int input_get_volume(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, const char *postfix, int voices)
+static int elem_read_volume(snd_mixer_t *mixer, selem_t *simple, snd_mixer_selem_t *control, const char *direction, const char *postfix, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s%s%s", get_full_name(simple->sid.name), direction, postfix);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s%s%s", get_full_name(simple->id.name), direction, postfix);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < simple->voices && idx < 32; idx++)
-               control->volume.values[idx] = ctl.value.integer.value[voices == 1 ? 0 : idx];
+               control->volume[idx] = ctl.value.integer.value[voices == 1 ? 0 : idx];
        return 0;
 }
 
-static int input_get_mute_switch(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, const char *postfix, int voices)
+static int elem_read_mute_switch(snd_mixer_t *mixer, selem_t *simple, snd_mixer_selem_t *control, const char *direction, const char *postfix, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s%s%s", get_full_name(simple->sid.name), direction, postfix);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s%s%s", get_full_name(simple->id.name), direction, postfix);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < simple->voices && idx < 32; idx++)
                if (ctl.value.integer.value[voices == 1 ? 0 : idx] == 0)
@@ -196,14 +229,14 @@ static int input_get_mute_switch(snd_mixer_t *handle, mixer_simple_t *simple, sn
        return 0;
 }
 
-static int input_get_mute_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, int voices)
+static int elem_read_mute_route(snd_mixer_t *mixer, selem_t *simple, snd_mixer_selem_t *control, const char *direction, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s %sRoute", get_full_name(simple->sid.name), direction);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s %sRoute", get_full_name(simple->id.name), direction);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < simple->voices && idx < 32; idx++)
                if (ctl.value.integer.value[(idx * voices) + idx] == 0)
@@ -211,14 +244,14 @@ static int input_get_mute_route(snd_mixer_t *handle, mixer_simple_t *simple, snd
        return 0;
 }
 
-static int input_get_capture_switch(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, int voices)
+static int elem_read_capture_switch(snd_mixer_t *mixer, selem_t *simple, snd_mixer_selem_t *control, const char *direction, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s %sSwitch", get_full_name(simple->sid.name), direction);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s %sSwitch", get_full_name(simple->id.name), direction);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < simple->voices && idx < 32; idx++)
                if (ctl.value.integer.value[voices == 1 ? 0 : idx])
@@ -226,14 +259,14 @@ static int input_get_capture_switch(snd_mixer_t *handle, mixer_simple_t *simple,
        return 0;
 }
 
-static int input_get_capture_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, int voices)
+static int elem_read_capture_route(snd_mixer_t *mixer, selem_t *simple, snd_mixer_selem_t *control, const char *direction, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s %sRoute", get_full_name(simple->sid.name), direction);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s %sRoute", get_full_name(simple->id.name), direction);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < simple->voices && idx < 32; idx++)
                if (ctl.value.integer.value[(idx * voices) + idx])
@@ -241,12 +274,16 @@ static int input_get_capture_route(snd_mixer_t *handle, mixer_simple_t *simple,
        return 0;
 }
 
-static int input_get(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control)
+static int elem_read(snd_mixer_elem_t *elem,
+                    snd_mixer_selem_t *control)
 {
+       snd_mixer_t *mixer;
+       selem_t *simple;
        int idx, err;
 
-       if (simple == NULL)
-               return -EINVAL;
+       assert(elem->type == SND_MIXER_ELEM_SIMPLE);
+       simple = elem->private;
+       mixer = elem->mixer;
 
        control->caps = simple->caps;
        control->channels = 0;
@@ -256,40 +293,40 @@ static int input_get(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simp
        control->min = simple->min;
        control->max = simple->max;
        for (idx = 0; idx < 32; idx++)
-               control->volume.values[idx] = 0;
+               control->volume[idx] = 0;
 
        for (idx = 0; idx < simple->voices && idx < 32; idx++)
                control->channels |= 1 << idx;
        if (simple->caps & SND_MIXER_SCTCAP_VOLUME) {
                if (simple->present & MIXER_PRESENT_PLAYBACK_VOLUME) {
-                       input_get_volume(handle, simple, control, " Playback", " Volume", simple->pvolume_values);
+                       elem_read_volume(mixer, simple, control, " Playback", " Volume", simple->pvolume_values);
                } else if (simple->present & MIXER_PRESENT_GLOBAL_VOLUME) {
-                       input_get_volume(handle, simple, control, "", " Volume", simple->gvolume_values);
+                       elem_read_volume(mixer, simple, control, "", " Volume", simple->gvolume_values);
                } else if (simple->present & MIXER_PRESENT_SINGLE_VOLUME) {
-                       input_get_volume(handle, simple, control, "", "", simple->global_values);
+                       elem_read_volume(mixer, simple, control, "", "", simple->global_values);
                }
        }
        if (simple->caps & SND_MIXER_SCTCAP_MUTE) {
                if (simple->present & MIXER_PRESENT_PLAYBACK_SWITCH) {
-                       input_get_mute_switch(handle, simple, control, " Playback", " Switch", simple->pswitch_values);
+                       elem_read_mute_switch(mixer, simple, control, " Playback", " Switch", simple->pswitch_values);
                } else if (simple->present & MIXER_PRESENT_GLOBAL_SWITCH) {
-                       input_get_mute_switch(handle, simple, control, "", " Switch", simple->gswitch_values);
+                       elem_read_mute_switch(mixer, simple, control, "", " Switch", simple->gswitch_values);
                } else if (simple->present & MIXER_PRESENT_SINGLE_SWITCH) {
-                       input_get_mute_switch(handle, simple, control, "", "", simple->global_values);
+                       elem_read_mute_switch(mixer, simple, control, "", "", simple->global_values);
                } else if (simple->present & MIXER_PRESENT_PLAYBACK_ROUTE) {
-                       input_get_mute_route(handle, simple, control, "Playback ", simple->proute_values);
+                       elem_read_mute_route(mixer, simple, control, "Playback ", simple->proute_values);
                } else if (simple->present & MIXER_PRESENT_GLOBAL_ROUTE) {
-                       input_get_mute_route(handle, simple, control, "", simple->groute_values);
+                       elem_read_mute_route(mixer, simple, control, "", simple->groute_values);
                }
        }
        if (simple->caps & SND_MIXER_SCTCAP_CAPTURE) {
                if (simple->present & MIXER_PRESENT_CAPTURE_SWITCH) {
-                       input_get_capture_switch(handle, simple, control, "Capture ", simple->cswitch_values);
+                       elem_read_capture_switch(mixer, simple, control, "Capture ", simple->cswitch_values);
                } else if (simple->present & MIXER_PRESENT_CAPTURE_ROUTE) {
-                       input_get_capture_route(handle, simple, control, "Capture ", simple->croute_values);
+                       elem_read_capture_route(mixer, simple, control, "Capture ", simple->croute_values);
                } else if (simple->present & MIXER_PRESENT_CAPTURE_SOURCE) {
-                       snd_ctl_element_t ctl;
-                       if ((err = get_mixer_read(handle, "Capture Source", 0, &ctl)) < 0)
+                       snd_ctl_elem_t ctl;
+                       if ((err = get_mixer_read(mixer, "Capture Source", 0, &ctl)) < 0)
                                return err;
                        for (idx = 0; idx < simple->voices && idx < 32; idx++)
                                if (ctl.value.enumerated.item[simple->ccapture_values == 1 ? 0 : idx] == simple->capture_item)
@@ -299,174 +336,191 @@ static int input_get(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simp
        return 0;
 }
 
-static int input_put_volume(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, const char *postfix, int voices)
+static int elem_write_volume(snd_mixer_t *mixer, selem_t *simple, const snd_mixer_selem_t *control, const char *direction, const char *postfix, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s%s%s", get_full_name(simple->sid.name), direction, postfix);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s%s%s", get_full_name(simple->id.name), direction, postfix);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < voices && idx < 32; idx++) {
-               ctl.value.integer.value[idx] = control->volume.values[idx];
+               ctl.value.integer.value[idx] = control->volume[idx];
                // fprintf(stderr, "ctl.id.name = '%s', volume = %i [%i]\n", ctl.id.name, ctl.value.integer.value[idx], idx);
        }
-       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+       if ((err = put_mixer_write(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        return 0;
 }
 
-static int input_put_mute_switch(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, const char *postfix, int voices)
+static int elem_write_mute_switch(snd_mixer_t *mixer, selem_t *simple, const snd_mixer_selem_t *control, const char *direction, const char *postfix, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s%s%s", get_full_name(simple->sid.name), direction, postfix);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s%s%s", get_full_name(simple->id.name), direction, postfix);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < voices && idx < 32; idx++)
                ctl.value.integer.value[idx] = (control->mute & (1 << idx)) ? 0 : 1;
-       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+       if ((err = put_mixer_write(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        return 0;
 }
 
-static int input_put_mute_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, int voices)
+static int elem_write_mute_route(snd_mixer_t *mixer, selem_t *simple, const snd_mixer_selem_t *control, const char *direction, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s %sRoute", get_full_name(simple->sid.name), direction);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s %sRoute", get_full_name(simple->id.name), direction);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < voices * voices; idx++)
                ctl.value.integer.value[idx] = 0;
        for (idx = 0; idx < voices && idx < 32; idx++)
                ctl.value.integer.value[(idx * voices) + idx] = (control->mute & (1 << idx)) ? 0 : 1;
-       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+       if ((err = put_mixer_write(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        return 0;
 }
 
-static int input_put_capture_switch(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, int voices)
+static int elem_write_capture_switch(snd_mixer_t *mixer, selem_t *simple, const snd_mixer_selem_t *control, const char *direction, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s %sSwitch", get_full_name(simple->sid.name), direction);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s %sSwitch", get_full_name(simple->id.name), direction);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < voices && idx < 32; idx++)
                ctl.value.integer.value[idx] = (control->capture & (1 << idx)) ? 1 : 0;
-       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+       if ((err = put_mixer_write(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        return 0;
 }
 
-static int input_put_capture_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control, const char *direction, int voices)
+static int elem_write_capture_route(snd_mixer_t *mixer, selem_t *simple, const snd_mixer_selem_t *control, const char *direction, int voices)
 {
        char str[128];
-       snd_ctl_element_t ctl;
+       snd_ctl_elem_t ctl;
        int idx, err;
        
-       sprintf(str, "%s %sRoute", get_full_name(simple->sid.name), direction);
-       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+       sprintf(str, "%s %sRoute", get_full_name(simple->id.name), direction);
+       if ((err = get_mixer_read(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        for (idx = 0; idx < voices * voices; idx++)
                ctl.value.integer.value[idx] = 0;
        for (idx = 0; idx < voices && idx < 32; idx++)
                ctl.value.integer.value[(idx * voices) + idx] = (control->capture & (1 << idx)) ? 1 : 0;
-       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+       if ((err = put_mixer_write(mixer, str, simple->id.index, &ctl)) < 0)
                return err;
        return 0;
 }
 
-static int input_put(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_element_t *control)
+static int elem_write(snd_mixer_elem_t *elem,
+                     const snd_mixer_selem_t *control)
 {
-       int err, idx;
+       snd_mixer_t *mixer;
+       selem_t *simple;
+       int idx, err;
 
-       if (simple == NULL)
-               return -EINVAL;
+       assert(elem->type == SND_MIXER_ELEM_SIMPLE);
+       simple = elem->private;
+       mixer = elem->mixer;
 
        if (simple->caps & SND_MIXER_SCTCAP_VOLUME) {
                if (simple->present & MIXER_PRESENT_PLAYBACK_VOLUME) {
-                       input_put_volume(handle, simple, control, " Playback", " Volume", simple->pvolume_values);
+                       elem_write_volume(mixer, simple, control, " Playback", " Volume", simple->pvolume_values);
                        if (simple->present & MIXER_PRESENT_CAPTURE_VOLUME)
-                               input_put_volume(handle, simple, control, " Capture", " Volume", simple->cvolume_values);
+                               elem_write_volume(mixer, simple, control, " Capture", " Volume", simple->cvolume_values);
                } else if (simple->present & MIXER_PRESENT_GLOBAL_VOLUME) {
-                       input_put_volume(handle, simple, control, "", " Volume", simple->gvolume_values);
+                       elem_write_volume(mixer, simple, control, "", " Volume", simple->gvolume_values);
                } else if (simple->present & MIXER_PRESENT_SINGLE_VOLUME) {
-                       input_put_volume(handle, simple, control, "", "", simple->global_values);
+                       elem_write_volume(mixer, simple, control, "", "", simple->global_values);
                }
        }
        if (simple->caps & SND_MIXER_SCTCAP_MUTE) {
                if (simple->present & MIXER_PRESENT_PLAYBACK_SWITCH)
-                       input_put_mute_switch(handle, simple, control, " Playback", " Switch", simple->pswitch_values);
+                       elem_write_mute_switch(mixer, simple, control, " Playback", " Switch", simple->pswitch_values);
                if (simple->present & MIXER_PRESENT_GLOBAL_SWITCH)
-                       input_put_mute_switch(handle, simple, control, "", " Switch", simple->gswitch_values);
+                       elem_write_mute_switch(mixer, simple, control, "", " Switch", simple->gswitch_values);
                if (simple->present & MIXER_PRESENT_SINGLE_SWITCH)
-                       input_put_mute_switch(handle, simple, control, "", "", simple->global_values);
+                       elem_write_mute_switch(mixer, simple, control, "", "", simple->global_values);
                if (simple->present & MIXER_PRESENT_PLAYBACK_ROUTE)
-                       input_put_mute_route(handle, simple, control, "Playback ", simple->proute_values);
+                       elem_write_mute_route(mixer, simple, control, "Playback ", simple->proute_values);
                if (simple->present & MIXER_PRESENT_GLOBAL_ROUTE)
-                       input_put_mute_route(handle, simple, control, "", simple->groute_values);
+                       elem_write_mute_route(mixer, simple, control, "", simple->groute_values);
        }
        if (simple->caps & SND_MIXER_SCTCAP_CAPTURE) {
                // fprintf(stderr, "capture: present = 0x%x\n", simple->present);
                if (simple->present & MIXER_PRESENT_CAPTURE_SWITCH) {
-                       input_put_capture_switch(handle, simple, control, "Capture ", simple->cswitch_values);
+                       elem_write_capture_switch(mixer, simple, control, "Capture ", simple->cswitch_values);
                } else if (simple->present & MIXER_PRESENT_CAPTURE_ROUTE) {
-                       input_put_capture_route(handle, simple, control, "Capture ", simple->croute_values);
+                       elem_write_capture_route(mixer, simple, control, "Capture ", simple->croute_values);
                } else if (simple->present & MIXER_PRESENT_CAPTURE_SOURCE) {
-                       snd_ctl_element_t ctl;
-                       if ((err = get_mixer_read(handle, "Capture Source", 0, &ctl)) < 0)
+                       snd_ctl_elem_t ctl;
+                       if ((err = get_mixer_read(mixer, "Capture Source", 0, &ctl)) < 0)
                                return err;
                        // fprintf(stderr, "put capture source : %i [0x%x]\n", simple->capture_item, control->capture);
                        for (idx = 0; idx < simple->voices && idx < 32; idx++) {
                                if (control->capture & (1 << idx))
                                        ctl.value.enumerated.item[idx] = simple->capture_item;
                        }
-                       if ((err = put_mixer_write(handle, "Capture Source", 0, &ctl)) < 0)
+                       if ((err = put_mixer_write(mixer, "Capture Source", 0, &ctl)) < 0)
                                return err;
                }
        }
        return 0;
 }
 
-static mixer_simple_t *build_input_scontrol(snd_mixer_t *handle, const char *sname, int index)
+static void selem_free(snd_mixer_elem_t *elem)
 {
-       mixer_simple_t s, *p;
+       selem_t *s;
+       assert(elem->type == SND_MIXER_ELEM_SIMPLE);
+       s = elem->private;
+       snd_hctl_bag_destroy(&s->helems);
+       free(s);
+}
 
-       memset(&s, 0, sizeof(s));
-       strcpy(s.sid.name, sname);
-       s.sid.index = index;
-       s.get = input_get;
-       s.put = input_put;
-       if (simple_add(handle, p = simple_new(&s)) < 0) {
-               free(p);
+static selem_t *build_elem_scontrol(snd_mixer_t *mixer, const char *sname, int index)
+{
+       snd_mixer_elem_t *elem;
+       selem_t *s;
+       s = calloc(1, sizeof(*s));
+       strcpy(s->id.name, sname);
+       s->id.index = index;
+       s->read = elem_read;
+       s->write = elem_write;
+       elem = snd_mixer_elem_add(mixer);
+       if (!elem) {
+               free(s);
                return NULL;
        }
-       return p;
+       elem->type = SND_MIXER_ELEM_SIMPLE;
+       elem->private = s;
+       elem->private_free = selem_free;
+       return s;
 }
 
-static int build_input(snd_mixer_t *handle, const char *sname)
+static int build_elem(snd_mixer_t *mixer, const char *sname)
 {
        char str[128];
        unsigned int present, caps, capture_item, voices;
        int index = -1, err;
-       snd_ctl_element_info_t global_info;
-       snd_ctl_element_info_t gswitch_info, pswitch_info, cswitch_info;
-       snd_ctl_element_info_t gvolume_info, pvolume_info, cvolume_info;
-       snd_ctl_element_info_t groute_info, proute_info, croute_info;
-       snd_ctl_element_info_t csource_info;
+       snd_ctl_elem_info_t global_info;
+       snd_ctl_elem_info_t gswitch_info, pswitch_info, cswitch_info;
+       snd_ctl_elem_info_t gvolume_info, pvolume_info, cvolume_info;
+       snd_ctl_elem_info_t groute_info, proute_info, croute_info;
+       snd_ctl_elem_info_t csource_info;
        long min, max;
-       void *bag;
-       mixer_simple_t *simple;
-       snd_hctl_element_t *helem;
+       snd_hctl_bag_t bag;
+       selem_t *simple;
+       snd_hctl_elem_t *helem;
        const char *sname1;
 
        memset(&gswitch_info, 0, sizeof(gswitch_info));
@@ -483,54 +537,54 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                voices = 0;
                present = caps = capture_item = 0;
                min = max = 0;
-               bag = NULL;
-               if ((helem = test_mixer_id(handle, sname, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, sname, index, &global_info)) < 0)
+               memset(&bag, 0, sizeof(bag));
+               if ((helem = test_mixer_id(mixer, sname, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, sname, index, &global_info)) < 0)
                                return err;
-                       if (global_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN || 
-                           global_info.type == SNDRV_CTL_ELEMENT_TYPE_INTEGER) {
+                       if (global_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || 
+                           global_info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                                if (voices < global_info.count)
                                        voices = global_info.count;
-                               caps |= global_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN ? SND_MIXER_SCTCAP_MUTE : SND_MIXER_SCTCAP_VOLUME;
-                               present |= global_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN ? MIXER_PRESENT_SINGLE_SWITCH : MIXER_PRESENT_SINGLE_VOLUME;
-                               if (global_info.type == SNDRV_CTL_ELEMENT_TYPE_INTEGER) {
+                               caps |= global_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ? SND_MIXER_SCTCAP_MUTE : SND_MIXER_SCTCAP_VOLUME;
+                               present |= global_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ? MIXER_PRESENT_SINGLE_SWITCH : MIXER_PRESENT_SINGLE_VOLUME;
+                               if (global_info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                                        if (min > global_info.value.integer.min)
                                                min = global_info.value.integer.min;
                                        if (max < global_info.value.integer.max)
                                                max = global_info.value.integer.max;
                                }
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Switch", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &gswitch_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &gswitch_info)) < 0)
                                return err;
-                       if (gswitch_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN) {
+                       if (gswitch_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN) {
                                if (voices < gswitch_info.count)
                                        voices = gswitch_info.count;
                                caps |= SND_MIXER_SCTCAP_MUTE;
                                present |= MIXER_PRESENT_GLOBAL_SWITCH;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Route", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &groute_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &groute_info)) < 0)
                                return err;
-                       if (groute_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN && groute_info.count == 4) {
+                       if (groute_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && groute_info.count == 4) {
                                if (voices < 2)
                                        voices = 2;
                                caps |= SND_MIXER_SCTCAP_MUTE;
                                present |= MIXER_PRESENT_GLOBAL_ROUTE;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Volume", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &gvolume_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &gvolume_info)) < 0)
                                return err;
-                       if (gvolume_info.type == SNDRV_CTL_ELEMENT_TYPE_INTEGER) {
+                       if (gvolume_info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                                if (voices < gvolume_info.count)
                                        voices = gvolume_info.count;
                                if (min > gvolume_info.value.integer.min)
@@ -539,62 +593,62 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                        max = gvolume_info.value.integer.max;
                                caps |= SND_MIXER_SCTCAP_VOLUME;
                                present |= MIXER_PRESENT_GLOBAL_VOLUME;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Playback Switch", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &pswitch_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &pswitch_info)) < 0)
                                return err;
-                       if (pswitch_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN) {
+                       if (pswitch_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN) {
                                if (voices < pswitch_info.count)
                                        voices = pswitch_info.count;
                                caps |= SND_MIXER_SCTCAP_MUTE;
                                present |= MIXER_PRESENT_PLAYBACK_SWITCH;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Playback Route", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &proute_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &proute_info)) < 0)
                                return err;
-                       if (proute_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN && proute_info.count == 4) {
+                       if (proute_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && proute_info.count == 4) {
                                if (voices < 2)
                                        voices = 2;
                                caps |= SND_MIXER_SCTCAP_MUTE;
                                present |= MIXER_PRESENT_PLAYBACK_ROUTE;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Capture Switch", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &cswitch_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &cswitch_info)) < 0)
                                return err;
-                       if (cswitch_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN) {
+                       if (cswitch_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN) {
                                if (voices < cswitch_info.count)
                                        voices = cswitch_info.count;
                                caps |= SND_MIXER_SCTCAP_CAPTURE;
                                present |= MIXER_PRESENT_CAPTURE_SWITCH;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Capture Route", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &croute_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &croute_info)) < 0)
                                return err;
-                       if (croute_info.type == SNDRV_CTL_ELEMENT_TYPE_BOOLEAN && croute_info.count == 4) {
+                       if (croute_info.type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && croute_info.count == 4) {
                                if (voices < 2)
                                        voices = 2;
                                caps |= SND_MIXER_SCTCAP_CAPTURE;
                                present |= MIXER_PRESENT_CAPTURE_ROUTE;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Playback Volume", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &pvolume_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &pvolume_info)) < 0)
                                return err;
-                       if (pvolume_info.type == SNDRV_CTL_ELEMENT_TYPE_INTEGER) {
+                       if (pvolume_info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                                if (voices < pvolume_info.count)
                                        voices = pvolume_info.count;
                                if (min > pvolume_info.value.integer.min)
@@ -603,14 +657,14 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                        max = pvolume_info.value.integer.max;
                                caps |= SND_MIXER_SCTCAP_VOLUME;
                                present |= MIXER_PRESENT_PLAYBACK_VOLUME;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
                sprintf(str, "%s Capture Volume", sname);
-               if ((helem = test_mixer_id(handle, str, index)) != NULL) {
-                       if ((err = get_mixer_info(handle, str, index, &cvolume_info)) < 0)
+               if ((helem = test_mixer_id(mixer, str, index)) != NULL) {
+                       if ((err = get_mixer_info(mixer, str, index, &cvolume_info)) < 0)
                                return err;
-                       if (cvolume_info.type == SNDRV_CTL_ELEMENT_TYPE_INTEGER) {
+                       if (cvolume_info.type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                                if (voices < cvolume_info.count)
                                        voices = cvolume_info.count;
                                if (min > pvolume_info.value.integer.min)
@@ -619,35 +673,35 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                        max = pvolume_info.value.integer.max;
                                caps |= SND_MIXER_SCTCAP_VOLUME;
                                present |= MIXER_PRESENT_CAPTURE_VOLUME;
-                               hctl_element_add(handle, &bag, helem);
+                               hctl_elem_add(&bag, helem);
                        }
                }
-               if (index == 0 && (helem = test_mixer_id(handle, "Capture Source", 0)) != NULL) {
-                       if ((err = get_mixer_info(handle, "Capture Source", 0, &csource_info)) < 0)
+               if (index == 0 && (helem = test_mixer_id(mixer, "Capture Source", 0)) != NULL) {
+                       if ((err = get_mixer_info(mixer, "Capture Source", 0, &csource_info)) < 0)
                                return err;
                        strcpy(str, sname);
                        if (!strcmp(str, "Master"))     /* special case */
                                strcpy(str, "Mix");
                        else if (!strcmp(str, "Master Mono")) /* special case */
                                strcpy(str, "Mono Mix");
-                       if (csource_info.type == SNDRV_CTL_ELEMENT_TYPE_ENUMERATED) {
+                       if (csource_info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
                                capture_item = 0;
                                if (!strcmp(csource_info.value.enumerated.name, str)) {
                                        if (voices < csource_info.count)
                                                voices = csource_info.count;
                                        caps |= SND_MIXER_SCTCAP_CAPTURE;
                                        present |= MIXER_PRESENT_CAPTURE_SOURCE;
-                                       hctl_element_add(handle, &bag, helem);
+                                       hctl_elem_add(&bag, helem);
                                } else for (capture_item = 1; capture_item < csource_info.value.enumerated.items; capture_item++) {
                                        csource_info.value.enumerated.item = capture_item;
-                                       if ((err = snd_ctl_element_info(handle->ctl_handle, &csource_info)) < 0)
+                                       if ((err = snd_ctl_elem_info(mixer->ctl, &csource_info)) < 0)
                                                return err;
                                        if (!strcmp(csource_info.value.enumerated.name, str)) {
                                                if (voices < csource_info.count)
                                                        voices = csource_info.count;
                                                caps |= SND_MIXER_SCTCAP_CAPTURE;
                                                present |= MIXER_PRESENT_CAPTURE_SOURCE;
-                                               hctl_element_add(handle, &bag, helem);
+                                               hctl_elem_add(&bag, helem);
                                                break;
                                        }
                                }
@@ -655,54 +709,54 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                }
                if (voices > 1) {
                        if (present & (MIXER_PRESENT_SINGLE_SWITCH|MIXER_PRESENT_GLOBAL_SWITCH|MIXER_PRESENT_GLOBAL_ROUTE|MIXER_PRESENT_PLAYBACK_SWITCH|MIXER_PRESENT_GLOBAL_SWITCH))
-                               caps |= SND_MIXER_SCTCAP_JOINTLY_MUTE;
+                               caps |= SND_MIXER_SCTCAP_JOIN_MUTE;
                        if (present & (MIXER_PRESENT_CAPTURE_SWITCH|MIXER_PRESENT_CAPTURE_ROUTE|MIXER_PRESENT_CAPTURE_SOURCE))
-                               caps |= SND_MIXER_SCTCAP_JOINTLY_CAPTURE;
+                               caps |= SND_MIXER_SCTCAP_JOIN_CAPTURE;
                        if (present & (MIXER_PRESENT_SINGLE_VOLUME|MIXER_PRESENT_GLOBAL_VOLUME|MIXER_PRESENT_PLAYBACK_VOLUME|MIXER_PRESENT_CAPTURE_VOLUME))
-                               caps |= SND_MIXER_SCTCAP_JOINTLY_VOLUME;
+                               caps |= SND_MIXER_SCTCAP_JOIN_VOLUME;
                        if (present & MIXER_PRESENT_SINGLE_SWITCH) {
                                if (global_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_MUTE;
                        }
                        if (present & MIXER_PRESENT_GLOBAL_SWITCH) {
                                if (gswitch_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_MUTE;
                        }
                        if (present & MIXER_PRESENT_PLAYBACK_SWITCH) {
                                if (pswitch_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_MUTE;
                        }
                        if (present & (MIXER_PRESENT_GLOBAL_ROUTE | MIXER_PRESENT_PLAYBACK_ROUTE))
-                               caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
+                               caps &= ~SND_MIXER_SCTCAP_JOIN_MUTE;
                        if (present & MIXER_PRESENT_CAPTURE_SWITCH) {
                                if (cswitch_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_CAPTURE;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_CAPTURE;
                        }
                        if (present & MIXER_PRESENT_CAPTURE_ROUTE)
-                               caps &= ~SND_MIXER_SCTCAP_JOINTLY_CAPTURE;
+                               caps &= ~SND_MIXER_SCTCAP_JOIN_CAPTURE;
                        if (present & MIXER_PRESENT_SINGLE_VOLUME) {
                                if (global_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_VOLUME;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_VOLUME;
                        }
                        if (present & MIXER_PRESENT_GLOBAL_VOLUME) {
                                if (gvolume_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_VOLUME;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_VOLUME;
                        }
                        if (present & MIXER_PRESENT_PLAYBACK_VOLUME) {
                                if (pvolume_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_VOLUME;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_VOLUME;
                        }
                        if (present & MIXER_PRESENT_CAPTURE_VOLUME) {
                                if (cvolume_info.count > 1)
-                                       caps &= ~SND_MIXER_SCTCAP_JOINTLY_VOLUME;
+                                       caps &= ~SND_MIXER_SCTCAP_JOIN_VOLUME;
                        }
                }
                if (present == 0)
                        break;
                sname1 = get_short_name(sname);
-               simple = build_input_scontrol(handle, sname1, index);
+               simple = build_elem_scontrol(mixer, sname1, index);
                if (simple == NULL) {
-                       snd_ctl_hbag_destroy(&bag, NULL);
+                       snd_hctl_bag_destroy(&bag);
                        return -ENOMEM;
                }
                simple->present = present;
@@ -722,15 +776,37 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                simple->voices = voices;
                simple->min = min;
                simple->max = max;
+               bag.private = simple;
                simple->helems = bag;
                // fprintf(stderr, "sname = '%s', index = %i, present = 0x%x, voices = %i\n", sname, index, present, voices);
        };
        return 0;
 }
 
-int snd_mixer_simple_build(snd_mixer_t *handle)
+int mixer_simple_ctl_callback(snd_ctl_t *ctl,
+                             snd_ctl_event_type_t event,
+                             snd_hctl_elem_t *elem ATTRIBUTE_UNUSED)
+{
+       snd_mixer_t *mixer = snd_hctl_get_callback_private(ctl);
+       int err;
+       switch (event) {
+       case SND_CTL_EVENT_REBUILD:
+               snd_mixer_free(mixer);
+               err = snd_mixer_simple_build(mixer);
+               if (err < 0)
+                       return err;
+               return mixer->callback(mixer, event, NULL);
+       case SND_CTL_EVENT_ADD:
+               /* TODO */
+               return 0;
+       default:
+               assert(0);
+       }
+}
+
+int snd_mixer_simple_build(snd_mixer_t *mixer)
 {
-       static char *inputs[] = {
+       static char *elems[] = {
                "Master",
                "Master Mono",
                "Master Digital",
@@ -759,27 +835,154 @@ int snd_mixer_simple_build(snd_mixer_t *handle)
                "Capture Boost",
                NULL
        };
-       char **input = inputs;
+       snd_ctl_t *ctl = mixer->ctl;
+       char **elem = elems;
        int err;
 
-       if ((err = snd_ctl_hbuild(handle->ctl_handle, snd_ctl_hsort)) < 0)
+       if ((err = snd_hctl_build(ctl)) < 0)
                return err;
-       while (*input) {
-               if ((err = build_input(handle, *input)) < 0) {
-                       snd_mixer_simple_destroy(handle);
+       while (*elem) {
+               if ((err = build_elem(mixer, *elem)) < 0)
                        return err;
-               }
-               input++;
+               elem++;
        }
-       handle->simple_valid = 1;
+       snd_hctl_set_callback(ctl, mixer_simple_ctl_callback);
+       snd_hctl_set_callback_private(ctl, mixer);
        return 0;
 }
 
-int snd_mixer_simple_destroy(snd_mixer_t *handle)
+snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer,
+                                                  const snd_mixer_selem_id_t *id)
 {
-       while (!list_empty(&handle->simples))
-               simple_remove(handle, list_entry(handle->simples.next, mixer_simple_t, list));
-       handle->simple_valid = 0;
-       snd_ctl_hfree(handle->ctl_handle);
-       return 0;
+       struct list_head *list;
+       list_for_each(list, &mixer->elems) {
+               snd_mixer_elem_t *e;
+               selem_t *s;
+               e = list_entry(list, snd_mixer_elem_t, list);
+               if (e->type != SND_MIXER_ELEM_SIMPLE)
+                       continue;
+               s = e->private;
+               if (!strcmp(s->id.name, id->name) && s->id.index == id->index)
+                       return e;
+       }
+       return NULL;
+}
+
+void snd_mixer_selem_get_id(snd_mixer_elem_t *element,
+                           snd_mixer_selem_id_t *id)
+{
+       selem_t *s;
+       assert(element && id);
+       assert(element->type == SND_MIXER_ELEM_SIMPLE);
+       s = element->private;
+       *id = s->id;
+}
+
+int snd_mixer_selem_read(snd_mixer_elem_t *element,
+                        snd_mixer_selem_t *value)
+{
+       selem_t *s;
+       assert(element && value);
+       assert(element->type == SND_MIXER_ELEM_SIMPLE);
+       s = element->private;
+       if (s->read == NULL)
+               return -EIO;
+       return s->read(element, value);
+}
+
+int snd_mixer_selem_write(snd_mixer_elem_t *element,
+                         const snd_mixer_selem_t *value)
+{
+       selem_t *s;
+       assert(element && value);
+       assert(element->type == SND_MIXER_ELEM_SIMPLE);
+       s = element->private;
+       if (s->write == NULL)
+               return -EIO;
+       return s->write(element, value);
+}
+
+int snd_mixer_selem_is_mono(const snd_mixer_selem_t *obj)
+{
+       assert(obj);
+       return obj->channels == 1 << SND_MIXER_CHN_MONO;
+}
+
+long snd_mixer_selem_get_volume(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel)
+{
+       assert(obj);
+       return obj->volume[channel];
+}
+
+void snd_mixer_selem_set_volume(snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel, long value)
+{
+       assert(obj);
+       obj->volume[channel] = value;
+}
+
+int snd_mixer_selem_has_channel(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel)
+{
+       assert(obj);
+       assert(channel <= SND_MIXER_CHN_LAST);
+       return !!(obj->channels & (1 << channel));
+}
+
+int snd_mixer_selem_get_mute(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel)
+{
+       assert(obj);
+       assert(channel <= SND_MIXER_CHN_LAST);
+       return !!(obj->mute & (1 << channel));
+}
+
+void snd_mixer_selem_set_mute(snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel, int mute)
+{
+       assert(obj);
+       assert(channel <= SND_MIXER_CHN_LAST);
+       if (mute)
+               obj->mute |= (1 << channel);
+       else
+               obj->mute &= ~(1 << channel);
+}
+
+int snd_mixer_selem_get_capture(const snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel)
+{
+       assert(obj);
+       assert(channel <= SND_MIXER_CHN_LAST);
+       return !!(obj->capture & (1 << channel));
+}
+
+void snd_mixer_selem_set_capture(snd_mixer_selem_t *obj, snd_mixer_channel_id_t channel, int capture)
+{
+       assert(obj);
+       assert(channel <= SND_MIXER_CHN_LAST);
+       if (capture)
+               obj->capture |= (1 << channel);
+       else
+               obj->capture &= ~(1 << channel);
+}
+
+void snd_mixer_selem_set_mute_all(snd_mixer_selem_t *obj, int mute)
+{
+       assert(obj);
+       if (mute)
+               obj->mute = ~0U;
+       else
+               obj->mute = 0;
+}
+
+void snd_mixer_selem_set_capture_all(snd_mixer_selem_t *obj, int capture)
+{
+       assert(obj);
+       if (capture)
+               obj->capture = ~0U;
+       else
+               obj->capture = 0;
+}
+
+void snd_mixer_selem_set_volume_all(snd_mixer_selem_t *obj, long value)
+{
+       unsigned int c;
+       assert(obj);
+       for (c = 0; c < sizeof(obj->volume) / sizeof(obj->volume[0]); c++)
+               obj->volume[c] = value;
 }