blob: 63ee464db750031b9b81d556a4713d233404d012 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/system/audio/audio_detailed_view.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/tray/hover_highlight_view.h"
#include "ash/system/tray/tray_popup_utils.h"
#include "ash/system/tray/tri_view.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/audio/cras_audio_handler.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/separator.h"
namespace {
base::string16 GetAudioDeviceName(const chromeos::AudioDevice& device) {
switch (device.type) {
case chromeos::AUDIO_TYPE_FRONT_MIC:
return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_AUDIO_FRONT_MIC);
case chromeos::AUDIO_TYPE_HEADPHONE:
return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_AUDIO_HEADPHONE);
case chromeos::AUDIO_TYPE_INTERNAL_SPEAKER:
return l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_AUDIO_INTERNAL_SPEAKER);
case chromeos::AUDIO_TYPE_INTERNAL_MIC:
return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_AUDIO_INTERNAL_MIC);
case chromeos::AUDIO_TYPE_REAR_MIC:
return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_AUDIO_REAR_MIC);
case chromeos::AUDIO_TYPE_USB:
return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_AUDIO_USB_DEVICE,
base::UTF8ToUTF16(device.display_name));
case chromeos::AUDIO_TYPE_BLUETOOTH:
return l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_AUDIO_BLUETOOTH_DEVICE,
base::UTF8ToUTF16(device.display_name));
case chromeos::AUDIO_TYPE_HDMI:
return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_AUDIO_HDMI_DEVICE,
base::UTF8ToUTF16(device.display_name));
case chromeos::AUDIO_TYPE_MIC:
return l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_AUDIO_MIC_JACK_DEVICE);
default:
return base::UTF8ToUTF16(device.display_name);
}
}
} // namespace
using chromeos::CrasAudioHandler;
namespace ash {
namespace tray {
AudioDetailedView::AudioDetailedView(DetailedViewDelegate* delegate)
: TrayDetailedView(delegate) {
CreateItems();
Update();
}
AudioDetailedView::~AudioDetailedView() = default;
void AudioDetailedView::Update() {
UpdateAudioDevices();
Layout();
}
void AudioDetailedView::AddAudioSubHeader(const gfx::VectorIcon& icon,
int text_id) {
TriView* header = AddScrollListSubHeader(icon, text_id);
header->SetContainerVisible(TriView::Container::END, false);
}
void AudioDetailedView::CreateItems() {
CreateScrollableList();
CreateTitleRow(IDS_ASH_STATUS_TRAY_AUDIO);
}
void AudioDetailedView::UpdateAudioDevices() {
output_devices_.clear();
input_devices_.clear();
chromeos::AudioDeviceList devices;
CrasAudioHandler* audio_handler = CrasAudioHandler::Get();
audio_handler->GetAudioDevices(&devices);
bool has_dual_internal_mic = audio_handler->HasDualInternalMic();
bool is_front_or_rear_mic_active = false;
for (const auto& device : devices) {
// Don't display keyboard mic or aokr type.
if (!device.is_for_simple_usage())
continue;
if (device.is_input) {
// Do not expose the internal front and rear mic to UI.
if (has_dual_internal_mic && audio_handler->IsFrontOrRearMic(device)) {
if (device.active)
is_front_or_rear_mic_active = true;
continue;
}
input_devices_.push_back(device);
} else {
output_devices_.push_back(device);
}
}
// Expose the dual internal mics as one device (internal mic) to user.
if (has_dual_internal_mic) {
// Create stub internal mic entry for UI rendering, which representing
// both internal front and rear mics.
chromeos::AudioDevice internal_mic;
internal_mic.is_input = true;
internal_mic.stable_device_id_version = 2;
internal_mic.type = chromeos::AUDIO_TYPE_INTERNAL_MIC;
internal_mic.active = is_front_or_rear_mic_active;
input_devices_.push_back(internal_mic);
}
UpdateScrollableList();
}
void AudioDetailedView::UpdateScrollableList() {
scroll_content()->RemoveAllChildViews(true);
device_map_.clear();
// Add audio output devices.
const bool has_output_devices = output_devices_.size() > 0;
if (has_output_devices) {
AddAudioSubHeader(kSystemMenuAudioOutputIcon,
IDS_ASH_STATUS_TRAY_AUDIO_OUTPUT);
}
for (const auto& device : output_devices_) {
HoverHighlightView* container =
AddScrollListCheckableItem(GetAudioDeviceName(device), device.active);
device_map_[container] = device;
}
if (has_output_devices) {
scroll_content()->AddChildView(CreateListSubHeaderSeparator());
}
// Add audio input devices.
const bool has_input_devices = input_devices_.size() > 0;
if (has_input_devices) {
AddAudioSubHeader(kSystemMenuAudioInputIcon,
IDS_ASH_STATUS_TRAY_AUDIO_INPUT);
}
for (const auto& device : input_devices_) {
HoverHighlightView* container =
AddScrollListCheckableItem(GetAudioDeviceName(device), device.active);
device_map_[container] = device;
}
scroll_content()->SizeToPreferredSize();
scroller()->Layout();
}
void AudioDetailedView::HandleViewClicked(views::View* view) {
AudioDeviceMap::iterator iter = device_map_.find(view);
if (iter == device_map_.end())
return;
chromeos::AudioDevice device = iter->second;
CrasAudioHandler* audio_handler = CrasAudioHandler::Get();
if (device.type == chromeos::AUDIO_TYPE_INTERNAL_MIC &&
audio_handler->HasDualInternalMic()) {
audio_handler->SwitchToFrontOrRearMic();
} else {
audio_handler->SwitchToDevice(device, true,
CrasAudioHandler::ACTIVATE_BY_USER);
}
}
} // namespace tray
} // namespace ash