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

Side by Side Diff: media/audio/audio_input_controller.cc

Issue 22801007: Adds the UserInputMonitor implementation for Mac. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 months 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
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/base/keyboard_event_counter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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_input_controller.h" 5 #include "media/audio/audio_input_controller.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/threading/thread_restrictions.h" 8 #include "base/threading/thread_restrictions.h"
9 #include "media/base/limits.h" 9 #include "media/base/limits.h"
10 #include "media/base/scoped_histogram_timer.h" 10 #include "media/base/scoped_histogram_timer.h"
11 #include "media/base/user_input_monitor.h"
11 12
12 namespace { 13 namespace {
13 const int kMaxInputChannels = 2; 14 const int kMaxInputChannels = 2;
14 15
15 // TODO(henrika): remove usage of timers and add support for proper 16 // TODO(henrika): remove usage of timers and add support for proper
16 // notification of when the input device is removed. This was originally added 17 // notification of when the input device is removed. This was originally added
17 // to resolve http://crbug.com/79936 for Windows platforms. This then caused 18 // to resolve http://crbug.com/79936 for Windows platforms. This then caused
18 // breakage (very hard to repro bugs!) on other platforms: See 19 // breakage (very hard to repro bugs!) on other platforms: See
19 // http://crbug.com/226327 and http://crbug.com/230972. 20 // http://crbug.com/226327 and http://crbug.com/230972.
20 const int kTimerResetIntervalSeconds = 1; 21 const int kTimerResetIntervalSeconds = 1;
(...skipping 18 matching lines...) Expand all
39 SyncWriter* sync_writer, 40 SyncWriter* sync_writer,
40 UserInputMonitor* user_input_monitor) 41 UserInputMonitor* user_input_monitor)
41 : creator_loop_(base::MessageLoopProxy::current()), 42 : creator_loop_(base::MessageLoopProxy::current()),
42 handler_(handler), 43 handler_(handler),
43 stream_(NULL), 44 stream_(NULL),
44 data_is_active_(false), 45 data_is_active_(false),
45 state_(kEmpty), 46 state_(kEmpty),
46 sync_writer_(sync_writer), 47 sync_writer_(sync_writer),
47 max_volume_(0.0), 48 max_volume_(0.0),
48 user_input_monitor_(user_input_monitor), 49 user_input_monitor_(user_input_monitor),
49 key_pressed_(false) { 50 prev_key_down_count_(0) {
50 DCHECK(creator_loop_.get()); 51 DCHECK(creator_loop_.get());
51 } 52 }
52 53
53 AudioInputController::~AudioInputController() { 54 AudioInputController::~AudioInputController() {
54 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); 55 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
55 } 56 }
56 57
57 // static 58 // static
58 scoped_refptr<AudioInputController> AudioInputController::Create( 59 scoped_refptr<AudioInputController> AudioInputController::Create(
59 AudioManager* audio_manager, 60 AudioManager* audio_manager,
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 no_data_timer_.reset(new base::Timer( 212 no_data_timer_.reset(new base::Timer(
212 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), 213 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds),
213 base::Bind(&AudioInputController::DoCheckForNoData, 214 base::Bind(&AudioInputController::DoCheckForNoData,
214 base::Unretained(this)), false)); 215 base::Unretained(this)), false));
215 } else { 216 } else {
216 DVLOG(1) << "Disabled: timer check for no data."; 217 DVLOG(1) << "Disabled: timer check for no data.";
217 } 218 }
218 219
219 state_ = kCreated; 220 state_ = kCreated;
220 handler_->OnCreated(this); 221 handler_->OnCreated(this);
222
223 if (user_input_monitor_) {
224 user_input_monitor_->EnableKeyPressMonitoring();
225 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount();
226 }
221 } 227 }
222 228
223 void AudioInputController::DoRecord() { 229 void AudioInputController::DoRecord() {
224 DCHECK(message_loop_->BelongsToCurrentThread()); 230 DCHECK(message_loop_->BelongsToCurrentThread());
225 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); 231 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
226 232
227 if (state_ != kCreated) 233 if (state_ != kCreated)
228 return; 234 return;
229 235
230 { 236 {
231 base::AutoLock auto_lock(lock_); 237 base::AutoLock auto_lock(lock_);
232 state_ = kRecording; 238 state_ = kRecording;
233 } 239 }
234 240
235 if (no_data_timer_) { 241 if (no_data_timer_) {
236 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, 242 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed,
237 // a callback to DoCheckForNoData() is made. 243 // a callback to DoCheckForNoData() is made.
238 no_data_timer_->Reset(); 244 no_data_timer_->Reset();
239 } 245 }
240 246
241 stream_->Start(this); 247 stream_->Start(this);
242 handler_->OnRecording(this); 248 handler_->OnRecording(this);
243
244 if (user_input_monitor_)
245 user_input_monitor_->AddKeyStrokeListener(this);
246 } 249 }
247 250
248 void AudioInputController::DoClose() { 251 void AudioInputController::DoClose() {
249 DCHECK(message_loop_->BelongsToCurrentThread()); 252 DCHECK(message_loop_->BelongsToCurrentThread());
250 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); 253 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
251 254
252 // Delete the timer on the same thread that created it. 255 // Delete the timer on the same thread that created it.
253 no_data_timer_.reset(); 256 no_data_timer_.reset();
254 257
255 if (state_ != kClosed) { 258 if (state_ != kClosed) {
256 DoStopCloseAndClearStream(NULL); 259 DoStopCloseAndClearStream(NULL);
257 SetDataIsActive(false); 260 SetDataIsActive(false);
258 261
259 if (LowLatencyMode()) { 262 if (LowLatencyMode()) {
260 sync_writer_->Close(); 263 sync_writer_->Close();
261 } 264 }
262 265
263 state_ = kClosed; 266 state_ = kClosed;
264 267
265 if (user_input_monitor_) 268 if (user_input_monitor_)
266 user_input_monitor_->RemoveKeyStrokeListener(this); 269 user_input_monitor_->DisableKeyPressMonitoring();
267 } 270 }
268 } 271 }
269 272
270 void AudioInputController::DoReportError() { 273 void AudioInputController::DoReportError() {
271 DCHECK(message_loop_->BelongsToCurrentThread()); 274 DCHECK(message_loop_->BelongsToCurrentThread());
272 handler_->OnError(this); 275 handler_->OnError(this);
273 } 276 }
274 277
275 void AudioInputController::DoSetVolume(double volume) { 278 void AudioInputController::DoSetVolume(double volume) {
276 DCHECK(message_loop_->BelongsToCurrentThread()); 279 DCHECK(message_loop_->BelongsToCurrentThread());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 SetDataIsActive(false); 326 SetDataIsActive(false);
324 327
325 // Restart the timer to ensure that we check the flag again in 328 // Restart the timer to ensure that we check the flag again in
326 // |kTimerResetIntervalSeconds|. 329 // |kTimerResetIntervalSeconds|.
327 no_data_timer_->Start( 330 no_data_timer_->Start(
328 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), 331 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds),
329 base::Bind(&AudioInputController::DoCheckForNoData, 332 base::Bind(&AudioInputController::DoCheckForNoData,
330 base::Unretained(this))); 333 base::Unretained(this)));
331 } 334 }
332 335
333 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data, 336 void AudioInputController::OnData(AudioInputStream* stream,
334 uint32 size, uint32 hardware_delay_bytes, 337 const uint8* data,
338 uint32 size,
339 uint32 hardware_delay_bytes,
335 double volume) { 340 double volume) {
336 bool key_pressed = false;
337 { 341 {
338 base::AutoLock auto_lock(lock_); 342 base::AutoLock auto_lock(lock_);
339 if (state_ != kRecording) 343 if (state_ != kRecording)
340 return; 344 return;
345 }
341 346
342 std::swap(key_pressed, key_pressed_); 347 bool key_pressed = false;
348 if (user_input_monitor_) {
349 size_t current_count = user_input_monitor_->GetKeyPressCount();
350 key_pressed = current_count != prev_key_down_count_;
351 prev_key_down_count_ = current_count;
352 DVLOG_IF(6, key_pressed) << "Detected keypress.";
343 } 353 }
344 354
345 // Mark data as active to ensure that the periodic calls to 355 // Mark data as active to ensure that the periodic calls to
346 // DoCheckForNoData() does not report an error to the event handler. 356 // DoCheckForNoData() does not report an error to the event handler.
347 SetDataIsActive(true); 357 SetDataIsActive(true);
348 358
349 // Use SyncSocket if we are in a low-latency mode. 359 // Use SyncSocket if we are in a low-latency mode.
350 if (LowLatencyMode()) { 360 if (LowLatencyMode()) {
351 sync_writer_->Write(data, size, volume, key_pressed); 361 sync_writer_->Write(data, size, volume, key_pressed);
352 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 362 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
353 return; 363 return;
354 } 364 }
355 365
356 handler_->OnData(this, data, size); 366 handler_->OnData(this, data, size);
357 } 367 }
358 368
359 void AudioInputController::OnClose(AudioInputStream* stream) { 369 void AudioInputController::OnClose(AudioInputStream* stream) {
360 DVLOG(1) << "AudioInputController::OnClose()"; 370 DVLOG(1) << "AudioInputController::OnClose()";
361 // TODO(satish): Sometimes the device driver closes the input stream without 371 // TODO(satish): Sometimes the device driver closes the input stream without
362 // us asking for it (may be if the device was unplugged?). Check how to handle 372 // us asking for it (may be if the device was unplugged?). Check how to handle
363 // such cases here. 373 // such cases here.
364 } 374 }
365 375
366 void AudioInputController::OnError(AudioInputStream* stream) { 376 void AudioInputController::OnError(AudioInputStream* stream) {
367 // Handle error on the audio-manager thread. 377 // Handle error on the audio-manager thread.
368 message_loop_->PostTask(FROM_HERE, base::Bind( 378 message_loop_->PostTask(FROM_HERE, base::Bind(
369 &AudioInputController::DoReportError, this)); 379 &AudioInputController::DoReportError, this));
370 } 380 }
371 381
372 void AudioInputController::OnKeyStroke() {
373 base::AutoLock auto_lock(lock_);
374 key_pressed_ = true;
375 }
376
377 void AudioInputController::DoStopCloseAndClearStream( 382 void AudioInputController::DoStopCloseAndClearStream(
378 base::WaitableEvent* done) { 383 base::WaitableEvent* done) {
379 DCHECK(message_loop_->BelongsToCurrentThread()); 384 DCHECK(message_loop_->BelongsToCurrentThread());
380 385
381 // Allow calling unconditionally and bail if we don't have a stream to close. 386 // Allow calling unconditionally and bail if we don't have a stream to close.
382 if (stream_ != NULL) { 387 if (stream_ != NULL) {
383 stream_->Stop(); 388 stream_->Stop();
384 stream_->Close(); 389 stream_->Close();
385 stream_ = NULL; 390 stream_ = NULL;
386 } 391 }
387 392
388 // Should be last in the method, do not touch "this" from here on. 393 // Should be last in the method, do not touch "this" from here on.
389 if (done != NULL) 394 if (done != NULL)
390 done->Signal(); 395 done->Signal();
391 } 396 }
392 397
393 void AudioInputController::SetDataIsActive(bool enabled) { 398 void AudioInputController::SetDataIsActive(bool enabled) {
394 base::subtle::Release_Store(&data_is_active_, enabled); 399 base::subtle::Release_Store(&data_is_active_, enabled);
395 } 400 }
396 401
397 bool AudioInputController::GetDataIsActive() { 402 bool AudioInputController::GetDataIsActive() {
398 return (base::subtle::Acquire_Load(&data_is_active_) != false); 403 return (base::subtle::Acquire_Load(&data_is_active_) != false);
399 } 404 }
400 405
401 } // namespace media 406 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/base/keyboard_event_counter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698