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;
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);
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);
# 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
#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;
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
#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)
#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" {
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
}
* 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
}
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; })
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);
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
#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
****************************************************************************/
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
}
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
#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
}
--- /dev/null
+#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
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:
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
#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)
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);
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)
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)
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),
TYPE(IEC958),
};
-const char *snd_ctl_element_iface_names[] = {
+const char *snd_ctl_elem_iface_names[] = {
IFACE(CARD),
IFACE(HWDEP),
IFACE(MIXER),
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)
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;
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;
#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)
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;
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;
}
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,
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);
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);
+
#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;
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);
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;
}
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;
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;
}
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);
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,
#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;
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;
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];
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;
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;
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);
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 */
}
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);
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)
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);
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)
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;
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);
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) {
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;
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;
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;
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;
reserved: { NULL, }
};
struct list_head *list;
- snd_hctl_element_t *helem;
+ snd_hctl_elem_t *helem;
int res;
assert(handle != NULL);
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;
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) {
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;
--- /dev/null
+/*
+ * 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);
+}
+
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
/*
* 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;
}
/*
* 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);
}
+
/*
* 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);
--- /dev/null
+/*
+ * 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);
+}
+
/*
* 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;
{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)
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)
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)
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])
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])
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;
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)
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));
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)
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)
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)
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;
}
}
}
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;
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",
"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;
}