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/win/wavein_input_win.h" | 5 #include "media/audio/win/wavein_input_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <mmsystem.h> | 8 #include <mmsystem.h> |
9 #pragma comment(lib, "winmm.lib") | 9 #pragma comment(lib, "winmm.lib") |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "media/audio/audio_io.h" | 12 #include "media/audio/audio_io.h" |
13 #include "media/audio/audio_util.h" | 13 #include "media/audio/audio_util.h" |
14 #include "media/audio/win/audio_manager_win.h" | 14 #include "media/audio/win/audio_manager_win.h" |
15 #include "media/audio/win/device_enumeration_win.h" | |
15 | 16 |
16 namespace { | 17 namespace { |
17 const int kStopInputStreamCallbackTimeout = 3000; // Three seconds. | 18 const int kStopInputStreamCallbackTimeout = 3000; // Three seconds. |
18 } | 19 } |
19 | 20 |
21 using media::AudioDeviceNames; | |
22 | |
20 // Our sound buffers are allocated once and kept in a linked list using the | 23 // Our sound buffers are allocated once and kept in a linked list using the |
21 // the WAVEHDR::dwUser variable. The last buffer points to the first buffer. | 24 // the WAVEHDR::dwUser variable. The last buffer points to the first buffer. |
22 static WAVEHDR* GetNextBuffer(WAVEHDR* current) { | 25 static WAVEHDR* GetNextBuffer(WAVEHDR* current) { |
23 return reinterpret_cast<WAVEHDR*>(current->dwUser); | 26 return reinterpret_cast<WAVEHDR*>(current->dwUser); |
24 } | 27 } |
25 | 28 |
26 PCMWaveInAudioInputStream::PCMWaveInAudioInputStream( | 29 PCMWaveInAudioInputStream::PCMWaveInAudioInputStream( |
27 AudioManagerWin* manager, const AudioParameters& params, int num_buffers, | 30 AudioManagerWin* manager, const AudioParameters& params, int num_buffers, |
28 UINT device_id) | 31 const std::string& device_id) |
29 : state_(kStateEmpty), | 32 : state_(kStateEmpty), |
30 manager_(manager), | 33 manager_(manager), |
31 device_id_(device_id), | 34 device_id_(device_id), |
32 wavein_(NULL), | 35 wavein_(NULL), |
33 callback_(NULL), | 36 callback_(NULL), |
34 num_buffers_(num_buffers), | 37 num_buffers_(num_buffers), |
35 buffer_(NULL), | 38 buffer_(NULL), |
36 channels_(params.channels) { | 39 channels_(params.channels) { |
37 format_.wFormatTag = WAVE_FORMAT_PCM; | 40 format_.wFormatTag = WAVE_FORMAT_PCM; |
38 format_.nChannels = params.channels > 2 ? 2 : params.channels; | 41 format_.nChannels = params.channels > 2 ? 2 : params.channels; |
(...skipping 12 matching lines...) Expand all Loading... | |
51 | 54 |
52 PCMWaveInAudioInputStream::~PCMWaveInAudioInputStream() { | 55 PCMWaveInAudioInputStream::~PCMWaveInAudioInputStream() { |
53 DCHECK(NULL == wavein_); | 56 DCHECK(NULL == wavein_); |
54 } | 57 } |
55 | 58 |
56 bool PCMWaveInAudioInputStream::Open() { | 59 bool PCMWaveInAudioInputStream::Open() { |
57 if (state_ != kStateEmpty) | 60 if (state_ != kStateEmpty) |
58 return false; | 61 return false; |
59 if (num_buffers_ < 2 || num_buffers_ > 10) | 62 if (num_buffers_ < 2 || num_buffers_ > 10) |
60 return false; | 63 return false; |
61 MMRESULT result = ::waveInOpen(&wavein_, device_id_, &format_, | 64 |
62 reinterpret_cast<DWORD_PTR>(WaveCallback), | 65 // Convert the stored device id string into an unsigned integer |
63 reinterpret_cast<DWORD_PTR>(this), | 66 // corresponding to the selected device. |
64 CALLBACK_FUNCTION); | 67 UINT device_id = WAVE_MAPPER; |
68 if (!GetDeviceId(&device_id)) { | |
69 return false; | |
70 } | |
71 | |
72 // Open the specified input device for recording. | |
73 MMRESULT result = MMSYSERR_NOERROR; | |
74 result = ::waveInOpen(&wavein_, device_id, &format_, | |
75 reinterpret_cast<DWORD_PTR>(WaveCallback), | |
76 reinterpret_cast<DWORD_PTR>(this), | |
77 CALLBACK_FUNCTION); | |
65 if (result != MMSYSERR_NOERROR) | 78 if (result != MMSYSERR_NOERROR) |
66 return false; | 79 return false; |
67 | 80 |
68 SetupBuffers(); | 81 SetupBuffers(); |
69 state_ = kStateReady; | 82 state_ = kStateReady; |
70 return true; | 83 return true; |
71 } | 84 } |
72 | 85 |
73 void PCMWaveInAudioInputStream::SetupBuffers() { | 86 void PCMWaveInAudioInputStream::SetupBuffers() { |
74 WAVEHDR* last = NULL; | 87 WAVEHDR* last = NULL; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 DLOG(WARNING) << "PCMWaveInAudio error " << error; | 191 DLOG(WARNING) << "PCMWaveInAudio error " << error; |
179 callback_->OnError(this, error); | 192 callback_->OnError(this, error); |
180 } | 193 } |
181 | 194 |
182 void PCMWaveInAudioInputStream::QueueNextPacket(WAVEHDR *buffer) { | 195 void PCMWaveInAudioInputStream::QueueNextPacket(WAVEHDR *buffer) { |
183 MMRESULT res = ::waveInAddBuffer(wavein_, buffer, sizeof(WAVEHDR)); | 196 MMRESULT res = ::waveInAddBuffer(wavein_, buffer, sizeof(WAVEHDR)); |
184 if (res != MMSYSERR_NOERROR) | 197 if (res != MMSYSERR_NOERROR) |
185 HandleError(res); | 198 HandleError(res); |
186 } | 199 } |
187 | 200 |
201 bool PCMWaveInAudioInputStream::GetDeviceId(UINT* device_index) { | |
202 // Deliver the default input device id (WAVE_MAPPER) if the default | |
203 // device has been selected. | |
204 if (device_id_ == AudioManagerBase::kDefaultDeviceId) { | |
205 *device_index = WAVE_MAPPER; | |
206 return true; | |
207 } | |
208 | |
209 // Get list of all available and active devices. | |
210 AudioDeviceNames device_names; | |
211 if (!GetInputDeviceNamesWinXP(&device_names)) { | |
tommi (sloooow) - chröme
2011/12/01 14:11:03
nit: no need for {} (like the the next statement)
henrika (OOO until Aug 14)
2011/12/01 16:02:38
Done.
| |
212 return false; | |
213 } | |
214 | |
215 if (device_names.empty()) | |
216 return false; | |
217 | |
218 // Search the full list of devices and compare with the specified | |
219 // device id which was specified in the constructor. Stop comparing | |
220 // when a match is found and return the corresponding index. | |
221 UINT index = 0; | |
222 AudioDeviceNames::const_iterator it = device_names.begin(); | |
223 while (it != device_names.end()) { | |
no longer working on chromium
2011/12/01 15:28:03
what happen if none of the device in the list matc
henrika (OOO until Aug 14)
2011/12/01 16:02:38
Done.
| |
224 if (it->unique_id.compare(device_id_) == 0) { | |
no longer working on chromium
2011/12/01 15:28:03
we can directly use device_id_ == it->unique_id
henrika (OOO until Aug 14)
2011/12/01 16:02:38
I actually prefer the compare() method for std::st
| |
225 *device_index = index; | |
226 break; | |
227 } | |
228 ++index; | |
229 ++it; | |
230 } | |
231 | |
232 return true; | |
233 } | |
234 | |
188 // Windows calls us back in this function when some events happen. Most notably | 235 // Windows calls us back in this function when some events happen. Most notably |
189 // when it has an audio buffer with recorded data. | 236 // when it has an audio buffer with recorded data. |
190 void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg, | 237 void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg, |
191 DWORD_PTR instance, | 238 DWORD_PTR instance, |
192 DWORD_PTR param1, DWORD_PTR) { | 239 DWORD_PTR param1, DWORD_PTR) { |
193 PCMWaveInAudioInputStream* obj = | 240 PCMWaveInAudioInputStream* obj = |
194 reinterpret_cast<PCMWaveInAudioInputStream*>(instance); | 241 reinterpret_cast<PCMWaveInAudioInputStream*>(instance); |
195 | 242 |
196 if (msg == WIM_DATA) { | 243 if (msg == WIM_DATA) { |
197 // WIM_DONE indicates that the driver is done with our buffer. We pass it | 244 // WIM_DONE indicates that the driver is done with our buffer. We pass it |
(...skipping 18 matching lines...) Expand all Loading... | |
216 // waveInPrepareHeader. | 263 // waveInPrepareHeader. |
217 obj->QueueNextPacket(buffer); | 264 obj->QueueNextPacket(buffer); |
218 } | 265 } |
219 } else if (msg == WIM_CLOSE) { | 266 } else if (msg == WIM_CLOSE) { |
220 // We can be closed before calling Start, so it is possible to have a | 267 // We can be closed before calling Start, so it is possible to have a |
221 // null callback at this point. | 268 // null callback at this point. |
222 if (obj->callback_) | 269 if (obj->callback_) |
223 obj->callback_->OnClose(obj); | 270 obj->callback_->OnClose(obj); |
224 } | 271 } |
225 } | 272 } |
OLD | NEW |