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

📄 pa_win_wmme.c

📁 一个开源SIP协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
        {
            result = paUnanticipatedHostError;
            PA_MME_SET_LAST_SYSTEM_ERROR( GetLastError() );
        }
    }
    
    return result;
}


/* PaWinMmeHostApiRepresentation - host api datastructure specific to this implementation */

typedef struct
{
    PaUtilHostApiRepresentation inheritedHostApiRep;
    PaUtilStreamInterface callbackStreamInterface;
    PaUtilStreamInterface blockingStreamInterface;

    PaUtilAllocationGroup *allocations;
    
    int inputDeviceCount, outputDeviceCount;

    /** winMmeDeviceIds is an array of WinMme device ids.
        fields in the range [0, inputDeviceCount) are input device ids,
        and [inputDeviceCount, inputDeviceCount + outputDeviceCount) are output
        device ids.
     */ 
    UINT *winMmeDeviceIds;
}
PaWinMmeHostApiRepresentation;


typedef struct
{
    PaDeviceInfo inheritedDeviceInfo;
    DWORD dwFormats; /**<< standard formats bitmask from the WAVEINCAPS and WAVEOUTCAPS structures */
}
PaWinMmeDeviceInfo;


/*************************************************************************
 * Returns recommended device ID.
 * On the PC, the recommended device can be specified by the user by
 * setting an environment variable. For example, to use device #1.
 *
 *    set PA_RECOMMENDED_OUTPUT_DEVICE=1
 *
 * The user should first determine the available device ID by using
 * the supplied application "pa_devs".
 */
#define PA_ENV_BUF_SIZE_  (32)
#define PA_REC_IN_DEV_ENV_NAME_  ("PA_RECOMMENDED_INPUT_DEVICE")
#define PA_REC_OUT_DEV_ENV_NAME_  ("PA_RECOMMENDED_OUTPUT_DEVICE")
static PaDeviceIndex GetEnvDefaultDeviceID( char *envName )
{
    PaDeviceIndex recommendedIndex = paNoDevice;
    DWORD   hresult;
    char    envbuf[PA_ENV_BUF_SIZE_];

#ifndef WIN32_PLATFORM_PSPC /* no GetEnvironmentVariable on PocketPC */

    /* Let user determine default device by setting environment variable. */
    hresult = GetEnvironmentVariable( envName, envbuf, PA_ENV_BUF_SIZE_ );
    if( (hresult > 0) && (hresult < PA_ENV_BUF_SIZE_) )
    {
        recommendedIndex = atoi( envbuf );
    }
#endif

    return recommendedIndex;
}


static void InitializeDefaultDeviceIdsFromEnv( PaWinMmeHostApiRepresentation *hostApi )
{
    PaDeviceIndex device;

    /* input */
    device = GetEnvDefaultDeviceID( PA_REC_IN_DEV_ENV_NAME_ );
    if( device != paNoDevice &&
            ( device >= 0 && device < hostApi->inheritedHostApiRep.info.deviceCount ) &&
            hostApi->inheritedHostApiRep.deviceInfos[ device ]->maxInputChannels > 0 )
    {
        hostApi->inheritedHostApiRep.info.defaultInputDevice = device;
    }

    /* output */
    device = GetEnvDefaultDeviceID( PA_REC_OUT_DEV_ENV_NAME_ );
    if( device != paNoDevice &&
            ( device >= 0 && device < hostApi->inheritedHostApiRep.info.deviceCount ) &&
            hostApi->inheritedHostApiRep.deviceInfos[ device ]->maxOutputChannels > 0 )
    {
        hostApi->inheritedHostApiRep.info.defaultOutputDevice = device;
    }
}


/** Convert external PA ID to a windows multimedia device ID
*/
static UINT LocalDeviceIndexToWinMmeDeviceId( PaWinMmeHostApiRepresentation *hostApi, PaDeviceIndex device )
{
    assert( device >= 0 && device < hostApi->inputDeviceCount + hostApi->outputDeviceCount );

	return hostApi->winMmeDeviceIds[ device ];
}


static PaError QueryInputWaveFormatEx( int deviceId, WAVEFORMATEX *waveFormatEx )
{
    MMRESULT mmresult;
    
    switch( mmresult = waveInOpen( NULL, deviceId, waveFormatEx, 0, 0, WAVE_FORMAT_QUERY ) )
    {
        case MMSYSERR_NOERROR:
            return paNoError;
        case MMSYSERR_ALLOCATED:    /* Specified resource is already allocated. */
            return paDeviceUnavailable;
        case MMSYSERR_NODRIVER:	    /* No device driver is present. */
            return paDeviceUnavailable;
        case MMSYSERR_NOMEM:	    /* Unable to allocate or lock memory. */
            return paInsufficientMemory;
        case WAVERR_BADFORMAT:      /* Attempted to open with an unsupported waveform-audio format. */
            return paSampleFormatNotSupported;
                    
        case MMSYSERR_BADDEVICEID:	/* Specified device identifier is out of range. */
            /* falls through */
        default:
            PA_MME_SET_LAST_WAVEIN_ERROR( mmresult );
            return paUnanticipatedHostError;
    }
}


static PaError QueryOutputWaveFormatEx( int deviceId, WAVEFORMATEX *waveFormatEx )
{
    MMRESULT mmresult;
    
    switch( mmresult = waveOutOpen( NULL, deviceId, waveFormatEx, 0, 0, WAVE_FORMAT_QUERY ) )
    {
        case MMSYSERR_NOERROR:
            return paNoError;
        case MMSYSERR_ALLOCATED:    /* Specified resource is already allocated. */
            return paDeviceUnavailable;
        case MMSYSERR_NODRIVER:	    /* No device driver is present. */
            return paDeviceUnavailable;
        case MMSYSERR_NOMEM:	    /* Unable to allocate or lock memory. */
            return paInsufficientMemory;
        case WAVERR_BADFORMAT:      /* Attempted to open with an unsupported waveform-audio format. */
            return paSampleFormatNotSupported;
                    
        case MMSYSERR_BADDEVICEID:	/* Specified device identifier is out of range. */
            /* falls through */
        default:
            PA_MME_SET_LAST_WAVEOUT_ERROR( mmresult );
            return paUnanticipatedHostError;
    }
}


static PaError QueryFormatSupported( PaDeviceInfo *deviceInfo,
        PaError (*waveFormatExQueryFunction)(int, WAVEFORMATEX*),
        int winMmeDeviceId, int channels, double sampleRate )
{
    PaWinMmeDeviceInfo *winMmeDeviceInfo = (PaWinMmeDeviceInfo*)deviceInfo;
    WAVEFORMATEX waveFormatEx;
    
    if( sampleRate == 11025.0
        && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1M16))
            || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1S16)) ) ){

        return paNoError;
    }

    if( sampleRate == 22050.0
        && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2M16))
            || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2S16)) ) ){

        return paNoError;
    }

    if( sampleRate == 44100.0
        && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4M16))
            || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4S16)) ) ){

        return paNoError;
    }

    waveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
    waveFormatEx.nChannels = (WORD)channels;
    waveFormatEx.nSamplesPerSec = (DWORD)sampleRate;
    waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * channels * sizeof(short);
    waveFormatEx.nBlockAlign = (WORD)(channels * sizeof(short));
    waveFormatEx.wBitsPerSample = 16;
    waveFormatEx.cbSize = 0;

    return waveFormatExQueryFunction( winMmeDeviceId, &waveFormatEx );
}


#define PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_  (13) /* must match array length below */
static double defaultSampleRateSearchOrder_[] =
    { 44100.0, 48000.0, 32000.0, 24000.0, 22050.0, 88200.0, 96000.0, 192000.0,
        16000.0, 12000.0, 11025.0, 9600.0, 8000.0 };

static void DetectDefaultSampleRate( PaWinMmeDeviceInfo *winMmeDeviceInfo, int winMmeDeviceId,
        PaError (*waveFormatExQueryFunction)(int, WAVEFORMATEX*), int maxChannels )
{
    PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
    int i;
    
    deviceInfo->defaultSampleRate = 0.;

    for( i=0; i < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++i )
    {
        double sampleRate = defaultSampleRateSearchOrder_[ i ]; 
        PaError paerror = QueryFormatSupported( deviceInfo, waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate );
        if( paerror == paNoError )
        {
            deviceInfo->defaultSampleRate = sampleRate;
            break;
        }
    }
}


static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeHostApi,
        PaWinMmeDeviceInfo *winMmeDeviceInfo, UINT winMmeInputDeviceId, int *success )
{
    PaError result = paNoError;
    char *deviceName; /* non-const ptr */
    MMRESULT mmresult;
    WAVEINCAPS wic;
    PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
    PJ_DECL_ANSI_TEMP_BUF(abuf,128)
    
    *success = 0;

    mmresult = waveInGetDevCaps( winMmeInputDeviceId, &wic, sizeof( WAVEINCAPS ) );
    if( mmresult == MMSYSERR_NOMEM )
    {
        result = paInsufficientMemory;
        goto error;
    }
    else if( mmresult != MMSYSERR_NOERROR )
    {
        /* instead of returning paUnanticipatedHostError we return
            paNoError, but leave success set as 0. This allows
            Pa_Initialize to just ignore this device, without failing
            the entire initialisation process.
        */
        return paNoError;
    }           

    if( winMmeInputDeviceId == WAVE_MAPPER )
    {
        /* Append I/O suffix to WAVE_MAPPER device. */
        deviceName = (char*)PaUtil_GroupAllocateMemory(
                    winMmeHostApi->allocations, 
		    pj_native_strlen( wic.szPname ) + sizeof(pj_char_t) + sizeof(constInputMapperSuffix_) );
        if( !deviceName )
        {
            result = paInsufficientMemory;
            goto error;
        }
        strcpy( deviceName, PJ_NATIVE_TO_STRING(wic.szPname,abuf,sizeof(abuf)) );
        strcat( deviceName, PJ_NATIVE_TO_STRING(constInputMapperSuffix_,abuf,sizeof(abuf)) );
    }
    else
    {
        deviceName = (char*)PaUtil_GroupAllocateMemory(
                    winMmeHostApi->allocations, pj_native_strlen( wic.szPname ) + sizeof(pj_char_t) );
        if( !deviceName )
        {
            result = paInsufficientMemory;
            goto error;
        }
        strcpy( deviceName, PJ_NATIVE_TO_STRING(wic.szPname,abuf,sizeof(abuf))  );
    }
    deviceInfo->name = deviceName;

    deviceInfo->maxInputChannels = wic.wChannels;
    /* Sometimes a device can return a rediculously large number of channels.
     * This happened with an SBLive card on a Windows ME box.
     * If that happens, then force it to 2 channels.  PLB20010413
     */
    if( (deviceInfo->maxInputChannels < 1) || (deviceInfo->maxInputChannels > 256) )
    {
        PA_DEBUG(("Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\n", deviceInfo->maxInputChannels ));
        deviceInfo->maxInputChannels = 2;
    }

    winMmeDeviceInfo->dwFormats = wic.dwFormats;

    DetectDefaultSampleRate( winMmeDeviceInfo, winMmeInputDeviceId,
            QueryInputWaveFormatEx, deviceInfo->maxInputChannels );

    *success = 1;
    
error:
    return result;
}


static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeHostApi,
        PaWinMmeDeviceInfo *winMmeDeviceInfo, UINT winMmeOutputDeviceId, int *success )
{
    PaError result = paNoError;
    char *deviceName; /* non-const ptr */
    MMRESULT mmresult;
    WAVEOUTCAPS woc;
    PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
    PJ_DECL_ANSI_TEMP_BUF(abuf,128)
    
    *success = 0;

    mmresult = waveOutGetDevCaps( winMmeOutputDeviceId, &woc, sizeof( WAVEOUTCAPS ) );
    if( mmresult == MMSYSERR_NOMEM )
    {
        result = paInsufficientMemory;
        goto error;
    }
    else if( mmresult != MMSYSERR_NOERROR )
    {
        /* instead of returning paUnanticipatedHostError we return
            paNoError, but leave success set as 0. This allows
            Pa_Initialize to just ignore this device, without failing
            the entire initialisation process.
        */

⌨️ 快捷键说明

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