diff options
-rw-r--r-- | aserver/aserver.c | 7 | ||||
-rw-r--r-- | include/aserver.h | 3 | ||||
-rw-r--r-- | include/control.h | 25 | ||||
-rw-r--r-- | include/control_m4.h | 14 | ||||
-rw-r--r-- | include/mixer.h | 4 | ||||
-rw-r--r-- | src/control/control.c | 71 | ||||
-rw-r--r-- | src/control/control_hw.c | 18 | ||||
-rw-r--r-- | src/control/control_local.h | 3 | ||||
-rw-r--r-- | src/control/control_m4.c | 49 | ||||
-rw-r--r-- | src/control/control_shm.c | 20 | ||||
-rw-r--r-- | src/control/hcontrol.c | 109 | ||||
-rw-r--r-- | src/mixer/mixer.c | 72 | ||||
-rw-r--r-- | src/mixer/mixer_local.h | 5 | ||||
-rw-r--r-- | src/mixer/simple.c | 30 |
14 files changed, 225 insertions, 205 deletions
diff --git a/aserver/aserver.c b/aserver/aserver.c index dcf8d0a9..c3f209fa 100644 --- a/aserver/aserver.c +++ b/aserver/aserver.c @@ -572,8 +572,11 @@ int ctl_shm_cmd(client_t *client) 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); + case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: + ctrl->result = snd_ctl_subscribe_events(ctl, ctrl->u.subscribe_events); + break; + case SNDRV_CTL_IOCTL_CARD_INFO: + ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.card_info); break; case SNDRV_CTL_IOCTL_ELEM_LIST: { diff --git a/include/aserver.h b/include/aserver.h index 69076a61..cc93d4b1 100644 --- a/include/aserver.h +++ b/include/aserver.h @@ -95,7 +95,8 @@ typedef struct { pid_t pid; } async; int device; - snd_ctl_card_info_t hw_info; + int subscribe_events; + snd_ctl_card_info_t card_info; snd_ctl_elem_list_t element_list; snd_ctl_elem_info_t element_info; snd_ctl_elem_value_t element_read; diff --git a/include/control.h b/include/control.h index 586db0d1..45393f9a 100644 --- a/include/control.h +++ b/include/control.h @@ -112,13 +112,14 @@ typedef enum sndrv_ctl_event_type snd_ctl_event_type_t; #define SND_CTL_ELEM_IFACE_SEQUENCER ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_SEQUENCER) #define SND_CTL_ELEM_IFACE_LAST ((snd_ctl_elem_iface_t) SNDRV_CTL_ELEM_IFACE_LAST) -#define SND_CTL_EVENT_REBUILD ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_REBUILD) -#define SND_CTL_EVENT_VALUE ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_VALUE) -#define SND_CTL_EVENT_INFO ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_INFO) -#define SND_CTL_EVENT_ADD ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_ADD) -#define SND_CTL_EVENT_REMOVE ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_REMOVE) +#define SND_CTL_EVENT_ELEM ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_ELEM) #define SND_CTL_EVENT_LAST ((snd_ctl_event_type_t) SNDRV_CTL_EVENT_LAST) +#define SND_CTL_EVENT_MASK_ADD SNDRV_CTL_EVENT_MASK_ADD +#define SND_CTL_EVENT_MASK_INFO SNDRV_CTL_EVENT_MASK_INFO +#define SND_CTL_EVENT_MASK_VALUE SNDRV_CTL_EVENT_MASK_VALUE +#define SND_CTL_EVENT_MASK_REMOVE SNDRV_CTL_EVENT_MASK_REMOVE + enum _snd_ctl_type { SND_CTL_TYPE_HW, SND_CTL_TYPE_SHM, @@ -160,6 +161,7 @@ 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_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int space); +int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe); 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); @@ -184,6 +186,15 @@ 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); +unsigned int snd_ctl_event_elem_get_mask(const snd_ctl_event_t *obj); +unsigned int snd_ctl_event_elem_get_numid(const snd_ctl_event_t *obj); +void snd_ctl_event_elem_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr); +snd_ctl_elem_iface_t snd_ctl_event_elem_get_interface(const snd_ctl_event_t *obj); +unsigned int snd_ctl_event_elem_get_device(const snd_ctl_event_t *obj); +unsigned int snd_ctl_event_elem_get_subdevice(const snd_ctl_event_t *obj); +const char *snd_ctl_event_elem_get_name(const snd_ctl_event_t *obj); +unsigned int snd_ctl_event_elem_get_index(const snd_ctl_event_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); @@ -206,10 +217,10 @@ extern "C" { 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_hctl_t *hctl, - snd_ctl_event_type_t event, + unsigned int mask, snd_hctl_elem_t *elem); typedef int (*snd_hctl_elem_callback_t)(snd_hctl_elem_t *elem, - snd_ctl_event_type_t event); + unsigned int mask); int snd_hctl_open(snd_hctl_t **hctl, const char *name); int snd_hctl_close(snd_hctl_t *hctl); diff --git a/include/control_m4.h b/include/control_m4.h index 0a911bf4..11cf6eb3 100644 --- a/include/control_m4.h +++ b/include/control_m4.h @@ -62,20 +62,6 @@ void snd_ctl_event_copy(snd_ctl_event_t *dst, const snd_ctl_event_t *src); 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_elem_id_t *ptr); - -snd_ctl_elem_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj); - -unsigned int snd_ctl_event_get_device(const snd_ctl_event_t *obj); - -unsigned int snd_ctl_event_get_subdevice(const snd_ctl_event_t *obj); - -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_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); diff --git a/include/mixer.h b/include/mixer.h index 0ce702d6..b65ed54a 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -10,10 +10,10 @@ typedef struct _snd_mixer_class snd_mixer_class_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, + unsigned int mask, snd_mixer_elem_t *elem); typedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem, - snd_ctl_event_type_t event); + unsigned int mask); typedef int (*snd_mixer_compare_t)(const snd_mixer_elem_t *e1, const snd_mixer_elem_t *e2); diff --git a/src/control/control.c b/src/control/control.c index fa62bb06..05e0fdfc 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -84,10 +84,16 @@ int snd_ctl_poll_descriptors(snd_ctl_t *ctl, struct pollfd *pfds, unsigned int s return 1; } +int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe) +{ + assert(ctl); + return ctl->ops->subscribe_events(ctl, subscribe); +} + int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) { assert(ctl && info); - return ctl->ops->hw_info(ctl, info); + return ctl->ops->card_info(ctl, info); } int snd_ctl_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) @@ -280,11 +286,7 @@ const char *snd_ctl_elem_iface_names[] = { }; const char *snd_ctl_event_type_names[] = { - EVENT(REBUILD), - EVENT(VALUE), - EVENT(INFO), - EVENT(ADD), - EVENT(REMOVE), + EVENT(ELEM), }; const char *snd_ctl_elem_type_name(snd_ctl_elem_type_t type) @@ -323,3 +325,60 @@ void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj) free(obj->pids); obj->pids = NULL; } + +unsigned int snd_ctl_event_elem_get_mask(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return obj->data.elem.mask; +} + +unsigned int snd_ctl_event_elem_get_numid(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return obj->data.elem.id.numid; +} + +void snd_ctl_event_elem_get_id(const snd_ctl_event_t *obj, snd_ctl_elem_id_t *ptr) +{ + assert(obj && ptr); + assert(obj->type == SND_CTL_EVENT_ELEM); + *ptr = obj->data.elem.id; +} + +snd_ctl_elem_iface_t snd_ctl_event_elem_get_interface(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return snd_int_to_enum(obj->data.elem.id.iface); +} + +unsigned int snd_ctl_event_elem_get_device(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return obj->data.elem.id.device; +} + +unsigned int snd_ctl_event_elem_get_subdevice(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return obj->data.elem.id.subdevice; +} + +const char *snd_ctl_event_elem_get_name(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return obj->data.elem.id.name; +} + +unsigned int snd_ctl_event_elem_get_index(const snd_ctl_event_t *obj) +{ + assert(obj); + assert(obj->type == SND_CTL_EVENT_ELEM); + return obj->data.elem.id.index; +} + diff --git a/src/control/control_hw.c b/src/control/control_hw.c index 09a9cdd0..92b2ab6b 100644 --- a/src/control/control_hw.c +++ b/src/control/control_hw.c @@ -111,10 +111,21 @@ static int snd_ctl_hw_poll_descriptor(snd_ctl_t *handle) return hw->fd; } -static int snd_ctl_hw_hw_info(snd_ctl_t *handle, snd_ctl_card_info_t *info) +static int snd_ctl_hw_subscribe_events(snd_ctl_t *handle, int subscribe) { snd_ctl_hw_t *hw = handle->private_data; - if (ioctl(hw->fd, SNDRV_CTL_IOCTL_INFO, info) < 0) + if (ioctl(hw->fd, SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS, &subscribe) < 0) { + SYSERR("SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS failed"); + return -errno; + } + return subscribe; +} + +static int snd_ctl_hw_card_info(snd_ctl_t *handle, snd_ctl_card_info_t *info) +{ + snd_ctl_hw_t *hw = handle->private_data; + if (ioctl(hw->fd, SNDRV_CTL_IOCTL_CARD_INFO, info) < 0) + SYSERR("SNDRV_CTL_IOCTL_CARD_INFO failed"); return -errno; return 0; } @@ -230,7 +241,8 @@ snd_ctl_ops_t snd_ctl_hw_ops = { nonblock: snd_ctl_hw_nonblock, async: snd_ctl_hw_async, poll_descriptor: snd_ctl_hw_poll_descriptor, - hw_info: snd_ctl_hw_hw_info, + subscribe_events: snd_ctl_hw_subscribe_events, + card_info: snd_ctl_hw_card_info, element_list: snd_ctl_hw_elem_list, element_info: snd_ctl_hw_elem_info, element_read: snd_ctl_hw_elem_read, diff --git a/src/control/control_local.h b/src/control/control_local.h index 0c810324..198dc7b6 100644 --- a/src/control/control_local.h +++ b/src/control/control_local.h @@ -27,7 +27,8 @@ typedef struct _snd_ctl_ops { 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 (*subscribe_events)(snd_ctl_t *handle, int subscribe); + int (*card_info)(snd_ctl_t *handle, snd_ctl_card_info_t *info); 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_value_t *control); diff --git a/src/control/control_m4.c b/src/control/control_m4.c index ad40e6cc..a0776a37 100644 --- a/src/control/control_m4.c +++ b/src/control/control_m4.c @@ -222,55 +222,6 @@ snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj) return snd_int_to_enum(obj->type); } -unsigned int snd_ctl_event_get_numid(const snd_ctl_event_t *obj) -{ - assert(obj); - assert(obj->type != SNDRV_CTL_EVENT_REBUILD); - return obj->data.id.numid; -} - -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_elem_iface_t snd_ctl_event_get_interface(const snd_ctl_event_t *obj) -{ - assert(obj); - assert(obj->type != SNDRV_CTL_EVENT_REBUILD); - return snd_int_to_enum(obj->data.id.iface); -} - -unsigned int snd_ctl_event_get_device(const snd_ctl_event_t *obj) -{ - assert(obj); - assert(obj->type != SNDRV_CTL_EVENT_REBUILD); - return obj->data.id.device; -} - -unsigned int snd_ctl_event_get_subdevice(const snd_ctl_event_t *obj) -{ - assert(obj); - assert(obj->type != SNDRV_CTL_EVENT_REBUILD); - return obj->data.id.subdevice; -} - -const char *snd_ctl_event_get_name(const snd_ctl_event_t *obj) -{ - assert(obj); - assert(obj->type != SNDRV_CTL_EVENT_REBUILD); - return obj->data.id.name; -} - -unsigned int snd_ctl_event_get_index(const snd_ctl_event_t *obj) -{ - assert(obj); - assert(obj->type != SNDRV_CTL_EVENT_REBUILD); - return obj->data.id.index; -} - size_t snd_ctl_elem_list_sizeof() { return sizeof(snd_ctl_elem_list_t); diff --git a/src/control/control_shm.c b/src/control/control_shm.c index 96fc5c97..79967d30 100644 --- a/src/control/control_shm.c +++ b/src/control/control_shm.c @@ -122,17 +122,26 @@ static int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl) return fd; } -static int snd_ctl_shm_hw_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) +static int snd_ctl_shm_subscribe_events(snd_ctl_t *ctl, int subscribe) +{ + snd_ctl_shm_t *shm = ctl->private_data; + volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; + ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR; + ctrl->u.subscribe_events = subscribe; + return snd_ctl_shm_action(ctl); +} + +static int snd_ctl_shm_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) { snd_ctl_shm_t *shm = ctl->private_data; volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; int err; -// ctrl->u.hw_info = *info; - ctrl->cmd = SNDRV_CTL_IOCTL_INFO; +// ctrl->u.card_info = *info; + ctrl->cmd = SNDRV_CTL_IOCTL_CARD_INFO; err = snd_ctl_shm_action(ctl); if (err < 0) return err; - *info = ctrl->u.hw_info; + *info = ctrl->u.card_info; return err; } @@ -334,7 +343,8 @@ snd_ctl_ops_t snd_ctl_shm_ops = { nonblock: snd_ctl_shm_nonblock, async: snd_ctl_shm_async, poll_descriptor: snd_ctl_shm_poll_descriptor, - hw_info: snd_ctl_shm_hw_info, + subscribe_events: snd_ctl_shm_subscribe_events, + card_info: snd_ctl_shm_card_info, element_list: snd_ctl_shm_elem_list, element_info: snd_ctl_shm_elem_info, element_read: snd_ctl_shm_elem_read, diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c index 713d1b9f..939169e6 100644 --- a/src/control/hcontrol.c +++ b/src/control/hcontrol.c @@ -89,42 +89,19 @@ int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned in return snd_ctl_poll_descriptors(hctl->ctl, pfds, space); } -static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, int *dir) -{ - unsigned int l, u; - int c = 0; - int idx = -1; - assert(hctl && id); - assert(hctl->compare); - l = 0; - u = hctl->count; - while (l < u) { - idx = (l + u) / 2; - c = hctl->compare((snd_hctl_elem_t *) id, hctl->pelems[idx]); - if (c < 0) - u = idx; - else if (c > 0) - l = idx + 1; - else - break; - } - *dir = c; - return idx; -} - -int snd_hctl_throw_event(snd_hctl_t *hctl, snd_ctl_event_type_t event, +int snd_hctl_throw_event(snd_hctl_t *hctl, unsigned int mask, snd_hctl_elem_t *elem) { if (hctl->callback) - return hctl->callback(hctl, event, elem); + return hctl->callback(hctl, mask, elem); return 0; } int snd_hctl_elem_throw_event(snd_hctl_elem_t *elem, - snd_ctl_event_type_t event) + unsigned int mask) { if (elem->callback) - return elem->callback(elem, event); + return elem->callback(elem, mask); return 0; } @@ -207,6 +184,32 @@ static int get_compare_weight(const char *name) return res + res1; } +static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, int *dir) +{ + unsigned int l, u; + snd_hctl_elem_t el; + int c = 0; + int idx = -1; + assert(hctl && id); + assert(hctl->compare); + el.id = *id; + el.compare_weight = get_compare_weight(id->name); + l = 0; + u = hctl->count; + while (l < u) { + idx = (l + u) / 2; + c = hctl->compare(&el, hctl->pelems[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_hctl_t *hctl, snd_hctl_elem_t *elem) { int dir; @@ -241,14 +244,14 @@ static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem) hctl->pelems[idx] = elem; } hctl->count++; - return snd_hctl_throw_event(hctl, SND_CTL_EVENT_ADD, elem); + return snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD, elem); } static void snd_hctl_elem_remove(snd_hctl_t *hctl, unsigned int idx) { snd_hctl_elem_t *elem = hctl->pelems[idx]; unsigned int m; - snd_hctl_elem_throw_event(elem, SND_CTL_EVENT_REMOVE); + snd_hctl_elem_throw_event(elem, SNDRV_CTL_EVENT_MASK_REMOVE); list_del(&elem->list); free(elem); hctl->count--; @@ -408,11 +411,12 @@ int snd_hctl_load(snd_hctl_t *hctl) hctl->compare = snd_hctl_compare_default; snd_hctl_sort(hctl); for (idx = 0; idx < hctl->count; idx++) { - int res = snd_hctl_throw_event(hctl, SND_CTL_EVENT_ADD, + int res = snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD, hctl->pelems[idx]); if (res < 0) return res; } + err = snd_ctl_subscribe_events(hctl->ctl, 1); _end: if (list.pids) free(list.pids); @@ -462,46 +466,41 @@ int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event) assert(hctl); assert(hctl->ctl); switch (event->type) { - case SND_CTL_EVENT_REMOVE: - { + case SND_CTL_EVENT_ELEM: + break; + default: + return 0; + } + if (event->data.elem.mask == SNDRV_CTL_EVENT_MASK_REMOVE) { int dir; - res = _snd_hctl_find_elem(hctl, &event->data.id, &dir); + res = _snd_hctl_find_elem(hctl, &event->data.elem.id, &dir); assert(res >= 0 && dir == 0); if (res < 0 || dir != 0) return -ENOENT; snd_hctl_elem_remove(hctl, res); - break; + return 0; } - case SND_CTL_EVENT_VALUE: - case SND_CTL_EVENT_INFO: - elem = snd_hctl_find_elem(hctl, &event->data.id); - assert(elem); - if (!elem) - return -ENOENT; - return snd_hctl_elem_throw_event(elem, event->type); - case SND_CTL_EVENT_ADD: + if (event->data.elem.mask & SNDRV_CTL_EVENT_MASK_ADD) { elem = calloc(1, sizeof(snd_hctl_elem_t)); if (elem == NULL) return -ENOMEM; - elem->id = event->data.id; + elem->id = event->data.elem.id; elem->hctl = hctl; res = snd_hctl_elem_add(hctl, elem); if (res < 0) return res; - break; - case SND_CTL_EVENT_REBUILD: - snd_hctl_free(hctl); - res = snd_hctl_load(hctl); + } + if (event->data.elem.mask & (SNDRV_CTL_EVENT_MASK_VALUE | + SNDRV_CTL_EVENT_MASK_INFO)) { + elem = snd_hctl_find_elem(hctl, &event->data.elem.id); + assert(elem); + if (!elem) + return -ENOENT; + res = snd_hctl_elem_throw_event(elem, event->data.elem.mask & + (SNDRV_CTL_EVENT_MASK_VALUE | + SNDRV_CTL_EVENT_MASK_INFO)); if (res < 0) return res; -#if 0 - /* I don't think this have to be passed to higher level */ - return hctl_event(hctl, event->type, NULL); -#endif - break; - default: - assert(0); - break; } return 0; } diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index 576d350c..65e8de0b 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -87,56 +87,44 @@ int snd_mixer_elem_empty(snd_mixer_elem_t *melem) } static int hctl_elem_event_handler(snd_hctl_elem_t *helem, - snd_ctl_event_type_t event) + unsigned int mask) { bag_t *bag = snd_hctl_elem_get_callback_private(helem); - int res = 0; - switch (event) { - case SND_CTL_EVENT_VALUE: - case SND_CTL_EVENT_INFO: - { - int err = 0; - bag_iterator_t i; - bag_for_each(i, bag) { - snd_mixer_elem_t *melem = bag_iterator_entry(i); - snd_mixer_class_t *class = melem->class; - err = class->event(class, event, helem, melem); - if (err < 0) - break; - } - break; - } - case SND_CTL_EVENT_REMOVE: - { + if (mask == SND_CTL_EVENT_MASK_REMOVE) { + int res = 0; int err; bag_iterator_t i, n; bag_for_each_safe(i, n, bag) { snd_mixer_elem_t *melem = bag_iterator_entry(i); snd_mixer_class_t *class = melem->class; - err = class->event(class, event, helem, melem); + err = class->event(class, mask, helem, melem); if (err < 0) res = err; } assert(bag_empty(bag)); bag_free(bag); - break; - + return res; } - default: - assert(0); - break; + if (mask & (SND_CTL_EVENT_MASK_VALUE | SND_CTL_EVENT_MASK_INFO)) { + int err = 0; + bag_iterator_t i; + bag_for_each(i, bag) { + snd_mixer_elem_t *melem = bag_iterator_entry(i); + snd_mixer_class_t *class = melem->class; + err = class->event(class, mask, helem, melem); + if (err < 0) + return err; + } } - return res; + return 0; } -static int hctl_event_handler(snd_hctl_t *hctl, snd_ctl_event_type_t event, +static int hctl_event_handler(snd_hctl_t *hctl, unsigned int mask, snd_hctl_elem_t *elem) { snd_mixer_t *mixer = snd_hctl_get_callback_private(hctl); int res = 0; - switch (event) { - case SND_CTL_EVENT_ADD: - { + if (mask & SND_CTL_EVENT_MASK_ADD) { struct list_head *pos; bag_t *bag; int err = bag_new(&bag); @@ -147,15 +135,10 @@ static int hctl_event_handler(snd_hctl_t *hctl, snd_ctl_event_type_t event, list_for_each(pos, &mixer->classes) { snd_mixer_class_t *c; c = list_entry(pos, snd_mixer_class_t, list); - err = c->event(c, event, elem, NULL); + err = c->event(c, mask, elem, NULL); if (err < 0) res = err; } - break; - } - default: - assert(0); - break; } return res; } @@ -203,21 +186,20 @@ int snd_mixer_detach(snd_mixer_t *mixer, const char *name) return -ENOENT; } -int snd_mixer_throw_event(snd_mixer_t *mixer, snd_ctl_event_type_t event, +int snd_mixer_throw_event(snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem) { mixer->events++; if (mixer->callback) - return mixer->callback(mixer, event, elem); + return mixer->callback(mixer, mask, elem); return 0; } -int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, - snd_ctl_event_type_t event) +int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask) { elem->class->mixer->events++; if (elem->callback) - return elem->callback(elem, event); + return elem->callback(elem, mask); return 0; } @@ -278,7 +260,7 @@ int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class) mixer->pelems[idx] = elem; } mixer->count++; - return snd_mixer_throw_event(mixer, SND_CTL_EVENT_ADD, elem); + return snd_mixer_throw_event(mixer, SND_CTL_EVENT_MASK_ADD, elem); } int snd_mixer_elem_remove(snd_mixer_elem_t *elem) @@ -296,7 +278,7 @@ int snd_mixer_elem_remove(snd_mixer_elem_t *elem) snd_hctl_elem_t *helem = bag_iterator_entry(i); snd_mixer_elem_detach(elem, helem); } - err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_REMOVE); + err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_REMOVE); list_del(&elem->list); if (elem->private_free) elem->private_free(elem); @@ -312,7 +294,7 @@ int snd_mixer_elem_remove(snd_mixer_elem_t *elem) int snd_mixer_elem_change(snd_mixer_elem_t *elem) { - return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_INFO); + return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_INFO); } @@ -330,7 +312,7 @@ int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer) slave = list_entry(pos, snd_mixer_slave_t, list); elem = snd_hctl_first_elem(slave->hctl); while (elem) { - err = class->event(class, SND_CTL_EVENT_ADD, elem, NULL); + err = class->event(class, SND_CTL_EVENT_MASK_ADD, elem, NULL); if (err < 0) return err; elem = snd_hctl_elem_next(elem); diff --git a/src/mixer/mixer_local.h b/src/mixer/mixer_local.h index 5910d0fa..ca53592c 100644 --- a/src/mixer/mixer_local.h +++ b/src/mixer/mixer_local.h @@ -49,7 +49,7 @@ typedef struct list_head *bag_iterator_t; struct _snd_mixer_class { struct list_head list; snd_mixer_t *mixer; - int (*event)(snd_mixer_class_t *class, snd_ctl_event_type_t event, + int (*event)(snd_mixer_class_t *class, unsigned int mask, snd_hctl_elem_t *helem, snd_mixer_elem_t *melem); void *private_data; void (*private_free)(snd_mixer_class_t *class); @@ -111,8 +111,7 @@ struct _snd_mixer_selem_value { int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer); int snd_mixer_add_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem); int snd_mixer_remove_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem); -int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, - snd_ctl_event_type_t event); +int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask); int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class); int snd_mixer_elem_remove(snd_mixer_elem_t *elem); int snd_mixer_elem_change(snd_mixer_elem_t *elem); diff --git a/src/mixer/simple.c b/src/mixer/simple.c index ce906fa4..077369c8 100644 --- a/src/mixer/simple.c +++ b/src/mixer/simple.c @@ -787,21 +787,27 @@ int simple_event_info(snd_mixer_elem_t *melem) return snd_mixer_elem_change(melem); } -int simple_event(snd_mixer_class_t *class, snd_ctl_event_type_t event, +int simple_event(snd_mixer_class_t *class, unsigned int mask, snd_hctl_elem_t *helem, snd_mixer_elem_t *melem) { - switch (event) { - case SND_CTL_EVENT_ADD: - return simple_event_add(class, helem); - case SND_CTL_EVENT_INFO: - return simple_event_info(melem); - case SND_CTL_EVENT_VALUE: - return snd_mixer_elem_throw_event(melem, event); - case SND_CTL_EVENT_REMOVE: + int err; + if (mask == SND_CTL_EVENT_MASK_REMOVE) return simple_event_remove(helem, melem); - default: - assert(0); - break; + if (mask & SND_CTL_EVENT_MASK_ADD) { + err = simple_event_add(class, helem); + if (err < 0) + return err; + } + if (mask & SND_CTL_EVENT_MASK_INFO) { + err = simple_event_info(melem); + if (err < 0) + return err; + } + if (mask & SND_CTL_EVENT_MASK_VALUE) { + /* FIXME */ + err = snd_mixer_elem_throw_event(melem, mask); + if (err < 0) + return err; } return 0; } |