diff options
author | rkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-10 10:55:57 +0000 |
---|---|---|
committer | rkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-10 10:55:57 +0000 |
commit | bf9fc82b8e82677ec039a6b9711c0e1aa3647a53 (patch) | |
tree | 0fae8f2317ce9db0adbec299973f676c0dea0b87 /chromeos | |
parent | 1c36fc4e54a794b9b7119b9267b215d9c58a8d5e (diff) | |
download | chromium_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.cc | 119 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_handler.h | 20 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_switch_handler.cc | 163 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_switch_handler.h | 83 | ||||
-rw-r--r-- | chromeos/chromeos.gyp | 2 |
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', |