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