]> git.alsa-project.org Git - alsa-utils.git/commitdiff
alsactl: monitor all cards as default
authorTakashi Iwai <tiwai@suse.de>
Tue, 26 Nov 2013 13:27:30 +0000 (14:27 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 26 Nov 2013 13:27:30 +0000 (14:27 +0100)
Signed-off-by: Takashi Iwai <tiwai@suse.de>
alsactl/alsactl.1
alsactl/monitor.c

index a11c17cb59e19fbae304ccd234178b553269510a..b1e17945c2fb76fb7a57c17114d97061495f5fcd 100644 (file)
@@ -39,9 +39,8 @@ rescan, save_and_quit).
 \fImonitor\fP is for monitoring the events received from the given
 control device.
 
-If no soundcards are specified, setup for all cards will be saved or
-loaded (except for \fImonitor\fP command that can handle only a single
-card; it selects the card "default" when unspecified).
+If no soundcards are specified, setup for all cards will be saved,
+loaded or monitored.
 
 .SH OPTIONS
 
index 1c0246849c62736717e11d62a5cba356fbbe84ef..536176d0e7cb49692315274900fefa48f7cd712f 100644 (file)
 #include <stdio.h>
 #include <alsa/asoundlib.h>
 
-int monitor(const char *name)
+static int open_ctl(const char *name, snd_ctl_t **ctlp)
 {
        snd_ctl_t *ctl;
-       snd_ctl_event_t *event;
        int err;
 
-       if (!name)
-               name = "default";
-
        err = snd_ctl_open(&ctl, name, SND_CTL_READONLY);
        if (err < 0) {
                fprintf(stderr, "Cannot open ctl %s\n", name);
@@ -42,36 +38,108 @@ int monitor(const char *name)
                snd_ctl_close(ctl);
                return err;
        }
+       *ctlp = ctl;
+       return 0;
+}
+
+static int print_event(int card, snd_ctl_t *ctl)
+{
+       snd_ctl_event_t *event;
+       unsigned int mask;
+       int err;
+
        snd_ctl_event_alloca(&event);
-       while (snd_ctl_read(ctl, event) > 0) {
-               unsigned int mask;
-
-               if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM)
-                       continue;
-
-               printf("#%d (%i,%i,%i,%s,%i)",
-                      snd_ctl_event_elem_get_numid(event),
-                      snd_ctl_event_elem_get_interface(event),
-                      snd_ctl_event_elem_get_device(event),
-                      snd_ctl_event_elem_get_subdevice(event),
-                      snd_ctl_event_elem_get_name(event),
-                      snd_ctl_event_elem_get_index(event));
-
-               mask = snd_ctl_event_elem_get_mask(event);
-               if (mask == SND_CTL_EVENT_MASK_REMOVE) {
-                       printf(" REMOVE\n");
-                       continue;
-               }
-               if (mask & SND_CTL_EVENT_MASK_VALUE)
-                       printf(" VALUE");
-               if (mask & SND_CTL_EVENT_MASK_INFO)
-                       printf(" INFO");
-               if (mask & SND_CTL_EVENT_MASK_ADD)
-                       printf(" ADD");
-               if (mask & SND_CTL_EVENT_MASK_TLV)
-                       printf(" TLV");
-               printf("\n");
+       err = snd_ctl_read(ctl, event);
+       if (err < 0)
+               return err;
+
+       if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM)
+               return 0;
+
+       if (card >= 0)
+               printf("card %d, ", card);
+       printf("#%d (%i,%i,%i,%s,%i)",
+              snd_ctl_event_elem_get_numid(event),
+              snd_ctl_event_elem_get_interface(event),
+              snd_ctl_event_elem_get_device(event),
+              snd_ctl_event_elem_get_subdevice(event),
+              snd_ctl_event_elem_get_name(event),
+              snd_ctl_event_elem_get_index(event));
+
+       mask = snd_ctl_event_elem_get_mask(event);
+       if (mask == SND_CTL_EVENT_MASK_REMOVE) {
+               printf(" REMOVE\n");
+               return 0;
        }
-       snd_ctl_close(ctl);
+
+       if (mask & SND_CTL_EVENT_MASK_VALUE)
+               printf(" VALUE");
+       if (mask & SND_CTL_EVENT_MASK_INFO)
+               printf(" INFO");
+       if (mask & SND_CTL_EVENT_MASK_ADD)
+               printf(" ADD");
+       if (mask & SND_CTL_EVENT_MASK_TLV)
+               printf(" TLV");
+       printf("\n");
        return 0;
 }
+
+#define MAX_CARDS      256
+
+int monitor(const char *name)
+{
+       snd_ctl_t *ctls[MAX_CARDS];
+       int ncards = 0;
+       int show_cards;
+       int i, err;
+
+       if (!name) {
+               int card = -1;
+               while (snd_card_next(&card) >= 0 && card >= 0) {
+                       char cardname[16];
+                       if (ncards >= MAX_CARDS) {
+                               fprintf(stderr, "alsactl: too many cards\n");
+                               err = -E2BIG;
+                               goto error;
+                       }
+                       sprintf(cardname, "hw:%d", card);
+                       err = open_ctl(cardname, &ctls[ncards]);
+                       if (err < 0)
+                               goto error;
+                       ncards++;
+               }
+               show_cards = 1;
+       } else {
+               err = open_ctl(name, &ctls[0]);
+               if (err < 0)
+                       goto error;
+               ncards++;
+               show_cards = 0;
+       }
+
+       for (;;) {
+               struct pollfd fds[ncards];
+
+               for (i = 0; i < ncards; i++)
+                       snd_ctl_poll_descriptors(ctls[i], &fds[i], 1);
+
+               err = poll(fds, ncards, -1);
+               if (err <= 0) {
+                       err = 0;
+                       break;
+               }
+
+               for (i = 0; i < ncards; i++) {
+                       unsigned short revents;
+                       snd_ctl_poll_descriptors_revents(ctls[i], &fds[i], 1,
+                                                        &revents);
+                       if (revents & POLLIN)
+                               print_event(show_cards ? i : -1, ctls[i]);
+               }
+       }
+
+ error:
+       for (i = 0; i < ncards; i++)
+               snd_ctl_close(ctls[i]);
+       return err;
+}