Chromium Code Reviews| 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 |