]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Added sort & compare functions to the mixer API.
authorJaroslav Kysela <perex@perex.cz>
Mon, 12 Feb 2001 13:29:33 +0000 (13:29 +0000)
committerJaroslav Kysela <perex@perex.cz>
Mon, 12 Feb 2001 13:29:33 +0000 (13:29 +0000)
doc/doxygen.cfg
include/control.h
include/mixer.h
src/control/hcontrol.c
src/mixer/mixer.c
src/mixer/mixer_local.h
src/mixer/simple.c

index 285f1a154568fe1e7dbdb41df1b29b082201f83d..959203770a9545ed7ee21ad6b466814172cf29be 100644 (file)
@@ -2,11 +2,12 @@ PROJECT_NAME     = "ALSA project - the C library reference"
 OUTPUT_DIRECTORY = doxygen
 GENERATE_LATEX   = NO
 GENERATE_MAN     = NO
-INPUT            = ../include/asoundlib.h ../src
+INPUT            = ../../alsa-driver/include/asound.h ../include/asoundlib.h ../src
 FILE_PATTERNS    = *.c *.h
 #EXAMPLE_PATH     = example_test.cpp
 QUIET            = NO
 
-EXTRACT_ALL     = NO
+EXTRACT_ALL     = YES
 EXTRACT_STATIC  = YES
-#PREDEFINED     = DOC_PUBLIC
+RECURSIVE       = YES
+PREDEFINED      = DOC_PUBLIC
index 35e934c8e99b91699e02a32ae9c3c6ab66702a86..a58133f679bb796507ea0e93b58c0bb191c78e7c 100644 (file)
@@ -216,18 +216,18 @@ int snd_hctl_close(snd_hctl_t *hctl);
 int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock);
 int snd_hctl_async(snd_hctl_t *hctl, int sig, pid_t pid);
 int snd_hctl_poll_descriptor(snd_hctl_t *hctl);
-unsigned int snd_hctl_get_count(snd_hctl_t *ctl);
-void snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort);
+unsigned int snd_hctl_get_count(snd_hctl_t *hctl);
+int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort);
 snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl);
 snd_hctl_elem_t *snd_hctl_last_elem(snd_hctl_t *hctl);
-snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *ctl, const snd_ctl_elem_id_t *id);
-void snd_hctl_set_callback(snd_hctl_t *ctl, snd_hctl_callback_t callback);
-void snd_hctl_set_callback_private(snd_hctl_t *ctl, void *data);
-void *snd_hctl_get_callback_private(snd_hctl_t *ctl);
-int snd_hctl_load(snd_hctl_t *ctl);
-int snd_hctl_free(snd_hctl_t *ctl);
-int snd_hctl_handle_event(snd_hctl_t *ctl, snd_ctl_event_t *event);
-int snd_hctl_handle_events(snd_hctl_t *ctl);
+snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id);
+void snd_hctl_set_callback(snd_hctl_t *hctl, snd_hctl_callback_t callback);
+void snd_hctl_set_callback_private(snd_hctl_t *hctl, void *data);
+void *snd_hctl_get_callback_private(snd_hctl_t *hctl);
+int snd_hctl_load(snd_hctl_t *hctl);
+int snd_hctl_free(snd_hctl_t *hctl);
+int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event);
+int snd_hctl_handle_events(snd_hctl_t *hctl);
 const char *snd_hctl_name(snd_hctl_t *hctl);
 snd_ctl_type_t snd_hctl_type(snd_hctl_t *hctl);
 
@@ -237,6 +237,8 @@ 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_value_t * value);
 int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value);
 
+snd_hctl_t *snd_hctl_elem_get_handle(snd_hctl_elem_t *elem);
+
 #ifdef __cplusplus
 }
 #endif
index 3b0231394c6a4fbc0dcb0dfbf945bc73f0cd6393..18391286c93998e25e215b82bfc03780e64b8fee 100644 (file)
@@ -46,7 +46,7 @@ int snd_mixer_attach(snd_mixer_t *mixer, const char *name);
 int snd_mixer_detach(snd_mixer_t *mixer, const char *name);
 int snd_mixer_poll_descriptor(snd_mixer_t *mixer, const char *name);
 int snd_mixer_load(snd_mixer_t *mixer);
-void snd_mixer_set_compare(snd_hctl_t *hctl, snd_mixer_compare_t hsort);
+int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort);
 
 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);
index 323feaf0685676018f0ee7197d7e0ee4a915967d..449382578dc4ac48bc2dba80f25093a26c79d338 100644 (file)
@@ -187,7 +187,7 @@ static void snd_hctl_sort(snd_hctl_t *hctl)
        unsigned int k;
        int compar(const void *a, const void *b) {
                return hctl->compare(*(const snd_hctl_elem_t **) a,
-                                     *(const snd_hctl_elem_t **) b);
+                                    *(const snd_hctl_elem_t **) b);
        }
        assert(hctl);
        assert(hctl->compare);
@@ -197,11 +197,12 @@ static void snd_hctl_sort(snd_hctl_t *hctl)
                list_add_tail(&hctl->pelems[k]->list, &hctl->elems);
 }
 
-void snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort)
+int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort)
 {
        assert(hctl);
        hctl->compare = hsort == NULL ? snd_hctl_compare_default : hsort;
        snd_hctl_sort(hctl);
+       return 0;
 }
 
 #define NOT_FOUND 1000000000
@@ -534,3 +535,8 @@ int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
        return snd_ctl_elem_write(elem->hctl->ctl, value);
 }
 
+snd_hctl_t *snd_hctl_elem_get_handle(snd_hctl_elem_t *elem)
+{
+       assert(elem);
+       return elem->hctl;
+}
index ebd339ae15df56a8bb0eb789b2e1028fa8ce89b1..5d42d75fda3c8739235a18f40cb08296ccacc56b 100644 (file)
@@ -38,6 +38,11 @@ typedef struct _snd_mixer_elem_bag {
 
 } snd_mixer_elem_bag_t;
 
+
+static int snd_mixer_compare_default(const snd_mixer_elem_t *c1,
+                                    const snd_mixer_elem_t *c2);
+
+
 int snd_mixer_open(snd_mixer_t **mixerp)
 {
        snd_mixer_t *mixer;
@@ -48,6 +53,7 @@ int snd_mixer_open(snd_mixer_t **mixerp)
        INIT_LIST_HEAD(&mixer->slaves);
        INIT_LIST_HEAD(&mixer->classes);
        INIT_LIST_HEAD(&mixer->elems);
+       mixer->compare = snd_mixer_compare_default;
        *mixerp = mixer;
        return 0;
 }
@@ -219,6 +225,7 @@ int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class)
 {
        snd_mixer_t *mixer = class->mixer;
        elem->class = class;
+
        list_add_tail(&elem->list, &mixer->elems);
        mixer->count++;
        return snd_mixer_throw_event(mixer, SND_CTL_EVENT_ADD, elem);
@@ -330,6 +337,62 @@ int snd_mixer_close(snd_mixer_t *mixer)
        return res;
 }
 
+static int snd_mixer_compare_default(const snd_mixer_elem_t *c1,
+                                    const snd_mixer_elem_t *c2)
+{
+       int d = c1->compare_weight - c2->compare_weight;
+       if (d)
+               return d;
+       assert(c1->class && c1->class->compare);
+       assert(c2->class && c2->class->compare);
+       assert(c1->class == c2->class);
+       return c1->class->compare(c1, c2);
+}
+
+static int snd_mixer_sort(snd_mixer_t *mixer)
+{
+       unsigned int k;
+       int compar(const void *a, const void *b) {
+               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);
+       for (k = 0; k < mixer->count; k++)
+               list_add_tail(&ptr[k]->list, &mixer->elems);
+       free(ptr);
+       return 0;
+}
+
+int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort)
+{
+       snd_mixer_compare_t msort_old;
+       int err;
+
+       assert(mixer);
+       msort_old = mixer->compare;
+       mixer->compare = msort == NULL ? snd_mixer_compare_default : msort;
+       if ((err = snd_mixer_sort(mixer)) < 0) {
+               mixer->compare = msort_old;
+               return err;
+       }
+       return 0;
+}
+
 int snd_mixer_poll_descriptor(snd_mixer_t *mixer, const char *name)
 {
        struct list_head *pos, *next;
index 17eabd9f3ff12863abb8d3a8af3bad4061e974e9..0333ee3e161c40ac0e5d5e4602d1b79cf98c5c98 100644 (file)
@@ -41,6 +41,10 @@ typedef struct list_head *bag_iterator_t;
 #define bag_iterator_entry(i) (list_entry((i), bag1_t, list)->ptr)
 #define bag_for_each(pos, next, bag) list_for_each(pos, next, bag)
 
+#define MIXER_COMPARE_WEIGHT_SIMPLE_BASE       0
+#define MIXER_COMPARE_WEIGHT_NEXT_BASE         10000000
+#define MIXER_COMPARE_WEIGHT_NOT_FOUND         1000000000
+
 struct _snd_mixer_class {
        struct list_head list;
        snd_mixer_t *mixer;
@@ -48,6 +52,7 @@ struct _snd_mixer_class {
                     snd_hctl_elem_t *helem, snd_mixer_elem_t *melem);
        void *private_data;             
        void (*private_free)(snd_mixer_class_t *class);
+       snd_mixer_compare_t compare;
 };
 
 struct _snd_mixer_elem {
@@ -59,6 +64,7 @@ struct _snd_mixer_elem {
        snd_mixer_elem_callback_t callback;
        void *callback_private;
        bag_t helems;
+       int compare_weight;             /* compare weight (reversed) */
 };
 
 struct _snd_mixer {
@@ -69,6 +75,7 @@ struct _snd_mixer {
        unsigned int events;
        snd_mixer_callback_t callback;
        void *callback_private;
+       snd_mixer_compare_t compare;
 };
 
 struct _snd_mixer_selem_id {
index 84b954d9c8395d381f4b0afb65eaf1c17b0d4048..1ce5901b09ca0e617e5e724529af0cdfb9e407ec 100644 (file)
@@ -94,47 +94,45 @@ static const char *get_short_name(const char *lname)
        return lname;
 }
 
-#if 0
-static const char *get_long_name(const char *sname)
-{
-       struct mixer_name_table *p;
-       for (p = name_table; p->longname; p++) {
-               if (!strcmp(sname, p->shortname))
-                       return p->longname;
-       }
-       return sname;
-}
-
-static const char *simple_elems[] = {
-       "Master Mono",
-       "Master Digital",
-       "Master",
-       "Tone Control - Bass",
-       "Tone Control - Treble",
-       "Synth Tone Control - Bass",
-       "Synth Tone Control - Treble",
-       "PCM",
-       "Surround",
-       "Synth",
-       "FM",
-       "Wave",
-       "Music",
-       "DSP",
-       "Line",
-       "CD",
-       "Mic",
-       "Video",
-       "Phone",
-       "PC Speaker",
-       "Aux",
-       "Mono Output",
-       "Mono",
-       "Playback",
-       "Capture Boost",
-       "Capture",
-       NULL
-};
-#endif
+static int get_compare_weight(const char *name, int index)
+{
+       static char *names[] = {
+               "Master Mono",
+               "Master Digital",
+               "Master",
+               "Tone Control - Bass",
+               "Tone Control - Treble",
+               "Synth Tone Control - Bass",
+               "Synth Tone Control - Treble",
+               "PCM",
+               "Surround",
+               "Synth",
+               "FM",
+               "Wave",
+               "Music",
+               "DSP",
+               "Line",
+               "CD",
+               "Mic",
+               "Video",
+               "Phone",
+               "PC Speaker",
+               "Aux",
+               "Mono Output",
+               "Mono",
+               "Playback",
+               "Capture Boost",
+               "Capture",
+               NULL
+       };
+       int res;
+
+       for (res = 0; names[res] != NULL; res++)
+               if (!strcmp(name, names[res]))
+                       return MIXER_COMPARE_WEIGHT_SIMPLE_BASE +
+                              (res * 1000) + index;
+       return MIXER_COMPARE_WEIGHT_NOT_FOUND;
+}
 
 static int selem_info(snd_mixer_elem_t *elem,
                      snd_mixer_selem_info_t *info)
@@ -592,7 +590,7 @@ static struct suf {
        const char *suffix;
        selem_ctl_type_t type;
 } suffixes[] = {
-       { " Playback Switch", CTL_PLAYBACK_SWITCH},
+       {" Playback Switch", CTL_PLAYBACK_SWITCH},
        {" Playback Route", CTL_PLAYBACK_ROUTE},
        {" Playback Volume", CTL_PLAYBACK_VOLUME},
        {" Capture Switch", CTL_CAPTURE_SWITCH},
@@ -713,6 +711,7 @@ int simple_add1(snd_mixer_class_t *class, const char *name,
        err = snd_mixer_elem_attach(melem, helem);
        if (err < 0)
                return err;
+       melem->compare_weight = get_compare_weight(simple->id.name, simple->id.index);
        err = simple_update(melem);
        assert(err >= 0);
        if (new)
@@ -743,13 +742,24 @@ int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
                        err = snd_hctl_elem_info(helem, info);
                        assert(err >= 0);
                        n = snd_ctl_elem_info_get_item_name(info);
-#if 0
-                       /* FIXME: es18xx has both Mix and Master */
-                       if (strcmp(n, "Mix") == 0)
-                               n = "Master";
-                       else if (strcmp(n, "Mono Mix") == 0)
-                               n = "Master Mono";
-#endif
+                       if (!strcmp(n, "Mix") || !strcmp(n, "Mono Mix")) {
+                               snd_hctl_t *hctl;
+                               hctl = snd_hctl_elem_get_handle(helem);
+                               if (hctl != NULL) {
+                                       snd_ctl_elem_id_t *eid;
+                                       snd_ctl_elem_id_alloca(&eid);
+                                       snd_ctl_elem_id_set_interface(eid, SND_CTL_ELEM_IFACE_MIXER);
+                                       if (!strcmp(n, "Mix")) {
+                                               snd_ctl_elem_id_set_name(eid, "Mix");
+                                               if (snd_hctl_find_elem(hctl, eid) == NULL)
+                                                       n = "Master";
+                                       } else if (!strcmp(n, "Mono Mix")) {
+                                               snd_ctl_elem_id_set_name(eid, "Mono Mix");
+                                               if (snd_hctl_find_elem(hctl, eid) == NULL)
+                                                       n = "Master Mono";
+                                       }
+                               }
+                       }
                        err = simple_add1(class, n, helem, CTL_CAPTURE_SOURCE, k);
                        if (err < 0)
                                return err;
@@ -815,6 +825,13 @@ int simple_event(snd_mixer_class_t *class, snd_ctl_event_type_t event,
        return 0;
 }
 
+static int simple_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
+{
+       selem_t *s1 = c1->private_data;
+       selem_t *s2 = c2->private_data;
+       return strcmp(s1->id.name, s2->id.name);
+}
+
 int snd_mixer_selem_register(snd_mixer_t *mixer, snd_mixer_class_t **classp)
 {
        snd_mixer_class_t *class = calloc(1, sizeof(*class));
@@ -822,6 +839,7 @@ int snd_mixer_selem_register(snd_mixer_t *mixer, snd_mixer_class_t **classp)
        if (!class)
                return -ENOMEM;
        class->event = simple_event;
+       class->compare = simple_compare;
        err = snd_mixer_class_register(class, mixer);
        if (err < 0) {
                free(class);