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

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: Added more tests and initiated WASAPI support 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 namespace win {
20
21 #define PRINT(sz, ...) wprintf(sz L"\n", __VA_ARGS__);
22
23 class ScopedPropertyVariant {
24 public:
25 ScopedPropertyVariant() {
26 PropVariantInit(&prop_);
27 }
28 ~ScopedPropertyVariant() {
29 PropVariantClear(&prop_);
30 }
31
32 PROPVARIANT* Get() {
33 return &prop_;
34 }
35
36 private:
37 PROPVARIANT prop_;
38
39 DISALLOW_COPY_AND_ASSIGN(ScopedPropertyVariant);
40 };
41
42 bool CoreAudioIsSupported() {
43 // Note that Windows Server 2003 does not support Windows Core Audio.
44 return (base::win::GetVersion() >= base::win::VERSION_VISTA);
45 }
46
47 int NumberOfActiveAudioDevices(EDataFlow data_flow) {
48 // Create the IMMDeviceEnumerator interface.
49 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
50 CreateDeviceEnumerator();
51 if (!device_enumerator)
52 return 0;
53
54 // Generate a collection of active (present and not disabled) audio endpoint
55 // devices for the specified data-flow direction.
56 // This method will succeed even if all devices are disabled.
57 ScopedComPtr<IMMDeviceCollection> collection;
58 HRESULT hr = device_enumerator->EnumAudioEndpoints(data_flow,
59 DEVICE_STATE_ACTIVE,
60 collection.Receive());
61 if (FAILED(hr)) {
62 LOG(ERROR) << "IMMDeviceCollection::EnumAudioEndpoints: " << std::hex << hr;
63 return 0;
64 }
65
66 // Retrieve the number of active audio devices for the specified direction
67 UINT number_of_active_devices = 0;
68 collection->GetCount(&number_of_active_devices);
69 std::string flow = (data_flow == eCapture) ? "[in ] " : "[out] ";
70 DVLOG(1) << flow << "number of devices: " << number_of_active_devices;
71
72 return static_cast<int>(number_of_active_devices);
73 }
74
75 ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumerator() {
76 ScopedComPtr<IMMDeviceEnumerator> device_enumerator;
77 HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
78 NULL,
79 CLSCTX_INPROC_SERVER,
80 __uuidof(IMMDeviceEnumerator),
81 device_enumerator.ReceiveVoid());
82 LOG_IF(ERROR, FAILED(hr)) << "CoCreateInstance(IMMDeviceEnumerator): "
83 << std::hex << hr;
84 return device_enumerator;
85 }
86
87 ScopedComPtr<IMMDevice> CreateDefaultAudioDevice(EDataFlow data_flow,
88 ERole role) {
89 ScopedComPtr<IMMDevice> endpoint_device;
90
91 // Create the IMMDeviceEnumerator interface.
92 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
93 CreateDeviceEnumerator();
94 if (!device_enumerator)
95 return endpoint_device;
96
97 // Retrieve the default audio endpoint for the specified data-flow
98 // direction and role.
99 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint(
100 data_flow, role, endpoint_device.Receive());
101
102 if (FAILED(hr)) {
103 LOG(ERROR) << "IMMDeviceEnumerator::GetDefaultAudioEndpoint: "
104 << std::hex << hr;
105 return endpoint_device;
106 }
107
108 // Verify that the audio endpoint device is active, i.e., that the audio
109 // adapter that connects to the endpoint device is present and enabled.
110 DWORD state = DEVICE_STATE_DISABLED;
111 hr = endpoint_device->GetState(&state);
112 if (SUCCEEDED(hr)) {
113 if (!(state & DEVICE_STATE_ACTIVE)) {
114 LOG(ERROR) << "Selected endpoint device is not active";
115 endpoint_device.Release();
116 }
117 }
118 return endpoint_device;
119 }
120
121 ScopedComPtr<IMMDevice> CreateAudioDevice(const std::string& device_id) {
122 ScopedComPtr<IMMDevice> endpoint_device;
123
124 // Create the IMMDeviceEnumerator interface.
125 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
126 CreateDeviceEnumerator();
127 if (!device_enumerator)
128 return endpoint_device;
129
130 // Retrieve an audio device specified by an endpoint device-identification
131 // string.
132 HRESULT hr = device_enumerator->GetDevice(UTF8ToUTF16(device_id).c_str(),
133 endpoint_device.Receive());
134 LOG_IF(ERROR, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: "
135 << std::hex << hr;
136 return endpoint_device;
137 }
138
139 HRESULT GetAudioDeviceName(IMMDevice* device, AudioDeviceName* name) {
140 DCHECK(device);
141 AudioDeviceName device_name;
142
143 // Retrieve unique name of endpoint device.
144 // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}".
145 ScopedCoMem<WCHAR> endpoint_device_id;
146 HRESULT hr = device->GetId(&endpoint_device_id);
147 if (FAILED(hr))
148 return hr;
149 device_name.unique_id = WideToUTF8(static_cast<WCHAR*>(endpoint_device_id));
150
151 // Retrieve user-friendly name of endpoint device.
152 // Example: "Microphone (Realtek High Definition Audio)".
153 ScopedComPtr<IPropertyStore> properties;
154 hr = device->OpenPropertyStore(STGM_READ, properties.Receive());
155 if (FAILED(hr))
156 return hr;
157 PROPVARIANT friendly_name;
158 PropVariantInit(&friendly_name);
159 hr = properties->GetValue(PKEY_Device_FriendlyName, &friendly_name);
160 if (FAILED(hr))
161 return hr;
162 if (friendly_name.vt == VT_LPWSTR && friendly_name.pwszVal) {
163 device_name.device_name = WideToUTF8(friendly_name.pwszVal);
164 }
165 PropVariantClear(&friendly_name);
166
167 *name = device_name;
168 DVLOG(1) << "friendly name: " << device_name.device_name;
169 DVLOG(1) << "unique id : " << device_name.unique_id;
170 return hr;
171 }
172
173 std::string GetFriendlyName(const std::string& device_id) {
174 std::string name;
175
176 ScopedComPtr<IMMDevice> audio_device = CreateAudioDevice(device_id);
177 if (!audio_device)
178 return name;
179
180 AudioDeviceName device_name;
181 HRESULT hr = GetAudioDeviceName(audio_device, &device_name);
182 if (FAILED(hr))
183 return name;
184
185 name = device_name.device_name;
186 return name;
187 }
188
189 bool IsDeviceDefault(EDataFlow flow, ERole role, std::string device_id) {
190 ScopedComPtr<IMMDevice> device = CreateDefaultAudioDevice(flow, role);
191 if (!device)
192 return false;
193
194 ScopedCoMem<WCHAR> default_device_id;
195 HRESULT hr = device->GetId(&default_device_id);
196 if (FAILED(hr))
197 return false;
198
199 std::string str_default = WideToUTF8(static_cast<WCHAR*>(default_device_id));
200 if (device_id.compare(str_default) != 0) {
201 return false;
202 }
203 return true;
204 }
205
206 EDataFlow GetDataFlow(IMMDevice* device) {
207 if (!device)
208 return eAll;
209
210 ScopedComPtr<IMMEndpoint> endpoint;
211 device->QueryInterface(endpoint.Receive());
212
213 EDataFlow data_flow;
214 HRESULT hr = endpoint->GetDataFlow(&data_flow);
215 if (FAILED(hr)) {
216 LOG(ERROR) << "IMMEndpoint::GetDataFlow: " << std::hex << hr;
217 return eAll;
218 }
219 return data_flow;
220 }
221
222 ScopedComPtr<IAudioClient> CreateAudioClient(IMMDevice* audio_device) {
223 ScopedComPtr<IAudioClient> audio_client;
224
225 // Creates and activates an IAudioClient COM object given the selected
226 // endpoint device.
227 HRESULT hr = audio_device->Activate(__uuidof(IAudioClient),
228 CLSCTX_INPROC_SERVER,
229 NULL,
230 audio_client.ReceiveVoid());
231 LOG_IF(ERROR, FAILED(hr)) << "IMMDevice::Activate: " << std::hex << hr;
232 return audio_client;
233 }
234
235 } // namespace win
236 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698