monitor.c (3475B)
1 /* 2 * Advanced Linux Sound Architecture Control Program 3 * Copyright (c) by Takashi Iwai <tiwai@suse.de> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 #include "aconfig.h" 21 #include "version.h" 22 #include <stdio.h> 23 #include <alsa/asoundlib.h> 24 25 static int open_ctl(const char *name, snd_ctl_t **ctlp) 26 { 27 snd_ctl_t *ctl; 28 int err; 29 30 err = snd_ctl_open(&ctl, name, SND_CTL_READONLY); 31 if (err < 0) { 32 fprintf(stderr, "Cannot open ctl %s\n", name); 33 return err; 34 } 35 err = snd_ctl_subscribe_events(ctl, 1); 36 if (err < 0) { 37 fprintf(stderr, "Cannot open subscribe events to ctl %s\n", name); 38 snd_ctl_close(ctl); 39 return err; 40 } 41 *ctlp = ctl; 42 return 0; 43 } 44 45 static int print_event(int card, snd_ctl_t *ctl) 46 { 47 snd_ctl_event_t *event; 48 unsigned int mask; 49 int err; 50 51 snd_ctl_event_alloca(&event); 52 err = snd_ctl_read(ctl, event); 53 if (err < 0) 54 return err; 55 56 if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM) 57 return 0; 58 59 if (card >= 0) 60 printf("card %d, ", card); 61 printf("#%d (%i,%i,%i,%s,%i)", 62 snd_ctl_event_elem_get_numid(event), 63 snd_ctl_event_elem_get_interface(event), 64 snd_ctl_event_elem_get_device(event), 65 snd_ctl_event_elem_get_subdevice(event), 66 snd_ctl_event_elem_get_name(event), 67 snd_ctl_event_elem_get_index(event)); 68 69 mask = snd_ctl_event_elem_get_mask(event); 70 if (mask == SND_CTL_EVENT_MASK_REMOVE) { 71 printf(" REMOVE\n"); 72 return 0; 73 } 74 75 if (mask & SND_CTL_EVENT_MASK_VALUE) 76 printf(" VALUE"); 77 if (mask & SND_CTL_EVENT_MASK_INFO) 78 printf(" INFO"); 79 if (mask & SND_CTL_EVENT_MASK_ADD) 80 printf(" ADD"); 81 if (mask & SND_CTL_EVENT_MASK_TLV) 82 printf(" TLV"); 83 printf("\n"); 84 return 0; 85 } 86 87 #define MAX_CARDS 256 88 89 int monitor(const char *name) 90 { 91 snd_ctl_t *ctls[MAX_CARDS]; 92 int ncards = 0; 93 int show_cards; 94 int i, err = 0; 95 96 if (!name) { 97 int card = -1; 98 while (snd_card_next(&card) >= 0 && card >= 0) { 99 char cardname[16]; 100 if (ncards >= MAX_CARDS) { 101 fprintf(stderr, "alsactl: too many cards\n"); 102 err = -E2BIG; 103 goto error; 104 } 105 sprintf(cardname, "hw:%d", card); 106 err = open_ctl(cardname, &ctls[ncards]); 107 if (err < 0) 108 goto error; 109 ncards++; 110 } 111 show_cards = 1; 112 } else { 113 err = open_ctl(name, &ctls[0]); 114 if (err < 0) 115 goto error; 116 ncards++; 117 show_cards = 0; 118 } 119 120 for (;ncards > 0;) { 121 struct pollfd fds[ncards]; 122 123 for (i = 0; i < ncards; i++) 124 snd_ctl_poll_descriptors(ctls[i], &fds[i], 1); 125 126 err = poll(fds, ncards, -1); 127 if (err <= 0) { 128 err = 0; 129 break; 130 } 131 132 for (i = 0; i < ncards; i++) { 133 unsigned short revents; 134 snd_ctl_poll_descriptors_revents(ctls[i], &fds[i], 1, 135 &revents); 136 if (revents & POLLIN) 137 print_event(show_cards ? i : -1, ctls[i]); 138 } 139 } 140 141 error: 142 for (i = 0; i < ncards; i++) 143 snd_ctl_close(ctls[i]); 144 return err; 145 }