blob: d0658f371c348de96f7a3a16f40e9007b83098d8 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "src/ui/bin/root_presenter/media_buttons_handler.h"
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <lib/fostr/fidl/fuchsia/ui/input/formatting.h>
#include <zircon/types.h>
#include <src/ui/bin/root_presenter/constants.h>
using fuchsia::ui::policy::MediaButtonsListenerPtr;
namespace root_presenter {
namespace {
void ChattyReportLog(const fuchsia::ui::input::InputReport& report) {
static uint32_t chatty = 0;
if (chatty++ < ChattyMax()) {
FX_LOGS(INFO) << "RP-MediaReport[" << chatty << "/" << ChattyMax() << "]: " << report;
}
}
void ChattyEventLog(const fuchsia::ui::input::MediaButtonsEvent& event,
fuchsia::ui::policy::MediaButtonsListenerPtr& listener) {
static uint32_t chatty = 0;
if (chatty++ < ChattyMax()) {
zx_koid_t koid = ZX_KOID_INVALID;
{
zx_info_handle_basic_t info{};
size_t actual_count = 0;
size_t avail_count = 0;
zx_status_t status = listener.channel().get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info),
&actual_count, &avail_count);
if (status == ZX_OK) {
koid = info.koid;
}
}
FX_LOGS(INFO) << "RP-MediaEvent[" << chatty << "/" << ChattyMax() << "]: dest=" << koid << ", "
<< event;
}
}
} // namespace
bool MediaButtonsHandler::OnDeviceAdded(ui_input::InputDeviceImpl* input_device) {
if (!input_device->descriptor()->media_buttons) {
return false;
}
FX_VLOGS(1) << "MediaButtonsHandler::OnDeviceAdded: device_id=" << input_device->id();
ui_input::OnMediaButtonsEventCallback callback = [this](fuchsia::ui::input::InputReport report) {
OnEvent(std::move(report));
};
auto state = std::make_unique<ui_input::DeviceState>(
input_device->id(), input_device->descriptor(), std::move(callback));
ui_input::DeviceState* state_ptr = state.get();
auto device_pair = std::make_pair(input_device, std::move(state));
state_ptr->OnRegistered();
device_states_by_id_.emplace(input_device->id(), std::move(device_pair));
return true;
}
bool MediaButtonsHandler::OnReport(uint32_t device_id,
fuchsia::ui::input::InputReport input_report) {
ChattyReportLog(input_report);
if (device_states_by_id_.count(device_id) == 0) {
FX_VLOGS(1) << "OnReport: Unknown device " << device_id;
return false;
}
ui_input::DeviceState* state = device_states_by_id_[device_id].second.get();
fuchsia::math::Size unused;
state->Update(std::move(input_report), unused);
return true;
}
bool MediaButtonsHandler::OnDeviceRemoved(uint32_t device_id) {
FX_VLOGS(1) << "MediaButtonsHandler::OnDeviceRemoved: device_id=" << device_id;
if (device_states_by_id_.count(device_id) == 0) {
FX_VLOGS(1) << "OnReport: Unknown device " << device_id;
return false;
}
device_states_by_id_[device_id].second->OnUnregistered();
device_states_by_id_.erase(device_id);
return true;
}
fuchsia::ui::input::MediaButtonsEvent CreateMediaButtonsEvent(
const fuchsia::ui::input::InputReport& report) {
fuchsia::ui::input::MediaButtonsEvent event;
int8_t volume_gain = 0;
if (report.media_buttons->volume_up) {
volume_gain++;
}
if (report.media_buttons->volume_down) {
volume_gain--;
}
event.set_volume(volume_gain);
event.set_mic_mute(report.media_buttons->mic_mute);
event.set_camera_disable(report.media_buttons->camera_disable);
event.set_pause(report.media_buttons->pause);
return event;
}
void MediaButtonsHandler::OnEvent(fuchsia::ui::input::InputReport report) {
FX_CHECK(report.media_buttons);
for (auto& listener : media_buttons_listeners_) {
fuchsia::ui::input::MediaButtonsEvent event = CreateMediaButtonsEvent(report);
ChattyEventLog(event, listener);
listener->OnMediaButtonsEvent(std::move(event));
}
}
void MediaButtonsHandler::RegisterListener(
fidl::InterfaceHandle<fuchsia::ui::policy::MediaButtonsListener> listener_handle) {
MediaButtonsListenerPtr listener;
listener.Bind(std::move(listener_handle));
// Auto-remove listeners if the interface closes.
listener.set_error_handler([this, listener = listener.get()](zx_status_t status) {
media_buttons_listeners_.erase(
std::remove_if(media_buttons_listeners_.begin(), media_buttons_listeners_.end(),
[listener](const MediaButtonsListenerPtr& item) -> bool {
return item.get() == listener;
}),
media_buttons_listeners_.end());
});
// Send the last seen report to the listener so they have the information
// about the media button's state.
for (auto it = device_states_by_id_.begin(); it != device_states_by_id_.end(); it++) {
const ui_input::InputDeviceImpl* device_impl = it->second.first;
const fuchsia::ui::input::InputReport* report = device_impl->LastReport();
if (report) {
listener->OnMediaButtonsEvent(CreateMediaButtonsEvent(*report));
}
}
media_buttons_listeners_.push_back(std::move(listener));
}
} // namespace root_presenter