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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |