forked from pool/alsa-utils
Takashi Iwai
3331bcfb82
* A few alsactl init fix patches: * amixer control-id parse fix * new aloop utility * robusitfy speaker-test * misc clean up, translation updates - Use systemd for openSUSE 11.4 - Put udev rules into this package instead of alsa.rpm OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa-utils?expand=0&rev=23
228 lines
7.2 KiB
Diff
228 lines
7.2 KiB
Diff
From e77983d3c55a7822e2151dfd60d9a20ec2023c9f Mon Sep 17 00:00:00 2001
|
|
From: Jaroslav Kysela <perex@perex.cz>
|
|
Date: Fri, 8 Oct 2010 22:23:05 +0200
|
|
Subject: [PATCH 24/38] alsaloop: Fix command-line parsing and pollfd initialization
|
|
|
|
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
---
|
|
alsaloop/alsaloop.c | 28 ++++++++++++++++++++--------
|
|
alsaloop/control.c | 4 ++++
|
|
alsaloop/pcmjob.c | 24 +++++++++++++-----------
|
|
alsaloop/test.sh | 18 +++++++++++++++++-
|
|
4 files changed, 54 insertions(+), 20 deletions(-)
|
|
|
|
diff --git a/alsaloop/alsaloop.c b/alsaloop/alsaloop.c
|
|
index effa073..97b00d5 100644
|
|
--- a/alsaloop/alsaloop.c
|
|
+++ b/alsaloop/alsaloop.c
|
|
@@ -47,6 +47,8 @@ int daemonize = 0;
|
|
int use_syslog = 0;
|
|
struct loopback **loopbacks = NULL;
|
|
int loopbacks_count = 0;
|
|
+char **my_argv = NULL;
|
|
+int my_argc = 0;
|
|
|
|
static void my_exit(struct loopback_thread *thread, int exitcode)
|
|
{
|
|
@@ -575,9 +577,6 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
|
int argc, c, err = 0;
|
|
char **argv;
|
|
|
|
- argv = malloc(sizeof(char *) * MAX_ARGS);
|
|
- if (argv == NULL)
|
|
- return -ENOMEM;
|
|
fp = fopen(file, "r");
|
|
if (fp == NULL) {
|
|
logit(LOG_CRIT, "Unable to open file '%s': %s\n", file, strerror(errno));
|
|
@@ -587,8 +586,13 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
|
if (fgets(line, sizeof(line)-1, fp) == NULL)
|
|
break;
|
|
line[sizeof(line)-1] = '\0';
|
|
+ my_argv = realloc(my_argv, my_argc + MAX_ARGS * sizeof(char *));
|
|
+ if (my_argv == NULL)
|
|
+ return -ENOMEM;
|
|
+ argv = my_argv + my_argc;
|
|
argc = 0;
|
|
argv[argc++] = strdup("<prog>");
|
|
+ my_argc++;
|
|
str = line;
|
|
while (*str) {
|
|
ptr = word;
|
|
@@ -607,25 +611,30 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
|
*ptr++ = *str++;
|
|
}
|
|
if (ptr != word) {
|
|
+ if (*(ptr-1) == '\n')
|
|
+ ptr--;
|
|
*ptr = '\0';
|
|
+ if (argc >= MAX_ARGS) {
|
|
+ logit(LOG_CRIT, "Too many arguments.");
|
|
+ goto __error;
|
|
+ }
|
|
argv[argc++] = strdup(word);
|
|
+ my_argc++;
|
|
}
|
|
}
|
|
/* erase runtime variables for getopt */
|
|
optarg = NULL;
|
|
optind = opterr = 1;
|
|
- optopt = 63;
|
|
+ optopt = '?';
|
|
|
|
err = parse_config(argc, argv, output);
|
|
__next:
|
|
- while (argc > 0)
|
|
- free(argv[--argc]);
|
|
if (err < 0)
|
|
break;
|
|
err = 0;
|
|
}
|
|
+ __error:
|
|
fclose(fp);
|
|
- free(argv);
|
|
|
|
return err;
|
|
}
|
|
@@ -656,7 +665,7 @@ static void thread_job1(void *_data)
|
|
pfds_count += thread->loopbacks[i]->pollfd_count;
|
|
}
|
|
pfds = calloc(pfds_count, sizeof(struct pollfd));
|
|
- if (pfds == NULL) {
|
|
+ if (pfds == NULL || pfds_count <= 0) {
|
|
logit(LOG_CRIT, "Poll FDs allocation failed.\n");
|
|
my_exit(thread, EXIT_FAILURE);
|
|
}
|
|
@@ -723,6 +732,9 @@ int main(int argc, char *argv[])
|
|
logit(LOG_CRIT, "Unable to parse arguments or configuration...\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
+ while (my_argc > 0)
|
|
+ free(my_argv[--my_argc]);
|
|
+ free(my_argv);
|
|
|
|
if (loopbacks_count <= 0) {
|
|
logit(LOG_CRIT, "No loopback defined...\n");
|
|
diff --git a/alsaloop/control.c b/alsaloop/control.c
|
|
index 967f1e9..8383d79 100644
|
|
--- a/alsaloop/control.c
|
|
+++ b/alsaloop/control.c
|
|
@@ -164,6 +164,10 @@ static int control_init1(struct loopback_handle *lhandle,
|
|
|
|
snd_ctl_elem_info_set_id(ctl->info, ctl->id);
|
|
snd_ctl_elem_value_set_id(ctl->value, ctl->id);
|
|
+ if (lhandle->ctl == NULL) {
|
|
+ logit(LOG_WARNING, "Unable to read control info for '%s'\n", id_str(ctl->id));
|
|
+ return -EIO;
|
|
+ }
|
|
err = snd_ctl_elem_info(lhandle->ctl, ctl->info);
|
|
if (err < 0) {
|
|
logit(LOG_WARNING, "Unable to read control info '%s': %s\n", id_str(ctl->id), snd_strerror(err));
|
|
diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c
|
|
index 5c2fed0..df835f0 100644
|
|
--- a/alsaloop/pcmjob.c
|
|
+++ b/alsaloop/pcmjob.c
|
|
@@ -1195,6 +1195,16 @@ int pcmjob_start(struct loopback *loop)
|
|
snd_pcm_uframes_t count;
|
|
int err;
|
|
|
|
+ loop->pollfd_count = loop->play->ctl_pollfd_count +
|
|
+ loop->capt->ctl_pollfd_count;
|
|
+ if ((err = snd_pcm_poll_descriptors_count(loop->play->handle)) < 0)
|
|
+ goto __error;
|
|
+ loop->play->pollfd_count = err;
|
|
+ loop->pollfd_count += err;
|
|
+ if ((err = snd_pcm_poll_descriptors_count(loop->capt->handle)) < 0)
|
|
+ goto __error;
|
|
+ loop->capt->pollfd_count = err;
|
|
+ loop->pollfd_count += err;
|
|
if (loop->slave == SLAVE_TYPE_ON) {
|
|
err = get_active(loop->capt);
|
|
if (err < 0)
|
|
@@ -1214,8 +1224,6 @@ int pcmjob_start(struct loopback *loop)
|
|
goto __error;
|
|
loop->play->channels = loop->capt->channels = err;
|
|
}
|
|
- loop->pollfd_count = loop->play->ctl_pollfd_count +
|
|
- loop->capt->ctl_pollfd_count;
|
|
loop->reinit = 0;
|
|
loop->use_samplerate = 0;
|
|
loop->latency = loop->latency_req;
|
|
@@ -1258,14 +1266,6 @@ int pcmjob_start(struct loopback *loop)
|
|
if (loop->capt->rate_req != loop->capt->rate)
|
|
loop->use_samplerate = 1;
|
|
}
|
|
- if ((err = snd_pcm_poll_descriptors_count(loop->play->handle)) < 0)
|
|
- goto __error;
|
|
- loop->play->pollfd_count = err;
|
|
- loop->pollfd_count += err;
|
|
- if ((err = snd_pcm_poll_descriptors_count(loop->capt->handle)) < 0)
|
|
- goto __error;
|
|
- loop->capt->pollfd_count = err;
|
|
- loop->pollfd_count += err;
|
|
#ifdef USE_SAMPLERATE
|
|
if (loop->sync == SYNC_TYPE_SAMPLERATE)
|
|
loop->use_samplerate = 1;
|
|
@@ -1463,9 +1463,11 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
|
if (lhandle == lhandle->loopback->play)
|
|
goto __ctl_check;
|
|
if (verbose > 6)
|
|
- snd_output_printf(lhandle->loopback->output, "ctl event!!!! %s\n", snd_ctl_event_elem_get_name(ev));
|
|
+ snd_output_printf(lhandle->loopback->output, "%s: ctl event!!!! %s\n", lhandle->id, snd_ctl_event_elem_get_name(ev));
|
|
if (ctl_event_check(lhandle->ctl_active, ev)) {
|
|
err = get_active(lhandle);
|
|
+ if (verbose > 7)
|
|
+ snd_output_printf(lhandle->loopback->output, "%s: ctl event active %i\n", lhandle->id, err);
|
|
if (err != lhandle->loopback->running)
|
|
goto __restart;
|
|
} else if (ctl_event_check(lhandle->ctl_format, ev)) {
|
|
diff --git a/alsaloop/test.sh b/alsaloop/test.sh
|
|
index 13a5ba7..91f4cbc 100755
|
|
--- a/alsaloop/test.sh
|
|
+++ b/alsaloop/test.sh
|
|
@@ -2,6 +2,7 @@
|
|
|
|
#DBG="gdb --args "
|
|
#DBG="strace"
|
|
+#DBG="valgrind --leak-check=full"
|
|
CFGFILE="/tmp/alsaloop.test.cfg"
|
|
|
|
test1() {
|
|
@@ -35,7 +36,8 @@ cat > $CFGFILE <<EOF
|
|
-C hw:1,0,0 -P plug:dmix:0 --tlatency 50000 --thread 0 \
|
|
--mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
|
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
|
- --mixer "name='PCM Playback Volume'"
|
|
+ --mixer "name='PCM Playback Volume'" \
|
|
+ --ossmixer "name=Master@VOLUME"
|
|
-C hw:1,0,1 -P plug:dmix:0 --tlatency 50000 --thread 1
|
|
-C hw:1,0,2 -P plug:dmix:0 --tlatency 50000 --thread 2
|
|
-C hw:1,0,3 -P plug:dmix:0 --tlatency 50000 --thread 3
|
|
@@ -56,10 +58,24 @@ test4() {
|
|
--mixer "name='PCM Playback Volume'"
|
|
}
|
|
|
|
+test5() {
|
|
+ echo "TEST5"
|
|
+cat > $CFGFILE <<EOF
|
|
+-C hw:1,0,0 -P plughw:0,0 --tlatency 50000 --thread 1 \
|
|
+ --mixer "name='Master Playback Volume'@name='Master Playback Volume'" \
|
|
+ --mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
|
+ --mixer "name='PCM Playback Volume'" \
|
|
+ --ossmixer "name=Master@VOLUME"
|
|
+-C hw:1,0,1 -P plughw:0,1 --tlatency 50000 --thread 2
|
|
+EOF
|
|
+ $DBG ./alsaloop --config $CFGFILE
|
|
+}
|
|
+
|
|
case "$1" in
|
|
test1) test1 ;;
|
|
test2) test2 ;;
|
|
test3) test3 ;;
|
|
test4) test4 ;;
|
|
+test5) test5 ;;
|
|
*) test1 ;;
|
|
esac
|
|
--
|
|
1.7.3.1
|
|
|