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 |
