mic_gain_slider_view.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/system/audio/mic_gain_slider_view.h"
  5. #include "ash/resources/vector_icons/vector_icons.h"
  6. #include "ash/strings/grit/ash_strings.h"
  7. #include "ash/style/ash_color_provider.h"
  8. #include "ash/system/audio/mic_gain_slider_controller.h"
  9. #include "ash/system/tray/tray_constants.h"
  10. #include "ash/system/tray/tray_popup_utils.h"
  11. #include "base/bind.h"
  12. #include "chromeos/ash/components/audio/cras_audio_handler.h"
  13. #include "ui/accessibility/ax_enums.mojom.h"
  14. #include "ui/base/l10n/l10n_util.h"
  15. #include "ui/views/accessibility/view_accessibility.h"
  16. #include "ui/views/border.h"
  17. #include "ui/views/controls/label.h"
  18. #include "ui/views/layout/box_layout.h"
  19. #include "ui/views/style/typography.h"
  20. namespace ash {
  21. namespace {
  22. // Gets resource ID for the string that should be used for mute state portion of
  23. // the microphone toggle button tooltip.
  24. int GetMuteStateTooltipTextResourceId(bool is_muted,
  25. bool is_muted_by_mute_switch) {
  26. if (is_muted_by_mute_switch)
  27. return IDS_ASH_STATUS_TRAY_MIC_STATE_MUTED_BY_HW_SWITCH;
  28. if (is_muted)
  29. return IDS_ASH_STATUS_TRAY_MIC_STATE_MUTED;
  30. return IDS_ASH_STATUS_TRAY_MIC_STATE_ON;
  31. }
  32. } // namespace
  33. MicGainSliderView::MicGainSliderView(MicGainSliderController* controller)
  34. : UnifiedSliderView(
  35. base::BindRepeating(&MicGainSliderController::SliderButtonPressed,
  36. base::Unretained(controller)),
  37. controller,
  38. kImeMenuMicrophoneIcon,
  39. IDS_ASH_STATUS_TRAY_VOLUME_SLIDER_LABEL),
  40. device_id_(CrasAudioHandler::Get()->GetPrimaryActiveInputNode()),
  41. internal_(false) {
  42. CrasAudioHandler::Get()->AddAudioObserver(this);
  43. CreateToastLabel();
  44. slider()->SetVisible(false);
  45. announcement_view_ = AddChildView(std::make_unique<views::View>());
  46. Update(false /* by_user */);
  47. announcement_view_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
  48. }
  49. MicGainSliderView::MicGainSliderView(MicGainSliderController* controller,
  50. uint64_t device_id,
  51. bool internal)
  52. : UnifiedSliderView(
  53. base::BindRepeating(&MicGainSliderController::SliderButtonPressed,
  54. base::Unretained(controller)),
  55. controller,
  56. kImeMenuMicrophoneIcon,
  57. IDS_ASH_STATUS_TRAY_VOLUME_SLIDER_LABEL),
  58. device_id_(device_id),
  59. internal_(internal) {
  60. CrasAudioHandler::Get()->AddAudioObserver(this);
  61. auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
  62. views::BoxLayout::Orientation::kHorizontal, kMicGainSliderViewPadding,
  63. kMicGainSliderViewSpacing));
  64. slider()->SetBorder(views::CreateEmptyBorder(kMicGainSliderPadding));
  65. layout->SetFlexForView(slider(), 1);
  66. layout->set_cross_axis_alignment(
  67. views::BoxLayout::CrossAxisAlignment::kCenter);
  68. announcement_view_ = AddChildView(std::make_unique<views::View>());
  69. Update(false /* by_user */);
  70. }
  71. MicGainSliderView::~MicGainSliderView() {
  72. CrasAudioHandler::Get()->RemoveAudioObserver(this);
  73. }
  74. void MicGainSliderView::Update(bool by_user) {
  75. auto* audio_handler = CrasAudioHandler::Get();
  76. uint64_t active_device_id = audio_handler->GetPrimaryActiveInputNode();
  77. auto* active_device = audio_handler->GetDeviceFromId(active_device_id);
  78. // If the device has dual internal mics the internal mic shown in the ui is a
  79. // stub. We need to show this slider despite the device_id_ not matching the
  80. // active input node.
  81. bool show_internal_stub = internal_ &&
  82. (active_device && active_device->IsInternalMic()) &&
  83. audio_handler->HasDualInternalMic();
  84. if (audio_handler->GetPrimaryActiveInputNode() != device_id_ &&
  85. !show_internal_stub) {
  86. SetVisible(false);
  87. return;
  88. }
  89. SetVisible(true);
  90. bool is_muted = audio_handler->IsInputMuted();
  91. bool is_muted_by_mute_switch =
  92. audio_handler->input_muted_by_microphone_mute_switch();
  93. float level = audio_handler->GetInputGainPercent() / 100.f;
  94. if (toast_label()) {
  95. toast_label()->SetText(
  96. l10n_util::GetStringUTF16(is_muted ? IDS_ASH_STATUS_AREA_TOAST_MIC_OFF
  97. : IDS_ASH_STATUS_AREA_TOAST_MIC_ON));
  98. }
  99. if (announcement_view_) {
  100. announcement_view_->GetViewAccessibility().OverrideName(
  101. l10n_util::GetStringUTF16(is_muted ? IDS_ASH_STATUS_AREA_TOAST_MIC_OFF
  102. : IDS_ASH_STATUS_AREA_TOAST_MIC_ON));
  103. }
  104. // To indicate that the volume is muted, set the volume slider to the minimal
  105. // visual style.
  106. slider()->SetRenderingStyle(
  107. is_muted ? views::Slider::RenderingStyle::kMinimalStyle
  108. : views::Slider::RenderingStyle::kDefaultStyle);
  109. // The button should be gray when muted and colored otherwise.
  110. button()->SetToggled(!is_muted);
  111. button()->SetEnabled(!is_muted_by_mute_switch);
  112. button()->SetVectorIcon(is_muted ? kMutedMicrophoneIcon
  113. : kImeMenuMicrophoneIcon);
  114. std::u16string state_tooltip_text = l10n_util::GetStringUTF16(
  115. GetMuteStateTooltipTextResourceId(is_muted, is_muted_by_mute_switch));
  116. button()->SetTooltipText(l10n_util::GetStringFUTF16(
  117. IDS_ASH_STATUS_TRAY_MIC_GAIN, state_tooltip_text));
  118. // Slider's value is in finer granularity than audio volume level(0.01),
  119. // there will be a small discrepancy between slider's value and volume level
  120. // on audio side. To avoid the jittering in slider UI, use the slider's
  121. // current value.
  122. if (std::abs(level - slider()->GetValue()) <
  123. kAudioSliderIgnoreUpdateThreshold) {
  124. level = slider()->GetValue();
  125. }
  126. // Note: even if the value does not change, we still need to call this
  127. // function to enable accessibility events (crbug.com/1013251).
  128. SetSliderValue(level, by_user);
  129. }
  130. void MicGainSliderView::OnInputNodeGainChanged(uint64_t node_id, int gain) {
  131. Update(true /* by_user */);
  132. }
  133. void MicGainSliderView::OnInputMutedByMicrophoneMuteSwitchChanged(bool muted) {
  134. Update(true /* by_user */);
  135. }
  136. void MicGainSliderView::OnInputMuteChanged(bool mute_on) {
  137. Update(true /* by_user */);
  138. announcement_view_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
  139. }
  140. void MicGainSliderView::OnActiveInputNodeChanged() {
  141. Update(true /* by_user */);
  142. }
  143. const char* MicGainSliderView::GetClassName() const {
  144. return "MicGainSliderView";
  145. }
  146. } // namespace ash