Commit b47947f8 authored by jennyz's avatar jennyz Committed by Commit bot

Supports multiple active input/output audio nodes in CrasAudioHandler.

BUG=402072
TBR=xiyuan,jamescook

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

Cr-Commit-Position: refs/heads/master@{#296593}
parent 756a9d59
...@@ -26,7 +26,7 @@ int TrayAudioDelegateChromeOs::GetOutputVolumeLevel() { ...@@ -26,7 +26,7 @@ int TrayAudioDelegateChromeOs::GetOutputVolumeLevel() {
int TrayAudioDelegateChromeOs::GetActiveOutputDeviceIconId() { int TrayAudioDelegateChromeOs::GetActiveOutputDeviceIconId() {
chromeos::AudioDevice device; chromeos::AudioDevice device;
if (!CrasAudioHandler::Get()->GetActiveOutputDevice(&device)) if (!CrasAudioHandler::Get()->GetPrimaryActiveOutputDevice(&device))
return kNoAudioDeviceIcon; return kNoAudioDeviceIcon;
if (device.type == chromeos::AUDIO_TYPE_HEADPHONE) if (device.type == chromeos::AUDIO_TYPE_HEADPHONE)
......
...@@ -1122,7 +1122,7 @@ void LoginDisplayHostImpl::SetOobeProgressBarVisible(bool visible) { ...@@ -1122,7 +1122,7 @@ void LoginDisplayHostImpl::SetOobeProgressBarVisible(bool visible) {
void LoginDisplayHostImpl::TryToPlayStartupSound() { void LoginDisplayHostImpl::TryToPlayStartupSound() {
if (startup_sound_played_ || login_prompt_visible_time_.is_null() || if (startup_sound_played_ || login_prompt_visible_time_.is_null() ||
!CrasAudioHandler::Get()->GetActiveOutputNode()) { !CrasAudioHandler::Get()->GetPrimaryActiveOutputNode()) {
return; return;
} }
......
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "chromeos/audio/audio_device.h" #include "chromeos/audio/audio_device.h"
#include "chromeos/audio/cras_audio_handler.h" #include "chromeos/audio/cras_audio_handler.h"
#include "chromeos/dbus/cras_audio_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
using content::BrowserThread; using content::BrowserThread;
...@@ -137,62 +135,12 @@ void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) { ...@@ -137,62 +135,12 @@ void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) {
if (!cras_audio_handler_) if (!cras_audio_handler_)
return; return;
// De-activate all the nodes with RemoveActive{Input/Output}Node API. This is cras_audio_handler_->RemoveAllActiveNodes();
// kind of hacky, but we don't know which set of nodes are active from
// CrasAudioHandler.
// TODO(rkc): Fix it in http://crbug.com/402072.
chromeos::AudioDeviceList devices;
cras_audio_handler_->GetAudioDevices(&devices);
for (size_t i = 0; i < devices.size(); ++i) {
if (devices[i].is_input) {
chromeos::DBusThreadManager::Get()
->GetCrasAudioClient()
->RemoveActiveInputNode(devices[i].id);
} else { // output
chromeos::DBusThreadManager::Get()
->GetCrasAudioClient()
->RemoveActiveOutputNode(devices[i].id);
}
}
bool input_device_set = false;
bool output_device_set = false;
std::string active_input_node_ids, active_output_node_ids;
for (size_t i = 0; i < device_list.size(); ++i) { for (size_t i = 0; i < device_list.size(); ++i) {
chromeos::AudioDevice device; chromeos::AudioDevice device;
bool found = FindDevice(GetIdFromStr(device_list[i]), &device); if (FindDevice(GetIdFromStr(device_list[i]), &device))
if (found) { cras_audio_handler_->AddActiveNode(device.id);
if (device.is_input) {
if (!input_device_set) {
cras_audio_handler_->SwitchToDevice(device);
input_device_set = true;
} else {
active_input_node_ids.push_back(device.id);
}
} else { // output device
if (!output_device_set) {
cras_audio_handler_->SwitchToDevice(device);
output_device_set = true;
} else {
active_output_node_ids.push_back(device.id);
}
}
}
}
// Once we have set our devices to active and all the inactive ones have been
// set correctly to inactive, go through our active devices again and set
// them to active using the AddActiveNode API.
// TODO(rkc):Fix this ugly hack in http://crbug.com/402072.
for (size_t i = 0; i < active_input_node_ids.size(); ++i) {
chromeos::DBusThreadManager::Get()
->GetCrasAudioClient()
->AddActiveInputNode(active_input_node_ids[i]);
}
for (size_t i = 0; i < active_output_node_ids.size(); ++i) {
chromeos::DBusThreadManager::Get()
->GetCrasAudioClient()
->AddActiveOutputNode(active_output_node_ids[i]);
} }
} }
......
This diff is collapsed.
...@@ -87,7 +87,7 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -87,7 +87,7 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Returns true if keyboard mic exists. // Returns true if keyboard mic exists.
virtual bool HasKeyboardMic(); virtual bool HasKeyboardMic();
// Returns true if audio output is muted. // Returns true if audio output is muted for the system.
virtual bool IsOutputMuted(); virtual bool IsOutputMuted();
// Returns true if audio output is muted for a device. // Returns true if audio output is muted for a device.
...@@ -119,31 +119,35 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -119,31 +119,35 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Gets volume level in 0-100% range (0 being pure silence) for a device. // Gets volume level in 0-100% range (0 being pure silence) for a device.
virtual int GetInputGainPercentForDevice(uint64 device_id); virtual int GetInputGainPercentForDevice(uint64 device_id);
// Returns node_id of the active output node. // Returns node_id of the primary active output node.
virtual uint64 GetActiveOutputNode() const; virtual uint64 GetPrimaryActiveOutputNode() const;
// Returns the node_id of the active input node. // Returns the node_id of the primary active input node.
virtual uint64 GetActiveInputNode() const; virtual uint64 GetPrimaryActiveInputNode() const;
// Gets the audio devices back in |device_list|. // Gets the audio devices back in |device_list|.
virtual void GetAudioDevices(AudioDeviceList* device_list) const; virtual void GetAudioDevices(AudioDeviceList* device_list) const;
virtual bool GetActiveOutputDevice(AudioDevice* device) const; virtual bool GetPrimaryActiveOutputDevice(AudioDevice* device) const;
// Whether there is alternative input/output audio device. // Whether there is alternative input/output audio device.
virtual bool has_alternative_input() const; virtual bool has_alternative_input() const;
virtual bool has_alternative_output() const; virtual bool has_alternative_output() const;
// Sets volume level to |volume_percent|, whose range is from 0-100%. // Sets all active output devices' volume level to |volume_percent|, whose
// range is from 0-100%.
virtual void SetOutputVolumePercent(int volume_percent); virtual void SetOutputVolumePercent(int volume_percent);
// Sets gain level to |gain_percent|, whose range is from 0-100%. // Sets all active input devices' gain level to |gain_percent|, whose range is
// from 0-100%.
virtual void SetInputGainPercent(int gain_percent); virtual void SetInputGainPercent(int gain_percent);
// Adjusts volume up (positive percentage) or down (negative percentage). // Adjusts all active output devices' volume up (positive percentage) or down
// (negative percentage).
virtual void AdjustOutputVolumeByPercent(int adjust_by_percent); virtual void AdjustOutputVolumeByPercent(int adjust_by_percent);
// Adjusts output volume to a minimum audible level if it is too low. // Adjusts all active output devices' volume to a minimum audible level if it
// is too low.
virtual void AdjustOutputVolumeToAudibleLevel(); virtual void AdjustOutputVolumeToAudibleLevel();
// Mutes or unmutes audio output device. // Mutes or unmutes audio output device.
...@@ -164,6 +168,22 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -164,6 +168,22 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Activates or deactivates keyboard mic if there's one. // Activates or deactivates keyboard mic if there's one.
virtual void SetKeyboardMicActive(bool active); virtual void SetKeyboardMicActive(bool active);
// Adds an active node.
// If there is no active node, |node_id| will be switched to become the
// primary active node. Otherwise, it will be added as an additional active
// node.
virtual void AddActiveNode(uint64 node_id);
// Removes an active audio node.
// If |node_id| is the only active input/output node, or is an additional
// active input/output node, it will be removed and becomes inactive.
// Note: It is not proper call this api to remove the primary active node
// while there are additional active nodes.
virtual void RemoveActiveNode(uint64 node_id);
// Removes all active audio nodes, including the primary active ones.
virtual void RemoveAllActiveNodes();
// Enables error logging. // Enables error logging.
virtual void LogErrors(); virtual void LogErrors();
...@@ -173,6 +193,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -173,6 +193,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
virtual ~CrasAudioHandler(); virtual ~CrasAudioHandler();
private: private:
friend class CrasAudioHandlerTest;
// CrasAudioClient::Observer overrides. // CrasAudioClient::Observer overrides.
virtual void AudioClientRestarted() OVERRIDE; virtual void AudioClientRestarted() OVERRIDE;
virtual void NodesChanged() OVERRIDE; virtual void NodesChanged() OVERRIDE;
...@@ -194,6 +216,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -194,6 +216,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
void SetupAudioInputState(); void SetupAudioInputState();
void SetupAudioOutputState(); void SetupAudioOutputState();
// Sets up the additional active audio node's state.
void SetupAdditionalActiveAudioNodeState(uint64 node_id);
const AudioDevice* GetDeviceFromId(uint64 device_id) const; const AudioDevice* GetDeviceFromId(uint64 device_id) const;
const AudioDevice* GetKeyboardMic() const; const AudioDevice* GetKeyboardMic() const;
...@@ -208,6 +233,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -208,6 +233,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Sets output volume of |node_id| to |volume|. // Sets output volume of |node_id| to |volume|.
void SetOutputNodeVolume(uint64 node_id, int volume); void SetOutputNodeVolume(uint64 node_id, int volume);
void SetOutputNodeVolumePercent(uint64 node_id, int volume_percent);
// Sets output mute state to |mute_on| internally, returns true if output mute // Sets output mute state to |mute_on| internally, returns true if output mute
// is set. // is set.
bool SetOutputMuteInternal(bool mute_on); bool SetOutputMuteInternal(bool mute_on);
...@@ -215,6 +242,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -215,6 +242,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Sets input gain of |node_id| to |gain|. // Sets input gain of |node_id| to |gain|.
void SetInputNodeGain(uint64 node_id, int gain); void SetInputNodeGain(uint64 node_id, int gain);
void SetInputNodeGainPercent(uint64 node_id, int gain_percent);
// Sets input mute state to |mute_on| internally, returns true if input mute // Sets input mute state to |mute_on| internally, returns true if input mute
// is set. // is set.
bool SetInputMuteInternal(bool mute_on); bool SetInputMuteInternal(bool mute_on);
...@@ -248,11 +277,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -248,11 +277,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
void HandleGetNodesError(const std::string& error_name, void HandleGetNodesError(const std::string& error_name,
const std::string& error_msg); const std::string& error_msg);
// Returns true if |device| is not found in audio_devices_. // Adds |node_id| into additional active nodes.
bool FoundNewDevice(const AudioDevice& device); void AddAdditionalActiveNode(uint64 node_id);
// Removes |node_id| from additional active nodes.
void RemoveActiveNodeInternal(uint64 node_id);
// Returns a sanitized AudioDevice from |node|. // Returns true if |device| is not found in audio_devices_, or it is found
AudioDevice GetSanitizedAudioDevice(const AudioNode& node); // but changed its |active| property.
bool FoundNewOrChangedDevice(const AudioDevice& device);
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler_; scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler_;
ObserverList<AudioObserver> observers_; ObserverList<AudioObserver> observers_;
......
...@@ -116,13 +116,13 @@ void ShellAudioController::ActivateDevices() { ...@@ -116,13 +116,13 @@ void ShellAudioController::ActivateDevices() {
best_output = it->id; best_output = it->id;
} }
if (best_input && best_input != handler->GetActiveInputNode()) { if (best_input && best_input != handler->GetPrimaryActiveInputNode()) {
const chromeos::AudioDevice* device = GetDevice(devices, best_input); const chromeos::AudioDevice* device = GetDevice(devices, best_input);
DCHECK(device); DCHECK(device);
VLOG(1) << "Activating input device: " << device->ToString(); VLOG(1) << "Activating input device: " << device->ToString();
handler->SwitchToDevice(*device); handler->SwitchToDevice(*device);
} }
if (best_output && best_output != handler->GetActiveOutputNode()) { if (best_output && best_output != handler->GetPrimaryActiveOutputNode()) {
const chromeos::AudioDevice* device = GetDevice(devices, best_output); const chromeos::AudioDevice* device = GetDevice(devices, best_output);
DCHECK(device); DCHECK(device);
VLOG(1) << "Activating output device: " << device->ToString(); VLOG(1) << "Activating output device: " << device->ToString();
......
...@@ -97,8 +97,8 @@ TEST_F(ShellAudioControllerTest, SelectBestDevices) { ...@@ -97,8 +97,8 @@ TEST_F(ShellAudioControllerTest, SelectBestDevices) {
all_nodes.push_back(headphone); all_nodes.push_back(headphone);
all_nodes.push_back(external_mic); all_nodes.push_back(external_mic);
audio_client_->SetAudioNodesAndNotifyObserversForTesting(all_nodes); audio_client_->SetAudioNodesAndNotifyObserversForTesting(all_nodes);
EXPECT_EQ(headphone.id, audio_handler_->GetActiveOutputNode()); EXPECT_EQ(headphone.id, audio_handler_->GetPrimaryActiveOutputNode());
EXPECT_EQ(external_mic.id, audio_handler_->GetActiveInputNode()); EXPECT_EQ(external_mic.id, audio_handler_->GetPrimaryActiveInputNode());
// Unplug the headphones and mic and check that we switch to the internal // Unplug the headphones and mic and check that we switch to the internal
// devices. // devices.
...@@ -106,16 +106,16 @@ TEST_F(ShellAudioControllerTest, SelectBestDevices) { ...@@ -106,16 +106,16 @@ TEST_F(ShellAudioControllerTest, SelectBestDevices) {
internal_nodes.push_back(internal_speaker); internal_nodes.push_back(internal_speaker);
internal_nodes.push_back(internal_mic); internal_nodes.push_back(internal_mic);
audio_client_->SetAudioNodesAndNotifyObserversForTesting(internal_nodes); audio_client_->SetAudioNodesAndNotifyObserversForTesting(internal_nodes);
EXPECT_EQ(internal_speaker.id, audio_handler_->GetActiveOutputNode()); EXPECT_EQ(internal_speaker.id, audio_handler_->GetPrimaryActiveOutputNode());
EXPECT_EQ(internal_mic.id, audio_handler_->GetActiveInputNode()); EXPECT_EQ(internal_mic.id, audio_handler_->GetPrimaryActiveInputNode());
// Switch back to the external devices. Mark the previously-activated internal // Switch back to the external devices. Mark the previously-activated internal
// devices as being active so CrasAudioHandler doesn't complain. // devices as being active so CrasAudioHandler doesn't complain.
SetNodeActive(&all_nodes, internal_speaker.id, true); SetNodeActive(&all_nodes, internal_speaker.id, true);
SetNodeActive(&all_nodes, internal_mic.id, true); SetNodeActive(&all_nodes, internal_mic.id, true);
audio_client_->SetAudioNodesAndNotifyObserversForTesting(all_nodes); audio_client_->SetAudioNodesAndNotifyObserversForTesting(all_nodes);
EXPECT_EQ(headphone.id, audio_handler_->GetActiveOutputNode()); EXPECT_EQ(headphone.id, audio_handler_->GetPrimaryActiveOutputNode());
EXPECT_EQ(external_mic.id, audio_handler_->GetActiveInputNode()); EXPECT_EQ(external_mic.id, audio_handler_->GetPrimaryActiveInputNode());
} }
// Tests that active audio devices are unmuted and set to 100% volume. // Tests that active audio devices are unmuted and set to 100% volume.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment