Chromium Code Reviews| 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 |