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

📄 px_win_wmme.c

📁 IAX client库, 一个VOIP的库. 支持H.323和SIP, PBX就是采用的它
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * PortMixer * Windows WMME Implementation * * Copyright (c) 2002 * * Written by Dominic Mazzoni and Augustus Saunders * * PortMixer is intended to work side-by-side with PortAudio, * the Portable Real-Time Audio Library by Ross Bencina and * Phil Burk. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */#include <Windows.h>#include <stdio.h>#include "portaudio.h"#include "pa_host.h"#include "portmixer.h"typedef struct PaWMMEStreamData{    /* Input -------------- */    HWAVEIN            hWaveIn;    WAVEHDR           *inputBuffers;    int                currentInputBuffer;    int                bytesPerHostInputBuffer;    int                bytesPerUserInputBuffer;    /* native buffer size in bytes */    /* Output -------------- */    HWAVEOUT           hWaveOut;} PaWMMEStreamData;typedef struct PxSrcInfo{   char  name[256];   DWORD lineID;   DWORD controlID;} PxSrcInfo;typedef struct PxInfo{   HMIXEROBJ   hInputMixer;   HMIXEROBJ   hOutputMixer;   int         numInputs;   PxSrcInfo   src[32];   int         useMuxID;   DWORD       muxID;   DWORD       inputID;   DWORD       speakerID;   DWORD       waveID;} PxInfo;// alternate volume control initialization routinesMMRESULT _Px_InitInputVolumeControls( PxInfo* mixer, int hWaveIn ) ;MMRESULT _Px_InitOutputVolumeControls( PxInfo* mixer, int hWaveOut ) ;// toggle microphone boost functionMMRESULT _Px_SetMicrophoneBoost( PxMixer* mixer, int enable ) ;int _Px_GetMicrophoneBoost( PxMixer* mixer ) ;// set input source by nameMMRESULT _Px_SetCurrentInputSourceByName( PxInfo* mixer, const char* line_name ) ;int Px_GetNumMixers( void *pa_stream ){   return 1;}const char *Px_GetMixerName( void *pa_stream, int index ){   return "Mixer";}PxMixer *Px_OpenMixer( void *pa_stream, int index ){	/* initialize new mixer object */	PxInfo* mixer = ( PxMixer* )( malloc( sizeof( PxInfo ) ) ) ;	mixer->hInputMixer = NULL ;	mixer->hOutputMixer = NULL ;	internalPortAudioStream* past = ( internalPortAudioStream* )( pa_stream ) ;	PaWMMEStreamData* wmmeStreamData = ( PaWMMEStreamData* )( past->past_DeviceData ) ;	MMRESULT result ;	if ( wmmeStreamData->hWaveIn != NULL )	{		/* initialize input volume controls */		result = _Px_InitInputVolumeControls( 			( PxInfo* )( mixer ), 			( UINT )( wmmeStreamData->hWaveIn ) 		) ;		if ( result != MMSYSERR_NOERROR )		{			free( mixer ) ;			return NULL ;		}			}		if ( wmmeStreamData->hWaveOut != NULL )	{		/* initialize output volume controls */		result = _Px_InitOutputVolumeControls( 			( PxInfo* )( mixer ),			( UINT )( wmmeStreamData->hWaveOut ) 		) ;		if ( result != MMSYSERR_NOERROR )		{			free( mixer ) ;			return NULL ;		}			}	// report found info//	fprintf( stdout, "useMuxID => %d, muxID => %u, inputID => %u, speakerID => %u, waveID => %u\n", //		mixer->useMuxID, mixer->muxID, mixer->inputID, mixer->speakerID, mixer->waveID ) ;		return mixer ;}void VolumeFunction(HMIXEROBJ hMixer, DWORD controlID, PxVolume *volume){   MIXERCONTROLDETAILS details;   MMRESULT result;   MIXERCONTROLDETAILS_UNSIGNED value;   memset(&value, 0, sizeof(MIXERCONTROLDETAILS_UNSIGNED));   details.cbStruct = sizeof(MIXERCONTROLDETAILS);   details.dwControlID = controlID;   details.cChannels = 1; /* all channels */   details.cMultipleItems = 0;   details.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);   details.paDetails = &value;   result = mixerGetControlDetails(hMixer, &details,                                   MIXER_GETCONTROLDETAILSF_VALUE);   if (*volume < 0.0) {      *volume = (PxVolume)(value.dwValue / 65535.0);   }   else {      if (result != MMSYSERR_NOERROR)         return;      value.dwValue = (unsigned short)(*volume * 65535.0);      mixerSetControlDetails(hMixer, &details,                             MIXER_GETCONTROLDETAILSF_VALUE);   }}/* Px_CloseMixer() closes a mixer opened using Px_OpenMixer and frees any memory associated with it. */void Px_CloseMixer(PxMixer *mixer){   PxInfo *info = (PxInfo *)mixer;   if (info->hInputMixer)      mixerClose((HMIXER)info->hInputMixer);   if (info->hOutputMixer)      mixerClose((HMIXER)info->hOutputMixer);   free( mixer );}/* Master (output) volume*/PxVolume Px_GetMasterVolume( PxMixer *mixer ){   PxInfo *info = (PxInfo *)mixer;   PxVolume vol;   vol = -1.0;   VolumeFunction(info->hOutputMixer, info->speakerID, &vol);   return vol;}void Px_SetMasterVolume( PxMixer *mixer, PxVolume volume ){   PxInfo *info = (PxInfo *)mixer;   VolumeFunction(info->hOutputMixer, info->speakerID, &volume);}/* PCM output volume*/int Px_SupportsPCMOutputVolume( PxMixer* mixer ) {	PxInfo* info = ( PxInfo* )( mixer ) ;	return ( info->waveID == -1 ) ? 0 : 1 ;}PxVolume Px_GetPCMOutputVolume( PxMixer *mixer ){	PxVolume volume = -1.0 ;	PxInfo* info = ( PxInfo* )( mixer ) ;	if ( info == NULL ) return volume ;	VolumeFunction( info->hOutputMixer, info->waveID, &volume ) ;		return volume ;}void Px_SetPCMOutputVolume( PxMixer *mixer, PxVolume volume ){	PxInfo* info = ( PxInfo* )( mixer ) ;	if ( info == NULL ) return ;	VolumeFunction( info->hOutputMixer, info->waveID, &volume ) ;}/* All output volumes*/int Px_GetNumOutputVolumes( PxMixer *mixer ){   PxInfo *info = (PxInfo *)mixer;   return 2;}const char *Px_GetOutputVolumeName( PxMixer *mixer, int i ){   PxInfo *info = (PxInfo *)mixer;      if (i==1)      return "Wave Out";   else      return "Master Volume";}PxVolume Px_GetOutputVolume( PxMixer *mixer, int i ){   PxInfo *info = (PxInfo *)mixer;   if (i==1)      return Px_GetPCMOutputVolume(mixer);   else      return Px_GetMasterVolume(mixer);}void Px_SetOutputVolume( PxMixer *mixer, int i, PxVolume volume ){   PxInfo *info = (PxInfo *)mixer;   if (i==1)      Px_SetPCMOutputVolume(mixer, volume);   else      Px_SetMasterVolume(mixer, volume);}/* Input sources*/int Px_GetNumInputSources( PxMixer *mixer ){   PxInfo *info = (PxInfo *)mixer;      return info->numInputs;}const char *Px_GetInputSourceName( PxMixer *mixer, int i){   PxInfo *info = (PxInfo *)mixer;      return info->src[i].name;}int Px_GetCurrentInputSource( PxMixer *mixer ){	PxInfo* info = ( PxInfo* )( mixer ) ;		if ( info->useMuxID == 1 )	{  		MIXERCONTROLDETAILS_BOOLEAN flags[32] ;			MIXERCONTROLDETAILS details ;		details.cbStruct = sizeof( MIXERCONTROLDETAILS ) ;		details.dwControlID = info->muxID ;		details.cChannels = 1 ;		details.cMultipleItems = info->numInputs ;		details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN ) ;		details.paDetails = ( LPMIXERCONTROLDETAILS_BOOLEAN )&flags[0] ;				MMRESULT result = mixerGetControlDetails(			( HMIXEROBJ )( info->hInputMixer ),			( LPMIXERCONTROLDETAILS )&details,			MIXER_GETCONTROLDETAILSF_VALUE		) ;				if ( result == MMSYSERR_NOERROR )		{			int i = 0 ;			for ( ; i < info->numInputs ; ++i )			{				if ( flags[i].fValue )					return i ;			}		}		else		{			// !!! handle errors !!!		}	}	else	{		// use altenate input control id		return info->inputID ;	}		return 0 ;}void Px_SetCurrentInputSource( PxMixer *mixer, int source_index ){	PxInfo* info = ( PxInfo* )( mixer ) ;	if ( info->useMuxID == 1 )	{  		MIXERCONTROLDETAILS_BOOLEAN flags[32] ;		memset( &flags, 0x0, sizeof( flags ) ) ;		flags[ source_index ].fValue = 1 ;				MIXERCONTROLDETAILS details ;		details.cbStruct = sizeof( MIXERCONTROLDETAILS ) ;		details.dwControlID = info->muxID ;		details.cMultipleItems = info->numInputs ;		details.cChannels = 1 ; 		details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN ) ;		details.paDetails = ( LPMIXERCONTROLDETAILS_BOOLEAN )&flags[0] ;			MMRESULT result = mixerSetControlDetails(			( HMIXEROBJ )( info->hInputMixer ),			( LPMIXERCONTROLDETAILS )&details,			MIXER_SETCONTROLDETAILSF_VALUE		) ;				// !!! handle errors !!!	}	else	{		// we don't have a mux or mixer to work with, 		// so we use the control id directly		info->inputID = info->src[source_index].controlID ;	}	return ;}/* Input volume*/PxVolume Px_GetInputVolume( PxMixer *mixer ){	PxVolume volume = -1.0 ;	PxInfo* info = ( PxInfo* )( mixer ) ;	if ( info == NULL ) return volume ;	if ( info->useMuxID == 1 )	{		int src = Px_GetCurrentInputSource( mixer ) ;		VolumeFunction( info->hInputMixer, info->src[src].controlID, &volume ) ;	}	else	{			VolumeFunction( info->hInputMixer, info->inputID, &volume ) ;	}		return volume ;}void Px_SetInputVolume( PxMixer *mixer, PxVolume volume ){	PxInfo* info = ( PxInfo* )( mixer ) ;	if ( info == NULL ) return ;		if ( info->useMuxID == 1 )	{		int src = Px_GetCurrentInputSource( mixer ) ;		VolumeFunction( info->hInputMixer, info->src[src].controlID, &volume ) ;	}	else	{		VolumeFunction( info->hInputMixer, info->inputID, &volume ) ;	}		return ;}/*  Balance*/int Px_SupportsOutputBalance( PxMixer *mixer ){   return 0;}PxBalance Px_GetOutputBalance( PxMixer *mixer ){   return 0.0;}void Px_SetOutputBalance( PxMixer *mixer, PxBalance balance ){}/*  Playthrough*/int Px_SupportsPlaythrough( PxMixer *mixer ){   return 0;}PxVolume Px_GetPlaythrough( PxMixer *mixer ){   return 0.0;}void Px_SetPlaythrough( PxMixer *mixer, PxVolume volume ){}//// alternate control initialization functions//MMRESULT_Px_InitInputVolumeControls( PxInfo* mixer, int hWaveIn ) {	MMRESULT mmr ;	// cast void pointer	PxInfo* info = ( PxInfo* )( mixer ) ;		if ( info == NULL ) 		return MMSYSERR_ERROR ;		//	// open the mixer device	//		mmr = mixerOpen( 		( LPHMIXER )( &mixer->hInputMixer ), 		( UINT )( hWaveIn ), 0, 0, 		MIXER_OBJECTF_HWAVEIN 	) ;		if ( mmr != MMSYSERR_NOERROR )		return mmr ;		//	// get the line info for the wavein line	//		MIXERLINE mixerLine ;    mixerLine.cbStruct = sizeof( MIXERLINE ) ;    mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN ;		mmr = mixerGetLineInfo(		( HMIXEROBJ )( mixer->hInputMixer ),		&mixerLine,		MIXER_GETLINEINFOF_COMPONENTTYPE	) ;	if ( mmr != MMSYSERR_NOERROR )	{		mixerClose( (HMIXER)( mixer->hInputMixer ) ) ;		return mmr ;	}		// we now know the number of inputs	mixer->numInputs = mixerLine.cConnections ;		//	// find a mux or mixer control for the wavein line	//	// set defaults	mixer->useMuxID = 0 ;		LPMIXERCONTROL muxControl = malloc( sizeof( MIXERCONTROL ) * mixerLine.cControls ) ;	MIXERLINECONTROLS muxLineControls ;	muxLineControls.cbStruct = sizeof( MIXERLINECONTROLS ) ;	muxLineControls.dwLineID = mixerLine.dwLineID ;	muxLineControls.cControls = mixerLine.cControls ;	muxLineControls.cbmxctrl = sizeof( MIXERCONTROL ) ;	muxLineControls.pamxctrl = ( LPMIXERCONTROL )( muxControl ) ;		mmr = mixerGetLineControls(		mixer->hInputMixer,		&muxLineControls,		MIXER_GETLINECONTROLSF_ALL	) ;	int i = 0 ;	for ( ; i < mixerLine.cControls ; ++i )	{		if ( 			muxControl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_MUX			|| muxControl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_MIXER		)		{			// okay, we have a mux control, let's use it			mixer->muxID = muxControl[i].dwControlID ;			mixer->useMuxID = 1 ;		}		else if ( muxControl[i].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME )		{			// normally the master volume, use as our default inputID			mixer->inputID = muxControl[i].dwControlID ;		}	}	free( muxControl ) ;	//	// gather information about the wavein line volume controls	// 		if ( mixer->useMuxID == 1 )	{		// use mux controls				MIXERCONTROLDETAILS_LISTTEXT mixList[32] ;		MIXERCONTROLDETAILS details ;		details.cbStruct = sizeof( MIXERCONTROLDETAILS ) ;		details.dwControlID = mixer->muxID ;

⌨️ 快捷键说明

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