mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04:00
Improved mixer sort/compare interface.
This commit is contained in:
parent
6f3b01b79c
commit
515d1a6415
3 changed files with 70 additions and 18 deletions
|
|
@ -134,8 +134,10 @@ static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem)
|
||||||
snd_hctl_elem_t **h;
|
snd_hctl_elem_t **h;
|
||||||
hctl->alloc += 32;
|
hctl->alloc += 32;
|
||||||
h = realloc(hctl->pelems, sizeof(*h) * hctl->alloc);
|
h = realloc(hctl->pelems, sizeof(*h) * hctl->alloc);
|
||||||
if (!h)
|
if (!h) {
|
||||||
|
hctl->alloc -= 32;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
hctl->pelems = h;
|
hctl->pelems = h;
|
||||||
}
|
}
|
||||||
if (hctl->count == 0) {
|
if (hctl->count == 0) {
|
||||||
|
|
|
||||||
|
|
@ -221,12 +221,61 @@ int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem,
|
||||||
return 0;
|
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 snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class)
|
||||||
{
|
{
|
||||||
|
int dir, idx;
|
||||||
snd_mixer_t *mixer = class->mixer;
|
snd_mixer_t *mixer = class->mixer;
|
||||||
elem->class = class;
|
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++;
|
mixer->count++;
|
||||||
return snd_mixer_throw_event(mixer, SND_CTL_EVENT_ADD, elem);
|
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)
|
int snd_mixer_elem_remove(snd_mixer_elem_t *elem)
|
||||||
{
|
{
|
||||||
snd_mixer_t *mixer = elem->class->mixer;
|
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);
|
err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_REMOVE);
|
||||||
list_del(&elem->list);
|
list_del(&elem->list);
|
||||||
free(elem);
|
free(elem);
|
||||||
mixer->count--;
|
mixer->count--;
|
||||||
|
m = mixer->count - idx;
|
||||||
|
if (m > 0)
|
||||||
|
memmove(mixer->pelems + idx, mixer->pelems + idx + 1, m);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -323,6 +380,10 @@ int snd_mixer_close(snd_mixer_t *mixer)
|
||||||
snd_mixer_class_unregister(c);
|
snd_mixer_class_unregister(c);
|
||||||
}
|
}
|
||||||
assert(list_empty(&mixer->elems));
|
assert(list_empty(&mixer->elems));
|
||||||
|
if (mixer->pelems) {
|
||||||
|
free(mixer->pelems);
|
||||||
|
mixer->pelems = NULL;
|
||||||
|
}
|
||||||
while (!list_empty(&mixer->slaves)) {
|
while (!list_empty(&mixer->slaves)) {
|
||||||
int err;
|
int err;
|
||||||
snd_mixer_slave_t *s;
|
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,
|
return mixer->compare(*(const snd_mixer_elem_t **) a,
|
||||||
*(const snd_mixer_elem_t **) b);
|
*(const snd_mixer_elem_t **) b);
|
||||||
}
|
}
|
||||||
snd_mixer_elem_t **ptr;
|
|
||||||
struct list_head *pos, *next;
|
|
||||||
|
|
||||||
assert(mixer);
|
assert(mixer);
|
||||||
assert(mixer->compare);
|
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);
|
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++)
|
for (k = 0; k < mixer->count; k++)
|
||||||
list_add_tail(&ptr[k]->list, &mixer->elems);
|
list_add_tail(&mixer->pelems[k]->list, &mixer->elems);
|
||||||
free(ptr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,9 @@ struct _snd_mixer {
|
||||||
struct list_head slaves; /* list of all slaves */
|
struct list_head slaves; /* list of all slaves */
|
||||||
struct list_head classes; /* list of all elem classes */
|
struct list_head classes; /* list of all elem classes */
|
||||||
struct list_head elems; /* list of all elems */
|
struct list_head elems; /* list of all elems */
|
||||||
|
snd_mixer_elem_t **pelems; /* array of all elems */
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
unsigned int alloc;
|
||||||
unsigned int events;
|
unsigned int events;
|
||||||
snd_mixer_callback_t callback;
|
snd_mixer_callback_t callback;
|
||||||
void *callback_private;
|
void *callback_private;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue