srpcgen: Use 'const char*' for string parameters
[chromium-blink-merge.git] / media / audio / audio_input_controller.cc
blob7bb1d26a0f5083d9107932a430fa16a7f60da4da
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
3 // found in the LICENSE file.
5 #include "media/audio/audio_input_controller.h"
7 #include "base/bind.h"
8 #include "base/threading/thread_restrictions.h"
9 #include "media/base/limits.h"
11 namespace {
12 const int kMaxInputChannels = 2;
13 const int kTimerResetInterval = 1; // One second.
16 namespace media {
18 // static
19 AudioInputController::Factory* AudioInputController::factory_ = NULL;
21 AudioInputController::AudioInputController(AudioManager* audio_manager,
22 EventHandler* handler,
23 SyncWriter* sync_writer)
24 : audio_manager_(audio_manager),
25 handler_(handler),
26 stream_(NULL),
27 ALLOW_THIS_IN_INITIALIZER_LIST(no_data_timer_(FROM_HERE,
28 base::TimeDelta::FromSeconds(kTimerResetInterval),
29 this,
30 &AudioInputController::DoReportNoDataError)),
31 state_(kEmpty),
32 thread_("AudioInputControllerThread"),
33 sync_writer_(sync_writer) {
34 DCHECK(audio_manager_); // Fail early.
37 AudioInputController::~AudioInputController() {
38 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_);
41 // static
42 scoped_refptr<AudioInputController> AudioInputController::Create(
43 AudioManager* audio_manager,
44 EventHandler* event_handler,
45 const AudioParameters& params) {
46 DCHECK(audio_manager);
47 if (!params.IsValid() || (params.channels > kMaxInputChannels))
48 return NULL;
50 if (factory_) {
51 return factory_->Create(audio_manager, event_handler, params);
54 scoped_refptr<AudioInputController> controller(new AudioInputController(
55 audio_manager, event_handler, NULL));
57 // Start the thread and post a task to create the audio input stream.
58 // Pass an empty string to indicate using default device.
59 std::string device_id = AudioManagerBase::kDefaultDeviceId;
60 controller->thread_.Start();
61 controller->thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
62 &AudioInputController::DoCreate, controller.get(),
63 params, device_id));
64 return controller;
67 // static
68 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
69 AudioManager* audio_manager,
70 EventHandler* event_handler,
71 const AudioParameters& params,
72 const std::string& device_id,
73 SyncWriter* sync_writer) {
74 DCHECK(audio_manager);
75 DCHECK(sync_writer);
77 if (!params.IsValid() || (params.channels > kMaxInputChannels))
78 return NULL;
80 // Starts the audio controller thread.
81 scoped_refptr<AudioInputController> controller(new AudioInputController(
82 audio_manager, event_handler, sync_writer));
84 // Start the thread and post a task to create the audio input stream.
85 controller->thread_.Start();
86 controller->thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
87 &AudioInputController::DoCreate, controller.get(), params, device_id));
88 return controller;
91 void AudioInputController::Record() {
92 DCHECK(thread_.IsRunning());
93 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
94 &AudioInputController::DoRecord, this));
97 void AudioInputController::Close() {
98 if (!thread_.IsRunning()) {
99 // If the thread is not running make sure we are stopped.
100 DCHECK_EQ(kClosed, state_);
101 return;
104 // Wait for all tasks to complete on the audio thread.
105 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
106 &AudioInputController::DoClose, this));
108 // A ScopedAllowIO object is required to join the thread when calling Stop.
109 // This is because as joining threads may be a long operation it's now
110 // not allowed in threads without IO access, which is the case of the IO
111 // thread (it is missnamed) being used here. This object overrides
112 // temporarily this restriction and should be used only in specific
113 // infrequent cases where joining is guaranteed to be fast.
114 // Bug: http://code.google.com/p/chromium/issues/detail?id=67806
115 base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join;
116 thread_.Stop();
119 void AudioInputController::DoCreate(const AudioParameters& params,
120 const std::string& device_id) {
121 stream_ = audio_manager_->MakeAudioInputStream(params, device_id);
123 if (!stream_) {
124 // TODO(satish): Define error types.
125 handler_->OnError(this, 0);
126 return;
129 if (stream_ && !stream_->Open()) {
130 stream_->Close();
131 stream_ = NULL;
132 // TODO(satish): Define error types.
133 handler_->OnError(this, 0);
134 return;
137 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
138 &AudioInputController::DoResetNoDataTimer, this));
139 state_ = kCreated;
140 handler_->OnCreated(this);
143 void AudioInputController::DoRecord() {
144 DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
146 if (state_ != kCreated)
147 return;
150 base::AutoLock auto_lock(lock_);
151 state_ = kRecording;
154 stream_->Start(this);
155 handler_->OnRecording(this);
158 void AudioInputController::DoClose() {
159 DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
160 DCHECK_NE(kClosed, state_);
162 // |stream_| can be null if creating the device failed in DoCreate().
163 if (stream_) {
164 stream_->Stop();
165 stream_->Close();
166 // After stream is closed it is destroyed, so don't keep a reference to it.
167 stream_ = NULL;
170 if (LowLatencyMode()) {
171 sync_writer_->Close();
174 // Since the stream is closed at this point there's no other threads reading
175 // |state_| so we don't need to lock.
176 state_ = kClosed;
179 void AudioInputController::DoReportError(int code) {
180 DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
181 handler_->OnError(this, code);
184 void AudioInputController::DoReportNoDataError() {
185 DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
186 handler_->OnError(this, 0);
189 void AudioInputController::DoResetNoDataTimer() {
190 DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
191 no_data_timer_.Reset();
194 void AudioInputController::OnData(AudioInputStream* stream, const uint8* data,
195 uint32 size, uint32 hardware_delay_bytes) {
197 base::AutoLock auto_lock(lock_);
198 if (state_ != kRecording)
199 return;
202 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
203 &AudioInputController::DoResetNoDataTimer, this));
205 // Use SyncSocket if we are in a low-latency mode.
206 if (LowLatencyMode()) {
207 sync_writer_->Write(data, size);
208 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes);
209 return;
212 handler_->OnData(this, data, size);
215 void AudioInputController::OnClose(AudioInputStream* stream) {
216 // TODO(satish): Sometimes the device driver closes the input stream without
217 // us asking for it (may be if the device was unplugged?). Check how to handle
218 // such cases here.
221 void AudioInputController::OnError(AudioInputStream* stream, int code) {
222 // Handle error on the audio controller thread.
223 thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
224 &AudioInputController::DoReportError, this, code));
227 } // namespace media