mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-10 00:45:41 +01:00
alsaloop: Fix command-line parsing and pollfd initialization
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
147a1cc75c
commit
e77983d3c5
4 changed files with 54 additions and 20 deletions
|
@ -47,6 +47,8 @@ int daemonize = 0;
|
||||||
int use_syslog = 0;
|
int use_syslog = 0;
|
||||||
struct loopback **loopbacks = NULL;
|
struct loopback **loopbacks = NULL;
|
||||||
int loopbacks_count = 0;
|
int loopbacks_count = 0;
|
||||||
|
char **my_argv = NULL;
|
||||||
|
int my_argc = 0;
|
||||||
|
|
||||||
static void my_exit(struct loopback_thread *thread, int exitcode)
|
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;
|
int argc, c, err = 0;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
|
||||||
argv = malloc(sizeof(char *) * MAX_ARGS);
|
|
||||||
if (argv == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
fp = fopen(file, "r");
|
fp = fopen(file, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
logit(LOG_CRIT, "Unable to open file '%s': %s\n", file, strerror(errno));
|
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)
|
if (fgets(line, sizeof(line)-1, fp) == NULL)
|
||||||
break;
|
break;
|
||||||
line[sizeof(line)-1] = '\0';
|
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;
|
argc = 0;
|
||||||
argv[argc++] = strdup("<prog>");
|
argv[argc++] = strdup("<prog>");
|
||||||
|
my_argc++;
|
||||||
str = line;
|
str = line;
|
||||||
while (*str) {
|
while (*str) {
|
||||||
ptr = word;
|
ptr = word;
|
||||||
|
@ -607,25 +611,30 @@ static int parse_config_file(const char *file, snd_output_t *output)
|
||||||
*ptr++ = *str++;
|
*ptr++ = *str++;
|
||||||
}
|
}
|
||||||
if (ptr != word) {
|
if (ptr != word) {
|
||||||
|
if (*(ptr-1) == '\n')
|
||||||
|
ptr--;
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
if (argc >= MAX_ARGS) {
|
||||||
|
logit(LOG_CRIT, "Too many arguments.");
|
||||||
|
goto __error;
|
||||||
|
}
|
||||||
argv[argc++] = strdup(word);
|
argv[argc++] = strdup(word);
|
||||||
|
my_argc++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* erase runtime variables for getopt */
|
/* erase runtime variables for getopt */
|
||||||
optarg = NULL;
|
optarg = NULL;
|
||||||
optind = opterr = 1;
|
optind = opterr = 1;
|
||||||
optopt = 63;
|
optopt = '?';
|
||||||
|
|
||||||
err = parse_config(argc, argv, output);
|
err = parse_config(argc, argv, output);
|
||||||
__next:
|
__next:
|
||||||
while (argc > 0)
|
|
||||||
free(argv[--argc]);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
__error:
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
free(argv);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -656,7 +665,7 @@ static void thread_job1(void *_data)
|
||||||
pfds_count += thread->loopbacks[i]->pollfd_count;
|
pfds_count += thread->loopbacks[i]->pollfd_count;
|
||||||
}
|
}
|
||||||
pfds = calloc(pfds_count, sizeof(struct pollfd));
|
pfds = calloc(pfds_count, sizeof(struct pollfd));
|
||||||
if (pfds == NULL) {
|
if (pfds == NULL || pfds_count <= 0) {
|
||||||
logit(LOG_CRIT, "Poll FDs allocation failed.\n");
|
logit(LOG_CRIT, "Poll FDs allocation failed.\n");
|
||||||
my_exit(thread, EXIT_FAILURE);
|
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");
|
logit(LOG_CRIT, "Unable to parse arguments or configuration...\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
while (my_argc > 0)
|
||||||
|
free(my_argv[--my_argc]);
|
||||||
|
free(my_argv);
|
||||||
|
|
||||||
if (loopbacks_count <= 0) {
|
if (loopbacks_count <= 0) {
|
||||||
logit(LOG_CRIT, "No loopback defined...\n");
|
logit(LOG_CRIT, "No loopback defined...\n");
|
||||||
|
|
|
@ -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_info_set_id(ctl->info, ctl->id);
|
||||||
snd_ctl_elem_value_set_id(ctl->value, 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);
|
err = snd_ctl_elem_info(lhandle->ctl, ctl->info);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
logit(LOG_WARNING, "Unable to read control info '%s': %s\n", id_str(ctl->id), snd_strerror(err));
|
logit(LOG_WARNING, "Unable to read control info '%s': %s\n", id_str(ctl->id), snd_strerror(err));
|
||||||
|
|
|
@ -1195,6 +1195,16 @@ int pcmjob_start(struct loopback *loop)
|
||||||
snd_pcm_uframes_t count;
|
snd_pcm_uframes_t count;
|
||||||
int err;
|
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) {
|
if (loop->slave == SLAVE_TYPE_ON) {
|
||||||
err = get_active(loop->capt);
|
err = get_active(loop->capt);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
@ -1214,8 +1224,6 @@ int pcmjob_start(struct loopback *loop)
|
||||||
goto __error;
|
goto __error;
|
||||||
loop->play->channels = loop->capt->channels = err;
|
loop->play->channels = loop->capt->channels = err;
|
||||||
}
|
}
|
||||||
loop->pollfd_count = loop->play->ctl_pollfd_count +
|
|
||||||
loop->capt->ctl_pollfd_count;
|
|
||||||
loop->reinit = 0;
|
loop->reinit = 0;
|
||||||
loop->use_samplerate = 0;
|
loop->use_samplerate = 0;
|
||||||
loop->latency = loop->latency_req;
|
loop->latency = loop->latency_req;
|
||||||
|
@ -1258,14 +1266,6 @@ int pcmjob_start(struct loopback *loop)
|
||||||
if (loop->capt->rate_req != loop->capt->rate)
|
if (loop->capt->rate_req != loop->capt->rate)
|
||||||
loop->use_samplerate = 1;
|
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
|
#ifdef USE_SAMPLERATE
|
||||||
if (loop->sync == SYNC_TYPE_SAMPLERATE)
|
if (loop->sync == SYNC_TYPE_SAMPLERATE)
|
||||||
loop->use_samplerate = 1;
|
loop->use_samplerate = 1;
|
||||||
|
@ -1463,9 +1463,11 @@ static int handle_ctl_events(struct loopback_handle *lhandle,
|
||||||
if (lhandle == lhandle->loopback->play)
|
if (lhandle == lhandle->loopback->play)
|
||||||
goto __ctl_check;
|
goto __ctl_check;
|
||||||
if (verbose > 6)
|
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)) {
|
if (ctl_event_check(lhandle->ctl_active, ev)) {
|
||||||
err = get_active(lhandle);
|
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)
|
if (err != lhandle->loopback->running)
|
||||||
goto __restart;
|
goto __restart;
|
||||||
} else if (ctl_event_check(lhandle->ctl_format, ev)) {
|
} else if (ctl_event_check(lhandle->ctl_format, ev)) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#DBG="gdb --args "
|
#DBG="gdb --args "
|
||||||
#DBG="strace"
|
#DBG="strace"
|
||||||
|
#DBG="valgrind --leak-check=full"
|
||||||
CFGFILE="/tmp/alsaloop.test.cfg"
|
CFGFILE="/tmp/alsaloop.test.cfg"
|
||||||
|
|
||||||
test1() {
|
test1() {
|
||||||
|
@ -35,7 +36,8 @@ cat > $CFGFILE <<EOF
|
||||||
-C hw:1,0,0 -P plug:dmix:0 --tlatency 50000 --thread 0 \
|
-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 Volume'@name='Master Playback Volume'" \
|
||||||
--mixer "name='Master Playback Switch'@name='Master Playback Switch'" \
|
--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,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,2 -P plug:dmix:0 --tlatency 50000 --thread 2
|
||||||
-C hw:1,0,3 -P plug:dmix:0 --tlatency 50000 --thread 3
|
-C hw:1,0,3 -P plug:dmix:0 --tlatency 50000 --thread 3
|
||||||
|
@ -56,10 +58,24 @@ test4() {
|
||||||
--mixer "name='PCM Playback Volume'"
|
--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
|
case "$1" in
|
||||||
test1) test1 ;;
|
test1) test1 ;;
|
||||||
test2) test2 ;;
|
test2) test2 ;;
|
||||||
test3) test3 ;;
|
test3) test3 ;;
|
||||||
test4) test4 ;;
|
test4) test4 ;;
|
||||||
|
test5) test5 ;;
|
||||||
*) test1 ;;
|
*) test1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
Loading…
Reference in a new issue