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 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 Loading... |
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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 // TODO(jennyz): crbug.com/417418, track the status for the decison if |
| 530 // we should persist input gain value in prefs. |
| 531 if (!device->is_input) { |
| 532 audio_pref_handler_->SetMuteValue(*device, IsOutputMuted()); |
| 533 SetOutputNodeVolumePercent(node_id, GetOutputVolumePercent()); |
| 534 } |
| 535 } |
| 536 |
473 void CrasAudioHandler::InitializeAudioState() { | 537 void CrasAudioHandler::InitializeAudioState() { |
474 ApplyAudioPolicy(); | 538 ApplyAudioPolicy(); |
475 GetNodes(); | 539 GetNodes(); |
476 } | 540 } |
477 | 541 |
478 void CrasAudioHandler::ApplyAudioPolicy() { | 542 void CrasAudioHandler::ApplyAudioPolicy() { |
479 output_mute_locked_ = false; | 543 output_mute_locked_ = false; |
480 if (!audio_pref_handler_->GetAudioOutputAllowedValue()) { | 544 if (!audio_pref_handler_->GetAudioOutputAllowedValue()) { |
481 // Mute the device, but do not update the preference. | 545 // Mute the device, but do not update the preference. |
482 SetOutputMuteInternal(true); | 546 SetOutputMuteInternal(true); |
(...skipping 16 matching lines...) Expand all Loading... |
499 SetInputMuteInternal(true); | 563 SetInputMuteInternal(true); |
500 input_mute_locked_ = true; | 564 input_mute_locked_ = true; |
501 } | 565 } |
502 } | 566 } |
503 | 567 |
504 void CrasAudioHandler::SetOutputNodeVolume(uint64 node_id, int volume) { | 568 void CrasAudioHandler::SetOutputNodeVolume(uint64 node_id, int volume) { |
505 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 569 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
506 SetOutputNodeVolume(node_id, volume); | 570 SetOutputNodeVolume(node_id, volume); |
507 } | 571 } |
508 | 572 |
| 573 void CrasAudioHandler::SetOutputNodeVolumePercent(uint64 node_id, |
| 574 int volume_percent) { |
| 575 const AudioDevice* device = this->GetDeviceFromId(node_id); |
| 576 if (!device || device->is_input) |
| 577 return; |
| 578 |
| 579 volume_percent = min(max(volume_percent, 0), 100); |
| 580 if (volume_percent <= kMuteThresholdPercent) |
| 581 volume_percent = 0; |
| 582 if (node_id == active_output_node_id_) |
| 583 output_volume_ = volume_percent; |
| 584 |
| 585 audio_pref_handler_->SetVolumeGainValue(*device, volume_percent); |
| 586 |
| 587 if (device->active) { |
| 588 SetOutputNodeVolume(node_id, volume_percent); |
| 589 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged()); |
| 590 } |
| 591 } |
| 592 |
509 bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) { | 593 bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) { |
510 if (output_mute_locked_) | 594 if (output_mute_locked_) |
511 return false; | 595 return false; |
512 | 596 |
513 output_mute_on_ = mute_on; | 597 output_mute_on_ = mute_on; |
514 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 598 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
515 SetOutputUserMute(mute_on); | 599 SetOutputUserMute(mute_on); |
516 return true; | 600 return true; |
517 } | 601 } |
518 | 602 |
519 void CrasAudioHandler::SetInputNodeGain(uint64 node_id, int gain) { | 603 void CrasAudioHandler::SetInputNodeGain(uint64 node_id, int gain) { |
520 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 604 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
521 SetInputNodeGain(node_id, gain); | 605 SetInputNodeGain(node_id, gain); |
522 } | 606 } |
523 | 607 |
| 608 void CrasAudioHandler::SetInputNodeGainPercent(uint64 node_id, |
| 609 int gain_percent) { |
| 610 const AudioDevice* device = GetDeviceFromId(node_id); |
| 611 if (!device || !device->is_input) |
| 612 return; |
| 613 |
| 614 // NOTE: We do not sanitize input gain values since the range is completely |
| 615 // dependent on the device. |
| 616 if (active_input_node_id_ == node_id) |
| 617 input_gain_ = gain_percent; |
| 618 |
| 619 audio_pref_handler_->SetVolumeGainValue(*device, gain_percent); |
| 620 |
| 621 if (device->active) { |
| 622 SetInputNodeGain(node_id, gain_percent); |
| 623 FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged()); |
| 624 } |
| 625 } |
| 626 |
524 bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) { | 627 bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) { |
525 if (input_mute_locked_) | 628 if (input_mute_locked_) |
526 return false; | 629 return false; |
527 | 630 |
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; | 631 input_mute_on_ = mute_on; |
531 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> | 632 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> |
532 SetInputMute(mute_on); | 633 SetInputMute(mute_on); |
533 return true; | 634 return true; |
534 } | 635 } |
535 | 636 |
536 void CrasAudioHandler::GetNodes() { | 637 void CrasAudioHandler::GetNodes() { |
537 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( | 638 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes( |
538 base::Bind(&CrasAudioHandler::HandleGetNodes, | 639 base::Bind(&CrasAudioHandler::HandleGetNodes, |
539 weak_ptr_factory_.GetWeakPtr()), | 640 weak_ptr_factory_.GetWeakPtr()), |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 if (is_input == it->second.is_input) | 698 if (is_input == it->second.is_input) |
598 ++num_old_devices; | 699 ++num_old_devices; |
599 } | 700 } |
600 | 701 |
601 for (AudioNodeList::const_iterator it = new_nodes.begin(); | 702 for (AudioNodeList::const_iterator it = new_nodes.begin(); |
602 it != new_nodes.end(); ++it) { | 703 it != new_nodes.end(); ++it) { |
603 if (is_input == it->is_input) { | 704 if (is_input == it->is_input) { |
604 ++num_new_devices; | 705 ++num_new_devices; |
605 // Look to see if the new device not in the old device list. | 706 // Look to see if the new device not in the old device list. |
606 AudioDevice device(*it); | 707 AudioDevice device(*it); |
607 if (FoundNewDevice(device)) | 708 if (FoundNewOrChangedDevice(device)) |
608 return true; | 709 return true; |
609 } | 710 } |
610 } | 711 } |
611 return num_old_devices != num_new_devices; | 712 return num_old_devices != num_new_devices; |
612 } | 713 } |
613 | 714 |
614 bool CrasAudioHandler::FoundNewDevice(const AudioDevice& device) { | 715 bool CrasAudioHandler::FoundNewOrChangedDevice(const AudioDevice& device) { |
615 const AudioDevice* device_found = GetDeviceFromId(device.id); | 716 const AudioDevice* device_found = GetDeviceFromId(device.id); |
616 if (!device_found) | 717 if (!device_found) |
617 return true; | 718 return true; |
618 | 719 |
619 if (!IsSameAudioDevice(device, *device_found)) { | 720 if (!IsSameAudioDevice(device, *device_found)) { |
620 LOG(WARNING) << "Different Audio devices with same id:" | 721 LOG(WARNING) << "Different Audio devices with same id:" |
621 << " new device: " << device.ToString() | 722 << " new device: " << device.ToString() |
622 << " old device: " << device_found->ToString(); | 723 << " old device: " << device_found->ToString(); |
623 return true; | 724 return true; |
| 725 } else if (device.active != device_found->active) { |
| 726 return true; |
624 } | 727 } |
| 728 |
625 return false; | 729 return false; |
626 } | 730 } |
627 | 731 |
628 // Sanitize the audio node data. When a device is plugged in or unplugged, there | |
629 // should be only one NodesChanged signal from cras. However, we've observed | |
630 // the case that multiple NodesChanged signals being sent from cras. After the | |
631 // first NodesChanged being processed, chrome sets the active node properly. | |
632 // However, the NodesChanged received after the first one, can return stale | |
633 // nodes data in GetNodes call, the staled nodes data does not reflect the | |
634 // latest active node state. Since active audio node should only be set by | |
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 } | |
667 } | |
668 return device; | |
669 } | |
670 | |
671 void CrasAudioHandler::UpdateDevicesAndSwitchActive( | 732 void CrasAudioHandler::UpdateDevicesAndSwitchActive( |
672 const AudioNodeList& nodes) { | 733 const AudioNodeList& nodes) { |
673 size_t old_audio_devices_size = audio_devices_.size(); | 734 size_t old_audio_devices_size = audio_devices_.size(); |
674 bool output_devices_changed = HasDeviceChange(nodes, false); | 735 bool output_devices_changed = HasDeviceChange(nodes, false); |
675 bool input_devices_changed = HasDeviceChange(nodes, true); | 736 bool input_devices_changed = HasDeviceChange(nodes, true); |
676 audio_devices_.clear(); | 737 audio_devices_.clear(); |
677 has_alternative_input_ = false; | 738 has_alternative_input_ = false; |
678 has_alternative_output_ = false; | 739 has_alternative_output_ = false; |
679 | 740 |
680 while (!input_devices_pq_.empty()) | 741 while (!input_devices_pq_.empty()) |
681 input_devices_pq_.pop(); | 742 input_devices_pq_.pop(); |
682 while (!output_devices_pq_.empty()) | 743 while (!output_devices_pq_.empty()) |
683 output_devices_pq_.pop(); | 744 output_devices_pq_.pop(); |
684 | 745 |
685 for (size_t i = 0; i < nodes.size(); ++i) { | 746 for (size_t i = 0; i < nodes.size(); ++i) { |
686 AudioDevice device = GetSanitizedAudioDevice(nodes[i]); | 747 AudioDevice device(nodes[i]); |
687 audio_devices_[device.id] = device; | 748 audio_devices_[device.id] = device; |
688 | 749 |
689 if (!has_alternative_input_ && | 750 if (!has_alternative_input_ && |
690 device.is_input && | 751 device.is_input && |
691 device.type != AUDIO_TYPE_INTERNAL_MIC && | 752 device.type != AUDIO_TYPE_INTERNAL_MIC && |
692 device.type != AUDIO_TYPE_KEYBOARD_MIC) { | 753 device.type != AUDIO_TYPE_KEYBOARD_MIC) { |
693 has_alternative_input_ = true; | 754 has_alternative_input_ = true; |
694 } else if (!has_alternative_output_ && | 755 } else if (!has_alternative_output_ && |
695 !device.is_input && | 756 !device.is_input && |
696 device.type != AUDIO_TYPE_INTERNAL_SPEAKER) { | 757 device.type != AUDIO_TYPE_INTERNAL_SPEAKER) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 | 791 |
731 UpdateDevicesAndSwitchActive(node_list); | 792 UpdateDevicesAndSwitchActive(node_list); |
732 FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged()); | 793 FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged()); |
733 } | 794 } |
734 | 795 |
735 void CrasAudioHandler::HandleGetNodesError(const std::string& error_name, | 796 void CrasAudioHandler::HandleGetNodesError(const std::string& error_name, |
736 const std::string& error_msg) { | 797 const std::string& error_msg) { |
737 LOG_IF(ERROR, log_errors_) << "Failed to call GetNodes: " | 798 LOG_IF(ERROR, log_errors_) << "Failed to call GetNodes: " |
738 << error_name << ": " << error_msg; | 799 << error_name << ": " << error_msg; |
739 } | 800 } |
| 801 |
| 802 void CrasAudioHandler::AddAdditionalActiveNode(uint64 node_id) { |
| 803 const AudioDevice* device = GetDeviceFromId(node_id); |
| 804 if (!device) { |
| 805 VLOG(1) << "AddActiveInputNode: Cannot find device id=" |
| 806 << "0x" << std::hex << node_id; |
| 807 return; |
| 808 } |
| 809 |
| 810 audio_devices_[node_id].active = true; |
| 811 SetupAdditionalActiveAudioNodeState(node_id); |
| 812 |
| 813 if (device->is_input) { |
| 814 DCHECK(node_id != active_input_node_id_); |
| 815 chromeos::DBusThreadManager::Get() |
| 816 ->GetCrasAudioClient() |
| 817 ->AddActiveInputNode(node_id); |
| 818 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); |
| 819 } else { |
| 820 DCHECK(node_id != active_output_node_id_); |
| 821 chromeos::DBusThreadManager::Get() |
| 822 ->GetCrasAudioClient() |
| 823 ->AddActiveOutputNode(node_id); |
| 824 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged()); |
| 825 } |
| 826 } |
| 827 |
| 828 void CrasAudioHandler::RemoveActiveNodeInternal(uint64 node_id) { |
| 829 const AudioDevice* device = GetDeviceFromId(node_id); |
| 830 if (!device) { |
| 831 VLOG(1) << "RemoveActiveInputNode: Cannot find device id=" |
| 832 << "0x" << std::hex << node_id; |
| 833 return; |
| 834 } |
| 835 |
| 836 audio_devices_[node_id].active = false; |
| 837 if (device->is_input) { |
| 838 if (node_id == active_input_node_id_) |
| 839 active_input_node_id_ = 0; |
| 840 chromeos::DBusThreadManager::Get() |
| 841 ->GetCrasAudioClient() |
| 842 ->RemoveActiveInputNode(node_id); |
| 843 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged()); |
| 844 } else { |
| 845 if (node_id == active_output_node_id_) |
| 846 active_output_node_id_ = 0; |
| 847 chromeos::DBusThreadManager::Get() |
| 848 ->GetCrasAudioClient() |
| 849 ->RemoveActiveOutputNode(node_id); |
| 850 } |
| 851 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged()); |
| 852 } |
| 853 |
740 } // namespace chromeos | 854 } // namespace chromeos |
OLD | NEW |