📄 windowsaudioinputdevice_mixer.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**********/// Copyright (c) 2001-2004 Live Networks, Inc. All rights reserved.// Windows implementation of a generic audio input device// This version uses Windows' built-in software mixer.// Implementation#include <WindowsAudioInputDevice_mixer.hh>////////// Mixer and AudioInputPort definition //////////class AudioInputPort {public: int tag; DWORD dwComponentType; char name[MIXER_LONG_NAME_CHARS];};class Mixer {public: Mixer(); virtual ~Mixer(); void open(unsigned numChannels, unsigned samplingFrequency, unsigned granularityInMS); void open(); // open with default parameters void getPortsInfo(); Boolean enableInputPort(unsigned portIndex, char const*& errReason, MMRESULT& errCode); void close(); unsigned index; HMIXER hMixer; // valid when open DWORD dwRecLineID; // valid when open unsigned numPorts; AudioInputPort* ports; char name[MAXPNAMELEN];};////////// AudioInputDevice (remaining) implementation //////////AudioInputDevice*AudioInputDevice::createNew(UsageEnvironment& env, int inputPortNumber, unsigned char bitsPerSample, unsigned char numChannels, unsigned samplingFrequency, unsigned granularityInMS) { Boolean success; WindowsAudioInputDevice* newSource = new WindowsAudioInputDevice(env, inputPortNumber, bitsPerSample, numChannels, samplingFrequency, granularityInMS, success); if (!success) {delete newSource; newSource = NULL;} return newSource;}AudioPortNames* AudioInputDevice::getPortNames() { WindowsAudioInputDevice::initializeIfNecessary(); AudioPortNames* portNames = new AudioPortNames; portNames->numPorts = WindowsAudioInputDevice::numInputPortsTotal; portNames->portName = new char*[WindowsAudioInputDevice::numInputPortsTotal]; // If there's more than one mixer, print only the port name. // If there's two or more mixers, also include the mixer name // (to disambiguate port names that may be the same name in different mixers) char portNameBuffer[2*MAXPNAMELEN+10/*slop*/]; char mixerNameBuffer[MAXPNAMELEN]; char const* portNameFmt; if (WindowsAudioInputDevice::numMixers <= 1) { portNameFmt = "%s"; } else { portNameFmt = "%s (%s)"; } unsigned curPortNum = 0; for (unsigned i = 0; i < WindowsAudioInputDevice::numMixers; ++i) { Mixer& mixer = WindowsAudioInputDevice::ourMixers[i]; if (WindowsAudioInputDevice::numMixers <= 1) { mixerNameBuffer[0] = '\0'; } else { strncpy(mixerNameBuffer, mixer.name, sizeof mixerNameBuffer);#if 0 // Hack: Simplify the mixer name, by truncating after the first space character: for (int k = 0; k < sizeof mixerNameBuffer && mixerNameBuffer[k] != '\0'; ++k) { if (mixerNameBuffer[k] == ' ') { mixerNameBuffer[k] = '\0'; break; } }#endif } for (unsigned j = 0; j < mixer.numPorts; ++j) { sprintf(portNameBuffer, portNameFmt, mixer.ports[j].name, mixerNameBuffer); portNames->portName[curPortNum++] = strDup(portNameBuffer); } } return portNames;}////////// WindowsAudioInputDevice implementation //////////WindowsAudioInputDevice::WindowsAudioInputDevice(UsageEnvironment& env, int inputPortNumber, unsigned char bitsPerSample, unsigned char numChannels, unsigned samplingFrequency, unsigned granularityInMS, Boolean& success) : WindowsAudioInputDevice_common(env, inputPortNumber, bitsPerSample, numChannels, samplingFrequency, granularityInMS), fCurMixerId(-1) { success = initialSetInputPort(inputPortNumber);}WindowsAudioInputDevice::~WindowsAudioInputDevice() { if (fCurMixerId >= 0) ourMixers[fCurMixerId].close(); delete[] ourMixers; ourMixers = NULL; numMixers = numInputPortsTotal = 0;}void WindowsAudioInputDevice::initializeIfNecessary() { if (ourMixers != NULL) return; // we've already been initialized numMixers = mixerGetNumDevs(); ourMixers = new Mixer[numMixers]; // Initialize each mixer: numInputPortsTotal = 0; for (unsigned i = 0; i < numMixers; ++i) { Mixer& mixer = ourMixers[i]; mixer.index = i; mixer.open(); if (mixer.hMixer != NULL) { // This device has a valid mixer. Get information about its ports: mixer.getPortsInfo(); mixer.close(); if (mixer.numPorts == 0) continue; numInputPortsTotal += mixer.numPorts; } else { mixer.ports = NULL; mixer.numPorts = 0; } }}Boolean WindowsAudioInputDevice::setInputPort(int portIndex) { initializeIfNecessary(); if (portIndex < 0 || portIndex >= (int)numInputPortsTotal) { // bad index envir().setResultMsg("Bad input port index\n"); return False; } // Find the mixer and port that corresponds to "portIndex": int newMixerId, portWithinMixer, portIndexCount = 0; for (newMixerId = 0; newMixerId < (int)numMixers; ++newMixerId) { int prevPortIndexCount = portIndexCount; portIndexCount += ourMixers[newMixerId].numPorts; if (portIndexCount > portIndex) { // it's with this mixer portWithinMixer = portIndex - prevPortIndexCount; break; } } // Check that this mixer is allowed: if (allowedDeviceNames != NULL) { int i; for (i = 0; allowedDeviceNames[i] != NULL; ++i) { if (strncmp(ourMixers[newMixerId].name, allowedDeviceNames[i], strlen(allowedDeviceNames[i])) == 0) { // The allowed device name is a prefix of this mixer's name break; // this mixer is allowed } } if (allowedDeviceNames[i] == NULL) { // this mixer is not on the allowed list envir().setResultMsg("Access to this audio device is not allowed\n"); return False; } } if (newMixerId != fCurMixerId) { // The mixer has changed, so close the old one and open the new one: if (fCurMixerId >= 0) ourMixers[fCurMixerId].close(); fCurMixerId = newMixerId; ourMixers[fCurMixerId].open(fNumChannels, fSamplingFrequency, fGranularityInMS); } if (portIndex != fCurPortIndex) { // Change the input port: fCurPortIndex = portIndex; char const* errReason; MMRESULT errCode; if (!ourMixers[newMixerId].enableInputPort(portWithinMixer, errReason, errCode)) { char resultMsg[100]; sprintf(resultMsg, "Failed to enable input port: %s failed (0x%08x)\n", errReason, errCode); envir().setResultMsg(resultMsg); return False; } // Later, may also need to transfer 'gain' to new port ##### } return True;}unsigned WindowsAudioInputDevice::numMixers = 0;Mixer* WindowsAudioInputDevice::ourMixers = NULL;unsigned WindowsAudioInputDevice::numInputPortsTotal = 0;////////// Mixer and AudioInputPort implementation //////////Mixer::Mixer()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -