Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5479)

Unified Diff: chrome/browser/chromeos/audio_mixer_alsa.cc

Issue 6118006: Save/Restore ALSA volume/mute (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/browser/chromeos
Patch Set: Fixed mute not set case Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/chromeos/audio_mixer_alsa.h ('k') | chrome/browser/prefs/browser_prefs.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/chromeos/audio_mixer_alsa.cc
diff --git a/chrome/browser/chromeos/audio_mixer_alsa.cc b/chrome/browser/chromeos/audio_mixer_alsa.cc
index 7f96fa4f2cd9daaa67abbc0bdc61c63940f78256..1dcc9643f030b575d2e0fc96e28f322e9c30bb09 100644
--- a/chrome/browser/chromeos/audio_mixer_alsa.cc
+++ b/chrome/browser/chromeos/audio_mixer_alsa.cc
@@ -8,6 +8,10 @@
#include "base/logging.h"
#include "base/task.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
namespace chromeos {
@@ -19,8 +23,6 @@ namespace chromeos {
// adjusting that as well. If the PCM element has more volume steps, it allows
// for finer granularity in the total volume.
-// TODO(davej): Serialize volume/mute to preserve settings when restarting.
-
typedef long alsa_long_t; // 'long' is required for ALSA API calls.
namespace {
@@ -29,6 +31,10 @@ const char* kMasterVolume = "Master";
const char* kPCMVolume = "PCM";
const double kDefaultMinVolume = -90.0;
const double kDefaultMaxVolume = 0.0;
+const double kPrefVolumeInvalid = -999.0;
+const int kPrefMuteOff = 0;
+const int kPrefMuteOn = 1;
+const int kPrefMuteInvalid = 2;
} // namespace
@@ -57,8 +63,9 @@ void AudioMixerAlsa::Init(InitDoneCallback* callback) {
delete callback;
return;
}
+ InitPrefs();
- // Post the task of starting up, which can block for 200-500ms,
+ // Post the task of starting up, which may block on the order of ms,
// so best not to do it on the caller's thread.
thread_->message_loop()->PostTask(FROM_HERE,
NewRunnableMethod(this, &AudioMixerAlsa::DoInit, callback));
@@ -67,6 +74,7 @@ void AudioMixerAlsa::Init(InitDoneCallback* callback) {
bool AudioMixerAlsa::InitSync() {
if (!InitThread())
return false;
+ InitPrefs();
return InitializeAlsaMixer();
}
@@ -93,7 +101,10 @@ void AudioMixerAlsa::SetVolumeDb(double vol_db) {
AutoLock lock(mixer_state_lock_);
if (mixer_state_ != READY)
return;
+ if (vol_db < kSilenceDb)
+ vol_db = kSilenceDb;
DoSetVolumeDb_Locked(vol_db);
+ volume_pref_.SetValue(vol_db);
}
bool AudioMixerAlsa::IsMute() const {
@@ -103,6 +114,12 @@ bool AudioMixerAlsa::IsMute() const {
return GetElementMuted_Locked(elem_master_);
}
+// To indicate the volume is not valid yet, a very low volume value is stored.
+// We compare against a slightly higher value in case of rounding errors.
+static bool PrefVolumeValid(double volume) {
+ return (volume > kPrefVolumeInvalid + 0.1);
+}
+
void AudioMixerAlsa::SetMute(bool mute) {
AutoLock lock(mixer_state_lock_);
if (mixer_state_ != READY)
@@ -111,8 +128,9 @@ void AudioMixerAlsa::SetMute(bool mute) {
// Set volume to minimum on mute, since switching the element off does not
// always mute as it should.
- // TODO(davej): Setting volume to minimum can be removed once switching the
- // element off can be guaranteed to work.
+ // TODO(davej): Remove save_volume_ and setting volume to minimum if
+ // switching the element off can be guaranteed to mute it. Currently mute
+ // is done by setting the volume to min_volume_.
bool old_value = GetElementMuted_Locked(elem_master_);
@@ -128,6 +146,7 @@ void AudioMixerAlsa::SetMute(bool mute) {
SetElementMuted_Locked(elem_master_, mute);
if (elem_pcm_)
SetElementMuted_Locked(elem_pcm_, mute);
+ mute_pref_.SetValue(mute ? kPrefMuteOn : kPrefMuteOff);
}
AudioMixer::State AudioMixerAlsa::GetState() const {
@@ -138,12 +157,26 @@ AudioMixer::State AudioMixerAlsa::GetState() const {
return mixer_state_;
}
+// static
+void AudioMixerAlsa::RegisterPrefs(PrefService* local_state) {
+ if (!local_state->FindPreference(prefs::kAudioVolume))
+ local_state->RegisterRealPref(prefs::kAudioVolume, kPrefVolumeInvalid);
+ if (!local_state->FindPreference(prefs::kAudioMute))
+ local_state->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteInvalid);
+}
+
////////////////////////////////////////////////////////////////////////////////
// Private functions follow
void AudioMixerAlsa::DoInit(InitDoneCallback* callback) {
bool success = InitializeAlsaMixer();
+ if (success) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &AudioMixerAlsa::RestoreVolumeMuteOnUIThread));
+ }
+
if (callback) {
callback->Run(success);
delete callback;
@@ -168,6 +201,13 @@ bool AudioMixerAlsa::InitThread() {
return true;
}
+void AudioMixerAlsa::InitPrefs() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ PrefService* prefs = g_browser_process->local_state();
+ volume_pref_.Init(prefs::kAudioVolume, prefs, NULL);
+ mute_pref_.Init(prefs::kAudioMute, prefs, NULL);
+}
+
bool AudioMixerAlsa::InitializeAlsaMixer() {
AutoLock lock(mixer_state_lock_);
if (mixer_state_ != INITIALIZING)
@@ -241,6 +281,42 @@ void AudioMixerAlsa::FreeAlsaMixer() {
}
}
+void AudioMixerAlsa::DoSetVolumeMute(double pref_volume, int pref_mute) {
+ AutoLock lock(mixer_state_lock_);
+ if (mixer_state_ != READY)
+ return;
+
+ // If volume or mute are invalid, set them now to the current actual values.
+ if (!PrefVolumeValid(pref_volume))
+ pref_volume = DoGetVolumeDb_Locked();
+ bool mute;
+ if (pref_mute == kPrefMuteInvalid)
+ mute = GetElementMuted_Locked(elem_master_);
+ else
+ mute = (pref_mute == kPrefMuteOn) ? true : false;
+
+ VLOG(1) << "Setting volume to " << pref_volume << " and mute to " << mute;
+
+ if (mute) {
+ save_volume_ = pref_volume;
+ DoSetVolumeDb_Locked(min_volume_);
+ } else if (pref_mute == kPrefMuteOff) {
+ DoSetVolumeDb_Locked(pref_volume);
+ }
+
+ SetElementMuted_Locked(elem_master_, mute);
+ if (elem_pcm_)
+ SetElementMuted_Locked(elem_pcm_, mute);
+}
+
+void AudioMixerAlsa::RestoreVolumeMuteOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // This happens during init, so set the volume off the UI thread.
+ thread_->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &AudioMixerAlsa::DoSetVolumeMute,
+ volume_pref_.GetValue(), mute_pref_.GetValue()));
+}
+
double AudioMixerAlsa::DoGetVolumeDb_Locked() const {
double vol_total = 0.0;
GetElementVolume_Locked(elem_master_, &vol_total);
@@ -258,7 +334,6 @@ void AudioMixerAlsa::DoSetVolumeDb_Locked(double vol_db) {
// If a PCM volume slider exists, then first set the Master volume to the
// nearest volume >= requested volume, then adjust PCM volume down to get
// closer to the requested volume.
-
if (elem_pcm_) {
SetElementVolume_Locked(elem_master_, vol_db, &actual_vol, 0.9999f);
SetElementVolume_Locked(elem_pcm_, vol_db - actual_vol, NULL, 0.5f);
@@ -273,7 +348,7 @@ snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName_Locked(
snd_mixer_selem_id_t* sid;
// Using id_malloc/id_free API instead of id_alloca since the latter gives the
- // warning: the address of 'sid' will always evaluate as 'true'
+ // warning: the address of 'sid' will always evaluate as 'true'.
if (snd_mixer_selem_id_malloc(&sid))
return NULL;
« no previous file with comments | « chrome/browser/chromeos/audio_mixer_alsa.h ('k') | chrome/browser/prefs/browser_prefs.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698