Mercurial > hg > audiostuff
comparison alsacap.c @ 1:9cadc470e3da
reorganize, add more
author | pmeerw@pan |
---|---|
date | Fri, 30 Oct 2009 23:07:52 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:deadffdf5d60 | 1:9cadc470e3da |
---|---|
1 /* | |
2 * ALSA parameter test program | |
3 * | |
4 * compile with: gcc -o alsacap alsacap.c -lasound | |
5 */ | |
6 | |
7 | |
8 /*============================================================================ | |
9 Includes | |
10 ============================================================================*/ | |
11 | |
12 #include <stdlib.h> | |
13 #include <stdio.h> | |
14 #include <alsa/asoundlib.h> | |
15 #include <errno.h> | |
16 #include <string.h> | |
17 #include <ctype.h> | |
18 | |
19 /*============================================================================ | |
20 Constant and type definitions | |
21 ============================================================================*/ | |
22 | |
23 #define RATE_KHZ_LIMIT 200 | |
24 | |
25 #define HWP_END 0 | |
26 #define HWP_RATE 1 | |
27 #define HWP_NCH 2 | |
28 #define HWP_FORMAT 3 | |
29 #define SIZE_HWP 7 | |
30 | |
31 typedef struct { | |
32 int recdevices, verbose, card, dev; | |
33 char *device; | |
34 int hwparams[SIZE_HWP]; | |
35 } | |
36 aiopts; | |
37 | |
38 | |
39 /*============================================================================ | |
40 Global variables | |
41 ============================================================================*/ | |
42 | |
43 static snd_ctl_t *handle= NULL; | |
44 static snd_pcm_t *pcm= NULL; | |
45 static snd_ctl_card_info_t *info; | |
46 static snd_pcm_info_t *pcminfo; | |
47 static snd_pcm_hw_params_t *pars; | |
48 static snd_pcm_format_mask_t *fmask; | |
49 | |
50 | |
51 /*============================================================================ | |
52 Prototypes | |
53 ============================================================================*/ | |
54 | |
55 void usagemsg(int code); | |
56 void errnumarg(char optchar); | |
57 void errarg(char optchar); | |
58 void errtoomany(); | |
59 | |
60 void scancards(snd_pcm_stream_t stream, int thecard, int thedev); | |
61 int sc_errcheck(int retval, const char *doingwhat, int cardnr, int devnr); | |
62 | |
63 void testconfig(snd_pcm_stream_t stream, const char *device, const int *hwpars); | |
64 void tc_errcheck(int retval, const char *doingwhat); | |
65 | |
66 const char *alsaerrstr(const int errcode); | |
67 const char *dirstr(int dir); | |
68 | |
69 int parse_alsaformat(const char *fmtstr); | |
70 const char *alsafmtstr(int fmtnum); | |
71 | |
72 void printfmtmask(const snd_pcm_format_mask_t *fmask); | |
73 | |
74 | |
75 /*============================================================================ | |
76 Main program | |
77 ============================================================================*/ | |
78 | |
79 int main(int argc, char **argv) | |
80 { | |
81 aiopts options= { 0, 1, -1, -1, NULL }; | |
82 snd_pcm_stream_t stream; | |
83 char *argpar; | |
84 int argind, hwpind; | |
85 | |
86 snd_ctl_card_info_alloca(&info); | |
87 snd_pcm_info_alloca(&pcminfo); | |
88 snd_pcm_hw_params_alloca(&pars); | |
89 snd_pcm_format_mask_alloca(&fmask); | |
90 | |
91 hwpind= 0; | |
92 for( argind= 1; argind< argc; ++argind ) | |
93 { | |
94 if( argv[argind][0]!='-' ) { | |
95 fprintf(stderr, "Unrecognised command-line argument `%s'.\n", argv[argind]); | |
96 usagemsg(1); | |
97 } | |
98 if( argv[argind][2] ) argpar= argv[argind]+2; | |
99 else { | |
100 if( argind+1 >= argc ) argpar= NULL; | |
101 else argpar= argv[argind+1]; | |
102 } | |
103 if( argv[argind][1]=='h' || !strcmp(argv[argind]+1, "-help") ) | |
104 usagemsg(0); | |
105 else if( argv[argind][1]=='R' ) { | |
106 options.recdevices= 1; | |
107 argpar= NULL; // set to NULL if unused to keep track of next arg index | |
108 } | |
109 else if( argv[argind][1]=='C' ) { | |
110 if( !argpar || !isdigit(*argpar) ) errnumarg('C'); | |
111 options.card= strtol(argpar, NULL, 0); | |
112 } | |
113 else if( argv[argind][1]=='D' ) { | |
114 if( !argpar || !isdigit(*argpar) ) errnumarg('D'); | |
115 options.dev= strtol(argpar, NULL, 0); | |
116 } | |
117 else if( argv[argind][1]=='d' ) { | |
118 if( !argpar ) errarg('d'); | |
119 options.device= argpar; | |
120 } | |
121 else if( argv[argind][1]=='r' ) { | |
122 if( !argpar || !isdigit(*argpar) ) errnumarg('r'); | |
123 if( hwpind+3 > SIZE_HWP ) errtoomany(); | |
124 options.hwparams[hwpind++]= HWP_RATE; | |
125 options.hwparams[hwpind]= strtol(argpar, NULL, 0); | |
126 if( options.hwparams[hwpind] <= RATE_KHZ_LIMIT ) | |
127 options.hwparams[hwpind] *= 1000; // sanity check: Hz or kHz ? | |
128 ++hwpind; | |
129 } | |
130 else if( argv[argind][1]=='c' ) { | |
131 if( !argpar || !isdigit(*argpar) ) errnumarg('c'); | |
132 if( hwpind+3 > SIZE_HWP ) errtoomany(); | |
133 options.hwparams[hwpind++]= HWP_NCH; | |
134 options.hwparams[hwpind++]= strtol(argpar, NULL, 0); | |
135 } | |
136 else if( argv[argind][1]=='f' ) { | |
137 if( !argpar ) errarg('f'); | |
138 if( hwpind+3 > SIZE_HWP ) errtoomany(); | |
139 options.hwparams[hwpind++]= HWP_FORMAT; | |
140 options.hwparams[hwpind++]= parse_alsaformat(argpar); | |
141 } | |
142 else { | |
143 fprintf(stderr, "Unrecognised command-line option `%s'.\n", argv[argind]); | |
144 usagemsg(1); | |
145 } | |
146 if( argpar && !argv[argind][2] ) | |
147 ++argind; // additional increment if separate parameter argument was used | |
148 } | |
149 options.hwparams[hwpind]= HWP_END; | |
150 if( options.dev >= 0 && options.card < 0 ) { | |
151 fprintf(stderr, "The card has to be specified with -C if a device number is given (-D).\n"); | |
152 exit(1); | |
153 } | |
154 if( options.device && (options.card>=0 || options.dev>=0) ) { | |
155 fprintf(stderr, "Specifying a device name (-d) and a card and possibly device number (-C, -D) is mutually exclusive.\n"); | |
156 exit(1); | |
157 } | |
158 stream= options.recdevices? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK; | |
159 | |
160 if( !options.device ) | |
161 scancards(stream, options.card, options.dev); | |
162 else | |
163 testconfig(stream, options.device, options.hwparams); | |
164 | |
165 exit(0); | |
166 } | |
167 | |
168 | |
169 | |
170 /*============================================================================ | |
171 Usage message and command-line argument error functions | |
172 ============================================================================*/ | |
173 | |
174 void usagemsg(int code) | |
175 { | |
176 fprintf(stderr, "Usage: alsacap [-R] [-C <card #> [-D <device #>]]\n" | |
177 " alsacap [-R] -d <device name> [-r <rate>|-c <# of channels>|-f <sample format>]...\n" | |
178 "ALSA capability lister.\n" | |
179 "First form: Scans one or all soundcards known to ALSA for devices, \n" | |
180 "subdevices and parameter ranges. -R causes a scan for recording\n" | |
181 "rather than playback devices. The other options specify the sound\n" | |
182 "card and possibly the device by number.\n" | |
183 "Second form: Displays ranges of configuration parameters for the given\n" | |
184 "ALSA device. Unlike with the first form, a non-hardware device may be\n" | |
185 "given. Up to three optional command-line arguments fix the rate,\n" | |
186 "number of channels and sample format in the order in which they are\n" | |
187 "given. The remaining parameter ranges are output. If unique, the\n" | |
188 "number of significant bits of the sample values is output. (Some\n" | |
189 "sound cards ignore some of the bits.)\n"); | |
190 exit(code); | |
191 } | |
192 | |
193 void errnumarg(char optchar) | |
194 { | |
195 fprintf(stderr, "The -%c option requires a numerical argument! Aborting.\n", optchar); | |
196 exit(1); | |
197 } | |
198 | |
199 void errarg(char optchar) | |
200 { | |
201 fprintf(stderr, "The -%c option requires an argument! Aborting.\n", optchar); | |
202 exit(1); | |
203 } | |
204 | |
205 void errtoomany() | |
206 { | |
207 fprintf(stderr, "Too many -r/-c/-f options given! (Maximum is %d.) Aborting.\n", (SIZE_HWP-1)/2); | |
208 exit(1); | |
209 } | |
210 | |
211 | |
212 /*============================================================================ | |
213 Function for scanning all cards | |
214 ============================================================================*/ | |
215 | |
216 #define HWCARDTEMPL "hw:%d" | |
217 #define HWDEVTEMPL "hw:%d,%d" | |
218 #define HWDEVLEN 32 | |
219 | |
220 void scancards(snd_pcm_stream_t stream, int thecard, int thedev) | |
221 { | |
222 char hwdev[HWDEVLEN+1]; | |
223 unsigned min, max; | |
224 int card, err, dev, subd, nsubd; | |
225 | |
226 printf("*** Scanning for %s devices", stream==SND_PCM_STREAM_CAPTURE? "recording" : "playback"); | |
227 if( thecard >= 0 ) | |
228 printf(" on card %d", thecard); | |
229 if( thedev >= 0 ) | |
230 printf(", device %d", thedev); | |
231 printf(" ***\n"); | |
232 hwdev[HWDEVLEN]= 0; | |
233 if( thecard >= 0 ) | |
234 card= thecard; | |
235 else { | |
236 card= -1; | |
237 if( snd_card_next(&card) < 0 ) | |
238 return; | |
239 } | |
240 while( card >= 0 ) | |
241 { | |
242 snprintf(hwdev, HWDEVLEN, HWCARDTEMPL, card); | |
243 err= snd_ctl_open(&handle, hwdev, 0); | |
244 if( sc_errcheck(err, "opening control interface", card, -1) ) goto nextcard; | |
245 err= snd_ctl_card_info(handle, info); | |
246 if( sc_errcheck(err, "obtaining card info", card, -1) ) { | |
247 snd_ctl_close(handle); | |
248 goto nextcard; | |
249 } | |
250 printf("Card %d, ID `%s', name `%s'\n", card, snd_ctl_card_info_get_id(info), | |
251 snd_ctl_card_info_get_name(info)); | |
252 if( thedev >= 0 ) | |
253 dev= thedev; | |
254 else { | |
255 dev= -1; | |
256 if( snd_ctl_pcm_next_device(handle, &dev) < 0 ) { | |
257 snd_ctl_close(handle); | |
258 goto nextcard; | |
259 } | |
260 } | |
261 while( dev >= 0 ) | |
262 { | |
263 snd_pcm_info_set_device(pcminfo, dev); | |
264 snd_pcm_info_set_subdevice(pcminfo, 0); | |
265 snd_pcm_info_set_stream(pcminfo, stream); | |
266 err= snd_ctl_pcm_info(handle, pcminfo); | |
267 if( thedev<0 && err == -ENOENT ) goto nextdev; | |
268 if( sc_errcheck(err, "obtaining device info", card, dev) ) goto nextdev; | |
269 nsubd= snd_pcm_info_get_subdevices_count(pcminfo); | |
270 if( sc_errcheck(nsubd, "obtaining device info", card, dev) ) goto nextdev; | |
271 printf(" Device %d, ID `%s', name `%s', %d subdevices (%d available)\n", | |
272 dev, snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_name(pcminfo), | |
273 nsubd, snd_pcm_info_get_subdevices_avail(pcminfo)); | |
274 snprintf(hwdev, HWDEVLEN, HWDEVTEMPL, card, dev); | |
275 err= snd_pcm_open(&pcm, hwdev, stream, SND_PCM_NONBLOCK); | |
276 if( sc_errcheck(err, "opening sound device", card, dev) ) goto nextdev; | |
277 err= snd_pcm_hw_params_any(pcm, pars); | |
278 if( sc_errcheck(err, "obtaining hardware parameters", card, dev) ) { | |
279 snd_pcm_close(pcm); | |
280 goto nextdev; | |
281 } | |
282 snd_pcm_hw_params_get_channels_min(pars, &min); | |
283 snd_pcm_hw_params_get_channels_max(pars, &max); | |
284 if( min == max ) | |
285 if( min == 1 ) printf(" 1 channel, "); | |
286 else printf(" %d channels, ", min); | |
287 else printf(" %u..%u channels, ", min, max); | |
288 snd_pcm_hw_params_get_rate_min(pars, &min, NULL); | |
289 snd_pcm_hw_params_get_rate_max(pars, &max, NULL); | |
290 printf("sampling rate %u..%u Hz\n Sample formats: ", min, max); | |
291 snd_pcm_hw_params_get_format_mask(pars, fmask); | |
292 printfmtmask(fmask); | |
293 snd_pcm_close(pcm); | |
294 printf("\n"); | |
295 pcm= NULL; | |
296 for( subd= 0; subd< nsubd; ++subd ) { | |
297 snd_pcm_info_set_subdevice(pcminfo, subd); | |
298 err= snd_ctl_pcm_info(handle, pcminfo); | |
299 if( sc_errcheck(err, "obtaining subdevice info", card, dev) ) goto nextdev; | |
300 printf(" Subdevice %d, name `%s'\n", subd, snd_pcm_info_get_subdevice_name(pcminfo)); | |
301 } | |
302 nextdev: | |
303 if( thedev >= 0 || snd_ctl_pcm_next_device(handle, &dev) < 0 ) | |
304 break; | |
305 } | |
306 snd_ctl_close(handle); | |
307 nextcard: | |
308 if( thecard >= 0 || snd_card_next(&card) < 0 ) | |
309 break; | |
310 } | |
311 } | |
312 | |
313 | |
314 int sc_errcheck(int retval, const char *doingwhat, int cardnr, int devnr) | |
315 { | |
316 if( retval<0 ) { | |
317 if( devnr>= 0 ) | |
318 fprintf(stderr, "Error %s for card %d, device %d: %s. Skipping.\n", doingwhat, cardnr, devnr, alsaerrstr(retval)); | |
319 else | |
320 fprintf(stderr, "Error %s for card %d: %s. Skipping.\n", doingwhat, cardnr, alsaerrstr(retval)); | |
321 return 1; | |
322 } | |
323 return 0; | |
324 } | |
325 | |
326 | |
327 | |
328 /*============================================================================ | |
329 Function for investigating device configurations | |
330 ============================================================================*/ | |
331 | |
332 void testconfig(snd_pcm_stream_t stream, const char *device, const int *hwpars) | |
333 { | |
334 unsigned min, max, param; | |
335 int err, count, dir, result; | |
336 | |
337 printf("*** Exploring configuration space of device `%s' for %s ***\n", device, | |
338 stream==SND_PCM_STREAM_CAPTURE? "recording" : "playback"); | |
339 | |
340 if (stream==SND_PCM_STREAM_CAPTURE && stream==SND_PCM_STREAM_PLAYBACK) | |
341 dir = 0; | |
342 else if (stream==SND_PCM_STREAM_CAPTURE) | |
343 dir = -1; | |
344 else | |
345 dir = 1; | |
346 | |
347 err= snd_pcm_open(&pcm, device, stream, SND_PCM_NONBLOCK); | |
348 tc_errcheck(err, "opening sound device"); | |
349 err= snd_pcm_hw_params_any(pcm, pars); | |
350 tc_errcheck(err, "initialising hardware parameters"); | |
351 for( count= 0; hwpars[count]!=HWP_END; count += 2 ) | |
352 | |
353 switch(hwpars[count]) | |
354 { | |
355 case HWP_RATE:param= hwpars[count+1]; | |
356 err= snd_pcm_hw_params_set_rate_near(pcm, pars, ¶m, &result); | |
357 if( err<0 ) | |
358 fprintf(stderr, "Could not set sampling rate to %d Hz: %s. " | |
359 "Continuing regardless.\n", hwpars[count+1], alsaerrstr(err)); | |
360 else | |
361 printf("Set sampling rate %d Hz --> got %u Hz, %s requested.\n", hwpars[count+1], param, dirstr(dir)); | |
362 break; | |
363 case HWP_NCH:err= snd_pcm_hw_params_set_channels(pcm, pars, hwpars[count+1]); | |
364 if( err<0 ) | |
365 fprintf(stderr, "Could not set # of channels to %d: %s. " | |
366 "Continuing regardless.\n", hwpars[count+1], alsaerrstr(err)); | |
367 else | |
368 printf("Set number of channels to %d.\n", hwpars[count+1]); | |
369 break; | |
370 case HWP_FORMAT:err= snd_pcm_hw_params_set_format(pcm, pars, hwpars[count+1]); | |
371 if( err<0 ) | |
372 fprintf(stderr, "Could not set sample format to %s: %s." | |
373 " Continuing regardless.\n", alsafmtstr(hwpars[count+1]), alsaerrstr(err)); | |
374 else | |
375 printf("Set sample format to %s.\n", alsafmtstr(hwpars[count+1])); | |
376 break; | |
377 default: | |
378 break; | |
379 } | |
380 if( count>0 ) | |
381 printf("Parameter ranges remaining after these settings:\n"); | |
382 snd_pcm_hw_params_get_channels_min(pars, &min); | |
383 snd_pcm_hw_params_get_channels_max(pars, &max); | |
384 if( min==max ) | |
385 if( min==1 ) | |
386 printf("1 channel\n"); | |
387 else | |
388 printf("%u channels\n", min); | |
389 else | |
390 printf("%u..%u channels\n", min, max); | |
391 snd_pcm_hw_params_get_rate_min(pars, &min, NULL); | |
392 snd_pcm_hw_params_get_rate_max(pars, &max, NULL); | |
393 if( min==max ) | |
394 printf("Sampling rate %u Hz\nSample formats: ", min); | |
395 else | |
396 printf("Sampling rate %u..%u Hz\nSample formats: ", min, max); | |
397 snd_pcm_hw_params_get_format_mask(pars, fmask); | |
398 printfmtmask(fmask); | |
399 printf("\n"); | |
400 result= snd_pcm_hw_params_get_sbits(pars); | |
401 if( result >= 0 ) // only available if bit width of all formats is the same | |
402 printf("Significant bits: %d\n", result); | |
403 snd_pcm_close(pcm); | |
404 } | |
405 | |
406 | |
407 void tc_errcheck(int retval, const char *doingwhat) | |
408 { | |
409 if( retval<0 ) { | |
410 fprintf(stderr, "Error %s: %s. Aborting.\n", doingwhat, alsaerrstr(retval)); | |
411 if( pcm ) | |
412 snd_pcm_close(pcm); | |
413 exit(1); | |
414 } | |
415 } | |
416 | |
417 | |
418 /*============================================================================ | |
419 String-building functions | |
420 ============================================================================*/ | |
421 | |
422 struct alsaerr { int err; char *msg; }; | |
423 struct alsaerr aelist[]= { | |
424 {-EBADFD, "PCM device is in a bad state"}, | |
425 {-EPIPE, "An underrun occurred"}, | |
426 {-ESTRPIPE, "A suspend event occurred"}, | |
427 {-ENOTTY, "Hotplug device has been removed"}, | |
428 {-ENODEV, "Hotplug device has been removed"}, | |
429 {-ENOENT, "Device does not exist"}, | |
430 {0, NULL} | |
431 }; | |
432 const char *alsaerrstr(const int errcode) | |
433 { | |
434 struct alsaerr *search; | |
435 | |
436 if( errcode >= 0 ) | |
437 return "No error"; | |
438 for( search= aelist; search->msg && search->err!=errcode; ++search); | |
439 if( search->msg ) | |
440 return search->msg; | |
441 else | |
442 return strerror(-errcode); | |
443 } | |
444 | |
445 | |
446 const char *dirstr(int dir) | |
447 { | |
448 if( !dir ) | |
449 return "="; | |
450 else if( dir<0 ) | |
451 return "<"; | |
452 else | |
453 return ">"; | |
454 } | |
455 | |
456 | |
457 /*============================================================================ | |
458 Functions for parsing and string output of ALSA sample formats | |
459 ============================================================================*/ | |
460 | |
461 struct fmtdef { char *fmtname; int format; }; | |
462 static struct fmtdef fmtlist[]= { | |
463 {"S8", SND_PCM_FORMAT_S8}, | |
464 {"U8", SND_PCM_FORMAT_U8}, | |
465 {"S16_LE", SND_PCM_FORMAT_S16_LE}, | |
466 {"S16_BE", SND_PCM_FORMAT_S16_BE}, | |
467 {"U16_LE", SND_PCM_FORMAT_U16_LE}, | |
468 {"U16_BE", SND_PCM_FORMAT_U16_BE}, | |
469 {"S24_LE", SND_PCM_FORMAT_S24_LE}, | |
470 {"S24_BE", SND_PCM_FORMAT_S24_BE}, | |
471 {"U24_LE", SND_PCM_FORMAT_U24_LE}, | |
472 {"U24_BE", SND_PCM_FORMAT_U24_BE}, | |
473 {"S32_LE", SND_PCM_FORMAT_S32_LE}, | |
474 {"S32_BE", SND_PCM_FORMAT_S32_BE}, | |
475 {"U32_LE", SND_PCM_FORMAT_U32_LE}, | |
476 {"U32_BE", SND_PCM_FORMAT_U32_BE}, | |
477 {"FLOAT_LE", SND_PCM_FORMAT_FLOAT_LE}, | |
478 {"FLOAT_BE", SND_PCM_FORMAT_FLOAT_BE}, | |
479 {"FLOAT64_LE", SND_PCM_FORMAT_FLOAT64_LE}, | |
480 {"FLOAT64_BE", SND_PCM_FORMAT_FLOAT64_BE}, | |
481 {"IEC958_SUBFRAME_LE", SND_PCM_FORMAT_IEC958_SUBFRAME_LE}, | |
482 {"IEC958_SUBFRAME_BE", SND_PCM_FORMAT_IEC958_SUBFRAME_BE}, | |
483 {"MU_LAW", SND_PCM_FORMAT_MU_LAW}, | |
484 {"A_LAW", SND_PCM_FORMAT_A_LAW}, | |
485 {"IMA_ADPCM", SND_PCM_FORMAT_IMA_ADPCM}, | |
486 {"MPEG", SND_PCM_FORMAT_MPEG}, | |
487 {"GSM", SND_PCM_FORMAT_GSM}, | |
488 {"SPECIAL", SND_PCM_FORMAT_SPECIAL}, | |
489 {"S24_3LE", SND_PCM_FORMAT_S24_3LE}, | |
490 {"S24_3BE", SND_PCM_FORMAT_S24_3BE}, | |
491 {"U24_3LE", SND_PCM_FORMAT_U24_3LE}, | |
492 {"U24_3BE", SND_PCM_FORMAT_U24_3BE}, | |
493 {"S20_3LE", SND_PCM_FORMAT_S20_3LE}, | |
494 {"S20_3BE", SND_PCM_FORMAT_S20_3BE}, | |
495 {"U20_3LE", SND_PCM_FORMAT_U20_3LE}, | |
496 {"U20_3BE", SND_PCM_FORMAT_U20_3BE}, | |
497 {"S18_3LE", SND_PCM_FORMAT_S18_3LE}, | |
498 {"S18_3BE", SND_PCM_FORMAT_S18_3BE}, | |
499 {"U18_3LE", SND_PCM_FORMAT_U18_3LE}, | |
500 {"U18_3BE", SND_PCM_FORMAT_U18_3BE}, | |
501 {"S16", SND_PCM_FORMAT_S16}, | |
502 {"U16", SND_PCM_FORMAT_U16}, | |
503 {"S24", SND_PCM_FORMAT_S24}, | |
504 {"U24", SND_PCM_FORMAT_U24}, | |
505 {"S32", SND_PCM_FORMAT_S32}, | |
506 {"U32", SND_PCM_FORMAT_U32}, | |
507 {"FLOAT", SND_PCM_FORMAT_FLOAT}, | |
508 {"FLOAT64", SND_PCM_FORMAT_FLOAT64}, | |
509 {"IEC958_SUBFRAME", SND_PCM_FORMAT_IEC958_SUBFRAME}, | |
510 {NULL, 0} | |
511 }; | |
512 | |
513 int parse_alsaformat(const char *fmtstr) | |
514 { | |
515 struct fmtdef *search; | |
516 | |
517 for( search= fmtlist; search->fmtname && strcmp(search->fmtname, fmtstr); ++search ); | |
518 if( !search->fmtname ) { | |
519 fprintf(stderr, "Unknown sample format `%s'. Aborting.\n", fmtstr); | |
520 exit(1); | |
521 } | |
522 return search->format; | |
523 } | |
524 | |
525 const char *alsafmtstr(int fmtnum) | |
526 { | |
527 struct fmtdef *search; | |
528 | |
529 for( search= fmtlist; search->fmtname && search->format!=fmtnum; ++search ); | |
530 if( !search->fmtname ) | |
531 return "(unknown)"; | |
532 else | |
533 return search->fmtname; | |
534 } | |
535 | |
536 | |
537 /*============================================================================ | |
538 Printout functions | |
539 ============================================================================*/ | |
540 | |
541 void printfmtmask(const snd_pcm_format_mask_t *fmask) | |
542 { | |
543 int fmt, prevformat= 0; | |
544 | |
545 for( fmt= 0; fmt <= SND_PCM_FORMAT_LAST; ++fmt ) | |
546 if( snd_pcm_format_mask_test(fmask, (snd_pcm_format_t)fmt) ) { | |
547 if( prevformat ) | |
548 printf(", "); | |
549 printf("%s", snd_pcm_format_name((snd_pcm_format_t)fmt)); | |
550 prevformat= 1; | |
551 } | |
552 if( !prevformat ) | |
553 printf("(none)"); | |
554 } | |
555 | |
556 |