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: ``` diff --git a/lua/settings.lua b/lua/settings.lua index f2a1ec7e..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 } @@ -290,7 +294,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() 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/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_) { 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(); } } } diff --git a/src/tangara/database/tag_parser.cpp b/src/tangara/database/tag_parser.cpp index a6a25555..15323a7c 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) @@ -310,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 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}; 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