[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 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 | |
jamescook | 9439c739 | 2014-12-18 01:47:25 | [diff] [blame] | 5 | #include "chromeos/audio/audio_devices_pref_handler_impl.h" |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 6 | |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 7 | #include <algorithm> |
| 8 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 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" |
[email protected] | 9eec53fe | 2013-10-30 20:21:17 | [diff] [blame] | 14 | #include "base/prefs/scoped_user_pref_update.h" |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 15 | #include "base/strings/string_number_conversions.h" |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 16 | #include "chromeos/audio/audio_device.h" |
jamescook | 9439c739 | 2014-12-18 01:47:25 | [diff] [blame] | 17 | #include "chromeos/chromeos_pref_names.h" |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 18 | |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 19 | namespace { |
| 20 | |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 21 | // Values used for muted preference. |
| 22 | const int kPrefMuteOff = 0; |
| 23 | const int kPrefMuteOn = 1; |
| 24 | |
[email protected] | 6e5feea | 2013-09-19 05:02:11 | [diff] [blame] | 25 | // Gets the device id string for storing audio preference. The format of |
| 26 | // device string is a string consisting of 3 parts. |
| 27 | // |device_name| : |integer from lower 32 bit of device id| : |
| 28 | // |0(output device) or 1(input device)| |
| 29 | // If an audio device has both integrated input and output devices, the first 2 |
| 30 | // parts of the string could be identical, only the last part will differentiate |
| 31 | // them. |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 32 | std::string GetDeviceIdString(const chromeos::AudioDevice& device) { |
rkc | e0a1ab0b | 2014-12-15 23:45:23 | [diff] [blame] | 33 | std::string device_id_string = |
| 34 | device.device_name + " : " + |
| 35 | base::Uint64ToString(device.id & static_cast<uint64>(0xffffffff)) + |
| 36 | " : " + (device.is_input ? "1" : "0"); |
| 37 | // Replace any periods from the device id string with a space, since setting |
| 38 | // names cannot contain periods. |
| 39 | std::replace(device_id_string.begin(), device_id_string.end(), '.', ' '); |
| 40 | return device_id_string; |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 41 | } |
| 42 | |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 43 | } // namespace |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 44 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 45 | namespace chromeos { |
| 46 | |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 47 | double AudioDevicesPrefHandlerImpl::GetOutputVolumeValue( |
| 48 | const AudioDevice* device) { |
| 49 | if (!device) |
jamescook | 15015851 | 2014-12-19 02:55:00 | [diff] [blame] | 50 | return kDefaultOutputVolumePercent; |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 51 | else |
| 52 | return GetVolumeGainPrefValue(*device); |
| 53 | } |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 54 | |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 55 | double AudioDevicesPrefHandlerImpl::GetInputGainValue( |
| 56 | const AudioDevice* device) { |
| 57 | DCHECK(device); |
| 58 | return GetVolumeGainPrefValue(*device); |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 59 | } |
| 60 | |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 61 | void AudioDevicesPrefHandlerImpl::SetVolumeGainValue( |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 62 | const AudioDevice& device, double value) { |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 63 | device_volume_settings_->SetDouble(GetDeviceIdString(device), value); |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 64 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 65 | SaveDevicesVolumePref(); |
| 66 | } |
| 67 | |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 68 | bool AudioDevicesPrefHandlerImpl::GetMuteValue(const AudioDevice& device) { |
[email protected] | bf9fc82 | 2013-05-10 10:55:57 | [diff] [blame] | 69 | UpdateDevicesMutePref(); |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 70 | |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 71 | std::string device_id_str = GetDeviceIdString(device); |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 72 | if (!device_mute_settings_->HasKey(device_id_str)) |
| 73 | MigrateDeviceMuteSettings(device_id_str); |
| 74 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 75 | int mute = kPrefMuteOff; |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 76 | device_mute_settings_->GetInteger(device_id_str, &mute); |
| 77 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 78 | return (mute == kPrefMuteOn); |
| 79 | } |
| 80 | |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 81 | void AudioDevicesPrefHandlerImpl::SetMuteValue(const AudioDevice& device, |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 82 | bool mute) { |
[email protected] | 6fda9fb8 | 2013-06-20 21:57:38 | [diff] [blame] | 83 | device_mute_settings_->SetInteger(GetDeviceIdString(device), |
[email protected] | 029a00c | 2013-05-07 00:44:58 | [diff] [blame] | 84 | mute ? kPrefMuteOn : kPrefMuteOff); |
[email protected] | bf9fc82 | 2013-05-10 10:55:57 | [diff] [blame] | 85 | SaveDevicesMutePref(); |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 86 | } |
| 87 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 88 | bool AudioDevicesPrefHandlerImpl::GetAudioOutputAllowedValue() { |
| 89 | return local_state_->GetBoolean(prefs::kAudioOutputAllowed); |
| 90 | } |
| 91 | |
| 92 | void AudioDevicesPrefHandlerImpl::AddAudioPrefObserver( |
| 93 | AudioPrefObserver* observer) { |
| 94 | observers_.AddObserver(observer); |
| 95 | } |
| 96 | |
| 97 | void AudioDevicesPrefHandlerImpl::RemoveAudioPrefObserver( |
| 98 | AudioPrefObserver* observer) { |
| 99 | observers_.RemoveObserver(observer); |
| 100 | } |
| 101 | |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 102 | double AudioDevicesPrefHandlerImpl::GetVolumeGainPrefValue( |
| 103 | const AudioDevice& device) { |
| 104 | UpdateDevicesVolumePref(); |
| 105 | |
| 106 | std::string device_id_str = GetDeviceIdString(device); |
| 107 | if (!device_volume_settings_->HasKey(device_id_str)) |
| 108 | MigrateDeviceVolumeSettings(device_id_str); |
| 109 | |
| 110 | // TODO(jennyz, rkc): Return a meaningful input gain default value, when |
| 111 | // cras has added support for normalizing input gain range. |
| 112 | double value = device.is_input ? |
| 113 | 0.0 : GetDeviceDefaultOutputVolume(device); |
rkc | e0a1ab0b | 2014-12-15 23:45:23 | [diff] [blame] | 114 | // TODO(rkc): The above code is completely ignored since we 'always' have a |
| 115 | // default pref value. Fix this. http://crbug.com/442489 |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 116 | device_volume_settings_->GetDouble(device_id_str, &value); |
| 117 | |
| 118 | return value; |
| 119 | } |
| 120 | |
| 121 | double AudioDevicesPrefHandlerImpl::GetDeviceDefaultOutputVolume( |
| 122 | const AudioDevice& device) { |
| 123 | if (device.type == AUDIO_TYPE_HDMI) |
jamescook | 15015851 | 2014-12-19 02:55:00 | [diff] [blame] | 124 | return kDefaultHdmiOutputVolumePercent; |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 125 | else |
jamescook | 15015851 | 2014-12-19 02:55:00 | [diff] [blame] | 126 | return kDefaultOutputVolumePercent; |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 127 | } |
| 128 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 129 | AudioDevicesPrefHandlerImpl::AudioDevicesPrefHandlerImpl( |
jamescook | 928c5e8 | 2015-01-07 20:47:18 | [diff] [blame] | 130 | PrefService* local_state) |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 131 | : device_mute_settings_(new base::DictionaryValue()), |
| 132 | device_volume_settings_(new base::DictionaryValue()), |
jamescook | 928c5e8 | 2015-01-07 20:47:18 | [diff] [blame] | 133 | local_state_(local_state) { |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 134 | InitializePrefObservers(); |
| 135 | |
| 136 | UpdateDevicesMutePref(); |
| 137 | UpdateDevicesVolumePref(); |
| 138 | } |
| 139 | |
| 140 | AudioDevicesPrefHandlerImpl::~AudioDevicesPrefHandlerImpl() { |
rkc | e0a1ab0b | 2014-12-15 23:45:23 | [diff] [blame] | 141 | } |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 142 | |
| 143 | void AudioDevicesPrefHandlerImpl::InitializePrefObservers() { |
| 144 | pref_change_registrar_.Init(local_state_); |
| 145 | base::Closure callback = |
| 146 | base::Bind(&AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange, |
| 147 | base::Unretained(this)); |
| 148 | pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback); |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | void AudioDevicesPrefHandlerImpl::UpdateDevicesMutePref() { |
| 152 | const base::DictionaryValue* mute_prefs = |
| 153 | local_state_->GetDictionary(prefs::kAudioDevicesMute); |
| 154 | if (mute_prefs) |
| 155 | device_mute_settings_.reset(mute_prefs->DeepCopy()); |
| 156 | } |
| 157 | |
| 158 | void AudioDevicesPrefHandlerImpl::SaveDevicesMutePref() { |
| 159 | DictionaryPrefUpdate dict_update(local_state_, prefs::kAudioDevicesMute); |
| 160 | base::DictionaryValue::Iterator it(*device_mute_settings_); |
| 161 | while (!it.IsAtEnd()) { |
| 162 | int mute = kPrefMuteOff; |
| 163 | it.value().GetAsInteger(&mute); |
[email protected] | bf9fc82 | 2013-05-10 10:55:57 | [diff] [blame] | 164 | dict_update->SetInteger(it.key(), mute); |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 165 | it.Advance(); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | void AudioDevicesPrefHandlerImpl::UpdateDevicesVolumePref() { |
| 170 | const base::DictionaryValue* volume_prefs = |
| 171 | local_state_->GetDictionary(prefs::kAudioDevicesVolumePercent); |
| 172 | if (volume_prefs) |
| 173 | device_volume_settings_.reset(volume_prefs->DeepCopy()); |
| 174 | } |
| 175 | |
| 176 | void AudioDevicesPrefHandlerImpl::SaveDevicesVolumePref() { |
| 177 | DictionaryPrefUpdate dict_update(local_state_, |
| 178 | prefs::kAudioDevicesVolumePercent); |
| 179 | base::DictionaryValue::Iterator it(*device_volume_settings_); |
| 180 | while (!it.IsAtEnd()) { |
jamescook | 15015851 | 2014-12-19 02:55:00 | [diff] [blame] | 181 | double volume = kDefaultOutputVolumePercent; |
[email protected] | 140a3145 | 2013-09-09 18:54:37 | [diff] [blame] | 182 | bool success = it.value().GetAsDouble(&volume); |
| 183 | DCHECK(success); |
[email protected] | bf9fc82 | 2013-05-10 10:55:57 | [diff] [blame] | 184 | dict_update->SetDouble(it.key(), volume); |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 185 | it.Advance(); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | void AudioDevicesPrefHandlerImpl::MigrateDeviceMuteSettings( |
| 190 | std::string active_device) { |
| 191 | int old_mute = local_state_->GetInteger(prefs::kAudioMute); |
| 192 | device_mute_settings_->SetInteger(active_device, old_mute); |
| 193 | SaveDevicesMutePref(); |
| 194 | } |
| 195 | |
| 196 | void AudioDevicesPrefHandlerImpl::MigrateDeviceVolumeSettings( |
| 197 | std::string active_device) { |
| 198 | double old_volume = local_state_->GetDouble(prefs::kAudioVolumePercent); |
| 199 | device_volume_settings_->SetDouble(active_device, old_volume); |
| 200 | SaveDevicesVolumePref(); |
| 201 | } |
| 202 | |
| 203 | void AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange() { |
| 204 | FOR_EACH_OBSERVER(AudioPrefObserver, |
| 205 | observers_, |
| 206 | OnAudioPolicyPrefChanged()); |
| 207 | } |
| 208 | |
| 209 | // static |
jamescook | 928c5e8 | 2015-01-07 20:47:18 | [diff] [blame] | 210 | void AudioDevicesPrefHandlerImpl::RegisterPrefs(PrefRegistrySimple* registry) { |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 211 | registry->RegisterDictionaryPref(prefs::kAudioDevicesVolumePercent); |
| 212 | registry->RegisterDictionaryPref(prefs::kAudioDevicesMute); |
| 213 | |
[email protected] | 82578f9 | 2013-08-01 20:14:40 | [diff] [blame] | 214 | // Register the prefs backing the audio muting policies. |
jamescook | 928c5e8 | 2015-01-07 20:47:18 | [diff] [blame] | 215 | // Policy for audio input is handled by kAudioCaptureAllowed in the Chrome |
| 216 | // media system. |
[email protected] | 82578f9 | 2013-08-01 20:14:40 | [diff] [blame] | 217 | registry->RegisterBooleanPref(prefs::kAudioOutputAllowed, true); |
jamescook | 9439c739 | 2014-12-18 01:47:25 | [diff] [blame] | 218 | |
[email protected] | 82578f9 | 2013-08-01 20:14:40 | [diff] [blame] | 219 | // Register the legacy audio prefs for migration. |
| 220 | registry->RegisterDoublePref(prefs::kAudioVolumePercent, |
jamescook | 15015851 | 2014-12-19 02:55:00 | [diff] [blame] | 221 | kDefaultOutputVolumePercent); |
[email protected] | 82578f9 | 2013-08-01 20:14:40 | [diff] [blame] | 222 | registry->RegisterIntegerPref(prefs::kAudioMute, kPrefMuteOff); |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 223 | } |
| 224 | |
[email protected] | 36221c69 | 2013-05-02 23:45:47 | [diff] [blame] | 225 | } // namespace chromeos |