Changeset 3687
- Timestamp:
- 02/13/06 18:29:49 (7 years ago)
- Location:
- rat/trunk
- Files:
-
- 4 modified
-
auddev.c (modified) (2 diffs)
-
auddev_alsa.c (modified) (23 diffs)
-
auddev_alsa.h (modified) (1 diff)
-
configure.in (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
rat/trunk/auddev.c
r3667 r3687 239 239 }, 240 240 #endif /* HAVE_OSPREY_AUDIO */ 241 #ifdef HAVE_ LIBASOUND241 #ifdef HAVE_ALSA_AUDIO 242 242 { 243 243 alsa_audio_init, … … 270 270 alsa_audio_supports 271 271 }, 272 #endif /* HAVE_ LIBASOUND*/272 #endif /* HAVE_ALSA_AUDIO */ 273 273 #ifdef HAVE_OSS_AUDIO 274 274 { -
rat/trunk/auddev_alsa.c
r3669 r3687 20 20 #define ALSA_PCM_NEW_SW_PARAMS_API 21 21 #include <alsa/asoundlib.h> 22 #include <stdio.h> 23 #include <stdarg.h> 22 24 23 25 #include "config_unix.h" … … 39 41 int card_number; 40 42 char *pcm_device; 43 char *pcm_mixer; 41 44 } RatCardInfo; 42 45 … … 108 111 current.tx.handle = NULL; 109 112 current.rx.handle = NULL; 113 current.mixer = NULL; 110 114 current.index = -1; 111 115 current.info = NULL; … … 239 243 fprintf(stderr, msg ": %s\n", snd_strerror(err)); \ 240 244 snd_pcm_close(stream->handle); \ 245 stream->handle=NULL; \ 241 246 return FALSE; \ 242 247 } \ … … 247 252 { 248 253 int err; 254 int dir=0; 249 255 size_t bsize; 250 256 snd_pcm_uframes_t frames; … … 252 258 snd_pcm_hw_params_t *hw_params; 253 259 snd_pcm_sw_params_t *sw_params; 260 /* Set avail min inside a software configuration container */ 261 /* Can we tweak this up/down?*/ 262 snd_pcm_uframes_t avail_min=4; 263 snd_pcm_uframes_t xfer_align=1; 254 264 255 265 err = snd_pcm_open(&stream->handle, info->pcm_device, … … 277 287 rrate = fmt->sample_rate; 278 288 err = snd_pcm_hw_params_set_rate_near (stream->handle, hw_params, 279 &rrate, 0);289 &rrate, &dir); 280 290 CHECKOPENERR("Failed to set sample rate"); 281 291 if (rrate != fmt->sample_rate) { … … 291 301 bsize = snd_pcm_format_size (mapformat(fmt->encoding), 292 302 fmt->sample_rate / RAT_ALSA_BUFFER_DIVISOR); 303 bsize = (fmt->sample_rate * (fmt->bits_per_sample/8) * fmt->channels* RAT_ALSA_BUFFER_DIVISOR)/ (1000); 304 //* fmt->bytes_per_block 305 293 306 frames = bsize; 307 debug_msg("Bsize == %d\n", bsize); 294 308 err = snd_pcm_hw_params_set_buffer_size_near(stream->handle, hw_params, 295 309 &frames); … … 299 313 debug_msg("Buffer == %d\n", stream->buffer_size); 300 314 301 frames = bsize / 2;315 frames = stream->buffer_size / 2; 302 316 err = snd_pcm_hw_params_set_period_size_near(stream->handle, hw_params, 303 &frames, 0); 317 &frames, &dir); 318 stream->buffer_size = frames; 304 319 CHECKOPENERR("Failed to set period size"); 305 320 … … 320 335 CHECKOPENERR("Failed to set threshold value"); 321 336 322 err = snd_pcm_sw_params_set_avail_min(stream->handle, sw_params, 4);337 err = snd_pcm_sw_params_set_avail_min(stream->handle, sw_params, avail_min); 323 338 CHECKOPENERR("Failed to set min available value"); 324 339 325 err = snd_pcm_sw_params_set_xfer_align(stream->handle, sw_params, 1);340 err = snd_pcm_sw_params_set_xfer_align(stream->handle,sw_params,xfer_align); 326 341 CHECKOPENERR("Failed to set xfer align value"); 327 342 … … 342 357 fprintf(stderr, msg ": %s\n", snd_strerror(err)); \ 343 358 snd_mixer_close(current.mixer); \ 359 current.mixer=NULL; \ 344 360 return FALSE; \ 345 361 } \ … … 350 366 static int open_volume_ctl(char *name, snd_mixer_elem_t **ctl) 351 367 { 352 snd_mixer_selem_id_t *sid; 353 int err; 354 355 snd_mixer_selem_id_alloca(&sid); 356 357 // FIXME? Find the appropriate mixer element. This feels really wrong, 358 // there has to be another way to do this. 359 snd_mixer_selem_id_set_name (sid, name); 360 361 *ctl = snd_mixer_find_selem(current.mixer, sid); 362 err = (int)*ctl; 363 CHECKOPENERR("Couldn't find mixer control element"); 364 365 if (snd_mixer_selem_has_playback_volume(*ctl)) { 366 debug_msg("Got volume control %s of type PLAY\n", name); 367 // FIXME: Does this always work? 368 snd_mixer_selem_set_playback_volume_range (*ctl, 0, 100); 369 370 err = snd_mixer_selem_set_playback_switch_all(*ctl, 1); 371 CHECKOPENERR("Failed to switch on playback volume"); 372 373 } else if (snd_mixer_selem_has_capture_volume(*ctl)) { 374 debug_msg("Got volume control %s of type CAPTURE\n", name); 375 snd_mixer_selem_set_capture_volume_range (*ctl, 0, 100); 376 377 err = snd_mixer_selem_set_capture_switch_all(*ctl, 1); 378 CHECKOPENERR("Failed to switch on capture volume"); 379 380 } else { 381 debug_msg("Unknown mixer type %s set\n", name); 382 return FALSE; 383 } 384 385 return TRUE; 368 snd_mixer_selem_id_t *sid; 369 int err=NULL; 370 371 snd_mixer_selem_id_alloca(&sid); 372 373 // FIXME? Find the appropriate mixer element. This feels really wrong, 374 // there has to be another way to do this. 375 snd_mixer_selem_id_set_index (sid, 0); 376 snd_mixer_selem_id_set_name (sid, name); 377 378 *ctl = snd_mixer_find_selem(current.mixer, sid); 379 //err = (int)*ctl; 380 //CHECKOPENERR("Couldn't find mixer control element"); 381 if (*ctl == NULL ) { 382 fprintf(stderr,"ALSA:Couldn't find mixer control element (name:%s)\n",name); 383 return FALSE; 384 } 385 386 printf("open_volume_ctl err2:%d\n",err); 387 if (snd_mixer_selem_has_playback_volume(*ctl)) { 388 debug_msg("Got volume control %s of type PLAY\n", name); 389 // FIXME: Does this always work? 390 snd_mixer_selem_set_playback_volume_range (*ctl, 0, 100); 391 392 if ( snd_mixer_selem_has_playback_switch( *ctl ) ) { 393 err = snd_mixer_selem_set_playback_switch_all(*ctl, 1); 394 CHECKOPENERR("Failed to switch on playback volume"); 395 } 396 397 } else if (snd_mixer_selem_has_capture_volume(*ctl)) { 398 debug_msg("Got volume control %s of type CAPTURE\n", name); 399 snd_mixer_selem_set_capture_volume_range (*ctl, 0, 100); 400 401 err = snd_mixer_selem_set_capture_switch_all(*ctl, 1); 402 CHECKOPENERR("Failed to switch on capture volume"); 403 404 } else { 405 debug_msg("Unknown mixer type %s set\n", name); 406 return FALSE; 407 } 408 409 return TRUE; 386 410 } 387 411 … … 391 415 static int porder(const void *a, const void *b) 392 416 { 393 return ((( const port_t *)a)->priority - ((const port_t*)b)->priority);417 return (((port_t*)a)->priority - ((port_t*)b)->priority); 394 418 } 395 419 … … 404 428 405 429 // FIXME: Attach the mixer to the default card. Is this enough? 406 err = snd_mixer_attach(current.mixer, "default"); 430 //err = snd_mixer_attach(current.mixer, "default"); 431 err = snd_mixer_attach(current.mixer, current.info->pcm_mixer); 432 // err = snd_mixer_attach(current.mixer, "hw:0,0"); 407 433 CHECKOPENERR("Failed to attach mixer"); 408 434 … … 425 451 // can be flipped between. 426 452 for (elem = snd_mixer_first_elem (current.mixer); 427 elem && (num_iports < MAX_RAT_DEVICES);428 elem = snd_mixer_elem_next (elem))453 elem && (num_iports < MAX_RAT_DEVICES); 454 elem = snd_mixer_elem_next (elem)) 429 455 { 430 if (snd_mixer_selem_is_active (elem) && 431 snd_mixer_selem_has_capture_switch(elem) && 432 snd_mixer_selem_has_capture_switch_exclusive(elem)) 433 { 434 // FIXME: It's theoretically possible that there would be more 435 // than one capture group, but RAT isn't really equipped to handle 436 // the case so we'll just ignore it for now. 437 int gid = snd_mixer_selem_get_capture_group(elem); 438 439 const char *name = snd_mixer_selem_get_name(elem); 440 441 debug_msg("Got CAPTURE element '%s' of group %d\n", name, gid); 442 443 snprintf(iports[num_iports].details.name, AUDIO_PORT_NAME_LENGTH, 444 "%s", name); 445 iports[num_iports].mixer = elem; 446 447 // The principle of least-surprise means that we should present 448 // the ports in the same order as the other drivers. As we're 449 // more flexible about retrieving the mixer ports we need to 450 // attempt to reorder the list, so we assign a priority and 451 // sort the list at the end. 452 if (strstr(name, RAT_ALSA_MIXER_MIC_NAME) == name) { 453 iports[num_iports].priority = 100; 454 } else if (strstr(name, RAT_ALSA_MIXER_LINE_NAME) == name) { 455 iports[num_iports].priority = 50; 456 } else if (strstr(name, RAT_ALSA_MIXER_CD_NAME) == name) { 457 iports[num_iports].priority = 30; 458 } else { 459 iports[num_iports].priority = 10; 460 } 461 462 463 num_iports++; 464 456 if (snd_mixer_selem_is_active (elem) && 457 snd_mixer_selem_has_capture_switch(elem) && 458 snd_mixer_selem_has_capture_switch_exclusive(elem)) 459 { 460 // FIXME: It's theoretically possible that there would be more 461 // than one capture group, but RAT isn't really equipped to handle 462 // the case so we'll just ignore it for now. 463 int gid = snd_mixer_selem_get_capture_group(elem); 464 465 const char *name = snd_mixer_selem_get_name(elem); 466 467 debug_msg("Got CAPTURE element '%s' of group %d\n", name, gid); 468 469 snprintf(iports[num_iports].details.name, AUDIO_PORT_NAME_LENGTH, 470 "%s", name); 471 iports[num_iports].mixer = elem; 472 473 // The principle of least-surprise means that we should present 474 // the ports in the same order as the other drivers. As we're 475 // more flexible about retrieving the mixer ports we need to 476 // attempt to reorder the list, so we assign a priority and 477 // sort the list at the end. 478 if (strstr(name, RAT_ALSA_MIXER_MIC_NAME) == name) { 479 iports[num_iports].priority = 100; 480 } else if (strstr(name, RAT_ALSA_MIXER_LINE_NAME) == name) { 481 iports[num_iports].priority = 50; 482 } else if (strstr(name, RAT_ALSA_MIXER_CD_NAME) == name) { 483 iports[num_iports].priority = 30; 484 } else { 485 iports[num_iports].priority = 10; 465 486 } 466 487 num_iports++; 488 } 467 489 } 468 490 … … 474 496 iports[i].details.port = i; 475 497 } 476 477 498 478 499 return TRUE; … … 490 511 dump_audio_format(outfmt); 491 512 513 //clear_current(); 492 514 if (current.tx.handle != NULL) { 493 515 fprintf(stderr, "Attempt to open a device while another is open\n"); … … 498 520 current.bytes_per_block = infmt->bytes_per_block; 499 521 522 fprintf(stderr, "to open device for playback\n"); 500 523 if (!open_stream(current.info, ¤t.tx, 501 524 SND_PCM_STREAM_PLAYBACK, outfmt)) { 525 alsa_audio_close(ad); 502 526 fprintf(stderr, "Failed to open device for playback\n"); 503 527 return FALSE; 504 528 } 529 fprintf(stderr, "to open device for capture\n"); 505 530 if (!open_stream(current.info, ¤t.rx, 506 531 SND_PCM_STREAM_CAPTURE, infmt)) { 532 alsa_audio_close(ad); 507 533 fprintf(stderr, "Failed to open device for capture\n"); 508 534 return FALSE; 509 535 } 510 536 511 setup_mixers(); 537 if (setup_mixers() == FALSE) { 538 alsa_audio_close(ad); 539 fprintf(stderr, "Failed to set mixer levels \n"); 540 return FALSE; 541 } 512 542 513 543 err = snd_pcm_prepare(current.tx.handle); … … 535 565 debug_msg("Closing device \"%s\"\n", current.info->name); 536 566 537 err = snd_pcm_close(current.tx.handle); 538 CHECKERRCONT("Error closing playback PCM"); 539 540 err = snd_pcm_close(current.rx.handle); 541 CHECKERRCONT("Error closing capture PCM"); 542 543 // Open a mixer for each of the ports 544 err = snd_mixer_close(current.mixer); 545 CHECKERRCONT("Error closing mixer"); 567 if (current.tx.handle != NULL ) { 568 err = snd_pcm_close(current.tx.handle); 569 CHECKERRCONT("Error closing playback PCM"); 570 } 571 572 if (current.rx.handle != NULL ) { 573 err = snd_pcm_close(current.rx.handle); 574 CHECKERRCONT("Error closing capture PCM"); 575 } 576 577 // Close mixer 578 if (current.mixer != NULL ) { 579 err = snd_mixer_close(current.mixer); 580 CHECKERRCONT("Error closing mixer"); 581 } 546 582 547 583 clear_current(); … … 605 641 debug_msg("Set igain %d %d\n", ad, vol); 606 642 643 err = snd_mixer_selem_set_playback_switch_all(current.txgain, 1); 644 VCHECKERR("Failed to switch on playback volume"); 645 607 646 err = snd_mixer_selem_set_playback_volume_all(current.txgain, vol); 608 647 VCHECKERR("Couldn't set mixer playback volume"); 609 648 610 err = snd_mixer_selem_set_playback_switch_all(current.txgain, 1);611 VCHECKERR("Failed to switch on playback volume");612 649 } 613 650 … … 660 697 err = snd_pcm_prepare(current.rx.handle); 661 698 CHECKERR("Can't recover from capture overrun"); 699 err = snd_pcm_start(current.rx.handle); 700 CHECKERR("Failed to start PCM capture"); 662 701 return FALSE; 663 702 … … 922 961 int err, cindex = 0; 923 962 char card[128]; 963 // Ptr to ratCards array 924 964 RatCardInfo *ratCard; 925 965 926 966 debug_msg("ALSA get device count\n"); 927 967 968 snd_ctl_card_info_alloca(&ctl_info); 928 969 do { 929 970 sprintf (card , "hw:%d", cindex); 930 err = snd_ctl_open (&ctl_handle, card, 0);931 971 debug_msg("ALSA for dev:%s\n",card); 972 err = snd_ctl_open (&ctl_handle, card, SND_CTL_NONBLOCK); 932 973 933 974 if (err == 0) { … … 935 976 ratCard = ratCards + cindex; 936 977 ratCard->card_number = cindex; 978 ratCard->pcm_mixer = strdup(card); 937 979 sprintf (card , "plughw:%d", cindex); 938 980 ratCard->pcm_device = strdup(card); 939 981 940 snd_ctl_card_info_alloca(&ctl_info);941 982 if ((err = snd_ctl_card_info (ctl_handle, ctl_info) < 0)) { 942 983 fprintf(stderr, "Card query failed: %s\n", snd_strerror(err)); 943 return 0; 944 } 984 snprintf(card, sizeof(card), "ALSA %d: Not Available", cindex); 985 ratCard->name = strdup (card); 986 debug_msg("Got failed ALSA card %s\n", ratCard->name); 987 snd_ctl_close(ctl_handle); 988 cindex++; 989 err=0; 990 continue; 991 } 945 992 snprintf(card, sizeof(card), "ALSA %d: %s", cindex, 946 993 snd_ctl_card_info_get_name (ctl_info)); 947 994 ratCard->name = strdup (card); 948 debug_msg(" Gotcard %s\n", ratCard->name);995 debug_msg("Got ALSA card %s\n", ratCard->name); 949 996 950 997 snd_ctl_close(ctl_handle); 951 }998 } 952 999 cindex++; 953 1000 954 1001 } while (err == 0); 1002 cindex--; 1003 1004 // Get ALSA "default" card - so things like dsnoop etc can work 1005 if (!snd_ctl_open(&ctl_handle, "default", SND_CTL_NONBLOCK)) { 1006 ratCard = ratCards + cindex; 1007 ratCard->card_number = cindex; 1008 ratCard->pcm_device = strdup("default"); 1009 ratCard->pcm_mixer = "default"; 1010 if ((err = snd_ctl_card_info (ctl_handle, ctl_info) < 0)) { 1011 fprintf(stderr, "ALSA default Card query failed: %s\n", snd_strerror(err)); 1012 snd_ctl_close(ctl_handle); 1013 } else { 1014 snprintf(card, sizeof(card), "ALSA default: %s", 1015 snd_ctl_card_info_get_name (ctl_info)); 1016 ratCard->name = strdup (card); 1017 debug_msg("Got \"default\" card %s\n", ratCard->name); 1018 snd_ctl_close(ctl_handle); 1019 cindex++; 1020 cindex++; 1021 } 1022 } 955 1023 956 1024 nRatCards = cindex - 1; -
rat/trunk/auddev_alsa.h
r3667 r3687 22 22 /* Define some tuneables: */ 23 23 24 /* Buffer length, in fractions of a second. This value is used to24 /* Buffer length, in milliseconds. This value is used to 25 25 * divide the sample-rate to define the buffer-size. */ 26 #define RAT_ALSA_BUFFER_DIVISOR 626 #define RAT_ALSA_BUFFER_DIVISOR 80 27 27 28 28 // External prototypes -
rat/trunk/configure.in
r3670 r3687 1 1 dnl UCL RAT configure script. 2 dnl $Header $2 dnl $Header: /cs/research/mice/starship/src/local/CVS_repository/rat/configure.in,v 1.54 2004/11/16 14:39:36 ucaccsp Exp $ 3 3 dnl 4 4 dnl Process this file with GNU autoconf to generate a configure script. … … 188 188 ]) 189 189 # Do we have ALSA? 190 AC_CHECK_HEADER( alsa/asoundlib.h,[190 AC_CHECK_HEADER(sys/asoundlib.h,[ 191 191 AU_OBJ="$AU_OBJ auddev_alsa.o" 192 AU_LIB="$AU_LIB /usr/lib/libasound.a"192 AU_LIB="$AU_LIB -lasound" 193 193 AC_DEFINE(HAVE_ALSA_AUDIO) 194 194 # HAVE_OSS_AUDIO is defined so that the ALSA OSS emulation
