Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: media/audio/win/core_audio_util_win.cc

Issue 11226057: Adds Core Audio Utility methods for Windows (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed unit test based on feedback from Tommi Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/audio/win/core_audio_util_win.h"
6
7 #include <Audioclient.h>
8 #include <Functiondiscoverykeys_devpkey.h>
9
10 #include "base/logging.h"
11 #include "base/stringprintf.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/win/scoped_co_mem.h"
14 #include "base/win/windows_version.h"
15
16 using base::win::ScopedCoMem;
17
18 namespace media {
19
20 #define PRINT(sz, ...) wprintf(sz L"\n", __VA_ARGS__);
scherkus (not reviewing) 2012/10/25 16:52:13 not removed :)
henrika (OOO until Aug 14) 2012/10/26 17:51:56 Done.
21
22 class ScopedPropertyVariant {
23 public:
24 ScopedPropertyVariant() {
25 PropVariantInit(&prop_);
26 }
27 ~ScopedPropertyVariant() {
28 PropVariantClear(&prop_);
29 }
30
31 PROPVARIANT* Get() {
32 return &prop_;
33 }
34
35 private:
36 PROPVARIANT prop_;
37
38 DISALLOW_COPY_AND_ASSIGN(ScopedPropertyVariant);
39 };
40
41 bool CoreAudioUtil::CoreAudioIsSupported() {
scherkus (not reviewing) 2012/10/25 16:52:13 TODO-ify de-duping?
henrika (OOO until Aug 14) 2012/10/26 17:51:56 Done.
42 // Microsoft does not plan to make the Core Audio APIs available for use
43 // with earlier versions of Windows, including Microsoft Windows Server 2003,
44 // Windows XP, Windows Millennium Edition, Windows 2000, and Windows 98.
45 return (base::win::GetVersion() >= base::win::VERSION_VISTA);
46 }
47
48 int CoreAudioUtil::NumberOfActiveDevices(EDataFlow data_flow) {
49 DCHECK(CoreAudioIsSupported());
50 // Create the IMMDeviceEnumerator interface.
51 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
52 CreateDeviceEnumerator();
53 if (!device_enumerator)
54 return 0;
55
56 // Generate a collection of active (present and not disabled) audio endpoint
57 // devices for the specified data-flow direction.
58 // This method will succeed even if all devices are disabled.
59 ScopedComPtr<IMMDeviceCollection> collection;
60 HRESULT hr = device_enumerator->EnumAudioEndpoints(data_flow,
61 DEVICE_STATE_ACTIVE,
62 collection.Receive());
63 if (FAILED(hr)) {
64 LOG(ERROR) << "IMMDeviceCollection::EnumAudioEndpoints: " << std::hex << hr;
65 return 0;
66 }
67
68 // Retrieve the number of active audio devices for the specified direction
69 UINT number_of_active_devices = 0;
70 collection->GetCount(&number_of_active_devices);
71 std::string flow = (data_flow == eCapture) ? "[in ] " : "[out] ";
72 DVLOG(1) << flow << "number of devices: " << number_of_active_devices;
73 return static_cast<int>(number_of_active_devices);
74 }
75
76 ScopedComPtr<IMMDeviceEnumerator> CoreAudioUtil::CreateDeviceEnumerator() {
77 DCHECK(CoreAudioIsSupported());
78 ScopedComPtr<IMMDeviceEnumerator> device_enumerator;
79 HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
80 NULL,
81 CLSCTX_INPROC_SERVER,
82 __uuidof(IMMDeviceEnumerator),
83 device_enumerator.ReceiveVoid());
84 LOG_IF(ERROR, FAILED(hr)) << "CoCreateInstance(IMMDeviceEnumerator): "
85 << std::hex << hr;
86 return device_enumerator;
87 }
88
89 ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDefaultDevice(EDataFlow data_flow,
90 ERole role) {
91 DCHECK(CoreAudioIsSupported());
92 ScopedComPtr<IMMDevice> endpoint_device;
93
94 // Create the IMMDeviceEnumerator interface.
95 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
96 CreateDeviceEnumerator();
97 if (!device_enumerator)
98 return endpoint_device;
99
100 // Retrieve the default audio endpoint for the specified data-flow
101 // direction and role.
102 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint(
103 data_flow, role, endpoint_device.Receive());
104
105 if (FAILED(hr)) {
106 LOG(ERROR) << "IMMDeviceEnumerator::GetDefaultAudioEndpoint: "
107 << std::hex << hr;
108 return endpoint_device;
109 }
110
111 // Verify that the audio endpoint device is active, i.e., that the audio
112 // adapter that connects to the endpoint device is present and enabled.
113 DWORD state = DEVICE_STATE_DISABLED;
114 hr = endpoint_device->GetState(&state);
115 if (SUCCEEDED(hr)) {
116 if (!(state & DEVICE_STATE_ACTIVE)) {
117 LOG(ERROR) << "Selected endpoint device is not active";
118 endpoint_device.Release();
119 }
120 }
121 return endpoint_device;
122 }
123
124 ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDevice(
125 const std::string& device_id) {
126 DCHECK(CoreAudioIsSupported());
127 ScopedComPtr<IMMDevice> endpoint_device;
128
129 // Create the IMMDeviceEnumerator interface.
130 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
131 CreateDeviceEnumerator();
132 if (!device_enumerator)
133 return endpoint_device;
134
135 // Retrieve an audio device specified by an endpoint device-identification
136 // string.
137 HRESULT hr = device_enumerator->GetDevice(UTF8ToUTF16(device_id).c_str(),
138 endpoint_device.Receive());
139 LOG_IF(ERROR, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: "
140 << std::hex << hr;
141 return endpoint_device;
142 }
143
144 HRESULT CoreAudioUtil::GetDeviceName(IMMDevice* device, AudioDeviceName* name) {
145 DCHECK(CoreAudioIsSupported());
146 DCHECK(device);
147 AudioDeviceName device_name;
148
149 // Retrieve unique name of endpoint device.
150 // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}".
151 ScopedCoMem<WCHAR> endpoint_device_id;
152 HRESULT hr = device->GetId(&endpoint_device_id);
153 if (FAILED(hr))
154 return hr;
155 device_name.unique_id = WideToUTF8(static_cast<WCHAR*>(endpoint_device_id));
156
157 // Retrieve user-friendly name of endpoint device.
158 // Example: "Microphone (Realtek High Definition Audio)".
159 ScopedComPtr<IPropertyStore> properties;
160 hr = device->OpenPropertyStore(STGM_READ, properties.Receive());
161 if (FAILED(hr))
162 return hr;
163 PROPVARIANT friendly_name;
164 PropVariantInit(&friendly_name);
165 hr = properties->GetValue(PKEY_Device_FriendlyName, &friendly_name);
166 if (FAILED(hr))
167 return hr;
168 if (friendly_name.vt == VT_LPWSTR && friendly_name.pwszVal) {
169 device_name.device_name = WideToUTF8(friendly_name.pwszVal);
170 }
171 PropVariantClear(&friendly_name);
172
173 *name = device_name;
174 DVLOG(1) << "friendly name: " << device_name.device_name;
175 DVLOG(1) << "unique id : " << device_name.unique_id;
176 return hr;
177 }
178
179 std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) {
180 DCHECK(CoreAudioIsSupported());
181 std::string name;
182
183 ScopedComPtr<IMMDevice> audio_device = CreateDevice(device_id);
184 if (!audio_device)
185 return name;
186
187 AudioDeviceName device_name;
188 HRESULT hr = GetDeviceName(audio_device, &device_name);
189 if (FAILED(hr))
190 return name;
191
192 name = device_name.device_name;
193 return name;
194 }
195
196 bool CoreAudioUtil::DeviceIsDefault(EDataFlow flow,
197 ERole role,
198 std::string device_id) {
199 DCHECK(CoreAudioIsSupported());
200 ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role);
201 if (!device)
202 return false;
203
204 ScopedCoMem<WCHAR> default_device_id;
205 HRESULT hr = device->GetId(&default_device_id);
206 if (FAILED(hr))
207 return false;
208
209 std::string str_default = WideToUTF8(static_cast<WCHAR*>(default_device_id));
210 if (device_id.compare(str_default) != 0) {
211 return false;
212 }
213 return true;
214 }
215
216 EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) {
217 DCHECK(CoreAudioIsSupported());
218 if (!device)
219 return eAll;
220
221 ScopedComPtr<IMMEndpoint> endpoint;
222 device->QueryInterface(endpoint.Receive());
223
224 EDataFlow data_flow;
225 HRESULT hr = endpoint->GetDataFlow(&data_flow);
226 if (FAILED(hr)) {
227 LOG(ERROR) << "IMMEndpoint::GetDataFlow: " << std::hex << hr;
228 return eAll;
229 }
230 return data_flow;
231 }
232
233 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient(
234 IMMDevice* audio_device) {
235 DCHECK(CoreAudioIsSupported());
236 ScopedComPtr<IAudioClient> audio_client;
237
238 // Creates and activates an IAudioClient COM object given the selected
239 // endpoint device.
240 HRESULT hr = audio_device->Activate(__uuidof(IAudioClient),
241 CLSCTX_INPROC_SERVER,
242 NULL,
243 audio_client.ReceiveVoid());
244 LOG_IF(ERROR, FAILED(hr)) << "IMMDevice::Activate: " << std::hex << hr;
245 return audio_client;
246 }
247
248 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698