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