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

📄 px_win_wmme.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
字号:
/* * 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 "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];   DWORD       muxID;   DWORD       speakerID;   DWORD       waveID;} PxInfo;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 ){   internalPortAudioStream     *past;   PaWMMEStreamData            *wmmeStreamData;   HWAVEIN                      hWaveIn;   HWAVEOUT                     hWaveOut;   PxInfo                      *mixer;   MMRESULT                     result;   MIXERLINE                    line;   MIXERLINECONTROLS            controls;   MIXERCONTROL                 control;   MIXERCONTROLDETAILS          details;   MIXERCONTROLDETAILS_LISTTEXT mixList[32];   int                          j;   mixer = (PxMixer *)malloc(sizeof(PxInfo));   mixer->hInputMixer = NULL;   mixer->hOutputMixer = NULL;   past = (internalPortAudioStream *) pa_stream;   wmmeStreamData = (PaWMMEStreamData *) past->past_DeviceData;   hWaveIn = wmmeStreamData->hWaveIn;   if (hWaveIn) {      result = mixerOpen((HMIXER *)&mixer->hInputMixer, (UINT)hWaveIn, 0, 0, MIXER_OBJECTF_HWAVEIN);      if (result != MMSYSERR_NOERROR) {         free(mixer);         return NULL;      }   }   hWaveOut = wmmeStreamData->hWaveOut;   if (hWaveOut) {      result = mixerOpen((HMIXER *)&mixer->hOutputMixer, (UINT)hWaveOut, 0, 0, MIXER_OBJECTF_HWAVEOUT);      if (result != MMSYSERR_NOERROR) {         free(mixer);         return NULL;      }   }   mixer->numInputs = 0;   mixer->muxID = 0;	/* ??? win32 default for wave control seems to be 0 ??? */	mixer->waveID = 0 ;    /*    * Find the input source selector (mux or mixer) and    * get the names and IDs of all of the input sources    */   if (mixer->hInputMixer) {      line.cbStruct = sizeof(MIXERLINE);      line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;      result = mixerGetLineInfo(mixer->hInputMixer,                                &line,                                MIXER_GETLINEINFOF_COMPONENTTYPE);      if (result == MMSYSERR_NOERROR) {         controls.cbStruct = sizeof(MIXERLINECONTROLS);         controls.dwLineID = line.dwLineID;         controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;         controls.cbmxctrl = sizeof(MIXERCONTROL);         controls.pamxctrl = &control;         control.cbStruct = sizeof(MIXERCONTROL);         result = mixerGetLineControls(mixer->hInputMixer,                                       &controls,                                       MIXER_GETLINECONTROLSF_ONEBYTYPE);         if (result != MMSYSERR_NOERROR) {            controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER;            result = mixerGetLineControls(mixer->hInputMixer,                                          &controls,                                          MIXER_GETLINECONTROLSF_ONEBYTYPE);         }         if (result == MMSYSERR_NOERROR) {            mixer->numInputs = control.cMultipleItems;            mixer->muxID = control.dwControlID;            details.cbStruct = sizeof(MIXERCONTROLDETAILS);            details.dwControlID = mixer->muxID;            details.cChannels = 1;            details.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT);            details.paDetails = (LPMIXERCONTROLDETAILS_LISTTEXT)&mixList[0];            details.cMultipleItems = mixer->numInputs;            result = mixerGetControlDetails(mixer->hInputMixer,                                            (LPMIXERCONTROLDETAILS)&details,                                            MIXER_GETCONTROLDETAILSF_LISTTEXT);            if (result != MMSYSERR_NOERROR)               mixer->numInputs = 0;            for(j=0; j<mixer->numInputs; j++) {               mixer->src[j].lineID = mixList[j].dwParam1;               strcpy(mixer->src[j].name, mixList[j].szName);            }         }         /*          * We've found the names - now we need to find the volume          * controls for each one          */         for(j=0; j<mixer->numInputs; j++) {            controls.cbStruct = sizeof(MIXERLINECONTROLS);            controls.dwLineID = mixer->src[j].lineID;            controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;            controls.cbmxctrl = sizeof(MIXERCONTROL);            controls.pamxctrl = &control;            control.cbStruct = sizeof(MIXERCONTROL);            result = mixerGetLineControls(mixer->hInputMixer,                                          &controls,                                          MIXER_GETLINECONTROLSF_ONEBYTYPE);            if (result == MMSYSERR_NOERROR)               mixer->src[j].controlID = control.dwControlID;            else               mixer->src[j].controlID = 0;         }      }   }   /*    * Find the ID of the output speaker volume control    */   mixer->speakerID = 0;      if (mixer->hOutputMixer) {      line.cbStruct = sizeof(MIXERLINE);      line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;      result = mixerGetLineInfo(mixer->hOutputMixer,                                &line,                                MIXER_GETLINEINFOF_COMPONENTTYPE);      if (result == MMSYSERR_NOERROR) {         controls.cbStruct = sizeof(MIXERLINECONTROLS);         controls.dwLineID = line.dwLineID;         controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;         controls.cbmxctrl = sizeof(MIXERCONTROL);         controls.pamxctrl = &control;         control.cbStruct = sizeof(MIXERCONTROL);         result = mixerGetLineControls(mixer->hOutputMixer,                                       &controls,                                       MIXER_GETLINECONTROLSF_ONEBYTYPE);         if (result == MMSYSERR_NOERROR)            mixer->speakerID = control.dwControlID;      }   }   return (PxMixer *)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 ){  MMRESULT result;  DWORD vol = 0;  unsigned short mono_vol = 0;  PxInfo *info = (PxInfo *)mixer;	/* invalid waveID, return zero */	if ( info->waveID == -1 )		return 0.0 ;	/* get the wave output volume */	result = waveOutGetVolume( (HWAVEOUT)( info->waveID ), &vol);	/* on failure, mark waveID as invalid and return zero */	if ( result != MMSYSERR_NOERROR )	{		info->waveID = -1 ;		return 0.0 ;	}  mono_vol = (unsigned short)vol;  return (PxVolume)mono_vol/65535.0;}void Px_SetPCMOutputVolume( PxMixer *mixer, PxVolume volume ){	MMRESULT result;	PxInfo *info = (PxInfo *)mixer;	/* invalid waveID */	if ( info->waveID == -1 )		return ;	/* set the wave output volume */	result = waveOutSetVolume( (HWAVEOUT)( info->waveID ), MAKELONG(volume*0xFFFF, volume*0xFFFF));	/* on failure, mark waveID as invalid  */	if ( result != MMSYSERR_NOERROR )	{		info->waveID = -1 ;	}	return ;}/* 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;   MIXERCONTROLDETAILS details;   MIXERCONTROLDETAILS_BOOLEAN flags[32];   MMRESULT result;   int i;   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];   result = mixerGetControlDetails(info->hInputMixer,                                   (LPMIXERCONTROLDETAILS)&details,                                   MIXER_GETCONTROLDETAILSF_VALUE);   if (result == MMSYSERR_NOERROR) {      for(i=0; i<info->numInputs; i++)         if (flags[i].fValue)            return i;   }   return 0;}void Px_SetCurrentInputSource( PxMixer *mixer, int i ){   PxInfo *info = (PxInfo *)mixer;   MIXERCONTROLDETAILS details;   MIXERCONTROLDETAILS_BOOLEAN flags[32];   MMRESULT result;   int j;   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];   for(j=0; j<info->numInputs; j++)      flags[j].fValue = (i == j);   result = mixerSetControlDetails(info->hInputMixer,                                   (LPMIXERCONTROLDETAILS)&details,                                   MIXER_SETCONTROLDETAILSF_VALUE);}/* Input volume*/PxVolume Px_GetInputVolume( PxMixer *mixer ){   PxInfo *info = (PxInfo *)mixer;   PxVolume vol;   int src = Px_GetCurrentInputSource(mixer);   vol = -1.0;   VolumeFunction(info->hInputMixer, info->src[src].controlID, &vol);   return vol;}void Px_SetInputVolume( PxMixer *mixer, PxVolume volume ){   PxInfo *info = (PxInfo *)mixer;   int src = Px_GetCurrentInputSource(mixer);   VolumeFunction(info->hInputMixer, info->src[src].controlID, &volume);}/*  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 ){}

⌨️ 快捷键说明

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