summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorrkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-10 10:55:57 +0000
committerrkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-10 10:55:57 +0000
commitbf9fc82b8e82677ec039a6b9711c0e1aa3647a53 (patch)
tree0fae8f2317ce9db0adbec299973f676c0dea0b87 /chromeos
parent1c36fc4e54a794b9b7119b9267b215d9c58a8d5e (diff)
downloadchromium_src-bf9fc82b8e82677ec039a6b9711c0e1aa3647a53.zip
chromium_src-bf9fc82b8e82677ec039a6b9711c0e1aa3647a53.tar.gz
chromium_src-bf9fc82b8e82677ec039a6b9711c0e1aa3647a53.tar.bz2
Merge the cras audio switch handler with the handler.
This CL also fixes a few bugs with handling mute. R=jennyz@chromium.org BUG=239206 TEST=Tested audio switching with both volume and mute settings. Review URL: https://chromiumcodereview.appspot.com/14915003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199453 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/audio/cras_audio_handler.cc119
-rw-r--r--chromeos/audio/cras_audio_handler.h20
-rw-r--r--chromeos/audio/cras_audio_switch_handler.cc163
-rw-r--r--chromeos/audio/cras_audio_switch_handler.h83
-rw-r--r--chromeos/chromeos.gyp2
5 files changed, 115 insertions, 272 deletions
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 7dc5132..b6a601d 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -165,6 +165,7 @@ void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) {
if (volume_percent <= kMuteThresholdPercent)
volume_percent = 0;
SetOutputVolumeInternal(volume_percent);
+
if (IsOutputMuted() && volume_percent > 0)
SetOutputMute(false);
if (!IsOutputMuted() && volume_percent == 0)
@@ -176,6 +177,7 @@ void CrasAudioHandler::SetInputGainPercent(int gain_percent) {
if (gain_percent <= kMuteThresholdPercent)
gain_percent = 0;
SetInputGainInternal(gain_percent);
+
if (IsInputMuted() && gain_percent > 0)
SetInputMute(false);
if (!IsInputMuted() && gain_percent == 0)
@@ -190,6 +192,7 @@ void CrasAudioHandler::SetOutputMute(bool mute_on) {
if (output_mute_locked_)
return;
+ audio_pref_handler_->SetMuteValue(active_output_node_id_, mute_on);
chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
SetOutputMute(mute_on);
@@ -206,6 +209,7 @@ void CrasAudioHandler::SetInputMute(bool mute_on) {
if (input_mute_locked_)
return;
+ audio_pref_handler_->SetMuteValue(active_input_node_id_, mute_on);
chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
SetInputMute(mute_on);
}
@@ -296,8 +300,7 @@ void CrasAudioHandler::OutputVolumeChanged(int volume) {
return;
output_volume_ = volume;
- audio_pref_handler_->SetVolumeGainValue(active_output_node_id_,
- output_volume_);
+ audio_pref_handler_->SetVolumeGainValue(active_output_node_id_, volume);
FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged());
}
@@ -306,7 +309,7 @@ void CrasAudioHandler::InputGainChanged(int gain) {
return;
input_gain_ = gain;
- audio_pref_handler_->SetVolumeGainValue(active_input_node_id_, input_gain_);
+ audio_pref_handler_->SetVolumeGainValue(active_input_node_id_, gain);
FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged());
}
@@ -315,8 +318,8 @@ void CrasAudioHandler::OutputMuteChanged(bool mute_on) {
return;
output_mute_on_ = mute_on;
- audio_pref_handler_->SetMuteValue(active_output_node_id_,
- mute_on);
+ // TODO(rkc,jennyz): We need to save the mute preferences here. See
+ // crbug.com/239646.
FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputMuteChanged());
}
@@ -325,8 +328,8 @@ void CrasAudioHandler::InputMuteChanged(bool mute_on) {
return;
input_mute_on_ = mute_on;
- audio_pref_handler_->SetMuteValue(active_input_node_id_,
- mute_on);
+ // TODO(rkc,jennyz): Fix this also when fixing the output mute. See
+ // crbug.com/239646.
FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputMuteChanged());
}
@@ -340,7 +343,7 @@ void CrasAudioHandler::ActiveOutputNodeChanged(uint64 node_id) {
return;
active_output_node_id_ = node_id;
- SetupAudioState();
+ SetupAudioOutputState();
FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged());
}
@@ -349,7 +352,7 @@ void CrasAudioHandler::ActiveInputNodeChanged(uint64 node_id) {
return;
active_input_node_id_ = node_id;
- SetupAudioState();
+ SetupAudioInputState();
FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged());
}
@@ -357,7 +360,7 @@ void CrasAudioHandler::OnAudioPolicyPrefChanged() {
ApplyAudioPolicy();
}
-void CrasAudioHandler::SetupAudioState() {
+void CrasAudioHandler::SetupAudioInputState() {
ApplyAudioPolicy();
// Set the initial audio state to the ones read from audio prefs.
@@ -371,6 +374,10 @@ void CrasAudioHandler::SetupAudioState() {
SetInputMute(kPrefMuteOff);
SetInputGainInternal(kDefaultVolumeGainPercent);
}
+}
+
+void CrasAudioHandler::SetupAudioOutputState() {
+ ApplyAudioPolicy();
if (active_output_node_id_) {
output_mute_on_ = audio_pref_handler_->GetMuteValue(active_output_node_id_);
@@ -416,12 +423,38 @@ void CrasAudioHandler::GetNodes() {
weak_ptr_factory_.GetWeakPtr()));
}
-void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
- bool success) {
- if (!success) {
- LOG(ERROR) << "Failed to retrieve audio nodes data";
- return;
+void CrasAudioHandler::SwitchToDevice(const AudioDevice& device) {
+ // The flow we follow is this,
+ // .) Global mute.
+ // .) Switch to active device.
+ // .) Once device is switched, set sound state for new device.
+ // We do this since during the state from when a device is plugged in or out,
+ // we are in between devices. We cannot switch to the new device with the
+ // old devices volume, since in certain situations it might be a very jarring
+ // or disturbing sound (for example, plugging out headphones, which were set
+ // to high volume, and switching to speakers, that were set to low volume).
+ // To avoid this, we mute all sound, do our switch, and then directly set
+ // the volume and mute to that of the new device. This way the user never has
+ // to hear the wrong volume for a device.
+ LOG(INFO) << "Switching active device to: " << device.ToString();
+ if (device.is_input) {
+ DBusThreadManager::Get()->GetCrasAudioClient()->SetInputMute(true);
+ DBusThreadManager::Get()->GetCrasAudioClient()->SetActiveInputNode(
+ device.id);
+ } else {
+ DBusThreadManager::Get()->GetCrasAudioClient()->SetOutputMute(true);
+ DBusThreadManager::Get()->GetCrasAudioClient()->SetActiveOutputNode(
+ device.id);
}
+}
+
+void CrasAudioHandler::UpdateDevicesAndSwitchActive(
+ const AudioNodeList& nodes) {
+ bool input_device_removed = false;
+ bool output_device_removed = false;
+
+ size_t num_previous_input_devices = input_devices_pq_.size();
+ size_t num_previous_output_devices = output_devices_pq_.size();
audio_devices_.clear();
active_input_node_id_ = 0;
@@ -429,13 +462,19 @@ void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
has_alternative_input_ = false;
has_alternative_output_ = false;
- for (size_t i = 0; i < node_list.size(); ++i) {
- if (node_list[i].is_input && node_list[i].active)
- active_input_node_id_ = node_list[i].id;
- else if (!node_list[i].is_input && node_list[i].active)
- active_output_node_id_ = node_list[i].id;
- AudioDevice device(node_list[i]);
+ while (!input_devices_pq_.empty())
+ input_devices_pq_.pop();
+ while (!output_devices_pq_.empty())
+ output_devices_pq_.pop();
+
+ for (size_t i = 0; i < nodes.size(); ++i) {
+ if (nodes[i].is_input && nodes[i].active)
+ active_input_node_id_ = nodes[i].id;
+ else if (!nodes[i].is_input && nodes[i].active)
+ active_output_node_id_ = nodes[i].id;
+ AudioDevice device(nodes[i]);
audio_devices_.push_back(device);
+
if (!has_alternative_input_ &&
device.is_input &&
device.type != AUDIO_TYPE_INTERNAL_MIC) {
@@ -445,9 +484,45 @@ void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
device.type != AUDIO_TYPE_INTERNAL_SPEAKER) {
has_alternative_output_ = true;
}
+
+ if (device.is_input)
+ input_devices_pq_.push(device);
+ else
+ output_devices_pq_.push(device);
+ }
+
+ if (num_previous_input_devices > input_devices_pq_.size())
+ input_device_removed = true;
+ if (num_previous_output_devices > output_devices_pq_.size())
+ output_device_removed = true;
+
+ // If either,
+ // .) the top input/output device is already active, or,
+ // .) an input/output device was removed but not the active device,
+ // then we don't need to switch the device, otherwise we do need to switch.
+ if (!input_devices_pq_.empty() &&
+ (!(input_devices_pq_.top().active || (input_device_removed &&
+ active_input_node_id_))))
+ SwitchToDevice(input_devices_pq_.top());
+ else
+ SetupAudioInputState();
+
+ if (!output_devices_pq_.empty() &&
+ (!(output_devices_pq_.top().active || (output_device_removed &&
+ active_output_node_id_))))
+ SwitchToDevice(output_devices_pq_.top());
+ else
+ SetupAudioOutputState();
+}
+
+void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
+ bool success) {
+ if (!success) {
+ LOG(ERROR) << "Failed to retrieve audio nodes data";
+ return;
}
- SetupAudioState();
+ UpdateDevicesAndSwitchActive(node_list);
FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged());
}
diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h
index 2d2a8af..8c6469e 100644
--- a/chromeos/audio/cras_audio_handler.h
+++ b/chromeos/audio/cras_audio_handler.h
@@ -5,6 +5,8 @@
#ifndef CHROMEOS_AUDIO_CRAS_AUDIO_HANDLER_H_
#define CHROMEOS_AUDIO_CRAS_AUDIO_HANDLER_H_
+#include <queue>
+
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
@@ -36,6 +38,10 @@ class AudioDevicesPrefHandler;
class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
public AudioPrefObserver {
public:
+ typedef std::priority_queue<AudioDevice,
+ std::vector<AudioDevice>,
+ AudioDeviceCompare> AudioDevicePriorityQueue;
+
class AudioObserver {
public:
// Called when output volume changed.
@@ -172,7 +178,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Sets up the audio device state based on audio policy and audio settings
// saved in prefs.
- void SetupAudioState();
+ void SetupAudioInputState();
+ void SetupAudioOutputState();
// Applies the audio muting policies whenever the user logs in or policy
// change notification is received.
@@ -187,6 +194,12 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Calling dbus to get nodes data.
void GetNodes();
+ // Updates the current audio nodes list and switches the active device
+ // if needed.
+ void UpdateDevicesAndSwitchActive(const AudioNodeList& nodes);
+
+ void SwitchToDevice(const AudioDevice& device);
+
// Handles dbus callback for GetNodes.
void HandleGetNodes(const chromeos::AudioNodeList& node_list, bool success);
@@ -196,7 +209,10 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Audio data and state.
AudioDeviceList audio_devices_;
- VolumeState volume_state_;
+
+ AudioDevicePriorityQueue input_devices_pq_;
+ AudioDevicePriorityQueue output_devices_pq_;
+
bool output_mute_on_;
bool input_mute_on_;
int output_volume_;
diff --git a/chromeos/audio/cras_audio_switch_handler.cc b/chromeos/audio/cras_audio_switch_handler.cc
deleted file mode 100644
index efda61e..0000000
--- a/chromeos/audio/cras_audio_switch_handler.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// 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 "chromeos/audio/cras_audio_switch_handler.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/logging.h"
-#include "chromeos/audio/audio_pref_handler.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-
-using std::max;
-using std::min;
-
-namespace chromeos {
-
-namespace {
-
-static CrasAudioSwitchHandler* g_cras_audio_handler = NULL;
-
-} // namespace
-
-// static
-void CrasAudioSwitchHandler::Initialize() {
- CHECK(!g_cras_audio_handler);
- g_cras_audio_handler = new CrasAudioSwitchHandler();
-}
-
-// static
-void CrasAudioSwitchHandler::Shutdown() {
- CHECK(g_cras_audio_handler);
- delete g_cras_audio_handler;
- g_cras_audio_handler = NULL;
-}
-
-// static
-CrasAudioSwitchHandler* CrasAudioSwitchHandler::Get() {
- CHECK(g_cras_audio_handler)
- << "CrasAudioSwitchHandler::Get() called before Initialize().";
- return g_cras_audio_handler;
-}
-
-void CrasAudioSwitchHandler::UpdateActiveDevice() {
- GetNodes();
-}
-
-CrasAudioSwitchHandler::CrasAudioSwitchHandler()
- : muted_device_id_(0),
- weak_ptr_factory_(this) {
- chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->AddObserver(this);
- GetNodes();
-}
-
-CrasAudioSwitchHandler::~CrasAudioSwitchHandler() {
- chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
- RemoveObserver(this);
-}
-
-void CrasAudioSwitchHandler::AudioClientRestarted() {
- // Get the initial audio data.
- GetNodes();
-}
-
-void CrasAudioSwitchHandler::NodesChanged() {
- // Refresh audio nodes data.
- GetNodes();
-}
-
-void CrasAudioSwitchHandler::ActiveOutputNodeChanged(uint64 node_id) {
- if (muted_device_id_ == node_id) {
- LOG(WARNING) << "Active output device switched to: " << node_id;
- muted_device_id_ = 0;
- DBusThreadManager::Get()->GetCrasAudioClient()->SetOutputMute(false);
- }
-}
-
-void CrasAudioSwitchHandler::ActiveInputNodeChanged(uint64 node_id) {
- if (muted_device_id_ == node_id) {
- LOG(WARNING) << "Active input device switched to: " << node_id;
- muted_device_id_ = 0;
- DBusThreadManager::Get()->GetCrasAudioClient()->SetInputMute(false);
- }
-}
-
-void CrasAudioSwitchHandler::GetNodes() {
- chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes(
- base::Bind(&CrasAudioSwitchHandler::HandleGetNodes,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void CrasAudioSwitchHandler::SwitchToDevice(const AudioDevice& device) {
- // Mute -> Switch active device -> (on active device changed event) Unmute.
- muted_device_id_ = device.id;
- LOG(WARNING) << "Switching active device to: " << device.ToString();
- if (device.is_input) {
- DBusThreadManager::Get()->GetCrasAudioClient()->SetInputMute(true);
- DBusThreadManager::Get()->GetCrasAudioClient()->SetActiveInputNode(
- device.id);
- } else {
- DBusThreadManager::Get()->GetCrasAudioClient()->SetOutputMute(true);
- DBusThreadManager::Get()->GetCrasAudioClient()->SetActiveOutputNode(
- device.id);
- }
-}
-
-void CrasAudioSwitchHandler::UpdateDevicesAndSwitch(
- const AudioNodeList& nodes) {
- bool input_device_removed = false;
- bool output_device_removed = false;
- bool have_active_input_device = false;
- bool have_active_output_device = false;
-
- size_t num_previous_input_devices = input_devices_.size();
- size_t num_previous_output_devices = output_devices_.size();
-
- while (!input_devices_.empty())
- input_devices_.pop();
- while (!output_devices_.empty())
- output_devices_.pop();
-
- for (size_t i = 0; i < nodes.size(); ++i) {
- AudioDevice dev(nodes[i]);
- if (dev.is_input)
- input_devices_.push(dev);
- else
- output_devices_.push(dev);
-
- if (dev.is_input && dev.active)
- have_active_input_device = true;
- if (!dev.is_input && dev.active)
- have_active_output_device = true;
- }
-
- if (num_previous_input_devices > input_devices_.size())
- input_device_removed = true;
- if (num_previous_output_devices > output_devices_.size())
- output_device_removed = true;
-
- // If either,
- // .) the top input/output device is already active, or,
- // .) an input/output device was removed but not the active device,
- // then we don't need to switch the device, otherwise we do need to switch.
- if (!input_devices_.empty() && (!(input_devices_.top().active ||
- (input_device_removed && have_active_input_device))))
- SwitchToDevice(input_devices_.top());
-
- if (!output_devices_.empty() && (!(output_devices_.top().active ||
- (output_device_removed && have_active_output_device))))
- SwitchToDevice(output_devices_.top());
-}
-
-void CrasAudioSwitchHandler::HandleGetNodes(
- const AudioNodeList& node_list, bool success) {
- if (!success) {
- LOG(ERROR) << "Failed to retrieve audio nodes data";
- return;
- }
-
- UpdateDevicesAndSwitch(node_list);
-}
-
-} // namespace chromeos
diff --git a/chromeos/audio/cras_audio_switch_handler.h b/chromeos/audio/cras_audio_switch_handler.h
deleted file mode 100644
index eb66f52..0000000
--- a/chromeos/audio/cras_audio_switch_handler.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.
-
-#ifndef CHROMEOS_AUDIO_CRAS_AUDIO_SWITCH_HANDLER_H_
-#define CHROMEOS_AUDIO_CRAS_AUDIO_SWITCH_HANDLER_H_
-
-#include <queue>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "chromeos/audio/audio_device.h"
-#include "chromeos/dbus/audio_node.h"
-#include "chromeos/dbus/cras_audio_client.h"
-
-class PrefRegistrySimple;
-class PrefService;
-
-namespace chromeos {
-
-class AudioPrefHandler;
-
-typedef std::priority_queue<AudioDevice,
- std::vector<AudioDevice>,
- AudioDeviceCompare> AudioDevicePriorityQueue;
-
-// Class which handles switching between audio devices when a new device is
-// plugged in or an active device is plugged out.
-class CHROMEOS_EXPORT CrasAudioSwitchHandler
- : public CrasAudioClient::Observer {
- public:
- // Sets the global instance. Must be called before any calls to Get().
- static void Initialize();
-
- // Destroys the global instance.
- static void Shutdown();
-
- // Gets the global instance. Initialize must be called first.
- static CrasAudioSwitchHandler* Get();
-
- void UpdateActiveDevice();
-
- private:
- explicit CrasAudioSwitchHandler();
- virtual ~CrasAudioSwitchHandler();
-
- // Overriden from CrasAudioSwitchHandler::Observer.
- virtual void AudioClientRestarted() OVERRIDE;
- virtual void NodesChanged() OVERRIDE;
- virtual void ActiveOutputNodeChanged(uint64 node_id) OVERRIDE;
- virtual void ActiveInputNodeChanged(uint64 node_id) OVERRIDE;
-
- // Sets up the initial audio device state based on audio policy and
- // audio settings saved in prefs.
- void SetupInitialAudioState();
-
- // Calling dbus to get nodes data.
- void GetNodes();
-
- // Updates the current audio nodes list and switches our active device
- // if needed.
- void UpdateDevicesAndSwitch(const AudioNodeList& nodes);
-
- void SwitchToDevice(const AudioDevice& device);
-
- // Handles dbus callback for GetNodes.
- void HandleGetNodes(const chromeos::AudioNodeList& node_list, bool success);
-
- // Audio data and state.
- AudioDevicePriorityQueue input_devices_;
- AudioDevicePriorityQueue output_devices_;
- uint64 muted_device_id_;
-
- base::WeakPtrFactory<CrasAudioSwitchHandler> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CrasAudioSwitchHandler);
-};
-
-} // namespace chromeos
-
-#endif // CHROMEOS_AUDIO_CRAS_AUDIO_SWITCH_HANDLER_H_
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 51c532a..7c47b59 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -40,8 +40,6 @@
'audio/cras_audio_handler.h',
'audio/mock_cras_audio_handler.cc',
'audio/mock_cras_audio_handler.h',
- 'audio/cras_audio_switch_handler.cc',
- 'audio/cras_audio_switch_handler.h',
'attestation/attestation_constants.cc',
'attestation/attestation_constants.h',
'attestation/attestation_flow.cc',