OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/audio_io.h" | 5 #include "media/audio/audio_io.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <objbase.h> // This has to be before initguid.h | 8 #include <objbase.h> // This has to be before initguid.h |
9 #include <initguid.h> | 9 #include <initguid.h> |
10 #include <mmsystem.h> | 10 #include <mmsystem.h> |
11 #include <setupapi.h> | 11 #include <setupapi.h> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/file_path.h" | 15 #include "base/file_path.h" |
16 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
17 #include "base/path_service.h" | 17 #include "base/path_service.h" |
18 #include "base/process_util.h" | 18 #include "base/process_util.h" |
19 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
20 #include "base/string_util.h" | 20 #include "base/string_util.h" |
21 #include "media/audio/audio_util.h" | 21 #include "media/audio/audio_util.h" |
22 #include "media/audio/fake_audio_input_stream.h" | |
23 #include "media/audio/fake_audio_output_stream.h" | |
24 #include "media/audio/win/audio_low_latency_input_win.h" | 22 #include "media/audio/win/audio_low_latency_input_win.h" |
25 #include "media/audio/win/audio_low_latency_output_win.h" | 23 #include "media/audio/win/audio_low_latency_output_win.h" |
26 #include "media/audio/win/audio_manager_win.h" | 24 #include "media/audio/win/audio_manager_win.h" |
27 #include "media/audio/win/device_enumeration_win.h" | 25 #include "media/audio/win/device_enumeration_win.h" |
28 #include "media/audio/win/wavein_input_win.h" | 26 #include "media/audio/win/wavein_input_win.h" |
29 #include "media/audio/win/waveout_output_win.h" | 27 #include "media/audio/win/waveout_output_win.h" |
30 #include "media/base/limits.h" | 28 #include "media/base/limits.h" |
31 | 29 |
32 // Libraries required for the SetupAPI and Wbem APIs used here. | 30 // Libraries required for the SetupAPI and Wbem APIs used here. |
33 #pragma comment(lib, "setupapi.lib") | 31 #pragma comment(lib, "setupapi.lib") |
34 | 32 |
35 // The following are defined in various DDK headers, and we (re)define them | 33 // The following are defined in various DDK headers, and we (re)define them |
36 // here to avoid adding the DDK as a chrome dependency. | 34 // here to avoid adding the DDK as a chrome dependency. |
37 #define DRV_QUERYDEVICEINTERFACE 0x80c | 35 #define DRV_QUERYDEVICEINTERFACE 0x80c |
38 #define DRVM_MAPPER_PREFERRED_GET 0x2015 | 36 #define DRVM_MAPPER_PREFERRED_GET 0x2015 |
39 #define DRV_QUERYDEVICEINTERFACESIZE 0x80d | 37 #define DRV_QUERYDEVICEINTERFACESIZE 0x80d |
40 DEFINE_GUID(AM_KSCATEGORY_AUDIO, 0x6994ad04, 0x93ef, 0x11d0, | 38 DEFINE_GUID(AM_KSCATEGORY_AUDIO, 0x6994ad04, 0x93ef, 0x11d0, |
41 0xa3, 0xcc, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96); | 39 0xa3, 0xcc, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96); |
42 | 40 |
43 // Maximum number of output streams that can be open simultaneously. | 41 // Maximum number of output streams that can be open simultaneously. |
44 static const size_t kMaxOutputStreams = 50; | 42 static const int kMaxOutputStreams = 50; |
45 | 43 |
46 // Up to 8 channels can be passed to the driver. | 44 // Up to 8 channels can be passed to the driver. |
47 // This should work, given the right drivers, but graceful error handling is | 45 // This should work, given the right drivers, but graceful error handling is |
48 // needed. | 46 // needed. |
49 static const int kWinMaxChannels = 8; | 47 static const int kWinMaxChannels = 8; |
50 | 48 |
51 static const int kWinMaxInputChannels = 2; | 49 static const int kWinMaxInputChannels = 2; |
52 // We use 3 buffers for recording audio so that if a recording callback takes | 50 // We use 3 buffers for recording audio so that if a recording callback takes |
53 // some time to return we won't lose audio. More buffers while recording are | 51 // some time to return we won't lose audio. More buffers while recording are |
54 // ok because they don't introduce any delay in recording, unlike in playback | 52 // ok because they don't introduce any delay in recording, unlike in playback |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 89 } |
92 SetupDiDestroyDriverInfoList(device_info, device_data, SPDIT_COMPATDRIVER); | 90 SetupDiDestroyDriverInfoList(device_info, device_data, SPDIT_COMPATDRIVER); |
93 } | 91 } |
94 | 92 |
95 SetupDiSetDeviceInstallParams(device_info, device_data, | 93 SetupDiSetDeviceInstallParams(device_info, device_data, |
96 &old_device_install_params); | 94 &old_device_install_params); |
97 | 95 |
98 return device_and_driver_info; | 96 return device_and_driver_info; |
99 } | 97 } |
100 | 98 |
101 AudioManagerWin::AudioManagerWin() | 99 AudioManagerWin::AudioManagerWin() { |
102 : num_output_streams_(0) { | |
103 if (!media::IsWASAPISupported()) { | 100 if (!media::IsWASAPISupported()) { |
104 // Use the Wave API for device enumeration if XP or lower. | 101 // Use the Wave API for device enumeration if XP or lower. |
105 enumeration_type_ = kWaveEnumeration; | 102 enumeration_type_ = kWaveEnumeration; |
106 } else { | 103 } else { |
107 // Use the MMDevice API for device enumeration if Vista or higher. | 104 // Use the MMDevice API for device enumeration if Vista or higher. |
108 enumeration_type_ = kMMDeviceEnumeration; | 105 enumeration_type_ = kMMDeviceEnumeration; |
109 } | 106 } |
| 107 |
| 108 SetMaxOutputStreamsAllowed(kMaxOutputStreams); |
110 } | 109 } |
111 | 110 |
112 AudioManagerWin::~AudioManagerWin() { | 111 AudioManagerWin::~AudioManagerWin() { |
113 // All output streams should be released upon termination. | |
114 DCHECK_EQ(0, num_output_streams_); | |
115 } | 112 } |
116 | 113 |
117 bool AudioManagerWin::HasAudioOutputDevices() { | 114 bool AudioManagerWin::HasAudioOutputDevices() { |
118 return (::waveOutGetNumDevs() != 0); | 115 return (::waveOutGetNumDevs() != 0); |
119 } | 116 } |
120 | 117 |
121 bool AudioManagerWin::HasAudioInputDevices() { | 118 bool AudioManagerWin::HasAudioInputDevices() { |
122 return (::waveInGetNumDevs() != 0); | 119 return (::waveInGetNumDevs() != 0); |
123 } | 120 } |
124 | 121 |
125 // Factory for the implementations of AudioOutputStream. Two implementations | |
126 // should suffice most windows user's needs. | |
127 // - PCMWaveOutAudioOutputStream: Based on the waveOut API. | |
128 // - WASAPIAudioOutputStream: Based on Core Audio (WASAPI) API. | |
129 AudioOutputStream* AudioManagerWin::MakeAudioOutputStream( | |
130 const AudioParameters& params) { | |
131 if (!params.IsValid() || (params.channels > kWinMaxChannels)) | |
132 return NULL; | |
133 | |
134 // Limit the number of audio streams opened. | |
135 if (num_output_streams_ >= kMaxOutputStreams) { | |
136 return NULL; | |
137 } | |
138 | |
139 if (params.format == AudioParameters::AUDIO_MOCK) { | |
140 return FakeAudioOutputStream::MakeFakeStream(params); | |
141 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { | |
142 num_output_streams_++; | |
143 return new PCMWaveOutAudioOutputStream(this, params, 3, WAVE_MAPPER); | |
144 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | |
145 num_output_streams_++; | |
146 if (!media::IsWASAPISupported()) { | |
147 // Fall back to Windows Wave implementation on Windows XP or lower. | |
148 DLOG(INFO) << "Using WaveOut since WASAPI requires at least Vista."; | |
149 return new PCMWaveOutAudioOutputStream(this, params, 2, WAVE_MAPPER); | |
150 } else { | |
151 // TODO(henrika): improve possibility to specify audio endpoint. | |
152 // Use the default device (same as for Wave) for now to be compatible. | |
153 return new WASAPIAudioOutputStream(this, params, eConsole); | |
154 } | |
155 } | |
156 return NULL; | |
157 } | |
158 | |
159 // Factory for the implementations of AudioInputStream. | |
160 AudioInputStream* AudioManagerWin::MakeAudioInputStream( | |
161 const AudioParameters& params, const std::string& device_id) { | |
162 if (!params.IsValid() || (params.channels > kWinMaxInputChannels) || | |
163 device_id.empty()) | |
164 return NULL; | |
165 | |
166 if (params.format == AudioParameters::AUDIO_MOCK) { | |
167 return FakeAudioInputStream::MakeFakeStream(params); | |
168 } else if (params.format == AudioParameters::AUDIO_PCM_LINEAR) { | |
169 return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers, | |
170 AudioManagerBase::kDefaultDeviceId); | |
171 } else if (params.format == AudioParameters::AUDIO_PCM_LOW_LATENCY) { | |
172 if (!media::IsWASAPISupported()) { | |
173 // Fall back to Windows Wave implementation on Windows XP or lower. | |
174 DLOG(INFO) << "Using WaveIn since WASAPI requires at least Vista."; | |
175 return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers, | |
176 device_id); | |
177 } else { | |
178 return new WASAPIAudioInputStream(this, params, device_id); | |
179 } | |
180 } | |
181 return NULL; | |
182 } | |
183 | |
184 void AudioManagerWin::ReleaseOutputStream(AudioOutputStream* stream) { | |
185 DCHECK(stream); | |
186 num_output_streams_--; | |
187 delete stream; | |
188 } | |
189 | |
190 void AudioManagerWin::ReleaseInputStream(AudioInputStream* stream) { | |
191 delete stream; | |
192 } | |
193 | |
194 void AudioManagerWin::MuteAll() { | 122 void AudioManagerWin::MuteAll() { |
195 } | 123 } |
196 | 124 |
197 void AudioManagerWin::UnMuteAll() { | 125 void AudioManagerWin::UnMuteAll() { |
198 } | 126 } |
199 | 127 |
200 string16 AudioManagerWin::GetAudioInputDeviceModel() { | 128 string16 AudioManagerWin::GetAudioInputDeviceModel() { |
201 // Get the default audio capture device and its device interface name. | 129 // Get the default audio capture device and its device interface name. |
202 DWORD device_id = 0; | 130 DWORD device_id = 0; |
203 waveInMessage(reinterpret_cast<HWAVEIN>(WAVE_MAPPER), | 131 waveInMessage(reinterpret_cast<HWAVEIN>(WAVE_MAPPER), |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 | 226 |
299 // Always add default device parameters as first element. | 227 // Always add default device parameters as first element. |
300 if (!device_names->empty()) { | 228 if (!device_names->empty()) { |
301 media::AudioDeviceName name; | 229 media::AudioDeviceName name; |
302 name.device_name = AudioManagerBase::kDefaultDeviceName; | 230 name.device_name = AudioManagerBase::kDefaultDeviceName; |
303 name.unique_id = AudioManagerBase::kDefaultDeviceId; | 231 name.unique_id = AudioManagerBase::kDefaultDeviceId; |
304 device_names->push_front(name); | 232 device_names->push_front(name); |
305 } | 233 } |
306 } | 234 } |
307 | 235 |
| 236 // Factory for the implementations of AudioOutputStream for AUDIO_PCM_LINEAR |
| 237 // mode. |
| 238 // - PCMWaveOutAudioOutputStream: Based on the waveOut API. |
| 239 AudioOutputStream* AudioManagerWin::MakeLinearOutputStream( |
| 240 const AudioParameters& params) { |
| 241 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format); |
| 242 if (params.channels > kWinMaxChannels) |
| 243 return NULL; |
| 244 |
| 245 return new PCMWaveOutAudioOutputStream(this, params, 3, WAVE_MAPPER); |
| 246 } |
| 247 |
| 248 // Factory for the implementations of AudioOutputStream for |
| 249 // AUDIO_PCM_LOW_LATENCY mode. Two implementations should suffice most |
| 250 // windows user's needs. |
| 251 // - PCMWaveOutAudioOutputStream: Based on the waveOut API. |
| 252 // - WASAPIAudioOutputStream: Based on Core Audio (WASAPI) API. |
| 253 AudioOutputStream* AudioManagerWin::MakeLowLatencyOutputStream( |
| 254 const AudioParameters& params) { |
| 255 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format); |
| 256 if (params.channels > kWinMaxChannels) |
| 257 return NULL; |
| 258 |
| 259 AudioOutputStream* stream = NULL; |
| 260 if (!media::IsWASAPISupported()) { |
| 261 // Fall back to Windows Wave implementation on Windows XP or lower. |
| 262 DVLOG(1) << "Using WaveOut since WASAPI requires at least Vista."; |
| 263 stream = new PCMWaveOutAudioOutputStream(this, params, 2, WAVE_MAPPER); |
| 264 } else { |
| 265 // TODO(henrika): improve possibility to specify audio endpoint. |
| 266 // Use the default device (same as for Wave) for now to be compatible. |
| 267 stream = new WASAPIAudioOutputStream(this, params, eConsole); |
| 268 } |
| 269 |
| 270 return stream; |
| 271 } |
| 272 |
| 273 // Factory for the implementations of AudioInputStream for AUDIO_PCM_LINEAR |
| 274 // mode. |
| 275 AudioInputStream* AudioManagerWin::MakeLinearInputStream( |
| 276 const AudioParameters& params, const std::string& device_id) { |
| 277 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format); |
| 278 if (params.channels > kWinMaxInputChannels) |
| 279 return NULL; |
| 280 |
| 281 return new PCMWaveInAudioInputStream(this, params, kNumInputBuffers, |
| 282 AudioManagerBase::kDefaultDeviceId); |
| 283 } |
| 284 |
| 285 // Factory for the implementations of AudioInputStream for |
| 286 // AUDIO_PCM_LOW_LATENCY mode. |
| 287 AudioInputStream* AudioManagerWin::MakeLowLatencyInputStream( |
| 288 const AudioParameters& params, const std::string& device_id) { |
| 289 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format); |
| 290 if (params.channels > kWinMaxInputChannels) |
| 291 return NULL; |
| 292 |
| 293 AudioInputStream* stream = NULL; |
| 294 if (!media::IsWASAPISupported()) { |
| 295 // Fall back to Windows Wave implementation on Windows XP or lower. |
| 296 DVLOG(1) << "Using WaveIn since WASAPI requires at least Vista."; |
| 297 stream = new PCMWaveInAudioInputStream(this, params, kNumInputBuffers, |
| 298 device_id); |
| 299 } else { |
| 300 stream = new WASAPIAudioInputStream(this, params, device_id); |
| 301 } |
| 302 |
| 303 return stream; |
| 304 } |
| 305 |
308 /// static | 306 /// static |
309 AudioManager* CreateAudioManager() { | 307 AudioManager* CreateAudioManager() { |
310 return new AudioManagerWin(); | 308 return new AudioManagerWin(); |
311 } | 309 } |
OLD | NEW |