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

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

Issue 1380103003: Store audio device's active state in preference (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed code review comments Created 4 years, 11 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
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 <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 28 matching lines...) Expand all
39 bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) { 39 bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) {
40 return a.id == b.id && a.is_input == b.is_input && a.type == b.type 40 return a.id == b.id && a.is_input == b.is_input && a.type == b.type
41 && a.device_name == b.device_name; 41 && a.device_name == b.device_name;
42 } 42 }
43 43
44 bool IsInNodeList(uint64_t node_id, 44 bool IsInNodeList(uint64_t node_id,
45 const CrasAudioHandler::NodeIdList& id_list) { 45 const CrasAudioHandler::NodeIdList& id_list) {
46 return std::find(id_list.begin(), id_list.end(), node_id) != id_list.end(); 46 return std::find(id_list.begin(), id_list.end(), node_id) != id_list.end();
47 } 47 }
48 48
49 bool IsNodeInTheList(uint64_t node_id, const AudioNodeList& node_list) {
50 for (size_t i = 0; i < node_list.size(); ++i) {
51 if (node_id == node_list[i].id)
52 return true;
53 }
54 return false;
55 }
56
57 } // namespace 49 } // namespace
58 50
59 CrasAudioHandler::AudioObserver::AudioObserver() { 51 CrasAudioHandler::AudioObserver::AudioObserver() {
60 } 52 }
61 53
62 CrasAudioHandler::AudioObserver::~AudioObserver() { 54 CrasAudioHandler::AudioObserver::~AudioObserver() {
63 } 55 }
64 56
65 void CrasAudioHandler::AudioObserver::OnOutputNodeVolumeChanged( 57 void CrasAudioHandler::AudioObserver::OnOutputNodeVolumeChanged(
66 uint64_t /* node_id */, 58 uint64_t /* node_id */,
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 SetInputMuteInternal(mute_on); 383 SetInputMuteInternal(mute_on);
392 FOR_EACH_OBSERVER(AudioObserver, observers_, 384 FOR_EACH_OBSERVER(AudioObserver, observers_,
393 OnInputMuteChanged(input_mute_on_)); 385 OnInputMuteChanged(input_mute_on_));
394 } 386 }
395 387
396 void CrasAudioHandler::SetActiveOutputNode(uint64_t node_id, bool notify) { 388 void CrasAudioHandler::SetActiveOutputNode(uint64_t node_id, bool notify) {
397 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> 389 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
398 SetActiveOutputNode(node_id); 390 SetActiveOutputNode(node_id);
399 if (notify) 391 if (notify)
400 NotifyActiveNodeChanged(false); 392 NotifyActiveNodeChanged(false);
393
394 // Save state for all output nodes.
395 for (AudioDeviceMap::iterator it = audio_devices_.begin();
396 it != audio_devices_.end(); ++it) {
397 if (it->second.is_input)
398 continue;
399 audio_pref_handler_->SetDeviceState(it->second,
400 it->second.active ? AUDIO_STATE_ACTIVE : AUDIO_STATE_INACTIVE);
401 }
401 } 402 }
402 403
403 void CrasAudioHandler::SetActiveInputNode(uint64_t node_id, bool notify) { 404 void CrasAudioHandler::SetActiveInputNode(uint64_t node_id, bool notify) {
404 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> 405 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
405 SetActiveInputNode(node_id); 406 SetActiveInputNode(node_id);
406 if (notify) 407 if (notify)
407 NotifyActiveNodeChanged(true); 408 NotifyActiveNodeChanged(true);
409
410 // Save state for all input nodes.
411 for (AudioDeviceMap::iterator it = audio_devices_.begin();
412 it != audio_devices_.end(); ++it) {
413 if (!it->second.is_input)
414 continue;
415 audio_pref_handler_->SetDeviceState(it->second,
416 it->second.active ? AUDIO_STATE_ACTIVE : AUDIO_STATE_INACTIVE);
417 }
408 } 418 }
409 419
410 void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64_t device_id, 420 void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64_t device_id,
411 int value) { 421 int value) {
412 const AudioDevice* device = GetDeviceFromId(device_id); 422 const AudioDevice* device = GetDeviceFromId(device_id);
413 if (!device) 423 if (!device)
414 return; 424 return;
415 425
416 if (device->is_input) 426 if (device->is_input)
417 SetInputNodeGainPercent(device_id, value); 427 SetInputNodeGainPercent(device_id, value);
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 SetActiveInputNode(active_input_node_id_, notify); 785 SetActiveInputNode(active_input_node_id_, notify);
776 } else { 786 } else {
777 if (!ChangeActiveDevice(device, &active_output_node_id_)) 787 if (!ChangeActiveDevice(device, &active_output_node_id_))
778 return; 788 return;
779 SetupAudioOutputState(); 789 SetupAudioOutputState();
780 SetActiveOutputNode(active_output_node_id_, notify); 790 SetActiveOutputNode(active_output_node_id_, notify);
781 } 791 }
782 } 792 }
783 793
784 bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes, 794 bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
785 bool is_input, 795 bool is_input,
786 AudioNodeList* new_discovered) { 796 AudioDevicePriorityQueue* new_discovered) {
787 size_t num_old_devices = 0; 797 size_t num_old_devices = 0;
788 size_t num_new_devices = 0; 798 size_t num_new_devices = 0;
789 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); 799 for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
790 it != audio_devices_.end(); ++it) { 800 it != audio_devices_.end(); ++it) {
791 if (is_input == it->second.is_input) 801 if (is_input == it->second.is_input)
792 ++num_old_devices; 802 ++num_old_devices;
793 } 803 }
794 804
795 bool new_or_changed_device = false; 805 bool new_or_changed_device = false;
796 new_discovered->clear(); 806 while (!new_discovered->empty())
807 new_discovered->pop();
797 for (AudioNodeList::const_iterator it = new_nodes.begin(); 808 for (AudioNodeList::const_iterator it = new_nodes.begin();
798 it != new_nodes.end(); ++it) { 809 it != new_nodes.end(); ++it) {
799 if (is_input == it->is_input) { 810 if (is_input == it->is_input) {
800 ++num_new_devices; 811 ++num_new_devices;
801 // Look to see if the new device not in the old device list. 812 // Look to see if the new device not in the old device list.
802 AudioDevice device(*it); 813 AudioDevice device(*it);
803 DeviceStatus status = CheckDeviceStatus(device); 814 DeviceStatus status = CheckDeviceStatus(device);
804 if (status == NEW_DEVICE) 815 if (status == NEW_DEVICE)
805 new_discovered->push_back(*it); 816 new_discovered->push(device);
806 if (status == NEW_DEVICE || status == CHANGED_DEVICE) { 817 if (status == NEW_DEVICE || status == CHANGED_DEVICE) {
807 new_or_changed_device = true; 818 new_or_changed_device = true;
808 } 819 }
809 } 820 }
810 } 821 }
811 return new_or_changed_device || (num_old_devices != num_new_devices); 822 return new_or_changed_device || (num_old_devices != num_new_devices);
812 } 823 }
813 824
814 CrasAudioHandler::DeviceStatus CrasAudioHandler::CheckDeviceStatus( 825 CrasAudioHandler::DeviceStatus CrasAudioHandler::CheckDeviceStatus(
815 const AudioDevice& device) { 826 const AudioDevice& device) {
(...skipping 25 matching lines...) Expand all
841 size_t old_output_device_size = 0; 852 size_t old_output_device_size = 0;
842 size_t old_input_device_size = 0; 853 size_t old_input_device_size = 0;
843 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); 854 for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
844 it != audio_devices_.end(); ++it) { 855 it != audio_devices_.end(); ++it) {
845 if (it->second.is_input) 856 if (it->second.is_input)
846 ++old_input_device_size; 857 ++old_input_device_size;
847 else 858 else
848 ++old_output_device_size; 859 ++old_output_device_size;
849 } 860 }
850 861
851 AudioNodeList hotplug_output_nodes; 862 AudioDevicePriorityQueue hotplug_output_nodes;
852 AudioNodeList hotplug_input_nodes; 863 AudioDevicePriorityQueue hotplug_input_nodes;
853 bool output_devices_changed = 864 bool output_devices_changed =
854 HasDeviceChange(nodes, false, &hotplug_output_nodes); 865 HasDeviceChange(nodes, false, &hotplug_output_nodes);
855 bool input_devices_changed = 866 bool input_devices_changed =
856 HasDeviceChange(nodes, true, &hotplug_input_nodes); 867 HasDeviceChange(nodes, true, &hotplug_input_nodes);
857 audio_devices_.clear(); 868 audio_devices_.clear();
858 has_alternative_input_ = false; 869 has_alternative_input_ = false;
859 has_alternative_output_ = false; 870 has_alternative_output_ = false;
860 871
861 while (!input_devices_pq_.empty()) 872 while (!input_devices_pq_.empty())
862 input_devices_pq_.pop(); 873 input_devices_pq_.pop();
(...skipping 30 matching lines...) Expand all
893 // or changed to inactive by cras, reset active_output_node_id_. 904 // or changed to inactive by cras, reset active_output_node_id_.
894 // See crbug.com/478968. 905 // See crbug.com/478968.
895 const AudioDevice* active_output = GetDeviceFromId(active_output_node_id_); 906 const AudioDevice* active_output = GetDeviceFromId(active_output_node_id_);
896 if (!active_output || !active_output->active) 907 if (!active_output || !active_output->active)
897 active_output_node_id_ = 0; 908 active_output_node_id_ = 0;
898 const AudioDevice* active_input = GetDeviceFromId(active_input_node_id_); 909 const AudioDevice* active_input = GetDeviceFromId(active_input_node_id_);
899 if (!active_input || !active_input->active) 910 if (!active_input || !active_input->active)
900 active_input_node_id_ = 0; 911 active_input_node_id_ = 0;
901 912
902 // If audio nodes change is caused by unplugging some non-active audio 913 // If audio nodes change is caused by unplugging some non-active audio
903 // devices, the previously set active audio device will stay active. 914 // devices, we wont't change the current active audio devices.
904 // Otherwise, switch to a new active audio device according to their priority.
905 if (input_devices_changed && 915 if (input_devices_changed &&
906 !NonActiveDeviceUnplugged(old_input_device_size, 916 !NonActiveDeviceUnplugged(old_input_device_size,
907 new_input_device_size, 917 new_input_device_size,
908 active_input_node_id_)) { 918 active_input_node_id_)) {
909 // Some devices like chromeboxes don't have the internal audio input. In 919 // Some devices like chromeboxes don't have the internal audio input. In
910 // that case the active input node id should be reset. 920 // that case the active input node id should be reset.
911 if (input_devices_pq_.empty()) { 921 if (input_devices_pq_.empty()) {
912 active_input_node_id_ = 0; 922 active_input_node_id_ = 0;
913 NotifyActiveNodeChanged(true); 923 NotifyActiveNodeChanged(true);
914 } else { 924 } else {
915 // If user has hot plugged a new node, we should change to the active 925 // If there is no current active node, or, no new hot plugged node, select
916 // device to the new node if it has the highest priority; otherwise, 926 // the active node by their priorities.
917 // we should keep the existing active node chosen by user. 927 if (!active_input_node_id_ || hotplug_input_nodes.empty()) {
918 // For all other cases, we will choose the node with highest priority.
919 if (!active_input_node_id_ || hotplug_input_nodes.empty() ||
920 IsNodeInTheList(input_devices_pq_.top().id, hotplug_input_nodes)) {
921 SwitchToDevice(input_devices_pq_.top(), true); 928 SwitchToDevice(input_devices_pq_.top(), true);
929 } else {
930 // If user has hot plugged any input nodes, look at the one with highest
931 // priority (normally, there is only one hot plugged input node), and
932 // consider switch to it depend on its last state stored in preference.
933 AudioDeviceState last_state =
934 audio_pref_handler_->GetDeviceState(hotplug_input_nodes.top());
935 switch (last_state) {
936 case AUDIO_STATE_ACTIVE:
937 // This node was plugged in before and was selected as the active one
938 // before it was unplugged last time, switch to this device.
939 SwitchToDevice(hotplug_input_nodes.top(), true);
940 break;
941 case AUDIO_STATE_NOT_AVAILABLE:
942 // This is a new node, not plugged in before, with the highest
943 // priority. Switch to this device.
944 if (input_devices_pq_.top().id == hotplug_input_nodes.top().id)
945 SwitchToDevice(hotplug_input_nodes.top(), true);
946 break;
947 case AUDIO_STATE_INACTIVE:
948 // This node was NOT selected as the active one last time before it
949 // got unplugged, so don't switch to it.
950 default:
951 break;
952 }
922 } 953 }
923 } 954 }
924 } 955 }
925 if (output_devices_changed && 956 if (output_devices_changed &&
926 !NonActiveDeviceUnplugged(old_output_device_size, 957 !NonActiveDeviceUnplugged(old_output_device_size,
927 new_output_device_size, 958 new_output_device_size,
928 active_output_node_id_)) { 959 active_output_node_id_)) {
929 // This is really unlikely to happen because all ChromeOS devices have the 960 // ditto input node logic.
930 // internal audio output.
931 if (output_devices_pq_.empty()) { 961 if (output_devices_pq_.empty()) {
932 active_output_node_id_ = 0; 962 active_output_node_id_ = 0;
933 NotifyActiveNodeChanged(false); 963 NotifyActiveNodeChanged(false);
934 } else { 964 } else {
935 // ditto input node case. 965 if (!active_output_node_id_ || hotplug_output_nodes.empty()) {
936 if (!active_output_node_id_ || hotplug_output_nodes.empty() ||
937 IsNodeInTheList(output_devices_pq_.top().id, hotplug_output_nodes)) {
938 SwitchToDevice(output_devices_pq_.top(), true); 966 SwitchToDevice(output_devices_pq_.top(), true);
967 } else {
968 AudioDeviceState last_state =
969 audio_pref_handler_->GetDeviceState(hotplug_output_nodes.top());
970 switch (last_state) {
971 case AUDIO_STATE_ACTIVE:
972 SwitchToDevice(hotplug_output_nodes.top(), true);
973 break;
974 case AUDIO_STATE_NOT_AVAILABLE:
975 if (output_devices_pq_.top().id == hotplug_output_nodes.top().id)
976 SwitchToDevice(hotplug_output_nodes.top(), true);
977 break;
978 case AUDIO_STATE_INACTIVE:
979 default:
980 break;
981 }
939 } 982 }
940 } 983 }
941 } 984 }
942 } 985 }
943 986
944 void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list, 987 void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
945 bool success) { 988 bool success) {
946 if (!success) { 989 if (!success) {
947 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data"; 990 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data";
948 return; 991 return;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 hdmi_rediscover_grace_period_duration_in_ms_), 1086 hdmi_rediscover_grace_period_duration_in_ms_),
1044 this, &CrasAudioHandler::UpdateAudioAfterHDMIRediscoverGracePeriod); 1087 this, &CrasAudioHandler::UpdateAudioAfterHDMIRediscoverGracePeriod);
1045 } 1088 }
1046 1089
1047 void CrasAudioHandler::SetHDMIRediscoverGracePeriodForTesting( 1090 void CrasAudioHandler::SetHDMIRediscoverGracePeriodForTesting(
1048 int duration_in_ms) { 1091 int duration_in_ms) {
1049 hdmi_rediscover_grace_period_duration_in_ms_ = duration_in_ms; 1092 hdmi_rediscover_grace_period_duration_in_ms_ = duration_in_ms;
1050 } 1093 }
1051 1094
1052 } // namespace chromeos 1095 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698