| Index: webrtc/modules/audio_device/win/audio_mixer_manager_win.cc
|
| diff --git a/webrtc/modules/audio_device/win/audio_mixer_manager_win.cc b/webrtc/modules/audio_device/win/audio_mixer_manager_win.cc
|
| deleted file mode 100644
|
| index ae2d00faeb89ecb899e8dddd7dd63e5fbb5bde53..0000000000000000000000000000000000000000
|
| --- a/webrtc/modules/audio_device/win/audio_mixer_manager_win.cc
|
| +++ /dev/null
|
| @@ -1,2725 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#include "webrtc/modules/audio_device/win/audio_mixer_manager_win.h"
|
| -#include "webrtc/system_wrappers/include/trace.h"
|
| -
|
| -#include <assert.h> // assert()
|
| -#include <strsafe.h> // StringCchCopy(), StringCchCat(), StringCchPrintf()
|
| -
|
| -#ifdef _WIN32
|
| -// removes warning: "reinterpret_cast: conversion from 'UINT' to 'HMIXEROBJ'
|
| -// of greater size"
|
| -#pragma warning(disable:4312)
|
| -#endif
|
| -
|
| -// Avoids the need of Windows 7 SDK
|
| -#ifndef WAVE_MAPPED_kDefaultCommunicationDevice
|
| -#define WAVE_MAPPED_kDefaultCommunicationDevice 0x0010
|
| -#endif
|
| -
|
| -namespace webrtc {
|
| -
|
| -// ============================================================================
|
| -// CONSTRUCTION/DESTRUCTION
|
| -// ============================================================================
|
| -
|
| -AudioMixerManager::AudioMixerManager(const int32_t id) :
|
| - _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
|
| - _id(id),
|
| - _inputMixerHandle(NULL),
|
| - _outputMixerHandle(NULL)
|
| -{
|
| - WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s constructed", __FUNCTION__);
|
| - ClearSpeakerState();
|
| - ClearMicrophoneState();
|
| -}
|
| -
|
| -AudioMixerManager::~AudioMixerManager()
|
| -{
|
| - WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destructed", __FUNCTION__);
|
| -
|
| - Close();
|
| -
|
| - delete &_critSect;
|
| -}
|
| -
|
| -// ============================================================================
|
| -// PUBLIC METHODS
|
| -// ============================================================================
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// Close
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::Close()
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_outputMixerHandle != NULL)
|
| - {
|
| - mixerClose(_outputMixerHandle);
|
| - _outputMixerHandle = NULL;
|
| - }
|
| - if (_inputMixerHandle != NULL)
|
| - {
|
| - mixerClose(_inputMixerHandle);
|
| - _inputMixerHandle = NULL;
|
| - }
|
| - return 0;
|
| -
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// CloseSpeaker
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::CloseSpeaker()
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - ClearSpeakerState(_outputMixerID);
|
| -
|
| - mixerClose(_outputMixerHandle);
|
| - _outputMixerHandle = NULL;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// CloseMicrophone
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::CloseMicrophone()
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - ClearMicrophoneState(_inputMixerID);
|
| -
|
| - mixerClose(_inputMixerHandle);
|
| - _inputMixerHandle = NULL;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// EnumerateAll
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::EnumerateAll()
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - UINT nDevices = mixerGetNumDevs();
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#mixer devices: %u", nDevices);
|
| -
|
| - MIXERCAPS caps;
|
| - MIXERLINE destLine;
|
| - MIXERLINE sourceLine;
|
| - MIXERCONTROL controlArray[MAX_NUMBER_OF_LINE_CONTROLS];
|
| -
|
| - UINT mixId(0);
|
| - UINT destId(0);
|
| - UINT sourceId(0);
|
| -
|
| - for (mixId = 0; mixId < nDevices; mixId++)
|
| - {
|
| - if (!GetCapabilities(mixId, caps, true))
|
| - continue;
|
| -
|
| - for (destId = 0; destId < caps.cDestinations; destId++)
|
| - {
|
| - GetDestinationLineInfo(mixId, destId, destLine, true);
|
| - GetAllLineControls(mixId, destLine, controlArray, true);
|
| -
|
| - for (sourceId = 0; sourceId < destLine.cConnections; sourceId++)
|
| - {
|
| - GetSourceLineInfo(mixId, destId, sourceId, sourceLine, true);
|
| - GetAllLineControls(mixId, sourceLine, controlArray, true);
|
| - }
|
| - }
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// EnumerateSpeakers
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::EnumerateSpeakers()
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - UINT nDevices = mixerGetNumDevs();
|
| - if (nDevices > MAX_NUMBER_MIXER_DEVICES)
|
| - {
|
| - assert(false);
|
| - return -1;
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#mixer devices: %u", nDevices);
|
| -
|
| - MIXERCAPS caps;
|
| - MIXERLINE destLine;
|
| - MIXERCONTROL controlArray[MAX_NUMBER_OF_LINE_CONTROLS];
|
| -
|
| - UINT mixId(0);
|
| - UINT destId(0);
|
| -
|
| - ClearSpeakerState();
|
| -
|
| - // scan all avaliable mixer devices
|
| - for (mixId = 0; mixId < nDevices; mixId++)
|
| - {
|
| - // get capabilities for the specified mixer ID
|
| - if (!GetCapabilities(mixId, caps))
|
| - continue;
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[mixerID=%d] %s: ", mixId, WideToUTF8(caps.szPname));
|
| - // scan all avaliable destinations for this mixer
|
| - for (destId = 0; destId < caps.cDestinations; destId++)
|
| - {
|
| - GetDestinationLineInfo(mixId, destId, destLine);
|
| - if ((destLine.cControls == 0) || // no controls or
|
| - (destLine.cConnections == 0) || // no source lines or
|
| - (destLine.fdwLine & MIXERLINE_LINEF_DISCONNECTED) || // disconnected or
|
| - !(destLine.fdwLine & MIXERLINE_LINEF_ACTIVE)) // inactive
|
| - {
|
| - // don't store this line ID since it will not be possible to control
|
| - continue;
|
| - }
|
| - if ((destLine.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS) ||
|
| - (destLine.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_HEADPHONES))
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found valid speaker/headphone (name: %s, ID: %u)", WideToUTF8(destLine.szName), destLine.dwLineID);
|
| - _speakerState[mixId].dwLineID = destLine.dwLineID;
|
| - _speakerState[mixId].speakerIsValid = true;
|
| - // retrieve all controls for the speaker component
|
| - GetAllLineControls(mixId, destLine, controlArray);
|
| - for (UINT c = 0; c < destLine.cControls; c++)
|
| - {
|
| - if (controlArray[c].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
|
| - {
|
| - _speakerState[mixId].dwVolumeControlID = controlArray[c].dwControlID;
|
| - _speakerState[mixId].volumeControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found volume control (name: %s, ID: %u)", WideToUTF8(controlArray[c].szName), controlArray[c].dwControlID);
|
| - }
|
| - else if (controlArray[c].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
|
| - {
|
| - _speakerState[mixId].dwMuteControlID = controlArray[c].dwControlID;
|
| - _speakerState[mixId].muteControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found mute control (name: %s, ID: %u)", WideToUTF8(controlArray[c].szName), controlArray[c].dwControlID);
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - }
|
| - if (!SpeakerIsValid(mixId))
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to find a valid speaker destination line", mixId);
|
| - }
|
| - }
|
| -
|
| - if (ValidSpeakers() == 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to locate any valid speaker line");
|
| - return -1;
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// EnumerateMicrophones
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::EnumerateMicrophones()
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - UINT nDevices = mixerGetNumDevs();
|
| - if (nDevices > MAX_NUMBER_MIXER_DEVICES)
|
| - {
|
| - assert(false);
|
| - return -1;
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#mixer devices: %u", nDevices);
|
| -
|
| - MIXERCAPS caps;
|
| - MIXERLINE destLine;
|
| - MIXERLINE sourceLine;
|
| - MIXERCONTROL controlArray[MAX_NUMBER_OF_LINE_CONTROLS];
|
| -
|
| - UINT mixId(0);
|
| - UINT destId(0);
|
| -
|
| - ClearMicrophoneState();
|
| -
|
| - // scan all avaliable mixer devices
|
| - for (mixId = 0; mixId < nDevices; mixId++)
|
| - {
|
| - // get capabilities for the specified mixer ID
|
| - if (!GetCapabilities(mixId, caps))
|
| - continue;
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[mixerID=%d] %s: ", mixId, WideToUTF8(caps.szPname));
|
| - // scan all avaliable destinations for this mixer
|
| - for (destId = 0; destId < caps.cDestinations; destId++)
|
| - {
|
| - GetDestinationLineInfo(mixId, destId, destLine);
|
| -
|
| - if ((destLine.cConnections == 0) || // no source lines or
|
| - (destLine.fdwLine & MIXERLINE_LINEF_DISCONNECTED) || // disconnected or
|
| - !(destLine.fdwLine & MIXERLINE_LINEF_ACTIVE)) // inactive
|
| - {
|
| - // Don't store this line ID since there are no sources connected to this destination.
|
| - // Compare with the speaker side where we also exclude lines with no controls.
|
| - continue;
|
| - }
|
| -
|
| - if (destLine.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_WAVEIN)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found valid Wave In destination (name: %s, ID: %u)", WideToUTF8(destLine.szName), destLine.dwLineID);
|
| - _microphoneState[mixId].dwLineID = destLine.dwLineID;
|
| - _microphoneState[mixId].microphoneIsValid = true;
|
| -
|
| - // retrieve all controls for the identified wave-in destination
|
| - if (!GetAllLineControls(mixId, destLine, controlArray))
|
| - {
|
| - // This destination has no controls. We must try to control
|
| - // one of its sources instead.
|
| - // This is a rare state but has been found for some
|
| - // Logitech USB headsets.
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "this destination has no controls => must control source");
|
| - for (DWORD sourceId = 0; sourceId < destLine.cConnections; sourceId++)
|
| - {
|
| - GetSourceLineInfo(mixId, destId, sourceId, sourceLine, false);
|
| - if (sourceLine.dwComponentType ==
|
| - MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "found microphone source ( name: %s, ID: %u)",
|
| - WideToUTF8(sourceLine.szName), sourceId);
|
| - GetAllLineControls(mixId, sourceLine, controlArray, false);
|
| - // scan the controls for this source and search for volume,
|
| - // mute and on/off (<=> boost) controls
|
| - for (UINT sc = 0; sc < sourceLine.cControls; sc++)
|
| - {
|
| - if (controlArray[sc].dwControlType ==
|
| - MIXERCONTROL_CONTROLTYPE_VOLUME)
|
| - {
|
| - // store this volume control
|
| - _microphoneState[mixId].dwVolumeControlID =
|
| - controlArray[sc].dwControlID;
|
| - _microphoneState[mixId].volumeControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "found volume control (name: %s, ID: %u)",
|
| - WideToUTF8(controlArray[sc].szName),
|
| - controlArray[sc].dwControlID);
|
| - }
|
| - else if (controlArray[sc].dwControlType ==
|
| - MIXERCONTROL_CONTROLTYPE_MUTE)
|
| - {
|
| - // store this mute control
|
| - _microphoneState[mixId].dwMuteControlID =
|
| - controlArray[sc].dwControlID;
|
| - _microphoneState[mixId].muteControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "found mute control (name: %s, ID: %u)",
|
| - WideToUTF8(controlArray[sc].szName),
|
| - controlArray[sc].dwControlID);
|
| - }
|
| - else if (controlArray[sc].dwControlType ==
|
| - MIXERCONTROL_CONTROLTYPE_ONOFF ||
|
| - controlArray[sc].dwControlType ==
|
| - MIXERCONTROL_CONTROLTYPE_LOUDNESS)
|
| - {
|
| - // store this on/off control (most likely a Boost control)
|
| - _microphoneState[mixId].dwOnOffControlID =
|
| - controlArray[sc].dwControlID;
|
| - _microphoneState[mixId].onOffControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "found on/off control (name: %s, ID: %u)",
|
| - WideToUTF8(controlArray[sc].szName),
|
| - controlArray[sc].dwControlID);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - break;
|
| - }
|
| -
|
| - // It seems like there are three different configurations we can find in this state:
|
| - //
|
| - // (1) The Wave-in destination contains one MUX control only
|
| - // (2) The Wave-in destination contains one or more controls where one is a volume control
|
| - // (3) On Vista and Win 7, it seems like case 2 above is extended.
|
| - // It is common that a Wave-in destination has two master controls (volume and mute),
|
| - // AND a microphone source as well with its own volume and mute controls with unique
|
| - // identifiers. Initial tests have shown that it is sufficient to modify the master
|
| - // controls only. The source controls will "follow" the master settings, hence the
|
| - // source controls seem to be redundant.
|
| - //
|
| - // For case 1, we should locate the selected source and its controls. The MUX setting will
|
| - // give us the selected source. NOTE - the selecion might not be a microphone.
|
| - //
|
| - // For case 2, the volume control works as a master level control and we should use that one.
|
| - //
|
| - // For case 3, we use the master controls only and assume that the source control will "follow".
|
| - //
|
| - // Examples of case 1: - SigmaTel Audio (built-in)
|
| - // - add more..
|
| - //
|
| - // Examples of case 2: - Plantronics USB Headset
|
| - // - Eutectics IPP 200 USB phone
|
| - // - add more...
|
| - //
|
| - // Examples of case 3: - Realtek High Definition on Vista (TL)
|
| - // - add more...
|
| -
|
| - if ((destLine.cControls == 1) &&
|
| - (controlArray[0].dwControlType == MIXERCONTROL_CONTROLTYPE_MUX))
|
| - {
|
| - // Case 1: MUX control detected => locate the selected source and its volume control
|
| - // Note that, the selecion might not be a microphone. A warning is given for
|
| - // this case only, i.e., it is OK to control a selected Line In source as long
|
| - // as it is connected to the wave-in destination.
|
| -
|
| - UINT selection(0);
|
| - const DWORD nItemsInMux(controlArray[0].cMultipleItems);
|
| -
|
| - // decide which source line that is selected in the mux
|
| - if (GetSelectedMuxSource(mixId, controlArray[0].dwControlID, nItemsInMux, selection))
|
| - {
|
| - // selection now contains the index of the selected source =>
|
| - // read the line information for this source
|
| - // if conditions listed below
|
| - // condition 1: invalid source
|
| - // condition 2: no controls
|
| - // condition 3: disconnected
|
| - // condition 4: inactive
|
| - if (!GetSourceLineInfo(mixId, destId, selection, sourceLine) ||
|
| - (sourceLine.cControls == 0) ||
|
| - (sourceLine.fdwLine & MIXERLINE_LINEF_DISCONNECTED) ||
|
| - !(sourceLine.fdwLine & MIXERLINE_LINEF_ACTIVE))
|
| - {
|
| - continue;
|
| - }
|
| -
|
| - if (sourceLine.dwComponentType != MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
|
| - {
|
| - // add more details about the selected source (not a microphone)
|
| - TraceComponentType(sourceLine.dwComponentType);
|
| - // send a warning just to inform about the fact that a non-microphone source will be controlled
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "the selected (to be controlled) source is not a microphone type");
|
| - }
|
| -
|
| - // retrieve all controls for the selected source
|
| - GetAllLineControls(mixId, sourceLine, controlArray);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "MUX selection is %u [0,%u]", selection, nItemsInMux-1);
|
| -
|
| - // scan the controls for this source and search for volume, mute and on/off (<=> boost) controls
|
| - for (UINT sc = 0; sc < sourceLine.cControls; sc++)
|
| - {
|
| - if (controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
|
| - {
|
| - // store this volume control
|
| - _microphoneState[mixId].dwVolumeControlID = controlArray[sc].dwControlID;
|
| - _microphoneState[mixId].volumeControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found volume control (name: %s, ID: %u)", WideToUTF8(controlArray[sc].szName), controlArray[sc].dwControlID);
|
| - }
|
| - else if (controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
|
| - {
|
| - // store this mute control
|
| - _microphoneState[mixId].dwMuteControlID = controlArray[sc].dwControlID;
|
| - _microphoneState[mixId].muteControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found mute control (name: %s, ID: %u)", WideToUTF8(controlArray[sc].szName), controlArray[sc].dwControlID);
|
| - }
|
| - else if (controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF ||
|
| - controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_LOUDNESS)
|
| - {
|
| - // store this on/off control (most likely a Boost control)
|
| - _microphoneState[mixId].dwOnOffControlID = controlArray[sc].dwControlID;
|
| - _microphoneState[mixId].onOffControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found on/off control (name: %s, ID: %u)", WideToUTF8(controlArray[sc].szName), controlArray[sc].dwControlID);
|
| - }
|
| - }
|
| - }
|
| - else
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to detect which source to control");
|
| - }
|
| -
|
| - }
|
| - else if (destLine.cConnections == 1)
|
| - {
|
| - // Case 2 or Case 3:
|
| -
|
| - GetSourceLineInfo(mixId, destId, 0, sourceLine);
|
| - if ((sourceLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) &&
|
| - (sourceLine.cControls > 0))
|
| - {
|
| - // Case 3: same as Case 2 below but we have also detected a Microphone source
|
| - // with its own controls. So far, I have not been able to find any device
|
| - // where it is required to modify these controls. Until I have found such
|
| - // a device, this case will be handled as a Case 2 (see below).
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "microphone source controls will not be controlled");
|
| - }
|
| - else if ((sourceLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) &&
|
| - (sourceLine.cControls == 0))
|
| - {
|
| - // default state on non Vista/Win 7 machines
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "microphone source has no controls => use master controls instead");
|
| - }
|
| - else
|
| - {
|
| - // add more details about the selected source (not a microphone)
|
| - TraceComponentType(sourceLine.dwComponentType);
|
| - // send a warning just to inform about the fact that a non-microphone source will be controlled
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "the connected (to be controlled) source is not a microphone type");
|
| - }
|
| -
|
| - // Case 2 : one source only and no MUX control detected =>
|
| - // locate the master volume control (and mute + boost controls if possible)
|
| -
|
| - // scan the controls for this wave-in destination and search for volume, mute and on/off (<=> boost) controls
|
| - for (UINT dc = 0; dc < destLine.cControls; dc++)
|
| - {
|
| - if (controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
|
| - {
|
| - // store this volume control
|
| - _microphoneState[mixId].dwVolumeControlID = controlArray[dc].dwControlID;
|
| - _microphoneState[mixId].volumeControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found volume control (name: %s, ID: %u)", WideToUTF8(controlArray[dc].szName), controlArray[dc].dwControlID);
|
| - }
|
| - else if (controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
|
| - {
|
| - // store this mute control
|
| - _microphoneState[mixId].dwMuteControlID = controlArray[dc].dwControlID;
|
| - _microphoneState[mixId].muteControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found mute control (name: %s, ID: %u)", WideToUTF8(controlArray[dc].szName), controlArray[dc].dwControlID);
|
| - }
|
| - else if (controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF ||
|
| - controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_LOUDNESS ||
|
| - controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN)
|
| - {
|
| - // store this on/off control
|
| - _microphoneState[mixId].dwOnOffControlID = controlArray[dc].dwControlID;
|
| - _microphoneState[mixId].onOffControlIsValid = true;
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found on/off control (name: %s, ID: %u)", WideToUTF8(controlArray[dc].szName), controlArray[dc].dwControlID);
|
| - }
|
| - }
|
| - }
|
| - else
|
| - {
|
| - // We are in a state where more than one source is connected to the wave-in destination.
|
| - // I am bailing out here for now until I understand this case better.
|
| - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to locate valid microphone controls for this mixer");
|
| - }
|
| - break;
|
| - }
|
| - } // for (destId = 0; destId < caps.cDestinations; destId++)
|
| -
|
| - if (!MicrophoneIsValid(mixId))
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to find a valid microphone destination line", mixId);
|
| - }
|
| - } // for (mixId = 0; mixId < nDevices; mixId++)
|
| -
|
| - if (ValidMicrophones() == 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to locate any valid microphone line");
|
| - return -1;
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// OpenSpeaker I(II)
|
| -//
|
| -// Verifies that the mixer contains a valid speaker destination line.
|
| -// Avoids opening the mixer if valid control has not been found.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::OpenSpeaker(AudioDeviceModule::WindowsDeviceType device)
|
| -{
|
| - if (device == AudioDeviceModule::kDefaultDevice)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenSpeaker(kDefaultDevice)");
|
| - }
|
| - else if (device == AudioDeviceModule::kDefaultCommunicationDevice)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenSpeaker(kDefaultCommunicationDevice)");
|
| - }
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - // Close any existing output mixer handle
|
| - //
|
| - if (_outputMixerHandle != NULL)
|
| - {
|
| - mixerClose(_outputMixerHandle);
|
| - _outputMixerHandle = NULL;
|
| - }
|
| -
|
| - MMRESULT res = MMSYSERR_NOERROR;
|
| - WAVEFORMATEX waveFormat;
|
| - HWAVEOUT hWaveOut(NULL);
|
| -
|
| - waveFormat.wFormatTag = WAVE_FORMAT_PCM ;
|
| - waveFormat.nChannels = 2;
|
| - waveFormat.nSamplesPerSec = 48000;
|
| - waveFormat.wBitsPerSample = 16;
|
| - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
|
| - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
|
| - waveFormat.cbSize = 0;
|
| -
|
| - // We need a waveform-audio output handle for the currently selected output device.
|
| - // This handle will then give us the corresponding mixer identifier. Once the mixer
|
| - // ID is known, it is possible to open the output mixer.
|
| - //
|
| - if (device == AudioDeviceModule::kDefaultCommunicationDevice)
|
| - {
|
| - // check if it is possible to open the default communication device (supported on Windows 7)
|
| - res = waveOutOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL |
|
| - WAVE_MAPPED_kDefaultCommunicationDevice | WAVE_FORMAT_QUERY);
|
| - if (MMSYSERR_NOERROR == res)
|
| - {
|
| - // if so, open the default communication device for real
|
| - res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_kDefaultCommunicationDevice);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device");
|
| - }
|
| - else
|
| - {
|
| - // use default device since default communication device was not avaliable
|
| - res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "unable to open default communication device => using default instead");
|
| - }
|
| - }
|
| - else if (device == AudioDeviceModule::kDefaultDevice)
|
| - {
|
| - // open default device since it has been requested
|
| - res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default output device");
|
| - }
|
| -
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutOpen() failed (err=%d)", res);
|
| - TraceWaveOutError(res);
|
| - }
|
| -
|
| - UINT mixerId(0);
|
| - HMIXER hMixer(NULL);
|
| -
|
| - // Retrieve the device identifier for a mixer device associated with the
|
| - // aquired waveform-audio output handle.
|
| - //
|
| - res = mixerGetID((HMIXEROBJ)hWaveOut, &mixerId, MIXER_OBJECTF_HWAVEOUT);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEOUT) failed (err=%d)", res);
|
| - // identification failed => use default mixer identifier (=0)
|
| - mixerId = 0;
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified output device <=> mixer ID %u", mixerId);
|
| -
|
| - // The waveform-audio output handle is no longer needed.
|
| - //
|
| - waveOutClose(hWaveOut);
|
| -
|
| - // Verify that the mixer contains a valid speaker destination line.
|
| - // Avoid opening the mixer if valid control has not been found.
|
| - //
|
| - if (!SpeakerIsValid(mixerId))
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the speaker volume for this mixer device");
|
| - return -1;
|
| - }
|
| -
|
| - // Open the specified mixer device and ensure that the device will not
|
| - // be removed until the application closes the handle.
|
| - //
|
| - res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
|
| - }
|
| -
|
| - // Store the output mixer handle and active mixer identifier
|
| - //
|
| - _outputMixerHandle = hMixer;
|
| - _outputMixerID = mixerId;
|
| -
|
| - if (_outputMixerHandle != NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the output mixer device is now open (0x%x)", _outputMixerHandle);
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// OpenSpeaker II(II)
|
| -//
|
| -// Verifies that the mixer contains a valid speaker destination line.
|
| -// Avoids opening the mixer if valid control has not been found.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::OpenSpeaker(uint16_t index)
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenSpeaker(index=%d)", index);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - // Close any existing output mixer handle
|
| - //
|
| - if (_outputMixerHandle != NULL)
|
| - {
|
| - mixerClose(_outputMixerHandle);
|
| - _outputMixerHandle = NULL;
|
| - }
|
| -
|
| - MMRESULT res;
|
| - WAVEFORMATEX waveFormat;
|
| - HWAVEOUT hWaveOut(NULL);
|
| -
|
| - const UINT deviceID(index); // use index parameter as device identifier
|
| -
|
| - waveFormat.wFormatTag = WAVE_FORMAT_PCM ;
|
| - waveFormat.nChannels = 2;
|
| - waveFormat.nSamplesPerSec = 48000;
|
| - waveFormat.wBitsPerSample = 16;
|
| - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
|
| - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
|
| - waveFormat.cbSize = 0;
|
| -
|
| - // We need a waveform-audio output handle for the currently selected output device.
|
| - // This handle will then give us the corresponding mixer identifier. Once the mixer
|
| - // ID is known, it is possible to open the output mixer.
|
| - //
|
| - res = waveOutOpen(&hWaveOut, deviceID, &waveFormat, 0, 0, CALLBACK_NULL);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutOpen(deviceID=%u) failed (err=%d)", index, res);
|
| - TraceWaveOutError(res);
|
| - }
|
| -
|
| - UINT mixerId(0);
|
| - HMIXER hMixer(NULL);
|
| -
|
| - // Retrieve the device identifier for a mixer device associated with the
|
| - // aquired waveform-audio output handle.
|
| - //
|
| - res = mixerGetID((HMIXEROBJ)hWaveOut, &mixerId, MIXER_OBJECTF_HWAVEOUT);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEOUT) failed (err=%d)", res);
|
| - // identification failed => use default mixer identifier (=0)
|
| - mixerId = 0;
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified output device <=> mixer ID %u", mixerId);
|
| -
|
| - // The waveform-audio output handle is no longer needed.
|
| - //
|
| - waveOutClose(hWaveOut);
|
| -
|
| - // Verify that the mixer contains a valid speaker destination line.
|
| - // Avoid opening the mixer if valid control has not been found.
|
| - //
|
| - if (!SpeakerIsValid(mixerId))
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the speaker volume for this mixer device");
|
| - return -1;
|
| - }
|
| -
|
| - // Open the specified mixer device and ensure that the device will not
|
| - // be removed until the application closes the handle.
|
| - //
|
| - res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
|
| - }
|
| -
|
| - // Store the output mixer handle and active mixer identifier
|
| - //
|
| - _outputMixerHandle = hMixer;
|
| - _outputMixerID = mixerId;
|
| -
|
| - if (_outputMixerHandle != NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the output mixer device is now open (0x%x)", _outputMixerHandle);
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// OpenMicrophone I(II)
|
| -//
|
| -// Verifies that the mixer contains a valid wave-in destination line.
|
| -// Avoids opening the mixer if valid control has not been found.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::OpenMicrophone(AudioDeviceModule::WindowsDeviceType device)
|
| -{
|
| - if (device == AudioDeviceModule::kDefaultDevice)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenMicrophone(kDefaultDevice)");
|
| - }
|
| - else if (device == AudioDeviceModule::kDefaultCommunicationDevice)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenMicrophone(kDefaultCommunicationDevice)");
|
| - }
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - // Close any existing output mixer handle
|
| - //
|
| - if (_inputMixerHandle != NULL)
|
| - {
|
| - mixerClose(_inputMixerHandle);
|
| - _inputMixerHandle = NULL;
|
| - }
|
| -
|
| - MMRESULT res = MMSYSERR_NOERROR;
|
| - WAVEFORMATEX waveFormat;
|
| - HWAVEIN hWaveIn(NULL);
|
| -
|
| - waveFormat.wFormatTag = WAVE_FORMAT_PCM ;
|
| - waveFormat.nChannels = 1;
|
| - waveFormat.nSamplesPerSec = 48000;
|
| - waveFormat.wBitsPerSample = 16;
|
| - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
|
| - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
|
| - waveFormat.cbSize = 0 ;
|
| -
|
| - // We need a waveform-audio input handle for the currently selected input device.
|
| - // This handle will then give us the corresponding mixer identifier. Once the mixer
|
| - // ID is known, it is possible to open the input mixer.
|
| - //
|
| - if (device == AudioDeviceModule::kDefaultCommunicationDevice)
|
| - {
|
| - // check if it is possible to open the default communication device (supported on Windows 7)
|
| - res = waveInOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL |
|
| - WAVE_MAPPED_kDefaultCommunicationDevice | WAVE_FORMAT_QUERY);
|
| - if (MMSYSERR_NOERROR == res)
|
| - {
|
| - // if so, open the default communication device for real
|
| - res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_kDefaultCommunicationDevice);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device");
|
| - }
|
| - else
|
| - {
|
| - // use default device since default communication device was not avaliable
|
| - res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
|
| - "unable to open default communication device => using default instead");
|
| - }
|
| - }
|
| - else if (device == AudioDeviceModule::kDefaultDevice)
|
| - {
|
| - // open default device since it has been requested
|
| - res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default input device");
|
| - }
|
| -
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInOpen() failed (err=%d)", res);
|
| - TraceWaveInError(res);
|
| - }
|
| -
|
| - UINT mixerId(0);
|
| - HMIXER hMixer(NULL);
|
| -
|
| - // Retrieve the device identifier for a mixer device associated with the
|
| - // aquired waveform-audio input handle.
|
| - //
|
| - res = mixerGetID((HMIXEROBJ)hWaveIn, &mixerId, MIXER_OBJECTF_HWAVEIN);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEIN) failed (err=%d)", res);
|
| - // identification failed => use default mixer identifier (=0)
|
| - mixerId = 0;
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified input device <=> mixer ID %u", mixerId);
|
| -
|
| - // The waveform-audio input handle is no longer needed.
|
| - //
|
| - waveInClose(hWaveIn);
|
| -
|
| - // Verify that the mixer contains a valid wave-in destination line and a volume control.
|
| - // Avoid opening the mixer if valid control has not been found.
|
| - //
|
| - if (!MicrophoneIsValid(mixerId))
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the microphone volume for this mixer device");
|
| - return -1;
|
| - }
|
| -
|
| - // Open the specified mixer device and ensure that the device will not
|
| - // be removed until the application closes the handle.
|
| - //
|
| - res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
|
| - }
|
| -
|
| - // Store the input mixer handle and active mixer identifier
|
| - //
|
| - _inputMixerHandle = hMixer;
|
| - _inputMixerID = mixerId;
|
| -
|
| - if (_inputMixerHandle != NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the input mixer device is now open (0x%x)", _inputMixerHandle);
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// OpenMicrophone II(II)
|
| -//
|
| -// Verifies that the mixer contains a valid wave-in destination line.
|
| -// Avoids opening the mixer if valid control has not been found.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::OpenMicrophone(uint16_t index)
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenMicrophone(index=%d)", index);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - // Close any existing input mixer handle
|
| - //
|
| - if (_inputMixerHandle != NULL)
|
| - {
|
| - mixerClose(_inputMixerHandle);
|
| - _inputMixerHandle = NULL;
|
| - }
|
| -
|
| - MMRESULT res;
|
| - WAVEFORMATEX waveFormat;
|
| - HWAVEIN hWaveIn(NULL);
|
| -
|
| - const UINT deviceID(index); // use index parameter as device identifier
|
| -
|
| - waveFormat.wFormatTag = WAVE_FORMAT_PCM ;
|
| - waveFormat.nChannels = 1;
|
| - waveFormat.nSamplesPerSec = 48000;
|
| - waveFormat.wBitsPerSample = 16;
|
| - waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
|
| - waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
|
| - waveFormat.cbSize = 0;
|
| -
|
| - // We need a waveform-audio input handle for the currently selected input device.
|
| - // This handle will then give us the corresponding mixer identifier. Once the mixer
|
| - // ID is known, it is possible to open the input mixer.
|
| - //
|
| - res = waveInOpen(&hWaveIn, deviceID, &waveFormat, 0, 0, CALLBACK_NULL);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInOpen(deviceID=%u) failed (err=%d)", index, res);
|
| - TraceWaveInError(res);
|
| - }
|
| -
|
| - UINT mixerId(0);
|
| - HMIXER hMixer(NULL);
|
| -
|
| - // Retrieve the device identifier for a mixer device associated with the
|
| - // aquired waveform-audio input handle.
|
| - //
|
| - res = mixerGetID((HMIXEROBJ)hWaveIn, &mixerId, MIXER_OBJECTF_HWAVEIN);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEIN) failed (err=%d)", res);
|
| - // identification failed => use default mixer identifier (=0)
|
| - mixerId = 0;
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified input device <=> mixer ID %u", mixerId);
|
| -
|
| - // The waveform-audio input handle is no longer needed.
|
| - //
|
| - waveInClose(hWaveIn);
|
| -
|
| - // Verify that the mixer contains a valid wave-in destination line.
|
| - // Avoid opening the mixer if valid control has not been found.
|
| - //
|
| - if (!MicrophoneIsValid(mixerId))
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the microphone volume for this mixer device");
|
| - return -1;
|
| - }
|
| -
|
| - // Open the specified mixer device and ensure that the device will not
|
| - // be removed until the application closes the handle.
|
| - //
|
| - res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
|
| - if (MMSYSERR_NOERROR != res)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
|
| - }
|
| -
|
| - // Store the input mixer handle and active mixer identifier
|
| - //
|
| - _inputMixerHandle = hMixer;
|
| - _inputMixerID = mixerId;
|
| -
|
| - if (_inputMixerHandle != NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the input mixer device is now open (0x%x)", _inputMixerHandle);
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerIsInitialized
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::SpeakerIsInitialized() const
|
| -{
|
| - WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - return (_outputMixerHandle != NULL);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneIsInitialized
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::MicrophoneIsInitialized() const
|
| -{
|
| - WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - return (_inputMixerHandle != NULL);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetSpeakerVolume
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SetSpeakerVolume(uint32_t volume)
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetSpeakerVolume(volume=%u)", volume);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_outputMixerID);
|
| - const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
|
| - DWORD dwValue(volume);
|
| -
|
| - // Set one unsigned control value for a specified volume-control identifier
|
| - //
|
| - if (!SetUnsignedControlValue(mixerID, dwControlID, dwValue))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - return (0);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerVolume
|
| -//
|
| -// Note that (MIXERCONTROL_CONTROLTYPE_VOLUME & MIXERCONTROL_CT_UNITS_MASK)
|
| -// always equals MIXERCONTROL_CT_UNITS_UNSIGNED;
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SpeakerVolume(uint32_t& volume) const
|
| -{
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_outputMixerID);
|
| - const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
|
| - DWORD dwValue(0);
|
| -
|
| - // Retrieve one unsigned control value for a specified volume-control identifier
|
| - //
|
| - if (!GetUnsignedControlValue(mixerID, dwControlID, dwValue))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - volume = dwValue;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MaxSpeakerVolume
|
| -//
|
| -// Note that (MIXERCONTROL_CONTROLTYPE_VOLUME & MIXERCONTROL_CT_UNITS_MASK)
|
| -// always equals MIXERCONTROL_CT_UNITS_UNSIGNED
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MaxSpeakerVolume(uint32_t& maxVolume) const
|
| -{
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_outputMixerID);
|
| - const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
|
| - MIXERCONTROL mixerControl;
|
| -
|
| - // Retrieve one control line for a specified volume-control identifier
|
| - //
|
| - if (!GetLineControl(mixerID, dwControlID, mixerControl))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - maxVolume = mixerControl.Bounds.dwMaximum;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MinSpeakerVolume
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MinSpeakerVolume(uint32_t& minVolume) const
|
| -{
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_outputMixerID);
|
| - const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
|
| - MIXERCONTROL mixerControl;
|
| -
|
| - // Retrieve one control line for a specified volume-control identifier
|
| - //
|
| - if (!GetLineControl(mixerID, dwControlID, mixerControl))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - minVolume = mixerControl.Bounds.dwMinimum;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerVolumeStepSize
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SpeakerVolumeStepSize(uint16_t& stepSize) const
|
| -{
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_outputMixerID);
|
| - MIXERCONTROL mixerControl;
|
| -
|
| - // Retrieve one control line for a specified volume-control identifier
|
| - //
|
| - if (!GetLineControl(mixerID, _speakerState[mixerID].dwVolumeControlID, mixerControl))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - stepSize = static_cast<uint16_t> (mixerControl.Metrics.cSteps);
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerVolumeIsAvailable
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SpeakerVolumeIsAvailable(bool& available)
|
| -{
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - available = _speakerState[_outputMixerID].volumeControlIsValid;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerMuteIsAvailable
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SpeakerMuteIsAvailable(bool& available)
|
| -{
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - available = _speakerState[_outputMixerID].muteControlIsValid;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetSpeakerMute
|
| -//
|
| -// This mute function works a master mute for the output speaker.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SetSpeakerMute(bool enable)
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetSpeakerMute(enable=%u)", enable);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - // Ensure that the selected speaker destination has a valid mute control.
|
| - // If so, its identifier was stored during the enumeration phase which must
|
| - // have taken place since the output mixer handle exists.
|
| - //
|
| - if (!_speakerState[_outputMixerID].muteControlIsValid)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this speaker line");
|
| - return -1;
|
| - }
|
| -
|
| - const DWORD dwControlID(_speakerState[_outputMixerID].dwMuteControlID);
|
| -
|
| - // Set one boolean control value for the specified mute-control
|
| - //
|
| - if (!SetBooleanControlValue(_outputMixerID, dwControlID, enable))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - return (0);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerMute
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SpeakerMute(bool& enabled) const
|
| -{
|
| -
|
| - if (_outputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - // Ensure that the selected speaker destination has a valid mute control.
|
| - // If so, its identifier was stored during the enumeration phase which must
|
| - // have taken place since the output mixer handle exists.
|
| - //
|
| - if (!_speakerState[_outputMixerID].muteControlIsValid)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this speaker line");
|
| - return -1;
|
| - }
|
| -
|
| - const DWORD dwControlID(_speakerState[_outputMixerID].dwMuteControlID);
|
| - bool value(false);
|
| -
|
| - // Retrieve one boolean control value for a specified mute-control identifier
|
| - //
|
| - if (!GetBooleanControlValue(_outputMixerID, dwControlID, value))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - enabled = value;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneMuteIsAvailable
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneMuteIsAvailable(bool& available)
|
| -{
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - available = _microphoneState[_inputMixerID].muteControlIsValid;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetMicrophoneMute
|
| -//
|
| -// This mute function works a master mute for the input microphone.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SetMicrophoneMute(bool enable)
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetMicrophoneMute(enable=%u)", enable);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - // Ensure that the selected wave-in destinationhas a valid mute control.
|
| - // If so, its identifier was stored during the enumeration phase which must
|
| - // have taken place since the input mixer handle exists.
|
| - //
|
| - if (!_microphoneState[_inputMixerID].muteControlIsValid)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this microphone line");
|
| - return -1;
|
| - }
|
| -
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwMuteControlID);
|
| -
|
| - // Set one boolean control value for the specified mute-control
|
| - //
|
| - if (!SetBooleanControlValue(_inputMixerID, dwControlID, enable))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - return (0);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneMute
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneMute(bool& enabled) const
|
| -{
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - // Ensure that the selected wave-in destinationhas a valid mute control.
|
| - // If so, its identifier was stored during the enumeration phase which must
|
| - // have taken place since the input mixer handle exists.
|
| - //
|
| - if (!_microphoneState[_inputMixerID].muteControlIsValid)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this microphone line");
|
| - return -1;
|
| - }
|
| -
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwMuteControlID);
|
| - bool value(false);
|
| -
|
| - // Retrieve one boolean control value for a specified mute-control identifier
|
| - //
|
| - if (!GetBooleanControlValue(_inputMixerID, dwControlID, value))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - enabled = value;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneBoostIsAvailable
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneBoostIsAvailable(bool& available)
|
| -{
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - available = _microphoneState[_inputMixerID].onOffControlIsValid;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetMicrophoneBoost
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SetMicrophoneBoost(bool enable)
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetMicrophoneBoost(enable=%u)", enable);
|
| -
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - // Ensure that the selected wave-in destination has a valid boost (on/off) control.
|
| - // If so, its identifier was stored during the enumeration phase which must
|
| - // have taken place since the input mixer handle exists.
|
| - //
|
| - if (!_microphoneState[_inputMixerID].onOffControlIsValid)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no boost control exists for this wave-in line");
|
| - return -1;
|
| - }
|
| -
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwOnOffControlID);
|
| -
|
| - // Set one boolean control value for the specified boost (on/off) control
|
| - //
|
| - if (!SetBooleanControlValue(_inputMixerID, dwControlID, enable))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - return (0);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneBoost
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneBoost(bool& enabled) const
|
| -{
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - // Ensure that the selected wave-in destination has a valid boost (on/off) control.
|
| - // If so, its identifier was stored during the enumeration phase which must
|
| - // have taken place since the input mixer handle exists.
|
| - //
|
| - if (!_microphoneState[_inputMixerID].onOffControlIsValid)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no boost control exists for this wave-in line");
|
| - return -1;
|
| - }
|
| -
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwOnOffControlID);
|
| - bool value(false);
|
| -
|
| - // Retrieve one boolean control value for a specified boost-control identifier
|
| - //
|
| - if (!GetBooleanControlValue(_inputMixerID, dwControlID, value))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - enabled = value;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneVolumeIsAvailable
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneVolumeIsAvailable(bool& available)
|
| -{
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - available = _microphoneState[_inputMixerID].volumeControlIsValid;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetMicrophoneVolume
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::SetMicrophoneVolume(uint32_t volume)
|
| -{
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_inputMixerID);
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
|
| - DWORD dwValue(volume);
|
| -
|
| - // Set one unsigned control value for a specified volume-control identifier
|
| - //
|
| - if (!SetUnsignedControlValue(mixerID, dwControlID, dwValue))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - return (0);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneVolume
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneVolume(uint32_t& volume) const
|
| -{
|
| - CriticalSectionScoped lock(&_critSect);
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_inputMixerID);
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
|
| - DWORD dwValue(0);
|
| -
|
| - // Retrieve one unsigned control value for a specified volume-control identifier
|
| - //
|
| - if (!GetUnsignedControlValue(mixerID, dwControlID, dwValue))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - volume = dwValue;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MaxMicrophoneVolume
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MaxMicrophoneVolume(uint32_t& maxVolume) const
|
| -{
|
| - WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "%s", __FUNCTION__);
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_inputMixerID);
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
|
| - MIXERCONTROL mixerControl;
|
| -
|
| - // Retrieve one control line for a specified volume-control identifier
|
| - //
|
| - if (!GetLineControl(mixerID, dwControlID, mixerControl))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - maxVolume = mixerControl.Bounds.dwMaximum;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MinMicrophoneVolume
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MinMicrophoneVolume(uint32_t& minVolume) const
|
| -{
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_inputMixerID);
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
|
| - MIXERCONTROL mixerControl;
|
| -
|
| - // Retrieve one control line for a specified volume-control identifier
|
| - //
|
| - if (!GetLineControl(mixerID, dwControlID, mixerControl))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - minVolume = mixerControl.Bounds.dwMinimum;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneVolumeStepSize
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -int32_t AudioMixerManager::MicrophoneVolumeStepSize(uint16_t& stepSize) const
|
| -{
|
| -
|
| - if (_inputMixerHandle == NULL)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
|
| - return -1;
|
| - }
|
| -
|
| - const UINT mixerID(_inputMixerID);
|
| - const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
|
| - MIXERCONTROL mixerControl;
|
| -
|
| - // Retrieve one control line for a specified volume-control identifier
|
| - //
|
| - if (!GetLineControl(mixerID, dwControlID, mixerControl))
|
| - {
|
| - return -1;
|
| - }
|
| -
|
| - stepSize = static_cast<uint16_t> (mixerControl.Metrics.cSteps);
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// ============================================================================
|
| -// PRIVATE METHODS
|
| -// ============================================================================
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// Devices
|
| -//
|
| -// A given audio card has one Mixer device associated with it. All of the
|
| -// various components on that card are controlled through that card's one
|
| -// Mixer device.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -UINT AudioMixerManager::Devices() const
|
| -{
|
| - UINT nDevs = mixerGetNumDevs();
|
| - return nDevs;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// DestinationLines
|
| -//
|
| -// # destination lines given mixer ID.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -UINT AudioMixerManager::DestinationLines(UINT mixId) const
|
| -{
|
| - MIXERCAPS caps;
|
| - if (!GetCapabilities(mixId, caps))
|
| - {
|
| - return 0;
|
| - }
|
| - return (caps.cDestinations);
|
| -}
|
| -// ----------------------------------------------------------------------------
|
| -// DestinationLines
|
| -//
|
| -// # source lines given mixer ID and destination ID.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -UINT AudioMixerManager::SourceLines(UINT mixId, DWORD destId) const
|
| -{
|
| - MIXERLINE dline;
|
| - if (!GetDestinationLineInfo(mixId, destId, dline))
|
| - {
|
| - return 0;
|
| - }
|
| - return (dline.cConnections);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetCapabilities
|
| -//
|
| -// Queries a specified mixer device to determine its capabilities.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetCapabilities(UINT mixId, MIXERCAPS& caps, bool trace) const
|
| -{
|
| - MMRESULT res;
|
| - MIXERCAPS mcaps;
|
| -
|
| - res = mixerGetDevCaps(mixId, &mcaps, sizeof(MIXERCAPS));
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetDevCaps() failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - memcpy(&caps, &mcaps, sizeof(MIXERCAPS));
|
| -
|
| - if (trace)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "===============================================================");
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Mixer ID %u:", mixId);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID : %u", caps.wMid);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID : %u", caps.wPid);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "version of driver : %u", caps.vDriverVersion);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name : %s", WideToUTF8(caps.szPname));
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "misc. support bits : %u", caps.fdwSupport);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "count of destinations: %u (+)", caps.cDestinations);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "===============================================================");
|
| - }
|
| -
|
| - if (caps.cDestinations == 0)
|
| - {
|
| - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "invalid number of mixer destinations");
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetDestinationLineInfo
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetDestinationLineInfo(UINT mixId, DWORD destId, MIXERLINE& line, bool trace) const
|
| -{
|
| - MMRESULT res;
|
| - MIXERLINE mline;
|
| -
|
| - mline.cbStruct = sizeof(MIXERLINE);
|
| - mline.dwDestination = destId; // max destination index is cDestinations-1
|
| - mline.dwSource = 0; // not set for MIXER_GETLINEINFOF_DESTINATION
|
| -
|
| - // Retrieve information about the specified destination line of a mixer device.
|
| - // Note that we use the mixer ID here and not a handle to an opened mixer.
|
| - // It is not required to open the mixer for enumeration purposes only.
|
| - //
|
| - res = mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(mixId), &mline, MIXER_OBJECTF_MIXER | MIXER_GETLINEINFOF_DESTINATION);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineInfo(MIXER_GETLINEINFOF_DESTINATION) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - memcpy(&line, &mline, sizeof(MIXERLINE));
|
| -
|
| - if (trace)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "> Destination Line ID %u:", destId);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "destination line index : %u", mline.dwDestination);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwLineID : %lu (unique)", mline.dwLineID);
|
| - TraceStatusAndSupportFlags(mline.fdwLine);
|
| - TraceComponentType(mline.dwComponentType);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "count of channels : %u", mline.cChannels);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "# audio source lines : %u (+)", mline.cConnections); // valid only for destinations
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "# controls : %u (*)", mline.cControls); // can be zero
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "short name : %s", WideToUTF8(mline.szShortName));
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "full name : %s", WideToUTF8(mline.szName));
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
| - TraceTargetType(mline.Target.dwType);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "target device ID : %lu", mline.Target.dwDeviceID);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID : %u", mline.Target.wMid);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID : %u", mline.Target.wPid);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "driver version : %u", mline.Target.vDriverVersion);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name : %s", WideToUTF8(mline.Target.szPname));
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "---------------------------------------------------------------");
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetSourceLineInfo
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetSourceLineInfo(UINT mixId, DWORD destId, DWORD srcId, MIXERLINE& line, bool trace) const
|
| -{
|
| - MMRESULT res;
|
| - MIXERLINE mline;
|
| -
|
| - mline.cbStruct = sizeof(MIXERLINE);
|
| - mline.dwDestination = destId; // we want the source info for this destination
|
| - mline.dwSource = srcId; // source index (enumerate over these)
|
| -
|
| - // Retrieve information about the specified source line of a mixer device.
|
| - // Note that we use the mixer ID here and not a handle to an opened mixer.
|
| - // It is not required to open the mixer for enumeration purposes only.
|
| - //
|
| - res = mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(mixId), &mline, MIXER_OBJECTF_MIXER | MIXER_GETLINEINFOF_SOURCE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineInfo(MIXER_GETLINEINFOF_SOURCE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - memcpy(&line, &mline, sizeof(MIXERLINE));
|
| -
|
| - if (trace)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " >> Source Line ID %u:", srcId);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "destination line index : %u", mline.dwDestination);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwSource : %u", mline.dwSource);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwLineID : %lu (unique)", mline.dwLineID);
|
| - TraceStatusAndSupportFlags(mline.fdwLine);
|
| - TraceComponentType(mline.dwComponentType);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "# controls : %u (*)", mline.cControls);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "full name : %s", WideToUTF8(mline.szName));
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
| - TraceTargetType(mline.Target.dwType);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "---------------------------------------------------------------");
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetAllLineControls
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetAllLineControls(UINT mixId, const MIXERLINE& line, MIXERCONTROL* controlArray, bool trace) const
|
| -{
|
| - // Ensure that we don't try to aquire information if there are no controls for this line
|
| - //
|
| - if (line.cControls == 0)
|
| - return false;
|
| -
|
| - MMRESULT res;
|
| - MIXERLINECONTROLS mlineControls; // contains information about the controls of an audio line
|
| -
|
| - mlineControls.dwLineID = line.dwLineID; // unique audio line identifier
|
| - mlineControls.cControls = line.cControls; // number of controls associated with the line
|
| - mlineControls.pamxctrl = controlArray; // points to the first MIXERCONTROL structure to be filled
|
| - mlineControls.cbStruct = sizeof(MIXERLINECONTROLS);
|
| - mlineControls.cbmxctrl = sizeof(MIXERCONTROL);
|
| -
|
| - // Get information on ALL controls associated with the specified audio line
|
| - //
|
| - res = mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(mixId), &mlineControls, MIXER_OBJECTF_MIXER | MIXER_GETLINECONTROLSF_ALL);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineControls(MIXER_GETLINECONTROLSF_ALL) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - if (trace)
|
| - {
|
| - for (UINT c = 0; c < line.cControls; c++)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " >> Control ID %u:", c);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwControlID : %u (unique)", controlArray[c].dwControlID);
|
| - TraceControlType(controlArray[c].dwControlType);
|
| - TraceControlStatusAndSupportFlags(controlArray[c].fdwControl);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cMultipleItems : %u", controlArray[c].cMultipleItems);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "short name : %s", WideToUTF8(controlArray[c].szShortName));
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "full name : %s", WideToUTF8(controlArray[c].szName));
|
| - if ((controlArray[c].dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_SIGNED)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "min signed value : %d", controlArray[c].Bounds.lMinimum);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "max signed value : %d", controlArray[c].Bounds.lMaximum);
|
| - }
|
| - else if ((controlArray[c].dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_UNSIGNED ||
|
| - (controlArray[c].dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_BOOLEAN)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "min unsigned value : %u", controlArray[c].Bounds.dwMinimum);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "max unsigned value : %u", controlArray[c].Bounds.dwMaximum);
|
| - }
|
| - if (controlArray[c].dwControlType != MIXERCONTROL_CONTROLTYPE_CUSTOM)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cSteps : %u", controlArray[c].Metrics.cSteps);
|
| - }
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "...............................................................");
|
| - GetControlDetails(mixId, controlArray[c], true);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "...............................................................");
|
| -
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetLineControls
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetLineControl(UINT mixId, DWORD dwControlID, MIXERCONTROL& control) const
|
| -{
|
| - MMRESULT res;
|
| - MIXERLINECONTROLS mlineControl;
|
| -
|
| - mlineControl.dwControlID = dwControlID;
|
| - mlineControl.cControls = 1;
|
| - mlineControl.pamxctrl = &control;
|
| - mlineControl.cbStruct = sizeof(MIXERLINECONTROLS);
|
| - mlineControl.cbmxctrl = sizeof(MIXERCONTROL);
|
| -
|
| - // Get information on one controls associated with the specified conrol identifier
|
| - //
|
| - res = mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(mixId), &mlineControl, MIXER_OBJECTF_MIXER | MIXER_GETLINECONTROLSF_ONEBYID);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineControls(MIXER_GETLINECONTROLSF_ONEBYID) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetControlDetails
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetControlDetails(UINT mixId, MIXERCONTROL& controlArray, bool trace) const
|
| -{
|
| - assert(controlArray.cMultipleItems <= MAX_NUMBER_OF_MULTIPLE_ITEMS);
|
| -
|
| - MMRESULT res;
|
| - MIXERCONTROLDETAILS controlDetails;
|
| -
|
| - MIXERCONTROLDETAILS_UNSIGNED valueUnsigned[MAX_NUMBER_OF_MULTIPLE_ITEMS];
|
| - MIXERCONTROLDETAILS_SIGNED valueSigned[MAX_NUMBER_OF_MULTIPLE_ITEMS];
|
| - MIXERCONTROLDETAILS_BOOLEAN valueBoolean[MAX_NUMBER_OF_MULTIPLE_ITEMS];
|
| -
|
| - enum ControlType
|
| - {
|
| - CT_UNITS_UNSIGNED,
|
| - CT_UNITS_SIGNED,
|
| - CT_UNITS_BOOLEAN
|
| - };
|
| -
|
| - ControlType ctype(CT_UNITS_UNSIGNED);
|
| -
|
| - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
|
| - controlDetails.dwControlID = controlArray.dwControlID; // control identifier
|
| - controlDetails.cChannels = 1; // we need to set values as if they were uniform
|
| - controlDetails.cMultipleItems = controlArray.cMultipleItems; // only nonzero for CONTROLF_MULTIPLE controls
|
| - // can e.g. happen for CONTROLTYPE_MUX
|
| - if (controlDetails.cMultipleItems > MAX_NUMBER_OF_MULTIPLE_ITEMS)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "cMultipleItems > %d", MAX_NUMBER_OF_MULTIPLE_ITEMS);
|
| - controlDetails.cMultipleItems = MAX_NUMBER_OF_MULTIPLE_ITEMS;
|
| - }
|
| -
|
| - if ((controlArray.dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_SIGNED)
|
| - {
|
| - ctype = CT_UNITS_SIGNED;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_SIGNED);
|
| - controlDetails.paDetails = &valueSigned[0];
|
| - }
|
| - else if ((controlArray.dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_UNSIGNED)
|
| - {
|
| - ctype = CT_UNITS_UNSIGNED;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
|
| - controlDetails.paDetails = &valueUnsigned[0];
|
| - }
|
| - else if ((controlArray.dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_BOOLEAN)
|
| - {
|
| - ctype = CT_UNITS_BOOLEAN;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
|
| - controlDetails.paDetails = &valueBoolean[0];
|
| - }
|
| -
|
| - // Retrieve a control's value
|
| - //
|
| - res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - if (trace)
|
| - {
|
| - UINT nItems(1);
|
| - nItems = (controlDetails.cMultipleItems > 0 ? controlDetails.cMultipleItems : 1);
|
| - for (UINT i = 0; i < nItems; i++)
|
| - {
|
| - if (ctype == CT_UNITS_SIGNED)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "signed value : %d", valueSigned[i].lValue);
|
| - }
|
| - else if (ctype == CT_UNITS_UNSIGNED)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unsigned value : %u", valueUnsigned[i].dwValue);
|
| - }
|
| - else if (ctype == CT_UNITS_BOOLEAN)
|
| - {
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "boolean value : %u", valueBoolean[i].fValue);
|
| - }
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetUnsignedControlValue
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetUnsignedControlValue(UINT mixId, DWORD dwControlID, DWORD& dwValue) const
|
| -{
|
| - MMRESULT res;
|
| - MIXERCONTROLDETAILS controlDetails;
|
| - MIXERCONTROLDETAILS_UNSIGNED valueUnsigned;
|
| -
|
| - controlDetails.dwControlID = dwControlID;
|
| - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
|
| - controlDetails.cChannels = 1;
|
| - controlDetails.cMultipleItems = 0;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
|
| - controlDetails.paDetails = &valueUnsigned;
|
| -
|
| - // Retrieve the unsigned value
|
| - //
|
| - res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - // Deliver the retrieved value
|
| - //
|
| - dwValue = valueUnsigned.dwValue;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetUnsignedControlValue
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::SetUnsignedControlValue(UINT mixId, DWORD dwControlID, DWORD dwValue) const
|
| -{
|
| - WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "AudioMixerManager::SetUnsignedControlValue(mixId=%u, dwControlID=%d, dwValue=%d)", mixId, dwControlID, dwValue);
|
| -
|
| - MMRESULT res;
|
| - MIXERCONTROLDETAILS controlDetails;
|
| - MIXERCONTROLDETAILS_UNSIGNED valueUnsigned;
|
| -
|
| - controlDetails.dwControlID = dwControlID;
|
| - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
|
| - controlDetails.cChannels = 1;
|
| - controlDetails.cMultipleItems = 0;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
|
| - controlDetails.paDetails = &valueUnsigned;
|
| -
|
| - valueUnsigned.dwValue = dwValue;
|
| -
|
| - // Set the unsigned value
|
| - //
|
| - res = mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerSetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SetBooleanControlValue
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::SetBooleanControlValue(UINT mixId, DWORD dwControlID, bool value) const
|
| -{
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetBooleanControlValue(mixId=%u, dwControlID=%d, value=%d)", mixId, dwControlID, value);
|
| -
|
| - MMRESULT res;
|
| - MIXERCONTROLDETAILS controlDetails;
|
| - MIXERCONTROLDETAILS_BOOLEAN valueBoolean;
|
| -
|
| - controlDetails.dwControlID = dwControlID;
|
| - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
|
| - controlDetails.cChannels = 1;
|
| - controlDetails.cMultipleItems = 0;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
|
| - controlDetails.paDetails = &valueBoolean;
|
| -
|
| - if (value == true)
|
| - valueBoolean.fValue = TRUE;
|
| - else
|
| - valueBoolean.fValue = FALSE;
|
| -
|
| - // Set the boolean value
|
| - //
|
| - res = mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerSetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetBooleanControlValue
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetBooleanControlValue(UINT mixId, DWORD dwControlID, bool& value) const
|
| -{
|
| - MMRESULT res;
|
| - MIXERCONTROLDETAILS controlDetails;
|
| - MIXERCONTROLDETAILS_BOOLEAN valueBoolean;
|
| -
|
| - controlDetails.dwControlID = dwControlID;
|
| - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
|
| - controlDetails.cChannels = 1;
|
| - controlDetails.cMultipleItems = 0;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
|
| - controlDetails.paDetails = &valueBoolean;
|
| -
|
| - // Retrieve the boolean value
|
| - //
|
| - res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - // Deliver the retrieved value
|
| - //
|
| - if (valueBoolean.fValue == 0)
|
| - value = false;
|
| - else
|
| - value = true;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// GetSelectedMuxSource
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::GetSelectedMuxSource(UINT mixId, DWORD dwControlID, DWORD cMultipleItems, UINT& index) const
|
| -{
|
| - assert(cMultipleItems <= MAX_NUMBER_OF_MULTIPLE_ITEMS);
|
| -
|
| - MMRESULT res;
|
| - MIXERCONTROLDETAILS controlDetails;
|
| - MIXERCONTROLDETAILS_BOOLEAN valueBoolean[MAX_NUMBER_OF_MULTIPLE_ITEMS];
|
| - memset(&valueBoolean, 0, sizeof(valueBoolean));
|
| -
|
| - controlDetails.dwControlID = dwControlID;
|
| - controlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
|
| - controlDetails.cChannels = 1;
|
| - controlDetails.cMultipleItems = cMultipleItems;
|
| - controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
|
| - controlDetails.paDetails = &valueBoolean;
|
| -
|
| - // Retrieve the boolean values
|
| - //
|
| - res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
|
| - if (res != MMSYSERR_NOERROR)
|
| - {
|
| - WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
|
| - return false;
|
| - }
|
| -
|
| - // Map the current MUX setting to an index corresponding to a source index.
|
| - // e.g. with cMultipleItems = 3,
|
| - // valueBoolean[] = {1,0,0} => index = 2
|
| - // valueBoolean[] = {0,1,0} => index = 1
|
| - // valueBoolean[] = {0,0,1} => index = 0
|
| - //
|
| - // If there is no "1" in the array, we assume index should be 0.
|
| - index = 0;
|
| - for (DWORD i = 0; i < cMultipleItems; i++)
|
| - {
|
| - if (valueBoolean[i].fValue > 0)
|
| - {
|
| - index = (cMultipleItems - 1) - i;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceStatusAndSupportFlags
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceStatusAndSupportFlags(DWORD fdwLine) const
|
| -{
|
| - TCHAR buf[128];
|
| -
|
| - StringCchPrintf(buf, 128, TEXT("status & support flags : 0x%x "), fdwLine);
|
| -
|
| - switch (fdwLine)
|
| - {
|
| - case MIXERLINE_LINEF_ACTIVE:
|
| - StringCchCat(buf, 128, TEXT("(ACTIVE DESTINATION)"));
|
| - break;
|
| - case MIXERLINE_LINEF_DISCONNECTED:
|
| - StringCchCat(buf, 128, TEXT("(DISCONNECTED)"));
|
| - break;
|
| - case MIXERLINE_LINEF_SOURCE:
|
| - StringCchCat(buf, 128, TEXT("(INACTIVE SOURCE)"));
|
| - break;
|
| - case MIXERLINE_LINEF_SOURCE | MIXERLINE_LINEF_ACTIVE:
|
| - StringCchCat(buf, 128, TEXT("(ACTIVE SOURCE)"));
|
| - break;
|
| - default:
|
| - StringCchCat(buf, 128, TEXT("(INVALID)"));
|
| - break;
|
| - }
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceComponentType
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceComponentType(DWORD dwComponentType) const
|
| -{
|
| - TCHAR buf[128];
|
| -
|
| - StringCchPrintf(buf, 128, TEXT("component type : 0x%x "), dwComponentType);
|
| -
|
| - switch (dwComponentType)
|
| - {
|
| - // Destination
|
| - case MIXERLINE_COMPONENTTYPE_DST_UNDEFINED:
|
| - StringCchCat(buf, 128, TEXT("(DST_UNDEFINED)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_DIGITAL:
|
| - StringCchCat(buf, 128, TEXT("(DST_DIGITAL)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_LINE:
|
| - StringCchCat(buf, 128, TEXT("(DST_LINE)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_MONITOR:
|
| - StringCchCat(buf, 128, TEXT("(DST_MONITOR)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
|
| - StringCchCat(buf, 128, TEXT("(DST_SPEAKERS)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_HEADPHONES:
|
| - StringCchCat(buf, 128, TEXT("(DST_HEADPHONES)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_TELEPHONE:
|
| - StringCchCat(buf, 128, TEXT("(DST_TELEPHONE)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_WAVEIN:
|
| - StringCchCat(buf, 128, TEXT("(DST_WAVEIN)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_DST_VOICEIN:
|
| - StringCchCat(buf, 128, TEXT("(DST_VOICEIN)"));
|
| - break;
|
| - // Source
|
| - case MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED:
|
| - StringCchCat(buf, 128, TEXT("(SRC_UNDEFINED)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_DIGITAL:
|
| - StringCchCat(buf, 128, TEXT("(SRC_DIGITAL)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_LINE:
|
| - StringCchCat(buf, 128, TEXT("(SRC_LINE)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE:
|
| - StringCchCat(buf, 128, TEXT("(SRC_MICROPHONE)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER:
|
| - StringCchCat(buf, 128, TEXT("(SRC_SYNTHESIZER)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC:
|
| - StringCchCat(buf, 128, TEXT("(SRC_COMPACTDISC)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE:
|
| - StringCchCat(buf, 128, TEXT("(SRC_TELEPHONE)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER:
|
| - StringCchCat(buf, 128, TEXT("(SRC_PCSPEAKER)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT:
|
| - StringCchCat(buf, 128, TEXT("(SRC_WAVEOUT)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY:
|
| - StringCchCat(buf, 128, TEXT("(SRC_AUXILIARY)"));
|
| - break;
|
| - case MIXERLINE_COMPONENTTYPE_SRC_ANALOG:
|
| - StringCchCat(buf, 128, TEXT("(SRC_ANALOG)"));
|
| - break;
|
| - default:
|
| - StringCchCat(buf, 128, TEXT("(INVALID)"));
|
| - break;
|
| - }
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceTargetType
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceTargetType(DWORD dwType) const
|
| -{
|
| - TCHAR buf[128];
|
| -
|
| - StringCchPrintf(buf, 128, TEXT("media device type : 0x%x "), dwType);
|
| -
|
| - switch (dwType)
|
| - {
|
| - case MIXERLINE_TARGETTYPE_UNDEFINED:
|
| - StringCchCat(buf, 128, TEXT("(UNDEFINED)"));
|
| - break;
|
| - case MIXERLINE_TARGETTYPE_WAVEOUT:
|
| - StringCchCat(buf, 128, TEXT("(WAVEOUT)"));
|
| - break;
|
| - case MIXERLINE_TARGETTYPE_WAVEIN:
|
| - StringCchCat(buf, 128, TEXT("(WAVEIN)"));
|
| - break;
|
| - case MIXERLINE_TARGETTYPE_MIDIOUT:
|
| - StringCchCat(buf, 128, TEXT("(MIDIOUT)"));
|
| - break;
|
| - case MIXERLINE_TARGETTYPE_MIDIIN:
|
| - StringCchCat(buf, 128, TEXT("(MIDIIN)"));
|
| - break;
|
| - default:
|
| - StringCchCat(buf, 128, TEXT("(INVALID)"));
|
| - break;
|
| - }
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceControlType
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceControlType(DWORD dwControlType) const
|
| -{
|
| - TCHAR buf[128];
|
| -
|
| - // Class type classification
|
| - //
|
| - StringCchPrintf(buf, 128, TEXT("class type : 0x%x "), dwControlType);
|
| -
|
| - switch (dwControlType & MIXERCONTROL_CT_CLASS_MASK)
|
| - {
|
| - case MIXERCONTROL_CT_CLASS_CUSTOM:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_CUSTOM)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_METER:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_METER)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_SWITCH:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_SWITCH)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_NUMBER:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_NUMBER)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_SLIDER:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_SLIDER)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_FADER:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_FADER)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_TIME:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_TIME)"));
|
| - break;
|
| - case MIXERCONTROL_CT_CLASS_LIST:
|
| - StringCchCat(buf, 128, TEXT("(CT_CLASS_LIST)"));
|
| - break;
|
| - default:
|
| - StringCchCat(buf, 128, TEXT("(INVALID)"));
|
| - break;
|
| - }
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -
|
| - // Control type (for each class)
|
| - //
|
| - StringCchPrintf(buf, 128, TEXT("control type : 0x%x "), dwControlType);
|
| -
|
| - switch (dwControlType)
|
| - {
|
| - case MIXERCONTROL_CONTROLTYPE_CUSTOM:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_CUSTOM)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_BOOLEANMETER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BOOLEANMETER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_SIGNEDMETER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SIGNEDMETER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_PEAKMETER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_PEAKMETER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_UNSIGNEDMETER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_BOOLEAN:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BOOLEAN)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_ONOFF:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_ONOFF)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MUTE:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MUTE)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MONO:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MONO)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_LOUDNESS:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_LOUDNESS)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_STEREOENH:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_STEREOENH)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_BASS_BOOST:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BASS_BOOST)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_BUTTON:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BUTTON)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_DECIBELS:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_DECIBELS)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_SIGNED:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SIGNED)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_UNSIGNED:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_UNSIGNED)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_PERCENT:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_PERCENT)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_SLIDER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SLIDER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_PAN:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_PAN)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_QSOUNDPAN:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_QSOUNDPAN)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_FADER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_FADER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_VOLUME)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_BASS:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BASS)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_TREBLE:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_TREBLE)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_EQUALIZER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SINGLESELECT)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MUX:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MUX)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MULTIPLESELECT)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MIXER:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MIXER)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MICROTIME:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MICROTIME)"));
|
| - break;
|
| - case MIXERCONTROL_CONTROLTYPE_MILLITIME:
|
| - StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MILLITIME)"));
|
| - break;
|
| - default:
|
| - StringCchCat(buf, 128, TEXT("(INVALID)"));
|
| - break;
|
| - }
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceControlStatusAndSupportFlags
|
| -//
|
| -// fdwControl
|
| -//
|
| -// Status and support flags for the audio line control. The following values
|
| -// are defined:
|
| -//
|
| -// MIXERCONTROL_CONTROLF_DISABLED
|
| -//
|
| -// The control is disabled, perhaps due to other settings for the mixer hardware,
|
| -// and cannot be used. An application can read current settings from a
|
| -// disabled control, but it cannot apply settings.
|
| -//
|
| -// MIXERCONTROL_CONTROLF_MULTIPLE
|
| -//
|
| -// The control has two or more settings per channel. An equalizer, for example,
|
| -// requires this flag because each frequency band can be set to a different value.
|
| -// An equalizer that affects both channels of a stereo line in a uniform fashion
|
| -// will also specify the MIXERCONTROL_CONTROLF_UNIFORM flag.
|
| -//
|
| -// MIXERCONTROL_CONTROLF_UNIFORM
|
| -//
|
| -// The control acts on all channels of a multichannel line in a uniform fashion.
|
| -// For example, a control that mutes both channels of a stereo line would set
|
| -// this flag. Most MIXERCONTROL_CONTROLTYPE_MUX and
|
| -// MIXERCONTROL_CONTROLTYPE_MIXER controls also specify the
|
| -// MIXERCONTROL_CONTROLF_UNIFORM flag.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceControlStatusAndSupportFlags(DWORD fdwControl) const
|
| -{
|
| - TCHAR buf[128];
|
| -
|
| - StringCchPrintf(buf, 128, TEXT("control support flags : 0x%x "), fdwControl);
|
| -
|
| - if (fdwControl & MIXERCONTROL_CONTROLF_DISABLED)
|
| - {
|
| - // The control is disabled, perhaps due to other settings for the mixer hardware,
|
| - // and cannot be used. An application can read current settings from a disabled
|
| - // control, but it cannot apply settings.
|
| - StringCchCat(buf, 128, TEXT("(CONTROLF_DISABLED)"));
|
| - }
|
| -
|
| - if (fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE)
|
| - {
|
| - // The control has two or more settings per channel. An equalizer, for example,
|
| - // requires this flag because each frequency band can be set to a different
|
| - // value. An equalizer that affects both channels of a stereo line in a
|
| - // uniform fashion will also specify the MIXERCONTROL_CONTROLF_UNIFORM flag.
|
| - StringCchCat(buf, 128, TEXT("(CONTROLF_MULTIPLE)"));
|
| - }
|
| -
|
| - if (fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
|
| - {
|
| - // The control acts on all channels of a multichannel line in a uniform
|
| - // fashion. For example, a control that mutes both channels of a stereo
|
| - // line would set this flag. Most MIXERCONTROL_CONTROLTYPE_MUX and
|
| - // MIXERCONTROL_CONTROLTYPE_MIXER controls also specify the
|
| - // MIXERCONTROL_CONTROLF_UNIFORM flag.
|
| - StringCchCat(buf, 128, TEXT("(CONTROLF_UNIFORM)"));
|
| - }
|
| -
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// ClearSpeakerState I (II)
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::ClearSpeakerState(UINT idx)
|
| -{
|
| - _speakerState[idx].dwLineID = 0L;
|
| - _speakerState[idx].dwVolumeControlID = 0L;
|
| - _speakerState[idx].dwMuteControlID = 0L;
|
| - _speakerState[idx].speakerIsValid = false;
|
| - _speakerState[idx].muteControlIsValid = false;
|
| - _speakerState[idx].volumeControlIsValid = false;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// ClearSpeakerState II (II)
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::ClearSpeakerState()
|
| -{
|
| - for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
|
| - {
|
| - ClearSpeakerState(i);
|
| - }
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// SpeakerIsValid
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::SpeakerIsValid(UINT idx) const
|
| -{
|
| - return (_speakerState[idx].speakerIsValid);
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// ValidSpeakers
|
| -//
|
| -// Counts number of valid speaker destinations for all mixer devices.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -UINT AudioMixerManager::ValidSpeakers() const
|
| -{
|
| - UINT nSpeakers(0);
|
| - for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
|
| - {
|
| - if (SpeakerIsValid(i))
|
| - nSpeakers++;
|
| - }
|
| - return nSpeakers;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// ClearMicrophoneState I (II)
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::ClearMicrophoneState(UINT idx)
|
| -{
|
| - _microphoneState[idx].dwLineID = 0L;
|
| - _microphoneState[idx].dwVolumeControlID = 0L;
|
| - _microphoneState[idx].dwMuteControlID = 0L;
|
| - _microphoneState[idx].dwOnOffControlID = 0L;
|
| - _microphoneState[idx].microphoneIsValid = false;
|
| - _microphoneState[idx].muteControlIsValid = false;
|
| - _microphoneState[idx].volumeControlIsValid = false;
|
| - _microphoneState[idx].onOffControlIsValid = false;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// ClearMicrophoneState II (II)
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::ClearMicrophoneState()
|
| -{
|
| - for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
|
| - {
|
| - ClearMicrophoneState(i);
|
| - }
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// MicrophoneIsValid
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -bool AudioMixerManager::MicrophoneIsValid(UINT idx) const
|
| -{
|
| - return (_microphoneState[idx].microphoneIsValid);
|
| -
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// ValidMicrophones
|
| -//
|
| -// Counts number of valid speaker destinations for all mixer devices.
|
| -// To be valid, a speaker destination line must exist.
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -UINT AudioMixerManager::ValidMicrophones() const
|
| -{
|
| - UINT nMicrophones(0);
|
| - for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
|
| - {
|
| - if (MicrophoneIsValid(i))
|
| - nMicrophones++;
|
| - }
|
| - return nMicrophones;
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceWaveInError
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceWaveInError(MMRESULT error) const
|
| -{
|
| - TCHAR buf[MAXERRORLENGTH];
|
| - TCHAR msg[MAXERRORLENGTH];
|
| -
|
| - StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: "));
|
| - waveInGetErrorText(error, msg, MAXERRORLENGTH);
|
| - StringCchCat(buf, MAXERRORLENGTH, msg);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// TraceWaveOutError
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -void AudioMixerManager::TraceWaveOutError(MMRESULT error) const
|
| -{
|
| - TCHAR buf[MAXERRORLENGTH];
|
| - TCHAR msg[MAXERRORLENGTH];
|
| -
|
| - StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: "));
|
| - waveOutGetErrorText(error, msg, MAXERRORLENGTH);
|
| - StringCchCat(buf, MAXERRORLENGTH, msg);
|
| - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
|
| -}
|
| -
|
| -// ----------------------------------------------------------------------------
|
| -// WideToUTF8
|
| -// ----------------------------------------------------------------------------
|
| -
|
| -char* AudioMixerManager::WideToUTF8(const TCHAR* src) const {
|
| -#ifdef UNICODE
|
| - const size_t kStrLen = sizeof(_str);
|
| - memset(_str, 0, kStrLen);
|
| - // Get required size (in bytes) to be able to complete the conversion.
|
| - unsigned int required_size = (unsigned int)WideCharToMultiByte(CP_UTF8, 0, src, -1, _str, 0, 0, 0);
|
| - if (required_size <= kStrLen)
|
| - {
|
| - // Process the entire input string, including the terminating null char.
|
| - if (WideCharToMultiByte(CP_UTF8, 0, src, -1, _str, kStrLen, 0, 0) == 0)
|
| - memset(_str, 0, kStrLen);
|
| - }
|
| - return _str;
|
| -#else
|
| - return const_cast<char*>(src);
|
| -#endif
|
| -}
|
| -
|
| -} // namespace webrtc
|
|
|