1
|
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
|