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