OLD | NEW |
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 "chrome/browser/chromeos/audio/audio_mixer_alsa.h" | 5 #include "chrome/browser/chromeos/audio/audio_mixer_alsa.h" |
6 | 6 |
7 #include <unistd.h> | 7 #include <unistd.h> |
8 | 8 |
9 #include <alsa/asoundlib.h> | 9 #include <alsa/asoundlib.h> |
10 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 #include <cmath> | 12 #include <cmath> |
13 | 13 |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/callback.h" |
16 #include "base/chromeos/chromeos_version.h" | 17 #include "base/chromeos/chromeos_version.h" |
17 #include "base/logging.h" | 18 #include "base/logging.h" |
18 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
19 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
20 #include "base/threading/thread_restrictions.h" | 21 #include "base/threading/thread_restrictions.h" |
21 #include "chrome/browser/speech/extension_api/tts_extension_api_chromeos.h" | |
22 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
23 | 23 |
24 typedef long alsa_long_t; // 'long' is required for ALSA API calls. | 24 typedef long alsa_long_t; // 'long' is required for ALSA API calls. |
25 | 25 |
26 using content::BrowserThread; | 26 using content::BrowserThread; |
27 using std::string; | 27 using std::string; |
28 | 28 |
29 namespace chromeos { | 29 namespace chromeos { |
30 | 30 |
31 namespace { | 31 namespace { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // http://crbug.com/125206 | 97 // http://crbug.com/125206 |
98 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 98 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
99 disconnected_event_.Wait(); | 99 disconnected_event_.Wait(); |
100 } | 100 } |
101 | 101 |
102 base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join; | 102 base::ThreadRestrictions::ScopedAllowIO allow_io_for_thread_join; |
103 thread_->Stop(); | 103 thread_->Stop(); |
104 thread_.reset(); | 104 thread_.reset(); |
105 } | 105 } |
106 | 106 |
107 void AudioMixerAlsa::Init() { | 107 void AudioMixerAlsa::Init(const base::Closure& on_connected) { |
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
109 DCHECK(!thread_.get()) << "Init() called twice"; | 109 DCHECK(!thread_.get()) << "Init() called twice"; |
110 thread_.reset(new base::Thread("AudioMixerAlsa")); | 110 thread_.reset(new base::Thread("AudioMixerAlsa")); |
111 CHECK(thread_->Start()); | 111 CHECK(thread_->Start()); |
112 thread_->message_loop()->PostTask( | 112 thread_->message_loop()->PostTask( |
113 FROM_HERE, base::Bind(&AudioMixerAlsa::Connect, base::Unretained(this))); | 113 FROM_HERE, base::Bind(&AudioMixerAlsa::Connect, |
| 114 base::Unretained(this), |
| 115 on_connected)); |
114 } | 116 } |
115 | 117 |
116 double AudioMixerAlsa::GetVolumePercent() { | 118 double AudioMixerAlsa::GetVolumePercent() { |
117 base::AutoLock lock(lock_); | 119 base::AutoLock lock(lock_); |
118 return !alsa_mixer_ ? | 120 return !alsa_mixer_ ? |
119 initial_volume_percent_ : | 121 initial_volume_percent_ : |
120 DbToPercent(volume_db_); | 122 DbToPercent(volume_db_); |
121 } | 123 } |
122 | 124 |
123 void AudioMixerAlsa::SetVolumePercent(double percent) { | 125 void AudioMixerAlsa::SetVolumePercent(double percent) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 base::AutoLock lock(lock_); | 185 base::AutoLock lock(lock_); |
184 return is_capture_mute_locked_; | 186 return is_capture_mute_locked_; |
185 } | 187 } |
186 | 188 |
187 void AudioMixerAlsa::SetCaptureMuteLocked(bool locked) { | 189 void AudioMixerAlsa::SetCaptureMuteLocked(bool locked) { |
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
189 base::AutoLock lock(lock_); | 191 base::AutoLock lock(lock_); |
190 is_capture_mute_locked_ = locked; | 192 is_capture_mute_locked_ = locked; |
191 } | 193 } |
192 | 194 |
193 void AudioMixerAlsa::Connect() { | 195 void AudioMixerAlsa::Connect(const base::Closure& on_connected) { |
194 DCHECK(MessageLoop::current() == thread_->message_loop()); | 196 DCHECK(MessageLoop::current() == thread_->message_loop()); |
195 DCHECK(!alsa_mixer_); | 197 DCHECK(!alsa_mixer_); |
196 | 198 |
197 if (disconnected_event_.IsSignaled()) | 199 if (disconnected_event_.IsSignaled()) |
198 return; | 200 return; |
199 | 201 |
200 // Do not attempt to connect if we're not on the device. | 202 // Do not attempt to connect if we're not on the device. |
201 if (!base::chromeos::IsRunningOnChromeOS()) | 203 if (!base::chromeos::IsRunningOnChromeOS()) |
202 return; | 204 return; |
203 | 205 |
204 if (!ConnectInternal()) { | 206 if (!ConnectInternal(on_connected)) { |
205 thread_->message_loop()->PostDelayedTask(FROM_HERE, | 207 thread_->message_loop()->PostDelayedTask( |
206 base::Bind(&AudioMixerAlsa::Connect, base::Unretained(this)), | 208 FROM_HERE, |
| 209 base::Bind(&AudioMixerAlsa::Connect, |
| 210 base::Unretained(this), |
| 211 on_connected), |
207 base::TimeDelta::FromSeconds(kConnectionRetrySleepSec)); | 212 base::TimeDelta::FromSeconds(kConnectionRetrySleepSec)); |
208 } | 213 } |
209 } | 214 } |
210 | 215 |
211 bool AudioMixerAlsa::ConnectInternal() { | 216 bool AudioMixerAlsa::ConnectInternal(const base::Closure& on_connected) { |
212 DCHECK(MessageLoop::current() == thread_->message_loop()); | 217 DCHECK(MessageLoop::current() == thread_->message_loop()); |
213 num_connection_attempts_++; | 218 num_connection_attempts_++; |
214 int err; | 219 int err; |
215 snd_mixer_t* handle = NULL; | 220 snd_mixer_t* handle = NULL; |
216 | 221 |
217 if ((err = snd_mixer_open(&handle, 0)) < 0) { | 222 if ((err = snd_mixer_open(&handle, 0)) < 0) { |
218 if (num_connection_attempts_ == kConnectionAttemptToLogFailure) | 223 if (num_connection_attempts_ == kConnectionAttemptToLogFailure) |
219 LOG(WARNING) << "Mixer open error: " << snd_strerror(err); | 224 LOG(WARNING) << "Mixer open error: " << snd_strerror(err); |
220 return false; | 225 return false; |
221 } | 226 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 alsa_mixer_ = handle; | 323 alsa_mixer_ = handle; |
319 master_element_ = master_element; | 324 master_element_ = master_element; |
320 pcm_element_ = pcm_element; | 325 pcm_element_ = pcm_element; |
321 mic_element_ = mic_element; | 326 mic_element_ = mic_element; |
322 front_mic_element_ = front_mic_element; | 327 front_mic_element_ = front_mic_element; |
323 min_volume_db_ = min_volume_db; | 328 min_volume_db_ = min_volume_db; |
324 max_volume_db_ = max_volume_db; | 329 max_volume_db_ = max_volume_db; |
325 volume_db_ = PercentToDb(initial_volume_percent_); | 330 volume_db_ = PercentToDb(initial_volume_percent_); |
326 } | 331 } |
327 | 332 |
328 // The speech synthesis service shouldn't be initialized until after | 333 on_connected.Run(); |
329 // we get to this point, so we call this function to tell it that it's | |
330 // safe to do TTS now. NotificationService would be cleaner, | |
331 // but it's not available at this point. | |
332 EnableChromeOsTts(); | |
333 | 334 |
334 ApplyState(); | 335 ApplyState(); |
335 return true; | 336 return true; |
336 } | 337 } |
337 | 338 |
338 void AudioMixerAlsa::Disconnect() { | 339 void AudioMixerAlsa::Disconnect() { |
339 DCHECK(MessageLoop::current() == thread_->message_loop()); | 340 DCHECK(MessageLoop::current() == thread_->message_loop()); |
340 if (alsa_mixer_) { | 341 if (alsa_mixer_) { |
341 snd_mixer_close(alsa_mixer_); | 342 snd_mixer_close(alsa_mixer_); |
342 alsa_mixer_ = NULL; | 343 alsa_mixer_ = NULL; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 void AudioMixerAlsa::ApplyStateIfNeeded() { | 499 void AudioMixerAlsa::ApplyStateIfNeeded() { |
499 lock_.AssertAcquired(); | 500 lock_.AssertAcquired(); |
500 if (!apply_is_pending_) { | 501 if (!apply_is_pending_) { |
501 thread_->message_loop()->PostTask( | 502 thread_->message_loop()->PostTask( |
502 FROM_HERE, | 503 FROM_HERE, |
503 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this))); | 504 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this))); |
504 } | 505 } |
505 } | 506 } |
506 | 507 |
507 } // namespace chromeos | 508 } // namespace chromeos |
OLD | NEW |