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

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

Issue 596603002: Supports multiple active input/output audio nodes in CrasAudioHandler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix another api name change in shell_audio_controller_chromeos_unittest.cc. Created 6 years, 3 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 <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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698