From d5946a91d076d12b6376fb46ccbcc23ea82980f5 Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Sun, 29 Dec 2024 22:37:26 +0000 Subject: [PATCH 1/8] BUILDING.md: add some notes about setup on Linux (#150) Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/150 Co-authored-by: Clayton Craft Co-committed-by: Clayton Craft --- BUILDING.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/BUILDING.md b/BUILDING.md index ee64b088..70ef7b8a 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1,5 +1,13 @@ # Building and flashing +NOTE: The development environment for Linux requires running external pre-compiled binaries linked against GLIBC. This means they will not run on Linux distros that use alternative libc (e.g. musl). + +0. For Linux, the following packages are needed to run the development env. Note that package names are from Debian, and may vary on other distros. + +- cmake +- libusb-1.0 +- python3-venv + 1. Make sure you've got all of the submodules in this repo correctly initialised: ``` From 6e087b2dc42787679bcb9d828d057b64fac77e33 Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Wed, 25 Dec 2024 18:04:40 -0800 Subject: [PATCH 2/8] suspend playback when headphones disconnected I think this is what most folks would expect to happen if BT is disconnected/disabled and the headphones are removed. Also, I think(?) this fixes one situation where the device doesn't idle/ sleep when folks would expect it to (not connected to headphones or bt). --- src/tangara/audio/audio_fsm.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tangara/audio/audio_fsm.cpp b/src/tangara/audio/audio_fsm.cpp index 63b960e4..603584b7 100644 --- a/src/tangara/audio/audio_fsm.cpp +++ b/src/tangara/audio/audio_fsm.cpp @@ -270,6 +270,9 @@ void AudioState::react(const system_fsm::HasPhonesChanged& ev) { if (sServices->bluetooth().enabled()) { events::Audio().Dispatch(audio::OutputModeChanged{ .set_to = drivers::NvsStorage::Output::kBluetooth}); + } else { + // Nothing connected + transit(); } } } From d985cfb5fbc500f6b32c34383a900f7fe0604c1f Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Thu, 26 Dec 2024 17:23:24 -0800 Subject: [PATCH 3/8] console: loglevel: improve help text I was confused about why setting the level to something lower didn't seem to work, so this attempts make it more clear that not all log levels are actually available on release builds. Fixes #155 --- src/tangara/dev_console/console.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tangara/dev_console/console.cpp b/src/tangara/dev_console/console.cpp index bc3a7aca..d902c176 100644 --- a/src/tangara/dev_console/console.cpp +++ b/src/tangara/dev_console/console.cpp @@ -73,7 +73,8 @@ void RegisterLogLevel() { .command = "loglevel", .help = "Sets the log level to one of \"VERBOSE\", \"DEBUG\", \"INFO\", " - "\"WARN\", \"ERROR\", \"NONE\"", + "\"WARN\", \"ERROR\", \"NONE\". NOTE: Some log levels aren't available " + "on release builds.", .hint = "level", .func = &CmdLogLevel, .argtable = NULL}; From 8a6c41be459d1eefa874137a6961434640d2a5e4 Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Fri, 27 Dec 2024 17:21:21 -0800 Subject: [PATCH 4/8] display: set lower limit for brightness Fixes #158 --- src/drivers/display.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/drivers/display.cpp b/src/drivers/display.cpp index 7321f20b..15cd6c62 100644 --- a/src/drivers/display.cpp +++ b/src/drivers/display.cpp @@ -194,6 +194,10 @@ auto Display::SetDisplayOn(bool enabled) -> void { } auto Display::SetBrightness(uint_fast8_t percent) -> void { + // Set a lower limit of 7%, below this the backlight turns off. + // See https://codeberg.org/cool-tech-zone/tangara-fw/issues/158 + if (percent < 7) + percent = 7; brightness_ = std::pow(static_cast(percent) / 100.0, 2.8) * 1024.0 + 0.5; if (first_flush_finished_ && display_on_) { From 93eec1ac6c8de691511a69235f8b072619d39a19 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Mon, 30 Dec 2024 10:08:48 +1100 Subject: [PATCH 5/8] Set the min brightness setting to 20% This is quite dim, but also slightly higher than the 'screensaver' brightness in #127. --- lua/settings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/settings.lua b/lua/settings.lua index f2a1ec7e..8547aa19 100644 --- a/lua/settings.lua +++ b/lua/settings.lua @@ -290,7 +290,7 @@ settings.DisplaySettings = SettingsScreen:new { local brightness = self.content:Slider { w = lvgl.PCT(100), - range = { min = 0, max = 100 }, + range = { min = 20, max = 100 }, value = display.brightness:get(), } brightness:onevent(lvgl.EVENT.VALUE_CHANGED, function() From 46f55e3a1f951683bbbff02e6d5ca8a13fdc7a19 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Mon, 30 Dec 2024 10:25:05 +1100 Subject: [PATCH 6/8] Accept more tags for track and disc number - Accept 'DISCNUMBER' as a synonym for 'DISC' - Accept 'TRACK' as a synonum for 'TRACKNUMBER' This should help with #146 --- src/tangara/database/tag_parser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tangara/database/tag_parser.cpp b/src/tangara/database/tag_parser.cpp index a6a25555..ab1d30f3 100644 --- a/src/tangara/database/tag_parser.cpp +++ b/src/tangara/database/tag_parser.cpp @@ -171,9 +171,11 @@ OggTagParser::OggTagParser() { nameToTag_["ALBUM"] = Tag::kAlbum; nameToTag_["ARTIST"] = Tag::kArtist; nameToTag_["ALBUMARTIST"] = Tag::kAlbumArtist; + nameToTag_["TRACK"] = Tag::kTrack; nameToTag_["TRACKNUMBER"] = Tag::kTrack; nameToTag_["GENRE"] = Tag::kGenres; nameToTag_["DISC"] = Tag::kDisc; + nameToTag_["DISCNUMBER"] = Tag::kDisc; } auto OggTagParser::ReadAndParseTags(std::string_view p) From 92908533c48a9bc9b84e66a65c09f590858a6c45 Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Thu, 26 Dec 2024 09:53:15 -0800 Subject: [PATCH 7/8] Attempt to parse tags only from supported audio files Trying and failing to parse tags from unsupported files is probably costly (requires reading from SD card), and it probably slows down indexing large collections that include a lot of non-audio files (like cover art, etc). This limits tag parsing to only files that have extensions for supported audio formats. It assumes that folks don't have audio files in supported formats with crazy extensions (e.g. an mp3-formatted file with the extension .lol). Since this hardcodes a list of supported file extensions for tag parsing, it'll need to be maintained later if more formats are supported. The file ext matching is case-insensitive. Fixes #149 --- src/tangara/database/tag_parser.cpp | 17 +++++++++++++++++ src/tangara/database/tag_parser.hpp | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/tangara/database/tag_parser.cpp b/src/tangara/database/tag_parser.cpp index ab1d30f3..15323a7c 100644 --- a/src/tangara/database/tag_parser.cpp +++ b/src/tangara/database/tag_parser.cpp @@ -312,6 +312,23 @@ auto GenericTagParser::ReadAndParseTags(std::string_view p) -> std::shared_ptr { std::string path{p}; libtags::Aux aux; + + // Fail fast if trying to parse a file that doesn't appear to be a supported audio format + // For context, see: https://codeberg.org/cool-tech-zone/tangara-fw/issues/149 + bool found = false; + for (const auto& ext : supported_exts) { + // Case-insensitive file extension check + if (std::equal(ext.rbegin(), ext.rend(), path.rbegin(), + [](char a, char b) { return std::tolower(a) == std::tolower(b); })) { + found=true; + break; + } + } + if (!found) { + ESP_LOGD(kTag, "skipping unsupported file: %s", path.c_str()); + return {}; + } + auto out = TrackTags::create(); aux.tags = out.get(); diff --git a/src/tangara/database/tag_parser.hpp b/src/tangara/database/tag_parser.hpp index 642c4876..9130b306 100644 --- a/src/tangara/database/tag_parser.hpp +++ b/src/tangara/database/tag_parser.hpp @@ -55,6 +55,19 @@ class GenericTagParser : public ITagParser { public: auto ReadAndParseTags(std::string_view path) -> std::shared_ptr override; + + private: + // Supported file extensions for parsing tags, derived from the list of + // supported audio formats here: + // https://cooltech.zone/tangara/docs/music-library/ + static constexpr std::string supported_exts[] = { + "flac", + "mp3", + "ogg", + "ogx", + "opus", + "wav" + }; }; } // namespace database From ff87c9217577783b60ee4cf466a3c59777a2fc40 Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Fri, 27 Dec 2024 23:23:49 -0800 Subject: [PATCH 8/8] Write settings to nvs when changing from the setting screen Otherwise, settings may not actually be saved if the device crashes/ reboots unexpectedly. Fixes #148 --- lua/settings.lua | 4 ++++ luals-stubs/nvs.lua | 9 +++++++++ src/tangara/lua/bridge.cpp | 2 ++ src/tangara/lua/lua_nvs.cpp | 39 +++++++++++++++++++++++++++++++++++++ src/tangara/lua/lua_nvs.hpp | 15 ++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 luals-stubs/nvs.lua create mode 100644 src/tangara/lua/lua_nvs.cpp create mode 100644 src/tangara/lua/lua_nvs.hpp diff --git a/lua/settings.lua b/lua/settings.lua index 8547aa19..9018d884 100644 --- a/lua/settings.lua +++ b/lua/settings.lua @@ -13,6 +13,7 @@ local usb = require("usb") local font = require("font") local main_menu = require("main_menu") local img = require("images") +local nvs = require("nvs") local settings = {} @@ -33,6 +34,9 @@ local SettingsScreen = widgets.MenuScreen:new { pad_left = 4, pad_right = 4, } + end, + on_hide = function(self) + nvs.write(); end } diff --git a/luals-stubs/nvs.lua b/luals-stubs/nvs.lua new file mode 100644 index 00000000..9e6eb8ee --- /dev/null +++ b/luals-stubs/nvs.lua @@ -0,0 +1,9 @@ +--- @meta + +--- @class nvs +local nvs = {} + +--- Saves current nvs +function nvs.write() end + +return nvs diff --git a/src/tangara/lua/bridge.cpp b/src/tangara/lua/bridge.cpp index 1c757a22..9521f265 100644 --- a/src/tangara/lua/bridge.cpp +++ b/src/tangara/lua/bridge.cpp @@ -25,6 +25,7 @@ #include "lua/lua_database.hpp" #include "lua/lua_filesystem.hpp" #include "lua/lua_font.hpp" +#include "lua/lua_nvs.hpp" #include "lua/lua_queue.hpp" #include "lua/lua_screen.hpp" #include "lua/lua_testing.hpp" @@ -84,6 +85,7 @@ auto Bridge::installBaseModules(lua_State* L) -> void { RegisterVersionModule(L); RegisterThemeModule(L); RegisterScreenModule(L); + RegisterNvsModule(L); } auto Bridge::installLvgl(lua_State* L) -> void { diff --git a/src/tangara/lua/lua_nvs.cpp b/src/tangara/lua/lua_nvs.cpp new file mode 100644 index 00000000..e38e58d9 --- /dev/null +++ b/src/tangara/lua/lua_nvs.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 2024 Clayton Craft + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "lua/lua_version.hpp" + +#include "lua.hpp" +#include "lua/bridge.hpp" + +#include "lua.h" +#include "lua/lua_thread.hpp" + +namespace lua { + +[[maybe_unused]] static constexpr char kTag[] = "lua_nvs"; + +static auto write(lua_State* L) -> int { + Bridge* instance = Bridge::Get(L); + instance->services().nvs().Write(); + + return 1; +} + +static const struct luaL_Reg kNvsFuncs[] = {{"write", write}, + {NULL, NULL}}; + +static auto lua_nvs(lua_State* L) -> int { + luaL_newlib(L, kNvsFuncs); + return 1; +} + +auto RegisterNvsModule(lua_State* L) -> void { + luaL_requiref(L, "nvs", lua_nvs, true); + lua_pop(L, 1); +} + +} // namespace lua diff --git a/src/tangara/lua/lua_nvs.hpp b/src/tangara/lua/lua_nvs.hpp new file mode 100644 index 00000000..1275fcc7 --- /dev/null +++ b/src/tangara/lua/lua_nvs.hpp @@ -0,0 +1,15 @@ +/* + * Copyright 2024 Clayton Craft + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include "lua.hpp" + +namespace lua { + +auto RegisterNvsModule(lua_State*) -> void; + +} // namespace lua