mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	Added bag operations for the high-level control interface.
Added event layer for simple mixer controls (not fully finished).
This commit is contained in:
		
							parent
							
								
									5bb1fcb00a
								
							
						
					
					
						commit
						7376ad380e
					
				
					 7 changed files with 304 additions and 85 deletions
				
			
		| 
						 | 
				
			
			@ -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
									
								
							
							
						
						
									
										87
									
								
								src/control/bag.c
									
										
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue