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() {
int TrayAudioDelegateChromeOs::GetActiveOutputDeviceIconId() {
chromeos::AudioDevice device;
if (!CrasAudioHandler::Get()->GetActiveOutputDevice(&device))
if (!CrasAudioHandler::Get()->GetPrimaryActiveOutputDevice(&device))
return kNoAudioDeviceIcon;
if (device.type == chromeos::AUDIO_TYPE_HEADPHONE)
......
......@@ -1122,7 +1122,7 @@ void LoginDisplayHostImpl::SetOobeProgressBarVisible(bool visible) {
void LoginDisplayHostImpl::TryToPlayStartupSound() {
if (startup_sound_played_ || login_prompt_visible_time_.is_null() ||
!CrasAudioHandler::Get()->GetActiveOutputNode()) {
!CrasAudioHandler::Get()->GetPrimaryActiveOutputNode()) {
return;
}
......
......@@ -9,8 +9,6 @@
#include "base/strings/string_number_conversions.h"
#include "chromeos/audio/audio_device.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"
using content::BrowserThread;
......@@ -137,62 +135,12 @@ void AudioServiceImpl::SetActiveDevices(const DeviceIdList& device_list) {
if (!cras_audio_handler_)
return;
// De-activate all the nodes with RemoveActive{Input/Output}Node API. This is
// 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);
}
}
cras_audio_handler_->RemoveAllActiveNodes();
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) {
chromeos::AudioDevice device;
bool found = FindDevice(GetIdFromStr(device_list[i]), &device);
if (found) {
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]);
if (FindDevice(GetIdFromStr(device_list[i]), &device))
cras_audio_handler_->AddActiveNode(device.id);
}
}
......
This diff is collapsed.
......@@ -87,7 +87,7 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Returns true if keyboard mic exists.
virtual bool HasKeyboardMic();
// Returns true if audio output is muted.
// Returns true if audio output is muted for the system.
virtual bool IsOutputMuted();
// Returns true if audio output is muted for a device.
......@@ -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.
virtual int GetInputGainPercentForDevice(uint64 device_id);
// Returns node_id of the active output node.
virtual uint64 GetActiveOutputNode() const;
// Returns node_id of the primary active output node.
virtual uint64 GetPrimaryActiveOutputNode() const;
// Returns the node_id of the active input node.
virtual uint64 GetActiveInputNode() const;
// Returns the node_id of the primary active input node.
virtual uint64 GetPrimaryActiveInputNode() const;
// Gets the audio devices back in |device_list|.
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.
virtual bool has_alternative_input() 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);
// 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);
// 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);
// 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();
// Mutes or unmutes audio output device.
......@@ -164,6 +168,22 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Activates or deactivates keyboard mic if there's one.
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.
virtual void LogErrors();
......@@ -173,6 +193,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
virtual ~CrasAudioHandler();
private:
friend class CrasAudioHandlerTest;
// CrasAudioClient::Observer overrides.
virtual void AudioClientRestarted() OVERRIDE;
virtual void NodesChanged() OVERRIDE;
......@@ -194,6 +216,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
void SetupAudioInputState();
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* GetKeyboardMic() const;
......@@ -208,6 +233,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Sets output volume of |node_id| to |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
// is set.
bool SetOutputMuteInternal(bool mute_on);
......@@ -215,6 +242,8 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
// Sets input gain of |node_id| to |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
// is set.
bool SetInputMuteInternal(bool mute_on);
......@@ -248,11 +277,15 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
void HandleGetNodesError(const std::string& error_name,
const std::string& error_msg);
// Returns true if |device| is not found in audio_devices_.
bool FoundNewDevice(const AudioDevice& device);
// Adds |node_id| into additional active nodes.
void AddAdditionalActiveNode(uint64 node_id);
// Removes |node_id| from additional active nodes.
void RemoveActiveNodeInternal(uint64 node_id);
// Returns a sanitized AudioDevice from |node|.
AudioDevice GetSanitizedAudioDevice(const AudioNode& node);
// Returns true if |device| is not found in audio_devices_, or it is found
// but changed its |active| property.
bool FoundNewOrChangedDevice(const AudioDevice& device);
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler_;
ObserverList<AudioObserver> observers_;
......
......@@ -116,13 +116,13 @@ void ShellAudioController::ActivateDevices() {
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);
DCHECK(device);
VLOG(1) << "Activating input device: " << device->ToString();
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);
DCHECK(device);
VLOG(1) << "Activating output device: " << device->ToString();
......
......@@ -97,8 +97,8 @@ TEST_F(ShellAudioControllerTest, SelectBestDevices) {
all_nodes.push_back(headphone);
all_nodes.push_back(external_mic);
audio_client_->SetAudioNodesAndNotifyObserversForTesting(all_nodes);
EXPECT_EQ(headphone.id, audio_handler_->GetActiveOutputNode());
EXPECT_EQ(external_mic.id, audio_handler_->GetActiveInputNode());
EXPECT_EQ(headphone.id, audio_handler_->GetPrimaryActiveOutputNode());
EXPECT_EQ(external_mic.id, audio_handler_->GetPrimaryActiveInputNode());
// Unplug the headphones and mic and check that we switch to the internal
// devices.
......@@ -106,16 +106,16 @@ TEST_F(ShellAudioControllerTest, SelectBestDevices) {
internal_nodes.push_back(internal_speaker);
internal_nodes.push_back(internal_mic);
audio_client_->SetAudioNodesAndNotifyObserversForTesting(internal_nodes);
EXPECT_EQ(internal_speaker.id, audio_handler_->GetActiveOutputNode());
EXPECT_EQ(internal_mic.id, audio_handler_->GetActiveInputNode());
EXPECT_EQ(internal_speaker.id, audio_handler_->GetPrimaryActiveOutputNode());
EXPECT_EQ(internal_mic.id, audio_handler_->GetPrimaryActiveInputNode());
// Switch back to the external devices. Mark the previously-activated internal
// devices as being active so CrasAudioHandler doesn't complain.
SetNodeActive(&all_nodes, internal_speaker.id, true);
SetNodeActive(&all_nodes, internal_mic.id, true);
audio_client_->SetAudioNodesAndNotifyObserversForTesting(all_nodes);
EXPECT_EQ(headphone.id, audio_handler_->GetActiveOutputNode());
EXPECT_EQ(external_mic.id, audio_handler_->GetActiveInputNode());
EXPECT_EQ(headphone.id, audio_handler_->GetPrimaryActiveOutputNode());
EXPECT_EQ(external_mic.id, audio_handler_->GetPrimaryActiveInputNode());
}
// 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