Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: chromeos/audio/cras_audio_handler.cc

Issue 596603002: Supports multiple active input/output audio nodes in CrasAudioHandler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove unused function. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/audio/cras_audio_handler.h ('k') | chromeos/audio/cras_audio_handler_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromeos/audio/cras_audio_handler.cc
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc
index 1907190f0ba0e52075ae06e254b6ce3cb27aaead..c6453118b4c393381d38ddf2489b37e0845530f4 100644
--- a/chromeos/audio/cras_audio_handler.cc
+++ b/chromeos/audio/cras_audio_handler.cc
@@ -170,11 +170,11 @@ int CrasAudioHandler::GetInputGainPercentForDevice(uint64 device_id) {
}
}
-uint64 CrasAudioHandler::GetActiveOutputNode() const {
+uint64 CrasAudioHandler::GetPrimaryActiveOutputNode() const {
return active_output_node_id_;
}
-uint64 CrasAudioHandler::GetActiveInputNode() const {
+uint64 CrasAudioHandler::GetPrimaryActiveInputNode() const {
return active_input_node_id_;
}
@@ -185,7 +185,7 @@ void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const {
device_list->push_back(it->second);
}
-bool CrasAudioHandler::GetActiveOutputDevice(AudioDevice* device) const {
+bool CrasAudioHandler::GetPrimaryActiveOutputDevice(AudioDevice* device) const {
const AudioDevice* active_device = GetDeviceFromId(active_output_node_id_);
if (!active_device || !device)
return false;
@@ -197,12 +197,59 @@ void CrasAudioHandler::SetKeyboardMicActive(bool active) {
const AudioDevice* keyboard_mic = GetKeyboardMic();
if (!keyboard_mic)
return;
- if (active) {
- chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
- AddActiveInputNode(keyboard_mic->id);
- } else {
- chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
- RemoveActiveInputNode(keyboard_mic->id);
+ // Keyboard mic is invisible to chromeos users. It is always added or removed
+ // as additional active node.
+ DCHECK(active_input_node_id_ && active_input_node_id_ != keyboard_mic->id);
+ if (active)
+ AddActiveNode(keyboard_mic->id);
+ else
+ RemoveActiveNode(keyboard_mic->id);
+}
+
+void CrasAudioHandler::AddActiveNode(uint64 node_id) {
+ const AudioDevice* device = GetDeviceFromId(node_id);
+ if (!device) {
+ VLOG(1) << "AddActiveInputNode: Cannot find device id="
+ << "0x" << std::hex << node_id;
+ return;
+ }
+
+ // If there is no primary active device, set |node_id| to primary active node.
+ if ((device->is_input && !active_input_node_id_) ||
+ (!device->is_input && !active_output_node_id_)) {
+ SwitchToDevice(*device);
+ return;
+ }
+ AddAdditionalActiveNode(node_id);
+}
+
+void CrasAudioHandler::RemoveActiveNode(uint64 node_id) {
+ const AudioDevice* device = GetDeviceFromId(node_id);
+ if (!device) {
+ VLOG(1) << "RemoveActiveInputNode: Cannot find device id="
+ << "0x" << std::hex << node_id;
+ return;
+ }
+
+ // We do NOT allow to remove the primary active node.
+ if (device->is_input && device->id == active_input_node_id_) {
+ VLOG(1) << "Cannot remove the primary active input node: "
+ << "0x" << std::hex << node_id;
+ return;
+ }
+ if (!device->is_input && device->id == active_output_node_id_) {
+ VLOG(1) << "Cannot remove the primary active output node: "
+ << "0x" << std::hex << node_id;
+ return;
+ }
+ RemoveActiveNodeInternal(node_id);
+}
+
+void CrasAudioHandler::RemoveAllActiveNodes() {
+ for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
+ it != audio_devices_.end();
+ ++it) {
+ RemoveActiveNodeInternal(it->second.id);
}
}
@@ -215,29 +262,26 @@ bool CrasAudioHandler::has_alternative_output() const {
}
void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) {
- volume_percent = min(max(volume_percent, 0), 100);
- if (volume_percent <= kMuteThresholdPercent)
- volume_percent = 0;
- output_volume_ = volume_percent;
-
- if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_))
- audio_pref_handler_->SetVolumeGainValue(*device, output_volume_);
-
- SetOutputNodeVolume(active_output_node_id_, output_volume_);
- FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged());
+ // Set all active devices to the same volume.
+ for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
+ it != audio_devices_.end();
+ it++) {
+ const AudioDevice& device = it->second;
+ if (!device.is_input && device.active)
+ SetOutputNodeVolumePercent(device.id, volume_percent);
+ }
}
// TODO: Rename the 'Percent' to something more meaningful.
void CrasAudioHandler::SetInputGainPercent(int gain_percent) {
- // NOTE: We do not sanitize input gain values since the range is completely
- // dependent on the device.
- input_gain_ = gain_percent;
-
- if (const AudioDevice* device = GetDeviceFromId(active_input_node_id_))
- audio_pref_handler_->SetVolumeGainValue(*device, input_gain_);
-
- SetInputNodeGain(active_input_node_id_, input_gain_);
- FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged());
+ // TODO(jennyz): Should we set all input devices' gain to the same level?
+ for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
+ it != audio_devices_.end();
+ it++) {
+ const AudioDevice& device = it->second;
+ if (device.is_input && device.active)
+ SetInputNodeGainPercent(active_input_node_id_, gain_percent);
+ }
}
void CrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) {
@@ -248,9 +292,14 @@ void CrasAudioHandler::SetOutputMute(bool mute_on) {
if (!SetOutputMuteInternal(mute_on))
return;
- if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_)) {
- DCHECK(!device->is_input);
- audio_pref_handler_->SetMuteValue(*device, output_mute_on_);
+ // Save the mute state for all active output audio devices.
+ for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
+ it != audio_devices_.end();
+ it++) {
+ const AudioDevice& device = it->second;
+ if (!device.is_input && device.active) {
+ audio_pref_handler_->SetMuteValue(device, output_mute_on_);
+ }
}
FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputMuteChanged());
@@ -285,22 +334,14 @@ void CrasAudioHandler::SetActiveInputNode(uint64 node_id) {
void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64 device_id,
int value) {
- if (device_id == active_output_node_id_) {
- SetOutputVolumePercent(value);
- return;
- } else if (device_id == active_input_node_id_) {
- SetInputGainPercent(value);
+ const AudioDevice* device = GetDeviceFromId(device_id);
+ if (!device)
return;
- }
- if (const AudioDevice* device = GetDeviceFromId(device_id)) {
- if (!device->is_input) {
- value = min(max(value, 0), 100);
- if (value <= kMuteThresholdPercent)
- value = 0;
- }
- audio_pref_handler_->SetVolumeGainValue(*device, value);
- }
+ if (device->is_input)
+ SetInputNodeGainPercent(device_id, value);
+ else
+ SetOutputNodeVolumePercent(device_id, value);
}
void CrasAudioHandler::SetMuteForDevice(uint64 device_id, bool mute_on) {
@@ -470,6 +511,29 @@ void CrasAudioHandler::SetupAudioOutputState() {
SetOutputNodeVolume(active_output_node_id_, output_volume_);
}
+// This sets up the state of an additional active node.
+void CrasAudioHandler::SetupAdditionalActiveAudioNodeState(uint64 node_id) {
+ const AudioDevice* device = GetDeviceFromId(node_id);
+ if (!device) {
+ VLOG(1) << "Can't set up audio state for unknown device id ="
+ << "0x" << std::hex << node_id;
+ return;
+ }
+
+ DCHECK(node_id != active_output_node_id_ && node_id != active_input_node_id_);
+
+ // Note: The mute state is a system wide state, we don't set mute per device,
+ // but just keep the mute state consistent for the active node in prefs.
+ // The output volume should be set to the same value for all active output
+ // devices. For input devices, we don't restore their gain value so far.
+ // TODO(jennyz): crbug.com/417418, track the status for the decison if
+ // we should persist input gain value in prefs.
+ if (!device->is_input) {
+ audio_pref_handler_->SetMuteValue(*device, IsOutputMuted());
+ SetOutputNodeVolumePercent(node_id, GetOutputVolumePercent());
+ }
+}
+
void CrasAudioHandler::InitializeAudioState() {
ApplyAudioPolicy();
GetNodes();
@@ -506,6 +570,26 @@ void CrasAudioHandler::SetOutputNodeVolume(uint64 node_id, int volume) {
SetOutputNodeVolume(node_id, volume);
}
+void CrasAudioHandler::SetOutputNodeVolumePercent(uint64 node_id,
+ int volume_percent) {
+ const AudioDevice* device = this->GetDeviceFromId(node_id);
+ if (!device || device->is_input)
+ return;
+
+ volume_percent = min(max(volume_percent, 0), 100);
+ if (volume_percent <= kMuteThresholdPercent)
+ volume_percent = 0;
+ if (node_id == active_output_node_id_)
+ output_volume_ = volume_percent;
+
+ audio_pref_handler_->SetVolumeGainValue(*device, volume_percent);
+
+ if (device->active) {
+ SetOutputNodeVolume(node_id, volume_percent);
+ FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged());
+ }
+}
+
bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) {
if (output_mute_locked_)
return false;
@@ -521,12 +605,29 @@ void CrasAudioHandler::SetInputNodeGain(uint64 node_id, int gain) {
SetInputNodeGain(node_id, gain);
}
+void CrasAudioHandler::SetInputNodeGainPercent(uint64 node_id,
+ int gain_percent) {
+ const AudioDevice* device = GetDeviceFromId(node_id);
+ if (!device || !device->is_input)
+ return;
+
+ // NOTE: We do not sanitize input gain values since the range is completely
+ // dependent on the device.
+ if (active_input_node_id_ == node_id)
+ input_gain_ = gain_percent;
+
+ audio_pref_handler_->SetVolumeGainValue(*device, gain_percent);
+
+ if (device->active) {
+ SetInputNodeGain(node_id, gain_percent);
+ FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged());
+ }
+}
+
bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) {
if (input_mute_locked_)
return false;
- VLOG(1) << "SetInputMuteInternal sets active input device id="
- << "0x" << std::hex << active_input_node_id_ << " mute=" << mute_on;
input_mute_on_ = mute_on;
chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
SetInputMute(mute_on);
@@ -604,14 +705,14 @@ bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
++num_new_devices;
// Look to see if the new device not in the old device list.
AudioDevice device(*it);
- if (FoundNewDevice(device))
+ if (FoundNewOrChangedDevice(device))
return true;
}
}
return num_old_devices != num_new_devices;
}
-bool CrasAudioHandler::FoundNewDevice(const AudioDevice& device) {
+bool CrasAudioHandler::FoundNewOrChangedDevice(const AudioDevice& device) {
const AudioDevice* device_found = GetDeviceFromId(device.id);
if (!device_found)
return true;
@@ -621,51 +722,11 @@ bool CrasAudioHandler::FoundNewDevice(const AudioDevice& device) {
<< " new device: " << device.ToString()
<< " old device: " << device_found->ToString();
return true;
+ } else if (device.active != device_found->active) {
+ return true;
}
- return false;
-}
-// Sanitize the audio node data. When a device is plugged in or unplugged, there
-// should be only one NodesChanged signal from cras. However, we've observed
-// the case that multiple NodesChanged signals being sent from cras. After the
-// first NodesChanged being processed, chrome sets the active node properly.
-// However, the NodesChanged received after the first one, can return stale
-// nodes data in GetNodes call, the staled nodes data does not reflect the
-// latest active node state. Since active audio node should only be set by
-// chrome, the inconsistent data from cras could be the result of stale data
-// described above and sanitized.
-AudioDevice CrasAudioHandler::GetSanitizedAudioDevice(const AudioNode& node) {
- AudioDevice device(node);
- if (device.is_input) {
- if (device.active && device.id != active_input_node_id_) {
- LOG(WARNING) << "Stale audio device data, should not be active: "
- << " device = " << device.ToString()
- << " current active input node id = 0x" << std::hex
- << active_input_node_id_;
- device.active = false;
- } else if (device.id == active_input_node_id_ && !device.active) {
- LOG(WARNING) << "Stale audio device data, should be active:"
- << " device = " << device.ToString()
- << " current active input node id = 0x" << std::hex
- << active_input_node_id_;
- device.active = true;
- }
- } else {
- if (device.active && device.id != active_output_node_id_) {
- LOG(WARNING) << "Stale audio device data, should not be active: "
- << " device = " << device.ToString()
- << " current active output node id = 0x" << std::hex
- << active_output_node_id_;
- device.active = false;
- } else if (device.id == active_output_node_id_ && !device.active) {
- LOG(WARNING) << "Stale audio device data, should be active:"
- << " device = " << device.ToString()
- << " current active output node id = 0x" << std::hex
- << active_output_node_id_;
- device.active = true;
- }
- }
- return device;
+ return false;
}
void CrasAudioHandler::UpdateDevicesAndSwitchActive(
@@ -683,7 +744,7 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive(
output_devices_pq_.pop();
for (size_t i = 0; i < nodes.size(); ++i) {
- AudioDevice device = GetSanitizedAudioDevice(nodes[i]);
+ AudioDevice device(nodes[i]);
audio_devices_[device.id] = device;
if (!has_alternative_input_ &&
@@ -737,4 +798,57 @@ void CrasAudioHandler::HandleGetNodesError(const std::string& error_name,
LOG_IF(ERROR, log_errors_) << "Failed to call GetNodes: "
<< error_name << ": " << error_msg;
}
+
+void CrasAudioHandler::AddAdditionalActiveNode(uint64 node_id) {
+ const AudioDevice* device = GetDeviceFromId(node_id);
+ if (!device) {
+ VLOG(1) << "AddActiveInputNode: Cannot find device id="
+ << "0x" << std::hex << node_id;
+ return;
+ }
+
+ audio_devices_[node_id].active = true;
+ SetupAdditionalActiveAudioNodeState(node_id);
+
+ if (device->is_input) {
+ DCHECK(node_id != active_input_node_id_);
+ chromeos::DBusThreadManager::Get()
+ ->GetCrasAudioClient()
+ ->AddActiveInputNode(node_id);
+ FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged());
+ } else {
+ DCHECK(node_id != active_output_node_id_);
+ chromeos::DBusThreadManager::Get()
+ ->GetCrasAudioClient()
+ ->AddActiveOutputNode(node_id);
+ FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged());
+ }
+}
+
+void CrasAudioHandler::RemoveActiveNodeInternal(uint64 node_id) {
+ const AudioDevice* device = GetDeviceFromId(node_id);
+ if (!device) {
+ VLOG(1) << "RemoveActiveInputNode: Cannot find device id="
+ << "0x" << std::hex << node_id;
+ return;
+ }
+
+ audio_devices_[node_id].active = false;
+ if (device->is_input) {
+ if (node_id == active_input_node_id_)
+ active_input_node_id_ = 0;
+ chromeos::DBusThreadManager::Get()
+ ->GetCrasAudioClient()
+ ->RemoveActiveInputNode(node_id);
+ FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged());
+ } else {
+ if (node_id == active_output_node_id_)
+ active_output_node_id_ = 0;
+ chromeos::DBusThreadManager::Get()
+ ->GetCrasAudioClient()
+ ->RemoveActiveOutputNode(node_id);
+ }
+ FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged());
+}
+
} // namespace chromeos
« no previous file with comments | « chromeos/audio/cras_audio_handler.h ('k') | chromeos/audio/cras_audio_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698