1 /*
2 * Advanced Linux Sound Architecture Control Program - General info
3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "aconfig.h"
23 #include "alsactl.h"
24
pcm_device_list(snd_ctl_t *ctl, snd_pcm_stream_t stream, bool *first)25 static int pcm_device_list(snd_ctl_t *ctl, snd_pcm_stream_t stream, bool *first)
26 {
27 #ifdef __ALSA_PCM_H
28 int err, dev, idx;
29 unsigned int count;
30 snd_pcm_info_t *pcminfo;
31 snd_pcm_info_alloca(&pcminfo);
32 bool streamfirst, subfirst;
33
34 dev = -1;
35 streamfirst = true;
36 while (1) {
37 if ((err = snd_ctl_pcm_next_device(ctl, &dev)) < 0) {
38 error("snd_ctl_pcm_next_device");
39 return err;
40 }
41 if (dev < 0)
42 break;
43 snd_pcm_info_set_device(pcminfo, dev);
44 snd_pcm_info_set_subdevice(pcminfo, 0);
45 snd_pcm_info_set_stream(pcminfo, stream);
46 if ((err = snd_ctl_pcm_info(ctl, pcminfo)) < 0) {
47 if (err != -ENOENT)
48 return err;
49 continue;
50 }
51 if (*first) {
52 printf(" pcm:\n");
53 *first = false;
54 }
55 if (streamfirst) {
56 printf(" - stream: %s\n devices:\n", snd_pcm_stream_name(stream));
57 streamfirst = false;
58 }
59 printf(" - device: %d\n id: %s\n name: %s\n",
60 dev,
61 snd_pcm_info_get_id(pcminfo),
62 snd_pcm_info_get_name(pcminfo));
63 count = snd_pcm_info_get_subdevices_count(pcminfo);
64 subfirst = true;
65 for (idx = 0; idx < (int)count; idx++) {
66 snd_pcm_info_set_subdevice(pcminfo, idx);
67 if ((err = snd_ctl_pcm_info(ctl, pcminfo)) < 0) {
68 error("control digital audio playback info (%s): %s", snd_ctl_name(ctl), snd_strerror(err));
69 return err;
70 }
71 if (subfirst) {
72 printf(" subdevices:\n");
73 subfirst = false;
74 }
75 printf(" - subdevice: %d\n name: %s\n",
76 idx, snd_pcm_info_get_subdevice_name(pcminfo));
77 }
78 }
79 #endif
80 return 0;
81 }
82
snd_rawmidi_stream_name(snd_rawmidi_stream_t stream)83 static const char *snd_rawmidi_stream_name(snd_rawmidi_stream_t stream)
84 {
85 if (stream == SND_RAWMIDI_STREAM_INPUT)
86 return "INPUT";
87 if (stream == SND_RAWMIDI_STREAM_OUTPUT)
88 return "OUTPUT";
89 return "???";
90 }
91
rawmidi_device_list(snd_ctl_t *ctl, snd_rawmidi_stream_t stream, bool *first)92 static int rawmidi_device_list(snd_ctl_t *ctl, snd_rawmidi_stream_t stream, bool *first)
93 {
94 #ifdef __ALSA_RAWMIDI_H
95 int err, dev, idx;
96 unsigned int count;
97 snd_rawmidi_info_t *info;
98 snd_rawmidi_info_alloca(&info);
99 bool streamfirst, subfirst;
100
101 dev = -1;
102 streamfirst = true;
103 while (1) {
104 if ((err = snd_ctl_rawmidi_next_device(ctl, &dev)) < 0) {
105 error("snd_ctl_rawmidi_next_device");
106 return err;
107 }
108 if (dev < 0)
109 break;
110 snd_rawmidi_info_set_device(info, dev);
111 snd_rawmidi_info_set_subdevice(info, 0);
112 snd_rawmidi_info_set_stream(info, stream);
113 if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0) {
114 if (err != -ENOENT)
115 return err;
116 continue;
117 }
118 if (*first) {
119 printf(" rawmidi:\n");
120 *first = false;
121 }
122 if (streamfirst) {
123 printf(" - stream: %s\n devices:\n", snd_rawmidi_stream_name(stream));
124 streamfirst = false;
125 }
126 printf(" - device: %d\n id: %s\n name: %s\n",
127 dev,
128 snd_rawmidi_info_get_id(info),
129 snd_rawmidi_info_get_name(info));
130 count = snd_rawmidi_info_get_subdevices_count(info);
131 subfirst = true;
132 for (idx = 0; idx < (int)count; idx++) {
133 snd_rawmidi_info_set_subdevice(info, idx);
134 if ((err = snd_ctl_rawmidi_info(ctl, info)) < 0) {
135 error("control digital audio playback info (%s): %s", snd_ctl_name(ctl), snd_strerror(err));
136 return err;
137 }
138 if (subfirst) {
139 printf(" subdevices:\n");
140 subfirst = false;
141 }
142 printf(" - subdevice: %d\n name: %s\n",
143 idx, snd_rawmidi_info_get_subdevice_name(info));
144 }
145 }
146 #endif
147 return 0;
148 }
149
hwdep_device_list(snd_ctl_t *ctl)150 static int hwdep_device_list(snd_ctl_t *ctl)
151 {
152 #ifdef __ALSA_HWDEP_H
153 int err, dev;
154 snd_hwdep_info_t *info;
155 snd_hwdep_info_alloca(&info);
156 bool first;
157
158 dev = -1;
159 first = true;
160 while (1) {
161 if ((err = snd_ctl_hwdep_next_device(ctl, &dev)) < 0) {
162 error("snd_ctl_pcm_next_device");
163 return err;
164 }
165 if (dev < 0)
166 break;
167 snd_hwdep_info_set_device(info, dev);
168 if ((err = snd_ctl_hwdep_info(ctl, info)) < 0) {
169 if (err != -ENOENT)
170 return err;
171 continue;
172 }
173 if (first) {
174 printf(" hwdep:\n");
175 first = false;
176 }
177 printf(" - device: %d\n id: %s\n name: %s\n iface: %d\n",
178 dev,
179 snd_hwdep_info_get_id(info),
180 snd_hwdep_info_get_name(info),
181 snd_hwdep_info_get_iface(info));
182 }
183 #endif
184 return 0;
185 }
186
card_info(snd_ctl_t *ctl)187 static int card_info(snd_ctl_t *ctl)
188 {
189 snd_ctl_card_info_t *info;
190 snd_ctl_elem_list_t *clist;
191 int err;
192
193 snd_ctl_card_info_alloca(&info);
194 snd_ctl_elem_list_alloca(&clist);
195
196 if ((err = snd_ctl_card_info(ctl, info)) < 0) {
197 error("Control device %s hw info error: %s", snd_ctl_name(ctl), snd_strerror(err));
198 return err;
199 }
200 printf("#\n# Sound card\n#\n");
201 printf("- card: %i\n id: %s\n name: %s\n longname: %s\n",
202 snd_ctl_card_info_get_card(info),
203 snd_ctl_card_info_get_id(info),
204 snd_ctl_card_info_get_name(info),
205 snd_ctl_card_info_get_longname(info));
206 printf(" driver_name: %s\n", snd_ctl_card_info_get_driver(info));
207 printf(" mixer_name: %s\n", snd_ctl_card_info_get_mixername(info));
208 printf(" components: %s\n", snd_ctl_card_info_get_components(info));
209 if ((err = snd_ctl_elem_list(ctl, clist)) < 0) {
210 error("snd_ctl_elem_list failure: %s", snd_strerror(err));
211 } else {
212 printf(" controls_count: %i\n", snd_ctl_elem_list_get_count(clist));
213 }
214 return err;
215 }
216
general_card_info(int cardno)217 int general_card_info(int cardno)
218 {
219 snd_ctl_t *ctl;
220 char dev[16];
221 bool first;
222 int err;
223
224 snprintf(dev, sizeof(dev), "hw:%i", cardno);
225 if ((err = snd_ctl_open(&ctl, dev, 0)) < 0) {
226 error("Control device %s open error: %s", dev, snd_strerror(err));
227 return err;
228 }
229 err = card_info(ctl);
230
231 first = true;
232 if (err >= 0)
233 err = pcm_device_list(ctl, SND_PCM_STREAM_PLAYBACK, &first);
234 if (err >= 0)
235 err = pcm_device_list(ctl, SND_PCM_STREAM_CAPTURE, &first);
236
237 first = true;
238 if (err >= 0)
239 err = rawmidi_device_list(ctl, SND_RAWMIDI_STREAM_INPUT, &first);
240 if (err >= 0)
241 err = rawmidi_device_list(ctl, SND_RAWMIDI_STREAM_OUTPUT, &first);
242
243 if (err >= 0)
244 err = hwdep_device_list(ctl);
245 snd_ctl_close(ctl);
246 return err;
247 }
248
general_info(const char *cardname)249 int general_info(const char *cardname)
250 {
251 struct snd_card_iterator iter;
252 int err;
253
254 err = snd_card_iterator_sinit(&iter, cardname);
255 if (err < 0)
256 return err;
257 while (snd_card_iterator_next(&iter)) {
258 if ((err = general_card_info(iter.card)))
259 return err;
260 }
261 return snd_card_iterator_error(&iter);
262 }
263