⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pa_linux_alsa.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    snd_pcm_hw_params_alloca( &hwParams );    snd_pcm_hw_params_any( pcm, hwParams );    *canMmap = snd_pcm_hw_params_test_access( pcm, hwParams, SND_PCM_ACCESS_MMAP_INTERLEAVED ) >= 0 ||            snd_pcm_hw_params_test_access( pcm, hwParams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED ) >= 0;    if( defaultSr >= 0 )    {        /* Could be that the device opened in one mode supports samplerates that the other mode wont have,         * so try again .. */        if( SetApproximateSampleRate( pcm, hwParams, defaultSr ) < 0 )        {            defaultSr = -1.;            PA_DEBUG(( "%s: Original default samplerate failed, trying again ..\n", __FUNCTION__ ));        }    }    if( defaultSr < 0. )           /* Default sample rate not set */    {        unsigned int sampleRate = 44100;        /* Will contain approximate rate returned by alsa-lib */        if( snd_pcm_hw_params_set_rate_near( pcm, hwParams, &sampleRate, NULL ) < 0)        {            result = paUnanticipatedHostError;            goto error;        }        ENSURE_( GetExactSampleRate( hwParams, &defaultSr ), paUnanticipatedHostError );    }        ENSURE_( snd_pcm_hw_params_get_channels_min( hwParams, &minChans ), paUnanticipatedHostError );    ENSURE_( snd_pcm_hw_params_get_channels_max( hwParams, &maxChans ), paUnanticipatedHostError );    assert( maxChans <= INT_MAX );    assert( maxChans > 0 );    /* Weird linking issue could cause wrong version of ALSA symbols to be called,                                   resulting in zeroed values */    /* XXX: Limit to sensible number (ALSA plugins accept a crazy amount of channels)? */    if( isPlug && maxChans > 128 )    {        maxChans = 128;        PA_DEBUG(( "%s: Limiting number of plugin channels to %u\n", __FUNCTION__, maxChans ));    }    /* TWEAKME:     *     * Giving values for default min and max latency is not     * straightforward.  Here are our objectives:     *     *         * for low latency, we want to give the lowest value     *         that will work reliably.  This varies based on the     *         sound card, kernel, CPU, etc.  I think it is better     *         to give sub-optimal latency than to give a number     *         too low and cause dropouts.  My conservative     *         estimate at this point is to base it on 4096-sample     *         latency at 44.1 kHz, which gives a latency of 23ms.     *         * for high latency we want to give a large enough     *         value that dropouts are basically impossible.  This     *         doesn't really require as much tweaking, since     *         providing too large a number will just cause us to     *         select the nearest setting that will work at stream     *         config time.     */    ENSURE_( snd_pcm_hw_params_set_buffer_size_near( pcm, hwParams, &lowLatency ), paUnanticipatedHostError );    /* Have to reset hwParams, to set new buffer size */    ENSURE_( snd_pcm_hw_params_any( pcm, hwParams ), paUnanticipatedHostError );     ENSURE_( snd_pcm_hw_params_set_buffer_size_near( pcm, hwParams, &highLatency ), paUnanticipatedHostError );    *minChannels = (int)minChans;    *maxChannels = (int)maxChans;    *defaultSampleRate = defaultSr;    *defaultLowLatency = (double) lowLatency / *defaultSampleRate;    *defaultHighLatency = (double) highLatency / *defaultSampleRate;end:    snd_pcm_close( pcm );    return result;error:    goto end;}/* Initialize device info with invalid values (maxInputChannels and maxOutputChannels are set to zero since these indicate * wether input/output is available) */static void InitializeDeviceInfo( PaDeviceInfo *deviceInfo ){    deviceInfo->structVersion = -1;    deviceInfo->name = NULL;    deviceInfo->hostApi = -1;    deviceInfo->maxInputChannels = 0;    deviceInfo->maxOutputChannels = 0;    deviceInfo->defaultLowInputLatency = -1.;    deviceInfo->defaultLowOutputLatency = -1.;    deviceInfo->defaultHighInputLatency = -1.;    deviceInfo->defaultHighOutputLatency = -1.;    deviceInfo->defaultSampleRate = -1.;}/* Helper struct */typedef struct{    char *alsaName;    char *name;    int isPlug;    int hasPlayback;    int hasCapture;} HwDevInfo;HwDevInfo predefinedNames[] = {    { "center_lfe", NULL, 0, 1, 0 },/* { "default", NULL, 0, 1, 0 }, *//* { "dmix", NULL, 0, 1, 0 }, *//* { "dpl", NULL, 0, 1, 0 }, *//* { "dsnoop", NULL, 0, 1, 0 }, */    { "front", NULL, 0, 1, 0 },    { "iec958", NULL, 0, 1, 0 },/* { "modem", NULL, 0, 1, 0 }, */    { "rear", NULL, 0, 1, 0 },    { "side", NULL, 0, 1, 0 },/*     { "spdif", NULL, 0, 0, 0 }, */    { "surround40", NULL, 0, 1, 0 },    { "surround41", NULL, 0, 1, 0 },    { "surround50", NULL, 0, 1, 0 },    { "surround51", NULL, 0, 1, 0 },    { "surround71", NULL, 0, 1, 0 },    { NULL, NULL, 0, 1, 0 }};static const HwDevInfo *FindDeviceName( const char *name ){    int i;    for( i = 0; predefinedNames[i].alsaName; i++ )    {	if( strcmp( name, predefinedNames[i].alsaName ) == 0 )	{	    return &predefinedNames[i];	}    }    return NULL;}static PaError PaAlsa_StrDup( PaAlsaHostApiRepresentation *alsaApi,        char **dst,        const char *src){    PaError result = paNoError;    int len = strlen( src ) + 1;    /* PA_DEBUG(("PaStrDup %s %d\n", src, len)); */    PA_UNLESS( *dst = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ),            paInsufficientMemory );    strncpy( *dst, src, len );error:    return result;}/* Disregard some standard plugins */static int IgnorePlugin( const char *pluginId ){    static const char *ignoredPlugins[] = {"hw", "plughw", "plug", "dsnoop", "tee",        "file", "null", "shm", "cards", "rate_convert", NULL};    int i = 0;    while( ignoredPlugins[i] )    {        if( !strcmp( pluginId, ignoredPlugins[i] ) )        {            return 1;        }        ++i;    }    return 0;}/* Wrapper around snd_pcm_open which repeatedly retries opening a device for up to a second * if it is busy. This is because dmix may temporarily hold on to a device after it (dmix) * has been opened and closed. */static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode ){    int tries = 0;    int ret = snd_pcm_open( pcmp, name, stream, mode );    for( tries = 0; tries < 100 && -EBUSY == ret; ++tries )    {        Pa_Sleep( 10 );        ret = snd_pcm_open( pcmp, name, stream, mode );        if( -EBUSY != ret )        {            PA_DEBUG(( "%s: Successfully opened initially busy device after %d tries\n",                        __FUNCTION__, tries ));        }    }    if( -EBUSY == ret )    {        PA_DEBUG(( "%s: Failed to open busy device\n",                    __FUNCTION__ ));    }    return ret;}static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* deviceName, int blocking,        PaAlsaDeviceInfo* devInfo, int* devIdx ){    PaError result = 0;    PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo;    snd_pcm_t *pcm;    int canMmap = -1;    PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;    /* Zero fields */    InitializeDeviceInfo( baseDeviceInfo );    /* to determine device capabilities, we must open the device and query the     * hardware parameter configuration space */    /* Query capture */    if( deviceName->hasCapture &&            OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE, blocking )            >= 0 )    {        if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, blocking, devInfo,                    &canMmap ) != paNoError )        {            /* Error */            PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__, deviceName->alsaName));            goto end;        }    }    /* Query playback */    if( deviceName->hasPlayback &&            OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK, blocking )            >= 0 )    {        if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, blocking, devInfo,                    &canMmap ) != paNoError )        {            /* Error */            PA_DEBUG(("%s: Failed groping %s for playback\n", __FUNCTION__, deviceName->alsaName));            goto end;        }    }    if( 0 == canMmap )    {        PA_DEBUG(("%s: Device %s doesn't support mmap\n", __FUNCTION__, deviceName->alsaName));        goto end;    }    baseDeviceInfo->structVersion = 2;    baseDeviceInfo->hostApi = alsaApi->hostApiIndex;    baseDeviceInfo->name = deviceName->name;    devInfo->alsaName = deviceName->alsaName;    devInfo->isPlug = deviceName->isPlug;    /* A: Storing pointer to PaAlsaDeviceInfo object as pointer to PaDeviceInfo object.     * Should now be safe to add device info, unless the device supports neither capture nor playback     */    if( baseDeviceInfo->maxInputChannels > 0 || baseDeviceInfo->maxOutputChannels > 0 )    {        /* Make device default if there isn't already one or it is the ALSA "default" device */        if( baseApi->info.defaultInputDevice == paNoDevice && baseDeviceInfo->maxInputChannels > 0 )            baseApi->info.defaultInputDevice = *devIdx;        if( (baseApi->info.defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName,                        "default" )) && baseDeviceInfo->maxOutputChannels > 0 )        {            baseApi->info.defaultOutputDevice = *devIdx;            PA_DEBUG(("Default output device: %s\n", deviceName->name));        }        PA_DEBUG(("%s: Adding device %s: %d\n", __FUNCTION__, deviceName->name, *devIdx));        baseApi->deviceInfos[*devIdx] = (PaDeviceInfo *) devInfo;        (*devIdx) += 1;    }end:    return result;}/* Build PaDeviceInfo list, ignore devices for which we cannot determine capabilities (possibly busy, sigh) */static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ){    PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;    PaAlsaDeviceInfo *deviceInfoArray;    int cardIdx = -1, devIdx = 0;    snd_ctl_card_info_t *cardInfo;    PaError result = paNoError;    size_t numDeviceNames = 0, maxDeviceNames = 1, i;    HwDevInfo *hwDevInfos = NULL;    snd_config_t *topNode = NULL;    snd_pcm_info_t *pcmInfo;    int res;    int blocking = SND_PCM_NONBLOCK;    char alsaCardName[50];    if( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) && atoi( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) ) )        blocking = 0;    /* These two will be set to the first working input and output device, respectively */    baseApi->info.defaultInputDevice = paNoDevice;    baseApi->info.defaultOutputDevice = paNoDevice;    /* Gather info about hw devices     * snd_card_next() modifies the integer passed to it to be:     *      the index of the first card if the parameter is -1     *      the index of the next card if the parameter is the index of a card     *      -1 if there are no more cards     *     * The function itself returns 0 if it succeeded. */    cardIdx = -1;    snd_ctl_card_info_alloca( &cardInfo );    snd_pcm_info_alloca( &pcmInfo );    while( snd_card_next( &cardIdx ) == 0 && cardIdx >= 0 )    {        char *cardName;        int devIdx = -1;        snd_ctl_t *ctl;        char buf[50];        snprintf( alsaCardName, sizeof (alsaCardName), "hw:%d", cardIdx );        /* Acquire name of card */        if( snd_ctl_open( &ctl, alsaCardName, 0 ) < 0 )        {            /* Unable to open card :( */            PA_DEBUG(( "%s: Unable to open device %s\n", __FUNCTION__, alsaCardName ));            continue;        }        snd_ctl_card_info( ctl, cardInfo );        PA_ENSURE( PaAlsa_StrDup( alsaApi, &cardName, snd_ctl_card_info_get_name( cardInfo )) );        while( snd_ctl_pcm_next_device( ctl, &devIdx ) == 0 && devIdx >= 0 )        {            char *alsaDeviceName, *deviceName;            size_t len;            int hasPlayback = 0, hasCapture = 0;            snprintf( buf, sizeof (buf), "hw:%d,%d", cardIdx, devIdx );            /* Obtain info about this particular device */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -