Chromium Code Reviews| Index: chromeos/audio/cras_audio_handler.cc |
| diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc |
| index 970c78c79b8c6da55d8adaf7fffc7b1208bee378..cf4547fc6a347f9feecb79a0f7f77c68a294f57b 100644 |
| --- a/chromeos/audio/cras_audio_handler.cc |
| +++ b/chromeos/audio/cras_audio_handler.cc |
| @@ -46,14 +46,6 @@ bool IsInNodeList(uint64_t node_id, |
| return std::find(id_list.begin(), id_list.end(), node_id) != id_list.end(); |
| } |
| -bool IsNodeInTheList(uint64_t node_id, const AudioNodeList& node_list) { |
| - for (size_t i = 0; i < node_list.size(); ++i) { |
| - if (node_id == node_list[i].id) |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| } // namespace |
| CrasAudioHandler::AudioObserver::AudioObserver() { |
| @@ -301,7 +293,10 @@ void CrasAudioHandler::ChangeActiveNodes(const NodeIdList& new_active_ids) { |
| } |
| } |
| - // Adds the new active devices. |
| + // Adds the new active devices. Note that this function is used by audio |
| + // extension to manage multiple active nodes, in which case the devices |
| + // selection preference is controlled by the app, we intentionally exclude |
| + // the additional nodes from saving their device states as a result. |
| for (size_t i = 0; i < nodes_to_activate.size(); ++i) |
| AddActiveNode(nodes_to_activate[i], false); // no notification. |
| @@ -398,6 +393,15 @@ void CrasAudioHandler::SetActiveOutputNode(uint64_t node_id, bool notify) { |
| SetActiveOutputNode(node_id); |
| if (notify) |
| NotifyActiveNodeChanged(false); |
| + |
| + // Save state for all output nodes. |
| + for (AudioDeviceMap::iterator it = audio_devices_.begin(); |
| + it != audio_devices_.end(); ++it) { |
| + if (it->second.is_input) |
| + continue; |
| + audio_pref_handler_->SetDeviceState(it->second, |
| + it->second.active ? AUDIO_STATE_ACTIVE : AUDIO_STATE_INACTIVE); |
| + } |
| } |
| void CrasAudioHandler::SetActiveInputNode(uint64_t node_id, bool notify) { |
| @@ -405,6 +409,15 @@ void CrasAudioHandler::SetActiveInputNode(uint64_t node_id, bool notify) { |
| SetActiveInputNode(node_id); |
| if (notify) |
| NotifyActiveNodeChanged(true); |
| + |
| + // Save state for all input nodes. |
| + for (AudioDeviceMap::iterator it = audio_devices_.begin(); |
| + it != audio_devices_.end(); ++it) { |
| + if (!it->second.is_input) |
| + continue; |
| + audio_pref_handler_->SetDeviceState(it->second, |
| + it->second.active ? AUDIO_STATE_ACTIVE : AUDIO_STATE_INACTIVE); |
| + } |
| } |
| void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64_t device_id, |
| @@ -782,8 +795,8 @@ void CrasAudioHandler::SwitchToDevice(const AudioDevice& device, bool notify) { |
| } |
| bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes, |
| - bool is_input, |
| - AudioNodeList* new_discovered) { |
| + bool is_input, |
| + AudioDevicePriorityQueue* new_discovered) { |
| size_t num_old_devices = 0; |
| size_t num_new_devices = 0; |
| for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); |
| @@ -793,7 +806,8 @@ bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes, |
| } |
| bool new_or_changed_device = false; |
| - new_discovered->clear(); |
| + while (!new_discovered->empty()) |
| + new_discovered->pop(); |
| for (AudioNodeList::const_iterator it = new_nodes.begin(); |
| it != new_nodes.end(); ++it) { |
| if (is_input == it->is_input) { |
| @@ -802,7 +816,7 @@ bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes, |
| AudioDevice device(*it); |
| DeviceStatus status = CheckDeviceStatus(device); |
| if (status == NEW_DEVICE) |
| - new_discovered->push_back(*it); |
| + new_discovered->push(device); |
| if (status == NEW_DEVICE || status == CHANGED_DEVICE) { |
| new_or_changed_device = true; |
| } |
| @@ -848,8 +862,8 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive( |
| ++old_output_device_size; |
| } |
| - AudioNodeList hotplug_output_nodes; |
| - AudioNodeList hotplug_input_nodes; |
| + AudioDevicePriorityQueue hotplug_output_nodes; |
| + AudioDevicePriorityQueue hotplug_input_nodes; |
| bool output_devices_changed = |
| HasDeviceChange(nodes, false, &hotplug_output_nodes); |
| bool input_devices_changed = |
| @@ -900,8 +914,7 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive( |
| active_input_node_id_ = 0; |
| // If audio nodes change is caused by unplugging some non-active audio |
| - // devices, the previously set active audio device will stay active. |
| - // Otherwise, switch to a new active audio device according to their priority. |
| + // devices, we wont't change the current active audio devices. |
| if (input_devices_changed && |
| !NonActiveDeviceUnplugged(old_input_device_size, |
| new_input_device_size, |
| @@ -912,13 +925,34 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive( |
| active_input_node_id_ = 0; |
| NotifyActiveNodeChanged(true); |
| } else { |
| - // If user has hot plugged a new node, we should change to the active |
| - // device to the new node if it has the highest priority; otherwise, |
| - // we should keep the existing active node chosen by user. |
| - // For all other cases, we will choose the node with highest priority. |
| - if (!active_input_node_id_ || hotplug_input_nodes.empty() || |
| - IsNodeInTheList(input_devices_pq_.top().id, hotplug_input_nodes)) { |
| + // If there is no current active node, or, no new hot plugged node, select |
| + // the active node by their priorities. |
| + if (!active_input_node_id_ || hotplug_input_nodes.empty()) { |
| SwitchToDevice(input_devices_pq_.top(), true); |
| + } else { |
| + // If user has hot plugged any input nodes, look at the one with highest |
| + // priority (normally, there is only one hot plugged input node), and |
| + // consider switch to it depend on its last state stored in preference. |
| + AudioDeviceState last_state = |
| + audio_pref_handler_->GetDeviceState(hotplug_input_nodes.top()); |
| + switch (last_state) { |
| + case AUDIO_STATE_ACTIVE: |
|
Daniel Erat
2016/01/07 17:31:12
this should be indented two spaces beyond the prev
hychao
2016/01/11 07:02:32
Done.
|
| + // This node was plugged in before and was selected as the active one |
| + // before it was unplugged last time, switch to this device. |
| + SwitchToDevice(hotplug_input_nodes.top(), true); |
| + break; |
| + case AUDIO_STATE_NOT_AVAILABLE: |
| + // This is a new node, not plugged in before, with the highest |
| + // priority. Switch to this device. |
| + if (input_devices_pq_.top().id == hotplug_input_nodes.top().id) |
| + SwitchToDevice(hotplug_input_nodes.top(), true); |
| + break; |
| + case AUDIO_STATE_INACTIVE: |
| + // This node was NOT selected as the active one last time before it |
| + // got unplugged, so don't switch to it. |
| + default: |
| + break; |
| + } |
| } |
| } |
| } |
| @@ -926,16 +960,28 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive( |
| !NonActiveDeviceUnplugged(old_output_device_size, |
| new_output_device_size, |
| active_output_node_id_)) { |
| - // This is really unlikely to happen because all ChromeOS devices have the |
| - // internal audio output. |
| + // ditto input node logic. |
| if (output_devices_pq_.empty()) { |
| active_output_node_id_ = 0; |
| NotifyActiveNodeChanged(false); |
| } else { |
| - // ditto input node case. |
| - if (!active_output_node_id_ || hotplug_output_nodes.empty() || |
| - IsNodeInTheList(output_devices_pq_.top().id, hotplug_output_nodes)) { |
| + if (!active_output_node_id_ || hotplug_output_nodes.empty()) { |
| SwitchToDevice(output_devices_pq_.top(), true); |
| + } else { |
| + AudioDeviceState last_state = |
| + audio_pref_handler_->GetDeviceState(hotplug_output_nodes.top()); |
| + switch (last_state) { |
| + case AUDIO_STATE_ACTIVE: |
|
Daniel Erat
2016/01/07 17:31:12
same here
hychao
2016/01/11 07:02:32
Done.
|
| + SwitchToDevice(hotplug_output_nodes.top(), true); |
| + break; |
| + case AUDIO_STATE_NOT_AVAILABLE: |
| + if (output_devices_pq_.top().id == hotplug_output_nodes.top().id) |
| + SwitchToDevice(hotplug_output_nodes.top(), true); |
| + break; |
| + case AUDIO_STATE_INACTIVE: |
| + default: |
| + break; |
| + } |
| } |
| } |
| } |