OLD | NEW |
---|---|
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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 | 163 |
164 int CrasAudioHandler::GetInputGainPercentForDevice(uint64 device_id) { | 164 int CrasAudioHandler::GetInputGainPercentForDevice(uint64 device_id) { |
165 if (device_id == active_input_node_id_) { | 165 if (device_id == active_input_node_id_) { |
166 return input_gain_; | 166 return input_gain_; |
167 } else { | 167 } else { |
168 const AudioDevice* device = GetDeviceFromId(device_id); | 168 const AudioDevice* device = GetDeviceFromId(device_id); |
169 return static_cast<int>(audio_pref_handler_->GetInputGainValue(device)); | 169 return static_cast<int>(audio_pref_handler_->GetInputGainValue(device)); |
170 } | 170 } |
171 } | 171 } |
172 | 172 |
173 uint64 CrasAudioHandler::GetActiveOutputNode() const { | 173 uint64 CrasAudioHandler::GetPrimaryActiveOutputNode() const { |
174 return active_output_node_id_; | 174 return active_output_node_id_; |
175 } | 175 } |
176 | 176 |
177 uint64 CrasAudioHandler::GetActiveInputNode() const { | 177 uint64 CrasAudioHandler::GetPrimaryActiveInputNode() const { |
178 return active_input_node_id_; | 178 return active_input_node_id_; |
179 } | 179 } |
180 | 180 |
181 void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const { | 181 void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const { |
182 device_list->clear(); | 182 device_list->clear(); |
183 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); | 183 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); |
184 it != audio_devices_.end(); ++it) | 184 it != audio_devices_.end(); ++it) |
185 device_list->push_back(it->second); | 185 device_list->push_back(it->second); |
186 } | 186 } |
187 | 187 |
188 bool CrasAudioHandler::GetActiveOutputDevice(AudioDevice* device) const { | 188 bool CrasAudioHandler::GetPrimaryActiveOutputDevice(AudioDevice* device) const { |
189 const AudioDevice* active_device = GetDeviceFromId(active_output_node_id_); | 189 const AudioDevice* active_device = GetDeviceFromId(active_output_node_id_); |
190 if (!active_device || !device) | 190 if (!active_device || !device) |
191 return false; | 191 return false; |
192 *device = *active_device; | 192 *device = *active_device; |
193 return true; | 193 return true; |
194 } | 194 } |
195 | 195 |
196 void CrasAudioHandler::SetKeyboardMicActive(bool active) { | 196 void CrasAudioHandler::SetKeyboardMicActive(bool active) { |
197 const AudioDevice* keyboard_mic = GetKeyboardMic(); | 197 const AudioDevice* keyboard_mic = GetKeyboardMic(); |
198 if (!keyboard_mic) | 198 if (!keyboard_mic) |
199 return; | 199 return; |
200 if (active) { | 200 // Keyboard mic is invisible to chromeos users. It is always added or removed |
201 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 201 // as additional active node. |
202 AddActiveInputNode(keyboard_mic->id); | 202 DCHECK(active_input_node_id_ && active_input_node_id_ != keyboard_mic->id); |
203 } else { | 203 if (active) |
204 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 204 AddActiveNode(keyboard_mic->id); |
205 RemoveActiveInputNode(keyboard_mic->id); | 205 else |
206 RemoveActiveNode(keyboard_mic->id); | |
207 } | |
208 | |
209 void CrasAudioHandler::AddActiveNode(uint64 node_id) { | |
210 const AudioDevice* device = GetDeviceFromId(node_id); | |
211 if (!device) { | |
212 VLOG(1) << "AddActiveInputNode: Cannot find device id=" | |
213 << "0x" << std::hex << node_id; | |
214 return; | |
215 } | |
216 | |
217 // If there is no primary active device, set |node_id| to primary active node. | |
218 if ((device->is_input && !active_input_node_id_) || | |
219 (!device->is_input && !active_output_node_id_)) { | |
220 SwitchToDevice(*device); | |
221 return; | |
222 } | |
223 AddAdditionalActiveNode(node_id); | |
224 } | |
225 | |
226 void CrasAudioHandler::RemoveActiveNode(uint64 node_id) { | |
227 const AudioDevice* device = GetDeviceFromId(node_id); | |
228 if (!device) { | |
229 VLOG(1) << "RemoveActiveInputNode: Cannot find device id=" | |
230 << "0x" << std::hex << node_id; | |
231 return; | |
232 } | |
233 | |
234 // We only allow to remove the primary active node if it is | |
235 // the only active node. | |
rkc
2014/09/24 01:22:43
Why?
jennyz
2014/09/24 18:01:20
CrasAudioHandler and Cras need to consistently mai
rkc
2014/09/24 19:45:29
I agree - we should not allow this particular meth
| |
236 if (device->is_input && device->id == active_input_node_id_ && | |
237 HasAdditionalActiveInputNode()) { | |
hychao
2014/09/24 04:25:47
would this be simpler if we just don't allow the p
jennyz
2014/09/24 18:01:20
Yes, that's even better.
| |
238 VLOG(1) << "Cannot remove the primary active input node: " | |
239 << "0x" << std::hex << node_id; | |
240 return; | |
241 } | |
242 if (!device->is_input && device->id == active_output_node_id_ && | |
243 HasAdditionalActiveOutputNode()) { | |
244 VLOG(1) << "Cannot remove the primary active output node: " | |
245 << "0x" << std::hex << node_id; | |
246 return; | |
247 } | |
248 RemoveActiveNodeInternal(node_id); | |
249 } | |
250 | |
251 void CrasAudioHandler::RemoveAllActiveNodes() { | |
252 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); | |
253 it != audio_devices_.end(); | |
254 ++it) { | |
255 RemoveActiveNodeInternal(it->second.id); | |
206 } | 256 } |
207 } | 257 } |
208 | 258 |
209 bool CrasAudioHandler::has_alternative_input() const { | 259 bool CrasAudioHandler::has_alternative_input() const { |
210 return has_alternative_input_; | 260 return has_alternative_input_; |
211 } | 261 } |
212 | 262 |
213 bool CrasAudioHandler::has_alternative_output() const { | 263 bool CrasAudioHandler::has_alternative_output() const { |
214 return has_alternative_output_; | 264 return has_alternative_output_; |
215 } | 265 } |
216 | 266 |
217 void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) { | 267 void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) { |
218 volume_percent = min(max(volume_percent, 0), 100); | 268 // Set all active devices to the same volume. |
219 if (volume_percent <= kMuteThresholdPercent) | 269 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); |
220 volume_percent = 0; | 270 it != audio_devices_.end(); |
221 output_volume_ = volume_percent; | 271 it++) { |
222 | 272 const AudioDevice& device = it->second; |
223 if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_)) | 273 if (!device.is_input && device.active) |
224 audio_pref_handler_->SetVolumeGainValue(*device, output_volume_); | 274 SetOutputNodeVolumePercent(device.id, volume_percent); |
225 | 275 } |
226 SetOutputNodeVolume(active_output_node_id_, output_volume_); | |
227 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged()); | |
228 } | 276 } |
229 | 277 |
230 // TODO: Rename the 'Percent' to something more meaningful. | 278 // TODO: Rename the 'Percent' to something more meaningful. |
231 void CrasAudioHandler::SetInputGainPercent(int gain_percent) { | 279 void CrasAudioHandler::SetInputGainPercent(int gain_percent) { |
232 // NOTE: We do not sanitize input gain values since the range is completely | 280 // TODO(jennyz): Should we set all input devices' gain to the same level? |
233 // dependent on the device. | 281 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); |
234 input_gain_ = gain_percent; | 282 it != audio_devices_.end(); |
235 | 283 it++) { |
236 if (const AudioDevice* device = GetDeviceFromId(active_input_node_id_)) | 284 const AudioDevice& device = it->second; |
237 audio_pref_handler_->SetVolumeGainValue(*device, input_gain_); | 285 if (device.is_input && device.active) |
238 | 286 SetInputNodeGainPercent(active_input_node_id_, gain_percent); |
239 SetInputNodeGain(active_input_node_id_, input_gain_); | 287 } |
240 FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged()); | |
241 } | 288 } |
242 | 289 |
243 void CrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) { | 290 void CrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) { |
244 SetOutputVolumePercent(output_volume_ + adjust_by_percent); | 291 SetOutputVolumePercent(output_volume_ + adjust_by_percent); |
245 } | 292 } |
246 | 293 |
247 void CrasAudioHandler::SetOutputMute(bool mute_on) { | 294 void CrasAudioHandler::SetOutputMute(bool mute_on) { |
248 if (!SetOutputMuteInternal(mute_on)) | 295 if (!SetOutputMuteInternal(mute_on)) |
249 return; | 296 return; |
250 | 297 |
251 if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_)) { | 298 // Save the mute state for all active output audio devices. |
252 DCHECK(!device->is_input); | 299 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); |
253 audio_pref_handler_->SetMuteValue(*device, output_mute_on_); | 300 it != audio_devices_.end(); |
301 it++) { | |
302 const AudioDevice& device = it->second; | |
303 if (!device.is_input && device.active) { | |
304 audio_pref_handler_->SetMuteValue(device, output_mute_on_); | |
305 } | |
254 } | 306 } |
255 | 307 |
256 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputMuteChanged()); | 308 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputMuteChanged()); |
257 } | 309 } |
258 | 310 |
259 void CrasAudioHandler::AdjustOutputVolumeToAudibleLevel() { | 311 void CrasAudioHandler::AdjustOutputVolumeToAudibleLevel() { |
260 if (output_volume_ <= kMuteThresholdPercent) { | 312 if (output_volume_ <= kMuteThresholdPercent) { |
261 // Avoid the situation when sound has been unmuted, but the volume | 313 // Avoid the situation when sound has been unmuted, but the volume |
262 // is set to a very low value, so user still can't hear any sound. | 314 // is set to a very low value, so user still can't hear any sound. |
263 SetOutputVolumePercent(kDefaultUnmuteVolumePercent); | 315 SetOutputVolumePercent(kDefaultUnmuteVolumePercent); |
(...skipping 14 matching lines...) Expand all Loading... | |
278 } | 330 } |
279 | 331 |
280 void CrasAudioHandler::SetActiveInputNode(uint64 node_id) { | 332 void CrasAudioHandler::SetActiveInputNode(uint64 node_id) { |
281 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 333 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
282 SetActiveInputNode(node_id); | 334 SetActiveInputNode(node_id); |
283 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); | 335 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); |
284 } | 336 } |
285 | 337 |
286 void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64 device_id, | 338 void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64 device_id, |
287 int value) { | 339 int value) { |
288 if (device_id == active_output_node_id_) { | 340 const AudioDevice* device = GetDeviceFromId(device_id); |
289 SetOutputVolumePercent(value); | 341 if (!device) |
290 return; | 342 return; |
291 } else if (device_id == active_input_node_id_) { | |
292 SetInputGainPercent(value); | |
293 return; | |
294 } | |
295 | 343 |
296 if (const AudioDevice* device = GetDeviceFromId(device_id)) { | 344 if (device->is_input) |
297 if (!device->is_input) { | 345 SetInputNodeGainPercent(device_id, value); |
298 value = min(max(value, 0), 100); | 346 else |
299 if (value <= kMuteThresholdPercent) | 347 SetOutputNodeVolumePercent(device_id, value); |
300 value = 0; | |
301 } | |
302 audio_pref_handler_->SetVolumeGainValue(*device, value); | |
303 } | |
304 } | 348 } |
305 | 349 |
306 void CrasAudioHandler::SetMuteForDevice(uint64 device_id, bool mute_on) { | 350 void CrasAudioHandler::SetMuteForDevice(uint64 device_id, bool mute_on) { |
307 if (device_id == active_output_node_id_) { | 351 if (device_id == active_output_node_id_) { |
308 SetOutputMute(mute_on); | 352 SetOutputMute(mute_on); |
309 return; | 353 return; |
310 } else if (device_id == active_input_node_id_) { | 354 } else if (device_id == active_input_node_id_) { |
311 VLOG(1) << "SetMuteForDevice sets active input device id=" | 355 VLOG(1) << "SetMuteForDevice sets active input device id=" |
312 << "0x" << std::hex << device_id << " mute=" << mute_on; | 356 << "0x" << std::hex << device_id << " mute=" << mute_on; |
313 SetInputMute(mute_on); | 357 SetInputMute(mute_on); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 | 416 |
373 void CrasAudioHandler::AudioClientRestarted() { | 417 void CrasAudioHandler::AudioClientRestarted() { |
374 // Make sure the logging is enabled in case cras server | 418 // Make sure the logging is enabled in case cras server |
375 // restarts after crashing. | 419 // restarts after crashing. |
376 LogErrors(); | 420 LogErrors(); |
377 InitializeAudioState(); | 421 InitializeAudioState(); |
378 } | 422 } |
379 | 423 |
380 void CrasAudioHandler::NodesChanged() { | 424 void CrasAudioHandler::NodesChanged() { |
381 // Refresh audio nodes data. | 425 // Refresh audio nodes data. |
382 GetNodes(); | 426 GetNodes(true); // NodesChanged signal received. |
383 } | 427 } |
384 | 428 |
385 void CrasAudioHandler::ActiveOutputNodeChanged(uint64 node_id) { | 429 void CrasAudioHandler::ActiveOutputNodeChanged(uint64 node_id) { |
386 if (active_output_node_id_ == node_id) | 430 if (active_output_node_id_ == node_id) |
387 return; | 431 return; |
388 | 432 |
389 // Active audio output device should always be changed by chrome. | 433 // Active audio output device should always be changed by chrome. |
390 // During system boot, cras may change active input to unknown device 0x1, | 434 // During system boot, cras may change active input to unknown device 0x1, |
391 // we don't need to log it, since it is not an valid device. | 435 // we don't need to log it, since it is not an valid device. |
392 if (GetDeviceFromId(node_id)) { | 436 if (GetDeviceFromId(node_id)) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
463 return; | 507 return; |
464 } | 508 } |
465 DCHECK(!device->is_input); | 509 DCHECK(!device->is_input); |
466 output_mute_on_ = audio_pref_handler_->GetMuteValue(*device); | 510 output_mute_on_ = audio_pref_handler_->GetMuteValue(*device); |
467 output_volume_ = audio_pref_handler_->GetOutputVolumeValue(device); | 511 output_volume_ = audio_pref_handler_->GetOutputVolumeValue(device); |
468 | 512 |
469 SetOutputMuteInternal(output_mute_on_); | 513 SetOutputMuteInternal(output_mute_on_); |
470 SetOutputNodeVolume(active_output_node_id_, output_volume_); | 514 SetOutputNodeVolume(active_output_node_id_, output_volume_); |
471 } | 515 } |
472 | 516 |
517 // This sets up the state of an additional active node. | |
518 void CrasAudioHandler::SetupAdditionalActiveAudioNodeState(uint64 node_id) { | |
519 const AudioDevice* device = GetDeviceFromId(node_id); | |
520 if (!device) { | |
521 VLOG(1) << "Can't set up audio state for unknown device id =" | |
522 << "0x" << std::hex << node_id; | |
523 return; | |
524 } | |
525 | |
526 DCHECK(node_id != active_output_node_id_ && node_id != active_input_node_id_); | |
527 | |
528 // Note: The mute state is a system wide state, we don't set mute per device, | |
529 // but just keep the mute state consistent for the active node in prefs. | |
530 // The output volume should be set to the same value for all active output | |
531 // devices. For input devices, we don't restore their gain value so far. | |
rkc
2014/09/24 01:22:43
I don't recall the reason exactly, but I believe t
jennyz
2014/09/24 18:01:20
I also remembered this might be a hack to fix some
rkc
2014/09/24 19:45:30
That sounds fine. Please do create a bug to track
jennyz
2014/09/24 20:47:18
Done.
| |
532 if (!device->is_input) { | |
533 audio_pref_handler_->SetMuteValue(*device, IsOutputMuted()); | |
534 SetOutputNodeVolumePercent(node_id, GetOutputVolumePercent()); | |
535 } | |
536 } | |
537 | |
473 void CrasAudioHandler::InitializeAudioState() { | 538 void CrasAudioHandler::InitializeAudioState() { |
474 ApplyAudioPolicy(); | 539 ApplyAudioPolicy(); |
475 GetNodes(); | 540 GetNodes(true); |
476 } | 541 } |
477 | 542 |
478 void CrasAudioHandler::ApplyAudioPolicy() { | 543 void CrasAudioHandler::ApplyAudioPolicy() { |
479 output_mute_locked_ = false; | 544 output_mute_locked_ = false; |
480 if (!audio_pref_handler_->GetAudioOutputAllowedValue()) { | 545 if (!audio_pref_handler_->GetAudioOutputAllowedValue()) { |
481 // Mute the device, but do not update the preference. | 546 // Mute the device, but do not update the preference. |
482 SetOutputMuteInternal(true); | 547 SetOutputMuteInternal(true); |
483 output_mute_locked_ = true; | 548 output_mute_locked_ = true; |
484 } else { | 549 } else { |
485 // Restore the mute state. | 550 // Restore the mute state. |
(...skipping 13 matching lines...) Expand all Loading... | |
499 SetInputMuteInternal(true); | 564 SetInputMuteInternal(true); |
500 input_mute_locked_ = true; | 565 input_mute_locked_ = true; |
501 } | 566 } |
502 } | 567 } |
503 | 568 |
504 void CrasAudioHandler::SetOutputNodeVolume(uint64 node_id, int volume) { | 569 void CrasAudioHandler::SetOutputNodeVolume(uint64 node_id, int volume) { |
505 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 570 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
506 SetOutputNodeVolume(node_id, volume); | 571 SetOutputNodeVolume(node_id, volume); |
507 } | 572 } |
508 | 573 |
574 void CrasAudioHandler::SetOutputNodeVolumePercent(uint64 node_id, | |
575 int volume_percent) { | |
576 const AudioDevice* device = this->GetDeviceFromId(node_id); | |
577 if (!device || device->is_input) | |
578 return; | |
579 | |
580 volume_percent = min(max(volume_percent, 0), 100); | |
581 if (volume_percent <= kMuteThresholdPercent) | |
582 volume_percent = 0; | |
583 if (node_id == active_output_node_id_) | |
584 output_volume_ = volume_percent; | |
585 | |
586 audio_pref_handler_->SetVolumeGainValue(*device, volume_percent); | |
587 | |
588 if (device->active) { | |
589 SetOutputNodeVolume(node_id, volume_percent); | |
590 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged()); | |
591 } | |
592 } | |
593 | |
509 bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) { | 594 bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) { |
510 if (output_mute_locked_) | 595 if (output_mute_locked_) |
511 return false; | 596 return false; |
512 | 597 |
513 output_mute_on_ = mute_on; | 598 output_mute_on_ = mute_on; |
514 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 599 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
515 SetOutputUserMute(mute_on); | 600 SetOutputUserMute(mute_on); |
516 return true; | 601 return true; |
517 } | 602 } |
518 | 603 |
519 void CrasAudioHandler::SetInputNodeGain(uint64 node_id, int gain) { | 604 void CrasAudioHandler::SetInputNodeGain(uint64 node_id, int gain) { |
520 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 605 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
521 SetInputNodeGain(node_id, gain); | 606 SetInputNodeGain(node_id, gain); |
522 } | 607 } |
523 | 608 |
609 void CrasAudioHandler::SetInputNodeGainPercent(uint64 node_id, | |
610 int gain_percent) { | |
611 const AudioDevice* device = GetDeviceFromId(node_id); | |
612 if (!device || !device->is_input) | |
613 return; | |
614 | |
615 // NOTE: We do not sanitize input gain values since the range is completely | |
616 // dependent on the device. | |
617 if (active_input_node_id_ == node_id) | |
618 input_gain_ = gain_percent; | |
619 | |
620 audio_pref_handler_->SetVolumeGainValue(*device, gain_percent); | |
621 | |
622 if (device->active) { | |
623 SetInputNodeGain(node_id, gain_percent); | |
624 FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged()); | |
625 } | |
626 } | |
627 | |
524 bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) { | 628 bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) { |
525 if (input_mute_locked_) | 629 if (input_mute_locked_) |
526 return false; | 630 return false; |
527 | 631 |
528 VLOG(1) << "SetInputMuteInternal sets active input device id=" | |
529 << "0x" << std::hex << active_input_node_id_ << " mute=" << mute_on; | |
530 input_mute_on_ = mute_on; | 632 input_mute_on_ = mute_on; |
531 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 633 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
532 SetInputMute(mute_on); | 634 SetInputMute(mute_on); |
533 return true; | 635 return true; |
534 } | 636 } |
535 | 637 |
536 void CrasAudioHandler::GetNodes() { | 638 void CrasAudioHandler::GetNodes(bool nodes_changed) { |
537 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( | 639 if (nodes_changed) { |
538 base::Bind(&CrasAudioHandler::HandleGetNodes, | 640 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( |
539 weak_ptr_factory_.GetWeakPtr()), | 641 base::Bind(&CrasAudioHandler::HandleGetNodes, |
540 base::Bind(&CrasAudioHandler::HandleGetNodesError, | 642 weak_ptr_factory_.GetWeakPtr()), |
541 weak_ptr_factory_.GetWeakPtr())); | 643 base::Bind(&CrasAudioHandler::HandleGetNodesError, |
644 weak_ptr_factory_.GetWeakPtr())); | |
645 } else { | |
646 // If GetNodes is not triggered by NodesChanged signal, | |
rkc
2014/09/24 01:22:43
This code seems unused. Everywhere that GetNodes i
jennyz
2014/09/24 18:01:20
Yes, this is not used in the current code, it coul
rkc
2014/09/24 19:45:29
I am really uncomfortable checking in unused code.
jennyz
2014/09/24 20:47:18
Done.
| |
647 // HandleGetNodesWithoutNodesChange will just retrieve all the | |
648 // nodes data from cras without switching active device. | |
649 // This could be used for diagnostic purpose. | |
650 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( | |
651 base::Bind(&CrasAudioHandler::HandleGetNodesWithoutNodesChange, | |
652 weak_ptr_factory_.GetWeakPtr()), | |
653 base::Bind(&CrasAudioHandler::HandleGetNodesError, | |
654 weak_ptr_factory_.GetWeakPtr())); | |
655 } | |
542 } | 656 } |
543 | 657 |
544 bool CrasAudioHandler::ChangeActiveDevice(const AudioDevice& new_active_device, | 658 bool CrasAudioHandler::ChangeActiveDevice(const AudioDevice& new_active_device, |
545 uint64* current_active_node_id) { | 659 uint64* current_active_node_id) { |
546 // If the device we want to switch to is already the current active device, | 660 // If the device we want to switch to is already the current active device, |
547 // do nothing. | 661 // do nothing. |
548 if (new_active_device.active && | 662 if (new_active_device.active && |
549 new_active_device.id == *current_active_node_id) { | 663 new_active_device.id == *current_active_node_id) { |
550 return false; | 664 return false; |
551 } | 665 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
597 if (is_input == it->second.is_input) | 711 if (is_input == it->second.is_input) |
598 ++num_old_devices; | 712 ++num_old_devices; |
599 } | 713 } |
600 | 714 |
601 for (AudioNodeList::const_iterator it = new_nodes.begin(); | 715 for (AudioNodeList::const_iterator it = new_nodes.begin(); |
602 it != new_nodes.end(); ++it) { | 716 it != new_nodes.end(); ++it) { |
603 if (is_input == it->is_input) { | 717 if (is_input == it->is_input) { |
604 ++num_new_devices; | 718 ++num_new_devices; |
605 // Look to see if the new device not in the old device list. | 719 // Look to see if the new device not in the old device list. |
606 AudioDevice device(*it); | 720 AudioDevice device(*it); |
607 if (FoundNewDevice(device)) | 721 if (FoundNewOrChangedDevice(device)) |
608 return true; | 722 return true; |
609 } | 723 } |
610 } | 724 } |
611 return num_old_devices != num_new_devices; | 725 return num_old_devices != num_new_devices; |
612 } | 726 } |
613 | 727 |
614 bool CrasAudioHandler::FoundNewDevice(const AudioDevice& device) { | 728 bool CrasAudioHandler::FoundNewOrChangedDevice(const AudioDevice& device) { |
615 const AudioDevice* device_found = GetDeviceFromId(device.id); | 729 const AudioDevice* device_found = GetDeviceFromId(device.id); |
616 if (!device_found) | 730 if (!device_found) |
617 return true; | 731 return true; |
618 | 732 |
619 if (!IsSameAudioDevice(device, *device_found)) { | 733 if (!IsSameAudioDevice(device, *device_found)) { |
620 LOG(WARNING) << "Different Audio devices with same id:" | 734 LOG(WARNING) << "Different Audio devices with same id:" |
621 << " new device: " << device.ToString() | 735 << " new device: " << device.ToString() |
622 << " old device: " << device_found->ToString(); | 736 << " old device: " << device_found->ToString(); |
623 return true; | 737 return true; |
738 } else if (device.active != device_found->active) { | |
739 return true; | |
740 } | |
741 | |
742 return false; | |
743 } | |
744 | |
745 bool CrasAudioHandler::HasAdditionalActiveOutputNode() const { | |
746 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); | |
747 it != audio_devices_.end(); | |
748 ++it) { | |
749 if (active_output_node_id_ && !it->second.is_input && it->second.active && | |
750 it->second.id != active_output_node_id_) { | |
751 return true; | |
752 } | |
624 } | 753 } |
625 return false; | 754 return false; |
626 } | 755 } |
627 | 756 |
628 // Sanitize the audio node data. When a device is plugged in or unplugged, there | 757 bool CrasAudioHandler::HasAdditionalActiveInputNode() const { |
629 // should be only one NodesChanged signal from cras. However, we've observed | 758 for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); |
630 // the case that multiple NodesChanged signals being sent from cras. After the | 759 it != audio_devices_.end(); |
631 // first NodesChanged being processed, chrome sets the active node properly. | 760 ++it) { |
632 // However, the NodesChanged received after the first one, can return stale | 761 if (active_input_node_id_ && it->second.is_input && it->second.active && |
633 // nodes data in GetNodes call, the staled nodes data does not reflect the | 762 it->second.id != active_input_node_id_) { |
634 // latest active node state. Since active audio node should only be set by | 763 return true; |
635 // chrome, the inconsistent data from cras could be the result of stale data | |
636 // described above and sanitized. | |
637 AudioDevice CrasAudioHandler::GetSanitizedAudioDevice(const AudioNode& node) { | |
638 AudioDevice device(node); | |
639 if (device.is_input) { | |
640 if (device.active && device.id != active_input_node_id_) { | |
641 LOG(WARNING) << "Stale audio device data, should not be active: " | |
642 << " device = " << device.ToString() | |
643 << " current active input node id = 0x" << std::hex | |
644 << active_input_node_id_; | |
645 device.active = false; | |
646 } else if (device.id == active_input_node_id_ && !device.active) { | |
647 LOG(WARNING) << "Stale audio device data, should be active:" | |
648 << " device = " << device.ToString() | |
649 << " current active input node id = 0x" << std::hex | |
650 << active_input_node_id_; | |
651 device.active = true; | |
652 } | |
653 } else { | |
654 if (device.active && device.id != active_output_node_id_) { | |
655 LOG(WARNING) << "Stale audio device data, should not be active: " | |
656 << " device = " << device.ToString() | |
657 << " current active output node id = 0x" << std::hex | |
658 << active_output_node_id_; | |
659 device.active = false; | |
660 } else if (device.id == active_output_node_id_ && !device.active) { | |
661 LOG(WARNING) << "Stale audio device data, should be active:" | |
662 << " device = " << device.ToString() | |
663 << " current active output node id = 0x" << std::hex | |
664 << active_output_node_id_; | |
665 device.active = true; | |
666 } | 764 } |
667 } | 765 } |
668 return device; | 766 return false; |
669 } | 767 } |
670 | 768 |
671 void CrasAudioHandler::UpdateDevicesAndSwitchActive( | 769 void CrasAudioHandler::UpdateDevicesAndSwitchActive( |
672 const AudioNodeList& nodes) { | 770 const AudioNodeList& nodes) { |
673 size_t old_audio_devices_size = audio_devices_.size(); | 771 size_t old_audio_devices_size = audio_devices_.size(); |
674 bool output_devices_changed = HasDeviceChange(nodes, false); | 772 bool output_devices_changed = HasDeviceChange(nodes, false); |
675 bool input_devices_changed = HasDeviceChange(nodes, true); | 773 bool input_devices_changed = HasDeviceChange(nodes, true); |
676 audio_devices_.clear(); | 774 audio_devices_.clear(); |
677 has_alternative_input_ = false; | 775 has_alternative_input_ = false; |
678 has_alternative_output_ = false; | 776 has_alternative_output_ = false; |
679 | 777 |
680 while (!input_devices_pq_.empty()) | 778 while (!input_devices_pq_.empty()) |
681 input_devices_pq_.pop(); | 779 input_devices_pq_.pop(); |
682 while (!output_devices_pq_.empty()) | 780 while (!output_devices_pq_.empty()) |
683 output_devices_pq_.pop(); | 781 output_devices_pq_.pop(); |
684 | 782 |
685 for (size_t i = 0; i < nodes.size(); ++i) { | 783 for (size_t i = 0; i < nodes.size(); ++i) { |
686 AudioDevice device = GetSanitizedAudioDevice(nodes[i]); | 784 AudioDevice device(nodes[i]); |
687 audio_devices_[device.id] = device; | 785 audio_devices_[device.id] = device; |
688 | 786 |
689 if (!has_alternative_input_ && | 787 if (!has_alternative_input_ && |
690 device.is_input && | 788 device.is_input && |
691 device.type != AUDIO_TYPE_INTERNAL_MIC && | 789 device.type != AUDIO_TYPE_INTERNAL_MIC && |
692 device.type != AUDIO_TYPE_KEYBOARD_MIC) { | 790 device.type != AUDIO_TYPE_KEYBOARD_MIC) { |
693 has_alternative_input_ = true; | 791 has_alternative_input_ = true; |
694 } else if (!has_alternative_output_ && | 792 } else if (!has_alternative_output_ && |
695 !device.is_input && | 793 !device.is_input && |
696 device.type != AUDIO_TYPE_INTERNAL_SPEAKER) { | 794 device.type != AUDIO_TYPE_INTERNAL_SPEAKER) { |
(...skipping 28 matching lines...) Expand all Loading... | |
725 bool success) { | 823 bool success) { |
726 if (!success) { | 824 if (!success) { |
727 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data"; | 825 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data"; |
728 return; | 826 return; |
729 } | 827 } |
730 | 828 |
731 UpdateDevicesAndSwitchActive(node_list); | 829 UpdateDevicesAndSwitchActive(node_list); |
732 FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged()); | 830 FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged()); |
733 } | 831 } |
734 | 832 |
833 void CrasAudioHandler::HandleGetNodesWithoutNodesChange( | |
834 const chromeos::AudioNodeList& node_list, | |
835 bool success) { | |
836 if (!success) { | |
837 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data"; | |
838 return; | |
839 } | |
840 | |
841 // Just refresh the audio_devices_ with the latest audio_list from cras. | |
842 for (size_t i = 0; i < node_list.size(); ++i) { | |
843 AudioDevice device(node_list[i]); | |
844 audio_devices_[device.id] = device; | |
845 } | |
846 } | |
847 | |
735 void CrasAudioHandler::HandleGetNodesError(const std::string& error_name, | 848 void CrasAudioHandler::HandleGetNodesError(const std::string& error_name, |
736 const std::string& error_msg) { | 849 const std::string& error_msg) { |
737 LOG_IF(ERROR, log_errors_) << "Failed to call GetNodes: " | 850 LOG_IF(ERROR, log_errors_) << "Failed to call GetNodes: " |
738 << error_name << ": " << error_msg; | 851 << error_name << ": " << error_msg; |
739 } | 852 } |
853 | |
854 void CrasAudioHandler::AddAdditionalActiveNode(uint64 node_id) { | |
855 const AudioDevice* device = GetDeviceFromId(node_id); | |
856 if (!device) { | |
857 VLOG(1) << "AddActiveInputNode: Cannot find device id=" | |
858 << "0x" << std::hex << node_id; | |
859 return; | |
860 } | |
861 | |
862 audio_devices_[node_id].active = true; | |
863 SetupAdditionalActiveAudioNodeState(node_id); | |
864 | |
865 if (device->is_input) { | |
866 DCHECK(node_id != active_input_node_id_); | |
867 chromeos::DBusThreadManager::Get() | |
868 ->GetCrasAudioClient() | |
869 ->AddActiveInputNode(node_id); | |
870 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); | |
871 } else { | |
872 DCHECK(node_id != active_output_node_id_); | |
873 chromeos::DBusThreadManager::Get() | |
874 ->GetCrasAudioClient() | |
875 ->AddActiveOutputNode(node_id); | |
876 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged()); | |
877 } | |
878 } | |
879 | |
880 void CrasAudioHandler::RemoveActiveNodeInternal(uint64 node_id) { | |
881 const AudioDevice* device = GetDeviceFromId(node_id); | |
882 if (!device) { | |
883 VLOG(1) << "RemoveActiveInputNode: Cannot find device id=" | |
884 << "0x" << std::hex << node_id; | |
885 return; | |
886 } | |
887 | |
888 audio_devices_[node_id].active = false; | |
889 if (device->is_input) { | |
890 if (node_id == active_input_node_id_) | |
891 active_input_node_id_ = 0; | |
892 chromeos::DBusThreadManager::Get() | |
893 ->GetCrasAudioClient() | |
894 ->RemoveActiveInputNode(node_id); | |
895 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); | |
896 } else { | |
897 if (node_id == active_output_node_id_) | |
898 active_output_node_id_ = 0; | |
899 chromeos::DBusThreadManager::Get() | |
900 ->GetCrasAudioClient() | |
901 ->RemoveActiveOutputNode(node_id); | |
902 } | |
903 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged()); | |
904 } | |
905 | |
740 } // namespace chromeos | 906 } // namespace chromeos |
OLD | NEW |