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

📄 pa_linux_alsa.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            snd_pcm_info_set_device( pcmInfo, devIdx );            snd_pcm_info_set_subdevice( pcmInfo, 0 );            snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_CAPTURE );            if( snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )            {                hasCapture = 1;            }                        snd_pcm_info_set_stream( pcmInfo, SND_PCM_STREAM_PLAYBACK );            if( snd_ctl_pcm_info( ctl, pcmInfo ) >= 0 )            {                hasPlayback = 1;            }            if( !hasPlayback && !hasCapture )            {                /* Error */                continue;            }            /* The length of the string written by snprintf plus terminating 0 */            len = snprintf( NULL, 0, "%s: %s (%s)", cardName, snd_pcm_info_get_name( pcmInfo ), buf ) + 1;            PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ),                    paInsufficientMemory );            snprintf( deviceName, len, "%s: %s (%s)", cardName,                    snd_pcm_info_get_name( pcmInfo ), buf );            ++numDeviceNames;            if( !hwDevInfos || numDeviceNames > maxDeviceNames )            {                maxDeviceNames *= 2;                PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ),                        paInsufficientMemory );            }            PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) );            hwDevInfos[ numDeviceNames - 1 ].alsaName = alsaDeviceName;            hwDevInfos[ numDeviceNames - 1 ].name = deviceName;            hwDevInfos[ numDeviceNames - 1 ].isPlug = 0;            hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback;            hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture;        }        snd_ctl_close( ctl );    }    /* Iterate over plugin devices */    if( NULL == snd_config )    {        /* snd_config_update is called implicitly by some functions, if this hasn't happened snd_config will be NULL (bleh) */        ENSURE_( snd_config_update(), paUnanticipatedHostError );        PA_DEBUG(( "Updating snd_config\n" ));    }    assert( snd_config );    if( (res = snd_config_search( snd_config, "pcm", &topNode )) >= 0 )    {        snd_config_iterator_t i, next;        snd_config_for_each( i, next, topNode )        {            const char *tpStr = "unknown", *idStr = NULL;            int err = 0;            char *alsaDeviceName, *deviceName;	    const HwDevInfo *predefined = NULL;            snd_config_t *n = snd_config_iterator_entry( i ), * tp = NULL;;            if( (err = snd_config_search( n, "type", &tp )) < 0 )            {                if( -ENOENT != err )                {                    ENSURE_(err, paUnanticipatedHostError);                }            }            else             {                ENSURE_( snd_config_get_string( tp, &tpStr ), paUnanticipatedHostError );            }            ENSURE_( snd_config_get_id( n, &idStr ), paUnanticipatedHostError );            if( IgnorePlugin( idStr ) )            {                PA_DEBUG(( "%s: Ignoring ALSA plugin device %s of type %s\n", __FUNCTION__, idStr, tpStr ));                continue;            }            PA_DEBUG(( "%s: Found plugin %s of type %s\n", __FUNCTION__, idStr, tpStr ));            PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,                                                            strlen(idStr) + 6 ), paInsufficientMemory );            strcpy( alsaDeviceName, idStr );            PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations,                                                            strlen(idStr) + 1 ), paInsufficientMemory );            strcpy( deviceName, idStr );            ++numDeviceNames;            if( !hwDevInfos || numDeviceNames > maxDeviceNames )            {                maxDeviceNames *= 2;                PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, maxDeviceNames * sizeof (HwDevInfo) ),                        paInsufficientMemory );            }	    predefined = FindDeviceName( alsaDeviceName );            hwDevInfos[numDeviceNames - 1].alsaName = alsaDeviceName;            hwDevInfos[numDeviceNames - 1].name = deviceName;            hwDevInfos[numDeviceNames - 1].isPlug = 1;	    if( predefined )	    {		hwDevInfos[numDeviceNames - 1].hasPlayback =		    predefined->hasPlayback;		hwDevInfos[numDeviceNames - 1].hasCapture =		    predefined->hasCapture;	    }	    else	    {		hwDevInfos[numDeviceNames - 1].hasPlayback = 1;		hwDevInfos[numDeviceNames - 1].hasCapture = 1;	    }        }    }    else        PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, snd_strerror( res ) ));    /* allocate deviceInfo memory based on the number of devices */    PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(            alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory );    /* allocate all device info structs in a contiguous block */    PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory(            alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), paInsufficientMemory );    /* Loop over list of cards, filling in info. If a device is deemed unavailable (can't get name),     * it's ignored.     */    for( i = 0, devIdx = 0; i < numDeviceNames; ++i )    {        PaAlsaDeviceInfo* devInfo = &deviceInfoArray[i];        HwDevInfo* hwInfo = &hwDevInfos[i];        if( !strcmp( hwInfo->name, "dmix" ) || !strcmp( hwInfo->name, "default" ) )        {            continue;        }        PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, &devIdx ) );    }    assert( devIdx < numDeviceNames );    for( i = 0; i < numDeviceNames; ++i )    {        PaAlsaDeviceInfo* devInfo = &deviceInfoArray[i];        HwDevInfo* hwInfo = &hwDevInfos[i];        if( strcmp( hwInfo->name, "dmix" ) && strcmp( hwInfo->name, "default" ) )        {            continue;        }        PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo,                    &devIdx ) );    }    free( hwDevInfos );    baseApi->info.deviceCount = devIdx;   /* Number of successfully queried devices */end:    return result;error:    /* No particular action */    goto end;}/* Check against known device capabilities */static PaError ValidateParameters( const PaStreamParameters *parameters, PaUtilHostApiRepresentation *hostApi, StreamDirection mode ){    PaError result = paNoError;    int maxChans;    const PaAlsaDeviceInfo *deviceInfo = NULL;    assert( parameters );    if( parameters->device != paUseHostApiSpecificDeviceSpecification )    {        assert( parameters->device < hostApi->info.deviceCount );        PA_UNLESS( parameters->hostApiSpecificStreamInfo == NULL, paBadIODeviceCombination );        deviceInfo = GetDeviceInfo( hostApi, parameters->device );    }    else    {        const PaAlsaStreamInfo *streamInfo = parameters->hostApiSpecificStreamInfo;        PA_UNLESS( parameters->device == paUseHostApiSpecificDeviceSpecification, paInvalidDevice );        PA_UNLESS( streamInfo->size == sizeof (PaAlsaStreamInfo) && streamInfo->version == 1,                paIncompatibleHostApiSpecificStreamInfo );        PA_UNLESS( streamInfo->deviceString != NULL, paInvalidDevice );        /* Skip further checking */        return paNoError;    }    assert( deviceInfo );    assert( parameters->hostApiSpecificStreamInfo == NULL );    maxChans = (StreamDirection_In == mode ? deviceInfo->baseDeviceInfo.maxInputChannels :        deviceInfo->baseDeviceInfo.maxOutputChannels);    PA_UNLESS( parameters->channelCount <= maxChans, paInvalidChannelCount );error:    return result;}/* Given an open stream, what sample formats are available? */static PaSampleFormat GetAvailableFormats( snd_pcm_t *pcm ){    PaSampleFormat available = 0;    snd_pcm_hw_params_t *hwParams;    snd_pcm_hw_params_alloca( &hwParams );    snd_pcm_hw_params_any( pcm, hwParams );    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_FLOAT ) >= 0)        available |= paFloat32;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 0)        available |= paInt32;#ifdef PA_LITTLE_ENDIAN    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) >= 0)        available |= paInt24;#elif defined PA_BIG_ENDIAN    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) >= 0)        available |= paInt24;#endif    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 0)        available |= paInt16;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_U8 ) >= 0)        available |= paUInt8;    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S8 ) >= 0)        available |= paInt8;    return available;}static snd_pcm_format_t Pa2AlsaFormat( PaSampleFormat paFormat ){    switch( paFormat )    {        case paFloat32:            return SND_PCM_FORMAT_FLOAT;        case paInt16:            return SND_PCM_FORMAT_S16;        case paInt24:#ifdef PA_LITTLE_ENDIAN            return SND_PCM_FORMAT_S24_3LE;#elif defined PA_BIG_ENDIAN            return SND_PCM_FORMAT_S24_3BE;#endif        case paInt32:            return SND_PCM_FORMAT_S32;        case paInt8:            return SND_PCM_FORMAT_S8;        case paUInt8:            return SND_PCM_FORMAT_U8;        default:            return SND_PCM_FORMAT_UNKNOWN;    }}/** Open an ALSA pcm handle. *  * The device to be open can be specified in a custom PaAlsaStreamInfo struct, or it will be a device number. In case of a * device number, it maybe specified through an env variable (PA_ALSA_PLUGHW) that we should open the corresponding plugin * device. */static PaError AlsaOpen( const PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *params, StreamDirection        streamDir, snd_pcm_t **pcm ){    PaError result = paNoError;    int ret;    char dnameArray[50];    const char* deviceName = dnameArray;    const PaAlsaDeviceInfo *deviceInfo = NULL;    PaAlsaStreamInfo *streamInfo = (PaAlsaStreamInfo *)params->hostApiSpecificStreamInfo;    if( !streamInfo )    {        int usePlug = 0;        deviceInfo = GetDeviceInfo( hostApi, params->device );                /* If device name starts with hw: and PA_ALSA_PLUGHW is 1, we open the plughw device instead */        if( !strncmp( "hw:", deviceInfo->alsaName, 3 ) && getenv( "PA_ALSA_PLUGHW" ) )            usePlug = atoi( getenv( "PA_ALSA_PLUGHW" ) );        if( usePlug )            snprintf( dnameArray, 50, "plug%s", deviceInfo->alsaName );        else            deviceName = deviceInfo->alsaName;    }    else        deviceName = streamInfo->deviceString;    PA_DEBUG(( "%s: Opening device %s\n", __FUNCTION__, deviceName ));    if( (ret = OpenPcm( pcm, deviceName, streamDir == StreamDirection_In ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,                    SND_PCM_NONBLOCK )) < 0 )    {        /* Not to be closed */        *pcm = NULL;        if( -EBUSY == ret )        {            PA_DEBUG(( "%s: Device is busy\n", __FUNCTION__ ));        }        ENSURE_( ret, -EBUSY == ret ? paDeviceUnavailable : paBadIODeviceCombination );    }    ENSURE_( snd_pcm_nonblock( *pcm, 0 ), paUnanticipatedHostError );end:    return result;error:    goto end;}static PaError TestParameters( const PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *parameters,        double sampleRate, StreamDirection streamDir ){    PaError result = paNoError;    snd_pcm_t *pcm = NULL;    PaSampleFormat availableFormats;    /* We are able to adapt to a number of channels less than what the device supports */    unsigned int numHostChannels;    PaSampleFormat hostFormat;    snd_pcm_hw_params_t *hwParams;    snd_pcm_hw_params_alloca( &hwParams );        if( !parameters->hostApiSpecificStreamInfo )    {        const PaAlsaDeviceInfo *devInfo = GetDeviceInfo( hostApi, parameters->device );

⌨️ 快捷键说明

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