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

Side by Side Diff: chromeos/audio/cras_audio_handler.cc

Issue 872303003: Do not re-select active device if a lower priority device is hotplugged in and user has already sel… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/audio/cras_audio_handler.h" 5 #include "chromeos/audio/cras_audio_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 21 matching lines...) Expand all
32 32
33 bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) { 33 bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) {
34 return a.id == b.id && a.is_input == b.is_input && a.type == b.type 34 return a.id == b.id && a.is_input == b.is_input && a.type == b.type
35 && a.device_name == b.device_name; 35 && a.device_name == b.device_name;
36 } 36 }
37 37
38 bool IsInNodeList(uint64 node_id, const CrasAudioHandler::NodeIdList& id_list) { 38 bool IsInNodeList(uint64 node_id, const CrasAudioHandler::NodeIdList& id_list) {
39 return std::find(id_list.begin(), id_list.end(), node_id) != id_list.end(); 39 return std::find(id_list.begin(), id_list.end(), node_id) != id_list.end();
40 } 40 }
41 41
42 bool IsNodeInTheList(uint64 node_id, const AudioNodeList& node_list) {
43 for (size_t i = 0; i < node_list.size(); ++i) {
44 if (node_id == node_list[i].id)
45 return true;
46 }
47 return false;
48 }
49
42 } // namespace 50 } // namespace
43 51
44 CrasAudioHandler::AudioObserver::AudioObserver() { 52 CrasAudioHandler::AudioObserver::AudioObserver() {
45 } 53 }
46 54
47 CrasAudioHandler::AudioObserver::~AudioObserver() { 55 CrasAudioHandler::AudioObserver::~AudioObserver() {
48 } 56 }
49 57
50 void CrasAudioHandler::AudioObserver::OnOutputVolumeChanged() { 58 void CrasAudioHandler::AudioObserver::OnOutputVolumeChanged() {
51 } 59 }
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 SetActiveInputNode(active_input_node_id_, notify); 729 SetActiveInputNode(active_input_node_id_, notify);
722 } else { 730 } else {
723 if (!ChangeActiveDevice(device, &active_output_node_id_)) 731 if (!ChangeActiveDevice(device, &active_output_node_id_))
724 return; 732 return;
725 SetupAudioOutputState(); 733 SetupAudioOutputState();
726 SetActiveOutputNode(active_output_node_id_, notify); 734 SetActiveOutputNode(active_output_node_id_, notify);
727 } 735 }
728 } 736 }
729 737
730 bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes, 738 bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
731 bool is_input) { 739 bool is_input,
740 AudioNodeList* new_discovered) {
732 size_t num_old_devices = 0; 741 size_t num_old_devices = 0;
733 size_t num_new_devices = 0; 742 size_t num_new_devices = 0;
734 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); 743 for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
735 it != audio_devices_.end(); ++it) { 744 it != audio_devices_.end(); ++it) {
736 if (is_input == it->second.is_input) 745 if (is_input == it->second.is_input)
737 ++num_old_devices; 746 ++num_old_devices;
738 } 747 }
739 748
749 bool new_or_changed_device = false;
750 new_discovered->clear();
740 for (AudioNodeList::const_iterator it = new_nodes.begin(); 751 for (AudioNodeList::const_iterator it = new_nodes.begin();
741 it != new_nodes.end(); ++it) { 752 it != new_nodes.end(); ++it) {
742 if (is_input == it->is_input) { 753 if (is_input == it->is_input) {
743 ++num_new_devices; 754 ++num_new_devices;
744 // Look to see if the new device not in the old device list. 755 // Look to see if the new device not in the old device list.
745 AudioDevice device(*it); 756 AudioDevice device(*it);
746 if (FoundNewOrChangedDevice(device)) 757 DeviceStatus status = CheckDeviceStatus(device);
747 return true; 758 if (status == NEW_DEVICE)
759 new_discovered->push_back(*it);
760 if (status == NEW_DEVICE || status == CHANGED_DEVICE) {
761 new_or_changed_device = true;
762 }
748 } 763 }
749 } 764 }
750 return num_old_devices != num_new_devices; 765 return new_or_changed_device || (num_old_devices != num_new_devices);
751 } 766 }
752 767
753 bool CrasAudioHandler::FoundNewOrChangedDevice(const AudioDevice& device) { 768 CrasAudioHandler::DeviceStatus CrasAudioHandler::CheckDeviceStatus(
769 const AudioDevice& device) {
754 const AudioDevice* device_found = GetDeviceFromId(device.id); 770 const AudioDevice* device_found = GetDeviceFromId(device.id);
755 if (!device_found) 771 if (!device_found)
756 return true; 772 return NEW_DEVICE;
757 773
758 if (!IsSameAudioDevice(device, *device_found)) { 774 if (!IsSameAudioDevice(device, *device_found)) {
759 LOG(WARNING) << "Different Audio devices with same id:" 775 LOG(WARNING) << "Different Audio devices with same id:"
760 << " new device: " << device.ToString() 776 << " new device: " << device.ToString()
761 << " old device: " << device_found->ToString(); 777 << " old device: " << device_found->ToString();
762 return true; 778 return CHANGED_DEVICE;
763 } else if (device.active != device_found->active) { 779 } else if (device.active != device_found->active) {
764 return true; 780 return CHANGED_DEVICE;
765 } 781 }
766 782
767 return false; 783 return OLD_DEVICE;
768 } 784 }
769 785
770 void CrasAudioHandler::NotifyActiveNodeChanged(bool is_input) { 786 void CrasAudioHandler::NotifyActiveNodeChanged(bool is_input) {
771 if (is_input) 787 if (is_input)
772 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); 788 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged());
773 else 789 else
774 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged()); 790 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged());
775 } 791 }
776 792
777 void CrasAudioHandler::UpdateDevicesAndSwitchActive( 793 void CrasAudioHandler::UpdateDevicesAndSwitchActive(
778 const AudioNodeList& nodes) { 794 const AudioNodeList& nodes) {
779 size_t old_output_device_size = 0; 795 size_t old_output_device_size = 0;
780 size_t old_input_device_size = 0; 796 size_t old_input_device_size = 0;
781 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); 797 for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
782 it != audio_devices_.end(); ++it) { 798 it != audio_devices_.end(); ++it) {
783 if (it->second.is_input) 799 if (it->second.is_input)
784 ++old_input_device_size; 800 ++old_input_device_size;
785 else 801 else
786 ++old_output_device_size; 802 ++old_output_device_size;
787 } 803 }
788 804
789 bool output_devices_changed = HasDeviceChange(nodes, false); 805 AudioNodeList hotplug_output_nodes;
790 bool input_devices_changed = HasDeviceChange(nodes, true); 806 AudioNodeList hotplug_input_nodes;
807 bool output_devices_changed =
808 HasDeviceChange(nodes, false, &hotplug_output_nodes);
809 bool input_devices_changed =
810 HasDeviceChange(nodes, true, &hotplug_input_nodes);
791 audio_devices_.clear(); 811 audio_devices_.clear();
792 has_alternative_input_ = false; 812 has_alternative_input_ = false;
793 has_alternative_output_ = false; 813 has_alternative_output_ = false;
794 814
795 while (!input_devices_pq_.empty()) 815 while (!input_devices_pq_.empty())
796 input_devices_pq_.pop(); 816 input_devices_pq_.pop();
797 while (!output_devices_pq_.empty()) 817 while (!output_devices_pq_.empty())
798 output_devices_pq_.pop(); 818 output_devices_pq_.pop();
799 819
800 size_t new_output_device_size = 0; 820 size_t new_output_device_size = 0;
(...skipping 15 matching lines...) Expand all
816 836
817 if (device.is_input) { 837 if (device.is_input) {
818 input_devices_pq_.push(device); 838 input_devices_pq_.push(device);
819 ++new_input_device_size; 839 ++new_input_device_size;
820 } else { 840 } else {
821 output_devices_pq_.push(device); 841 output_devices_pq_.push(device);
822 ++new_output_device_size; 842 ++new_output_device_size;
823 } 843 }
824 } 844 }
825 845
846 // If the previous active device is removed from the new node list,
847 // reset active_output_node_id_.
848 if (!GetDeviceFromId(active_output_node_id_))
849 active_output_node_id_ = 0;
850 if (!GetDeviceFromId(active_input_node_id_))
851 active_input_node_id_ = 0;
852
826 // If audio nodes change is caused by unplugging some non-active audio 853 // If audio nodes change is caused by unplugging some non-active audio
827 // devices, the previously set active audio device will stay active. 854 // devices, the previously set active audio device will stay active.
828 // Otherwise, switch to a new active audio device according to their priority. 855 // Otherwise, switch to a new active audio device according to their priority.
829 if (input_devices_changed && 856 if (input_devices_changed &&
830 !NonActiveDeviceUnplugged(old_input_device_size, 857 !NonActiveDeviceUnplugged(old_input_device_size,
831 new_input_device_size, 858 new_input_device_size,
832 active_input_node_id_)) { 859 active_input_node_id_)) {
833 // Some devices like chromeboxes don't have the internal audio input. In 860 // Some devices like chromeboxes don't have the internal audio input. In
834 // that case the active input node id should be reset. 861 // that case the active input node id should be reset.
835 if (input_devices_pq_.empty()) { 862 if (input_devices_pq_.empty()) {
836 active_input_node_id_ = 0; 863 active_input_node_id_ = 0;
837 NotifyActiveNodeChanged(true); 864 NotifyActiveNodeChanged(true);
838 } else { 865 } else {
839 SwitchToDevice(input_devices_pq_.top(), true); 866 // If user has hot plugged a new node, we should change to the active
867 // device to the new node if it has the highest priority; otherwise,
868 // we should keep the existing active node chosen by user.
869 // For all other cases, we will choose the node with highest priority.
870 if (!active_input_node_id_ || hotplug_input_nodes.empty() ||
871 IsNodeInTheList(input_devices_pq_.top().id, hotplug_input_nodes)) {
872 SwitchToDevice(input_devices_pq_.top(), true);
873 }
840 } 874 }
841 } 875 }
842 if (output_devices_changed && 876 if (output_devices_changed &&
843 !NonActiveDeviceUnplugged(old_output_device_size, 877 !NonActiveDeviceUnplugged(old_output_device_size,
844 new_output_device_size, 878 new_output_device_size,
845 active_output_node_id_)) { 879 active_output_node_id_)) {
846 // This is really unlikely to happen because all ChromeOS devices have the 880 // This is really unlikely to happen because all ChromeOS devices have the
847 // internal audio output. 881 // internal audio output.
848 if (output_devices_pq_.empty()) { 882 if (output_devices_pq_.empty()) {
849 active_output_node_id_ = 0; 883 active_output_node_id_ = 0;
850 NotifyActiveNodeChanged(false); 884 NotifyActiveNodeChanged(false);
851 } else { 885 } else {
852 SwitchToDevice(output_devices_pq_.top(), true); 886 // ditto input node case.
887 if (!active_output_node_id_ || hotplug_output_nodes.empty() ||
888 IsNodeInTheList(output_devices_pq_.top().id, hotplug_output_nodes)) {
889 SwitchToDevice(output_devices_pq_.top(), true);
890 }
853 } 891 }
854 } 892 }
855 } 893 }
856 894
857 void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list, 895 void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
858 bool success) { 896 bool success) {
859 if (!success) { 897 if (!success) {
860 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data"; 898 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data";
861 return; 899 return;
862 } 900 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 active_output_node_id_ = 0; 959 active_output_node_id_ = 0;
922 chromeos::DBusThreadManager::Get() 960 chromeos::DBusThreadManager::Get()
923 ->GetCrasAudioClient() 961 ->GetCrasAudioClient()
924 ->RemoveActiveOutputNode(node_id); 962 ->RemoveActiveOutputNode(node_id);
925 if (notify) 963 if (notify)
926 NotifyActiveNodeChanged(false); 964 NotifyActiveNodeChanged(false);
927 } 965 }
928 } 966 }
929 967
930 } // namespace chromeos 968 } // namespace chromeos
OLDNEW
« 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