Skip to content

Commit

Permalink
Implement new audio handler which talks to the new audio dbus apis, a…
Browse files Browse the repository at this point in the history
…nd adds a new AudioClientRestarted signal in CrasAudioClient.

BUG=160311,232032
TBR=sky
TBR=battre

Review URL: https://codereview.chromium.org/14314002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195067 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
jennyz@chromium.org committed Apr 19, 2013
1 parent 9eb24cf commit d7b0883
Show file tree
Hide file tree
Showing 15 changed files with 892 additions and 80 deletions.
73 changes: 29 additions & 44 deletions chrome/browser/chromeos/audio/audio_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "base/prefs/pref_service.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
#include "chromeos/audio/audio_pref_handler.h"

using std::max;
using std::min;
Expand All @@ -29,31 +30,25 @@ namespace chromeos {

namespace {

// Default value for the volume pref, as a percent in the range [0.0, 100.0].
const double kDefaultVolumePercent = 75.0;

// Default value for unmuting, as a percent in the range [0.0, 100.0].
// Used when sound is unmuted, but volume was less than kMuteThresholdPercent.
const double kDefaultUnmuteVolumePercent = 4.0;

// Volume value which should be considered as muted in range [0.0, 100.0].
const double kMuteThresholdPercent = 1.0;

// Values used for muted preference.
const int kPrefMuteOff = 0;
const int kPrefMuteOn = 1;

static AudioHandler* g_audio_handler = NULL;

} // namespace

// static
void AudioHandler::Initialize() {
void AudioHandler::Initialize(
scoped_refptr<AudioPrefHandler> audio_pref_handler) {
CHECK(!g_audio_handler);
#if defined(USE_CRAS)
g_audio_handler = new AudioHandler(new AudioMixerCras());
g_audio_handler = new AudioHandler(new AudioMixerCras(), audio_pref_handler);
#else
g_audio_handler = new AudioHandler(new AudioMixerAlsa());
g_audio_handler = new AudioHandler(new AudioMixerAlsa(), audio_pref_handler);
#endif
}

Expand All @@ -67,9 +62,11 @@ void AudioHandler::Shutdown() {
}

// static
void AudioHandler::InitializeForTesting(AudioMixer* mixer) {
void AudioHandler::InitializeForTesting(
AudioMixer* mixer,
scoped_refptr<AudioPrefHandler> audio_pref_handler) {
CHECK(!g_audio_handler);
g_audio_handler = new AudioHandler(mixer);
g_audio_handler = new AudioHandler(mixer, audio_pref_handler);
}

// static
Expand All @@ -79,18 +76,6 @@ AudioHandler* AudioHandler::GetInstance() {
return g_audio_handler;
}

// static
void AudioHandler::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDoublePref(prefs::kAudioVolumePercent,
kDefaultVolumePercent);
registry->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteOff);
// Register the prefs backing the audio muting policies.
registry->RegisterBooleanPref(prefs::kAudioOutputAllowed, true);
// This pref has moved to the media subsystem but we should verify it is there
// before we use it.
registry->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true);
}

double AudioHandler::GetVolumePercent() {
return mixer_->GetVolumePercent();
}
Expand All @@ -108,7 +93,7 @@ void AudioHandler::SetVolumePercent(double volume_percent) {

void AudioHandler::SetVolumePercentInternal(double volume_percent) {
mixer_->SetVolumePercent(volume_percent);
local_state_->SetDouble(prefs::kAudioVolumePercent, volume_percent);
audio_pref_handler_->SetOutputVolumeValue(volume_percent);
if (volume_percent != volume_percent_) {
volume_percent_ = volume_percent;
FOR_EACH_OBSERVER(VolumeObserver, volume_observers_, OnVolumeChanged());
Expand All @@ -126,8 +111,7 @@ bool AudioHandler::IsMuted() {
void AudioHandler::SetMuted(bool mute) {
if (!mixer_->IsMuteLocked()) {
mixer_->SetMuted(mute);
local_state_->SetInteger(prefs::kAudioMute,
mute ? kPrefMuteOn : kPrefMuteOff);
audio_pref_handler_->SetOutputMuteValue(mute);

if (!mute) {
if (GetVolumePercent() <= kMuteThresholdPercent) {
Expand Down Expand Up @@ -160,38 +144,39 @@ void AudioHandler::RemoveVolumeObserver(VolumeObserver* observer) {
volume_observers_.RemoveObserver(observer);
}

AudioHandler::AudioHandler(AudioMixer* mixer)
void AudioHandler::OnAudioPolicyPrefChanged() {
ApplyAudioPolicy();
}

AudioHandler::AudioHandler(AudioMixer* mixer,
scoped_refptr<AudioPrefHandler> audio_pref_handler)
: mixer_(mixer),
local_state_(g_browser_process->local_state()),
volume_percent_(0),
muted_(false) {
InitializePrefObservers();
muted_(false),
audio_pref_handler_(audio_pref_handler) {
mixer_->Init();

DCHECK(audio_pref_handler_.get());
audio_pref_handler_->AddAudioPrefObserver(this);
ApplyAudioPolicy();
// Set initial state so that notifications are not triggered.
muted_ = (local_state_->GetInteger(prefs::kAudioMute) == kPrefMuteOn);
volume_percent_ = local_state_->GetDouble(prefs::kAudioVolumePercent);
muted_ = audio_pref_handler_->GetOutputMuteValue();
volume_percent_ = audio_pref_handler->GetOutputVolumeValue();
SetMuted(muted_);
SetVolumePercentInternal(volume_percent_);
}

AudioHandler::~AudioHandler() {
mixer_.reset();
audio_pref_handler_->RemoveAudioPrefObserver(this);
audio_pref_handler_ = NULL;
};

void AudioHandler::InitializePrefObservers() {
pref_change_registrar_.Init(local_state_);
base::Closure callback = base::Bind(&AudioHandler::ApplyAudioPolicy,
base::Unretained(this));
pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback);
pref_change_registrar_.Add(prefs::kAudioCaptureAllowed, callback);
}

void AudioHandler::ApplyAudioPolicy() {
mixer_->SetMuteLocked(false);
bool muted = false;
if (local_state_->GetBoolean(prefs::kAudioOutputAllowed)) {
muted = (local_state_->GetInteger(prefs::kAudioMute) == kPrefMuteOn);
if (audio_pref_handler_->GetAudioOutputAllowedValue()) {
muted = audio_pref_handler_->GetOutputMuteValue();
mixer_->SetMuted(muted);
} else {
muted = true;
Expand All @@ -203,7 +188,7 @@ void AudioHandler::ApplyAudioPolicy() {
FOR_EACH_OBSERVER(VolumeObserver, volume_observers_, OnMuteToggled());
}
mixer_->SetCaptureMuteLocked(false);
if (local_state_->GetBoolean(prefs::kAudioCaptureAllowed)) {
if (audio_pref_handler_->GetAudioCaptureAllowedValue()) {
mixer_->SetCaptureMuted(false);
} else {
mixer_->SetCaptureMuted(true);
Expand Down
34 changes: 18 additions & 16 deletions chrome/browser/chromeos/audio/audio_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
#define CHROME_BROWSER_CHROMEOS_AUDIO_AUDIO_HANDLER_H_

#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/threading/thread.h"
#include "chromeos/audio/audio_pref_observer.h"

template <typename T> struct DefaultSingletonTraits;

Expand All @@ -20,8 +20,12 @@ class PrefService;
namespace chromeos {

class AudioMixer;
class AudioPrefHandler;

class AudioHandler {
// TODO(jennyz): crbug.com/233301.
// Retire the old AudioHandler and the old audio library code once
// the new audio dbus and handler code stabilizes.
class AudioHandler : public AudioPrefObserver {
public:
class VolumeObserver {
public:
Expand All @@ -33,19 +37,18 @@ class AudioHandler {
DISALLOW_COPY_AND_ASSIGN(VolumeObserver);
};

static void Initialize();
static void Initialize(scoped_refptr<AudioPrefHandler> audio_pref_handler);
static void Shutdown();

// Same as Initialize but using the specified audio mixer. It takes
// ownership of |mixer|.
static void InitializeForTesting(AudioMixer* mixer);
static void InitializeForTesting(
AudioMixer* mixer,
scoped_refptr<AudioPrefHandler> audio_pref_handler);

// GetInstance returns NULL if not initialized or if already shutdown.
static AudioHandler* GetInstance();

// Registers volume and mute preferences.
static void RegisterPrefs(PrefRegistrySimple* registry);

// Gets volume level in our internal 0-100% range, 0 being pure silence.
double GetVolumePercent();

Expand Down Expand Up @@ -79,31 +82,30 @@ class AudioHandler {
friend struct DefaultSingletonTraits<AudioHandler>;

// Takes ownership of |mixer|.
explicit AudioHandler(AudioMixer* mixer);
explicit AudioHandler(AudioMixer* mixer,
scoped_refptr<AudioPrefHandler> audio_pref_handler);
virtual ~AudioHandler();

// Initializes the observers for the policy prefs.
void InitializePrefObservers();

// Applies the audio muting policies whenever the user logs in or policy
// change notification is received.
void ApplyAudioPolicy();

// Sets volume to specified value and notifies observers.
void SetVolumePercentInternal(double volume_percent);

// Overriden from AudioPrefObserver.
virtual void OnAudioPolicyPrefChanged() OVERRIDE;

scoped_ptr<AudioMixer> mixer_;

ObserverList<VolumeObserver> volume_observers_;

PrefService* local_state_; // not owned

PrefChangeRegistrar pref_change_registrar_;

// Track state for triggering callbacks
double volume_percent_;
bool muted_;

scoped_refptr<AudioPrefHandler> audio_pref_handler_;

DISALLOW_COPY_AND_ASSIGN(AudioHandler);
};

Expand Down
109 changes: 109 additions & 0 deletions chrome/browser/chromeos/audio/audio_pref_handler_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/audio/audio_pref_handler_impl.h"

#include <algorithm>
#include <cmath>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"

using std::max;
using std::min;

namespace chromeos {

namespace {

// Default value for the volume pref, as a percent in the range [0.0, 100.0].
const double kDefaultVolumePercent = 75.0;

// Values used for muted preference.
const int kPrefMuteOff = 0;
const int kPrefMuteOn = 1;

} // namespace

double AudioPrefHandlerImpl::GetOutputVolumeValue() {
return local_state_->GetDouble(prefs::kAudioVolumePercent);
}

void AudioPrefHandlerImpl::SetOutputVolumeValue(double volume_percent) {
local_state_->SetDouble(prefs::kAudioVolumePercent, volume_percent);
}

bool AudioPrefHandlerImpl::GetOutputMuteValue() {
return (local_state_->GetInteger(prefs::kAudioMute) == kPrefMuteOn);
}

void AudioPrefHandlerImpl::SetOutputMuteValue(bool mute) {
local_state_->SetInteger(prefs::kAudioMute,
mute ? kPrefMuteOn : kPrefMuteOff);
}

bool AudioPrefHandlerImpl::GetAudioCaptureAllowedValue() {
return local_state_->GetBoolean(::prefs::kAudioCaptureAllowed);
}

bool AudioPrefHandlerImpl::GetAudioOutputAllowedValue() {
return local_state_->GetBoolean(prefs::kAudioOutputAllowed);
}

void AudioPrefHandlerImpl::AddAudioPrefObserver(
AudioPrefObserver* observer) {
observers_.AddObserver(observer);
}

void AudioPrefHandlerImpl::RemoveAudioPrefObserver(
AudioPrefObserver* observer) {
observers_.RemoveObserver(observer);
}

AudioPrefHandlerImpl::AudioPrefHandlerImpl(PrefService* local_state)
: local_state_(local_state) {
InitializePrefObservers();
}

AudioPrefHandlerImpl::~AudioPrefHandlerImpl() {
};

void AudioPrefHandlerImpl::InitializePrefObservers() {
pref_change_registrar_.Init(local_state_);
base::Closure callback =
base::Bind(&AudioPrefHandlerImpl::NotifyAudioPolicyChange,
base::Unretained(this));
pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback);
pref_change_registrar_.Add(::prefs::kAudioCaptureAllowed, callback);
}

void AudioPrefHandlerImpl::NotifyAudioPolicyChange() {
FOR_EACH_OBSERVER(AudioPrefObserver,
observers_,
OnAudioPolicyPrefChanged());
}

// static
void AudioPrefHandlerImpl::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDoublePref(prefs::kAudioVolumePercent,
kDefaultVolumePercent);
registry->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteOff);
// Register the prefs backing the audio muting policies.
registry->RegisterBooleanPref(prefs::kAudioOutputAllowed, true);
// This pref has moved to the media subsystem but we should verify it is there
// before we use it.
registry->RegisterBooleanPref(::prefs::kAudioCaptureAllowed, true);
}

// static
AudioPrefHandler* AudioPrefHandler::Create(PrefService* local_state) {
return new AudioPrefHandlerImpl(local_state);
}

} // namespace chromeos
Loading

0 comments on commit d7b0883

Please sign in to comment.