Chromium Code Reviews| Index: chrome/browser/chromeos/audio_handler.cc |
| diff --git a/chrome/browser/chromeos/audio_handler.cc b/chrome/browser/chromeos/audio_handler.cc |
| index 2f6638fe6bcd693b241632c3f7e6c3c62846cfd9..6f1bc5422dd81088409aa0b6fd59d4b140f7b7a3 100644 |
| --- a/chrome/browser/chromeos/audio_handler.cc |
| +++ b/chrome/browser/chromeos/audio_handler.cc |
| @@ -8,13 +8,14 @@ |
| #include "base/logging.h" |
| #include "base/singleton.h" |
| -#include "chrome/browser/chromeos/pulse_audio_mixer.h" |
| +#include "chrome/browser/chromeos/audio_mixer_pulse.h" |
| +#include "chrome/browser/chromeos/audio_mixer_alsa.h" |
| +#include "chrome/browser/browser_thread.h" |
| namespace chromeos { |
| namespace { |
| -const double kSilenceDb = -200.0; |
| const double kMinVolumeDb = -90.0; |
| // Choosing 6.0dB here instead of 0dB to give user chance to amplify audio some |
| // in case sounds or their setup is too quiet for them. |
| @@ -25,12 +26,14 @@ const double kVolumeBias = 0.5; |
| // If a connection is lost, we try again this many times |
| const int kMaxReconnectTries = 4; |
| -} // namespace |
| +const int kUsingPulseAudio = 0; |
| +const int kUsingAlsa = 1; |
| +const int kUsingNone = 2; |
| -// This class will set volume using PulseAudio to adjust volume and mute, and |
| -// handles the volume level logic. |
| +} // namespace |
| -// TODO(davej): Serialize volume/mute for next startup? |
| +// This class will set volume using PulseAudio or ALSA to adjust volume and |
| +// mute, and handles the volume level logic. |
| double AudioHandler::GetVolumePercent() { |
| if (!VerifyMixerConnection()) |
| @@ -40,7 +43,7 @@ double AudioHandler::GetVolumePercent() { |
| } |
| // Set volume using our internal 0-100% range. Notice 0% is a special case of |
| -// silence, so we set the mixer volume to kSilenceDb instead of kMinVolumeDb. |
| +// silence, so we set the mixer volume to kSilenceDb instead of min_volume_db_. |
| void AudioHandler::SetVolumePercent(double volume_percent) { |
| if (!VerifyMixerConnection()) |
| return; |
| @@ -96,17 +99,61 @@ void AudioHandler::SetMute(bool do_mute) { |
| mixer_->SetMute(do_mute); |
| } |
| +bool AudioHandler::TryToConnect(bool async) { |
| + if (using_mixer_ == kUsingPulseAudio) { |
| + VLOG(1) << "Trying to connect to PulseAudio"; |
| + mixer_.reset(new AudioMixerPulse()); |
| + } else if (using_mixer_ == kUsingAlsa) { |
| + VLOG(1) << "Trying to connect to ALSA"; |
| + mixer_.reset(new AudioMixerAlsa()); |
| + } else { |
| + VLOG(1) << "Cannot find valid volume mixer"; |
| + mixer_.reset(); |
| + return false; |
| + } |
| + |
| + if (async) { |
| + if (mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized))) |
| + return true; |
| + } else { |
| + if (mixer_->InitSync()) |
| + return true; |
| + VLOG(1) << "Unable to reconnect to Mixer"; |
| + } |
| + return false; |
| +} |
| + |
| void AudioHandler::OnMixerInitialized(bool success) { |
| connected_ = success; |
| DVLOG(1) << "OnMixerInitialized, success = " << success; |
| + |
| + if (connected_) { |
| + mixer_->GetVolumeLimits(&min_volume_db_, &max_volume_db_); |
| + if (min_volume_db_ < kMinVolumeDb) |
| + min_volume_db_ = kMinVolumeDb; |
| + if (max_volume_db_ > kMaxVolumeDb) |
| + max_volume_db_ = kMaxVolumeDb; |
| + } else { |
| + ++using_mixer_; |
|
Daniel Erat
2010/12/20 22:01:12
this seems fragile; please spell out the transitio
davejcool
2010/12/21 02:00:21
Now logic is in UseNextMixer()
|
| + VLOG(1) << "Unable to connect to Mixer, trying next"; |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + NewRunnableMethod(this, &AudioHandler::TryToConnect, true)); |
| + } |
| } |
| AudioHandler::AudioHandler() |
| : connected_(false), |
| - reconnect_tries_(0) { |
| - mixer_.reset(new PulseAudioMixer()); |
| - if (!mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized))) { |
| - LOG(ERROR) << "Unable to connect to PulseAudio"; |
| + reconnect_tries_(0), |
| + max_volume_db_(0), |
| + min_volume_db_(-90), |
| + using_mixer_(kUsingPulseAudio) { |
| + while (using_mixer_ != kUsingNone) { |
| + if (TryToConnect(true)) { |
| + break; |
| + } |
| + ++using_mixer_; |
| } |
| } |
| @@ -115,58 +162,62 @@ AudioHandler::~AudioHandler() { |
| }; |
| bool AudioHandler::VerifyMixerConnection() { |
| - PulseAudioMixer::State mixer_state = mixer_->CheckState(); |
| - if (mixer_state == PulseAudioMixer::READY) |
| + if (mixer_ == NULL) |
| + return false; |
| + |
| + AudioMixerBase::State mixer_state = mixer_->CheckState(); |
| + if (mixer_state == AudioMixerBase::READY) |
| return true; |
| if (connected_) { |
| // Something happened and the mixer is no longer valid after having been |
| // initialized earlier. |
| connected_ = false; |
| - LOG(ERROR) << "Lost connection to PulseAudio"; |
| + LOG(ERROR) << "Lost connection to Mixer"; |
|
Daniel Erat
2010/12/20 22:01:12
nit: make all of the "mixer"s in these comments lo
|
| } else { |
| LOG(ERROR) << "Mixer not valid"; |
| } |
| - if ((mixer_state == PulseAudioMixer::INITIALIZING) || |
| - (mixer_state == PulseAudioMixer::SHUTTING_DOWN)) |
| + if ((mixer_state == AudioMixerBase::INITIALIZING) || |
| + (mixer_state == AudioMixerBase::SHUTTING_DOWN)) |
| return false; |
| if (reconnect_tries_ < kMaxReconnectTries) { |
| reconnect_tries_++; |
| - VLOG(1) << "Re-connecting to PulseAudio attempt " << reconnect_tries_ << "/" |
| + VLOG(1) << "Re-connecting to Mixer attempt " << reconnect_tries_ << "/" |
| << kMaxReconnectTries; |
| - mixer_.reset(new PulseAudioMixer()); |
| - connected_ = mixer_->InitSync(); |
| + |
| + connected_ = TryToConnect(false); |
| + |
| if (connected_) { |
| reconnect_tries_ = 0; |
| return true; |
| } |
| - LOG(ERROR) << "Unable to re-connect to PulseAudio"; |
| + LOG(ERROR) << "Unable to re-connect to Mixer"; |
| } |
| return false; |
| } |
| // VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us |
| // complete control over how the 0 to 100% range is mapped to actual loudness. |
| -// Volume range is from kMinVolumeDb at just above 0% to kMaxVolumeDb at 100% |
| -// with a special case at 0% which maps to kSilenceDb. |
| +// Volume range is from min_volume_db_ at just above 0% to max_volume_db_ |
| +// at 100% with a special case at 0% which maps to kSilenceDb. |
| // |
| // The mapping is confined to these two functions to make it easy to adjust and |
| // have everything else just work. The range is biased to give finer resolution |
| // in the higher volumes if kVolumeBias is less than 1.0. |
| // static |
| -double AudioHandler::VolumeDbToPercent(double volume_db) { |
| - if (volume_db < kMinVolumeDb) |
| +double AudioHandler::VolumeDbToPercent(double volume_db) const { |
| + if (volume_db < min_volume_db_) |
| return 0; |
| - return 100.0 * pow((volume_db - kMinVolumeDb) / |
| - (kMaxVolumeDb - kMinVolumeDb), 1/kVolumeBias); |
| + return 100.0 * pow((volume_db - min_volume_db_) / |
| + (max_volume_db_ - min_volume_db_), 1/kVolumeBias); |
| } |
| // static |
| -double AudioHandler::PercentToVolumeDb(double volume_percent) { |
| +double AudioHandler::PercentToVolumeDb(double volume_percent) const { |
| return pow(volume_percent / 100.0, kVolumeBias) * |
| - (kMaxVolumeDb - kMinVolumeDb) + kMinVolumeDb; |
| + (max_volume_db_ - min_volume_db_) + min_volume_db_; |
| } |
| // static |