From 6f3b01b79caa9b3df9223fed5ee13fa43fd8401e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 12 Feb 2001 13:29:33 +0000 Subject: [PATCH] Added sort & compare functions to the mixer API. --- doc/doxygen.cfg | 7 +-- include/control.h | 22 ++++---- include/mixer.h | 2 +- src/control/hcontrol.c | 10 +++- src/mixer/mixer.c | 63 ++++++++++++++++++++++ src/mixer/mixer_local.h | 7 +++ src/mixer/simple.c | 116 +++++++++++++++++++++++----------------- 7 files changed, 162 insertions(+), 65 deletions(-) diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index 285f1a15..95920377 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -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 diff --git a/include/control.h b/include/control.h index 35e934c8..a58133f6 100644 --- a/include/control.h +++ b/include/control.h @@ -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 diff --git a/include/mixer.h b/include/mixer.h index 3b023139..18391286 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -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); diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c index 323feaf0..44938257 100644 --- a/src/control/hcontrol.c +++ b/src/control/hcontrol.c @@ -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; +} diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index ebd339ae..5d42d75f 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -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; diff --git a/src/mixer/mixer_local.h b/src/mixer/mixer_local.h index 17eabd9f..0333ee3e 100644 --- a/src/mixer/mixer_local.h +++ b/src/mixer/mixer_local.h @@ -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 { diff --git a/src/mixer/simple.c b/src/mixer/simple.c index 84b954d9..1ce5901b 100644 --- a/src/mixer/simple.c +++ b/src/mixer/simple.c @@ -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); -- 2.47.1