 Chromium Code Reviews
 Chromium Code Reviews Issue 5859003:
  Add ALSA support to volume keys  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/browser/chromeos
    
  
    Issue 5859003:
  Add ALSA support to volume keys  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/browser/chromeos| 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..cdc2d534f9f1a90d5359a4066834f3a0ff39371e 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" | 
| 
scherkus (not reviewing)
2010/12/22 22:31:58
nit: alphabetize include order
 | 
| +#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. | 
| @@ -27,10 +28,8 @@ const int kMaxReconnectTries = 4; | 
| } // namespace | 
| -// This class will set volume using PulseAudio to adjust volume and mute, and | 
| -// handles the volume level logic. | 
| - | 
| -// 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 +39,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 +95,68 @@ void AudioHandler::SetMute(bool do_mute) { | 
| mixer_->SetMute(do_mute); | 
| } | 
| +bool AudioHandler::TryToConnect(bool async) { | 
| + if (using_mixer_ == MIXER_TYPE_PULSEAUDIO) { | 
| + VLOG(1) << "Trying to connect to PulseAudio"; | 
| + mixer_.reset(new AudioMixerPulse()); | 
| + } else if (using_mixer_ == MIXER_TYPE_ALSA) { | 
| + 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; | 
| 
zhurunz
2010/12/22 22:21:26
Prefer early-return only on error cases, and retur
 
davejcool
2010/12/23 03:09:02
Fixed.
 | 
| + VLOG(1) << "Unable to reconnect to Mixer"; | 
| + } | 
| + return false; | 
| +} | 
| + | 
| +void AudioHandler::UseNextMixer() { | 
| + if (using_mixer_ == MIXER_TYPE_PULSEAUDIO) | 
| + using_mixer_ = MIXER_TYPE_ALSA; | 
| + else | 
| + using_mixer_ = MIXER_TYPE_NONE; | 
| +} | 
| + | 
| void AudioHandler::OnMixerInitialized(bool success) { | 
| connected_ = success; | 
| DVLOG(1) << "OnMixerInitialized, success = " << success; | 
| + | 
| + if (connected_) { | 
| + mixer_->GetVolumeLimits(&min_volume_db_, &max_volume_db_); | 
| 
zhurunz
2010/12/22 22:21:26
undefined mXX_volume_db_ on error?
 
davejcool
2010/12/23 03:09:02
Values are unchanged on error, but now GetVolumeLi
 | 
| + if (min_volume_db_ < kMinVolumeDb) | 
| + min_volume_db_ = kMinVolumeDb; | 
| + if (max_volume_db_ > kMaxVolumeDb) | 
| + max_volume_db_ = kMaxVolumeDb; | 
| 
zhurunz
2010/12/22 22:21:26
Suggest moving this into a utility function.
Somet
 | 
| + } else { | 
| + 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_(MIXER_TYPE_PULSEAUDIO) { | 
| + while (using_mixer_ != MIXER_TYPE_NONE) { | 
| + if (TryToConnect(true)) { | 
| + break; | 
| + } | 
| + UseNextMixer(); | 
| } | 
| } | 
| @@ -115,58 +165,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"; | 
| } 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 |