OLD | NEW |
---|---|
(Empty) | |
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 "chromeos/audio/cras_audio_handler.h" | |
6 | |
7 #include <algorithm> | |
8 #include <cmath> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/logging.h" | |
13 #include "base/prefs/pref_registry_simple.h" | |
14 #include "base/prefs/pref_service.h" | |
15 #include "chromeos/audio/audio_pref_names.h" | |
16 #include "chromeos/dbus/dbus_thread_manager.h" | |
17 | |
18 using std::max; | |
19 using std::min; | |
20 | |
21 namespace chromeos { | |
22 | |
23 namespace { | |
24 | |
25 // Default value for the volume pref, as a percent in the range [0, 100]. | |
26 const int kDefaultVolumePercent = 75; | |
27 | |
28 // Default value for unmuting, as a percent in the range [0, 100]. | |
29 // Used when sound is unmuted, but volume was less than kMuteThresholdPercent. | |
30 const int kDefaultUnmuteVolumePercent = 4; | |
31 | |
32 // Volume value which should be considered as muted in range [0, 100]. | |
33 const int kMuteThresholdPercent = 1; | |
34 | |
35 // Values used for output muted preference. | |
36 const int kPrefOutputMuteOff = 0; | |
37 const int kPrefOutputMuteOn = 1; | |
38 | |
39 static CrasAudioHandler* g_cras_audio_handler = NULL; | |
40 | |
41 } // namespace | |
42 | |
43 CrasAudioHandler::AudioObserver::AudioObserver() { | |
44 } | |
45 | |
46 CrasAudioHandler::AudioObserver::~AudioObserver() { | |
47 } | |
48 | |
49 void CrasAudioHandler::AudioObserver::OnOutputVolumeChanged() { | |
50 } | |
51 | |
52 void CrasAudioHandler::AudioObserver::OnOutputMuteChanged() { | |
53 } | |
54 | |
55 void CrasAudioHandler::AudioObserver::OnInputMuteChanged() { | |
56 } | |
57 | |
58 void CrasAudioHandler::AudioObserver::OnAudioNodesChanged() { | |
59 } | |
60 | |
61 void CrasAudioHandler::AudioObserver::OnActiveOutputNodeChanged() { | |
62 } | |
63 | |
64 void CrasAudioHandler::AudioObserver::OnActiveInputNodeChanged() { | |
65 } | |
66 | |
67 // static | |
68 void CrasAudioHandler::Initialize(PrefService* local_state) { | |
69 CHECK(!g_cras_audio_handler); | |
70 g_cras_audio_handler = new CrasAudioHandler(local_state); | |
71 } | |
72 | |
73 // static | |
74 void CrasAudioHandler::Shutdown() { | |
75 CHECK(g_cras_audio_handler); | |
76 delete g_cras_audio_handler; | |
77 g_cras_audio_handler = NULL; | |
78 } | |
79 | |
80 // static | |
81 bool CrasAudioHandler::IsInitialized() { | |
82 return g_cras_audio_handler != NULL; | |
83 } | |
84 | |
85 // static | |
86 CrasAudioHandler* CrasAudioHandler::Get() { | |
87 CHECK(g_cras_audio_handler) | |
88 << "CrasAudioHandler::Get() called before Initialize()."; | |
89 return g_cras_audio_handler; | |
90 } | |
91 | |
92 // static | |
93 void CrasAudioHandler::RegisterPrefs(PrefRegistrySimple* registry) { | |
94 registry->RegisterDoublePref(prefs::kAudioVolumePercent, | |
95 kDefaultVolumePercent); | |
96 registry->RegisterIntegerPref(prefs::kAudioMute, kPrefOutputMuteOff); | |
97 // Register the prefs backing the audio muting policies. | |
98 registry->RegisterBooleanPref(prefs::kAudioOutputAllowed, true); | |
99 // This pref has moved to the media subsystem but we should verify it is there | |
100 // before we use it. | |
101 registry->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); | |
102 } | |
103 | |
104 void CrasAudioHandler::AddAudioObserver(AudioObserver* observer) { | |
105 observers_.AddObserver(observer); | |
106 } | |
107 | |
108 void CrasAudioHandler::RemoveAudioObserver(AudioObserver* observer) { | |
109 observers_.RemoveObserver(observer); | |
110 } | |
111 | |
112 bool CrasAudioHandler::IsOutputMuted() { | |
113 return output_mute_on_; | |
114 } | |
115 | |
116 bool CrasAudioHandler::IsInputMuted() { | |
117 return input_mute_on_; | |
118 } | |
119 | |
120 int CrasAudioHandler::GetOutputVolumePercent() { | |
121 return output_volume_; | |
122 } | |
123 | |
124 uint64 CrasAudioHandler::GetActiveOutputNode() const { | |
125 return active_output_node_id_; | |
126 } | |
127 | |
128 uint64 CrasAudioHandler::GetActiveInputNode() const { | |
129 return active_input_node_id_; | |
130 } | |
131 | |
132 void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) { | |
133 volume_percent = min(max(volume_percent, 0), 100); | |
134 if (volume_percent <= kMuteThresholdPercent) | |
135 volume_percent = 0; | |
136 if (IsOutputMuted() && volume_percent > 0) | |
137 SetOutputMute(false); | |
138 if (!IsOutputMuted() && volume_percent == 0) | |
139 SetOutputMute(true); | |
140 SetOutputVolumeInternal(volume_percent); | |
141 } | |
142 | |
143 void CrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) { | |
144 SetOutputVolumePercent(output_volume_ + adjust_by_percent); | |
145 } | |
146 | |
147 void CrasAudioHandler::SetOutputMute(bool mute_on) { | |
148 if (output_mute_locked_) { | |
149 NOTREACHED() << "Output mute has been locked"; | |
150 return; | |
151 } | |
152 | |
153 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | |
154 SetOutputMute(mute_on); | |
155 } | |
156 | |
157 void CrasAudioHandler::SetInputMute(bool mute_on) { | |
158 if (input_mute_locked_) { | |
159 NOTREACHED() << "Input mute has been locked"; | |
160 return; | |
161 } | |
162 | |
163 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | |
164 SetInputMute(mute_on); | |
165 } | |
166 | |
167 void CrasAudioHandler::SetActiveOutputNode(uint64 node_id) { | |
168 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | |
169 SetActiveOutputNode(node_id); | |
170 } | |
171 | |
172 void CrasAudioHandler::SetActiveInputNode(uint64 node_id) { | |
173 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | |
174 SetActiveInputNode(node_id); | |
175 } | |
176 | |
177 CrasAudioHandler::CrasAudioHandler(PrefService* local_state) | |
178 : weak_ptr_factory_(this), | |
stevenjb
2013/04/17 01:25:12
ALLOW_THIS...
jennyz
2013/04/18 01:21:19
Done.
| |
179 local_state_(local_state), | |
180 output_mute_on_(false), | |
181 input_mute_on_(false), | |
182 output_volume_(0), | |
183 active_output_node_id_(0), | |
184 active_input_node_id_(0), | |
185 output_mute_locked_(false), | |
186 input_mute_locked_(false) { | |
187 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->AddObserver(this); | |
188 SetupInitialAudioState(); | |
189 } | |
190 | |
191 CrasAudioHandler::~CrasAudioHandler() { | |
192 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | |
193 RemoveObserver(this); | |
194 } | |
195 | |
196 void CrasAudioHandler::AudioClientRestarted() { | |
197 SetupInitialAudioState(); | |
198 } | |
199 | |
200 void CrasAudioHandler::OutputVolumeChanged(int volume) { | |
201 if (output_volume_ != volume) { | |
stevenjb
2013/04/17 01:25:12
nit: early exit instead
jennyz
2013/04/18 01:21:19
Done.
| |
202 output_volume_ = volume; | |
203 local_state_->SetDouble(prefs::kAudioVolumePercent, output_volume_); | |
204 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged()); | |
205 } | |
206 } | |
207 | |
208 void CrasAudioHandler::OutputMuteChanged(bool mute_on) { | |
209 if (output_mute_on_ != mute_on) { | |
stevenjb
2013/04/17 01:25:12
nit: early exit
jennyz
2013/04/18 01:21:19
Done.
| |
210 output_mute_on_ = mute_on; | |
211 local_state_->SetInteger( | |
212 prefs::kAudioMute, | |
213 output_mute_on_ ? kPrefOutputMuteOn : kPrefOutputMuteOff); | |
214 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputMuteChanged()); | |
215 } | |
216 } | |
217 | |
218 void CrasAudioHandler::InputMuteChanged(bool mute_on) { | |
stevenjb
2013/04/17 01:25:12
nit: early exit
jennyz
2013/04/18 01:21:19
Done.
| |
219 if (input_mute_on_ != mute_on) { | |
220 input_mute_on_ = mute_on; | |
221 FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputMuteChanged()); | |
222 } | |
223 } | |
224 | |
225 void CrasAudioHandler::NodesChanged() { | |
226 // Refresh audio nodes data. | |
227 GetNodes(); | |
228 } | |
229 | |
230 void CrasAudioHandler::ActiveOutputNodeChanged(uint64 node_id) { | |
231 active_output_node_id_ = node_id; | |
232 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged()); | |
233 } | |
234 | |
235 void CrasAudioHandler::ActiveInputNodeChanged(uint64 node_id) { | |
236 active_input_node_id_ = node_id; | |
237 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); | |
238 } | |
239 | |
240 void CrasAudioHandler::InitializePrefObservers() { | |
241 pref_change_registrar_.Init(local_state_); | |
242 base::Closure callback = base::Bind(&CrasAudioHandler::ApplyAudioPolicy, | |
243 weak_ptr_factory_.GetWeakPtr()); | |
244 pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback); | |
245 pref_change_registrar_.Add(prefs::kAudioCaptureAllowed, callback); | |
246 } | |
247 | |
248 void CrasAudioHandler::SetupInitialAudioState() { | |
249 ApplyAudioPolicy(); | |
250 | |
251 // Set the initial audio state to the ones read from audio prefs. | |
252 output_mute_on_ = | |
253 (local_state_->GetInteger(prefs::kAudioMute) == kPrefOutputMuteOn); | |
254 output_volume_ = local_state_->GetDouble(prefs::kAudioVolumePercent); | |
255 SetOutputMute(output_mute_on_); | |
256 SetOutputVolumeInternal(output_volume_); | |
257 | |
258 // Get the initial audio data. | |
259 GetNodes(); | |
260 } | |
261 | |
262 void CrasAudioHandler::ApplyAudioPolicy() { | |
263 output_mute_locked_ = false; | |
264 if (!local_state_->GetBoolean(prefs::kAudioOutputAllowed)) { | |
265 SetOutputMute(true); | |
266 output_mute_locked_ = true; | |
267 } | |
268 | |
269 input_mute_locked_ = false; | |
270 if (local_state_->GetBoolean(prefs::kAudioCaptureAllowed)) { | |
271 SetInputMute(false); | |
272 } else { | |
273 SetInputMute(true); | |
274 input_mute_locked_ = true; | |
275 } | |
276 } | |
277 | |
278 void CrasAudioHandler::SetOutputVolumeInternal(int volume) { | |
279 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | |
280 SetOutputVolume(volume); | |
281 } | |
282 | |
283 void CrasAudioHandler::GetNodes() { | |
284 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( | |
285 base::Bind(&CrasAudioHandler::HandleGetNodes, | |
286 weak_ptr_factory_.GetWeakPtr())); | |
287 } | |
288 | |
289 void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list, | |
290 bool success) { | |
291 if (!success) { | |
292 LOG(ERROR) << "Failed to retrieve audio nodes data"; | |
293 return; | |
294 } | |
295 | |
296 audio_nodes_.clear(); | |
297 for (size_t i = 0; i < node_list.size(); ++i) { | |
298 if (node_list[i].is_input && node_list[i].active) | |
299 active_input_node_id_ = node_list[i].id; | |
300 else if (!node_list[i].is_input && node_list[i].active) | |
301 active_output_node_id_ = node_list[i].id; | |
302 audio_nodes_.push_back(node_list[i]); | |
303 } | |
304 | |
305 FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged()); | |
306 } | |
307 | |
308 } // namespace chromeos | |
OLD | NEW |