Added bag operations for the high-level control interface.

Added event layer for simple mixer controls (not fully finished).
This commit is contained in:
Jaroslav Kysela 2000-08-16 13:35:36 +00:00
parent 5bb1fcb00a
commit 7376ad380e
7 changed files with 304 additions and 85 deletions

View file

@ -1,6 +1,6 @@
EXTRA_LTLIBRARIES = libcontrol.la
libcontrol_la_SOURCES = cards.c control.c controls.c defaults.c
libcontrol_la_SOURCES = cards.c control.c controls.c bag.c defaults.c
all: libcontrol.la

87
src/control/bag.c Normal file
View file

@ -0,0 +1,87 @@
/*
* Control Interface - highlevel API - hcontrol bag operations
* Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz>
*
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <assert.h>
#define __USE_GNU
#include <search.h>
#include "asoundlib.h"
#include "control_local.h"
int snd_ctl_hbag_create(void **bag)
{
assert(bag != NULL);
*bag = NULL;
return 0;
}
static void snd_ctl_hbag_free_private(snd_hcontrol_t *hcontrol ATTRIBUTE_UNUSED)
{
/* nothing */
}
int snd_ctl_hbag_destroy(void **bag, void (*hcontrol_free)(snd_hcontrol_t *hcontrol))
{
assert(bag != NULL);
if (hcontrol_free == NULL)
hcontrol_free = snd_ctl_hbag_free_private;
tdestroy(*bag, (__free_fn_t)hcontrol_free);
*bag = NULL;
return 0;
}
int snd_ctl_hbag_add(void **bag, snd_hcontrol_t *hcontrol)
{
void *res;
assert(bag != NULL && hcontrol != NULL);
res = tsearch(hcontrol, bag, (__compar_fn_t)snd_ctl_hsort);
if (res == NULL)
return -ENOMEM;
if ((snd_hcontrol_t *)res == hcontrol)
return -EALREADY;
return 0;
}
int snd_ctl_hbag_del(void **bag, snd_hcontrol_t *hcontrol)
{
assert(bag != NULL && hcontrol != NULL);
if (tdelete(hcontrol, bag, (__compar_fn_t)snd_ctl_hsort) == NULL)
return -ENOENT;
return 0;
}
snd_hcontrol_t *snd_ctl_hbag_find(void **bag, snd_control_id_t *id)
{
void *res;
assert(bag != NULL && id != NULL);
if (*bag == NULL)
return NULL;
res = tfind(id, bag, (__compar_fn_t)snd_ctl_hsort);
return res == NULL ? NULL : *(snd_hcontrol_t **)res;
}

View file

@ -124,16 +124,103 @@ int snd_ctl_hfree(snd_ctl_t *handle)
return 0;
}
int snd_ctl_hsort(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2)
#define NOT_FOUND 1000000000
static int snd_ctl_hsort_mixer_priority_lookup(char **name, char * const *names, int coef)
{
int res;
for (res = 0; *names; names++, res += coef) {
if (!strncmp(*name, *names, strlen(*names))) {
*name += strlen(*names);
if (**name == ' ')
*name++;
return res;
}
}
return NOT_FOUND;
}
static int snd_ctl_hsort_mixer_priority(const char *name)
{
static char *names[] = {
"Master",
"Master Digital",
"Master Mono",
"Hardware Master",
"Headphone",
"Tone Control",
"3D Control",
"PCM",
"PCM Front",
"PCM Rear",
"PCM Pan",
"Wave",
"Music",
"Line",
"CD",
"Mic",
"Phone",
"Video",
"PC Speaker",
"Aux",
"ADC",
"Capture Source",
"Capture",
"Playback",
"Loopback",
"Analog Loopback",
"Digital Loopback",
"S/PDIF Input",
"S/PDIF Output",
NULL
};
static char *names1[] = {
"Switch",
"Volume",
"Playback",
"Capture",
"Bypass",
NULL
};
static char *names2[] = {
"Switch",
"Volume",
"Bypass",
NULL
};
char **ptr, *s;
int res, res1;
if ((res = snd_ctl_hsort_mixer_priority_lookup((char **)&name, names, 1000000)) == NOT_FOUND)
return NOT_FOUND;
if ((res1 = snd_ctl_hsort_mixer_priority_lookup((char **)&name, names1, 1000)) == NOT_FOUND)
return res;
res += res1;
if ((res1 = snd_ctl_hsort_mixer_priority_lookup((char **)&name, names2, 1)) == NOT_FOUND)
return res;
return res + res1;
}
int snd_ctl_hsort(const snd_hcontrol_t *c1, const snd_hcontrol_t *c2)
{
int res, p1, p2;
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)
if ((res = strcmp(c1->id.name, c2->id.name)) != 0) {
if (c1->id.iface != SND_CONTROL_IFACE_MIXER)
return res;
p1 = snd_ctl_hsort_mixer_priority(c1->id.name);
p2 = snd_ctl_hsort_mixer_priority(c2->id.name);
if (p1 < p2)
return -1;
if (p1 > p2)
return 1;
return res;
}
if (c1->id.index < c2->id.index)
return -1;
if (c1->id.index > c2->id.index)