| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ash/system/chromeos/audio/tray_audio.h" | 5 #include "ash/system/chromeos/audio/tray_audio.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "ash/ash_constants.h" | 9 #include "ash/ash_constants.h" |
| 10 #include "ash/ash_switches.h" | 10 #include "ash/ash_switches.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "ui/gfx/canvas.h" | 30 #include "ui/gfx/canvas.h" |
| 31 #include "ui/gfx/image/image.h" | 31 #include "ui/gfx/image/image.h" |
| 32 #include "ui/gfx/image/image_skia_operations.h" | 32 #include "ui/gfx/image/image_skia_operations.h" |
| 33 #include "ui/views/controls/button/image_button.h" | 33 #include "ui/views/controls/button/image_button.h" |
| 34 #include "ui/views/controls/image_view.h" | 34 #include "ui/views/controls/image_view.h" |
| 35 #include "ui/views/controls/label.h" | 35 #include "ui/views/controls/label.h" |
| 36 #include "ui/views/controls/slider.h" | 36 #include "ui/views/controls/slider.h" |
| 37 #include "ui/views/layout/box_layout.h" | 37 #include "ui/views/layout/box_layout.h" |
| 38 #include "ui/views/view.h" | 38 #include "ui/views/view.h" |
| 39 | 39 |
| 40 using chromeos::CrasAudioHandler; |
| 41 |
| 40 namespace ash { | 42 namespace ash { |
| 41 namespace internal { | 43 namespace internal { |
| 42 | 44 |
| 43 namespace { | 45 namespace { |
| 44 const int kVolumeImageWidth = 25; | 46 const int kVolumeImageWidth = 25; |
| 45 const int kVolumeImageHeight = 25; | 47 const int kVolumeImageHeight = 25; |
| 46 const int kBarSeparatorWidth = 25; | 48 const int kBarSeparatorWidth = 25; |
| 47 const int kBarSeparatorHeight = 30; | 49 const int kBarSeparatorHeight = 30; |
| 48 const int kSliderRightPaddingToVolumeViewEdge = 17; | 50 const int kSliderRightPaddingToVolumeViewEdge = 17; |
| 49 const int kExtraPaddingBetweenBarAndMore = 10; | 51 const int kExtraPaddingBetweenBarAndMore = 10; |
| 50 | 52 |
| 51 const int kNoAudioDeviceIcon = -1; | 53 const int kNoAudioDeviceIcon = -1; |
| 52 | 54 |
| 53 // IDR_AURA_UBER_TRAY_VOLUME_LEVELS contains 5 images, | 55 // IDR_AURA_UBER_TRAY_VOLUME_LEVELS contains 5 images, |
| 54 // The one for mute is at the 0 index and the other | 56 // The one for mute is at the 0 index and the other |
| 55 // four are used for ascending volume levels. | 57 // four are used for ascending volume levels. |
| 56 const int kVolumeLevels = 4; | 58 const int kVolumeLevels = 4; |
| 57 | 59 |
| 58 bool IsAudioMuted() { | 60 bool IsAudioMuted() { |
| 59 if(ash::switches::UseNewAudioHandler()) { | 61 if(ash::switches::UseNewAudioHandler()) { |
| 60 return chromeos::CrasAudioHandler::Get()->IsOutputMuted(); | 62 return CrasAudioHandler::Get()->IsOutputMuted(); |
| 61 } else { | 63 } else { |
| 62 return Shell::GetInstance()->system_tray_delegate()-> | 64 return Shell::GetInstance()->system_tray_delegate()-> |
| 63 GetVolumeControlDelegate()->IsAudioMuted(); | 65 GetVolumeControlDelegate()->IsAudioMuted(); |
| 64 } | 66 } |
| 65 } | 67 } |
| 66 | 68 |
| 67 float GetVolumeLevel() { | 69 float GetVolumeLevel() { |
| 68 if (ash::switches::UseNewAudioHandler()) { | 70 if (ash::switches::UseNewAudioHandler()) { |
| 69 return chromeos::CrasAudioHandler::Get()->GetOutputVolumePercent() / 100.0f; | 71 return CrasAudioHandler::Get()->GetOutputVolumePercent() / 100.0f; |
| 70 } else { | 72 } else { |
| 71 return Shell::GetInstance()->system_tray_delegate()-> | 73 return Shell::GetInstance()->system_tray_delegate()-> |
| 72 GetVolumeControlDelegate()->GetVolumeLevel(); | 74 GetVolumeControlDelegate()->GetVolumeLevel(); |
| 73 } | 75 } |
| 74 } | 76 } |
| 75 | 77 |
| 76 int GetAudioDeviceIconId(chromeos::AudioDeviceType type) { | 78 int GetAudioDeviceIconId(chromeos::AudioDeviceType type) { |
| 77 if (type == chromeos::AUDIO_TYPE_HEADPHONE) | 79 if (type == chromeos::AUDIO_TYPE_HEADPHONE) |
| 78 return IDR_AURA_UBER_TRAY_AUDIO_HEADPHONE; | 80 return IDR_AURA_UBER_TRAY_AUDIO_HEADPHONE; |
| 79 else if (type == chromeos::AUDIO_TYPE_USB) | 81 else if (type == chromeos::AUDIO_TYPE_USB) |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 | 215 |
| 214 virtual ~VolumeView() {} | 216 virtual ~VolumeView() {} |
| 215 | 217 |
| 216 void Update() { | 218 void Update() { |
| 217 icon_->Update(); | 219 icon_->Update(); |
| 218 slider_->Update(); | 220 slider_->Update(); |
| 219 UpdateDeviceTypeAndMore(); | 221 UpdateDeviceTypeAndMore(); |
| 220 Layout(); | 222 Layout(); |
| 221 } | 223 } |
| 222 | 224 |
| 225 // Sets volume level on slider_, |percent| is ranged from [0.00] to [1.00]. |
| 223 void SetVolumeLevel(float percent) { | 226 void SetVolumeLevel(float percent) { |
| 227 // Slider's value is in finer granularity than audio volume level(0.01), |
| 228 // there will be a small discrepancy between slider's value and volume level |
| 229 // on audio side. To avoid the jittering in slider UI, do not set change |
| 230 // slider value if the change is less than 1%. |
| 231 if (std::abs(percent-slider_->value()) < 0.01) |
| 232 return; |
| 224 // The change in volume will be reflected via accessibility system events, | 233 // The change in volume will be reflected via accessibility system events, |
| 225 // so we prevent the UI event from being sent here. | 234 // so we prevent the UI event from being sent here. |
| 226 slider_->set_enable_accessibility_events(false); | 235 slider_->set_enable_accessibility_events(false); |
| 227 slider_->SetValue(percent); | 236 slider_->SetValue(percent); |
| 228 // It is possible that the volume was (un)muted, but the actual volume level | 237 // It is possible that the volume was (un)muted, but the actual volume level |
| 229 // did not change. In that case, setting the value of the slider won't | 238 // did not change. In that case, setting the value of the slider won't |
| 230 // trigger an update. So explicitly trigger an update. | 239 // trigger an update. So explicitly trigger an update. |
| 231 Update(); | 240 Update(); |
| 232 slider_->set_enable_accessibility_events(true); | 241 slider_->set_enable_accessibility_events(true); |
| 233 } | 242 } |
| 234 | 243 |
| 235 private: | 244 private: |
| 236 // Updates bar_, device_type_ icon, and more_ buttons. | 245 // Updates bar_, device_type_ icon, and more_ buttons. |
| 237 void UpdateDeviceTypeAndMore() { | 246 void UpdateDeviceTypeAndMore() { |
| 238 if (!ash::switches::ShowAudioDeviceMenu() || !is_default_view_) { | 247 if (!ash::switches::ShowAudioDeviceMenu() || !is_default_view_) { |
| 239 more_->SetVisible(false); | 248 more_->SetVisible(false); |
| 240 bar_->SetVisible(false); | 249 bar_->SetVisible(false); |
| 241 device_type_->SetVisible(false); | 250 device_type_->SetVisible(false); |
| 242 return; | 251 return; |
| 243 } | 252 } |
| 244 | 253 |
| 245 chromeos::CrasAudioHandler* audio_handler = | 254 CrasAudioHandler* audio_handler = CrasAudioHandler::Get(); |
| 246 chromeos::CrasAudioHandler::Get(); | |
| 247 bool show_more = audio_handler->has_alternative_output() || | 255 bool show_more = audio_handler->has_alternative_output() || |
| 248 audio_handler->has_alternative_input(); | 256 audio_handler->has_alternative_input(); |
| 249 more_->SetVisible(show_more); | 257 more_->SetVisible(show_more); |
| 250 | 258 |
| 251 // Show output device icon if necessary. | 259 // Show output device icon if necessary. |
| 252 chromeos::AudioDevice device; | 260 chromeos::AudioDevice device; |
| 253 audio_handler->GetActiveOutputDevice(&device); | 261 audio_handler->GetActiveOutputDevice(&device); |
| 254 int device_icon = GetAudioDeviceIconId(device.type); | 262 int device_icon = GetAudioDeviceIconId(device.type); |
| 255 if (device_icon != kNoAudioDeviceIcon) { | 263 if (device_icon != kNoAudioDeviceIcon) { |
| 256 device_type_->SetVisible(true); | 264 device_type_->SetVisible(true); |
| 257 device_type_->SetImage( | 265 device_type_->SetImage( |
| 258 ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 266 ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 259 device_icon).ToImageSkia()); | 267 device_icon).ToImageSkia()); |
| 260 bar_->SetVisible(false); | 268 bar_->SetVisible(false); |
| 261 } else { | 269 } else { |
| 262 device_type_->SetVisible(false); | 270 device_type_->SetVisible(false); |
| 263 bar_->SetVisible(show_more); | 271 bar_->SetVisible(show_more); |
| 264 } | 272 } |
| 265 } | 273 } |
| 266 | 274 |
| 275 void HandleVolumeUp(int volume) { |
| 276 CrasAudioHandler* audio_handler = CrasAudioHandler::Get(); |
| 277 audio_handler->SetOutputVolumePercent(volume); |
| 278 if (audio_handler->IsOutputMuted() && |
| 279 !audio_handler->IsOutputVolumeBelowDefaultMuteLvel()) |
| 280 audio_handler->SetOutputMute(false); |
| 281 } |
| 282 |
| 283 void HandleVolumeDown(int volume) { |
| 284 CrasAudioHandler* audio_handler = CrasAudioHandler::Get(); |
| 285 audio_handler->SetOutputVolumePercent(volume); |
| 286 if (audio_handler->IsOutputVolumeBelowDefaultMuteLvel() && |
| 287 !audio_handler->IsOutputMuted()) { |
| 288 audio_handler->SetOutputMute(true); |
| 289 } else if (!audio_handler->IsOutputVolumeBelowDefaultMuteLvel() && |
| 290 audio_handler->IsOutputMuted()) { |
| 291 audio_handler->SetOutputMute(false); |
| 292 } |
| 293 } |
| 294 |
| 267 // Overridden from views::View. | 295 // Overridden from views::View. |
| 268 virtual void Layout() OVERRIDE { | 296 virtual void Layout() OVERRIDE { |
| 269 views::View::Layout(); | 297 views::View::Layout(); |
| 270 | 298 |
| 271 if (!more_->visible()) { | 299 if (!more_->visible()) { |
| 272 int w = width() - slider_->bounds().x() - | 300 int w = width() - slider_->bounds().x() - |
| 273 kSliderRightPaddingToVolumeViewEdge; | 301 kSliderRightPaddingToVolumeViewEdge; |
| 274 slider_->SetSize(gfx::Size(w, slider_->height())); | 302 slider_->SetSize(gfx::Size(w, slider_->height())); |
| 275 return; | 303 return; |
| 276 } | 304 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 302 view_left_to_more->bounds().x() - kTrayPopupPaddingBetweenItems | 330 view_left_to_more->bounds().x() - kTrayPopupPaddingBetweenItems |
| 303 - slider_bounds.x()); | 331 - slider_bounds.x()); |
| 304 slider_->SetBoundsRect(slider_bounds); | 332 slider_->SetBoundsRect(slider_bounds); |
| 305 } | 333 } |
| 306 | 334 |
| 307 // Overridden from views::ButtonListener. | 335 // Overridden from views::ButtonListener. |
| 308 virtual void ButtonPressed(views::Button* sender, | 336 virtual void ButtonPressed(views::Button* sender, |
| 309 const ui::Event& event) OVERRIDE { | 337 const ui::Event& event) OVERRIDE { |
| 310 CHECK(sender == icon_); | 338 CHECK(sender == icon_); |
| 311 if (ash::switches::UseNewAudioHandler()) { | 339 if (ash::switches::UseNewAudioHandler()) { |
| 312 chromeos::CrasAudioHandler::Get()->SetOutputMute(!IsAudioMuted()); | 340 bool mute_on = !IsAudioMuted(); |
| 341 CrasAudioHandler::Get()->SetOutputMute(mute_on); |
| 342 if (!mute_on) |
| 343 CrasAudioHandler::Get()->AdjustOutputVolumeToAudibleLevel(); |
| 313 } else { | 344 } else { |
| 314 ash::Shell::GetInstance()->system_tray_delegate()-> | 345 ash::Shell::GetInstance()->system_tray_delegate()-> |
| 315 GetVolumeControlDelegate()->SetAudioMuted(!IsAudioMuted()); | 346 GetVolumeControlDelegate()->SetAudioMuted(!IsAudioMuted()); |
| 316 } | 347 } |
| 317 } | 348 } |
| 318 | 349 |
| 319 // Overridden from views:SliderListener. | 350 // Overridden from views:SliderListener. |
| 320 virtual void SliderValueChanged(views::Slider* sender, | 351 virtual void SliderValueChanged(views::Slider* sender, |
| 321 float value, | 352 float value, |
| 322 float old_value, | 353 float old_value, |
| 323 views::SliderChangeReason reason) OVERRIDE { | 354 views::SliderChangeReason reason) OVERRIDE { |
| 324 if (reason == views::VALUE_CHANGED_BY_USER) { | 355 if (reason == views::VALUE_CHANGED_BY_USER) { |
| 325 if (ash::switches::UseNewAudioHandler()) { | 356 if (ash::switches::UseNewAudioHandler()) { |
| 326 chromeos::CrasAudioHandler::Get()-> | 357 int volume = value * 100.0f; |
| 327 SetOutputVolumePercent(value * 100.0f); | 358 int old_volume = CrasAudioHandler::Get()->GetOutputVolumePercent(); |
| 328 } | 359 // Do not call change audio volume if the difference is less than |
| 329 else { | 360 // 1%, which is beyond cras audio api's granularity for output volume. |
| 361 if (std::abs(volume - old_volume) < 1) |
| 362 return; |
| 363 if (volume > old_volume) |
| 364 HandleVolumeUp(volume); |
| 365 else |
| 366 HandleVolumeDown(volume); |
| 367 } else { |
| 330 ash::Shell::GetInstance()->system_tray_delegate()-> | 368 ash::Shell::GetInstance()->system_tray_delegate()-> |
| 331 GetVolumeControlDelegate()->SetVolumeLevel(value); | 369 GetVolumeControlDelegate()->SetVolumeLevel(value); |
| 332 } | 370 } |
| 333 } | 371 } |
| 334 icon_->Update(); | 372 icon_->Update(); |
| 335 } | 373 } |
| 336 | 374 |
| 337 // Overriden from ActinableView. | 375 // Overriden from ActinableView. |
| 338 virtual bool PerformAction(const ui::Event& event) OVERRIDE { | 376 virtual bool PerformAction(const ui::Event& event) OVERRIDE { |
| 339 if (!more_->visible()) | 377 if (!more_->visible()) |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 } | 416 } |
| 379 | 417 |
| 380 void CreateHeaderEntry() { | 418 void CreateHeaderEntry() { |
| 381 CreateSpecialRow(IDS_ASH_STATUS_TRAY_AUDIO, this); | 419 CreateSpecialRow(IDS_ASH_STATUS_TRAY_AUDIO, this); |
| 382 } | 420 } |
| 383 | 421 |
| 384 void UpdateAudioDevices() { | 422 void UpdateAudioDevices() { |
| 385 output_devices_.clear(); | 423 output_devices_.clear(); |
| 386 input_devices_.clear(); | 424 input_devices_.clear(); |
| 387 chromeos::AudioDeviceList devices; | 425 chromeos::AudioDeviceList devices; |
| 388 chromeos::CrasAudioHandler::Get()->GetAudioDevices(&devices); | 426 CrasAudioHandler::Get()->GetAudioDevices(&devices); |
| 389 for (size_t i = 0; i < devices.size(); ++i) { | 427 for (size_t i = 0; i < devices.size(); ++i) { |
| 390 if (devices[i].is_input) | 428 if (devices[i].is_input) |
| 391 input_devices_.push_back(devices[i]); | 429 input_devices_.push_back(devices[i]); |
| 392 else | 430 else |
| 393 output_devices_.push_back(devices[i]); | 431 output_devices_.push_back(devices[i]); |
| 394 } | 432 } |
| 395 UpdateScrollableList(); | 433 UpdateScrollableList(); |
| 396 } | 434 } |
| 397 | 435 |
| 398 void UpdateScrollableList() { | 436 void UpdateScrollableList() { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // Overridden from ViewClickListener. | 481 // Overridden from ViewClickListener. |
| 444 virtual void OnViewClicked(views::View* sender) OVERRIDE { | 482 virtual void OnViewClicked(views::View* sender) OVERRIDE { |
| 445 if (sender == footer()->content()) { | 483 if (sender == footer()->content()) { |
| 446 owner()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING); | 484 owner()->system_tray()->ShowDefaultView(BUBBLE_USE_EXISTING); |
| 447 } else { | 485 } else { |
| 448 AudioDeviceMap::iterator iter = device_map_.find(sender); | 486 AudioDeviceMap::iterator iter = device_map_.find(sender); |
| 449 if (iter == device_map_.end()) | 487 if (iter == device_map_.end()) |
| 450 return; | 488 return; |
| 451 chromeos::AudioDevice& device = iter->second; | 489 chromeos::AudioDevice& device = iter->second; |
| 452 if (device.is_input) | 490 if (device.is_input) |
| 453 chromeos::CrasAudioHandler::Get()->SetActiveInputNode(device.id); | 491 CrasAudioHandler::Get()->SetActiveInputNode(device.id); |
| 454 else | 492 else |
| 455 chromeos::CrasAudioHandler::Get()->SetActiveOutputNode(device.id); | 493 CrasAudioHandler::Get()->SetActiveOutputNode(device.id); |
| 456 } | 494 } |
| 457 } | 495 } |
| 458 | 496 |
| 459 typedef std::map<views::View*, chromeos::AudioDevice> AudioDeviceMap; | 497 typedef std::map<views::View*, chromeos::AudioDevice> AudioDeviceMap; |
| 460 | 498 |
| 461 user::LoginStatus login_; | 499 user::LoginStatus login_; |
| 462 chromeos::AudioDeviceList output_devices_; | 500 chromeos::AudioDeviceList output_devices_; |
| 463 chromeos::AudioDeviceList input_devices_; | 501 chromeos::AudioDeviceList input_devices_; |
| 464 AudioDeviceMap device_map_; | 502 AudioDeviceMap device_map_; |
| 465 | 503 |
| 466 DISALLOW_COPY_AND_ASSIGN(AudioDetailedView); | 504 DISALLOW_COPY_AND_ASSIGN(AudioDetailedView); |
| 467 }; | 505 }; |
| 468 | 506 |
| 469 } // namespace tray | 507 } // namespace tray |
| 470 | 508 |
| 471 TrayAudio::TrayAudio(SystemTray* system_tray) | 509 TrayAudio::TrayAudio(SystemTray* system_tray) |
| 472 : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_VOLUME_MUTE), | 510 : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_VOLUME_MUTE), |
| 473 volume_view_(NULL), | 511 volume_view_(NULL), |
| 474 audio_detail_(NULL), | 512 audio_detail_(NULL), |
| 475 pop_up_volume_view_(false) { | 513 pop_up_volume_view_(false) { |
| 476 if (ash::switches::UseNewAudioHandler()) | 514 if (ash::switches::UseNewAudioHandler()) |
| 477 chromeos::CrasAudioHandler::Get()->AddAudioObserver(this); | 515 CrasAudioHandler::Get()->AddAudioObserver(this); |
| 478 else | 516 else |
| 479 Shell::GetInstance()->system_tray_notifier()->AddAudioObserver(this); | 517 Shell::GetInstance()->system_tray_notifier()->AddAudioObserver(this); |
| 480 } | 518 } |
| 481 | 519 |
| 482 TrayAudio::~TrayAudio() { | 520 TrayAudio::~TrayAudio() { |
| 483 if (ash::switches::UseNewAudioHandler()) { | 521 if (ash::switches::UseNewAudioHandler()) { |
| 484 if (chromeos::CrasAudioHandler::IsInitialized()) | 522 if (CrasAudioHandler::IsInitialized()) |
| 485 chromeos::CrasAudioHandler::Get()->RemoveAudioObserver(this); | 523 CrasAudioHandler::Get()->RemoveAudioObserver(this); |
| 486 } else { | 524 } else { |
| 487 Shell::GetInstance()->system_tray_notifier()->RemoveAudioObserver(this); | 525 Shell::GetInstance()->system_tray_notifier()->RemoveAudioObserver(this); |
| 488 } | 526 } |
| 489 } | 527 } |
| 490 | 528 |
| 491 bool TrayAudio::GetInitialVisibility() { | 529 bool TrayAudio::GetInitialVisibility() { |
| 492 return IsAudioMuted(); | 530 return IsAudioMuted(); |
| 493 } | 531 } |
| 494 | 532 |
| 495 views::View* TrayAudio::CreateDefaultView(user::LoginStatus status) { | 533 views::View* TrayAudio::CreateDefaultView(user::LoginStatus status) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 if (audio_detail_) | 645 if (audio_detail_) |
| 608 audio_detail_->Update(); | 646 audio_detail_->Update(); |
| 609 if (volume_view_) { | 647 if (volume_view_) { |
| 610 volume_view_->SetVolumeLevel(GetVolumeLevel()); | 648 volume_view_->SetVolumeLevel(GetVolumeLevel()); |
| 611 volume_view_->Update(); | 649 volume_view_->Update(); |
| 612 } | 650 } |
| 613 } | 651 } |
| 614 | 652 |
| 615 } // namespace internal | 653 } // namespace internal |
| 616 } // namespace ash | 654 } // namespace ash |
| OLD | NEW |