From 61cc7209ef69e6142242fd67d8c484bc1c976dbe Mon Sep 17 00:00:00 2001 From: ailurux Date: Fri, 17 Jan 2025 02:24:05 +0000 Subject: [PATCH] ailurux/now-playing-menu (#184) Overflow menu for the now playing screen. New home for the info screen here. Adds quick navigation to current album or artist (thanks tjk!) and clear queue button. Also fixed up the way the now playing screen looks when queue is cleared (remove previous duration and don't show "loading" if nothing is actively loading). Reviewed-on: https://codeberg.org/cool-tech-zone/tangara-fw/pulls/184 Co-authored-by: ailurux Co-committed-by: ailurux --- lua/images.lua | 1 + lua/img/menu.png | Bin 0 -> 7067 bytes lua/playing.lua | 22 +++-- lua/playing_menu.lua | 141 +++++++++++++++++++++++++++++++ src/tangara/lua/lua_database.cpp | 25 ++++++ 5 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 lua/img/menu.png create mode 100644 lua/playing_menu.lua diff --git a/lua/images.lua b/lua/images.lua index 404ae66e..b10d0f74 100644 --- a/lua/images.lua +++ b/lua/images.lua @@ -28,6 +28,7 @@ local img = { listened = lvgl.ImgData("//lua/img/listened.png"), unlistened = lvgl.ImgData("//lua/img/unlistened.png"), info = lvgl.ImgData("//lua/img/info.png"), + menu = lvgl.ImgData("//lua/img/menu.png"), } return img diff --git a/lua/img/menu.png b/lua/img/menu.png new file mode 100644 index 0000000000000000000000000000000000000000..afb1a921fb4ff736495a85d8ace9094ba1ac672b GIT binary patch literal 7067 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 PjR +-- +-- SPDX-License-Identifier: GPL-3.0-only + +local lvgl = require("lvgl") +local widgets = require("widgets") +local backstack = require("backstack") +local font = require("font") +local playback = require("playback") +local queue = require("queue") +local screen = require("screen") +local theme = require("theme") +local track_info = require("track_info") +local styles = require("styles") + +return screen:new { + create_ui = function(self) + self.root = lvgl.Object(nil, { + flex = { + flex_direction = "column", + flex_wrap = "wrap", + justify_content = "center", + align_items = "center", + align_content = "center", + }, + w = lvgl.HOR_RES(), + h = lvgl.VER_RES(), + }) + self.root:center() + + self.status_bar = widgets.StatusBar(self, { + back_cb = backstack.pop, + transparent_bg = true, + }) + + + local menu_items = lvgl.List(self.root, { + w = lvgl.PCT(100), + h = lvgl.PCT(100), + flex_grow = 1, + }) + + local info_btn = menu_items:add_btn(nil, "Track Info") + info_btn:onClicked(function() + backstack.push(track_info:new()) + end) + info_btn:add_style(styles.list_item) + + local current_artist = nil + local album_artist = nil + local current_album = nil + + local artist_btn = menu_items:add_btn(nil, "Go To Artist") + artist_btn:add_style(styles.list_item) + artist_btn:onClicked(function() + local found_iter = nil + local media_type = nil + for _, idx in ipairs(database.indexes()) do + if idx:id() == database.IndexTypes.ALL_ARTISTS then + -- Find the sub-index for this artist. + local artist_iter = idx:iter() + -- Workaround for lack of pairs/ipairs on these iterators. + local artist_record = artist_iter:next() + while artist_record do + if artist_record:title() == current_artist then + found_iter = artist_record:contents() + media_type = idx:type() + goto artist_done + end + artist_record = artist_iter:next() + end + end + end + ::artist_done:: + if found_iter then + backstack.push(require("browser"):new { + title = current_artist, + iterator = found_iter, + mediatype = media_type, + }) + end + end) + + local album_btn = menu_items:add_btn(nil, "Go To Album") + album_btn:add_style(styles.list_item) + album_btn:onClicked(function() + local found_iter = nil + local media_type = nil + for _, idx in ipairs(database.indexes()) do + if idx:id() == database.IndexTypes.ALBUMS_BY_ARTIST then + -- Find the sub-index for this artist. + local artist_iter = idx:iter() + -- Workaround for lack of pairs/ipairs on these iterators. + local artist_record = artist_iter:next() + while artist_record do + if artist_record:title() == album_artist then + -- Find the sub-sub-index for this album. + local album_iter = artist_record:contents() + local album_record = album_iter:next() + while album_record do + if album_record:title() == current_album then + found_iter = album_record:contents() + media_type = idx:type() + goto album_done + end + album_record = album_iter:next() + end + end + artist_record = artist_iter:next() + end + end + end + ::album_done:: + if found_iter then + backstack.push(require("browser"):new { + title = current_album, + iterator = found_iter, + mediatype = media_type, + }) + end + end) + + + local clear_btn = menu_items:add_btn(nil, "Clear Queue") + clear_btn:onClicked(function() + queue.clear() + backstack.pop() + end) + clear_btn:add_style(styles.list_item) + + self.bindings = self.bindings + { + playback.track:bind(function(track) + current_artist = track.artist + current_album = track.album + album_artist = track.album_artist + end), + } + + end +} diff --git a/src/tangara/lua/lua_database.cpp b/src/tangara/lua/lua_database.cpp index 2a3ab59d..e79d6141 100644 --- a/src/tangara/lua/lua_database.cpp +++ b/src/tangara/lua/lua_database.cpp @@ -406,6 +406,31 @@ static auto lua_database(lua_State* state) -> int { lua_rawset(state, -3); + lua_pushliteral(state, "IndexTypes"); + lua_newtable(state); + lua_pushliteral(state, "ALBUMS_BY_ARTIST"); + lua_pushinteger(state, (int)database::kAlbumsByArtist.id); + lua_rawset(state, -3); + lua_pushliteral(state, "TRACKS_BY_GENRE"); + lua_pushinteger(state, (int)database::kTracksByGenre.id); + lua_rawset(state, -3); + lua_pushliteral(state, "ALL_TRACKS"); + lua_pushinteger(state, (int)database::kAllTracks.id); + lua_rawset(state, -3); + lua_pushliteral(state, "ALL_ALBUMS"); + lua_pushinteger(state, (int)database::kAllAlbums.id); + lua_rawset(state, -3); + lua_pushliteral(state, "ALL_ARTISTS"); + lua_pushinteger(state, (int)database::kAllArtists.id); + lua_rawset(state, -3); + lua_pushliteral(state, "PODCASTS"); + lua_pushinteger(state, (int)database::kPodcasts.id); + lua_rawset(state, -3); + lua_pushliteral(state, "AUDIOBOOKS"); + lua_pushinteger(state, (int)database::kAudiobooks.id); + lua_rawset(state, -3); + lua_rawset(state, -3); + return 1; }