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

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

Powered by Google App Engine
This is Rietveld 408576698