OSDN Git Service

alsaloop: Fix command-line parsing and pollfd initialization
authorJaroslav Kysela <perex@perex.cz>
Fri, 8 Oct 2010 20:23:05 +0000 (22:23 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 8 Oct 2010 20:23:05 +0000 (22:23 +0200)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
alsaloop/alsaloop.c
alsaloop/control.c
alsaloop/pcmjob.c
alsaloop/test.sh

index effa073..97b00d5 100644 (file)
@@ -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");
index 967f1e9..8383d79 100644 (file)
@@ -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));
index 5c2fed0..df835f0 100644 (file)
@@ -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)) {
index 13a5ba7..91f4cbc 100755 (executable)
@@ -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