From 4f5422e906b1d17720592d97bc0d5e82a71b1e5f Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 5 Dec 2023 11:36:34 +1100 Subject: Rewrite the track queue to work directly with database iterators --- src/audio/include/track_queue.hpp | 82 ++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 35 deletions(-) (limited to 'src/audio/include') diff --git a/src/audio/include/track_queue.hpp b/src/audio/include/track_queue.hpp index 0be2384a..9d5ef5b2 100644 --- a/src/audio/include/track_queue.hpp +++ b/src/audio/include/track_queue.hpp @@ -11,6 +11,7 @@ #include #include +#include "database.hpp" #include "source.hpp" #include "track.hpp" @@ -27,67 +28,78 @@ namespace audio { * * Instances of this class are broadly safe to use from multiple tasks; each * method represents an atomic operation. No guarantees are made about - * consistency between calls however. For example, there may be data changes - * between consecutive calls to AddNext() and GetUpcoming(); + * consistency between calls however. */ class TrackQueue { public: TrackQueue(); + class Editor { + public: + ~Editor(); + + // Cannot be copied or moved. + Editor(const Editor&) = delete; + Editor& operator=(const Editor&) = delete; + + private: + friend TrackQueue; + + Editor(TrackQueue&); + + std::lock_guard lock_; + bool has_current_changed_; + }; + + auto Edit() -> Editor; + /* Returns the currently playing track. */ - auto GetCurrent() const -> std::optional; + auto Current() const -> std::optional; + /* Returns, in order, tracks that have been queued to be played next. */ - auto GetUpcoming(std::size_t limit) const -> std::vector; + auto PeekNext(std::size_t limit) const -> std::vector; /* - * Enqueues a track, placing it immediately after the current track and - * before anything already queued. - * - * If there is no current track, the given track will begin playback. + * Returns the tracks in the queue that have already been played, ordered + * most recently played first. */ - auto AddNext(database::TrackId) -> void; - auto AddNext(std::shared_ptr) -> void; + auto PeekPrevious(std::size_t limit) const -> std::vector; - auto IncludeNext(std::shared_ptr) -> void; + auto GetCurrentPosition() const -> size_t; + auto GetTotalSize() const -> size_t; - /* - * Enqueues a track, placing it the end of all enqueued tracks. - * - * If there is no current track, the given track will begin playback. - */ - auto AddLast(database::TrackId) -> void; - auto AddLast(std::shared_ptr) -> void; - - auto IncludeLast(std::shared_ptr) -> void; + using Item = std::variant; + auto Insert(Editor&, Item, size_t) -> void; + auto Append(Editor&, Item i) -> void; /* * Advances to the next track in the queue, placing the current track at the * front of the 'played' queue. */ - auto Next() -> void; - auto Previous() -> void; + auto Next(Editor&) -> std::optional; + auto Previous(Editor&) -> std::optional; + + auto SkipTo(Editor&, database::TrackId) -> void; /* * Removes all tracks from all queues, and stops any currently playing track. */ - auto Clear() -> void; - - auto Position() -> size_t; - auto Size() -> size_t; + auto Clear(Editor&) -> void; + // Cannot be copied or moved. TrackQueue(const TrackQueue&) = delete; TrackQueue& operator=(const TrackQueue&) = delete; private: - mutable std::mutex mutex_; - - std::list>> - played_; - std::list, - std::shared_ptr>> - enqueued_; + // FIXME: Make this a shared_mutex so that multithread reads don't block. + mutable std::recursive_mutex mutex_; + + std::optional current_; + + // Note: stored in reverse order, i.e. most recent played it at the *back* of + // this vector. + std::pmr::vector played_; + std::pmr::vector enqueued_; }; } // namespace audio -- cgit v1.2.3