summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-04-24 16:06:10 +1000
committerjacqueline <me@jacqueline.id.au>2024-04-24 16:06:10 +1000
commit920345b940bb3993c389d9e9be1a75a8041d431d (patch)
tree562e53906a14c31ba8a21b3c2ae64c652a16acb4 /src
parent531475e3511e9c722677d3a351b51d4a579876df (diff)
downloadtangara-fw-920345b940bb3993c389d9e9be1a75a8041d431d.tar.gz
Support getting a tree of controls + hooks via lua
Diffstat (limited to 'src')
-rw-r--r--src/input/include/input_device.hpp10
-rw-r--r--src/input/include/input_hook.hpp34
-rw-r--r--src/input/include/input_hook_actions.hpp19
-rw-r--r--src/input/include/input_nav_buttons.hpp3
-rw-r--r--src/input/include/input_touch_dpad.hpp3
-rw-r--r--src/input/include/input_touch_wheel.hpp3
-rw-r--r--src/input/include/input_volume_buttons.hpp3
-rw-r--r--src/input/include/lvgl_input_driver.hpp2
-rw-r--r--src/input/input_hook.cpp67
-rw-r--r--src/input/input_hook_actions.cpp53
-rw-r--r--src/input/input_nav_buttons.cpp12
-rw-r--r--src/input/input_touch_dpad.cpp18
-rw-r--r--src/input/input_touch_wheel.cpp18
-rw-r--r--src/input/input_volume_buttons.cpp12
-rw-r--r--src/input/lvgl_input_driver.cpp20
-rw-r--r--src/ui/ui_fsm.cpp12
16 files changed, 220 insertions, 69 deletions
diff --git a/src/input/include/input_device.hpp b/src/input/include/input_device.hpp
index 5fc3e066..59456351 100644
--- a/src/input/include/input_device.hpp
+++ b/src/input/include/input_device.hpp
@@ -11,6 +11,7 @@
#include <vector>
#include "hal/lv_hal_indev.h"
+#include "input_hook.hpp"
#include "property.hpp"
namespace input {
@@ -27,13 +28,8 @@ class IInputDevice {
virtual auto read(lv_indev_data_t* data) -> void = 0;
- // TODO: Add hooks and configuration (or are hooks just one kind of
- // configuration?)
-
- virtual auto settings()
- -> std::vector<std::pair<std::string, lua::Property>> {
- return {};
- }
+ virtual auto name() -> std::string = 0;
+ virtual auto hooks() -> std::vector<TriggerHooks> { return {}; }
};
} // namespace input
diff --git a/src/input/include/input_hook.hpp b/src/input/include/input_hook.hpp
index 96b9b5cd..81eb80d9 100644
--- a/src/input/include/input_hook.hpp
+++ b/src/input/include/input_hook.hpp
@@ -8,35 +8,53 @@
#include <functional>
#include <optional>
+#include <string>
#include "hal/lv_hal_indev.h"
+#include "lua.hpp"
+
#include "input_trigger.hpp"
namespace input {
-using HookCb = std::optional<std::function<void(lv_indev_data_t*)>>;
+struct HookCallback {
+ std::string name;
+ std::function<void(lv_indev_data_t*)> fn;
+};
class Hook {
public:
- Hook(HookCb);
+ Hook(std::string name, std::optional<HookCallback> cb);
auto invoke(lv_indev_data_t*) -> void;
- auto override(HookCb) -> void;
+ auto override(std::optional<HookCallback>) -> void;
+
+ auto name() const -> const std::string& { return name_; }
+ auto callback() -> std::optional<HookCallback>;
private:
- HookCb default_;
- HookCb override_;
+ std::string name_;
+ std::optional<HookCallback> default_;
+ std::optional<HookCallback> override_;
};
class TriggerHooks {
public:
- TriggerHooks(HookCb cb) : TriggerHooks(cb, cb, cb) {}
- TriggerHooks(HookCb, HookCb, HookCb);
+ TriggerHooks(std::string name, std::optional<HookCallback> cb)
+ : TriggerHooks(name, cb, cb, cb) {}
+ TriggerHooks(std::string name,
+ std::optional<HookCallback> click,
+ std::optional<HookCallback> long_press,
+ std::optional<HookCallback> repeat);
auto update(bool, lv_indev_data_t*) -> void;
- auto override(Trigger::State, HookCb) -> void;
+ auto override(Trigger::State, std::optional<HookCallback>) -> void;
+
+ auto name() const -> const std::string&;
+ auto pushHooks(lua_State*) -> void;
private:
+ std::string name_;
Trigger trigger_;
Hook click_;
diff --git a/src/input/include/input_hook_actions.hpp b/src/input/include/input_hook_actions.hpp
index a05a14e8..105bd10d 100644
--- a/src/input/include/input_hook_actions.hpp
+++ b/src/input/include/input_hook_actions.hpp
@@ -7,22 +7,25 @@
#pragma once
#include "hal/lv_hal_indev.h"
+#include "input_hook.hpp"
namespace input {
namespace actions {
-auto select(lv_indev_data_t*) -> void;
+auto select() -> HookCallback;
-auto scrollUp(lv_indev_data_t*) -> void;
-auto scrollDown(lv_indev_data_t*) -> void;
+auto scrollUp() -> HookCallback;
+auto scrollDown() -> HookCallback;
-auto scrollToTop(lv_indev_data_t*) -> void;
-auto scrollToBottom(lv_indev_data_t*) -> void;
+auto scrollToTop() -> HookCallback;
+auto scrollToBottom() -> HookCallback;
-auto goBack(lv_indev_data_t*) -> void;
+auto goBack() -> HookCallback;
-auto volumeUp(lv_indev_data_t*) -> void;
-auto volumeDown(lv_indev_data_t*) -> void;
+auto volumeUp() -> HookCallback;
+auto volumeDown() -> HookCallback;
+
+auto allActions() -> std::vector<HookCallback>;
} // namespace actions
} // namespace input
diff --git a/src/input/include/input_nav_buttons.hpp b/src/input/include/input_nav_buttons.hpp
index 60566ebc..4e4952c9 100644
--- a/src/input/include/input_nav_buttons.hpp
+++ b/src/input/include/input_nav_buttons.hpp
@@ -25,6 +25,9 @@ class NavButtons : public IInputDevice {
auto read(lv_indev_data_t* data) -> void override;
+ auto name() -> std::string override;
+ auto hooks() -> std::vector<TriggerHooks> override;
+
private:
drivers::IGpios& gpios_;
diff --git a/src/input/include/input_touch_dpad.hpp b/src/input/include/input_touch_dpad.hpp
index f80400dc..691e3243 100644
--- a/src/input/include/input_touch_dpad.hpp
+++ b/src/input/include/input_touch_dpad.hpp
@@ -24,6 +24,9 @@ class TouchDPad : public IInputDevice {
auto read(lv_indev_data_t* data) -> void override;
+ auto name() -> std::string override;
+ auto hooks() -> std::vector<TriggerHooks> override;
+
private:
drivers::TouchWheel& wheel_;
diff --git a/src/input/include/input_touch_wheel.hpp b/src/input/include/input_touch_wheel.hpp
index 88ebee40..1f116da9 100644
--- a/src/input/include/input_touch_wheel.hpp
+++ b/src/input/include/input_touch_wheel.hpp
@@ -27,6 +27,9 @@ class TouchWheel : public IInputDevice {
auto read(lv_indev_data_t* data) -> void override;
+ auto name() -> std::string override;
+ auto hooks() -> std::vector<TriggerHooks> override;
+
auto sensitivity() -> lua::Property&;
private:
diff --git a/src/input/include/input_volume_buttons.hpp b/src/input/include/input_volume_buttons.hpp
index 68962908..a684aa48 100644
--- a/src/input/include/input_volume_buttons.hpp
+++ b/src/input/include/input_volume_buttons.hpp
@@ -24,6 +24,9 @@ class VolumeButtons : public IInputDevice {
auto read(lv_indev_data_t* data) -> void override;
+ auto name() -> std::string override;
+ auto hooks() -> std::vector<TriggerHooks> override;
+
private:
drivers::IGpios& gpios_;
diff --git a/src/input/include/lvgl_input_driver.hpp b/src/input/include/lvgl_input_driver.hpp
index 257ccb28..9f43d27f 100644
--- a/src/input/include/lvgl_input_driver.hpp
+++ b/src/input/include/lvgl_input_driver.hpp
@@ -41,6 +41,8 @@ class LvglInputDriver {
auto registration() -> lv_indev_t* { return registration_; }
auto lock(bool l) -> void { is_locked_ = l; }
+ auto pushHooks(lua_State* L) -> int;
+
private:
drivers::NvsStorage& nvs_;
DeviceFactory& factory_;
diff --git a/src/input/input_hook.cpp b/src/input/input_hook.cpp
index d22a0b7a..1bb92196 100644
--- a/src/input/input_hook.cpp
+++ b/src/input/input_hook.cpp
@@ -9,25 +9,42 @@
#include <functional>
#include <optional>
#include "hal/lv_hal_indev.h"
+#include "input_trigger.hpp"
+#include "lua.h"
namespace input {
-Hook::Hook(HookCb fn) : default_(fn), override_() {}
+Hook::Hook(std::string name, std::optional<HookCallback> cb)
+ : name_(name), default_(cb), override_() {}
auto Hook::invoke(lv_indev_data_t* d) -> void {
- if (override_) {
- std::invoke(*override_, d);
- } else if (default_) {
- std::invoke(*default_, d);
+ auto cb = callback();
+ if (cb) {
+ std::invoke(cb->fn, d);
}
}
-auto Hook::override(HookCb fn) -> void {
- override_ = fn;
+auto Hook::override(std::optional<HookCallback> cb) -> void {
+ override_ = cb;
+}
+
+auto Hook::callback() -> std::optional<HookCallback> {
+ if (override_) {
+ return override_;
+ } else if (default_) {
+ return default_;
+ }
+ return {};
}
-TriggerHooks::TriggerHooks(HookCb click, HookCb long_press, HookCb repeat)
- : click_(click), long_press_(long_press), repeat_(repeat) {}
+TriggerHooks::TriggerHooks(std::string name,
+ std::optional<HookCallback> click,
+ std::optional<HookCallback> long_press,
+ std::optional<HookCallback> repeat)
+ : name_(name),
+ click_("click", click),
+ long_press_("long_press", long_press),
+ repeat_("repeat", repeat) {}
auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> void {
switch (trigger_.update(pressed)) {
@@ -46,16 +63,17 @@ auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> void {
}
}
-auto TriggerHooks::override(Trigger::State s, HookCb fn) -> void {
+auto TriggerHooks::override(Trigger::State s, std::optional<HookCallback> cb)
+ -> void {
switch (s) {
case Trigger::State::kClick:
- click_.override(fn);
+ click_.override(cb);
break;
case Trigger::State::kLongPress:
- long_press_.override(fn);
+ long_press_.override(cb);
break;
case Trigger::State::kRepeatPress:
- repeat_.override(fn);
+ repeat_.override(cb);
break;
case Trigger::State::kNone:
default:
@@ -63,4 +81,27 @@ auto TriggerHooks::override(Trigger::State s, HookCb fn) -> void {
}
}
+auto TriggerHooks::name() const -> const std::string& {
+ return name_;
+}
+
+auto TriggerHooks::pushHooks(lua_State* L) -> void {
+ lua_newtable(L);
+
+ auto add_trigger = [&](Hook& h) {
+ lua_pushlstring(L, h.name().data(), h.name().size());
+ auto cb = h.callback();
+ if (cb) {
+ lua_pushlstring(L, cb->name.data(), cb->name.size());
+ } else {
+ lua_pushnil(L);
+ }
+ lua_rawset(L, -3);
+ };
+
+ add_trigger(click_);
+ add_trigger(long_press_);
+ add_trigger(repeat_);
+}
+
} // namespace input
diff --git a/src/input/input_hook_actions.cpp b/src/input/input_hook_actions.cpp
index 0694cccf..26075c4c 100644
--- a/src/input/input_hook_actions.cpp
+++ b/src/input/input_hook_actions.cpp
@@ -16,36 +16,57 @@
namespace input {
namespace actions {
-auto select(lv_indev_data_t* d) -> void {
- d->state = LV_INDEV_STATE_PRESSED;
+auto select() -> HookCallback {
+ return HookCallback{.name = "select", .fn = [&](lv_indev_data_t* d) {
+ d->state = LV_INDEV_STATE_PRESSED;
+ }};
}
-auto scrollUp(lv_indev_data_t* d) -> void {
- d->enc_diff = -1;
+auto scrollUp() -> HookCallback {
+ return HookCallback{.name = "scroll_up",
+ .fn = [&](lv_indev_data_t* d) { d->enc_diff = -1; }};
}
-auto scrollDown(lv_indev_data_t* d) -> void {
- d->enc_diff = 1;
+auto scrollDown() -> HookCallback {
+ return HookCallback{.name = "scroll_down",
+ .fn = [&](lv_indev_data_t* d) { d->enc_diff = 1; }};
}
-auto scrollToTop(lv_indev_data_t* d) -> void {
- d->enc_diff = INT16_MIN;
+auto scrollToTop() -> HookCallback {
+ return HookCallback{.name = "scroll_to_top", .fn = [&](lv_indev_data_t* d) {
+ d->enc_diff = INT16_MIN;
+ }};
}
-auto scrollToBottom(lv_indev_data_t* d) -> void {
- d->enc_diff = INT16_MAX;
+auto scrollToBottom() -> HookCallback {
+ return HookCallback{
+ .name = "scroll_to_bottom",
+ .fn = [&](lv_indev_data_t* d) { d->enc_diff = INT16_MAX; }};
}
-auto goBack(lv_indev_data_t* d) -> void {
- events::Ui().Dispatch(ui::internal::BackPressed{});
+auto goBack() -> HookCallback {
+ return HookCallback{.name = "back", .fn = [&](lv_indev_data_t* d) {
+ events::Ui().Dispatch(ui::internal::BackPressed{});
+ }};
}
-auto volumeUp(lv_indev_data_t* d) -> void {
- events::Audio().Dispatch(audio::StepUpVolume{});
+auto volumeUp() -> HookCallback {
+ return HookCallback{.name = "volume_up", .fn = [&](lv_indev_data_t* d) {
+ events::Audio().Dispatch(audio::StepUpVolume{});
+ }};
}
-auto volumeDown(lv_indev_data_t* d) -> void {
- events::Audio().Dispatch(audio::StepDownVolume{});
+auto volumeDown() -> HookCallback {
+ return HookCallback{.name = "volume_down", .fn = [&](lv_indev_data_t* d) {
+ events::Audio().Dispatch(audio::StepDownVolume{});
+ }};
+}
+
+auto allActions() -> std::vector<HookCallback> {
+ return {
+ select(), scrollUp(), scrollDown(), scrollToTop(),
+ scrollToBottom(), goBack(), volumeUp(), volumeDown(),
+ };
}
} // namespace actions
diff --git a/src/input/input_nav_buttons.cpp b/src/input/input_nav_buttons.cpp
index 9db19a2e..7e579a16 100644
--- a/src/input/input_nav_buttons.cpp
+++ b/src/input/input_nav_buttons.cpp
@@ -15,12 +15,20 @@ namespace input {
NavButtons::NavButtons(drivers::IGpios& gpios)
: gpios_(gpios),
- up_(actions::scrollUp, actions::select, {}),
- down_(actions::scrollDown, actions::select, {}) {}
+ up_("upper", actions::scrollUp(), actions::select(), {}),
+ down_("lower", actions::scrollDown(), actions::select(), {}) {}
auto NavButtons::read(lv_indev_data_t* data) -> void {
up_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyUp), data);
down_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyDown), data);
}
+auto NavButtons::name() -> std::string {
+ return "buttons";
+}
+
+auto NavButtons::hooks() -> std::vector<TriggerHooks> {
+ return {up_, down_};
+}
+
} // namespace input
diff --git a/src/input/input_touch_dpad.cpp b/src/input/input_touch_dpad.cpp
index 32ca1ac1..f0805993 100644
--- a/src/input/input_touch_dpad.cpp
+++ b/src/input/input_touch_dpad.cpp
@@ -21,11 +21,11 @@ namespace input {
TouchDPad::TouchDPad(drivers::TouchWheel& wheel)
: wheel_(wheel),
- centre_(actions::select, {}, {}),
- up_(actions::scrollUp),
- right_({}, {}, {}),
- down_(actions::scrollDown),
- left_(actions::goBack) {}
+ centre_("centre", actions::select(), {}, {}),
+ up_("up", actions::scrollUp()),
+ right_("right", {}, {}, {}),
+ down_("down", actions::scrollDown()),
+ left_("left", actions::goBack()) {}
auto TouchDPad::read(lv_indev_data_t* data) -> void {
wheel_.Update();
@@ -51,4 +51,12 @@ auto TouchDPad::read(lv_indev_data_t* data) -> void {
data);
}
+auto TouchDPad::name() -> std::string {
+ return "dpad";
+}
+
+auto TouchDPad::hooks() -> std::vector<TriggerHooks> {
+ return {centre_, up_, right_, down_, left_};
+}
+
} // namespace input
diff --git a/src/input/input_touch_wheel.cpp b/src/input/input_touch_wheel.cpp
index 031c21ef..121b1ee5 100644
--- a/src/input/input_touch_wheel.cpp
+++ b/src/input/input_touch_wheel.cpp
@@ -39,11 +39,11 @@ TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
threshold_ = calculateThreshold(int_val);
return true;
}),
- centre_(actions::select, {}, {}),
- up_({}, actions::scrollToTop, actions::scrollUp),
- right_({}, {}, {}),
- down_({}, actions::scrollToBottom, actions::scrollDown),
- left_({}, actions::goBack, {}),
+ centre_("centre", actions::select(), {}, {}),
+ up_("up", {}, actions::scrollToTop(), actions::scrollUp()),
+ right_("right", {}, {}, {}),
+ down_("down", {}, actions::scrollToBottom(), actions::scrollDown()),
+ left_("left", {}, actions::goBack(), {}),
is_scrolling_(false),
threshold_(calculateThreshold(nvs.ScrollSensitivity())),
is_first_read_(true),
@@ -88,6 +88,14 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void {
data);
}
+auto TouchWheel::name() -> std::string {
+ return "wheel";
+}
+
+auto TouchWheel::hooks() -> std::vector<TriggerHooks> {
+ return {centre_, up_, right_, down_, left_};
+}
+
auto TouchWheel::sensitivity() -> lua::Property& {
return sensitivity_;
}
diff --git a/src/input/input_volume_buttons.cpp b/src/input/input_volume_buttons.cpp
index bc04cd66..607f81f1 100644
--- a/src/input/input_volume_buttons.cpp
+++ b/src/input/input_volume_buttons.cpp
@@ -12,11 +12,21 @@
namespace input {
VolumeButtons::VolumeButtons(drivers::IGpios& gpios)
- : gpios_(gpios), up_(actions::volumeUp), down_(actions::volumeDown) {}
+ : gpios_(gpios),
+ up_("upper", actions::volumeUp()),
+ down_("lower", actions::volumeDown()) {}
auto VolumeButtons::read(lv_indev_data_t* data) -> void {
up_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyUp), data);
down_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyDown), data);
}
+auto VolumeButtons::name() -> std::string {
+ return "buttons";
+}
+
+auto VolumeButtons::hooks() -> std::vector<TriggerHooks> {
+ return {up_, down_};
+}
+
} // namespace input
diff --git a/src/input/lvgl_input_driver.cpp b/src/input/lvgl_input_driver.cpp
index 9698aa79..61a85fa5 100644
--- a/src/input/lvgl_input_driver.cpp
+++ b/src/input/lvgl_input_driver.cpp
@@ -16,6 +16,8 @@
#include "input_touch_wheel.hpp"
#include "input_trigger.hpp"
#include "input_volume_buttons.hpp"
+#include "lauxlib.h"
+#include "lua.h"
#include "lvgl.h"
#include "nvs.hpp"
#include "property.hpp"
@@ -104,4 +106,22 @@ auto LvglInputDriver::feedback(uint8_t event) -> void {
}
}
+auto LvglInputDriver::pushHooks(lua_State* L) -> int {
+ lua_newtable(L);
+
+ for (auto& dev : inputs_) {
+ lua_pushlstring(L, dev->name().data(), dev->name().size());
+ lua_newtable(L);
+
+ for (auto& hook : dev->hooks()) {
+ lua_pushlstring(L, hook.name().data(), hook.name().size());
+ hook.pushHooks(L);
+ lua_rawset(L, -3);
+ }
+
+ lua_rawset(L, -3);
+ }
+ return 1;
+}
+
} // namespace input
diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp
index ceeb194d..1cbf1be4 100644
--- a/src/ui/ui_fsm.cpp
+++ b/src/ui/ui_fsm.cpp
@@ -14,6 +14,7 @@
#include "db_events.hpp"
#include "device_factory.hpp"
#include "display_init.hpp"
+#include "esp_spp_api.h"
#include "feedback_haptics.hpp"
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"
@@ -497,10 +498,13 @@ void Lua::entry() {
{"brightness", &sDisplayBrightness},
});
- registry.AddPropertyModule("controls", {
- {"scheme", &sInput->mode()},
- {"lock_switch", &sLockSwitch},
- });
+ registry.AddPropertyModule(
+ "controls",
+ {
+ {"scheme", &sInput->mode()},
+ {"lock_switch", &sLockSwitch},
+ {"hooks", [&](lua_State* L) { return sInput->pushHooks(L); }},
+ });
if (sDeviceFactory->touch_wheel()) {
registry.AddPropertyModule(