1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/modules/audio_device/win/audio_mixer_manager_win.h"
12bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h>      // assert()
15bc669ace8f09d73e95f923253ecdadd366f9b7f1pbos@webrtc.org#include <strsafe.h>    // StringCchCopy(), StringCchCat(), StringCchPrintf()
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef _WIN32
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// removes warning: "reinterpret_cast: conversion from 'UINT' to 'HMIXEROBJ'
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//                of greater size"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#pragma warning(disable:4312)
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Avoids the need of Windows 7 SDK
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifndef WAVE_MAPPED_kDefaultCommunicationDevice
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define  WAVE_MAPPED_kDefaultCommunicationDevice   0x0010
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//                             CONSTRUCTION/DESTRUCTION
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgAudioMixerManager::AudioMixerManager(const int32_t id) :
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _id(id),
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _inputMixerHandle(NULL),
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _outputMixerHandle(NULL)
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s constructed", __FUNCTION__);
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ClearSpeakerState();
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ClearMicrophoneState();
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgAudioMixerManager::~AudioMixerManager()
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destructed", __FUNCTION__);
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Close();
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete &_critSect;
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//                                 PUBLIC METHODS
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Close
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
6264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::Close()
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle != NULL)
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerClose(_outputMixerHandle);
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _outputMixerHandle = NULL;
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle != NULL)
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerClose(_inputMixerHandle);
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _inputMixerHandle = NULL;
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  CloseSpeaker
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
8664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::CloseSpeaker()
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ClearSpeakerState(_outputMixerID);
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mixerClose(_outputMixerHandle);
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _outputMixerHandle = NULL;
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  CloseMicrophone
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
10964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::CloseMicrophone()
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ClearMicrophoneState(_inputMixerID);
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mixerClose(_inputMixerHandle);
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _inputMixerHandle = NULL;
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  EnumerateAll
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::EnumerateAll()
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT nDevices = mixerGetNumDevs();
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#mixer devices: %u", nDevices);
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCAPS    caps;
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE    destLine;
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE    sourceLine;
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL controlArray[MAX_NUMBER_OF_LINE_CONTROLS];
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT mixId(0);
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT destId(0);
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT sourceId(0);
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (mixId = 0; mixId < nDevices; mixId++)
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (!GetCapabilities(mixId, caps, true))
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            continue;
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for (destId = 0; destId < caps.cDestinations; destId++)
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            GetDestinationLineInfo(mixId, destId, destLine, true);
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            GetAllLineControls(mixId, destLine, controlArray, true);
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            for (sourceId = 0; sourceId < destLine.cConnections; sourceId++)
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                GetSourceLineInfo(mixId, destId, sourceId, sourceLine, true);
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                GetAllLineControls(mixId, sourceLine, controlArray, true);
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  EnumerateSpeakers
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::EnumerateSpeakers()
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT nDevices = mixerGetNumDevs();
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (nDevices > MAX_NUMBER_MIXER_DEVICES)
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert(false);
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#mixer devices: %u", nDevices);
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCAPS    caps;
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE    destLine;
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL controlArray[MAX_NUMBER_OF_LINE_CONTROLS];
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT mixId(0);
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT destId(0);
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ClearSpeakerState();
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // scan all avaliable mixer devices
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (mixId = 0; mixId < nDevices; mixId++)
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // get capabilities for the specified mixer ID
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        GetCapabilities(mixId, caps);
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[mixerID=%d] %s: ", mixId, WideToUTF8(caps.szPname));
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // scan all avaliable destinations for this mixer
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for (destId = 0; destId < caps.cDestinations; destId++)
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            GetDestinationLineInfo(mixId, destId, destLine);
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if ((destLine.cControls == 0)                         ||    // no controls or
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                (destLine.cConnections == 0)                      ||    // no source lines or
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                (destLine.fdwLine & MIXERLINE_LINEF_DISCONNECTED) ||    // disconnected or
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                !(destLine.fdwLine & MIXERLINE_LINEF_ACTIVE))           // inactive
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // don't store this line ID since it will not be possible to control
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                continue;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if ((destLine.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS) ||
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                (destLine.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_HEADPHONES))
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found valid speaker/headphone (name: %s, ID: %u)", WideToUTF8(destLine.szName), destLine.dwLineID);
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                _speakerState[mixId].dwLineID = destLine.dwLineID;
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                _speakerState[mixId].speakerIsValid = true;
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // retrieve all controls for the speaker component
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                GetAllLineControls(mixId, destLine, controlArray);
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                for (UINT c = 0; c < destLine.cControls; c++)
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                {
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    if (controlArray[c].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        _speakerState[mixId].dwVolumeControlID = controlArray[c].dwControlID;
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        _speakerState[mixId].volumeControlIsValid = true;
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found volume control (name: %s, ID: %u)", WideToUTF8(controlArray[c].szName), controlArray[c].dwControlID);
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    else if (controlArray[c].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        _speakerState[mixId].dwMuteControlID = controlArray[c].dwControlID;
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        _speakerState[mixId].muteControlIsValid = true;
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found mute control (name: %s, ID: %u)", WideToUTF8(controlArray[c].szName), controlArray[c].dwControlID);
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                }
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                break;
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (!SpeakerIsValid(mixId))
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to find a valid speaker destination line", mixId);
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (ValidSpeakers() == 0)
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to locate any valid speaker line");
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  EnumerateMicrophones
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
25764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::EnumerateMicrophones()
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", __FUNCTION__);
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT nDevices = mixerGetNumDevs();
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (nDevices > MAX_NUMBER_MIXER_DEVICES)
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        assert(false);
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#mixer devices: %u", nDevices);
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCAPS    caps;
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE    destLine;
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE    sourceLine;
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL controlArray[MAX_NUMBER_OF_LINE_CONTROLS];
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT mixId(0);
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT destId(0);
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ClearMicrophoneState();
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // scan all avaliable mixer devices
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (mixId = 0; mixId < nDevices; mixId++)
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // get capabilities for the specified mixer ID
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        GetCapabilities(mixId, caps);
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[mixerID=%d] %s: ", mixId, WideToUTF8(caps.szPname));
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // scan all avaliable destinations for this mixer
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for (destId = 0; destId < caps.cDestinations; destId++)
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            GetDestinationLineInfo(mixId, destId, destLine);
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if ((destLine.cConnections == 0)                      ||    // no source lines or
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                (destLine.fdwLine & MIXERLINE_LINEF_DISCONNECTED) ||    // disconnected or
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org               !(destLine.fdwLine & MIXERLINE_LINEF_ACTIVE))            // inactive
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // Don't store this line ID since there are no sources connected to this destination.
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // Compare with the speaker side where we also exclude lines with no controls.
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                continue;
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if (destLine.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_WAVEIN)
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found valid Wave In destination (name: %s, ID: %u)", WideToUTF8(destLine.szName), destLine.dwLineID);
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                _microphoneState[mixId].dwLineID = destLine.dwLineID;
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                _microphoneState[mixId].microphoneIsValid = true;
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // retrieve all controls for the identified wave-in destination
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                if (!GetAllLineControls(mixId, destLine, controlArray))
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                {
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // This destination has no controls. We must try to control
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // one of its sources instead.
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // This is a rare state but has been found for some
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // Logitech USB headsets.
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    "this destination has no controls => must control source");
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    for (DWORD sourceId = 0; sourceId < destLine.cConnections; sourceId++)
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        GetSourceLineInfo(mixId, destId, sourceId, sourceLine, false);
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        if (sourceLine.dwComponentType ==
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            "found microphone source ( name: %s, ID: %u)",
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WideToUTF8(sourceLine.szName), sourceId);
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            GetAllLineControls(mixId, sourceLine, controlArray, false);
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // scan the controls for this source and search for volume,
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // mute and on/off (<=> boost) controls
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            for (UINT sc = 0; sc < sourceLine.cControls; sc++)
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            {
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                if (controlArray[sc].dwControlType ==
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    MIXERCONTROL_CONTROLTYPE_VOLUME)
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                {
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    // store this volume control
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    _microphoneState[mixId].dwVolumeControlID =
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    controlArray[sc].dwControlID;
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    _microphoneState[mixId].volumeControlIsValid = true;
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    "found volume control (name: %s, ID: %u)",
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    WideToUTF8(controlArray[sc].szName),
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    controlArray[sc].dwControlID);
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                }
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                else if (controlArray[sc].dwControlType ==
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         MIXERCONTROL_CONTROLTYPE_MUTE)
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                {
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    // store this mute control
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    _microphoneState[mixId].dwMuteControlID =
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    controlArray[sc].dwControlID;
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    _microphoneState[mixId].muteControlIsValid = true;
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    "found mute control (name: %s, ID: %u)",
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    WideToUTF8(controlArray[sc].szName),
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    controlArray[sc].dwControlID);
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                }
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                else if (controlArray[sc].dwControlType ==
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         MIXERCONTROL_CONTROLTYPE_ONOFF ||
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         controlArray[sc].dwControlType ==
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         MIXERCONTROL_CONTROLTYPE_LOUDNESS)
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                {
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    // store this on/off control (most likely a Boost control)
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    _microphoneState[mixId].dwOnOffControlID =
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    controlArray[sc].dwControlID;
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    _microphoneState[mixId].onOffControlIsValid = true;
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    "found on/off control (name: %s, ID: %u)",
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    WideToUTF8(controlArray[sc].szName),
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    controlArray[sc].dwControlID);
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 }
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             }
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         }
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    break;
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                }
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // It seems like there are three different configurations we can find in this state:
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // (1) The Wave-in destination contains one MUX control only
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // (2) The Wave-in destination contains one or more controls where one is a volume control
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // (3) On Vista and Win 7, it seems like case 2 above is extended.
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //     It is common that a Wave-in destination has two master controls (volume and mute),
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //     AND a microphone source as well with its own volume and mute controls with unique
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //     identifiers. Initial tests have shown that it is sufficient to modify the master
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //     controls only. The source controls will "follow" the master settings, hence the
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //     source controls seem to be redundant.
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // For case 1, we should locate the selected source and its controls. The MUX setting will
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // give us the selected source. NOTE - the selecion might not be a microphone.
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // For case 2, the volume control works as a master level control and we should use that one.
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // For case 3, we use the master controls only and assume that the source control will "follow".
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // Examples of case 1: - SigmaTel Audio (built-in)
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //                     - add more..
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // Examples of case 2: - Plantronics USB Headset
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //                      - Eutectics IPP 200 USB phone
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //                      - add more...
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                // Examples of case 3: - Realtek High Definition on Vista (TL)
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                //                     - add more...
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                if ((destLine.cControls == 1) &&
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    (controlArray[0].dwControlType == MIXERCONTROL_CONTROLTYPE_MUX))
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                {
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // Case 1: MUX control detected  => locate the selected source and its volume control
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    //         Note that, the selecion might not be a microphone. A warning is given for
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    //         this case only, i.e., it is OK to control a selected Line In source as long
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    //         as it is connected to the wave-in destination.
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    UINT selection(0);
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    const DWORD nItemsInMux(controlArray[0].cMultipleItems);
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // decide which source line that is selected in the mux
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    if (GetSelectedMuxSource(mixId, controlArray[0].dwControlID, nItemsInMux, selection))
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // selection now contains the index of the selected source =>
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // read the line information for this source
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // if conditions listed below
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // condition 1: invalid source
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // condition 2: no controls
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // condition 3: disconnected
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // condition 4: inactive
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        if (!GetSourceLineInfo(mixId, destId, selection, sourceLine)  ||
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           (sourceLine.cControls == 0)                                ||
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           (sourceLine.fdwLine & MIXERLINE_LINEF_DISCONNECTED)        ||
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          !(sourceLine.fdwLine & MIXERLINE_LINEF_ACTIVE))
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            continue;
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        }
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        if (sourceLine.dwComponentType != MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // add more details about the selected source (not a microphone)
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            TraceComponentType(sourceLine.dwComponentType);
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // send a warning just to inform about the fact that a non-microphone source will be controlled
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "the selected (to be controlled) source is not a microphone type");
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        }
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // retrieve all controls for the selected source
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        GetAllLineControls(mixId, sourceLine, controlArray);
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "MUX selection is %u [0,%u]", selection, nItemsInMux-1);
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // scan the controls for this source and search for volume, mute and on/off (<=> boost) controls
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        for (UINT sc = 0; sc < sourceLine.cControls; sc++)
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            if (controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            {
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                // store this volume control
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                _microphoneState[mixId].dwVolumeControlID = controlArray[sc].dwControlID;
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                _microphoneState[mixId].volumeControlIsValid = true;
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found volume control (name: %s, ID: %u)", WideToUTF8(controlArray[sc].szName), controlArray[sc].dwControlID);
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            }
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            else if (controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            {
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                // store this mute control
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                _microphoneState[mixId].dwMuteControlID = controlArray[sc].dwControlID;
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                _microphoneState[mixId].muteControlIsValid = true;
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found mute control (name: %s, ID: %u)", WideToUTF8(controlArray[sc].szName), controlArray[sc].dwControlID);
459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            }
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            else if (controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF ||
461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     controlArray[sc].dwControlType == MIXERCONTROL_CONTROLTYPE_LOUDNESS)
462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            {
463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                // store this on/off control (most likely a Boost control)
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                _microphoneState[mixId].dwOnOffControlID = controlArray[sc].dwControlID;
465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                _microphoneState[mixId].onOffControlIsValid = true;
466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found on/off control (name: %s, ID: %u)", WideToUTF8(controlArray[sc].szName), controlArray[sc].dwControlID);
467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            }
468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        }
469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    else
471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to detect which source to control");
473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                }
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                else if (destLine.cConnections == 1)
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                {
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // Case 2 or Case 3:
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    GetSourceLineInfo(mixId, destId, 0, sourceLine);
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    if ((sourceLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) &&
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        (sourceLine.cControls > 0))
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // Case 3: same as Case 2 below but we have also detected a Microphone source
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        //         with its own controls. So far, I have not been able to find any device
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        //         where it is required to modify these controls. Until I have found such
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        //         a device, this case will be handled as a Case 2 (see below).
488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "microphone source controls will not be controlled");
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    else if ((sourceLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) &&
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             (sourceLine.cControls == 0))
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // default state on non Vista/Win 7 machines
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "microphone source has no controls => use master controls instead");
496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    else
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // add more details about the selected source (not a microphone)
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        TraceComponentType(sourceLine.dwComponentType);
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        // send a warning just to inform about the fact that a non-microphone source will be controlled
502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "the connected (to be controlled) source is not a microphone type");
503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // Case 2 : one source only and no MUX control detected =>
506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    //          locate the master volume control (and mute + boost controls if possible)
507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // scan the controls for this wave-in destination and search for volume, mute and on/off (<=> boost) controls
509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    for (UINT dc = 0; dc < destLine.cControls; dc++)
510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    {
511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        if (controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // store this volume control
514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            _microphoneState[mixId].dwVolumeControlID = controlArray[dc].dwControlID;
515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            _microphoneState[mixId].volumeControlIsValid = true;
516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found volume control (name: %s, ID: %u)", WideToUTF8(controlArray[dc].szName), controlArray[dc].dwControlID);
517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        }
518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        else if (controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // store this mute control
521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            _microphoneState[mixId].dwMuteControlID = controlArray[dc].dwControlID;
522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            _microphoneState[mixId].muteControlIsValid = true;
523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found mute control (name: %s, ID: %u)", WideToUTF8(controlArray[dc].szName), controlArray[dc].dwControlID);
524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        }
525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        else if (controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF ||
526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_LOUDNESS ||
527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 controlArray[dc].dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN)
528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        {
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            // store this on/off control
530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            _microphoneState[mixId].dwOnOffControlID = controlArray[dc].dwControlID;
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            _microphoneState[mixId].onOffControlIsValid = true;
532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "found on/off control (name: %s, ID: %u)", WideToUTF8(controlArray[dc].szName), controlArray[dc].dwControlID);
533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        }
534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    }
535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                }
536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                else
537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                {
538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // We are in a state where more than one source is connected to the wave-in destination.
539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    // I am bailing out here for now until I understand this case better.
540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to locate valid microphone controls for this mixer");
541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                }
542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                break;
543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }  // for (destId = 0; destId < caps.cDestinations; destId++)
545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (!MicrophoneIsValid(mixId))
547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to find a valid microphone destination line", mixId);
549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }  // for (mixId = 0; mixId < nDevices; mixId++)
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (ValidMicrophones() == 0)
553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to locate any valid microphone line");
555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  OpenSpeaker I(II)
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Verifies that the mixer contains a valid speaker destination line.
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Avoids opening the mixer if valid control has not been found.
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
56864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::OpenSpeaker(AudioDeviceModule::WindowsDeviceType device)
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (device == AudioDeviceModule::kDefaultDevice)
571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenSpeaker(kDefaultDevice)");
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (device == AudioDeviceModule::kDefaultCommunicationDevice)
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenSpeaker(kDefaultCommunicationDevice)");
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Close any existing output mixer handle
582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle != NULL)
584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerClose(_outputMixerHandle);
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _outputMixerHandle = NULL;
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
58922c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org    MMRESULT     res = MMSYSERR_NOERROR;
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WAVEFORMATEX waveFormat;
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HWAVEOUT     hWaveOut(NULL);
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wFormatTag      = WAVE_FORMAT_PCM ;
594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nChannels       = 2;
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nSamplesPerSec  = 48000;
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wBitsPerSample  = 16;
597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nBlockAlign     = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.cbSize          = 0;
600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // We need a waveform-audio output handle for the currently selected output device.
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // This handle will then give us the corresponding mixer identifier. Once the mixer
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // ID is known, it is possible to open the output mixer.
604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (device == AudioDeviceModule::kDefaultCommunicationDevice)
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // check if it is possible to open the default communication device (supported on Windows 7)
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        res = waveOutOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL |
609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WAVE_MAPPED_kDefaultCommunicationDevice | WAVE_FORMAT_QUERY);
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (MMSYSERR_NOERROR == res)
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // if so, open the default communication device for real
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_kDefaultCommunicationDevice);
614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device");
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        else
617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // use default device since default communication device was not avaliable
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                "unable to open default communication device => using default instead");
622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (device == AudioDeviceModule::kDefaultDevice)
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // open default device since it has been requested
627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default output device");
629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutOpen() failed (err=%d)", res);
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceWaveOutError(res);
635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT   mixerId(0);
638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HMIXER hMixer(NULL);
639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the device identifier for a mixer device associated with the
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // aquired waveform-audio output handle.
642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetID((HMIXEROBJ)hWaveOut, &mixerId, MIXER_OBJECTF_HWAVEOUT);
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEOUT) failed (err=%d)", res);
647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // identification failed => use default mixer identifier (=0)
648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerId = 0;
649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified output device <=> mixer ID %u", mixerId);
651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // The waveform-audio output handle is no longer needed.
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveOutClose(hWaveOut);
655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Verify that the mixer contains a valid speaker destination line.
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Avoid opening the mixer if valid control has not been found.
658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SpeakerIsValid(mixerId))
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the speaker volume for this mixer device");
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Open the specified mixer device and ensure that the device will not
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // be removed until the application closes the handle.
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Store the output mixer handle and active mixer identifier
675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _outputMixerHandle = hMixer;
677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _outputMixerID = mixerId;
678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle != NULL)
680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the output mixer device is now open (0x%x)", _outputMixerHandle);
682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  OpenSpeaker II(II)
689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Verifies that the mixer contains a valid speaker destination line.
691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Avoids opening the mixer if valid control has not been found.
692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
69464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::OpenSpeaker(uint16_t index)
695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenSpeaker(index=%d)", index);
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Close any existing output mixer handle
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle != NULL)
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerClose(_outputMixerHandle);
705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _outputMixerHandle = NULL;
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT     res;
709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WAVEFORMATEX waveFormat;
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HWAVEOUT     hWaveOut(NULL);
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT   deviceID(index);  // use index parameter as device identifier
713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wFormatTag      = WAVE_FORMAT_PCM ;
715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nChannels       = 2;
716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nSamplesPerSec  = 48000;
717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wBitsPerSample  = 16;
718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nBlockAlign     = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.cbSize          = 0;
721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // We need a waveform-audio output handle for the currently selected output device.
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // This handle will then give us the corresponding mixer identifier. Once the mixer
724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // ID is known, it is possible to open the output mixer.
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = waveOutOpen(&hWaveOut, deviceID, &waveFormat, 0, 0, CALLBACK_NULL);
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutOpen(deviceID=%u) failed (err=%d)", index, res);
730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceWaveOutError(res);
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT   mixerId(0);
734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HMIXER hMixer(NULL);
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the device identifier for a mixer device associated with the
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // aquired waveform-audio output handle.
738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetID((HMIXEROBJ)hWaveOut, &mixerId, MIXER_OBJECTF_HWAVEOUT);
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEOUT) failed (err=%d)", res);
743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // identification failed => use default mixer identifier (=0)
744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerId = 0;
745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified output device <=> mixer ID %u", mixerId);
747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // The waveform-audio output handle is no longer needed.
749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveOutClose(hWaveOut);
751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Verify that the mixer contains a valid speaker destination line.
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Avoid opening the mixer if valid control has not been found.
754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SpeakerIsValid(mixerId))
756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the speaker volume for this mixer device");
758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Open the specified mixer device and ensure that the device will not
762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // be removed until the application closes the handle.
763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Store the output mixer handle and active mixer identifier
771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _outputMixerHandle = hMixer;
773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _outputMixerID = mixerId;
774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle != NULL)
776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the output mixer device is now open (0x%x)", _outputMixerHandle);
778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  OpenMicrophone I(II)
785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Verifies that the mixer contains a valid wave-in destination line.
787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Avoids opening the mixer if valid control has not been found.
788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
79064a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::OpenMicrophone(AudioDeviceModule::WindowsDeviceType device)
791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (device == AudioDeviceModule::kDefaultDevice)
793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenMicrophone(kDefaultDevice)");
795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (device == AudioDeviceModule::kDefaultCommunicationDevice)
797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenMicrophone(kDefaultCommunicationDevice)");
799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Close any existing output mixer handle
804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle != NULL)
806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerClose(_inputMixerHandle);
808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _inputMixerHandle = NULL;
809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
81122c283b04855b8775d323e8788a0438ce2d7c2b5henrike@webrtc.org    MMRESULT     res = MMSYSERR_NOERROR;
812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WAVEFORMATEX waveFormat;
813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HWAVEIN         hWaveIn(NULL);
814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wFormatTag      = WAVE_FORMAT_PCM ;
816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nChannels       = 1;
817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nSamplesPerSec  = 48000;
818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wBitsPerSample  = 16;
819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nBlockAlign     = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.cbSize          = 0 ;
822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // We need a waveform-audio input handle for the currently selected input device.
824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // This handle will then give us the corresponding mixer identifier. Once the mixer
825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // ID is known, it is possible to open the input mixer.
826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (device == AudioDeviceModule::kDefaultCommunicationDevice)
828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // check if it is possible to open the default communication device (supported on Windows 7)
830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        res = waveInOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL |
831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WAVE_MAPPED_kDefaultCommunicationDevice | WAVE_FORMAT_QUERY);
832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (MMSYSERR_NOERROR == res)
833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // if so, open the default communication device for real
835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_kDefaultCommunicationDevice);
836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device");
837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        else
839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            // use default device since default communication device was not avaliable
841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                "unable to open default communication device => using default instead");
844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (device == AudioDeviceModule::kDefaultDevice)
847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // open default device since it has been requested
849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL);
850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default input device");
851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInOpen() failed (err=%d)", res);
856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceWaveInError(res);
857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT   mixerId(0);
860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HMIXER hMixer(NULL);
861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the device identifier for a mixer device associated with the
863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // aquired waveform-audio input handle.
864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetID((HMIXEROBJ)hWaveIn, &mixerId, MIXER_OBJECTF_HWAVEIN);
866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEIN) failed (err=%d)", res);
869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // identification failed => use default mixer identifier (=0)
870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerId = 0;
871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified input device <=> mixer ID %u", mixerId);
873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // The waveform-audio input handle is no longer needed.
875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveInClose(hWaveIn);
877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Verify that the mixer contains a valid wave-in destination line and a volume control.
879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Avoid opening the mixer if valid control has not been found.
880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!MicrophoneIsValid(mixerId))
882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the microphone volume for this mixer device");
884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Open the specified mixer device and ensure that the device will not
888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // be removed until the application closes the handle.
889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Store the input mixer handle and active mixer identifier
897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _inputMixerHandle = hMixer;
899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _inputMixerID = mixerId;
900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle != NULL)
902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the input mixer device is now open (0x%x)", _inputMixerHandle);
904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  OpenMicrophone II(II)
911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Verifies that the mixer contains a valid wave-in destination line.
913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Avoids opening the mixer if valid control has not been found.
914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
91664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::OpenMicrophone(uint16_t index)
917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::OpenMicrophone(index=%d)", index);
919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Close any existing input mixer handle
923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle != NULL)
925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerClose(_inputMixerHandle);
927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        _inputMixerHandle = NULL;
928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT     res;
931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WAVEFORMATEX waveFormat;
932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HWAVEIN         hWaveIn(NULL);
933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT   deviceID(index);  // use index parameter as device identifier
935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wFormatTag      = WAVE_FORMAT_PCM ;
937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nChannels       = 1;
938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nSamplesPerSec  = 48000;
939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.wBitsPerSample  = 16;
940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nBlockAlign     = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveFormat.cbSize          = 0;
943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // We need a waveform-audio input handle for the currently selected input device.
945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // This handle will then give us the corresponding mixer identifier. Once the mixer
946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // ID is known, it is possible to open the input mixer.
947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = waveInOpen(&hWaveIn, deviceID, &waveFormat, 0, 0, CALLBACK_NULL);
949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInOpen(deviceID=%u) failed (err=%d)", index, res);
952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceWaveInError(res);
953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT   mixerId(0);
956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    HMIXER hMixer(NULL);
957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the device identifier for a mixer device associated with the
959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // aquired waveform-audio input handle.
960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetID((HMIXEROBJ)hWaveIn, &mixerId, MIXER_OBJECTF_HWAVEIN);
962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetID(MIXER_OBJECTF_HWAVEIN) failed (err=%d)", res);
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // identification failed => use default mixer identifier (=0)
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        mixerId = 0;
967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "specified input device <=> mixer ID %u", mixerId);
969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // The waveform-audio input handle is no longer needed.
971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveInClose(hWaveIn);
973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Verify that the mixer contains a valid wave-in destination line.
975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Avoid opening the mixer if valid control has not been found.
976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!MicrophoneIsValid(mixerId))
978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to control the microphone volume for this mixer device");
980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Open the specified mixer device and ensure that the device will not
984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // be removed until the application closes the handle.
985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerOpen(&hMixer, mixerId, 0, 0, MIXER_OBJECTF_MIXER);
987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (MMSYSERR_NOERROR != res)
988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerOpen() failed (err=%d)", res);
990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Store the input mixer handle and active mixer identifier
993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _inputMixerHandle = hMixer;
995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _inputMixerID = mixerId;
996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle != NULL)
998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "the input mixer device is now open (0x%x)", _inputMixerHandle);
1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerIsInitialized
1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::SpeakerIsInitialized() const
1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (_outputMixerHandle != NULL);
1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MicrophoneIsInitialized
1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::MicrophoneIsInitialized() const
1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s", __FUNCTION__);
1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (_inputMixerHandle != NULL);
1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetSpeakerVolume
1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SetSpeakerVolume(uint32_t volume)
1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetSpeakerVolume(volume=%u)", volume);
1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_outputMixerID);
1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    DWORD dwValue(volume);
1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set one unsigned control value for a specified volume-control identifier
1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SetUnsignedControlValue(mixerID, dwControlID, dwValue))
1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (0);
1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SpeakerVolume
1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Note that (MIXERCONTROL_CONTROLTYPE_VOLUME & MIXERCONTROL_CT_UNITS_MASK)
1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  always equals MIXERCONTROL_CT_UNITS_UNSIGNED;
1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
106464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SpeakerVolume(uint32_t& volume) const
1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_outputMixerID);
1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    DWORD dwValue(0);
1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one unsigned control value for a specified volume-control identifier
1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetUnsignedControlValue(mixerID, dwControlID, dwValue))
1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    volume = dwValue;
1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MaxSpeakerVolume
1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Note that (MIXERCONTROL_CONTROLTYPE_VOLUME & MIXERCONTROL_CT_UNITS_MASK)
1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  always equals MIXERCONTROL_CT_UNITS_UNSIGNED
1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
109664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MaxSpeakerVolume(uint32_t& maxVolume) const
1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_outputMixerID);
1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL mixerControl;
1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one control line for a specified volume-control identifier
1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetLineControl(mixerID, dwControlID, mixerControl))
1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    maxVolume = mixerControl.Bounds.dwMaximum;
1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MinSpeakerVolume
1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
112564a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MinSpeakerVolume(uint32_t& minVolume) const
1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_outputMixerID);
1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_speakerState[_outputMixerID].dwVolumeControlID);
1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL mixerControl;
1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one control line for a specified volume-control identifier
1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetLineControl(mixerID, dwControlID, mixerControl))
1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    minVolume = mixerControl.Bounds.dwMinimum;
1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerVolumeStepSize
1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SpeakerVolumeStepSize(uint16_t& stepSize) const
1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_outputMixerID);
1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL mixerControl;
1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one control line for a specified volume-control identifier
1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetLineControl(mixerID, _speakerState[mixerID].dwVolumeControlID, mixerControl))
1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
117364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org    stepSize = static_cast<uint16_t> (mixerControl.Metrics.cSteps);
1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerVolumeIsAvailable
1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
118264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SpeakerVolumeIsAvailable(bool& available)
1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    available = _speakerState[_outputMixerID].volumeControlIsValid;
1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SpeakerMuteIsAvailable
1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
119964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SpeakerMuteIsAvailable(bool& available)
1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    available = _speakerState[_outputMixerID].muteControlIsValid;
1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SetSpeakerMute
1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  This mute function works a master mute for the output speaker.
1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121864a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SetSpeakerMute(bool enable)
1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetSpeakerMute(enable=%u)", enable);
1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that the selected speaker destination has a valid mute control.
1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If so, its identifier was stored during the enumeration phase which must
1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // have taken place since the output mixer handle exists.
1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!_speakerState[_outputMixerID].muteControlIsValid)
1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this speaker line");
1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_speakerState[_outputMixerID].dwMuteControlID);
1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set one boolean control value for the specified mute-control
1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SetBooleanControlValue(_outputMixerID, dwControlID, enable))
1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (0);
1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SpeakerMute
1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
125664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SpeakerMute(bool& enabled) const
1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_outputMixerHandle == NULL)
1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable output mixer exists");
1262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that the selected speaker destination has a valid mute control.
1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If so, its identifier was stored during the enumeration phase which must
1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // have taken place since the output mixer handle exists.
1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!_speakerState[_outputMixerID].muteControlIsValid)
1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this speaker line");
1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_speakerState[_outputMixerID].dwMuteControlID);
1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bool value(false);
1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one boolean control value for a specified mute-control identifier
1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetBooleanControlValue(_outputMixerID, dwControlID, value))
1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    enabled = value;
1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneMuteIsAvailable
1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
129464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneMuteIsAvailable(bool& available)
1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    available = _microphoneState[_inputMixerID].muteControlIsValid;
1303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// SetMicrophoneMute
1309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  This mute function works a master mute for the input microphone.
1311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
131364a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SetMicrophoneMute(bool enable)
1314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetMicrophoneMute(enable=%u)", enable);
1316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
1318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that the selected wave-in destinationhas a valid mute control.
1326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If so, its identifier was stored during the enumeration phase which must
1327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // have taken place since the input mixer handle exists.
1328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!_microphoneState[_inputMixerID].muteControlIsValid)
1330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this microphone line");
1332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwMuteControlID);
1336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set one boolean control value for the specified mute-control
1338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SetBooleanControlValue(_inputMixerID, dwControlID, enable))
1340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (0);
1345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneMute
1349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
135164a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneMute(bool& enabled) const
1352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that the selected wave-in destinationhas a valid mute control.
1361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If so, its identifier was stored during the enumeration phase which must
1362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // have taken place since the input mixer handle exists.
1363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!_microphoneState[_inputMixerID].muteControlIsValid)
1365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "it is not possible to mute this microphone line");
1367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwMuteControlID);
1371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bool value(false);
1372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one boolean control value for a specified mute-control identifier
1374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetBooleanControlValue(_inputMixerID, dwControlID, value))
1376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    enabled = value;
1381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneBoostIsAvailable
1387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
138964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneBoostIsAvailable(bool& available)
1390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    available = _microphoneState[_inputMixerID].onOffControlIsValid;
1398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SetMicrophoneBoost
1404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
140664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SetMicrophoneBoost(bool enable)
1407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetMicrophoneBoost(enable=%u)", enable);
1409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
1411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that the selected wave-in destination has a valid boost (on/off) control.
1419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If so, its identifier was stored during the enumeration phase which must
1420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // have taken place since the input mixer handle exists.
1421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!_microphoneState[_inputMixerID].onOffControlIsValid)
1423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no boost control exists for this wave-in line");
1425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwOnOffControlID);
1429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set one boolean control value for the specified boost (on/off) control
1431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SetBooleanControlValue(_inputMixerID, dwControlID, enable))
1433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (0);
1438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneBoost
1442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144464a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneBoost(bool& enabled) const
1445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that the selected wave-in destination has a valid boost (on/off) control.
1454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If so, its identifier was stored during the enumeration phase which must
1455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // have taken place since the input mixer handle exists.
1456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!_microphoneState[_inputMixerID].onOffControlIsValid)
1458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no boost control exists for this wave-in line");
1460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwOnOffControlID);
1464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bool value(false);
1465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one boolean control value for a specified boost-control identifier
1467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetBooleanControlValue(_inputMixerID, dwControlID, value))
1469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    enabled = value;
1474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneVolumeIsAvailable
1480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
148264a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneVolumeIsAvailable(bool& available)
1483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    available = _microphoneState[_inputMixerID].volumeControlIsValid;
1491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SetMicrophoneVolume
1497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
149964a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::SetMicrophoneVolume(uint32_t volume)
1500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
1502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_inputMixerID);
1510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
1511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    DWORD dwValue(volume);
1512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set one unsigned control value for a specified volume-control identifier
1514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!SetUnsignedControlValue(mixerID, dwControlID, dwValue))
1516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (0);
1521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneVolume
1525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
152764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneVolume(uint32_t& volume) const
1528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped lock(&_critSect);
1530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_inputMixerID);
1538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
1539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    DWORD dwValue(0);
1540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one unsigned control value for a specified volume-control identifier
1542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetUnsignedControlValue(mixerID, dwControlID, dwValue))
1544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    volume = dwValue;
1549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MaxMicrophoneVolume
1555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
155764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MaxMicrophoneVolume(uint32_t& maxVolume) const
1558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "%s", __FUNCTION__);
1560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_inputMixerID);
1568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
1569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL mixerControl;
1570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one control line for a specified volume-control identifier
1572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetLineControl(mixerID, dwControlID, mixerControl))
1574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    maxVolume = mixerControl.Bounds.dwMaximum;
1579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// MinMicrophoneVolume
1585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
158764a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MinMicrophoneVolume(uint32_t& minVolume) const
1588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_inputMixerID);
1597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
1598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL mixerControl;
1599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one control line for a specified volume-control identifier
1601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetLineControl(mixerID, dwControlID, mixerControl))
1603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    minVolume = mixerControl.Bounds.dwMinimum;
1608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneVolumeStepSize
1614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
161664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.orgint32_t AudioMixerManager::MicrophoneVolumeStepSize(uint16_t& stepSize) const
1617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (_inputMixerHandle == NULL)
1620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no avaliable input mixer exists");
1622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const UINT mixerID(_inputMixerID);
1626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const DWORD dwControlID(_microphoneState[_inputMixerID].dwVolumeControlID);
1627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROL mixerControl;
1628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve one control line for a specified volume-control identifier
1630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetLineControl(mixerID, dwControlID, mixerControl))
1632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
1634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
163664a144ff1bf67bc85942721aab04c98757b83e3bpbos@webrtc.org    stepSize = static_cast<uint16_t> (mixerControl.Metrics.cSteps);
1637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
1639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================
1642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//                              PRIVATE METHODS
1643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ============================================================================
1644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Devices
1647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  A given audio card has one Mixer device associated with it. All of the
1649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  various components on that card are controlled through that card's one
1650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Mixer device.
1651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgUINT AudioMixerManager::Devices() const
1654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT nDevs = mixerGetNumDevs();
1656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return nDevs;
1657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  DestinationLines
1661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  # destination lines given mixer ID.
1663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgUINT AudioMixerManager::DestinationLines(UINT mixId) const
1666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCAPS caps;
1668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetCapabilities(mixId, caps))
1669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return 0;
1671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (caps.cDestinations);
1673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  DestinationLines
1676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  # source lines given mixer ID and destination ID.
1678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgUINT AudioMixerManager::SourceLines(UINT mixId, DWORD destId) const
1681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE dline;
1683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!GetDestinationLineInfo(mixId, destId, dline))
1684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return 0;
1686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (dline.cConnections);
1688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetCapabilities
1692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
1693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Queries a specified mixer device to determine its capabilities.
1694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetCapabilities(UINT mixId, MIXERCAPS& caps, bool trace) const
1697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT res;
1699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCAPS mcaps;
1700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetDevCaps(mixId, &mcaps, sizeof(MIXERCAPS));
1702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
1703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetDevCaps() failed (err=%d)", res);
1705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&caps, &mcaps, sizeof(MIXERCAPS));
1709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (trace)
1711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "===============================================================");
1713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Mixer ID %u:", mixId);
1714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID      : %u", caps.wMid);
1715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID           : %u", caps.wPid);
1716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "version of driver    : %u", caps.vDriverVersion);
1717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name         : %s", WideToUTF8(caps.szPname));
1718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "misc. support bits   : %u", caps.fdwSupport);
1719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "count of destinations: %u (+)", caps.cDestinations);
1720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "===============================================================");
1721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (caps.cDestinations == 0)
1724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "invalid number of mixer destinations");
1726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
1730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetDestinationLineInfo
1734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetDestinationLineInfo(UINT mixId, DWORD destId, MIXERLINE& line, bool trace) const
1737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT  res;
1739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE mline;
1740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mline.cbStruct = sizeof(MIXERLINE);
1742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mline.dwDestination = destId;   // max destination index is cDestinations-1
1743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mline.dwSource = 0;             // not set for MIXER_GETLINEINFOF_DESTINATION
1744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve information about the specified destination line of a mixer device.
1746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Note that we use the mixer ID here and not a handle to an opened mixer.
1747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // It is not required to open the mixer for enumeration purposes only.
1748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(mixId), &mline, MIXER_OBJECTF_MIXER | MIXER_GETLINEINFOF_DESTINATION);
1750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
1751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineInfo(MIXER_GETLINEINFOF_DESTINATION) failed (err=%d)", res);
1753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&line, &mline, sizeof(MIXERLINE));
1757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (trace)
1759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "> Destination Line ID %u:", destId);
1761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "destination line index : %u", mline.dwDestination);
1763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwLineID               : %lu (unique)", mline.dwLineID);
1764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceStatusAndSupportFlags(mline.fdwLine);
1765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceComponentType(mline.dwComponentType);
1766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "count of channels      : %u", mline.cChannels);
1767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "# audio source lines   : %u (+)", mline.cConnections);    // valid only for destinations
1768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "# controls             : %u (*)", mline.cControls);       // can be zero
1769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "short name             : %s", WideToUTF8(mline.szShortName));
1770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "full name              : %s", WideToUTF8(mline.szName));
1771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceTargetType(mline.Target.dwType);
1773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "target device ID       : %lu", mline.Target.dwDeviceID);
1774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID        : %u", mline.Target.wMid);
1775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID             : %u", mline.Target.wPid);
1776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "driver version         : %u", mline.Target.vDriverVersion);
1777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name           : %s", WideToUTF8(mline.Target.szPname));
1778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "---------------------------------------------------------------");
1779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
1782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetSourceLineInfo
1786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetSourceLineInfo(UINT mixId, DWORD destId, DWORD srcId, MIXERLINE& line, bool trace) const
1789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT  res;
1791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINE mline;
1792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mline.cbStruct = sizeof(MIXERLINE);
1794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mline.dwDestination = destId;   // we want the source info for this destination
1795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mline.dwSource = srcId;         // source index (enumerate over these)
1796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve information about the specified source line of a mixer device.
1798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Note that we use the mixer ID here and not a handle to an opened mixer.
1799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // It is not required to open the mixer for enumeration purposes only.
1800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetLineInfo(reinterpret_cast<HMIXEROBJ>(mixId), &mline, MIXER_OBJECTF_MIXER | MIXER_GETLINEINFOF_SOURCE);
1802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
1803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineInfo(MIXER_GETLINEINFOF_SOURCE) failed (err=%d)", res);
1805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&line, &mline, sizeof(MIXERLINE));
1809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (trace)
1811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " >> Source Line ID %u:", srcId);
1813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "destination line index : %u", mline.dwDestination);
1814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwSource               : %u", mline.dwSource);
1815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwLineID               : %lu (unique)", mline.dwLineID);
1816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceStatusAndSupportFlags(mline.fdwLine);
1817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceComponentType(mline.dwComponentType);
1818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "# controls             : %u (*)", mline.cControls);
1819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "full name              : %s", WideToUTF8(mline.szName));
1820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
1821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        TraceTargetType(mline.Target.dwType);
1822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "---------------------------------------------------------------");
1823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
1826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// GetAllLineControls
1830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetAllLineControls(UINT mixId, const MIXERLINE& line, MIXERCONTROL* controlArray, bool trace) const
1833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Ensure that we don't try to aquire information if there are no controls for this line
1835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (line.cControls == 0)
1837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT          res;
1840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINECONTROLS mlineControls;            // contains information about the controls of an audio line
1841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControls.dwLineID  = line.dwLineID;    // unique audio line identifier
1843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControls.cControls = line.cControls;   // number of controls associated with the line
1844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControls.pamxctrl  = controlArray;     // points to the first MIXERCONTROL structure to be filled
1845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControls.cbStruct  = sizeof(MIXERLINECONTROLS);
1846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControls.cbmxctrl  = sizeof(MIXERCONTROL);
1847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Get information on ALL controls associated with the specified audio line
1849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(mixId), &mlineControls, MIXER_OBJECTF_MIXER | MIXER_GETLINECONTROLSF_ALL);
1851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
1852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineControls(MIXER_GETLINECONTROLSF_ALL) failed  (err=%d)", res);
1854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (trace)
1858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for (UINT c = 0; c < line.cControls; c++)
1860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " >> Control ID %u:", c);
1862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwControlID            : %u (unique)", controlArray[c].dwControlID);
1863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            TraceControlType(controlArray[c].dwControlType);
1864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            TraceControlStatusAndSupportFlags(controlArray[c].fdwControl);
1865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cMultipleItems         : %u", controlArray[c].cMultipleItems);
1866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "short name             : %s", WideToUTF8(controlArray[c].szShortName));
1867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "full name              : %s", WideToUTF8(controlArray[c].szName));
1868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if ((controlArray[c].dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_SIGNED)
1869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "min signed value       : %d", controlArray[c].Bounds.lMinimum);
1871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "max signed value       : %d", controlArray[c].Bounds.lMaximum);
1872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            else if ((controlArray[c].dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_UNSIGNED ||
1874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                     (controlArray[c].dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_BOOLEAN)
1875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "min unsigned value     : %u",  controlArray[c].Bounds.dwMinimum);
1877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "max unsigned value     : %u", controlArray[c].Bounds.dwMaximum);
1878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if (controlArray[c].dwControlType  != MIXERCONTROL_CONTROLTYPE_CUSTOM)
1880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cSteps                 : %u",  controlArray[c].Metrics.cSteps);
1882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "...............................................................");
1884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            GetControlDetails(mixId, controlArray[c], true);
1885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "...............................................................");
1886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
1888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
1891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetLineControls
1895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetLineControl(UINT mixId, DWORD dwControlID, MIXERCONTROL& control) const
1898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT          res;
1900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERLINECONTROLS mlineControl;
1901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControl.dwControlID = dwControlID;
1903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControl.cControls   = 1;
1904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControl.pamxctrl    = &control;
1905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControl.cbStruct    = sizeof(MIXERLINECONTROLS);
1906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mlineControl.cbmxctrl    = sizeof(MIXERCONTROL);
1907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Get information on one controls associated with the specified conrol identifier
1909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetLineControls(reinterpret_cast<HMIXEROBJ>(mixId), &mlineControl, MIXER_OBJECTF_MIXER | MIXER_GETLINECONTROLSF_ONEBYID);
1911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
1912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetLineControls(MIXER_GETLINECONTROLSF_ONEBYID) failed (err=%d)", res);
1914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
1918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetControlDetails
1922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
1923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetControlDetails(UINT mixId, MIXERCONTROL& controlArray, bool trace) const
1925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    assert(controlArray.cMultipleItems <= MAX_NUMBER_OF_MULTIPLE_ITEMS);
1927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT                     res;
1929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS          controlDetails;
1930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_UNSIGNED valueUnsigned[MAX_NUMBER_OF_MULTIPLE_ITEMS];
1932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_SIGNED   valueSigned[MAX_NUMBER_OF_MULTIPLE_ITEMS];
1933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_BOOLEAN  valueBoolean[MAX_NUMBER_OF_MULTIPLE_ITEMS];
1934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    enum ControlType
1936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        CT_UNITS_UNSIGNED,
1938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        CT_UNITS_SIGNED,
1939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        CT_UNITS_BOOLEAN
1940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    };
1941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ControlType ctype(CT_UNITS_UNSIGNED);
1943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbStruct       = sizeof(MIXERCONTROLDETAILS);
1945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.dwControlID    = controlArray.dwControlID;       // control identifier
1946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cChannels      = 1;                              // we need to set values as if they were uniform
1947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cMultipleItems = controlArray.cMultipleItems;    // only nonzero for CONTROLF_MULTIPLE controls
1948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                                    // can e.g. happen for CONTROLTYPE_MUX
1949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (controlDetails.cMultipleItems > MAX_NUMBER_OF_MULTIPLE_ITEMS)
1950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "cMultipleItems > %d", MAX_NUMBER_OF_MULTIPLE_ITEMS);
1952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.cMultipleItems = MAX_NUMBER_OF_MULTIPLE_ITEMS;
1953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((controlArray.dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_SIGNED)
1956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ctype = CT_UNITS_SIGNED;
1958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_SIGNED);
1959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.paDetails = &valueSigned[0];
1960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if ((controlArray.dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_UNSIGNED)
1962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ctype = CT_UNITS_UNSIGNED;
1964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
1965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.paDetails = &valueUnsigned[0];
1966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if ((controlArray.dwControlType & MIXERCONTROL_CT_UNITS_MASK) == MIXERCONTROL_CT_UNITS_BOOLEAN)
1968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ctype = CT_UNITS_BOOLEAN;
1970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
1971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        controlDetails.paDetails = &valueBoolean[0];
1972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve a control's value
1975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
1976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
1977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
1978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
1980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
1981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (trace)
1984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        UINT nItems(1);
1986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        nItems = (controlDetails.cMultipleItems > 0 ? controlDetails.cMultipleItems : 1);
1987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for (UINT i = 0; i < nItems; i++)
1988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
1989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            if (ctype == CT_UNITS_SIGNED)
1990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "signed value           : %d", valueSigned[i].lValue);
1992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            else if (ctype == CT_UNITS_UNSIGNED)
1994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unsigned value         : %u", valueUnsigned[i].dwValue);
1996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
1997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            else if (ctype == CT_UNITS_BOOLEAN)
1998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            {
1999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "boolean value          : %u", valueBoolean[i].fValue);
2000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            }
2001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
2002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
2005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetUnsignedControlValue
2009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetUnsignedControlValue(UINT mixId, DWORD dwControlID, DWORD& dwValue) const
2012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT                     res;
2014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS          controlDetails;
2015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_UNSIGNED valueUnsigned;
2016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.dwControlID    = dwControlID;
2018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbStruct       = sizeof(MIXERCONTROLDETAILS);
2019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cChannels      = 1;
2020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cMultipleItems = 0;
2021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbDetails      = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
2022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.paDetails      = &valueUnsigned;
2023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the unsigned value
2025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
2027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
2028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
2030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
2031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Deliver the retrieved value
2034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    dwValue = valueUnsigned.dwValue;
2036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
2038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SetUnsignedControlValue
2042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::SetUnsignedControlValue(UINT mixId, DWORD dwControlID, DWORD dwValue) const
2045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "AudioMixerManager::SetUnsignedControlValue(mixId=%u, dwControlID=%d, dwValue=%d)", mixId, dwControlID, dwValue);
2047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT                     res;
2049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS          controlDetails;
2050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_UNSIGNED valueUnsigned;
2051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.dwControlID    = dwControlID;
2053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbStruct       = sizeof(MIXERCONTROLDETAILS);
2054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cChannels      = 1;
2055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cMultipleItems = 0;
2056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbDetails      = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
2057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.paDetails      = &valueUnsigned;
2058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    valueUnsigned.dwValue         = dwValue;
2060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set the unsigned value
2062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
2064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
2065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerSetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
2067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
2068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
2071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SetBooleanControlValue
2075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::SetBooleanControlValue(UINT mixId, DWORD dwControlID, bool value) const
2078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioMixerManager::SetBooleanControlValue(mixId=%u, dwControlID=%d, value=%d)", mixId, dwControlID, value);
2080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT                    res;
2082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS         controlDetails;
2083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_BOOLEAN valueBoolean;
2084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.dwControlID    = dwControlID;
2086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbStruct       = sizeof(MIXERCONTROLDETAILS);
2087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cChannels      = 1;
2088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cMultipleItems = 0;
2089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbDetails      = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
2090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.paDetails      = &valueBoolean;
2091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (value == true)
2093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        valueBoolean.fValue = TRUE;
2094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else
2095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        valueBoolean.fValue = FALSE;
2096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set the boolean value
2098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
2100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
2101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerSetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
2103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
2104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
2107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetBooleanControlValue
2111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetBooleanControlValue(UINT mixId, DWORD dwControlID, bool& value) const
2114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT                    res;
2116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS         controlDetails;
2117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_BOOLEAN valueBoolean;
2118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.dwControlID    = dwControlID;
2120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbStruct       = sizeof(MIXERCONTROLDETAILS);
2121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cChannels      = 1;
2122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cMultipleItems = 0;
2123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbDetails      = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
2124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.paDetails      = &valueBoolean;
2125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the boolean value
2127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
2129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
2130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
2132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
2133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Deliver the retrieved value
2136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (valueBoolean.fValue == 0)
2138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        value = false;
2139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else
2140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        value = true;
2141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
2143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  GetSelectedMuxSource
2147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::GetSelectedMuxSource(UINT mixId, DWORD dwControlID, DWORD cMultipleItems, UINT& index) const
2150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    assert(cMultipleItems <= MAX_NUMBER_OF_MULTIPLE_ITEMS);
2152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MMRESULT                    res;
2154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS         controlDetails;
2155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    MIXERCONTROLDETAILS_BOOLEAN valueBoolean[MAX_NUMBER_OF_MULTIPLE_ITEMS];
2156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memset(&valueBoolean, 0, sizeof(valueBoolean));
2157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.dwControlID    = dwControlID;
2159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbStruct       = sizeof(MIXERCONTROLDETAILS);
2160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cChannels      = 1;
2161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cMultipleItems = cMultipleItems;
2162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.cbDetails      = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
2163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    controlDetails.paDetails      = &valueBoolean;
2164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Retrieve the boolean values
2166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    res = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(mixId), &controlDetails, MIXER_OBJECTF_MIXER | MIXER_GETCONTROLDETAILSF_VALUE);
2168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (res != MMSYSERR_NOERROR)
2169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE) failed (err=%d)", res);
2171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return false;
2172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Map the current MUX setting to an index corresponding to a source index.
2175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // e.g. with cMultipleItems = 3,
2176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //  valueBoolean[] = {1,0,0} => index = 2
2177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //  valueBoolean[] = {0,1,0} => index = 1
2178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //  valueBoolean[] = {0,0,1} => index = 0
2179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // If there is no "1" in the array, we assume index should be 0.
2181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index = 0;
2182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (DWORD i = 0; i < cMultipleItems; i++)
2183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (valueBoolean[i].fValue > 0)
2185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        {
2186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            index = (cMultipleItems - 1) - i;
2187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            break;
2188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
2189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return true;
2192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceStatusAndSupportFlags
2196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceStatusAndSupportFlags(DWORD fdwLine) const
2199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[128];
2201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, 128, TEXT("status & support flags : 0x%x "), fdwLine);
2203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (fdwLine)
2205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_LINEF_ACTIVE:
2207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(ACTIVE DESTINATION)"));
2208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_LINEF_DISCONNECTED:
2210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DISCONNECTED)"));
2211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_LINEF_SOURCE:
2213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(INACTIVE SOURCE)"));
2214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_LINEF_SOURCE | MIXERLINE_LINEF_ACTIVE:
2216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(ACTIVE SOURCE)"));
2217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(INVALID)"));
2220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceComponentType
2228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceComponentType(DWORD dwComponentType) const
2231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[128];
2233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, 128, TEXT("component type         : 0x%x "), dwComponentType);
2235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (dwComponentType)
2237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Destination
2239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_UNDEFINED:
2240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_UNDEFINED)"));
2241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_DIGITAL:
2243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_DIGITAL)"));
2244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_LINE:
2246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_LINE)"));
2247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_MONITOR:
2249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_MONITOR)"));
2250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS:
2252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_SPEAKERS)"));
2253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_HEADPHONES:
2255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_HEADPHONES)"));
2256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_TELEPHONE:
2258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_TELEPHONE)"));
2259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_WAVEIN:
2261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_WAVEIN)"));
2262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_DST_VOICEIN:
2264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(DST_VOICEIN)"));
2265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Source
2267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED:
2268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_UNDEFINED)"));
2269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_DIGITAL:
2271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_DIGITAL)"));
2272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_LINE:
2274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_LINE)"));
2275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE:
2277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_MICROPHONE)"));
2278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER:
2280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_SYNTHESIZER)"));
2281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC:
2283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_COMPACTDISC)"));
2284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE:
2286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_TELEPHONE)"));
2287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER:
2289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_PCSPEAKER)"));
2290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT:
2292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_WAVEOUT)"));
2293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY:
2295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_AUXILIARY)"));
2296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_COMPONENTTYPE_SRC_ANALOG:
2298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(SRC_ANALOG)"));
2299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(INVALID)"));
2302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceTargetType
2310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceTargetType(DWORD dwType) const
2313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[128];
2315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, 128, TEXT("media device type      : 0x%x "), dwType);
2317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (dwType)
2319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_TARGETTYPE_UNDEFINED:
2321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(UNDEFINED)"));
2322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_TARGETTYPE_WAVEOUT:
2324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(WAVEOUT)"));
2325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_TARGETTYPE_WAVEIN:
2327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(WAVEIN)"));
2328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_TARGETTYPE_MIDIOUT:
2330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(MIDIOUT)"));
2331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERLINE_TARGETTYPE_MIDIIN:
2333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(MIDIIN)"));
2334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(INVALID)"));
2337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceControlType
2345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceControlType(DWORD dwControlType) const
2348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[128];
2350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Class type classification
2352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, 128, TEXT("class type             : 0x%x "), dwControlType);
2354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (dwControlType & MIXERCONTROL_CT_CLASS_MASK)
2356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_CUSTOM:
2358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_CUSTOM)"));
2359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_METER:
2361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_METER)"));
2362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_SWITCH:
2364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_SWITCH)"));
2365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_NUMBER:
2367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_NUMBER)"));
2368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_SLIDER:
2370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_SLIDER)"));
2371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_FADER:
2373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_FADER)"));
2374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_TIME:
2376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_TIME)"));
2377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CT_CLASS_LIST:
2379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CT_CLASS_LIST)"));
2380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(INVALID)"));
2383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Control type (for each class)
2389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    //
2390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, 128, TEXT("control type           : 0x%x "), dwControlType);
2391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    switch (dwControlType)
2393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_CUSTOM:
2395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_CUSTOM)"));
2396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_BOOLEANMETER:
2398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BOOLEANMETER)"));
2399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_SIGNEDMETER:
2401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SIGNEDMETER)"));
2402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_PEAKMETER:
2404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_PEAKMETER)"));
2405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER:
2407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_UNSIGNEDMETER)"));
2408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_BOOLEAN:
2410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BOOLEAN)"));
2411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_ONOFF:
2413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_ONOFF)"));
2414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MUTE:
2416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MUTE)"));
2417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MONO:
2419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MONO)"));
2420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_LOUDNESS:
2422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_LOUDNESS)"));
2423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_STEREOENH:
2425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_STEREOENH)"));
2426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_BASS_BOOST:
2428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BASS_BOOST)"));
2429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_BUTTON:
2431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BUTTON)"));
2432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_DECIBELS:
2434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_DECIBELS)"));
2435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_SIGNED:
2437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SIGNED)"));
2438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_UNSIGNED:
2440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_UNSIGNED)"));
2441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_PERCENT:
2443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_PERCENT)"));
2444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_SLIDER:
2446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SLIDER)"));
2447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_PAN:
2449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_PAN)"));
2450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_QSOUNDPAN:
2452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_QSOUNDPAN)"));
2453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_FADER:
2455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_FADER)"));
2456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_VOLUME:
2458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_VOLUME)"));
2459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_BASS:
2461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_BASS)"));
2462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_TREBLE:
2464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_TREBLE)"));
2465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_EQUALIZER:
2467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_EQUALIZER)"));
2468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
2470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_SINGLESELECT)"));
2471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MUX:
2473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MUX)"));
2474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
2476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MULTIPLESELECT)"));
2477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MIXER:
2479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MIXER)"));
2480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MICROTIME:
2482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MICROTIME)"));
2483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case MIXERCONTROL_CONTROLTYPE_MILLITIME:
2485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLTYPE_MILLITIME)"));
2486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(INVALID)"));
2489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        break;
2490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceControlStatusAndSupportFlags
2497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  fdwControl
2499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Status and support flags for the audio line control. The following values
2501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  are defined:
2502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MIXERCONTROL_CONTROLF_DISABLED
2504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  The control is disabled, perhaps due to other settings for the mixer hardware,
2506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  and cannot be used. An application can read current settings from a
2507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  disabled control, but it cannot apply settings.
2508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MIXERCONTROL_CONTROLF_MULTIPLE
2510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  The control has two or more settings per channel. An equalizer, for example,
2512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  requires this flag because each frequency band can be set to a different value.
2513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  An equalizer that affects both channels of a stereo line in a uniform fashion
2514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  will also specify the MIXERCONTROL_CONTROLF_UNIFORM flag.
2515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MIXERCONTROL_CONTROLF_UNIFORM
2517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  The control acts on all channels of a multichannel line in a uniform fashion.
2519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  For example, a control that mutes both channels of a stereo line would set
2520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  this flag. Most MIXERCONTROL_CONTROLTYPE_MUX and
2521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MIXERCONTROL_CONTROLTYPE_MIXER controls also specify the
2522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MIXERCONTROL_CONTROLF_UNIFORM flag.
2523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceControlStatusAndSupportFlags(DWORD fdwControl) const
2526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[128];
2528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, 128, TEXT("control support flags  : 0x%x "), fdwControl);
2530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (fdwControl & MIXERCONTROL_CONTROLF_DISABLED)
2532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // The control is disabled, perhaps due to other settings for the mixer hardware,
2534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // and cannot be used. An application can read current settings from a disabled
2535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // control, but it cannot apply settings.
2536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLF_DISABLED)"));
2537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE)
2540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // The control has two or more settings per channel. An equalizer, for example,
2542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // requires this flag because each frequency band can be set to a different
2543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // value. An equalizer that affects both channels of a stereo line in a
2544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // uniform fashion will also specify the MIXERCONTROL_CONTROLF_UNIFORM flag.
2545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLF_MULTIPLE)"));
2546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
2549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // The control acts on all channels of a multichannel line in a uniform
2551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // fashion. For example, a control that mutes both channels of a stereo
2552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // line would set this flag. Most MIXERCONTROL_CONTROLTYPE_MUX and
2553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // MIXERCONTROL_CONTROLTYPE_MIXER controls also specify the
2554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // MIXERCONTROL_CONTROLF_UNIFORM flag.
2555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        StringCchCat(buf, 128, TEXT("(CONTROLF_UNIFORM)"));
2556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  ClearSpeakerState I (II)
2563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::ClearSpeakerState(UINT idx)
2566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _speakerState[idx].dwLineID = 0L;
2568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _speakerState[idx].dwVolumeControlID = 0L;
2569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _speakerState[idx].dwMuteControlID = 0L;
2570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _speakerState[idx].speakerIsValid = false;
2571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _speakerState[idx].muteControlIsValid = false;
2572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _speakerState[idx].volumeControlIsValid = false;
2573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  ClearSpeakerState II (II)
2577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::ClearSpeakerState()
2580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
2582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ClearSpeakerState(i);
2584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  SpeakerIsValid
2589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::SpeakerIsValid(UINT idx) const
2592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (_speakerState[idx].speakerIsValid);
2594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  ValidSpeakers
2598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Counts number of valid speaker destinations for all mixer devices.
2600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgUINT AudioMixerManager::ValidSpeakers() const
2603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT nSpeakers(0);
2605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
2606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (SpeakerIsValid(i))
2608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            nSpeakers++;
2609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return nSpeakers;
2611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  ClearMicrophoneState I (II)
2615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::ClearMicrophoneState(UINT idx)
2618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].dwLineID = 0L;
2620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].dwVolumeControlID = 0L;
2621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].dwMuteControlID = 0L;
2622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].dwOnOffControlID = 0L;
2623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].microphoneIsValid = false;
2624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].muteControlIsValid = false;
2625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].volumeControlIsValid = false;
2626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    _microphoneState[idx].onOffControlIsValid = false;
2627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  ClearMicrophoneState II (II)
2631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::ClearMicrophoneState()
2634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
2636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ClearMicrophoneState(i);
2638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  MicrophoneIsValid
2643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool AudioMixerManager::MicrophoneIsValid(UINT idx) const
2646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (_microphoneState[idx].microphoneIsValid);
2648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  ValidMicrophones
2653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//
2654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  Counts number of valid speaker destinations for all mixer devices.
2655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  To be valid, a speaker destination line must exist.
2656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgUINT AudioMixerManager::ValidMicrophones() const
2659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    UINT nMicrophones(0);
2661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < MAX_NUMBER_MIXER_DEVICES; i++)
2662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (MicrophoneIsValid(i))
2664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            nMicrophones++;
2665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return nMicrophones;
2667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceWaveInError
2671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceWaveInError(MMRESULT error) const
2674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[MAXERRORLENGTH];
2676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR msg[MAXERRORLENGTH];
2677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: "));
2679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveInGetErrorText(error, msg, MAXERRORLENGTH);
2680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchCat(buf, MAXERRORLENGTH, msg);
2681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  TraceWaveOutError
2686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid AudioMixerManager::TraceWaveOutError(MMRESULT error) const
2689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
2690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR buf[MAXERRORLENGTH];
2691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    TCHAR msg[MAXERRORLENGTH];
2692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: "));
2694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    waveOutGetErrorText(error, msg, MAXERRORLENGTH);
2695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StringCchCat(buf, MAXERRORLENGTH, msg);
2696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%s", WideToUTF8(buf));
2697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//  WideToUTF8
2701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// ----------------------------------------------------------------------------
2702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgchar* AudioMixerManager::WideToUTF8(const TCHAR* src) const {
2704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef UNICODE
2705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const size_t kStrLen = sizeof(_str);
2706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memset(_str, 0, kStrLen);
2707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Get required size (in bytes) to be able to complete the conversion.
2708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int required_size = WideCharToMultiByte(CP_UTF8, 0, src, -1, _str, 0, 0, 0);
2709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (required_size <= kStrLen)
2710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
2711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // Process the entire input string, including the terminating null char.
2712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (WideCharToMultiByte(CP_UTF8, 0, src, -1, _str, kStrLen, 0, 0) == 0)
2713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            memset(_str, 0, kStrLen);
2714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return _str;
2716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#else
2717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return const_cast<char*>(src);
2718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
2719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
2722