+6
-141
@@ -1,20 +1,16 @@
|
||||
#include <vamp_zero/ui.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <luma.hpp>
|
||||
|
||||
@@ -27,27 +23,15 @@
|
||||
#include <vamp_zero/parse.hpp>
|
||||
#include <vamp_zero/score.hpp>
|
||||
#include <vamp_zero/score_loader.hpp>
|
||||
#include <vamp_zero/touch_input.hpp>
|
||||
|
||||
|
||||
struct vamp_zero::ui_runtime : std::enable_shared_from_this<vamp_zero::ui_runtime> {
|
||||
struct vamp_zero::ui_runtime {
|
||||
ui_runtime(boost::asio::any_io_executor executor, std::function<void(vamp_protocol::page_command)> handler)
|
||||
: executor_{std::move(executor)}, tap_timer_{executor_}, command_handler_{std::move(handler)} {}
|
||||
auto handle_touch(luma::touch_event const &event) -> std::bool_t;
|
||||
auto send_touch_command(vamp_protocol::page_command command) -> void;
|
||||
auto arm_pending_tap_locked() -> void;
|
||||
auto cancel_pending_tap_locked() -> void;
|
||||
boost::asio::any_io_executor executor_;
|
||||
boost::asio::steady_timer tap_timer_;
|
||||
std::function<void(vamp_protocol::page_command)> command_handler_{};
|
||||
: touch_{std::move(executor), std::move(handler)} {}
|
||||
vamp_zero::touch_input touch_;
|
||||
std::mutex mutex_{};
|
||||
vamp_zero::ui_state state_{};
|
||||
std::mutex touch_mutex_{};
|
||||
std::optional<std::int32_t> active_touch_id_{};
|
||||
std::chrono::steady_clock::time_point touch_down_time_{};
|
||||
std::chrono::steady_clock::time_point last_tap_time_{};
|
||||
std::bool_t hold_sent_{};
|
||||
std::bool_t pending_tap_{};
|
||||
std::bool_t stopped_{};
|
||||
};
|
||||
|
||||
namespace {
|
||||
@@ -95,9 +79,6 @@ struct score_draw_cache {
|
||||
std::weak_ptr<vamp_zero::score_document const> document{};
|
||||
};
|
||||
|
||||
constexpr auto touch_hold_duration = std::chrono::milliseconds{700};
|
||||
constexpr auto touch_double_tap_duration = std::chrono::milliseconds{220};
|
||||
|
||||
auto bind_port(vamp_zero::config const &config) -> std::uint16_t {
|
||||
auto const &bind = config.control.endpoint.bind;
|
||||
auto colon = bind.rfind(':');
|
||||
@@ -561,7 +542,7 @@ public:
|
||||
}
|
||||
}
|
||||
auto handle_touch(luma::touch_event const &event) -> std::bool_t override {
|
||||
return runtime_->handle_touch(event);
|
||||
return runtime_->touch_.handle(event);
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<vamp_zero::ui_runtime> runtime_;
|
||||
@@ -583,117 +564,6 @@ vamp_zero::zero_ui::~zero_ui() {
|
||||
stop();
|
||||
}
|
||||
|
||||
auto vamp_zero::ui_runtime::send_touch_command(vamp_protocol::page_command command) -> void {
|
||||
if (!command_handler_) {
|
||||
return;
|
||||
}
|
||||
boost::asio::post(executor_, [weak = weak_from_this(), command] {
|
||||
auto self = weak.lock();
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = std::scoped_lock{self->touch_mutex_};
|
||||
if (self->stopped_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self->command_handler_(command);
|
||||
});
|
||||
}
|
||||
|
||||
auto vamp_zero::ui_runtime::cancel_pending_tap_locked() -> void {
|
||||
pending_tap_ = false;
|
||||
}
|
||||
|
||||
auto vamp_zero::ui_runtime::arm_pending_tap_locked() -> void {
|
||||
tap_timer_.expires_after(touch_double_tap_duration);
|
||||
tap_timer_.async_wait([weak = weak_from_this()](boost::system::error_code const &error) {
|
||||
auto self = weak.lock();
|
||||
if (error || !self) {
|
||||
return;
|
||||
}
|
||||
auto send_next = std::bool_t{false};
|
||||
{
|
||||
auto lock = std::scoped_lock{self->touch_mutex_};
|
||||
send_next = self->pending_tap_ && !self->stopped_;
|
||||
self->pending_tap_ = false;
|
||||
}
|
||||
if (send_next) {
|
||||
self->send_touch_command(vamp_protocol::page_command::NEXT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
auto vamp_zero::ui_runtime::handle_touch(luma::touch_event const &event) -> std::bool_t {
|
||||
if (!command_handler_ || event.points.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto consumed = std::bool_t{false};
|
||||
auto commands = std::vector<vamp_protocol::page_command>{};
|
||||
auto arm_tap = std::bool_t{false};
|
||||
{
|
||||
auto lock = std::scoped_lock{touch_mutex_};
|
||||
if (stopped_) {
|
||||
return false;
|
||||
}
|
||||
for (auto const &point : event.points) {
|
||||
if (point.phase == luma::touch_phase::DOWN && !active_touch_id_) {
|
||||
active_touch_id_ = point.id;
|
||||
touch_down_time_ = event.time;
|
||||
hold_sent_ = false;
|
||||
tap_timer_.cancel();
|
||||
consumed = true;
|
||||
continue;
|
||||
}
|
||||
if (!active_touch_id_ || point.id != *active_touch_id_) {
|
||||
continue;
|
||||
}
|
||||
consumed = true;
|
||||
if (point.phase == luma::touch_phase::CANCEL) {
|
||||
active_touch_id_.reset();
|
||||
hold_sent_ = false;
|
||||
cancel_pending_tap_locked();
|
||||
tap_timer_.cancel();
|
||||
continue;
|
||||
}
|
||||
if (point.phase == luma::touch_phase::MOVE) {
|
||||
if (!hold_sent_ && event.time - touch_down_time_ >= touch_hold_duration) {
|
||||
hold_sent_ = true;
|
||||
cancel_pending_tap_locked();
|
||||
tap_timer_.cancel();
|
||||
commands.push_back(vamp_protocol::page_command::SELECT);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (point.phase == luma::touch_phase::UP) {
|
||||
active_touch_id_.reset();
|
||||
if (!hold_sent_ && event.time - touch_down_time_ >= touch_hold_duration) {
|
||||
commands.push_back(vamp_protocol::page_command::SELECT);
|
||||
} else if (!hold_sent_) {
|
||||
if (pending_tap_ && event.time - last_tap_time_ <= touch_double_tap_duration) {
|
||||
cancel_pending_tap_locked();
|
||||
tap_timer_.cancel();
|
||||
commands.push_back(vamp_protocol::page_command::PREVIOUS);
|
||||
} else {
|
||||
pending_tap_ = true;
|
||||
last_tap_time_ = event.time;
|
||||
arm_tap = true;
|
||||
}
|
||||
}
|
||||
hold_sent_ = false;
|
||||
}
|
||||
}
|
||||
if (arm_tap) {
|
||||
arm_pending_tap_locked();
|
||||
}
|
||||
}
|
||||
for (auto command : commands) {
|
||||
send_touch_command(command);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
auto vamp_zero::zero_ui::run() -> std::expected<void, modulus::error> {
|
||||
if (auto status = application_->set_root(std::make_unique<vamp_root_control>(runtime_, score_loader_, *application_)); !status) {
|
||||
return status;
|
||||
@@ -704,12 +574,7 @@ auto vamp_zero::zero_ui::run() -> std::expected<void, modulus::error> {
|
||||
}
|
||||
|
||||
auto vamp_zero::zero_ui::stop() -> void {
|
||||
{
|
||||
auto lock = std::scoped_lock{runtime_->touch_mutex_};
|
||||
runtime_->stopped_ = true;
|
||||
runtime_->pending_tap_ = false;
|
||||
runtime_->tap_timer_.cancel();
|
||||
}
|
||||
runtime_->touch_.stop();
|
||||
score_loader_->stop();
|
||||
application_->request_stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user