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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/audio/audio_devices_pref_handler_impl.h" 6 7 #include <algorithm> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/logging.h" 12 #include "base/prefs/pref_registry_simple.h" 13 #include "base/prefs/pref_service.h" 14 #include "base/prefs/scoped_user_pref_update.h" 15 #include "base/strings/string_number_conversions.h" 16 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/common/pref_names.h" 18 #include "chromeos/audio/audio_device.h" 19 20 namespace { 21 22 const double kDefaultOutputVolume = 75.0; 23 const double kDefaultHDMIOutputVolume = 100.0; 24 25 // Values used for muted preference. 26 const int kPrefMuteOff = 0; 27 const int kPrefMuteOn = 1; 28 29 // Gets the device id string for storing audio preference. The format of 30 // device string is a string consisting of 3 parts. 31 // |device_name| : |integer from lower 32 bit of device id| : 32 // |0(output device) or 1(input device)| 33 // If an audio device has both integrated input and output devices, the first 2 34 // parts of the string could be identical, only the last part will differentiate 35 // them. 36 std::string GetDeviceIdString(const chromeos::AudioDevice& device) { 37 return device.device_name + " : " + 38 base::Uint64ToString(device.id & static_cast<uint64>(0xffffffff)) + 39 " : " + (device.is_input ? "1" : "0"); 40 } 41 42 } // namespace 43 44 namespace chromeos { 45 46 double AudioDevicesPrefHandlerImpl::GetOutputVolumeValue( 47 const AudioDevice* device) { 48 if (!device) 49 return kDefaultOutputVolume; 50 else 51 return GetVolumeGainPrefValue(*device); 52 } 53 54 double AudioDevicesPrefHandlerImpl::GetInputGainValue( 55 const AudioDevice* device) { 56 DCHECK(device); 57 return GetVolumeGainPrefValue(*device); 58 } 59 60 void AudioDevicesPrefHandlerImpl::SetVolumeGainValue( 61 const AudioDevice& device, double value) { 62 device_volume_settings_->SetDouble(GetDeviceIdString(device), value); 63 64 SaveDevicesVolumePref(); 65 } 66 67 bool AudioDevicesPrefHandlerImpl::GetMuteValue(const AudioDevice& device) { 68 UpdateDevicesMutePref(); 69 70 std::string device_id_str = GetDeviceIdString(device); 71 if (!device_mute_settings_->HasKey(device_id_str)) 72 MigrateDeviceMuteSettings(device_id_str); 73 74 int mute = kPrefMuteOff; 75 device_mute_settings_->GetInteger(device_id_str, &mute); 76 77 return (mute == kPrefMuteOn); 78 } 79 80 void AudioDevicesPrefHandlerImpl::SetMuteValue(const AudioDevice& device, 81 bool mute) { 82 device_mute_settings_->SetInteger(GetDeviceIdString(device), 83 mute ? kPrefMuteOn : kPrefMuteOff); 84 SaveDevicesMutePref(); 85 } 86 87 88 bool AudioDevicesPrefHandlerImpl::GetAudioCaptureAllowedValue() { 89 return local_state_->GetBoolean(prefs::kAudioCaptureAllowed); 90 } 91 92 bool AudioDevicesPrefHandlerImpl::GetAudioOutputAllowedValue() { 93 return local_state_->GetBoolean(prefs::kAudioOutputAllowed); 94 } 95 96 void AudioDevicesPrefHandlerImpl::AddAudioPrefObserver( 97 AudioPrefObserver* observer) { 98 observers_.AddObserver(observer); 99 } 100 101 void AudioDevicesPrefHandlerImpl::RemoveAudioPrefObserver( 102 AudioPrefObserver* observer) { 103 observers_.RemoveObserver(observer); 104 } 105 106 double AudioDevicesPrefHandlerImpl::GetVolumeGainPrefValue( 107 const AudioDevice& device) { 108 UpdateDevicesVolumePref(); 109 110 std::string device_id_str = GetDeviceIdString(device); 111 if (!device_volume_settings_->HasKey(device_id_str)) 112 MigrateDeviceVolumeSettings(device_id_str); 113 114 // TODO(jennyz, rkc): Return a meaningful input gain default value, when 115 // cras has added support for normalizing input gain range. 116 double value = device.is_input ? 117 0.0 : GetDeviceDefaultOutputVolume(device); 118 device_volume_settings_->GetDouble(device_id_str, &value); 119 120 return value; 121 } 122 123 double AudioDevicesPrefHandlerImpl::GetDeviceDefaultOutputVolume( 124 const AudioDevice& device) { 125 if (device.type == AUDIO_TYPE_HDMI) 126 return kDefaultHDMIOutputVolume; 127 else 128 return kDefaultOutputVolume; 129 } 130 131 AudioDevicesPrefHandlerImpl::AudioDevicesPrefHandlerImpl( 132 PrefService* local_state) 133 : device_mute_settings_(new base::DictionaryValue()), 134 device_volume_settings_(new base::DictionaryValue()), 135 local_state_(local_state) { 136 InitializePrefObservers(); 137 138 UpdateDevicesMutePref(); 139 UpdateDevicesVolumePref(); 140 } 141 142 AudioDevicesPrefHandlerImpl::~AudioDevicesPrefHandlerImpl() { 143 }; 144 145 void AudioDevicesPrefHandlerImpl::InitializePrefObservers() { 146 pref_change_registrar_.Init(local_state_); 147 base::Closure callback = 148 base::Bind(&AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange, 149 base::Unretained(this)); 150 pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback); 151 pref_change_registrar_.Add(prefs::kAudioCaptureAllowed, callback); 152 } 153 154 void AudioDevicesPrefHandlerImpl::UpdateDevicesMutePref() { 155 const base::DictionaryValue* mute_prefs = 156 local_state_->GetDictionary(prefs::kAudioDevicesMute); 157 if (mute_prefs) 158 device_mute_settings_.reset(mute_prefs->DeepCopy()); 159 } 160 161 void AudioDevicesPrefHandlerImpl::SaveDevicesMutePref() { 162 DictionaryPrefUpdate dict_update(local_state_, prefs::kAudioDevicesMute); 163 base::DictionaryValue::Iterator it(*device_mute_settings_); 164 while (!it.IsAtEnd()) { 165 int mute = kPrefMuteOff; 166 it.value().GetAsInteger(&mute); 167 dict_update->SetInteger(it.key(), mute); 168 it.Advance(); 169 } 170 } 171 172 void AudioDevicesPrefHandlerImpl::UpdateDevicesVolumePref() { 173 const base::DictionaryValue* volume_prefs = 174 local_state_->GetDictionary(prefs::kAudioDevicesVolumePercent); 175 if (volume_prefs) 176 device_volume_settings_.reset(volume_prefs->DeepCopy()); 177 } 178 179 void AudioDevicesPrefHandlerImpl::SaveDevicesVolumePref() { 180 DictionaryPrefUpdate dict_update(local_state_, 181 prefs::kAudioDevicesVolumePercent); 182 base::DictionaryValue::Iterator it(*device_volume_settings_); 183 while (!it.IsAtEnd()) { 184 double volume = kDefaultOutputVolume; 185 bool success = it.value().GetAsDouble(&volume); 186 DCHECK(success); 187 dict_update->SetDouble(it.key(), volume); 188 it.Advance(); 189 } 190 } 191 192 void AudioDevicesPrefHandlerImpl::MigrateDeviceMuteSettings( 193 std::string active_device) { 194 int old_mute = local_state_->GetInteger(prefs::kAudioMute); 195 device_mute_settings_->SetInteger(active_device, old_mute); 196 SaveDevicesMutePref(); 197 } 198 199 void AudioDevicesPrefHandlerImpl::MigrateDeviceVolumeSettings( 200 std::string active_device) { 201 double old_volume = local_state_->GetDouble(prefs::kAudioVolumePercent); 202 device_volume_settings_->SetDouble(active_device, old_volume); 203 SaveDevicesVolumePref(); 204 } 205 206 void AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange() { 207 FOR_EACH_OBSERVER(AudioPrefObserver, 208 observers_, 209 OnAudioPolicyPrefChanged()); 210 } 211 212 // static 213 void AudioDevicesPrefHandlerImpl::RegisterPrefs(PrefRegistrySimple* registry) { 214 registry->RegisterDictionaryPref(prefs::kAudioDevicesVolumePercent); 215 registry->RegisterDictionaryPref(prefs::kAudioDevicesMute); 216 217 // Register the prefs backing the audio muting policies. 218 registry->RegisterBooleanPref(prefs::kAudioOutputAllowed, true); 219 // This pref has moved to the media subsystem but we should verify it is there 220 // before we use it. 221 registry->RegisterBooleanPref(::prefs::kAudioCaptureAllowed, true); 222 223 // Register the legacy audio prefs for migration. 224 registry->RegisterDoublePref(prefs::kAudioVolumePercent, 225 kDefaultOutputVolume); 226 registry->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteOff); 227 } 228 229 // static 230 AudioDevicesPrefHandler* AudioDevicesPrefHandler::Create( 231 PrefService* local_state) { 232 return new AudioDevicesPrefHandlerImpl(local_state); 233 } 234 235 } // namespace chromeos 236