]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Improved mixer sort/compare interface.
authorJaroslav Kysela <perex@perex.cz>
Mon, 12 Feb 2001 18:10:31 +0000 (18:10 +0000)
committerJaroslav Kysela <perex@perex.cz>
Mon, 12 Feb 2001 18:10:31 +0000 (18:10 +0000)
src/control/hcontrol.c
src/mixer/mixer.c
src/mixer/mixer_local.h

index 449382578dc4ac48bc2dba80f25093a26c79d338..b7964d875551b065118b1c250a97aa03a30aa2ea 100644 (file)
@@ -134,8 +134,10 @@ static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem)
                snd_hctl_elem_t **h;
                hctl->alloc += 32;
                h = realloc(hctl->pelems, sizeof(*h) * hctl->alloc);
-               if (!h)
+               if (!h) {
+                       hctl->alloc -= 32;
                        return -ENOMEM;
+               }
                hctl->pelems = h;
        }
        if (hctl->count == 0) {
index 5d42d75fda3c8739235a18f40cb08296ccacc56b..2c67e79b8f07ecce8a6361b2c708d089811cb627 100644 (file)
@@ -221,12 +221,61 @@ int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem,
        return 0;
 }
 
+static int _snd_mixer_find_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem, int *dir)
+{
+       unsigned int l, u;
+       int c = 0;
+       int idx = -1;
+       assert(mixer && elem);
+       assert(mixer->compare);
+       l = 0;
+       u = mixer->count;
+       while (l < u) {
+               idx = (l + u) / 2;
+               c = mixer->compare(elem, mixer->pelems[idx]);
+               if (c < 0)
+                       u = idx;
+               else if (c > 0)
+                       l = idx + 1;
+               else
+                       break;
+       }
+       *dir = c;
+       return idx;
+}
+
 int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class)
 {
+       int dir, idx;
        snd_mixer_t *mixer = class->mixer;
        elem->class = class;
 
-       list_add_tail(&elem->list, &mixer->elems);
+       if (mixer->count == mixer->alloc) {
+               snd_mixer_elem_t **m;
+               mixer->alloc += 32;
+               m = realloc(mixer->pelems, sizeof(*m) * mixer->alloc);
+               if (!m) {
+                       mixer->alloc -= 32;
+                       return -ENOMEM;
+               }
+               mixer->pelems = m;
+       }
+       if (mixer->count == 0) {
+               list_add_tail(&elem->list, &mixer->elems);
+               mixer->pelems[0] = elem;
+       } else {
+               idx = _snd_mixer_find_elem(mixer, elem, &dir);
+               assert(dir != 0);
+               if (dir > 0) {
+                       list_add(&elem->list, &mixer->pelems[idx]->list);
+               } else {
+                       list_add_tail(&elem->list, &mixer->pelems[idx]->list);
+                       idx++;
+               }
+               memmove(mixer->pelems + idx + 1,
+                       mixer->pelems + idx,
+                       mixer->count - idx);
+       }
        mixer->count++;
        return snd_mixer_throw_event(mixer, SND_CTL_EVENT_ADD, elem);
 }
@@ -234,11 +283,19 @@ 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)
 {
        snd_mixer_t *mixer = elem->class->mixer;
-       int err;
+       int err, idx, dir;
+       unsigned int m;
+       assert(elem);
+       idx = _snd_mixer_find_elem(mixer, elem, &dir);
+       if (dir != 0)
+               return -EINVAL;
        err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_REMOVE);
        list_del(&elem->list);
        free(elem);
        mixer->count--;
+       m = mixer->count - idx;
+       if (m > 0)
+               memmove(mixer->pelems + idx, mixer->pelems + idx + 1, m);
        return err;
 }
 
@@ -323,6 +380,10 @@ int snd_mixer_close(snd_mixer_t *mixer)
                snd_mixer_class_unregister(c);
        }
        assert(list_empty(&mixer->elems));
+       if (mixer->pelems) {
+               free(mixer->pelems);
+               mixer->pelems = NULL;
+       }
        while (!list_empty(&mixer->slaves)) {
                int err;
                snd_mixer_slave_t *s;
@@ -356,25 +417,12 @@ static int snd_mixer_sort(snd_mixer_t *mixer)
                return mixer->compare(*(const snd_mixer_elem_t **) a,
                                      *(const snd_mixer_elem_t **) b);
        }
-       snd_mixer_elem_t **ptr;
-       struct list_head *pos, *next;
-
        assert(mixer);
        assert(mixer->compare);
-       ptr = malloc(sizeof(snd_mixer_elem_t) * mixer->count);
-       if (ptr == NULL)
-               return -ENOMEM;
-       k = 0;
-       list_for_each(pos, next, &mixer->elems) {
-               snd_mixer_elem_t *e;
-               e = list_entry(pos, snd_mixer_elem_t, list);
-               ptr[k++] = e;
-       }
        INIT_LIST_HEAD(&mixer->elems);
-       qsort(ptr, mixer->count, sizeof(snd_mixer_elem_t), compar);
+       qsort(mixer->pelems, mixer->count, sizeof(snd_mixer_elem_t), compar);
        for (k = 0; k < mixer->count; k++)
-               list_add_tail(&ptr[k]->list, &mixer->elems);
-       free(ptr);
+               list_add_tail(&mixer->pelems[k]->list, &mixer->elems);
        return 0;
 }
 
index 0333ee3e161c40ac0e5d5e4602d1b79cf98c5c98..0e8dd9fe2e3a1c741a50e9d372757da2a32fcdef 100644 (file)
@@ -71,7 +71,9 @@ struct _snd_mixer {
        struct list_head slaves;        /* list of all slaves */
        struct list_head classes;       /* list of all elem classes */
        struct list_head elems;         /* list of all elems */
+       snd_mixer_elem_t **pelems;      /* array of all elems */
        unsigned int count;
+       unsigned int alloc;
        unsigned int events;
        snd_mixer_callback_t callback;
        void *callback_private;