diff options
author | Jaroslav Kysela <perex@perex.cz> | 2000-08-11 19:28:43 +0000 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2000-08-11 19:28:43 +0000 |
commit | 82102903fe67d575e113af29d260f6bfb881e265 (patch) | |
tree | 76c48ad220b7bfc71902cf337b3e4edbc9b4d40b | |
parent | b99128d8de2b1a1b97285e9f9310a4f67e6037d7 (diff) | |
download | alsa-lib-82102903fe67d575e113af29d260f6bfb881e265.tar.gz |
The highlevel control layer was rewritten and updated.
Various fixes in mixer simple layer.
Added include/list.h (from the kernel tree).
-rw-r--r-- | include/control.h | 40 | ||||
-rw-r--r-- | include/list.h | 156 | ||||
-rw-r--r-- | src/control/control.c | 7 | ||||
-rw-r--r-- | src/control/control_local.h | 17 | ||||
-rw-r--r-- | src/control/controls.c | 301 | ||||
-rw-r--r-- | src/mixer/mixer.c | 2 | ||||
-rw-r--r-- | src/mixer/simple.c | 26 |
7 files changed, 371 insertions, 178 deletions
diff --git a/include/control.h b/include/control.h index a7c99d4c..af1eba9b 100644 --- a/include/control.h +++ b/include/control.h @@ -54,10 +54,25 @@ int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks); * Highlevel API for controls */ +#define LIST_HEAD_IS_DEFINED +struct list_head { + struct list_head *next, *prev; +}; + +typedef struct snd_hcontrol_list_stru snd_hcontrol_list_t; typedef struct snd_hcontrol_stru snd_hcontrol_t; +struct snd_hcontrol_list_stru { + unsigned int controls_offset; /* W: first control ID to get */ + unsigned int controls_request; /* W: count of control IDs to get */ + unsigned int controls_count; /* R: count of available (set) controls */ + unsigned int controls; /* R: count of all available controls */ + snd_control_id_t *pids; /* W: IDs */ +}; + struct snd_hcontrol_stru { snd_control_id_t id; /* must be always on top */ + struct list_head list; /* links for list of all hcontrols */ int change: 1, /* structure change */ value: 1; /* value change */ /* event callbacks */ @@ -71,18 +86,19 @@ struct snd_hcontrol_stru { snd_ctl_t *handle; /* associated handle */ }; -typedef int (snd_ctl_csort_t)(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2); -typedef int (snd_ctl_ccallback_rebuild_t)(snd_ctl_t *handle, void *private_data); -typedef int (snd_ctl_ccallback_add_t)(snd_ctl_t *handle, void *private_data, snd_hcontrol_t *hcontrol); - -int snd_ctl_cbuild(snd_ctl_t *handle, snd_ctl_csort_t *csort); -int snd_ctl_cfree(snd_ctl_t *handle); -snd_hcontrol_t *snd_ctl_cfind(snd_ctl_t *handle, snd_control_id_t *id); -int snd_ctl_csort(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2); -int snd_ctl_cresort(snd_ctl_t *handle, snd_ctl_csort_t *csort); -int snd_ctl_ccallback_rebuild(snd_ctl_t *handle, snd_ctl_ccallback_rebuild_t *callback, void *private_data); -int snd_ctl_ccallback_add(snd_ctl_t *handle, snd_ctl_ccallback_add_t *callback, void *private_data); -int snd_ctl_cevent(snd_ctl_t *handle); +typedef int (snd_ctl_hsort_t)(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2); +typedef int (snd_ctl_hcallback_rebuild_t)(snd_ctl_t *handle, void *private_data); +typedef int (snd_ctl_hcallback_add_t)(snd_ctl_t *handle, void *private_data, snd_hcontrol_t *hcontrol); + +int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t *csort); +int snd_ctl_hfree(snd_ctl_t *handle); +snd_hcontrol_t *snd_ctl_hfind(snd_ctl_t *handle, snd_control_id_t *id); +int snd_ctl_hlist(snd_ctl_t *handle, snd_hcontrol_list_t *hlist); +int snd_ctl_hsort(const snd_hcontrol_t *c1, const snd_hcontrol_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); #ifdef __cplusplus } diff --git a/include/list.h b/include/list.h new file mode 100644 index 00000000..320dbf16 --- /dev/null +++ b/include/list.h @@ -0,0 +1,156 @@ +#ifndef _LIST_H +#define _LIST_H + +/* + * This code was taken from the Linux 2.4.0 kernel. [jaroslav] + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#ifndef LIST_HEAD_IS_DEFINED +struct list_head { + struct list_head *next, *prev; +}; +#endif + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static __inline__ void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static __inline__ void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list.n + */ +static __inline__ void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static __inline__ int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static __inline__ void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#endif /* _LIST_H */ diff --git a/src/control/control.c b/src/control/control.c index 9a14c3d9..5c3dcfb8 100644 --- a/src/control/control.c +++ b/src/control/control.c @@ -64,6 +64,7 @@ int snd_ctl_open(snd_ctl_t **handle, int card) } ctl->card = card; ctl->fd = fd; + INIT_LIST_HEAD(&ctl->hlist); *handle = ctl; return 0; } @@ -101,7 +102,7 @@ int snd_ctl_clist(snd_ctl_t *handle, snd_control_list_t *list) int snd_ctl_cinfo(snd_ctl_t *handle, snd_control_info_t *info) { - assert(handle && info && info->id.name[0]); + assert(handle && info && (info->id.name[0] || info->id.numid)); if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_INFO, info) < 0) return -errno; return 0; @@ -109,7 +110,7 @@ int snd_ctl_cinfo(snd_ctl_t *handle, snd_control_info_t *info) int snd_ctl_cread(snd_ctl_t *handle, snd_control_t *control) { - assert(handle && control && control->id.name[0]); + assert(handle && control && (control->id.name[0] || control->id.numid)); if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_READ, control) < 0) return -errno; return 0; @@ -117,7 +118,7 @@ int snd_ctl_cread(snd_ctl_t *handle, snd_control_t *control) int snd_ctl_cwrite(snd_ctl_t *handle, snd_control_t *control) { - assert(handle && control && control->id.name[0]); + assert(handle && control && (control->id.name[0] || control->id.numid)); if (ioctl(handle->fd, SND_CTL_IOCTL_CONTROL_WRITE, control) < 0) return -errno; return 0; diff --git a/src/control/control_local.h b/src/control/control_local.h index d6e12531..4c2e826c 100644 --- a/src/control/control_local.h +++ b/src/control/control_local.h @@ -19,16 +19,19 @@ * */ +#include "list.h" + struct snd_ctl { int card; int fd; - int ccount; - int cerr; - void *croot; /* root of controls */ - void *croot_new; /* new croot */ - snd_ctl_csort_t *csort; - snd_ctl_ccallback_rebuild_t *callback_rebuild; + int hcount; + int herr; + 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_ccallback_add_t *callback_add; + snd_ctl_hcallback_add_t *callback_add; void *callback_add_private_data; }; diff --git a/src/control/controls.c b/src/control/controls.c index 7b53515b..9a169423 100644 --- a/src/control/controls.c +++ b/src/control/controls.c @@ -32,21 +32,20 @@ #include "asoundlib.h" #include "control_local.h" -static void snd_ctl_cfree1(snd_hcontrol_t *hcontrol); +static void snd_ctl_hfree1(snd_hcontrol_t *hcontrol); -int snd_ctl_cbuild(snd_ctl_t *handle, snd_ctl_csort_t *csort) +int snd_ctl_hbuild(snd_ctl_t *handle, snd_ctl_hsort_t *hsort) { snd_control_list_t list; snd_hcontrol_t *hcontrol, *prev; int err; unsigned int idx; - printf("cbuild - start\n"); assert(handle != NULL); - if ((err = snd_ctl_cfree(handle)) < 0) + if ((err = snd_ctl_hfree(handle)) < 0) return err; - if (csort == NULL) - csort = snd_ctl_csort; + if (hsort == NULL) + hsort = snd_ctl_hsort; memset(&list, 0, sizeof(list)); do { if (list.pids != NULL) @@ -67,132 +66,171 @@ int snd_ctl_cbuild(snd_ctl_t *handle, snd_ctl_csort_t *csort) } while (list.controls != list.controls_count); for (idx = 0, prev = NULL; idx < list.controls_count; idx++) { hcontrol = (snd_hcontrol_t *)calloc(1, sizeof(snd_hcontrol_t)); - if (hcontrol == NULL) { - snd_ctl_cfree(handle); - free(list.pids); - return -ENOMEM; - } + if (hcontrol == NULL) + goto __nomem; hcontrol->id = list.pids[idx]; hcontrol->handle = handle; - if (tsearch(hcontrol, &handle->croot, (__compar_fn_t)csort) == NULL) { - tdestroy(&handle->croot, (__free_fn_t)snd_ctl_cfree1); - handle->croot = NULL; + if (tsearch(hcontrol, &handle->hroot, (__compar_fn_t)hsort) == NULL) { + __nomem: + if (handle->hroot != NULL) { + tdestroy(handle->hroot, (__free_fn_t)snd_ctl_hfree1); + handle->hroot = NULL; + } + handle->hroot = NULL; + if (hcontrol != NULL) + free(hcontrol); + free(list.pids); + return -ENOMEM; } - handle->ccount++; + list_add_tail(&hcontrol->list, &handle->hlist); + handle->hcount++; } if (list.pids != NULL) free(list.pids); - handle->csort = csort; + if ((err = snd_ctl_hresort(handle, hsort)) < 0) { + tdestroy(handle->hroot, (__free_fn_t)snd_ctl_hfree1); + handle->hroot = NULL; + } return 0; } -static void snd_ctl_cfree1(snd_hcontrol_t *hcontrol) +static void snd_ctl_hfree1(snd_hcontrol_t *hcontrol) { snd_ctl_t *handle; assert(hcontrol != NULL); handle = hcontrol->handle; assert(handle != NULL); - assert(handle->ccount > 0); + assert(handle->hcount > 0); if (hcontrol->event_remove) hcontrol->event_remove(handle, hcontrol); if (hcontrol->private_free) hcontrol->private_free(hcontrol->private_data); + list_del(&hcontrol->list); free(hcontrol); - handle->ccount--; + handle->hcount--; } -int snd_ctl_cfree(snd_ctl_t *handle) +int snd_ctl_hfree(snd_ctl_t *handle) { - handle->csort = NULL; - handle->cerr = 0; - if (handle->croot != NULL) { - tdestroy(handle->croot, (__free_fn_t)snd_ctl_cfree1); - handle->croot = NULL; + handle->hsort = NULL; + handle->herr = 0; + if (handle->hroot != NULL) { + tdestroy(handle->hroot, (__free_fn_t)snd_ctl_hfree1); + handle->hroot = NULL; } - assert(handle->ccount == 0); + assert(list_empty(&handle->hlist)); + assert(handle->hcount == 0); return 0; } -int snd_ctl_csort(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2) +int snd_ctl_hsort(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2) { int res; - res = strcmp(c1->id.name, c2->id.name); - if (res == 0) { - if (c1->id.index < c2->id.index) - return -1; - if (c1->id.index > c2->id.index) - return 1; - return 0; - } - return res; -} - -static void snd_ctl_cresort_action(snd_hcontrol_t *hcontrol, VISIT which, int level) -{ - snd_ctl_t *handle; - - level = 0; /* to keep GCC happy */ - assert(hcontrol != NULL); - handle = hcontrol->handle; - assert(handle != NULL); - if (handle->cerr < 0) - return; - switch (which) { - case preorder: break; - case postorder: break; - case endorder: - case leaf: - if (tsearch(hcontrol, &handle->croot, (__compar_fn_t)handle->csort) == NULL) - handle->cerr = -ENOMEM; - break; - } + if (c1->id.iface < c2->id.iface) + return -1; + if (c1->id.iface > c2->id.iface) + return 1; + if ((res = strcmp(c1->id.name, c2->id.name)) != 0) + return res; + if (c1->id.index < c2->id.index) + return -1; + if (c1->id.index > c2->id.index) + return 1; + return 0; } -static void snd_ctl_cresort_free(snd_hcontrol_t *hcontrol) +static void snd_ctl_hresort_free(snd_hcontrol_t *hcontrol ATTRIBUTE_UNUSED) { - hcontrol = NULL; /* to keep GCC happy */ /* nothing */ } -int snd_ctl_cresort(snd_ctl_t *handle, snd_ctl_csort_t *csort) +int snd_ctl_hresort(snd_ctl_t *handle, snd_ctl_hsort_t *hsort) { - int result; - snd_ctl_csort_t *csort_old; + struct list_head *list; + snd_hcontrol_t *hcontrol; + snd_control_id_t *ids, *pids; + int idx; - assert(handle != NULL && csort != NULL); - if (handle->ccount == 0) + assert(handle != NULL && hsort != NULL); + if (handle->hcount == 0) return 0; - if (handle->cerr < 0) - return handle->cerr; - assert(handle->croot_new == NULL); - csort_old = handle->csort; - handle->csort = csort; - twalk(handle->croot, (__action_fn_t)snd_ctl_cresort_action); - if (handle->cerr < 0) { - result = handle->cerr; - handle->cerr = 0; - handle->csort = csort_old; - tdestroy(handle->croot_new, (__free_fn_t)snd_ctl_cresort_free); - handle->croot_new = NULL; - return result; + if (handle->herr < 0) + return handle->herr; + assert(handle->hroot_new == NULL); + ids = pids = (snd_control_id_t *)malloc(sizeof(snd_control_id_t) * handle->hcount); + if (ids == NULL) + return -ENOMEM; + /* first step - update search engine */ + list_for_each(list, &handle->hlist) { + hcontrol = list_entry(list, snd_hcontrol_t, list); + *pids++ = hcontrol->id; + if (tsearch(hcontrol, &handle->hroot_new, (__compar_fn_t)hsort) == NULL) { + if (handle->hroot_new != NULL) + tdestroy(handle->hroot_new, (__free_fn_t)snd_ctl_hresort_free); + handle->hroot_new = NULL; + free(ids); + return -ENOMEM; + } } - tdestroy(handle->croot, (__free_fn_t)snd_ctl_cresort_free); - handle->croot = handle->croot_new; - handle->croot_new = NULL; + if (handle->hroot != NULL) + tdestroy(handle->hroot, (__free_fn_t)snd_ctl_hresort_free); + handle->hsort = hsort; + handle->hroot = handle->hroot_new; + handle->hroot_new = NULL; + /* second step - perform qsort and save results */ + qsort(ids, handle->hcount, sizeof(snd_control_id_t), (int (*)(const void *, const void *))hsort); + INIT_LIST_HEAD(&handle->hlist); + for (idx = 0; idx < handle->hcount; idx++) { + hcontrol = snd_ctl_hfind(handle, ids + idx); + list_add_tail(&hcontrol->list, &handle->hlist); + } + free(ids); return 0; } -snd_hcontrol_t *snd_ctl_cfind(snd_ctl_t *handle, snd_control_id_t *id) +snd_hcontrol_t *snd_ctl_hfind(snd_ctl_t *handle, snd_control_id_t *id) { + void *res; + assert(handle != NULL); - if (handle->croot == NULL) + if (handle->hroot == NULL) return NULL; - return (snd_hcontrol_t *)tfind(id, &handle->croot, (__compar_fn_t)handle->csort); + res = tfind(id, &handle->hroot, (__compar_fn_t)handle->hsort); + return res == NULL ? NULL : *(snd_hcontrol_t **)res; +} + +int snd_ctl_hlist(snd_ctl_t *handle, snd_hcontrol_list_t *hlist) +{ + struct list_head *list; + snd_hcontrol_t *hcontrol; + unsigned int idx; + + assert(hlist != NULL); + if (hlist->controls_offset >= (unsigned int)handle->hcount) + return -EINVAL; + hlist->controls_count = 0; + hlist->controls = handle->hcount; + if (hlist->controls_request > 0) { + if (hlist->pids == NULL) + return -EINVAL; + idx = 0; + list_for_each(list, &handle->hlist) { + hcontrol = list_entry(list, snd_hcontrol_t, list); + if (idx >= hlist->controls_offset + hlist->controls_request) + break; + if (idx >= hlist->controls_offset) { + hlist->pids[idx] = hcontrol->id; + hlist->controls_count++; + } + idx++; + } + } + return 0; } -int snd_ctl_ccallback_rebuild(snd_ctl_t *handle, snd_ctl_ccallback_rebuild_t *callback, void *private_data) +int snd_ctl_hcallback_rebuild(snd_ctl_t *handle, snd_ctl_hcallback_rebuild_t *callback, void *private_data) { assert(handle != NULL); handle->callback_rebuild = callback; @@ -200,7 +238,7 @@ int snd_ctl_ccallback_rebuild(snd_ctl_t *handle, snd_ctl_ccallback_rebuild_t *ca return 0; } -int snd_ctl_ccallback_add(snd_ctl_t *handle, snd_ctl_ccallback_add_t *callback, void *private_data) +int snd_ctl_hcallback_add(snd_ctl_t *handle, snd_ctl_hcallback_add_t *callback, void *private_data) { assert(handle != NULL); handle->callback_add = callback; @@ -208,110 +246,85 @@ int snd_ctl_ccallback_add(snd_ctl_t *handle, snd_ctl_ccallback_add_t *callback, return 0; } -static void callback_rebuild(snd_ctl_t *handle, void *private_data) +static void callback_rebuild(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED) { - private_data = NULL; /* to keep GCC happy */ - handle->cerr = snd_ctl_cbuild(handle, handle->csort); - if (handle->cerr >= 0 && handle->callback_rebuild) + handle->herr = snd_ctl_hbuild(handle, handle->hsort); + if (handle->herr >= 0 && handle->callback_rebuild) handle->callback_rebuild(handle, handle->callback_rebuild_private_data); } -static void callback_change(snd_ctl_t *handle, void *private_data, snd_control_id_t *id) +static void callback_change(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_control_id_t *id) { snd_hcontrol_t *hcontrol; - private_data = NULL; /* to keep GCC happy */ - if (handle->cerr < 0) + if (handle->herr < 0) return; - hcontrol = snd_ctl_cfind(handle, id); + hcontrol = snd_ctl_hfind(handle, id); if (hcontrol == NULL) { - handle->cerr = -ENOENT; + handle->herr = -ENOENT; return; } hcontrol->change = 1; } -static void callback_value(snd_ctl_t *handle, void *private_data, snd_control_id_t *id) +static void callback_value(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_control_id_t *id) { snd_hcontrol_t *hcontrol; - private_data = NULL; /* to keep GCC happy */ - if (handle->cerr < 0) + if (handle->herr < 0) return; - hcontrol = snd_ctl_cfind(handle, id); + hcontrol = snd_ctl_hfind(handle, id); if (hcontrol == NULL) { - handle->cerr = -ENOENT; + handle->herr = -ENOENT; return; } hcontrol->value = 1; } -static void callback_add(snd_ctl_t *handle, void *private_data, snd_control_id_t *id) +static void callback_add(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_control_id_t *id) { snd_hcontrol_t *hcontrol, *icontrol; - private_data = NULL; /* to keep GCC happy */ - if (handle->cerr < 0) + if (handle->herr < 0) return; hcontrol = (snd_hcontrol_t *)calloc(1, sizeof(snd_hcontrol_t)); if (hcontrol == NULL) { - handle->cerr = -ENOMEM; + handle->herr = -ENOMEM; return; } hcontrol->id = *id; hcontrol->handle = handle; - icontrol = tsearch(hcontrol, &handle->croot, (__compar_fn_t)handle->csort); + icontrol = tsearch(hcontrol, &handle->hroot, (__compar_fn_t)handle->hsort); if (icontrol == NULL) { free(hcontrol); - handle->cerr = -ENOMEM; + handle->herr = -ENOMEM; return; } if (icontrol != hcontrol) { /* double hit */ free(hcontrol); return; } + list_add_tail(&hcontrol->list, &handle->hlist); if (handle->callback_add) handle->callback_add(handle, handle->callback_add_private_data, hcontrol); } -static void callback_remove(snd_ctl_t *handle, void *private_data, snd_control_id_t *id) +static void callback_remove(snd_ctl_t *handle, void *private_data ATTRIBUTE_UNUSED, snd_control_id_t *id) { snd_hcontrol_t *hcontrol; - private_data = NULL; /* to keep GCC happy */ - if (handle->cerr < 0) + if (handle->herr < 0) return; - hcontrol = snd_ctl_cfind(handle, id); + hcontrol = snd_ctl_hfind(handle, id); if (hcontrol == NULL) { - handle->cerr = -ENOENT; + handle->herr = -ENOENT; return; } - if (tdelete(hcontrol, &handle->croot, (__compar_fn_t)handle->csort) != NULL) - snd_ctl_cfree1(hcontrol); + if (tdelete(hcontrol, &handle->hroot, (__compar_fn_t)handle->hsort) != NULL) + snd_ctl_hfree1(hcontrol); } -static void snd_ctl_cevent_walk1(snd_hcontrol_t *hcontrol, VISIT which, int level) -{ - level = 0; /* to keep GCC happy */ - assert(hcontrol != NULL); - switch (which) { - case preorder: break; - case postorder: break; - case endorder: - case leaf: - if (hcontrol->change && hcontrol->event_change) { - hcontrol->event_change(hcontrol->handle, hcontrol); - hcontrol->change = 0; - } - if (hcontrol->value && hcontrol->event_value) { - hcontrol->event_value(hcontrol->handle, hcontrol); - hcontrol->value = 0; - } - break; - } -} - -int snd_ctl_cevent(snd_ctl_t *handle) +int snd_ctl_hevent(snd_ctl_t *handle) { static snd_ctl_callbacks_t callbacks = { rebuild: callback_rebuild, @@ -322,15 +335,27 @@ int snd_ctl_cevent(snd_ctl_t *handle) private_data: NULL, reserved: { NULL, } }; + struct list_head *list; + snd_hcontrol_t *hcontrol; int res; assert(handle != NULL); - handle->cerr = 0; + handle->herr = 0; res = snd_ctl_read(handle, &callbacks); if (res < 0) return res; - if (handle->cerr < 0) - return handle->cerr; - twalk(handle->croot, (__action_fn_t)snd_ctl_cevent_walk1); + if (handle->herr < 0) + return handle->herr; + list_for_each(list, &handle->hlist) { + hcontrol = list_entry(list, snd_hcontrol_t, list); + if (hcontrol->change && hcontrol->event_change) { + hcontrol->event_change(hcontrol->handle, hcontrol); + hcontrol->change = 0; + } + if (hcontrol->value && hcontrol->event_value) { + hcontrol->event_value(hcontrol->handle, hcontrol); + hcontrol->value = 0; + } + } return res; } diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index 1c9f27c1..4e5b4e8c 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -214,7 +214,7 @@ int snd_mixer_simple_read(snd_mixer_t *handle, snd_mixer_simple_callbacks_t *cal snd_mixer_simple_build(handle); handle->callbacks = callbacks; handle->simple_changes = 0; - if ((err = snd_ctl_cevent(handle->ctl_handle)) <= 0) { + if ((err = snd_ctl_hevent(handle->ctl_handle)) <= 0) { handle->callbacks = NULL; return err; } diff --git a/src/mixer/simple.c b/src/mixer/simple.c index f9e4bfc7..4a7c15f8 100644 --- a/src/mixer/simple.c +++ b/src/mixer/simple.c @@ -38,9 +38,8 @@ static int test_mixer_id(snd_mixer_t *handle, const char *name, int index) id.iface = SND_CONTROL_IFACE_MIXER; strcpy(id.name, name); id.index = index; - printf("look\n"); - hcontrol = snd_ctl_cfind(handle->ctl_handle, &id); - fprintf(stderr, "Looking for control: '%s', %i (0x%lx)\n", name, index, (long)hcontrol); + hcontrol = snd_ctl_hfind(handle->ctl_handle, &id); + // fprintf(stderr, "Looking for control: '%s', %i (0x%lx)\n", name, index, (long)hcontrol); return hcontrol != NULL; } @@ -339,19 +338,15 @@ static int build_input(snd_mixer_t *handle, const char *sname) memset(&gvolume_info, 0, sizeof(gvolume_info)); memset(&pvolume_info, 0, sizeof(pvolume_info)); memset(&cvolume_info, 0, sizeof(cvolume_info)); - printf("b (1)\n"); - do { + while (1) { index++; voices = 0; present = caps = capture_item = 0; min = max = 0; sprintf(str, "%s Switch", sname); - printf("b (2)\n"); if (test_mixer_id(handle, str, index)) { - printf("b (3)\n"); if ((err = get_mixer_info(handle, str, index, &gswitch_info)) < 0) return err; - printf("b (4)\n"); if (gswitch_info.type == SND_CONTROL_TYPE_BOOLEAN) { if (voices < gswitch_info.values_count) voices = gswitch_info.values_count; @@ -359,7 +354,6 @@ static int build_input(snd_mixer_t *handle, const char *sname) present |= MIXER_PRESENT_GLOBAL_SWITCH; } } - printf("b (3)\n"); sprintf(str, "%s Volume", sname); if (test_mixer_id(handle, str, index)) { if ((err = get_mixer_info(handle, str, index, &gvolume_info)) < 0) @@ -483,7 +477,8 @@ static int build_input(snd_mixer_t *handle, const char *sname) caps &= ~SND_MIXER_SCTCAP_JOINTLY_VOLUME; } } - printf("b (4)\n"); + if (present == 0) + break; simple = build_input_scontrol(handle, sname, index); if (simple == NULL) return -ENOMEM; @@ -500,8 +495,8 @@ static int build_input(snd_mixer_t *handle, const char *sname) simple->voices = voices; simple->min = min; simple->max = max; - fprintf(stderr, "sname = '%s', index = %i, present = 0x%x, voices = %i\n", sname, index, present, voices); - } while (present != 0); + // fprintf(stderr, "sname = '%s', index = %i, present = 0x%x, voices = %i\n", sname, index, present, voices); + }; return 0; } @@ -527,11 +522,9 @@ int snd_mixer_simple_build(snd_mixer_t *handle) char **input = inputs; int err; - printf("simple build - start\n"); - if ((err = snd_ctl_cbuild(handle->ctl_handle, snd_ctl_csort)) < 0) + if ((err = snd_ctl_hbuild(handle->ctl_handle, snd_ctl_hsort)) < 0) return err; while (*input) { - printf("simple build - input '%s'\n", *input); if ((err = build_input(handle, *input)) < 0) { snd_mixer_simple_destroy(handle); return err; @@ -539,7 +532,6 @@ int snd_mixer_simple_build(snd_mixer_t *handle) input++; } handle->simple_valid = 1; - printf("simple build - end\n"); return 0; } @@ -548,6 +540,6 @@ int snd_mixer_simple_destroy(snd_mixer_t *handle) while (handle->simple_first) simple_remove(handle, handle->simple_first); handle->simple_valid = 0; - snd_ctl_cfree(handle->ctl_handle); + snd_ctl_hfree(handle->ctl_handle); return 0; } |