OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/audio/win/core_audio_util_win.h" | 5 #include "media/audio/win/core_audio_util_win.h" |
6 | 6 |
7 #include <devicetopology.h> | 7 #include <devicetopology.h> |
8 #include <dxdiag.h> | 8 #include <dxdiag.h> |
9 #include <functiondiscoverykeys_devpkey.h> | 9 #include <functiondiscoverykeys_devpkey.h> |
10 #include <objbase.h> | 10 #include <objbase.h> |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 static bool IsDeviceActive(IMMDevice* device) { | 148 static bool IsDeviceActive(IMMDevice* device) { |
149 DWORD state = DEVICE_STATE_DISABLED; | 149 DWORD state = DEVICE_STATE_DISABLED; |
150 return SUCCEEDED(device->GetState(&state)) && (state & DEVICE_STATE_ACTIVE); | 150 return SUCCEEDED(device->GetState(&state)) && (state & DEVICE_STATE_ACTIVE); |
151 } | 151 } |
152 | 152 |
153 static HRESULT GetDeviceFriendlyNameInternal(IMMDevice* device, | 153 static HRESULT GetDeviceFriendlyNameInternal(IMMDevice* device, |
154 std::string* friendly_name) { | 154 std::string* friendly_name) { |
155 // Retrieve user-friendly name of endpoint device. | 155 // Retrieve user-friendly name of endpoint device. |
156 // Example: "Microphone (Realtek High Definition Audio)". | 156 // Example: "Microphone (Realtek High Definition Audio)". |
157 ScopedComPtr<IPropertyStore> properties; | 157 ScopedComPtr<IPropertyStore> properties; |
158 HRESULT hr = device->OpenPropertyStore(STGM_READ, properties.Receive()); | 158 HRESULT hr = device->OpenPropertyStore(STGM_READ, properties.GetAddressOf()); |
159 if (FAILED(hr)) | 159 if (FAILED(hr)) |
160 return hr; | 160 return hr; |
161 | 161 |
162 base::win::ScopedPropVariant friendly_name_pv; | 162 base::win::ScopedPropVariant friendly_name_pv; |
163 hr = properties->GetValue(PKEY_Device_FriendlyName, | 163 hr = properties->GetValue(PKEY_Device_FriendlyName, |
164 friendly_name_pv.Receive()); | 164 friendly_name_pv.Receive()); |
165 if (FAILED(hr)) | 165 if (FAILED(hr)) |
166 return hr; | 166 return hr; |
167 | 167 |
168 if (friendly_name_pv.get().vt == VT_LPWSTR && | 168 if (friendly_name_pv.get().vt == VT_LPWSTR && |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 // Create the IMMDeviceEnumerator interface. | 254 // Create the IMMDeviceEnumerator interface. |
255 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = | 255 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = |
256 CreateDeviceEnumerator(); | 256 CreateDeviceEnumerator(); |
257 if (!device_enumerator.Get()) | 257 if (!device_enumerator.Get()) |
258 return 0; | 258 return 0; |
259 | 259 |
260 // Generate a collection of active (present and not disabled) audio endpoint | 260 // Generate a collection of active (present and not disabled) audio endpoint |
261 // devices for the specified data-flow direction. | 261 // devices for the specified data-flow direction. |
262 // This method will succeed even if all devices are disabled. | 262 // This method will succeed even if all devices are disabled. |
263 ScopedComPtr<IMMDeviceCollection> collection; | 263 ScopedComPtr<IMMDeviceCollection> collection; |
264 HRESULT hr = device_enumerator->EnumAudioEndpoints(data_flow, | 264 HRESULT hr = device_enumerator->EnumAudioEndpoints( |
265 DEVICE_STATE_ACTIVE, | 265 data_flow, DEVICE_STATE_ACTIVE, collection.GetAddressOf()); |
266 collection.Receive()); | |
267 if (FAILED(hr)) { | 266 if (FAILED(hr)) { |
268 LOG(ERROR) << "IMMDeviceCollection::EnumAudioEndpoints: " << std::hex << hr; | 267 LOG(ERROR) << "IMMDeviceCollection::EnumAudioEndpoints: " << std::hex << hr; |
269 return 0; | 268 return 0; |
270 } | 269 } |
271 | 270 |
272 // Retrieve the number of active audio devices for the specified direction | 271 // Retrieve the number of active audio devices for the specified direction |
273 UINT number_of_active_devices = 0; | 272 UINT number_of_active_devices = 0; |
274 collection->GetCount(&number_of_active_devices); | 273 collection->GetCount(&number_of_active_devices); |
275 DVLOG(2) << ((data_flow == eCapture) ? "[in ] " : "[out] ") | 274 DVLOG(2) << ((data_flow == eCapture) ? "[in ] " : "[out] ") |
276 << "number of devices: " << number_of_active_devices; | 275 << "number of devices: " << number_of_active_devices; |
(...skipping 10 matching lines...) Expand all Loading... |
287 | 286 |
288 // Create the IMMDeviceEnumerator interface. | 287 // Create the IMMDeviceEnumerator interface. |
289 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = | 288 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = |
290 CreateDeviceEnumerator(); | 289 CreateDeviceEnumerator(); |
291 if (!device_enumerator.Get()) | 290 if (!device_enumerator.Get()) |
292 return endpoint_device; | 291 return endpoint_device; |
293 | 292 |
294 // Retrieve the default audio endpoint for the specified data-flow | 293 // Retrieve the default audio endpoint for the specified data-flow |
295 // direction and role. | 294 // direction and role. |
296 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint( | 295 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint( |
297 data_flow, role, endpoint_device.Receive()); | 296 data_flow, role, endpoint_device.GetAddressOf()); |
298 | 297 |
299 if (FAILED(hr)) { | 298 if (FAILED(hr)) { |
300 DVLOG(1) << "IMMDeviceEnumerator::GetDefaultAudioEndpoint: " | 299 DVLOG(1) << "IMMDeviceEnumerator::GetDefaultAudioEndpoint: " |
301 << std::hex << hr; | 300 << std::hex << hr; |
302 return endpoint_device; | 301 return endpoint_device; |
303 } | 302 } |
304 | 303 |
305 // Verify that the audio endpoint device is active, i.e., that the audio | 304 // Verify that the audio endpoint device is active, i.e., that the audio |
306 // adapter that connects to the endpoint device is present and enabled. | 305 // adapter that connects to the endpoint device is present and enabled. |
307 if (!IsDeviceActive(endpoint_device.Get())) { | 306 if (!IsDeviceActive(endpoint_device.Get())) { |
(...skipping 14 matching lines...) Expand all Loading... |
322 | 321 |
323 // Create the IMMDeviceEnumerator interface. | 322 // Create the IMMDeviceEnumerator interface. |
324 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = | 323 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = |
325 CreateDeviceEnumerator(); | 324 CreateDeviceEnumerator(); |
326 if (!device_enumerator.Get()) | 325 if (!device_enumerator.Get()) |
327 return endpoint_device; | 326 return endpoint_device; |
328 | 327 |
329 // Retrieve an audio device specified by an endpoint device-identification | 328 // Retrieve an audio device specified by an endpoint device-identification |
330 // string. | 329 // string. |
331 HRESULT hr = device_enumerator->GetDevice( | 330 HRESULT hr = device_enumerator->GetDevice( |
332 base::UTF8ToUTF16(device_id).c_str(), endpoint_device.Receive()); | 331 base::UTF8ToUTF16(device_id).c_str(), endpoint_device.GetAddressOf()); |
333 DVLOG_IF(1, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: " | 332 DVLOG_IF(1, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: " |
334 << std::hex << hr; | 333 << std::hex << hr; |
335 | 334 |
336 if (FAILED(hr)) { | 335 if (FAILED(hr)) { |
337 DVLOG(1) << "IMMDeviceEnumerator::GetDevice: " << std::hex << hr; | 336 DVLOG(1) << "IMMDeviceEnumerator::GetDevice: " << std::hex << hr; |
338 return endpoint_device; | 337 return endpoint_device; |
339 } | 338 } |
340 | 339 |
341 // Verify that the audio endpoint device is active, i.e., that the audio | 340 // Verify that the audio endpoint device is active, i.e., that the audio |
342 // adapter that connects to the endpoint device is present and enabled. | 341 // adapter that connects to the endpoint device is present and enabled. |
(...skipping 27 matching lines...) Expand all Loading... |
370 // Fetching the controller device id could be as simple as fetching the value | 369 // Fetching the controller device id could be as simple as fetching the value |
371 // of the "{B3F8FA53-0004-438E-9003-51A46E139BFC},2" property in the property | 370 // of the "{B3F8FA53-0004-438E-9003-51A46E139BFC},2" property in the property |
372 // store of the |device|, but that key isn't defined in any header and | 371 // store of the |device|, but that key isn't defined in any header and |
373 // according to MS should not be relied upon. | 372 // according to MS should not be relied upon. |
374 // So, instead, we go deeper, look at the device topology and fetch the | 373 // So, instead, we go deeper, look at the device topology and fetch the |
375 // PKEY_Device_InstanceId of the associated physical audio device. | 374 // PKEY_Device_InstanceId of the associated physical audio device. |
376 ScopedComPtr<IDeviceTopology> topology; | 375 ScopedComPtr<IDeviceTopology> topology; |
377 ScopedComPtr<IConnector> connector; | 376 ScopedComPtr<IConnector> connector; |
378 ScopedCoMem<WCHAR> filter_id; | 377 ScopedCoMem<WCHAR> filter_id; |
379 if (FAILED(device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, | 378 if (FAILED(device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, |
380 &topology)) || | 379 &topology)) || |
381 // For our purposes checking the first connected device should be enough | 380 // For our purposes checking the first connected device should be enough |
382 // and if there are cases where there are more than one device connected | 381 // and if there are cases where there are more than one device connected |
383 // we're not sure how to handle that anyway. So we pass 0. | 382 // we're not sure how to handle that anyway. So we pass 0. |
384 FAILED(topology->GetConnector(0, connector.Receive())) || | 383 FAILED(topology->GetConnector(0, connector.GetAddressOf())) || |
385 FAILED(connector->GetDeviceIdConnectedTo(&filter_id))) { | 384 FAILED(connector->GetDeviceIdConnectedTo(&filter_id))) { |
386 DLOG(ERROR) << "Failed to get the device identifier of the audio device"; | 385 DLOG(ERROR) << "Failed to get the device identifier of the audio device"; |
387 return std::string(); | 386 return std::string(); |
388 } | 387 } |
389 | 388 |
390 // Now look at the properties of the connected device node and fetch the | 389 // Now look at the properties of the connected device node and fetch the |
391 // instance id (PKEY_Device_InstanceId) of the device node that uniquely | 390 // instance id (PKEY_Device_InstanceId) of the device node that uniquely |
392 // identifies the controller. | 391 // identifies the controller. |
393 ScopedComPtr<IMMDevice> device_node; | 392 ScopedComPtr<IMMDevice> device_node; |
394 ScopedComPtr<IPropertyStore> properties; | 393 ScopedComPtr<IPropertyStore> properties; |
395 base::win::ScopedPropVariant instance_id; | 394 base::win::ScopedPropVariant instance_id; |
396 if (FAILED(enumerator->GetDevice(filter_id, device_node.Receive())) || | 395 if (FAILED(enumerator->GetDevice(filter_id, device_node.GetAddressOf())) || |
397 FAILED(device_node->OpenPropertyStore(STGM_READ, properties.Receive())) || | 396 FAILED(device_node->OpenPropertyStore(STGM_READ, |
| 397 properties.GetAddressOf())) || |
398 FAILED(properties->GetValue(PKEY_Device_InstanceId, | 398 FAILED(properties->GetValue(PKEY_Device_InstanceId, |
399 instance_id.Receive())) || | 399 instance_id.Receive())) || |
400 instance_id.get().vt != VT_LPWSTR) { | 400 instance_id.get().vt != VT_LPWSTR) { |
401 DLOG(ERROR) << "Failed to get instance id of the audio device node"; | 401 DLOG(ERROR) << "Failed to get instance id of the audio device node"; |
402 return std::string(); | 402 return std::string(); |
403 } | 403 } |
404 | 404 |
405 std::string controller_id; | 405 std::string controller_id; |
406 base::WideToUTF8(instance_id.get().pwszVal, | 406 base::WideToUTF8(instance_id.get().pwszVal, |
407 wcslen(instance_id.get().pwszVal), | 407 wcslen(instance_id.get().pwszVal), |
(...skipping 30 matching lines...) Expand all Loading... |
438 ScopedComPtr<IMMDeviceEnumerator> enumerator(CreateDeviceEnumerator()); | 438 ScopedComPtr<IMMDeviceEnumerator> enumerator(CreateDeviceEnumerator()); |
439 std::string controller_id( | 439 std::string controller_id( |
440 GetAudioControllerID(input_device.Get(), enumerator.Get())); | 440 GetAudioControllerID(input_device.Get(), enumerator.Get())); |
441 if (controller_id.empty()) | 441 if (controller_id.empty()) |
442 return std::string(); | 442 return std::string(); |
443 | 443 |
444 // Now enumerate the available (and active) output devices and see if any of | 444 // Now enumerate the available (and active) output devices and see if any of |
445 // them is associated with the same controller. | 445 // them is associated with the same controller. |
446 ScopedComPtr<IMMDeviceCollection> collection; | 446 ScopedComPtr<IMMDeviceCollection> collection; |
447 enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, | 447 enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, |
448 collection.Receive()); | 448 collection.GetAddressOf()); |
449 if (!collection.Get()) | 449 if (!collection.Get()) |
450 return std::string(); | 450 return std::string(); |
451 | 451 |
452 UINT count = 0; | 452 UINT count = 0; |
453 collection->GetCount(&count); | 453 collection->GetCount(&count); |
454 ScopedComPtr<IMMDevice> output_device; | 454 ScopedComPtr<IMMDevice> output_device; |
455 for (UINT i = 0; i < count; ++i) { | 455 for (UINT i = 0; i < count; ++i) { |
456 collection->Item(i, output_device.Receive()); | 456 collection->Item(i, output_device.GetAddressOf()); |
457 std::string output_controller_id( | 457 std::string output_controller_id( |
458 GetAudioControllerID(output_device.Get(), enumerator.Get())); | 458 GetAudioControllerID(output_device.Get(), enumerator.Get())); |
459 if (output_controller_id == controller_id) | 459 if (output_controller_id == controller_id) |
460 break; | 460 break; |
461 output_device = NULL; | 461 output_device = NULL; |
462 } | 462 } |
463 | 463 |
464 return output_device.Get() ? GetDeviceID(output_device.Get()) : std::string(); | 464 return output_device.Get() ? GetDeviceID(output_device.Get()) : std::string(); |
465 } | 465 } |
466 | 466 |
(...skipping 16 matching lines...) Expand all Loading... |
483 ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role); | 483 ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role); |
484 if (!device.Get()) | 484 if (!device.Get()) |
485 return false; | 485 return false; |
486 | 486 |
487 std::string str_default(GetDeviceID(device.Get())); | 487 std::string str_default(GetDeviceID(device.Get())); |
488 return device_id.compare(str_default) == 0; | 488 return device_id.compare(str_default) == 0; |
489 } | 489 } |
490 | 490 |
491 EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) { | 491 EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) { |
492 ScopedComPtr<IMMEndpoint> endpoint; | 492 ScopedComPtr<IMMEndpoint> endpoint; |
493 HRESULT hr = device->QueryInterface(endpoint.Receive()); | 493 HRESULT hr = device->QueryInterface(endpoint.GetAddressOf()); |
494 if (FAILED(hr)) { | 494 if (FAILED(hr)) { |
495 DVLOG(1) << "IMMDevice::QueryInterface: " << std::hex << hr; | 495 DVLOG(1) << "IMMDevice::QueryInterface: " << std::hex << hr; |
496 return eAll; | 496 return eAll; |
497 } | 497 } |
498 | 498 |
499 EDataFlow data_flow; | 499 EDataFlow data_flow; |
500 hr = endpoint->GetDataFlow(&data_flow); | 500 hr = endpoint->GetDataFlow(&data_flow); |
501 if (FAILED(hr)) { | 501 if (FAILED(hr)) { |
502 DVLOG(1) << "IMMEndpoint::GetDataFlow: " << std::hex << hr; | 502 DVLOG(1) << "IMMEndpoint::GetDataFlow: " << std::hex << hr; |
503 return eAll; | 503 return eAll; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 | 883 |
884 DXDIAG_INIT_PARAMS params = {sizeof(params)}; | 884 DXDIAG_INIT_PARAMS params = {sizeof(params)}; |
885 params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; | 885 params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; |
886 params.bAllowWHQLChecks = FALSE; | 886 params.bAllowWHQLChecks = FALSE; |
887 params.pReserved = NULL; | 887 params.pReserved = NULL; |
888 hr = provider->Initialize(¶ms); | 888 hr = provider->Initialize(¶ms); |
889 if (FAILED(hr)) | 889 if (FAILED(hr)) |
890 return false; | 890 return false; |
891 | 891 |
892 ScopedComPtr<IDxDiagContainer, &IID_IDxDiagContainer> root; | 892 ScopedComPtr<IDxDiagContainer, &IID_IDxDiagContainer> root; |
893 hr = provider->GetRootContainer(root.Receive()); | 893 hr = provider->GetRootContainer(root.GetAddressOf()); |
894 if (FAILED(hr)) | 894 if (FAILED(hr)) |
895 return false; | 895 return false; |
896 | 896 |
897 // Limit to the SoundDevices subtree. The tree in its entirity is | 897 // Limit to the SoundDevices subtree. The tree in its entirity is |
898 // enormous and only this branch contains useful information. | 898 // enormous and only this branch contains useful information. |
899 ScopedComPtr<IDxDiagContainer, &IID_IDxDiagContainer> sound_devices; | 899 ScopedComPtr<IDxDiagContainer, &IID_IDxDiagContainer> sound_devices; |
900 hr = root->GetChildContainer(L"DxDiag_DirectSound.DxDiag_SoundDevices.0", | 900 hr = root->GetChildContainer(L"DxDiag_DirectSound.DxDiag_SoundDevices.0", |
901 sound_devices.Receive()); | 901 sound_devices.GetAddressOf()); |
902 if (FAILED(hr)) | 902 if (FAILED(hr)) |
903 return false; | 903 return false; |
904 | 904 |
905 base::win::ScopedVariant variant; | 905 base::win::ScopedVariant variant; |
906 hr = sound_devices->GetProp(L"szDriverName", variant.Receive()); | 906 hr = sound_devices->GetProp(L"szDriverName", variant.Receive()); |
907 if (FAILED(hr)) | 907 if (FAILED(hr)) |
908 return false; | 908 return false; |
909 | 909 |
910 if (variant.type() == VT_BSTR && variant.ptr()->bstrVal) { | 910 if (variant.type() == VT_BSTR && variant.ptr()->bstrVal) { |
911 base::WideToUTF8(variant.ptr()->bstrVal, wcslen(variant.ptr()->bstrVal), | 911 base::WideToUTF8(variant.ptr()->bstrVal, wcslen(variant.ptr()->bstrVal), |
912 driver_name); | 912 driver_name); |
913 } | 913 } |
914 | 914 |
915 variant.Reset(); | 915 variant.Reset(); |
916 hr = sound_devices->GetProp(L"szDriverVersion", variant.Receive()); | 916 hr = sound_devices->GetProp(L"szDriverVersion", variant.Receive()); |
917 if (FAILED(hr)) | 917 if (FAILED(hr)) |
918 return false; | 918 return false; |
919 | 919 |
920 if (variant.type() == VT_BSTR && variant.ptr()->bstrVal) { | 920 if (variant.type() == VT_BSTR && variant.ptr()->bstrVal) { |
921 base::WideToUTF8(variant.ptr()->bstrVal, wcslen(variant.ptr()->bstrVal), | 921 base::WideToUTF8(variant.ptr()->bstrVal, wcslen(variant.ptr()->bstrVal), |
922 driver_version); | 922 driver_version); |
923 } | 923 } |
924 | 924 |
925 return true; | 925 return true; |
926 } | 926 } |
927 | 927 |
928 } // namespace media | 928 } // namespace media |
OLD | NEW |