From 6c323f0fd075beb406df04d444fc4029b733ceb4 Mon Sep 17 00:00:00 2001 From: Rockwell Schrock Date: Sat, 1 Feb 2025 00:16:04 -0500 Subject: [PATCH 1/9] Don't detect center button touch until 250ms after wheel touch --- src/tangara/input/input_touch_wheel.cpp | 13 ++++++++++++- src/tangara/input/input_touch_wheel.hpp | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/tangara/input/input_touch_wheel.cpp b/src/tangara/input/input_touch_wheel.cpp index 19ac5211..6621a77e 100644 --- a/src/tangara/input/input_touch_wheel.cpp +++ b/src/tangara/input/input_touch_wheel.cpp @@ -21,6 +21,8 @@ #include "lua/property.hpp" #include "ui/ui_events.hpp" +#include "esp_timer.h" + namespace input { TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel) @@ -77,7 +79,16 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void { data->enc_diff = 0; } - centre_.update(wheel_data.is_button_touched && !wheel_data.is_wheel_touched, + // Prevent accidental center button touches while scrolling + if (wheel_data.is_wheel_touched) { + last_wheel_touch_time_ = esp_timer_get_time(); + } + + bool wheel_touch_timed_out = + esp_timer_get_time() - last_wheel_touch_time_ > SCROLL_TIMEOUT_US; + + centre_.update(wheel_touch_timed_out && wheel_data.is_button_touched && + !wheel_data.is_wheel_touched, data); // If the user is touching the wheel but not scrolling, then they may be diff --git a/src/tangara/input/input_touch_wheel.hpp b/src/tangara/input/input_touch_wheel.hpp index 982f89f4..00da99f1 100644 --- a/src/tangara/input/input_touch_wheel.hpp +++ b/src/tangara/input/input_touch_wheel.hpp @@ -36,6 +36,8 @@ class TouchWheel : public IInputDevice { auto sensitivity() -> lua::Property&; private: + const int64_t SCROLL_TIMEOUT_US = 250000; // 250ms + auto calculateTicks(const drivers::TouchWheelData& data) -> int8_t; auto calculateThreshold(uint8_t sensitivity) -> uint8_t; @@ -55,6 +57,7 @@ class TouchWheel : public IInputDevice { uint8_t threshold_; bool is_first_read_; uint8_t last_angle_; + int64_t last_wheel_touch_time_; }; } // namespace input From 8b12310990bbf03835bd910070841977cd57d22f Mon Sep 17 00:00:00 2001 From: Rockwell Schrock Date: Sat, 1 Feb 2025 10:15:39 -0500 Subject: [PATCH 2/9] On the playing screen, show "Not Playing" when the queue is empty --- lua/playing.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/playing.lua b/lua/playing.lua index 08cdaaa2..9391a85c 100644 --- a/lua/playing.lua +++ b/lua/playing.lua @@ -276,7 +276,7 @@ return screen:new { if queue.loading:get() then title:set { text = "Loading..." } else - title:set{text=""} + title:set{ text = "Not Playing" } end album:set{text=""} artist:set{text=""} From 15806716c57d78f3b43ff85caa72b83f6057dfc9 Mon Sep 17 00:00:00 2001 From: Rockwell Schrock Date: Sat, 1 Feb 2025 09:42:18 -0500 Subject: [PATCH 3/9] Autofocus the first index on the main menu --- lua/main_menu.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lua/main_menu.lua b/lua/main_menu.lua index cc7874d7..3b512d72 100644 --- a/lua/main_menu.lua +++ b/lua/main_menu.lua @@ -56,7 +56,6 @@ return widgets.MenuScreen:new { now_playing:onClicked(function() backstack.push(playing:new()) end) - local has_focus = false local track_duration = nil self.bindings = self.bindings + { @@ -72,7 +71,6 @@ return widgets.MenuScreen:new { now_playing:add_flag(lvgl.FLAG.HIDDEN) return else - has_focus = true now_playing:clear_flag(lvgl.FLAG.HIDDEN) end title:set { text = track.title } @@ -140,6 +138,10 @@ return widgets.MenuScreen:new { local function hide_no_indexes() no_indexes_container:add_flag(lvgl.FLAG.HIDDEN) indexes_list:clear_flag(lvgl.FLAG.HIDDEN) + + if indexes[1] then + indexes[1].object:focus() + end end local function update_visible_indexes() From 281518eb58d91f4354912c0ef62ce67ecef9ee87 Mon Sep 17 00:00:00 2001 From: Rockwell Schrock Date: Sat, 1 Feb 2025 10:47:09 -0500 Subject: [PATCH 4/9] Autofocus controls in settings screens --- lua/settings.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lua/settings.lua b/lua/settings.lua index c0e7c23e..4f1e36f8 100644 --- a/lua/settings.lua +++ b/lua/settings.lua @@ -93,6 +93,7 @@ settings.BluetoothSettings = SettingsScreen:new { local enabled = enable_sw:enabled() bluetooth.enabled:set(enabled) end) + enable_sw:focus() self.bindings = self.bindings + { bluetooth.enabled:bind(function(en) @@ -232,6 +233,7 @@ settings.HeadphonesSettings = SettingsScreen:new { local selection = volume_chooser:get('selected') + 1 volume.limit_db:set(limits[selection]) end) + volume_chooser:focus() theme.set_subject(self.content:Label { text = "Left/Right balance", @@ -304,6 +306,7 @@ settings.DisplaySettings = SettingsScreen:new { brightness:onevent(lvgl.EVENT.VALUE_CHANGED, function() display.brightness:set(brightness:value()) end) + brightness:focus() self.bindings = self.bindings + { display.brightness:bind(function(b) @@ -372,6 +375,8 @@ settings.ThemeSettings = SettingsScreen:new { backstack.reset(main_menu:new()) end end) + + theme_chooser:focus() end } @@ -419,6 +424,8 @@ settings.InputSettings = SettingsScreen:new { controls.scheme:set(scheme) end) + controls_chooser:focus() + theme.set_subject(self.content:Label { text = "Scroll Sensitivity", }, "settings_title") @@ -483,6 +490,7 @@ settings.MassStorageSettings = SettingsScreen:new { end bind_switch() end) + enable_sw:focus() self.bindings = self.bindings + { usb.msc_enabled:bind(bind_switch), @@ -560,6 +568,7 @@ settings.DatabaseSettings = SettingsScreen:new { update:onClicked(function() database.update() end) + update:focus() self.bindings = self.bindings + { database.auto_update:bind(function(en) @@ -841,10 +850,11 @@ settings.Root = widgets.MenuScreen:new { end) end item:add_style(styles.list_item) + return item end local audio_section = section("Audio") - submenu("Bluetooth", settings.BluetoothSettings, audio_section) + local first_item = submenu("Bluetooth", settings.BluetoothSettings, audio_section) submenu("Headphones", settings.HeadphonesSettings) section("Interface") @@ -863,6 +873,8 @@ settings.Root = widgets.MenuScreen:new { submenu("Firmware", settings.FirmwareSettings) submenu("Licenses", settings.LicensesScreen) submenu("Regulatory", settings.RegulatoryScreen) + + first_item:focus() end } From 1c0170254cd0653cf089ba03b6a06fc9786e357a Mon Sep 17 00:00:00 2001 From: Rockwell Schrock Date: Sat, 1 Feb 2025 11:17:38 -0500 Subject: [PATCH 5/9] Add .DS_Store to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7776977d..1ff0f7b4 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ sdkconfig.old .vscode compile_commands.json warnings.txt +.DS_Store doc/ From e8eaf3df10a896cb28e91cfc416b19303926a00a Mon Sep 17 00:00:00 2001 From: Tess Eisenberger Date: Sat, 1 Feb 2025 15:59:08 -0800 Subject: [PATCH 6/9] Add a new setting for input controls when locked This is just the plumbing of the new setting. The input methods will come in subsequent patches. --- src/drivers/include/drivers/nvs.hpp | 8 ++++++ src/drivers/nvs.cpp | 17 +++++++++++++ src/tangara/input/input_device.hpp | 3 ++- src/tangara/input/input_nav_buttons.cpp | 2 +- src/tangara/input/input_nav_buttons.hpp | 2 +- src/tangara/input/input_touch_dpad.cpp | 2 +- src/tangara/input/input_touch_dpad.hpp | 2 +- src/tangara/input/input_touch_wheel.cpp | 2 +- src/tangara/input/input_touch_wheel.hpp | 2 +- src/tangara/input/input_volume_buttons.cpp | 2 +- src/tangara/input/input_volume_buttons.hpp | 2 +- src/tangara/input/lvgl_input_driver.cpp | 29 +++++++++++++++++++++- src/tangara/input/lvgl_input_driver.hpp | 2 ++ 13 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp index 9725bb0f..b6192ab5 100644 --- a/src/drivers/include/drivers/nvs.hpp +++ b/src/drivers/include/drivers/nvs.hpp @@ -138,6 +138,13 @@ class NvsStorage { auto PrimaryInput() -> InputModes; auto PrimaryInput(InputModes) -> void; + enum class LockedInputModes : uint8_t { + kDisabled = 0, + }; + + auto LockedInput() -> LockedInputModes; + auto LockedInput(LockedInputModes) -> void; + auto QueueRepeatMode() -> uint8_t; auto QueueRepeatMode(uint8_t) -> void; @@ -167,6 +174,7 @@ class NvsStorage { Setting amp_cur_vol_; Setting amp_left_bias_; Setting input_mode_; + Setting locked_input_mode_; Setting output_mode_; Setting theme_; diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index 6f0d874e..a9f30042 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -34,6 +34,7 @@ static constexpr char kKeyAmpMaxVolume[] = "hp_vol_max"; static constexpr char kKeyAmpCurrentVolume[] = "hp_vol"; static constexpr char kKeyAmpLeftBias[] = "hp_bias"; static constexpr char kKeyPrimaryInput[] = "in_pri"; +static constexpr char kKeyLockedInput[] = "in_locked"; static constexpr char kKeyScrollSensitivity[] = "scroll"; static constexpr char kKeyLockPolarity[] = "lockpol"; static constexpr char kKeyDisplayCols[] = "dispcols"; @@ -272,6 +273,7 @@ NvsStorage::NvsStorage(nvs_handle_t handle) amp_cur_vol_(kKeyAmpCurrentVolume), amp_left_bias_(kKeyAmpLeftBias), input_mode_(kKeyPrimaryInput), + locked_input_mode_(kKeyLockedInput), output_mode_(kKeyOutput), theme_{kKeyInterfaceTheme}, bt_preferred_(kKeyBluetoothPreferred), @@ -570,6 +572,21 @@ auto NvsStorage::PrimaryInput(InputModes mode) -> void { input_mode_.set(static_cast(mode)); } +auto NvsStorage::LockedInput() -> LockedInputModes { + std::lock_guard lock{mutex_}; + switch (input_mode_.get().value_or(static_cast(LockedInputModes::kDisabled))) { + case static_cast(LockedInputModes::kDisabled): + return LockedInputModes::kDisabled; + default: + return LockedInputModes::kDisabled; + } +} + +auto NvsStorage::LockedInput(LockedInputModes mode) -> void { + std::lock_guard lock{mutex_}; + locked_input_mode_.set(static_cast(mode)); +} + auto NvsStorage::QueueRepeatMode() -> uint8_t { std::lock_guard lock{mutex_}; return queue_repeat_mode_.get().value_or(0); diff --git a/src/tangara/input/input_device.hpp b/src/tangara/input/input_device.hpp index 7edded3e..424c0da3 100644 --- a/src/tangara/input/input_device.hpp +++ b/src/tangara/input/input_device.hpp @@ -10,6 +10,7 @@ #include #include +#include "drivers/nvs.hpp" #include "indev/lv_indev.h" #include "input/input_hook.hpp" #include "lua/property.hpp" @@ -34,7 +35,7 @@ class IInputDevice { } /* Called by the LVGL driver when controls are being locked. */ - virtual auto onLock() -> void {} + virtual auto onLock(drivers::NvsStorage::LockedInputModes) -> void {} /* Called by the LVGL driver when controls are being unlocked. */ virtual auto onUnlock() -> void {} }; diff --git a/src/tangara/input/input_nav_buttons.cpp b/src/tangara/input/input_nav_buttons.cpp index 54bef7a6..a5e10013 100644 --- a/src/tangara/input/input_nav_buttons.cpp +++ b/src/tangara/input/input_nav_buttons.cpp @@ -42,7 +42,7 @@ auto NavButtons::triggers() return {up_, down_}; } -auto NavButtons::onLock() -> void { +auto NavButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { locked_ = true; } diff --git a/src/tangara/input/input_nav_buttons.hpp b/src/tangara/input/input_nav_buttons.hpp index 95d56d54..c9575fe0 100644 --- a/src/tangara/input/input_nav_buttons.hpp +++ b/src/tangara/input/input_nav_buttons.hpp @@ -28,7 +28,7 @@ class NavButtons : public IInputDevice { auto name() -> std::string override; auto triggers() -> std::vector> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> void override; auto onUnlock() -> void override; private: diff --git a/src/tangara/input/input_touch_dpad.cpp b/src/tangara/input/input_touch_dpad.cpp index 8ed2bdd7..25c2315b 100644 --- a/src/tangara/input/input_touch_dpad.cpp +++ b/src/tangara/input/input_touch_dpad.cpp @@ -65,7 +65,7 @@ auto TouchDPad::triggers() return {centre_, up_, right_, down_, left_}; } -auto TouchDPad::onLock() -> void { +auto TouchDPad::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { wheel_.LowPowerMode(true); locked_ = true; } diff --git a/src/tangara/input/input_touch_dpad.hpp b/src/tangara/input/input_touch_dpad.hpp index d787bace..086f556e 100644 --- a/src/tangara/input/input_touch_dpad.hpp +++ b/src/tangara/input/input_touch_dpad.hpp @@ -27,7 +27,7 @@ class TouchDPad : public IInputDevice { auto name() -> std::string override; auto triggers() -> std::vector> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> void override; auto onUnlock() -> void override; private: diff --git a/src/tangara/input/input_touch_wheel.cpp b/src/tangara/input/input_touch_wheel.cpp index 19ac5211..ea6d1b56 100644 --- a/src/tangara/input/input_touch_wheel.cpp +++ b/src/tangara/input/input_touch_wheel.cpp @@ -113,7 +113,7 @@ auto TouchWheel::triggers() return {centre_, up_, right_, down_, left_}; } -auto TouchWheel::onLock() -> void { +auto TouchWheel::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { wheel_.LowPowerMode(true); locked_ = true; } diff --git a/src/tangara/input/input_touch_wheel.hpp b/src/tangara/input/input_touch_wheel.hpp index 982f89f4..e8391914 100644 --- a/src/tangara/input/input_touch_wheel.hpp +++ b/src/tangara/input/input_touch_wheel.hpp @@ -30,7 +30,7 @@ class TouchWheel : public IInputDevice { auto name() -> std::string override; auto triggers() -> std::vector> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> void override; auto onUnlock() -> void override; auto sensitivity() -> lua::Property&; diff --git a/src/tangara/input/input_volume_buttons.cpp b/src/tangara/input/input_volume_buttons.cpp index 7ffdfcdc..6720afae 100644 --- a/src/tangara/input/input_volume_buttons.cpp +++ b/src/tangara/input/input_volume_buttons.cpp @@ -39,7 +39,7 @@ auto VolumeButtons::triggers() return {up_, down_}; } -auto VolumeButtons::onLock() -> void { +auto VolumeButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { locked_ = true; } diff --git a/src/tangara/input/input_volume_buttons.hpp b/src/tangara/input/input_volume_buttons.hpp index ffb3156b..008252cd 100644 --- a/src/tangara/input/input_volume_buttons.hpp +++ b/src/tangara/input/input_volume_buttons.hpp @@ -27,7 +27,7 @@ class VolumeButtons : public IInputDevice { auto name() -> std::string override; auto triggers() -> std::vector> override; - auto onLock() -> void override; + auto onLock(drivers::NvsStorage::LockedInputModes) -> void override; auto onUnlock() -> void override; private: diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp index c008b007..9177f92f 100644 --- a/src/tangara/input/lvgl_input_driver.cpp +++ b/src/tangara/input/lvgl_input_driver.cpp @@ -53,6 +53,8 @@ static void focus_cb(lv_group_t* group) { instance->feedback(LV_EVENT_FOCUSED); } +namespace { + auto intToMode(int raw) -> std::optional { switch (raw) { case 0: @@ -68,6 +70,17 @@ auto intToMode(int raw) -> std::optional { } } +auto intToLockedMode(int raw) -> std::optional { + switch (raw) { + case 0: + return drivers::NvsStorage::LockedInputModes::kDisabled; + default: + return {}; + } +} + +} // namespace {} + LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs, DeviceFactory& factory) : nvs_(nvs), @@ -85,6 +98,18 @@ LvglInputDriver::LvglInputDriver(drivers::NvsStorage& nvs, inputs_ = factory.createInputs(*mode); return true; }), + locked_mode_(static_cast(nvs.LockedInput()), + [&](const lua::LuaValue& val) { + if (!std::holds_alternative(val)) { + return false; + } + auto mode = intToLockedMode(std::get(val)); + if (!mode) { + return false; + } + nvs.LockedInput(*mode); + return true; + }), inputs_(factory.createInputs(nvs.PrimaryInput())), feedbacks_(factory.createFeedbacks()), is_locked_(false) { @@ -130,9 +155,11 @@ auto LvglInputDriver::feedback(uint8_t event) -> void { auto LvglInputDriver::lock(bool l) -> void { is_locked_ = l; + auto locked_input_mode = nvs_.LockedInput(); + for (auto&& device : inputs_) { if (l) { - device->onLock(); + device->onLock(locked_input_mode); } else { device->onUnlock(); } diff --git a/src/tangara/input/lvgl_input_driver.hpp b/src/tangara/input/lvgl_input_driver.hpp index 9b62c24d..ce950621 100644 --- a/src/tangara/input/lvgl_input_driver.hpp +++ b/src/tangara/input/lvgl_input_driver.hpp @@ -36,6 +36,7 @@ class LvglInputDriver { LvglInputDriver(drivers::NvsStorage& nvs, DeviceFactory&); auto mode() -> lua::Property& { return mode_; } + auto lockedMode() -> lua::Property& { return locked_mode_; } auto setGroup(lv_group_t*) -> void; auto read(lv_indev_data_t* data) -> void; @@ -49,6 +50,7 @@ class LvglInputDriver { DeviceFactory& factory_; lua::Property mode_; + lua::Property locked_mode_; lv_indev_t* device_; std::vector> inputs_; From 1d485c97b0c03577a40b34fb762c76e98f417fa4 Mon Sep 17 00:00:00 2001 From: Tess Eisenberger Date: Sat, 1 Feb 2025 16:15:17 -0800 Subject: [PATCH 7/9] Add optional support for changing volume while locked This adds a new Controls setting for adjusting the behavior when locked, and an option for allowing volume control. --- lua/settings.lua | 78 +++++++++++++--------- src/drivers/include/drivers/nvs.hpp | 1 + src/drivers/nvs.cpp | 4 +- src/tangara/input/input_volume_buttons.cpp | 10 +-- src/tangara/input/input_volume_buttons.hpp | 3 +- src/tangara/input/lvgl_input_driver.cpp | 2 + src/tangara/lua/lua_controls.cpp | 17 +++++ src/tangara/ui/ui_fsm.cpp | 1 + 8 files changed, 78 insertions(+), 38 deletions(-) diff --git a/lua/settings.lua b/lua/settings.lua index c0e7c23e..6386b468 100644 --- a/lua/settings.lua +++ b/lua/settings.lua @@ -380,44 +380,58 @@ settings.InputSettings = SettingsScreen:new { create_ui = function(self) SettingsScreen.create_ui(self) - theme.set_subject(self.content:Label { - text = "Control scheme", - }, "settings_title") + -- Use the control scheme enum lists to generate the relevant dropdowns + local make_scheme_control = function(self, scheme_list, control_scheme) + local option_to_scheme = {} + local scheme_to_option = {} + local option_idx = 0 + local options = "" + + -- Sort the keys to order the dropdowns the same as the enums + keys = {} + for i in pairs(scheme_list) do table.insert(keys, i) end + table.sort(keys) + + for i, k in pairs(keys) do + v = scheme_list[k] + + option_to_scheme[option_idx] = k + scheme_to_option[k] = option_idx + if option_idx > 0 then + options = options .. "\n" + end + options = options .. v + option_idx = option_idx + 1 + end - local schemes = controls.schemes() - local option_to_scheme = {} - local scheme_to_option = {} + local controls_chooser = self.content:Dropdown { + options = options, + symbol = img.chevron, + } - local option_idx = 0 - local options = "" + self.bindings = self.bindings + { + control_scheme:bind(function(s) + local option = scheme_to_option[s] + controls_chooser:set({ selected = option }) + end) + } - for i, v in pairs(schemes) do - option_to_scheme[option_idx] = i - scheme_to_option[i] = option_idx - if option_idx > 0 then - options = options .. "\n" - end - options = options .. v - option_idx = option_idx + 1 + controls_chooser:onevent(lvgl.EVENT.VALUE_CHANGED, function() + local option = controls_chooser:get('selected') + local scheme = option_to_scheme[option] + control_scheme:set(scheme) + end) end - local controls_chooser = self.content:Dropdown { - options = options, - symbol = img.chevron, - } - - self.bindings = self.bindings + { - controls.scheme:bind(function(s) - local option = scheme_to_option[s] - controls_chooser:set({ selected = option }) - end) - } + theme.set_subject(self.content:Label { + text = "Control scheme", + }, "settings_title") + make_scheme_control(self, controls.schemes(), controls.scheme) - controls_chooser:onevent(lvgl.EVENT.VALUE_CHANGED, function() - local option = controls_chooser:get('selected') - local scheme = option_to_scheme[option] - controls.scheme:set(scheme) - end) + theme.set_subject(self.content:Label { + text = "Control scheme when locked", + }, "settings_title") + make_scheme_control(self, controls.locked_schemes(), controls.locked_scheme) theme.set_subject(self.content:Label { text = "Scroll Sensitivity", diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp index b6192ab5..18bc5de6 100644 --- a/src/drivers/include/drivers/nvs.hpp +++ b/src/drivers/include/drivers/nvs.hpp @@ -140,6 +140,7 @@ class NvsStorage { enum class LockedInputModes : uint8_t { kDisabled = 0, + kVolumeOnly = 1, }; auto LockedInput() -> LockedInputModes; diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index a9f30042..f46049ad 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -574,9 +574,11 @@ auto NvsStorage::PrimaryInput(InputModes mode) -> void { auto NvsStorage::LockedInput() -> LockedInputModes { std::lock_guard lock{mutex_}; - switch (input_mode_.get().value_or(static_cast(LockedInputModes::kDisabled))) { + switch (locked_input_mode_.get().value_or(static_cast(LockedInputModes::kDisabled))) { case static_cast(LockedInputModes::kDisabled): return LockedInputModes::kDisabled; + case static_cast(LockedInputModes::kVolumeOnly): + return LockedInputModes::kVolumeOnly; default: return LockedInputModes::kDisabled; } diff --git a/src/tangara/input/input_volume_buttons.cpp b/src/tangara/input/input_volume_buttons.cpp index 6720afae..5c814ffa 100644 --- a/src/tangara/input/input_volume_buttons.cpp +++ b/src/tangara/input/input_volume_buttons.cpp @@ -15,13 +15,15 @@ VolumeButtons::VolumeButtons(drivers::IGpios& gpios) : gpios_(gpios), up_("upper", actions::volumeUp()), down_("lower", actions::volumeDown()), - locked_(false) {} + locked_() {} auto VolumeButtons::read(lv_indev_data_t* data) -> void { bool up = !gpios_.Get(drivers::IGpios::Pin::kKeyUp); bool down = !gpios_.Get(drivers::IGpios::Pin::kKeyDown); - if ((up && down) || locked_) { + bool input_disabled = locked_.has_value() && (locked_ != drivers::NvsStorage::LockedInputModes::kVolumeOnly); + + if ((up && down) || input_disabled) { up = false; down = false; } @@ -40,11 +42,11 @@ auto VolumeButtons::triggers() } auto VolumeButtons::onLock(drivers::NvsStorage::LockedInputModes mode) -> void { - locked_ = true; + locked_ = mode; } auto VolumeButtons::onUnlock() -> void { - locked_ = false; + locked_ = {}; } } // namespace input diff --git a/src/tangara/input/input_volume_buttons.hpp b/src/tangara/input/input_volume_buttons.hpp index 008252cd..35a44390 100644 --- a/src/tangara/input/input_volume_buttons.hpp +++ b/src/tangara/input/input_volume_buttons.hpp @@ -36,7 +36,8 @@ class VolumeButtons : public IInputDevice { TriggerHooks up_; TriggerHooks down_; - bool locked_; + // When locked, this contains the active mode + std::optional locked_; }; } // namespace input diff --git a/src/tangara/input/lvgl_input_driver.cpp b/src/tangara/input/lvgl_input_driver.cpp index 9177f92f..2859c6a8 100644 --- a/src/tangara/input/lvgl_input_driver.cpp +++ b/src/tangara/input/lvgl_input_driver.cpp @@ -74,6 +74,8 @@ auto intToLockedMode(int raw) -> std::optional int { return 1; } +static auto locked_controls_schemes(lua_State* L) -> int { + lua_newtable(L); + + lua_pushliteral(L, "Disabled"); + lua_rawseti( + L, -2, + static_cast(drivers::NvsStorage::LockedInputModes::kDisabled)); + + lua_pushliteral(L, "Volume Only"); + lua_rawseti( + L, -2, + static_cast(drivers::NvsStorage::LockedInputModes::kVolumeOnly)); + + return 1; +} + static const struct luaL_Reg kControlsFuncs[] = {{"schemes", controls_schemes}, + {"locked_schemes", locked_controls_schemes}, {NULL, NULL}}; static auto lua_controls(lua_State* state) -> int { diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp index 4a54d974..1823f780 100644 --- a/src/tangara/ui/ui_fsm.cpp +++ b/src/tangara/ui/ui_fsm.cpp @@ -667,6 +667,7 @@ void Lua::entry() { "controls", { {"scheme", &sInput->mode()}, + {"locked_scheme", &sInput->lockedMode()}, {"lock_switch", &sLockSwitch}, {"hooks", [&](lua_State* L) { return sInput->pushHooks(L); }}, }); From 546daf71c1b04284848c4b5edfbaa3c5b4a284f4 Mon Sep 17 00:00:00 2001 From: Tess Eisenberger Date: Sun, 2 Feb 2025 00:30:59 -0800 Subject: [PATCH 8/9] Persist locked control mode setting --- src/drivers/nvs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp index f46049ad..02a0058b 100644 --- a/src/drivers/nvs.cpp +++ b/src/drivers/nvs.cpp @@ -302,6 +302,7 @@ auto NvsStorage::Read() -> void { amp_cur_vol_.read(handle_); amp_left_bias_.read(handle_); input_mode_.read(handle_); + locked_input_mode_.read(handle_); output_mode_.read(handle_); theme_.read(handle_); bt_preferred_.read(handle_); @@ -325,6 +326,7 @@ auto NvsStorage::Write() -> bool { amp_cur_vol_.write(handle_); amp_left_bias_.write(handle_); input_mode_.write(handle_); + locked_input_mode_.write(handle_); output_mode_.write(handle_); theme_.write(handle_); bt_preferred_.write(handle_); From 813db15da84ee82066564b51f83be451cf121a00 Mon Sep 17 00:00:00 2001 From: ailurux Date: Tue, 4 Feb 2025 14:00:32 +1100 Subject: [PATCH 9/9] Fix merge issue breaking control settings screen --- lua/settings.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lua/settings.lua b/lua/settings.lua index 74bd2103..aae6db99 100644 --- a/lua/settings.lua +++ b/lua/settings.lua @@ -426,12 +426,14 @@ settings.InputSettings = SettingsScreen:new { local scheme = option_to_scheme[option] control_scheme:set(scheme) end) + + return controls_chooser end theme.set_subject(self.content:Label { text = "Control scheme", }, "settings_title") - make_scheme_control(self, controls.schemes(), controls.scheme) + local controls_chooser = make_scheme_control(self, controls.schemes(), controls.scheme) theme.set_subject(self.content:Label { text = "Control scheme when locked",