diff --git a/luals-stubs/backstack.lua b/luals-stubs/backstack.lua index b39fcbf2..84a57e5c 100644 --- a/luals-stubs/backstack.lua +++ b/luals-stubs/backstack.lua @@ -17,4 +17,8 @@ function backstack.push(screen) end --- there are no other screens in the stack. function backstack.pop() end +--- Sets a new root screen, replacing any existing screens +--- @param screen screen The new root screen +function backstack.reset(screen) end + return backstack diff --git a/luals-stubs/bluetooth.lua b/luals-stubs/bluetooth.lua index a2dd476d..d362974a 100644 --- a/luals-stubs/bluetooth.lua +++ b/luals-stubs/bluetooth.lua @@ -5,8 +5,17 @@ --- @class bluetooth --- @field enabled Property Whether or not the Bluetooth stack is currently enabled. This property is writeable, and can be used to enable or disable Bluetooth. --- @field connected Property Whether or not there is an active connection to another Bluetooth device. ---- @field paired_device Property The device that is currently paired. The bluetooth stack will automatically connected to this device if possible. ---- @field devices Property Devices nearby that have been discovered. +--- @field connecting Property Whether or not we are currently connecting to the paired device. +--- @field discovering Property Whether or not we are actively scanning for new devices. +--- @field paired_device Property The device that is currently paired. The bluetooth stack will automatically connect to this device if possible. +--- @field discovered_devices Property Devices nearby that have been discovered. +--- @field known_devices Property Devices that have previously been paired. local bluetooth = {} +--- Enables Bluetooth, this is the same as bluetooth.enabled:set(true) +function bluetooth.enable() end + +--- Disables Bluetooth, this is the same as bluetooth.enabled:set(false) +function bluetooth.disable() end + return bluetooth diff --git a/luals-stubs/playback.lua b/luals-stubs/playback.lua index 85392e93..f905f384 100644 --- a/luals-stubs/playback.lua +++ b/luals-stubs/playback.lua @@ -8,4 +8,9 @@ --- @field position Property The current playback position within the current track, in seconds. local playback = {} +--- Returns whether or not this file can be played (i.e. is this an audio track) +--- @param filepath string +--- @return boolean +function playback.is_playable(filepath) end + return playback diff --git a/luals-stubs/queue.lua b/luals-stubs/queue.lua index 895b4c78..97583587 100644 --- a/luals-stubs/queue.lua +++ b/luals-stubs/queue.lua @@ -13,10 +13,10 @@ --- @field random Property Determines whether, when progressing to the next track in the queue, the next track will be chosen randomly. The random selection algorithm used is a Miller Shuffle, which guarantees that no repeat selections will be made until every item in the queue has been played. Writeable. local queue = {} ---- Adds the given track or database iterator to the end of the queue. Database +--- Adds the given track, database iterator, or file to the end of the queue. Database --- iterators passed to this method will be unnested and expanded into the track --- ids they contain. ---- @param val TrackId|Iterator +--- @param val TrackId|Iterator|string function queue.add(val) end --- Opens a playlist file from a filepath diff --git a/src/tangara/audio/track_queue.cpp b/src/tangara/audio/track_queue.cpp index cc4770ae..2c1faf96 100644 --- a/src/tangara/audio/track_queue.cpp +++ b/src/tangara/audio/track_queue.cpp @@ -236,6 +236,21 @@ auto TrackQueue::next() -> void { next(Reason::kExplicitUpdate); } +auto TrackQueue::currentPosition(size_t position) -> bool { + { + const std::shared_lock lock(mutex_); + if (position >= totalSize()) { + return false; + } + goTo(position); + } + + // If we're explicitly setting the position, we want to treat it as though + // the current track has changed, even if the position was the same + notifyChanged(true, Reason::kExplicitUpdate); + return true; +} + auto TrackQueue::goTo(size_t position) -> void { position_ = position; if (opened_playlist_) { diff --git a/src/tangara/audio/track_queue.hpp b/src/tangara/audio/track_queue.hpp index 1d25568d..a8d1dc3a 100644 --- a/src/tangara/audio/track_queue.hpp +++ b/src/tangara/audio/track_queue.hpp @@ -73,6 +73,7 @@ class TrackQueue { auto current() const -> TrackItem; auto currentPosition() const -> size_t; + auto currentPosition(size_t position) -> bool; auto totalSize() const -> size_t; auto open() -> bool; auto openPlaylist(const std::string& playlist_file, bool notify = true) diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp index 94d1caf8..669b3298 100644 --- a/src/tangara/ui/ui_fsm.cpp +++ b/src/tangara/ui/ui_fsm.cpp @@ -201,7 +201,14 @@ lua::Property UiState::sPlaybackPosition{ return true; }}; -lua::Property UiState::sQueuePosition{0}; +lua::Property UiState::sQueuePosition{0, [](const lua::LuaValue& val){ + if (!std::holds_alternative(val)) { + return false; + } + int new_val = std::get(val); + // val-1 because Lua uses 1-based indexing + return sServices->track_queue().currentPosition(new_val-1); + }}; lua::Property UiState::sQueueSize{0}; lua::Property UiState::sQueueRepeat{false, [](const lua::LuaValue& val) { if (!std::holds_alternative(val)) { @@ -610,6 +617,16 @@ void Lua::entry() { {"paired_device", &sBluetoothPairedDevice}, {"discovered_devices", &sBluetoothDiscoveredDevices}, {"known_devices", &sBluetoothKnownDevices}, + {"enable", + [&](lua_State* s) { + sBluetoothEnabled.set(true); + return 0; + }}, + {"disable", + [&](lua_State* s) { + sBluetoothEnabled.set(false); + return 0; + }}, }); registry.AddPropertyModule( "playback",