Changeset 3687

Show
Ignore:
Timestamp:
02/13/06 18:29:49 (8 years ago)
Author:
piers
Message:

Changes: auddev.c, configure.in, auddev_alsa.[ch]

auddev: Changed DEF's to match standard RAT style Audio device configuration
alsa: Fixed ALSA for UCL-RAT

Modified Sample selection to be more lenient
Added ALSA "default" device for use by ALSA plugins
Added preliminary support for

 http://alsa.opensrc.org/index.php?action=find&find=emu10k1

(e.g. Audigy) style cards (with no "Capture" dev).

Location:
rat/trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • rat/trunk/auddev.c

    r3667 r3687  
    239239        }, 
    240240#endif /* HAVE_OSPREY_AUDIO */ 
    241 #ifdef HAVE_LIBASOUND 
     241#ifdef HAVE_ALSA_AUDIO 
    242242        { 
    243243                alsa_audio_init, 
     
    270270                alsa_audio_supports 
    271271        }, 
    272 #endif /* HAVE_LIBASOUND */ 
     272#endif /* HAVE_ALSA_AUDIO */ 
    273273#ifdef HAVE_OSS_AUDIO 
    274274        { 
  • rat/trunk/auddev_alsa.c

    r3669 r3687  
    2020#define ALSA_PCM_NEW_SW_PARAMS_API 
    2121#include <alsa/asoundlib.h> 
     22#include <stdio.h> 
     23#include <stdarg.h> 
    2224 
    2325#include "config_unix.h" 
     
    3941    int card_number; 
    4042    char *pcm_device; 
     43    char *pcm_mixer; 
    4144} RatCardInfo; 
    4245 
     
    108111    current.tx.handle = NULL; 
    109112    current.rx.handle = NULL; 
     113    current.mixer =  NULL; 
    110114    current.index = -1; 
    111115    current.info = NULL; 
     
    239243    fprintf(stderr, msg ": %s\n", snd_strerror(err)); \ 
    240244    snd_pcm_close(stream->handle); \ 
     245    stream->handle=NULL; \ 
    241246    return FALSE; \ 
    242247  } \ 
     
    247252    { 
    248253    int err; 
     254    int dir=0; 
    249255    size_t bsize; 
    250256    snd_pcm_uframes_t frames; 
     
    252258    snd_pcm_hw_params_t *hw_params; 
    253259    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;   
    254264 
    255265    err = snd_pcm_open(&stream->handle, info->pcm_device, 
     
    277287    rrate = fmt->sample_rate; 
    278288    err = snd_pcm_hw_params_set_rate_near (stream->handle, hw_params, 
    279                                            &rrate, 0); 
     289                                           &rrate, &dir); 
    280290    CHECKOPENERR("Failed to set sample rate"); 
    281291    if (rrate != fmt->sample_rate) { 
     
    291301    bsize = snd_pcm_format_size (mapformat(fmt->encoding), 
    292302                                 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 
    293306    frames = bsize; 
     307    debug_msg("Bsize == %d\n", bsize); 
    294308    err = snd_pcm_hw_params_set_buffer_size_near(stream->handle, hw_params, 
    295309                                                 &frames); 
     
    299313    debug_msg("Buffer == %d\n", stream->buffer_size); 
    300314 
    301     frames = bsize / 2; 
     315    frames = stream->buffer_size / 2; 
    302316    err = snd_pcm_hw_params_set_period_size_near(stream->handle, hw_params, 
    303                                                  &frames, 0); 
     317                                                 &frames, &dir); 
     318    stream->buffer_size = frames; 
    304319    CHECKOPENERR("Failed to set period size"); 
    305320 
     
    320335    CHECKOPENERR("Failed to set threshold value"); 
    321336 
    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); 
    323338    CHECKOPENERR("Failed to set min available value"); 
    324339 
    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); 
    326341    CHECKOPENERR("Failed to set xfer align value"); 
    327342 
     
    342357    fprintf(stderr, msg ": %s\n", snd_strerror(err)); \ 
    343358    snd_mixer_close(current.mixer); \ 
     359    current.mixer=NULL; \ 
    344360    return FALSE; \ 
    345361  } \ 
     
    350366static int open_volume_ctl(char *name, snd_mixer_elem_t **ctl) 
    351367{ 
    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; 
    386410} 
    387411 
     
    391415static int porder(const void *a, const void *b) 
    392416{ 
    393     return (((const port_t *)a)->priority - ((const port_t *)b)->priority); 
     417    return (((port_t*)a)->priority - ((port_t*)b)->priority); 
    394418} 
    395419 
     
    404428 
    405429    // 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"); 
    407433    CHECKOPENERR("Failed to attach mixer"); 
    408434 
     
    425451    // can be flipped between. 
    426452    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)) 
    429455    { 
    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; 
    465486        } 
    466        
     487        num_iports++; 
     488      } 
    467489    } 
    468490 
     
    474496        iports[i].details.port = i; 
    475497    } 
    476  
    477498 
    478499    return TRUE; 
     
    490511    dump_audio_format(outfmt); 
    491512     
     513    //clear_current(); 
    492514    if (current.tx.handle != NULL) { 
    493515        fprintf(stderr, "Attempt to open a device while another is open\n"); 
     
    498520    current.bytes_per_block = infmt->bytes_per_block; 
    499521 
     522        fprintf(stderr, "to open device for playback\n"); 
    500523    if (!open_stream(current.info, &current.tx, 
    501524                     SND_PCM_STREAM_PLAYBACK, outfmt)) { 
     525        alsa_audio_close(ad);  
    502526        fprintf(stderr, "Failed to open device for playback\n"); 
    503527        return FALSE; 
    504528    } 
     529        fprintf(stderr, "to open device for capture\n"); 
    505530    if (!open_stream(current.info, &current.rx, 
    506531                     SND_PCM_STREAM_CAPTURE, infmt)) { 
     532        alsa_audio_close(ad);  
    507533        fprintf(stderr, "Failed to open device for capture\n"); 
    508534        return FALSE; 
    509535    } 
    510536 
    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    } 
    512542 
    513543    err = snd_pcm_prepare(current.tx.handle); 
     
    535565    debug_msg("Closing device \"%s\"\n", current.info->name); 
    536566 
    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    } 
    546582 
    547583    clear_current(); 
     
    605641    debug_msg("Set igain %d %d\n", ad, vol); 
    606642 
     643    err = snd_mixer_selem_set_playback_switch_all(current.txgain, 1); 
     644    VCHECKERR("Failed to switch on playback volume"); 
     645 
    607646    err = snd_mixer_selem_set_playback_volume_all(current.txgain, vol); 
    608647    VCHECKERR("Couldn't set mixer playback volume"); 
    609648 
    610     err = snd_mixer_selem_set_playback_switch_all(current.txgain, 1); 
    611     VCHECKERR("Failed to switch on playback volume"); 
    612649} 
    613650 
     
    660697        err = snd_pcm_prepare(current.rx.handle); 
    661698        CHECKERR("Can't recover from capture overrun"); 
     699    err = snd_pcm_start(current.rx.handle); 
     700    CHECKERR("Failed to start PCM capture"); 
    662701        return FALSE; 
    663702 
     
    922961    int err, cindex = 0; 
    923962    char card[128]; 
     963    // Ptr to ratCards array 
    924964    RatCardInfo *ratCard; 
    925965 
    926966    debug_msg("ALSA get device count\n"); 
    927              
     967 
     968    snd_ctl_card_info_alloca(&ctl_info); 
    928969    do { 
    929970        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); 
    932973 
    933974        if (err == 0) { 
     
    935976            ratCard = ratCards + cindex; 
    936977            ratCard->card_number = cindex; 
     978            ratCard->pcm_mixer = strdup(card); 
    937979            sprintf (card , "plughw:%d", cindex); 
    938980            ratCard->pcm_device = strdup(card); 
    939981 
    940             snd_ctl_card_info_alloca(&ctl_info); 
    941982            if ((err = snd_ctl_card_info (ctl_handle, ctl_info) < 0)) { 
    942983                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            } 
    945992            snprintf(card, sizeof(card), "ALSA %d: %s", cindex, 
    946993                     snd_ctl_card_info_get_name (ctl_info)); 
    947994            ratCard->name = strdup (card); 
    948             debug_msg("  Got card %s\n", ratCard->name); 
     995            debug_msg("Got ALSA card %s\n", ratCard->name); 
    949996     
    950997            snd_ctl_close(ctl_handle); 
    951 } 
     998        } 
    952999        cindex++; 
    9531000 
    9541001    } 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    } 
    9551023 
    9561024    nRatCards = cindex - 1; 
  • rat/trunk/auddev_alsa.h

    r3667 r3687  
    2222/* Define some tuneables: */ 
    2323 
    24 /* Buffer length, in fractions of a second.  This value is used to 
     24/* Buffer length, in milliseconds.  This value is used to 
    2525 * divide the sample-rate to define the buffer-size. */ 
    26 #define RAT_ALSA_BUFFER_DIVISOR 6 
     26#define RAT_ALSA_BUFFER_DIVISOR 80 
    2727 
    2828// External prototypes 
  • rat/trunk/configure.in

    r3670 r3687  
    11dnl UCL RAT configure script. 
    2 dnl $Header$ 
     2dnl $Header: /cs/research/mice/starship/src/local/CVS_repository/rat/configure.in,v 1.54 2004/11/16 14:39:36 ucaccsp Exp $ 
    33dnl 
    44dnl Process this file with GNU autoconf to generate a configure script. 
     
    188188        ]) 
    189189        # Do we have ALSA? 
    190         AC_CHECK_HEADER(alsa/asoundlib.h,[ 
     190        AC_CHECK_HEADER(sys/asoundlib.h,[ 
    191191                AU_OBJ="$AU_OBJ auddev_alsa.o" 
    192                 AU_LIB="$AU_LIB /usr/lib/libasound.a" 
     192                AU_LIB="$AU_LIB -lasound" 
    193193                AC_DEFINE(HAVE_ALSA_AUDIO) 
    194194                # HAVE_OSS_AUDIO is defined so that the ALSA OSS emulation