OLD | NEW |
1 // Copyright (c) 2010 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 "chrome/browser/chromeos/audio_mixer_alsa.h" | 5 #include "chrome/browser/chromeos/audio_mixer_alsa.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
| 8 #include <unistd.h> |
8 | 9 |
9 #include <alsa/asoundlib.h> | 10 #include <alsa/asoundlib.h> |
10 | 11 |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
13 #include "base/task.h" | 14 #include "base/task.h" |
14 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
15 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
16 #include "chrome/browser/prefs/pref_service.h" | 17 #include "chrome/browser/prefs/pref_service.h" |
17 #include "chrome/common/pref_names.h" | 18 #include "chrome/common/pref_names.h" |
(...skipping 15 matching lines...) Expand all Loading... |
33 | 34 |
34 const char kMasterVolume[] = "Master"; | 35 const char kMasterVolume[] = "Master"; |
35 const char kPCMVolume[] = "PCM"; | 36 const char kPCMVolume[] = "PCM"; |
36 const double kDefaultMinVolume = -90.0; | 37 const double kDefaultMinVolume = -90.0; |
37 const double kDefaultMaxVolume = 0.0; | 38 const double kDefaultMaxVolume = 0.0; |
38 const double kPrefVolumeInvalid = -999.0; | 39 const double kPrefVolumeInvalid = -999.0; |
39 const int kPrefMuteOff = 0; | 40 const int kPrefMuteOff = 0; |
40 const int kPrefMuteOn = 1; | 41 const int kPrefMuteOn = 1; |
41 const int kPrefMuteInvalid = 2; | 42 const int kPrefMuteInvalid = 2; |
42 | 43 |
| 44 // Maximum number of times that we'll attempt to initialize the mixer. |
| 45 // We'll fail until the ALSA modules have been loaded; see |
| 46 // http://crosbug.com/13162. |
| 47 const int kMaxInitAttempts = 20; |
| 48 |
| 49 // Number of seconds that we'll sleep between each initialization attempt. |
| 50 const int kInitRetrySleepSec = 1; |
| 51 |
43 } // namespace | 52 } // namespace |
44 | 53 |
45 AudioMixerAlsa::AudioMixerAlsa() | 54 AudioMixerAlsa::AudioMixerAlsa() |
46 : min_volume_(kDefaultMinVolume), | 55 : min_volume_(kDefaultMinVolume), |
47 max_volume_(kDefaultMaxVolume), | 56 max_volume_(kDefaultMaxVolume), |
48 save_volume_(0), | 57 save_volume_(0), |
49 mixer_state_(UNINITIALIZED), | 58 mixer_state_(UNINITIALIZED), |
50 alsa_mixer_(NULL), | 59 alsa_mixer_(NULL), |
51 elem_master_(NULL), | 60 elem_master_(NULL), |
52 elem_pcm_(NULL), | 61 elem_pcm_(NULL), |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 if (!local_state->FindPreference(prefs::kAudioVolume)) | 200 if (!local_state->FindPreference(prefs::kAudioVolume)) |
192 local_state->RegisterDoublePref(prefs::kAudioVolume, kPrefVolumeInvalid); | 201 local_state->RegisterDoublePref(prefs::kAudioVolume, kPrefVolumeInvalid); |
193 if (!local_state->FindPreference(prefs::kAudioMute)) | 202 if (!local_state->FindPreference(prefs::kAudioMute)) |
194 local_state->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteInvalid); | 203 local_state->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteInvalid); |
195 } | 204 } |
196 | 205 |
197 //////////////////////////////////////////////////////////////////////////////// | 206 //////////////////////////////////////////////////////////////////////////////// |
198 // Private functions follow | 207 // Private functions follow |
199 | 208 |
200 void AudioMixerAlsa::DoInit(InitDoneCallback* callback) { | 209 void AudioMixerAlsa::DoInit(InitDoneCallback* callback) { |
201 bool success = InitializeAlsaMixer(); | 210 bool success = false; |
| 211 for (int num_attempts = 0; num_attempts < kMaxInitAttempts; ++num_attempts) { |
| 212 success = InitializeAlsaMixer(); |
| 213 if (success) { |
| 214 break; |
| 215 } else { |
| 216 // If the destructor has reset the state, give up. |
| 217 { |
| 218 base::AutoLock lock(mixer_state_lock_); |
| 219 if (mixer_state_ != INITIALIZING) |
| 220 break; |
| 221 } |
| 222 sleep(kInitRetrySleepSec); |
| 223 } |
| 224 } |
202 | 225 |
203 if (success) { | 226 if (success) { |
204 BrowserThread::PostTask( | 227 BrowserThread::PostTask( |
205 BrowserThread::UI, FROM_HERE, | 228 BrowserThread::UI, FROM_HERE, |
206 NewRunnableMethod(this, &AudioMixerAlsa::RestoreVolumeMuteOnUIThread)); | 229 NewRunnableMethod(this, &AudioMixerAlsa::RestoreVolumeMuteOnUIThread)); |
207 } | 230 } |
208 | 231 |
209 if (callback) { | 232 if (callback) { |
210 callback->Run(success); | 233 callback->Run(success); |
211 delete callback; | 234 delete callback; |
(...skipping 17 matching lines...) Expand all Loading... |
229 | 252 |
230 mixer_state_ = INITIALIZING; | 253 mixer_state_ = INITIALIZING; |
231 return true; | 254 return true; |
232 } | 255 } |
233 | 256 |
234 void AudioMixerAlsa::InitPrefs() { | 257 void AudioMixerAlsa::InitPrefs() { |
235 prefs_ = g_browser_process->local_state(); | 258 prefs_ = g_browser_process->local_state(); |
236 } | 259 } |
237 | 260 |
238 bool AudioMixerAlsa::InitializeAlsaMixer() { | 261 bool AudioMixerAlsa::InitializeAlsaMixer() { |
| 262 // We can block; make sure that we're not on the UI thread. |
| 263 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 264 |
239 base::AutoLock lock(mixer_state_lock_); | 265 base::AutoLock lock(mixer_state_lock_); |
240 if (mixer_state_ != INITIALIZING) | 266 if (mixer_state_ != INITIALIZING) |
241 return false; | 267 return false; |
242 | 268 |
243 int err; | 269 int err; |
244 snd_mixer_t* handle = NULL; | 270 snd_mixer_t* handle = NULL; |
245 const char* card = "default"; | 271 const char* card = "default"; |
246 | 272 |
247 if ((err = snd_mixer_open(&handle, 0)) < 0) { | 273 if ((err = snd_mixer_open(&handle, 0)) < 0) { |
248 LOG(ERROR) << "ALSA mixer " << card << " open error: " << snd_strerror(err); | 274 LOG(ERROR) << "ALSA mixer " << card << " open error: " << snd_strerror(err); |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 if (alsa_result != 0) { | 548 if (alsa_result != 0) { |
523 LOG(WARNING) << "snd_mixer_selem_set_playback_switch_all() failed: " | 549 LOG(WARNING) << "snd_mixer_selem_set_playback_switch_all() failed: " |
524 << snd_strerror(alsa_result); | 550 << snd_strerror(alsa_result); |
525 } else { | 551 } else { |
526 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem) | 552 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem) |
527 << " to " << enabled; | 553 << " to " << enabled; |
528 } | 554 } |
529 } | 555 } |
530 | 556 |
531 } // namespace chromeos | 557 } // namespace chromeos |
OLD | NEW |