]> git.alsa-project.org Git - alsa-lib.git/commitdiff
The highlevel control layer was rewritten and updated.
authorJaroslav Kysela <perex@perex.cz>
Fri, 11 Aug 2000 19:28:43 +0000 (19:28 +0000)
committerJaroslav Kysela <perex@perex.cz>
Fri, 11 Aug 2000 19:28:43 +0000 (19:28 +0000)
Various fixes in mixer simple layer.
Added include/list.h (from the kernel tree).

include/control.h
include/list.h [new file with mode: 0644]
src/control/control.c
src/control/control_local.h
src/control/controls.c
src/mixer/mixer.c
src/mixer/simple.c

index a7c99d4c619f6c654fa5f4dba8242865392f1736..af1eba9bb5595ae0a5ac0ec46eebf5d539677c8f 100644 (file)
@@ -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 (file)
index 0000000..320dbf1
--- /dev/null
@@ -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 */
index 9a14c3d9a3d5c5cd26e22b7122fe7094936ad93f..5c3dcfb895c83b9dd09cc4dfdc5fe9c974e894e3 100644 (file)
@@ -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;
index d6e125319e39032a17e63e048cbe074279409c19..4c2e826cf3372f4acd5b652da347f2ca3952e706 100644 (file)
  *
  */
 
+#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;
 };
index 7b53515bbc092e4d19aac6016dca5ee40381793d..9a16942311bd9ca5dd4d55dea0ae69b7332f9788 100644 (file)
 #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;
 }
index 1c9f27c1e6d491fb3997676b4743a4e19a0d31b9..4e5b4e8c876208ed44cf52d3f1f3b813678d9d77 100644 (file)
@@ -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;
        }
index f9e4bfc75c0859e78d296f70a1fc7b09340c98a6..4a7c15f8cf59d948f70b4d1e1e0fa920488252a4 100644 (file)
@@ -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;
 }