Add native ALSA mixer support
This commit is contained in:
		
							parent
							
								
									5a441cd6de
								
							
						
					
					
						commit
						96ec41a88f
					
				
					 9 changed files with 654 additions and 103 deletions
				
			
		| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
CC		= gcc
 | 
					CC		= gcc
 | 
				
			||||||
CFLAGS		= -O3 -W -Wall
 | 
					CFLAGS		= -std=gnu99 -O3 -W -Wall `pkg-config --cflags alsa`
 | 
				
			||||||
LDFLAGS		= -L/usr/X11R6/lib
 | 
					LDFLAGS		= -L/usr/X11R6/lib
 | 
				
			||||||
LIBS		= -lXpm -lXext -lX11 -lm
 | 
					LIBS		= -lXpm -lXext -lX11 -lm `pkg-config --libs alsa`
 | 
				
			||||||
OBJECTS		= misc.o config.o mixer-oss.o ui_x.o mmkeys.o wmix.o
 | 
					OBJECTS		= misc.o config.o mixer-alsa.o mixer-oss.o ui_x.o mmkeys.o wmix.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# where to install this program (also for packaging stuff)
 | 
					# where to install this program (also for packaging stuff)
 | 
				
			||||||
PREFIX		= /usr/local
 | 
					PREFIX		= /usr/local
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,19 +30,21 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "include/common.h"
 | 
					#include "include/common.h"
 | 
				
			||||||
#include "include/config.h"
 | 
					#include "include/config.h"
 | 
				
			||||||
 | 
					#include "include/misc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define VERSION_TEXT \
 | 
					#define VERSION_TEXT \
 | 
				
			||||||
	"WMixer " VERSION " by timecop@japan.co.jp + skunk@mit.edu\n"
 | 
						"WMixer " VERSION " by timecop@japan.co.jp + skunk@mit.edu\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HELP_TEXT \
 | 
					#define HELP_TEXT \
 | 
				
			||||||
	"usage:\n" \
 | 
						"usage:\n" \
 | 
				
			||||||
 | 
					        "  -a <api>  use this sound api (oss or alsa) [alsa]\n" \
 | 
				
			||||||
	"  -d <dsp>  connect to remote X display\n" \
 | 
						"  -d <dsp>  connect to remote X display\n" \
 | 
				
			||||||
	"  -e <name> exclude channel, can be used many times\n" \
 | 
						"  -e <name> exclude channel, can be used many times\n" \
 | 
				
			||||||
	"  -f <file> parse this config [~/.wmixrc]\n" \
 | 
						"  -f <file> parse this config [~/.wmixrc]\n" \
 | 
				
			||||||
	"  -h        print this help\n" \
 | 
						"  -h        print this help\n" \
 | 
				
			||||||
	"  -k        disable grabing volume control keys\n" \
 | 
						"  -k        disable grabing volume control keys\n" \
 | 
				
			||||||
	"  -m <dev>  mixer device [/dev/mixer]\n" \
 | 
						"  -m <dev>  oss mixer device [/dev/mixer]\n" \
 | 
				
			||||||
 | 
						"            or alsa card name [default]\n" \
 | 
				
			||||||
	"  -v        verbose -> id, long name, name\n" \
 | 
						"  -v        verbose -> id, long name, name\n" \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The global configuration */
 | 
					/* The global configuration */
 | 
				
			||||||
| 
						 | 
					@ -50,7 +52,7 @@ struct _Config config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The default device used for Mixer control */
 | 
					/* The default device used for Mixer control */
 | 
				
			||||||
static const char default_mixer_device[] = "/dev/mixer";
 | 
					static const char default_mixer_device[] = "/dev/mixer";
 | 
				
			||||||
 | 
					static const char default_card_name[] = "default";
 | 
				
			||||||
/* Default color for OSD */
 | 
					/* Default color for OSD */
 | 
				
			||||||
const char default_osd_color[] = "green";
 | 
					const char default_osd_color[] = "green";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,8 +63,8 @@ const char default_osd_color[] = "green";
 | 
				
			||||||
void config_init(void)
 | 
					void config_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	memset(&config, 0, sizeof(config));
 | 
						memset(&config, 0, sizeof(config));
 | 
				
			||||||
 | 
					        config.api = 0;
 | 
				
			||||||
	config.mixer_device = (char *) default_mixer_device;
 | 
						config.mixer_device = NULL;
 | 
				
			||||||
	config.mousewheel = 1;
 | 
						config.mousewheel = 1;
 | 
				
			||||||
	config.scrolltext = 1;
 | 
						config.scrolltext = 1;
 | 
				
			||||||
	config.mmkeys = 1;
 | 
						config.mmkeys = 1;
 | 
				
			||||||
| 
						 | 
					@ -89,13 +91,14 @@ void config_release(void)
 | 
				
			||||||
	if (config.display_name)
 | 
						if (config.display_name)
 | 
				
			||||||
		free(config.display_name);
 | 
							free(config.display_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (config.mixer_device != default_mixer_device)
 | 
						if (config.mixer_device != default_mixer_device
 | 
				
			||||||
 | 
					            && config.mixer_device != default_card_name)
 | 
				
			||||||
		free(config.mixer_device);
 | 
							free(config.mixer_device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (config.osd_color != default_osd_color)
 | 
						if (config.osd_color != default_osd_color)
 | 
				
			||||||
		free(config.osd_color);
 | 
							free(config.osd_color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 | 
						for (i = 0; i < EXCLUDE_MAX_COUNT; i++) {
 | 
				
			||||||
		if (config.exclude_channel[i])
 | 
							if (config.exclude_channel[i])
 | 
				
			||||||
			free(config.exclude_channel[i]);
 | 
								free(config.exclude_channel[i]);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
| 
						 | 
					@ -119,7 +122,7 @@ void parse_cli_options(int argc, char **argv)
 | 
				
			||||||
	config.verbose = false;
 | 
						config.verbose = false;
 | 
				
			||||||
	error_found = false;
 | 
						error_found = false;
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		opt = getopt(argc, argv, ":d:e:f:hkm:v");
 | 
							opt = getopt(argc, argv, ":a:d:e:f:hkm:v");
 | 
				
			||||||
		if (opt == -1)
 | 
							if (opt == -1)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,7 +136,12 @@ void parse_cli_options(int argc, char **argv)
 | 
				
			||||||
			fprintf(stderr, "wmix:error: missing argument for option '-%c'\n", optopt);
 | 
								fprintf(stderr, "wmix:error: missing argument for option '-%c'\n", optopt);
 | 
				
			||||||
			error_found = true;
 | 
								error_found = true;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case 'a':
 | 
				
			||||||
 | 
								if(!strcmp("oss", optarg))
 | 
				
			||||||
 | 
									config.api = 1;
 | 
				
			||||||
 | 
								else if (strcmp("alsa", optarg))
 | 
				
			||||||
 | 
									fprintf(stderr, "Warning: Incorrect sound api specified, defaulting to alsa\n");
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'd':
 | 
							case 'd':
 | 
				
			||||||
			if (config.display_name)
 | 
								if (config.display_name)
 | 
				
			||||||
				free(config.display_name);
 | 
									free(config.display_name);
 | 
				
			||||||
| 
						 | 
					@ -141,7 +149,7 @@ void parse_cli_options(int argc, char **argv)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case 'e':
 | 
							case 'e':
 | 
				
			||||||
			if (count_exclude < SOUND_MIXER_NRDEVICES) {
 | 
								if (count_exclude < EXCLUDE_MAX_COUNT) {
 | 
				
			||||||
				config.exclude_channel[count_exclude] = strdup(optarg);
 | 
									config.exclude_channel[count_exclude] = strdup(optarg);
 | 
				
			||||||
				count_exclude++;
 | 
									count_exclude++;
 | 
				
			||||||
			} else
 | 
								} else
 | 
				
			||||||
| 
						 | 
					@ -180,6 +188,13 @@ void parse_cli_options(int argc, char **argv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	config.exclude_channel[count_exclude] = NULL;
 | 
						config.exclude_channel[count_exclude] = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!config.mixer_device) {
 | 
				
			||||||
 | 
							if (config.api == 0)
 | 
				
			||||||
 | 
								config.mixer_device = (char *)default_card_name;
 | 
				
			||||||
 | 
							else if (config.api == 1)
 | 
				
			||||||
 | 
								config.mixer_device = (char *)default_mixer_device;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (optind < argc) {
 | 
						if (optind < argc) {
 | 
				
			||||||
		fprintf(stderr, "wmix:error: argument '%s' not understood\n", argv[optind]);
 | 
							fprintf(stderr, "wmix:error: argument '%s' not understood\n", argv[optind]);
 | 
				
			||||||
		error_found = true;
 | 
							error_found = true;
 | 
				
			||||||
| 
						 | 
					@ -296,9 +311,10 @@ void config_read(void)
 | 
				
			||||||
		} else if (strcmp(keyword, "exclude") == 0) {
 | 
							} else if (strcmp(keyword, "exclude") == 0) {
 | 
				
			||||||
			int i;
 | 
								int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 | 
								for (i = 0; i < EXCLUDE_MAX_COUNT; i++) {
 | 
				
			||||||
				if (config.exclude_channel[i] == NULL) {
 | 
									if (config.exclude_channel[i] == NULL) {
 | 
				
			||||||
					config.exclude_channel[i] = strdup(value);
 | 
										config.exclude_channel[i] = strdup(value);
 | 
				
			||||||
 | 
										config.exclude_channel[i+1] = NULL;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,9 +20,7 @@
 | 
				
			||||||
#ifndef WMIX_CONFIG_H
 | 
					#ifndef WMIX_CONFIG_H
 | 
				
			||||||
#define WMIX_CONFIG_H
 | 
					#define WMIX_CONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Needed for SOUND_MIXER_NRDEVICES */
 | 
					#define EXCLUDE_MAX_COUNT 100
 | 
				
			||||||
#include <sys/soundcard.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Global Configuration */
 | 
					/* Global Configuration */
 | 
				
			||||||
extern struct _Config {
 | 
					extern struct _Config {
 | 
				
			||||||
| 
						 | 
					@ -30,6 +28,7 @@ extern struct _Config {
 | 
				
			||||||
	char        *display_name;		/* X Display to connect to */
 | 
						char        *display_name;		/* X Display to connect to */
 | 
				
			||||||
	char        *mixer_device;		/* device file to use for controlling Mixer volumes */
 | 
						char        *mixer_device;		/* device file to use for controlling Mixer volumes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsigned int api;               /* Sound API (0 = ALSA, 1 = OSS) */
 | 
				
			||||||
	unsigned int verbose    : 1;	/* be Verbose when starting */
 | 
						unsigned int verbose    : 1;	/* be Verbose when starting */
 | 
				
			||||||
	unsigned int osd        : 1;	/* show OSD? */
 | 
						unsigned int osd        : 1;	/* show OSD? */
 | 
				
			||||||
	unsigned int mousewheel : 1;	/* mousewheel enabled? */
 | 
						unsigned int mousewheel : 1;	/* mousewheel enabled? */
 | 
				
			||||||
| 
						 | 
					@ -42,7 +41,7 @@ extern struct _Config {
 | 
				
			||||||
	float        scrollstep;		/* scroll mouse step adjustment */
 | 
						float        scrollstep;		/* scroll mouse step adjustment */
 | 
				
			||||||
	char        *osd_color;			/* osd color */
 | 
						char        *osd_color;			/* osd color */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char        *exclude_channel[SOUND_MIXER_NRDEVICES + 1];	/* Devices to exclude from GUI's list */
 | 
						char        *exclude_channel[EXCLUDE_MAX_COUNT + 1];	/* Devices to exclude from GUI's list */
 | 
				
			||||||
} config;
 | 
					} config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Default color for OSD */
 | 
					/* Default color for OSD */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								wmix/include/mixer-alsa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								wmix/include/mixer-alsa.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					/* WMix 3.0 -- a mixer using the OSS mixer API.
 | 
				
			||||||
 | 
					 * Copyright (C) 2000, 2001
 | 
				
			||||||
 | 
					 *	Daniel Richard G. <skunk@mit.edu>,
 | 
				
			||||||
 | 
					 *	timecop <timecop@japan.co.jp>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU 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 General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_init(const char *mixer_oss_device,
 | 
				
			||||||
 | 
					                     bool verbose,
 | 
				
			||||||
 | 
					                     const char *exclude[]);
 | 
				
			||||||
 | 
					bool mixer_alsa_is_changed(void);
 | 
				
			||||||
 | 
					int mixer_alsa_get_channel_count(void);
 | 
				
			||||||
 | 
					int mixer_alsa_get_channel(void);
 | 
				
			||||||
 | 
					const char *mixer_alsa_get_channel_name(void);
 | 
				
			||||||
 | 
					const char *mixer_alsa_get_short_name(void);
 | 
				
			||||||
 | 
					void mixer_alsa_set_channel(int channel);
 | 
				
			||||||
 | 
					void mixer_alsa_set_channel_rel(int delta_channel);
 | 
				
			||||||
 | 
					float mixer_alsa_get_volume(void);
 | 
				
			||||||
 | 
					void mixer_alsa_set_volume(float volume);
 | 
				
			||||||
 | 
					void mixer_alsa_set_volume_rel(float delta_volume);
 | 
				
			||||||
 | 
					float mixer_alsa_get_balance(void);
 | 
				
			||||||
 | 
					void mixer_alsa_set_balance(float balance);
 | 
				
			||||||
 | 
					void mixer_alsa_set_balance_rel(float delta_balance);
 | 
				
			||||||
 | 
					void mixer_alsa_toggle_mute(void);
 | 
				
			||||||
 | 
					void mixer_alsa_toggle_rec(void);
 | 
				
			||||||
 | 
					bool mixer_alsa_is_muted(void);
 | 
				
			||||||
 | 
					bool mixer_alsa_is_stereo(void);
 | 
				
			||||||
 | 
					bool mixer_alsa_is_rec(void);
 | 
				
			||||||
 | 
					bool mixer_alsa_can_rec (void);
 | 
				
			||||||
 | 
					void mixer_alsa_tick(void);
 | 
				
			||||||
							
								
								
									
										42
									
								
								wmix/include/mixer-oss.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								wmix/include/mixer-oss.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					/* WMix 3.0 -- a mixer using the OSS mixer API.
 | 
				
			||||||
 | 
					 * Copyright (C) 2000, 2001
 | 
				
			||||||
 | 
					 *	Daniel Richard G. <skunk@mit.edu>,
 | 
				
			||||||
 | 
					 *	timecop <timecop@japan.co.jp>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU 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 General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_oss_init(const char *mixer_oss_device,
 | 
				
			||||||
 | 
					                    bool verbose,
 | 
				
			||||||
 | 
					                    const char *exclude[]);
 | 
				
			||||||
 | 
					bool mixer_oss_is_changed(void);
 | 
				
			||||||
 | 
					int mixer_oss_get_channel_count(void);
 | 
				
			||||||
 | 
					int mixer_oss_get_channel(void);
 | 
				
			||||||
 | 
					const char *mixer_oss_get_channel_name(void);
 | 
				
			||||||
 | 
					const char *mixer_oss_get_short_name(void);
 | 
				
			||||||
 | 
					void mixer_oss_set_channel(int channel);
 | 
				
			||||||
 | 
					void mixer_oss_set_channel_rel(int delta_channel);
 | 
				
			||||||
 | 
					float mixer_oss_get_volume(void);
 | 
				
			||||||
 | 
					void mixer_oss_set_volume(float volume);
 | 
				
			||||||
 | 
					void mixer_oss_set_volume_rel(float delta_volume);
 | 
				
			||||||
 | 
					float mixer_oss_get_balance(void);
 | 
				
			||||||
 | 
					void mixer_oss_set_balance(float balance);
 | 
				
			||||||
 | 
					void mixer_oss_set_balance_rel(float delta_balance);
 | 
				
			||||||
 | 
					void mixer_oss_toggle_mute(void);
 | 
				
			||||||
 | 
					void mixer_oss_toggle_rec(void);
 | 
				
			||||||
 | 
					bool mixer_oss_is_muted(void);
 | 
				
			||||||
 | 
					bool mixer_oss_is_stereo(void);
 | 
				
			||||||
 | 
					bool mixer_oss_is_rec(void);
 | 
				
			||||||
 | 
					bool mixer_oss_can_rec(void);
 | 
				
			||||||
| 
						 | 
					@ -55,27 +55,28 @@
 | 
				
			||||||
 * - Muting must occur independently of the volume level.
 | 
					 * - Muting must occur independently of the volume level.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void		mixer_init			(const char *mixer_device,
 | 
					void (*mixer_init)(const char *mixer_device,
 | 
				
			||||||
						 bool verbose,
 | 
					                   bool verbose,
 | 
				
			||||||
						 const char *exclude[]);
 | 
					                   const char *exclude[]);
 | 
				
			||||||
bool		mixer_is_changed		(void);
 | 
					bool (*mixer_is_changed)(void);
 | 
				
			||||||
int		mixer_get_channel_count		(void);
 | 
					int (*mixer_get_channel_count)(void);
 | 
				
			||||||
int		mixer_get_channel		(void);
 | 
					int (*mixer_get_channel)(void);
 | 
				
			||||||
const char *	mixer_get_channel_name		(void);
 | 
					const char *(*mixer_get_channel_name)(void);
 | 
				
			||||||
const char *	mixer_get_short_name		(void);
 | 
					const char *(*mixer_get_short_name)(void);
 | 
				
			||||||
void		mixer_set_channel		(int channel);
 | 
					void (*mixer_set_channel)(int channel);
 | 
				
			||||||
void		mixer_set_channel_rel		(int delta_channel);
 | 
					void (*mixer_set_channel_rel)(int delta_channel);
 | 
				
			||||||
float		mixer_get_volume		(void);
 | 
					float (*mixer_get_volume)(void);
 | 
				
			||||||
void		mixer_set_volume		(float volume);
 | 
					void (*mixer_set_volume)(float volume);
 | 
				
			||||||
void		mixer_set_volume_rel		(float delta_volume);
 | 
					void (*mixer_set_volume_rel)(float delta_volume);
 | 
				
			||||||
float		mixer_get_balance		(void);
 | 
					float (*mixer_get_balance)(void);
 | 
				
			||||||
void		mixer_set_balance		(float balance);
 | 
					void (*mixer_set_balance)(float balance);
 | 
				
			||||||
void		mixer_set_balance_rel		(float delta_balance);
 | 
					void (*mixer_set_balance_rel)(float delta_balance);
 | 
				
			||||||
void		mixer_toggle_mute		(void);
 | 
					void (*mixer_toggle_mute)(void);
 | 
				
			||||||
void		mixer_toggle_rec		(void);
 | 
					void (*mixer_toggle_rec)(void);
 | 
				
			||||||
bool		mixer_is_muted			(void);
 | 
					bool (*mixer_is_muted)(void);
 | 
				
			||||||
bool		mixer_is_stereo			(void);
 | 
					bool (*mixer_is_stereo)(void);
 | 
				
			||||||
bool		mixer_is_rec			(void);
 | 
					bool (*mixer_is_rec)(void);
 | 
				
			||||||
bool		mixer_can_rec			(void);
 | 
					bool (*mixer_can_rec)(void);
 | 
				
			||||||
bool            is_exclude                      (const char *short_name,
 | 
					bool (*is_exclude)(const char *short_name,
 | 
				
			||||||
						 const char *exclude[]);
 | 
					                   const char *exclude[]);
 | 
				
			||||||
 | 
					void (*mixer_tick)(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										399
									
								
								wmix/mixer-alsa.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								wmix/mixer-alsa.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,399 @@
 | 
				
			||||||
 | 
					#include "include/common.h"
 | 
				
			||||||
 | 
					#include "include/misc.h"
 | 
				
			||||||
 | 
					#include "include/mixer-alsa.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <alsa/asoundlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool get_mixer_state(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mixer_element {
 | 
				
			||||||
 | 
					    const char *name;		/* name of channel */
 | 
				
			||||||
 | 
					    const char *sname;		/* short name of the channel */
 | 
				
			||||||
 | 
					    snd_mixer_elem_t *element;  /* Mixer element pointer */
 | 
				
			||||||
 | 
					    long min;                   /* Min volume */
 | 
				
			||||||
 | 
					    long max;                   /* Max volume */
 | 
				
			||||||
 | 
					    int dev;			/* channel device number */
 | 
				
			||||||
 | 
					    int prev_dev_lr_volume;	/* last known left/right volume
 | 
				
			||||||
 | 
									 * (in device format) */
 | 
				
			||||||
 | 
					    float volume;		/* volume, in [0, 1] */
 | 
				
			||||||
 | 
					    float balance;		/* balance, in [-1, 1] */
 | 
				
			||||||
 | 
					    bool has_playback;
 | 
				
			||||||
 | 
					    bool has_playback_switch;
 | 
				
			||||||
 | 
					    bool has_capture;
 | 
				
			||||||
 | 
					    bool has_capture_switch;
 | 
				
			||||||
 | 
					    bool is_recording;		/* is it recording? */
 | 
				
			||||||
 | 
					    bool is_stereo;		/* capable of stereo? */
 | 
				
			||||||
 | 
					    bool is_muted;		/* is it muted? */
 | 
				
			||||||
 | 
					    int (*get_volume)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long *);
 | 
				
			||||||
 | 
					    int (*set_volume)(snd_mixer_elem_t *, snd_mixer_selem_channel_id_t, long);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static snd_mixer_t *mixer;
 | 
				
			||||||
 | 
					static struct mixer_element *element;
 | 
				
			||||||
 | 
					static int cur_element = 0;
 | 
				
			||||||
 | 
					static int n_elements;
 | 
				
			||||||
 | 
					static bool needs_update = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int elem_callback(__attribute__((unused)) snd_mixer_elem_t *elem,
 | 
				
			||||||
 | 
					                         __attribute__((unused)) unsigned int mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    needs_update = true;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mixer_callback(__attribute__((unused)) snd_mixer_t *ctl,
 | 
				
			||||||
 | 
					                          unsigned int mask,
 | 
				
			||||||
 | 
								  snd_mixer_elem_t *elem)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (mask & SND_CTL_EVENT_MASK_ADD) {
 | 
				
			||||||
 | 
					        snd_mixer_elem_set_callback(elem, elem_callback);
 | 
				
			||||||
 | 
					        needs_update = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool is_exclude(const char *short_name,
 | 
				
			||||||
 | 
					                       const char *exclude[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    for (int i = 0; exclude[i] != NULL; i++) {
 | 
				
			||||||
 | 
					        if (!strcmp(short_name, exclude[i])) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_init(const char *mixer_device, bool verbose, const char * exclude[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int err;
 | 
				
			||||||
 | 
					    static struct snd_mixer_selem_regopt selem_regopt = {
 | 
				
			||||||
 | 
					        .ver = 1,
 | 
				
			||||||
 | 
					        .abstract = SND_MIXER_SABSTRACT_NONE,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    selem_regopt.device = mixer_device;
 | 
				
			||||||
 | 
					    if (verbose) {
 | 
				
			||||||
 | 
					        printf("Sound card: %s\n", mixer_device);
 | 
				
			||||||
 | 
					        puts("Supported elements:");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((err = snd_mixer_open(&mixer, 0)) < 0) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "snd_mixer_open error");
 | 
				
			||||||
 | 
					        mixer = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((err = snd_mixer_selem_register(mixer, &selem_regopt, NULL)) < 0) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "snd_mixer_selem_register error");
 | 
				
			||||||
 | 
					        snd_mixer_close(mixer);
 | 
				
			||||||
 | 
					        mixer = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_mixer_set_callback(mixer, mixer_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((err = snd_mixer_load(mixer)) < 0) {
 | 
				
			||||||
 | 
					        fprintf(stderr, "snd_mixer_load error");
 | 
				
			||||||
 | 
					        snd_mixer_close(mixer);
 | 
				
			||||||
 | 
					        mixer = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int all_elements = snd_mixer_get_count(mixer);
 | 
				
			||||||
 | 
					    element = (struct mixer_element *)malloc(all_elements *
 | 
				
			||||||
 | 
					                                             sizeof(struct mixer_element));
 | 
				
			||||||
 | 
					    memset(element, 0, all_elements * sizeof(struct mixer_element));
 | 
				
			||||||
 | 
					    snd_mixer_elem_t *elem = snd_mixer_first_elem(mixer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int f = 0;
 | 
				
			||||||
 | 
					    for (int e = 0; e < all_elements; e++) {
 | 
				
			||||||
 | 
					        element[f].element = elem;
 | 
				
			||||||
 | 
					        element[f].name = snd_mixer_selem_get_name(elem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (is_exclude(element[f].name, exclude)) {
 | 
				
			||||||
 | 
					            if (verbose)
 | 
				
			||||||
 | 
					                printf("  x: '%s' - disabled\n", element[f].name);
 | 
				
			||||||
 | 
					            elem = snd_mixer_elem_next(elem);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        element[f].sname = element[f].name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        element[f].has_capture = snd_mixer_selem_has_capture_volume(elem);
 | 
				
			||||||
 | 
					        element[f].has_capture &= snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        element[f].has_playback = snd_mixer_selem_has_playback_volume(elem);
 | 
				
			||||||
 | 
					        element[f].has_playback &= snd_mixer_selem_has_playback_channel(elem,SND_MIXER_SCHN_FRONT_LEFT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (element[f].has_playback) {
 | 
				
			||||||
 | 
					            snd_mixer_selem_get_playback_volume_range(elem, &(element[f].min), &(element[f].max));
 | 
				
			||||||
 | 
					            element[f].is_stereo = !snd_mixer_selem_is_playback_mono(elem);
 | 
				
			||||||
 | 
					            element[f].is_stereo &= snd_mixer_selem_has_playback_channel(elem,SND_MIXER_SCHN_FRONT_RIGHT);
 | 
				
			||||||
 | 
					            element[f].get_volume = snd_mixer_selem_get_playback_volume;
 | 
				
			||||||
 | 
					            element[f].set_volume = snd_mixer_selem_set_playback_volume;
 | 
				
			||||||
 | 
					            element[f].has_playback_switch = snd_mixer_selem_has_playback_switch(elem);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (element[f].has_capture) {
 | 
				
			||||||
 | 
					            snd_mixer_selem_get_capture_volume_range(elem, &(element[f].min), &(element[f].max));
 | 
				
			||||||
 | 
					            element[f].is_stereo = !snd_mixer_selem_is_capture_mono(element[f].element);
 | 
				
			||||||
 | 
					            element[f].is_stereo &= snd_mixer_selem_has_capture_channel(elem,SND_MIXER_SCHN_FRONT_RIGHT);
 | 
				
			||||||
 | 
					            element[f].get_volume = snd_mixer_selem_get_capture_volume;
 | 
				
			||||||
 | 
					            element[f].set_volume = snd_mixer_selem_set_capture_volume;
 | 
				
			||||||
 | 
					            element[f].has_capture_switch = snd_mixer_selem_has_capture_switch(elem);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            elem = snd_mixer_elem_next(elem);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (verbose) {
 | 
				
			||||||
 | 
					            printf("  %d: '%s'%s%s%s%s %s (%ld - %ld)\n",
 | 
				
			||||||
 | 
					                   f,
 | 
				
			||||||
 | 
					                   element[f].name,
 | 
				
			||||||
 | 
					                   element[f].has_playback? " pvolume" : "",
 | 
				
			||||||
 | 
					                   element[f].has_playback_switch? " pswitch" : "",
 | 
				
			||||||
 | 
					                   element[f].has_capture? " cvolume" : "",
 | 
				
			||||||
 | 
					                   element[f].has_capture_switch? " cswitch" : "",
 | 
				
			||||||
 | 
					                   element[f].is_stereo? "Stereo" : "Mono",
 | 
				
			||||||
 | 
					                   element[f].min, element[f].max);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elem = snd_mixer_elem_next(elem);
 | 
				
			||||||
 | 
					        f++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    n_elements = f;
 | 
				
			||||||
 | 
					    get_mixer_state();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool element_is_muted(int e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!element[e].has_playback_switch)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_mixer_elem_t *elem = element[e].element;
 | 
				
			||||||
 | 
					    int left_on;
 | 
				
			||||||
 | 
					    snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &left_on);
 | 
				
			||||||
 | 
					    if (left_on)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    if (element[e].is_stereo) {
 | 
				
			||||||
 | 
					        int right_on;
 | 
				
			||||||
 | 
					        snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, &right_on);
 | 
				
			||||||
 | 
					        if (right_on)
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool element_is_recording(int e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!element[e].has_capture_switch)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_mixer_elem_t *elem = element[e].element;
 | 
				
			||||||
 | 
					    int left_on;
 | 
				
			||||||
 | 
					    snd_mixer_selem_get_capture_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &left_on);
 | 
				
			||||||
 | 
					    if (left_on)
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    if (element[e].is_stereo) {
 | 
				
			||||||
 | 
					        int right_on;
 | 
				
			||||||
 | 
					        snd_mixer_selem_get_capture_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, &right_on);
 | 
				
			||||||
 | 
					        if (right_on)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool get_mixer_state(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!needs_update)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    needs_update = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int e = 0; e < n_elements; e++) {
 | 
				
			||||||
 | 
					        snd_mixer_elem_t *elem = element[e].element;
 | 
				
			||||||
 | 
					        long left, right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        element[e].get_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &left);
 | 
				
			||||||
 | 
					        float fleft = 1.0 * (left-element[e].min) / (element[e].max-element[e].min);
 | 
				
			||||||
 | 
					        if (element[e].is_stereo) {
 | 
				
			||||||
 | 
					            element[e].get_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &right);
 | 
				
			||||||
 | 
					            float fright = 1.0 * (right-element[e].min) /
 | 
				
			||||||
 | 
					                (element[e].max-element[e].min);
 | 
				
			||||||
 | 
					            lr_to_vb(fleft, fright, &(element[e].volume), &(element[e].balance));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            element[e].volume = fleft;
 | 
				
			||||||
 | 
					            element[e].balance = 0.0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        element[e].is_muted = element_is_muted(e);
 | 
				
			||||||
 | 
					        element[e].is_recording = element_is_recording(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //printf("Channel %s, has_vol: %d, stereo: %d, muted: %d, max: %ld, min: %ld, left: %ld, right: %ld, vol: %f, bal: %f\n", element[e].name, element[e].has_playback, element[e].is_stereo, element[e].is_muted, element[e].max, element[e].min, left, element[e].is_stereo?right:-1, element[e].volume, element[e].balance);            
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void set_mixer_state(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    float left, right;
 | 
				
			||||||
 | 
					    long dev_left_volume, dev_right_volume;
 | 
				
			||||||
 | 
					    if (!element[cur_element].has_playback && !element[cur_element].has_capture)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool muted = element_is_muted(cur_element);
 | 
				
			||||||
 | 
					    if (muted != element[cur_element].is_muted) {
 | 
				
			||||||
 | 
					        snd_mixer_selem_set_playback_switch_all(element[cur_element].element,
 | 
				
			||||||
 | 
					                                                element[cur_element].is_muted?
 | 
				
			||||||
 | 
					                                                0:1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool recording = element_is_recording(cur_element);
 | 
				
			||||||
 | 
					    if (recording != element[cur_element].is_recording) {
 | 
				
			||||||
 | 
					        snd_mixer_selem_set_capture_switch_all(element[cur_element].element,
 | 
				
			||||||
 | 
					                                               element[cur_element].is_recording?
 | 
				
			||||||
 | 
					                                               1:0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (element[cur_element].is_stereo)
 | 
				
			||||||
 | 
					        vb_to_lr(element[cur_element].volume,
 | 
				
			||||||
 | 
					                 element[cur_element].balance, &left, &right);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        left = element[cur_element].volume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    long range = element[cur_element].max - element[cur_element].min;
 | 
				
			||||||
 | 
					    dev_left_volume = element[cur_element].min + (long) (range * left);
 | 
				
			||||||
 | 
					    element[cur_element].set_volume(element[cur_element].element,
 | 
				
			||||||
 | 
					                                    SND_MIXER_SCHN_FRONT_LEFT,
 | 
				
			||||||
 | 
					                                    dev_left_volume);
 | 
				
			||||||
 | 
					    if (element[cur_element].is_stereo) {
 | 
				
			||||||
 | 
					        dev_right_volume = element[cur_element].min + (long) (range * right);
 | 
				
			||||||
 | 
					        element[cur_element].set_volume(element[cur_element].element,
 | 
				
			||||||
 | 
					                                        SND_MIXER_SCHN_FRONT_RIGHT,
 | 
				
			||||||
 | 
					                                        dev_right_volume);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mixer_alsa_is_changed(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return get_mixer_state();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mixer_alsa_get_channel_count(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return n_elements;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int mixer_alsa_get_channel(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return cur_element;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *mixer_alsa_get_channel_name(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return element[cur_element].name;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *mixer_alsa_get_short_name(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return element[cur_element].sname;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_set_channel(int element)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert((element >= 0) && (element < n_elements));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cur_element = element;
 | 
				
			||||||
 | 
					    get_mixer_state();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_set_channel_rel(int delta_element)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    cur_element = (cur_element + delta_element) % n_elements;
 | 
				
			||||||
 | 
					    if (cur_element < 0)
 | 
				
			||||||
 | 
						cur_element += n_elements;
 | 
				
			||||||
 | 
					    get_mixer_state();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float mixer_alsa_get_volume(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    get_mixer_state();
 | 
				
			||||||
 | 
					    return element[cur_element].volume;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_set_volume(float volume)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert((volume >= 0.0) && (volume <= 1.0));
 | 
				
			||||||
 | 
					    element[cur_element].volume = volume;
 | 
				
			||||||
 | 
					    set_mixer_state();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_set_volume_rel(float delta_volume)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    element[cur_element].volume += delta_volume;
 | 
				
			||||||
 | 
					    element[cur_element].volume = CLAMP(element[cur_element].volume, 0.0, 1.0);
 | 
				
			||||||
 | 
					    set_mixer_state();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float mixer_alsa_get_balance(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    get_mixer_state();
 | 
				
			||||||
 | 
					    return element[cur_element].balance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_set_balance(float balance)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert((balance >= -1.0) && (balance <= 1.0));
 | 
				
			||||||
 | 
					    if (element[cur_element].is_stereo) {
 | 
				
			||||||
 | 
						element[cur_element].balance = balance;
 | 
				
			||||||
 | 
						set_mixer_state();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_set_balance_rel(float delta_balance)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (element[cur_element].is_stereo) {
 | 
				
			||||||
 | 
						element[cur_element].balance += delta_balance;
 | 
				
			||||||
 | 
						element[cur_element].balance =
 | 
				
			||||||
 | 
						    CLAMP(element[cur_element].balance, -1.0, 1.0);
 | 
				
			||||||
 | 
						set_mixer_state();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_toggle_mute(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (element[cur_element].has_playback_switch) {
 | 
				
			||||||
 | 
					        element[cur_element].is_muted ^= 1;
 | 
				
			||||||
 | 
					        set_mixer_state();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_toggle_rec(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (element[cur_element].has_capture_switch) {
 | 
				
			||||||
 | 
					        element[cur_element].is_recording ^= 1;
 | 
				
			||||||
 | 
					        set_mixer_state();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mixer_alsa_is_muted(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return element[cur_element].is_muted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mixer_alsa_is_stereo(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return element[cur_element].is_stereo;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mixer_alsa_is_rec(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return element[cur_element].is_recording;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool mixer_alsa_can_rec(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return element[cur_element].has_capture;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_alsa_tick(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    snd_mixer_handle_events(mixer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										116
									
								
								wmix/mixer-oss.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								wmix/mixer-oss.c
									
									
									
									
									
								
							| 
						 | 
					@ -32,7 +32,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "include/common.h"
 | 
					#include "include/common.h"
 | 
				
			||||||
#include "include/misc.h"
 | 
					#include "include/misc.h"
 | 
				
			||||||
#include "include/mixer.h"
 | 
					#include "include/mixer-oss.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define WMVOLUME_CHANNEL_NAMES \
 | 
					#define WMVOLUME_CHANNEL_NAMES \
 | 
				
			||||||
	"Master volume", \
 | 
						"Master volume", \
 | 
				
			||||||
| 
						 | 
					@ -221,7 +221,43 @@ static void set_record_state(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_init(const char *mixer_device, bool verbose, const char * exclude[])
 | 
					static bool is_exclude(const char *short_name, const char *exclude[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int count;
 | 
				
			||||||
 | 
					    int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (count = 0; exclude[count] != NULL; count++) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * Short names may be padded with spaces, because apparently there is a minimum
 | 
				
			||||||
 | 
					         * length requirement of 6 characters for the name, and we do not want to
 | 
				
			||||||
 | 
					         * include this padding in the match
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        len = strlen(short_name);
 | 
				
			||||||
 | 
					        while (len > 0) {
 | 
				
			||||||
 | 
					            if (short_name[len - 1] == ' ')
 | 
				
			||||||
 | 
					                len--;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (strncmp(short_name, exclude[count], len) != 0)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (exclude[count][len] != '\0')
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Check the remaining in short name is only space */
 | 
				
			||||||
 | 
					        while (short_name[len] == ' ')
 | 
				
			||||||
 | 
					            len++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (short_name[len] == '\0')
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mixer_oss_init(const char *mixer_device, bool verbose, const char * exclude[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int devmask, srcmask, recmask, stmask;
 | 
					    int devmask, srcmask, recmask, stmask;
 | 
				
			||||||
    struct mixer_info m_info;
 | 
					    struct mixer_info m_info;
 | 
				
			||||||
| 
						 | 
					@ -288,32 +324,32 @@ void mixer_init(const char *mixer_device, bool verbose, const char * exclude[])
 | 
				
			||||||
    get_mixer_state();
 | 
					    get_mixer_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool mixer_is_changed(void)
 | 
					bool mixer_oss_is_changed(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return get_mixer_state();
 | 
					    return get_mixer_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mixer_get_channel_count(void)
 | 
					int mixer_oss_get_channel_count(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return n_channels;
 | 
					    return n_channels;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mixer_get_channel(void)
 | 
					int mixer_oss_get_channel(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return cur_channel;
 | 
					    return cur_channel;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *mixer_get_channel_name(void)
 | 
					const char *mixer_oss_get_channel_name(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return mixer[cur_channel].name;
 | 
					    return mixer[cur_channel].name;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *mixer_get_short_name(void)
 | 
					const char *mixer_oss_get_short_name(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return mixer[cur_channel].sname;
 | 
					    return mixer[cur_channel].sname;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_set_channel(int channel)
 | 
					void mixer_oss_set_channel(int channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert((channel >= 0) && (channel < n_channels));
 | 
					    assert((channel >= 0) && (channel < n_channels));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -321,7 +357,7 @@ void mixer_set_channel(int channel)
 | 
				
			||||||
    get_record_state();
 | 
					    get_record_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_set_channel_rel(int delta_channel)
 | 
					void mixer_oss_set_channel_rel(int delta_channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    cur_channel = (cur_channel + delta_channel) % n_channels;
 | 
					    cur_channel = (cur_channel + delta_channel) % n_channels;
 | 
				
			||||||
    if (cur_channel < 0)
 | 
					    if (cur_channel < 0)
 | 
				
			||||||
| 
						 | 
					@ -329,13 +365,13 @@ void mixer_set_channel_rel(int delta_channel)
 | 
				
			||||||
    get_record_state();
 | 
					    get_record_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float mixer_get_volume(void)
 | 
					float mixer_oss_get_volume(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    get_mixer_state();
 | 
					    get_mixer_state();
 | 
				
			||||||
    return mixer[cur_channel].volume;
 | 
					    return mixer[cur_channel].volume;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_set_volume(float volume)
 | 
					void mixer_oss_set_volume(float volume)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert((volume >= 0.0) && (volume <= 1.0));
 | 
					    assert((volume >= 0.0) && (volume <= 1.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -343,20 +379,20 @@ void mixer_set_volume(float volume)
 | 
				
			||||||
    set_mixer_state();
 | 
					    set_mixer_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_set_volume_rel(float delta_volume)
 | 
					void mixer_oss_set_volume_rel(float delta_volume)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    mixer[cur_channel].volume += delta_volume;
 | 
					    mixer[cur_channel].volume += delta_volume;
 | 
				
			||||||
    mixer[cur_channel].volume = CLAMP(mixer[cur_channel].volume, 0.0, 1.0);
 | 
					    mixer[cur_channel].volume = CLAMP(mixer[cur_channel].volume, 0.0, 1.0);
 | 
				
			||||||
    set_mixer_state();
 | 
					    set_mixer_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float mixer_get_balance(void)
 | 
					float mixer_oss_get_balance(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    get_mixer_state();
 | 
					    get_mixer_state();
 | 
				
			||||||
    return mixer[cur_channel].balance;
 | 
					    return mixer[cur_channel].balance;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_set_balance(float balance)
 | 
					void mixer_oss_set_balance(float balance)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert((balance >= -1.0) && (balance <= 1.0));
 | 
					    assert((balance >= -1.0) && (balance <= 1.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -366,7 +402,7 @@ void mixer_set_balance(float balance)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_set_balance_rel(float delta_balance)
 | 
					void mixer_oss_set_balance_rel(float delta_balance)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (mixer[cur_channel].is_stereo) {
 | 
					    if (mixer[cur_channel].is_stereo) {
 | 
				
			||||||
	mixer[cur_channel].balance += delta_balance;
 | 
						mixer[cur_channel].balance += delta_balance;
 | 
				
			||||||
| 
						 | 
					@ -376,14 +412,14 @@ void mixer_set_balance_rel(float delta_balance)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_toggle_mute(void)
 | 
					void mixer_oss_toggle_mute(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    mixer[cur_channel].is_muted = !mixer[cur_channel].is_muted;
 | 
					    mixer[cur_channel].is_muted = !mixer[cur_channel].is_muted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    set_mixer_state();
 | 
					    set_mixer_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mixer_toggle_rec(void)
 | 
					void mixer_oss_toggle_rec(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (mixer[cur_channel].can_record) {
 | 
					    if (mixer[cur_channel].can_record) {
 | 
				
			||||||
	mixer[cur_channel].is_recording = !mixer[cur_channel].is_recording;
 | 
						mixer[cur_channel].is_recording = !mixer[cur_channel].is_recording;
 | 
				
			||||||
| 
						 | 
					@ -392,60 +428,22 @@ void mixer_toggle_rec(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool mixer_is_muted(void)
 | 
					bool mixer_oss_is_muted(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return mixer[cur_channel].is_muted;
 | 
					    return mixer[cur_channel].is_muted;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool mixer_is_stereo(void)
 | 
					bool mixer_oss_is_stereo(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return mixer[cur_channel].is_stereo;
 | 
					    return mixer[cur_channel].is_stereo;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool mixer_is_rec(void)
 | 
					bool mixer_oss_is_rec(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return mixer[cur_channel].is_recording;
 | 
					    return mixer[cur_channel].is_recording;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool mixer_can_rec(void)
 | 
					bool mixer_oss_can_rec(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return mixer[cur_channel].can_record;
 | 
					    return mixer[cur_channel].can_record;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
bool is_exclude(const char *short_name, const char *exclude[])
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int count;
 | 
					 | 
				
			||||||
	int len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (count = 0; count < SOUND_MIXER_NRDEVICES; count++) {
 | 
					 | 
				
			||||||
		if (exclude[count] == NULL)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * Short names may be padded with spaces, because apparently there is a minimum
 | 
					 | 
				
			||||||
		 * length requirement of 6 characters for the name, and we do not want to
 | 
					 | 
				
			||||||
		 * include this padding in the match
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		len = strlen(short_name);
 | 
					 | 
				
			||||||
		while (len > 0) {
 | 
					 | 
				
			||||||
			if (short_name[len - 1] == ' ')
 | 
					 | 
				
			||||||
				len--;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (strncmp(short_name, exclude[count], len) != 0)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (exclude[count][len] != '\0')
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Check the remaining in short name is only space */
 | 
					 | 
				
			||||||
		while (short_name[len] == ' ')
 | 
					 | 
				
			||||||
			len++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (short_name[len] == '\0')
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										57
									
								
								wmix/wmix.c
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								wmix/wmix.c
									
									
									
									
									
								
							| 
						 | 
					@ -31,14 +31,14 @@
 | 
				
			||||||
#include <X11/Xlib.h>
 | 
					#include <X11/Xlib.h>
 | 
				
			||||||
#include <X11/Xutil.h>
 | 
					#include <X11/Xutil.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/soundcard.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "include/common.h"
 | 
					#include "include/common.h"
 | 
				
			||||||
#include "include/mixer.h"
 | 
					#include "include/mixer.h"
 | 
				
			||||||
#include "include/misc.h"
 | 
					#include "include/misc.h"
 | 
				
			||||||
#include "include/ui_x.h"
 | 
					#include "include/ui_x.h"
 | 
				
			||||||
#include "include/mmkeys.h"
 | 
					#include "include/mmkeys.h"
 | 
				
			||||||
#include "include/config.h"
 | 
					#include "include/config.h"
 | 
				
			||||||
 | 
					#include "include/mixer-oss.h"
 | 
				
			||||||
 | 
					#include "include/mixer-alsa.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Display *display;
 | 
					static Display *display;
 | 
				
			||||||
| 
						 | 
					@ -58,6 +58,7 @@ static void button_press_event(XButtonEvent *event);
 | 
				
			||||||
static void button_release_event(XButtonEvent *event);
 | 
					static void button_release_event(XButtonEvent *event);
 | 
				
			||||||
static int  key_press_event(XKeyEvent *event);
 | 
					static int  key_press_event(XKeyEvent *event);
 | 
				
			||||||
static void motion_event(XMotionEvent *event);
 | 
					static void motion_event(XMotionEvent *event);
 | 
				
			||||||
 | 
					static void choose_api(int api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char **argv)
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
| 
						 | 
					@ -67,6 +68,7 @@ int main(int argc, char **argv)
 | 
				
			||||||
    config_init();
 | 
					    config_init();
 | 
				
			||||||
    parse_cli_options(argc, argv);
 | 
					    parse_cli_options(argc, argv);
 | 
				
			||||||
    config_read();
 | 
					    config_read();
 | 
				
			||||||
 | 
					    choose_api(config.api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mixer_init(config.mixer_device, config.verbose, (const char **)config.exclude_channel);
 | 
					    mixer_init(config.mixer_device, config.verbose, (const char **)config.exclude_channel);
 | 
				
			||||||
    mixer_set_channel(0);
 | 
					    mixer_set_channel(0);
 | 
				
			||||||
| 
						 | 
					@ -154,6 +156,8 @@ int main(int argc, char **argv)
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
	    usleep(100000);
 | 
						    usleep(100000);
 | 
				
			||||||
 | 
					            if (mixer_tick)
 | 
				
			||||||
 | 
					                mixer_tick();
 | 
				
			||||||
	    scroll_text(3, 4, 57, false);
 | 
						    scroll_text(3, 4, 57, false);
 | 
				
			||||||
	    /* rescroll message after some delay */
 | 
						    /* rescroll message after some delay */
 | 
				
			||||||
	    if (idle_loop++ > 256) {
 | 
						    if (idle_loop++ > 256) {
 | 
				
			||||||
| 
						 | 
					@ -196,6 +200,55 @@ static void signal_catch(int sig)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void choose_api(int api)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (api == 0) {
 | 
				
			||||||
 | 
					        mixer_init = &mixer_alsa_init;
 | 
				
			||||||
 | 
					        mixer_is_changed = &mixer_alsa_is_changed;
 | 
				
			||||||
 | 
					        mixer_get_channel_count = mixer_alsa_get_channel_count;
 | 
				
			||||||
 | 
					        mixer_get_channel = mixer_alsa_get_channel;
 | 
				
			||||||
 | 
					        mixer_get_channel_name = mixer_alsa_get_channel_name;
 | 
				
			||||||
 | 
					        mixer_get_short_name = mixer_alsa_get_short_name;
 | 
				
			||||||
 | 
					        mixer_set_channel = mixer_alsa_set_channel;
 | 
				
			||||||
 | 
					        mixer_set_channel_rel = mixer_alsa_set_channel_rel;
 | 
				
			||||||
 | 
					        mixer_get_volume = mixer_alsa_get_volume;
 | 
				
			||||||
 | 
					        mixer_set_volume = mixer_alsa_set_volume;
 | 
				
			||||||
 | 
					        mixer_set_volume_rel = mixer_alsa_set_volume_rel;
 | 
				
			||||||
 | 
					        mixer_get_balance = mixer_alsa_get_balance;
 | 
				
			||||||
 | 
					        mixer_set_balance = mixer_alsa_set_balance;
 | 
				
			||||||
 | 
					        mixer_set_balance_rel = mixer_alsa_set_balance_rel;
 | 
				
			||||||
 | 
					        mixer_toggle_mute = mixer_alsa_toggle_mute;
 | 
				
			||||||
 | 
					        mixer_toggle_rec = mixer_alsa_toggle_rec;
 | 
				
			||||||
 | 
					        mixer_is_muted = mixer_alsa_is_muted;
 | 
				
			||||||
 | 
					        mixer_is_stereo = mixer_alsa_is_stereo;
 | 
				
			||||||
 | 
					        mixer_is_rec = mixer_alsa_is_rec;
 | 
				
			||||||
 | 
					        mixer_can_rec = mixer_alsa_can_rec;
 | 
				
			||||||
 | 
					        mixer_tick = mixer_alsa_tick;
 | 
				
			||||||
 | 
					    } else if (api == 1) {
 | 
				
			||||||
 | 
					        mixer_init = &mixer_oss_init;
 | 
				
			||||||
 | 
					        mixer_is_changed = &mixer_oss_is_changed;
 | 
				
			||||||
 | 
					        mixer_get_channel_count = mixer_oss_get_channel_count;
 | 
				
			||||||
 | 
					        mixer_get_channel = mixer_oss_get_channel;
 | 
				
			||||||
 | 
					        mixer_get_channel_name = mixer_oss_get_channel_name;
 | 
				
			||||||
 | 
					        mixer_get_short_name = mixer_oss_get_short_name;
 | 
				
			||||||
 | 
					        mixer_set_channel = mixer_oss_set_channel;
 | 
				
			||||||
 | 
					        mixer_set_channel_rel = mixer_oss_set_channel_rel;
 | 
				
			||||||
 | 
					        mixer_get_volume = mixer_oss_get_volume;
 | 
				
			||||||
 | 
					        mixer_set_volume = mixer_oss_set_volume;
 | 
				
			||||||
 | 
					        mixer_set_volume_rel = mixer_oss_set_volume_rel;
 | 
				
			||||||
 | 
					        mixer_get_balance = mixer_oss_get_balance;
 | 
				
			||||||
 | 
					        mixer_set_balance = mixer_oss_set_balance;
 | 
				
			||||||
 | 
					        mixer_set_balance_rel = mixer_oss_set_balance_rel;
 | 
				
			||||||
 | 
					        mixer_toggle_mute = mixer_oss_toggle_mute;
 | 
				
			||||||
 | 
					        mixer_toggle_rec = mixer_oss_toggle_rec;
 | 
				
			||||||
 | 
					        mixer_is_muted = mixer_oss_is_muted;
 | 
				
			||||||
 | 
					        mixer_is_stereo = mixer_oss_is_stereo;
 | 
				
			||||||
 | 
					        mixer_is_rec = mixer_oss_is_rec;
 | 
				
			||||||
 | 
					        mixer_can_rec = mixer_oss_can_rec;
 | 
				
			||||||
 | 
					        mixer_tick = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void button_press_event(XButtonEvent *event)
 | 
					static void button_press_event(XButtonEvent *event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    double button_press_time = get_current_time();
 | 
					    double button_press_time = get_current_time();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue