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

📄 px_win_wmme.c

📁 IAX协议客户端源码
💻 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. * */#if defined(WIN32) || defined(_WIN32_WCE)#include <stdlib.h>#define strcasecmp _stricmp#define strncasecmp _strnicmp#else#include <strings.h>#endif#include <windows.h>#include "portaudio.h"#include "portmixer.h"#include "pa_cpuload.h"#include "pa_process.h"#include "pa_stream.h"typedef struct{    HANDLE bufferEvent;    void *waveHandles;    unsigned int deviceCount;    /* unsigned int channelCount; */    WAVEHDR **waveHeaders;                  /* waveHeaders[device][buffer] */    unsigned int bufferCount;    unsigned int currentBufferIndex;    unsigned int framesPerBuffer;    unsigned int framesUsedInCurrentBuffer;}PaWinMmeSingleDirectionHandlesAndBuffers;/* PaWinMmeStream - a stream data structure specifically for this implementation *//* note that struct PaWinMmeStream is typedeffed to PaWinMmeStream above. */struct PaWinMmeStream{    PaUtilStreamRepresentation streamRepresentation;    PaUtilCpuLoadMeasurer cpuLoadMeasurer;    PaUtilBufferProcessor bufferProcessor;    int primeStreamUsingCallback;    PaWinMmeSingleDirectionHandlesAndBuffers input;    PaWinMmeSingleDirectionHandlesAndBuffers output;    /* Processing thread management -------------- */    HANDLE abortEvent;    HANDLE processingThread;    DWORD processingThreadId;    char throttleProcessingThreadOnOverload; /* 0 -> don't throtte, non-0 -> throttle */    int processingThreadPriority;    int highThreadPriority;    int throttledThreadPriority;    unsigned long throttledSleepMsecs;    int isStopped;    volatile int isActive;    volatile int stopProcessing; /* stop thread once existing buffers have been returned */    volatile int abortProcessing; /* stop thread immediately */    DWORD allBuffersDurationMs; /* used to calculate timeouts */};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 ){   struct PaWinMmeStream *past;   HWAVEIN hWaveIn;   HWAVEOUT hWaveOut;   PxInfo *mixer;   MMRESULT result;   if (!pa_stream)      return NULL;   mixer = (PxInfo *)malloc(sizeof(PxInfo));   mixer->hInputMixer = NULL;   mixer->hOutputMixer = NULL;   past = (struct PaWinMmeStream *) pa_stream;   hWaveIn = 0;   if (past->input.waveHandles) {      hWaveIn = ((HWAVEIN *)past->input.waveHandles)[0];   }   hWaveOut = 0;   if (past->output.waveHandles) {      hWaveOut = ((HWAVEOUT *)past->output.waveHandles)[0];   }   if (hWaveIn) {      result = mixerOpen((HMIXER *)&mixer->hInputMixer, (UINT)hWaveIn, 0, 0, MIXER_OBJECTF_HWAVEIN);      if (result != MMSYSERR_NOERROR) {         free(mixer);         return NULL;      }   }   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 = -1;   if (mixer->hInputMixer)   {      MIXERLINE line;      line.cbStruct = sizeof(MIXERLINE);      line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;      result = mixerGetLineInfo(mixer->hInputMixer,                                &line,                                MIXER_GETLINEINFOF_COMPONENTTYPE);      if (result == MMSYSERR_NOERROR)      {         /* if the WaveInDestination has an InputSelectorControl (Mux or Mixer)          * get the names and IDs of all of the input sources          * make sure the name of the MicrophoneSource (if there is one)          * is "microphone" since pa_start() checks for it          */         MIXERLINECONTROLS controls;         MIXERCONTROL control;         controls.cbStruct = sizeof(MIXERLINECONTROLS);         controls.cbmxctrl = sizeof(MIXERCONTROL);         controls.pamxctrl = &control;         control.cbStruct = sizeof(MIXERCONTROL);         controls.dwLineID = line.dwLineID;         controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;         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)         {            int j;            int exactMic = -1;            int startMic = -1;            int firstMic = -1;            MIXERCONTROLDETAILS details;            MIXERCONTROLDETAILS_LISTTEXT mixList[32];            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;            controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;            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;               controls.dwLineID = mixer->src[j].lineID;               result = mixerGetLineControls(mixer->hInputMixer,                     &controls,                     MIXER_GETLINECONTROLSF_ONEBYTYPE);               if (result == MMSYSERR_NOERROR)               {                  /* mark as volume control */                  mixer->src[j].controlID = control.dwControlID;               }               else               {                  /* mark as NOT volume control */                  mixer->src[j].controlID = 0;               }               line.dwLineID = mixer->src[j].lineID;               result = mixerGetLineInfo(mixer->hInputMixer, &line, MIXER_GETLINEINFOF_LINEID);               if (result == MMSYSERR_NOERROR &&                     line.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)               {                  if (exactMic == -1)                  {                     if (strcasecmp(mixList[j].szName, "microphone") == 0)                     {                        exactMic = j;                     }                     else if (startMic == -1)                     {                        if (strncasecmp(mixList[j].szName, "microphone",                                 strlen("microphone")) == 0)                        {                           startMic = j;                        }                        else if (firstMic == -1)                        {                           firstMic = j;                        }                     }                  }               }               strcpy(mixer->src[j].name, mixList[j].szName);            }            if (exactMic == -1)            {               if (startMic != -1)               {                  strcpy(mixer->src[startMic].name, "microphone");               }               else if (firstMic != -1)               {                       strcpy(mixer->src[firstMic].name, "microphone");               }            }         }         else         {            /* if the WaveInDestination does not have an InputSelector             * see if the WaveInDestination SourceLine has a VolumeControl             */            controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;            result = mixerGetLineControls(mixer->hInputMixer,                                          &controls,                                          MIXER_GETLINECONTROLSF_ONEBYTYPE);            if (result == MMSYSERR_NOERROR)            {               mixer->src[0].lineID = line.dwLineID;               strcpy(mixer->src[0].name, line.szName);               mixer->src[0].controlID = control.dwControlID;               mixer->numInputs = 1;            }            else            {               line.dwSource = 0;               result = mixerGetLineInfo(mixer->hInputMixer,                                         &line,                                         MIXER_GETLINEINFOF_SOURCE);               if (result == MMSYSERR_NOERROR)               {                  mixer->src[0].lineID = line.dwLineID;                  strcpy(mixer->src[0].name, line.szName);                  controls.dwLineID = line.dwLineID;                  result = mixerGetLineControls(mixer->hInputMixer,                                                &controls,                                                MIXER_GETLINECONTROLSF_ONEBYTYPE);                  if (result == MMSYSERR_NOERROR)                  {                     mixer->src[0].controlID = control.dwControlID;                  }                  else                  {                     mixer->src[0].controlID = 0;                  }                  mixer->numInputs = 1;               }            }         }      }   }   // mixer->speakerID = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS/VolumeControl   // mixer->speakerID = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES/VolumeControl   // mixer->speakerID = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED/VolumeControl   mixer->speakerID = -1;   mixer->waveID = -1;   if (mixer->hOutputMixer) {      const DWORD componentTypes [] =      {         MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,         MIXERLINE_COMPONENTTYPE_DST_HEADPHONES,         MIXERLINE_COMPONENTTYPE_DST_UNDEFINED,      };      const size_t componentTypeLen = sizeof(componentTypes) / sizeof(DWORD);      DWORD j;      MIXERLINE line;      line.cbStruct = sizeof(MIXERLINE);      for (j = 0; j < componentTypeLen; j++)      {         line.dwComponentType = componentTypes[j];         result = mixerGetLineInfo(mixer->hOutputMixer,                                   &line,                                   MIXER_GETLINEINFOF_COMPONENTTYPE);         if (result == MMSYSERR_NOERROR)            break;      }      if (result == MMSYSERR_NOERROR)      {         MIXERLINECONTROLS controls;         MIXERCONTROL control;         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;         // mixer->waveID = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT/VolumeControl         const DWORD numSources = line.cConnections;         for (j = 0; j < numSources; j++)         {             line.dwSource = j;             result = mixerGetLineInfo(mixer->hOutputMixer,                                       &line,                                       MIXER_GETLINEINFOF_SOURCE);             if (result == MMSYSERR_NOERROR &&                 line.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT)             {                controls.dwLineID = line.dwLineID;                result = mixerGetLineControls(mixer->hOutputMixer,                                              &controls,                                              MIXER_GETLINECONTROLSF_ONEBYTYPE);                if (result == MMSYSERR_NOERROR)                {                   mixer->waveID = control.dwControlID;                   break;                }             }         }      }   }   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 ){

⌨️ 快捷键说明

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