From 7197da21f6bcc1aaa5d1905228e0e2ec1caf3fa8 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Mon, 17 Jul 2023 16:54:35 +1000 Subject: Basic playlists for upcoming Beware under-testing and bugs. Just getting something barebones in so that I can do rN+1 bringup --- src/audio/track_queue.cpp | 168 +++++++++++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 55 deletions(-) (limited to 'src/audio/track_queue.cpp') diff --git a/src/audio/track_queue.cpp b/src/audio/track_queue.cpp index 1c233f8f..0709056f 100644 --- a/src/audio/track_queue.cpp +++ b/src/audio/track_queue.cpp @@ -8,10 +8,12 @@ #include #include +#include #include "audio_events.hpp" #include "audio_fsm.hpp" #include "event_queue.hpp" +#include "source.hpp" #include "track.hpp" #include "ui_fsm.hpp" @@ -21,107 +23,163 @@ TrackQueue::TrackQueue() {} auto TrackQueue::GetCurrent() const -> std::optional { const std::lock_guard lock(mutex_); - return current_; + if (enqueued_.empty()) { + return {}; + } + auto item = enqueued_.front(); + if (std::holds_alternative(item)) { + return std::get(item); + } + if (std::holds_alternative>(item)) { + return std::get>(item)->Current(); + } + if (std::holds_alternative>( + item)) { + return std::get>(item) + ->Current(); + } + return {}; } auto TrackQueue::GetUpcoming(std::size_t limit) const -> std::vector { const std::lock_guard lock(mutex_); std::vector ret; - limit = std::min(limit, upcoming_.size()); - std::for_each_n(upcoming_.begin(), limit, - [&](const auto i) { ret.push_back(i); }); + + auto it = enqueued_.begin(); + if (it == enqueued_.end()) { + return ret; + } + + // Don't include the current track. This is only relevant to raw track ids, + // since sources include multiple tracks. + if (std::holds_alternative(*it)) { + it++; + } + + while (limit > 0 && it != enqueued_.end()) { + auto item = *it; + if (std::holds_alternative(item)) { + ret.push_back(std::get(item)); + limit--; + } else if (std::holds_alternative>( + item)) { + limit -= + std::get>(item)->Peek(limit, &ret); + } else if (std::holds_alternative< + std::shared_ptr>(item)) { + limit -= + std::get>(item)->Peek( + limit, &ret); + } + it++; + } + return ret; } auto TrackQueue::AddNext(database::TrackId t) -> void { const std::lock_guard lock(mutex_); - if (!current_) { - current_ = t; - } else { - upcoming_.push_front(t); - } + enqueued_.push_front(t); + events::Dispatch({}); +} +auto TrackQueue::AddNext(std::shared_ptr src) -> void { + const std::lock_guard lock(mutex_); + enqueued_.push_front(src); events::Dispatch({}); } -auto TrackQueue::AddNext(const std::vector& t) -> void { +auto TrackQueue::IncludeNext(std::shared_ptr src) + -> void { const std::lock_guard lock(mutex_); - std::for_each(t.rbegin(), t.rend(), - [&](const auto i) { upcoming_.push_front(i); }); - if (!current_) { - current_ = upcoming_.front(); - upcoming_.pop_front(); - } + enqueued_.push_front(src); events::Dispatch({}); } auto TrackQueue::AddLast(database::TrackId t) -> void { const std::lock_guard lock(mutex_); - if (!current_) { - current_ = t; - } else { - upcoming_.push_back(t); - } + enqueued_.push_back(t); + events::Dispatch({}); +} +auto TrackQueue::AddLast(std::shared_ptr src) -> void { + const std::lock_guard lock(mutex_); + enqueued_.push_back(src); events::Dispatch({}); } -auto TrackQueue::AddLast(const std::vector& t) -> void { +auto TrackQueue::IncludeLast(std::shared_ptr src) + -> void { const std::lock_guard lock(mutex_); - std::for_each(t.begin(), t.end(), - [&](const auto i) { upcoming_.push_back(i); }); - if (!current_) { - current_ = upcoming_.front(); - upcoming_.pop_front(); - } + enqueued_.push_back(src); events::Dispatch({}); } auto TrackQueue::Next() -> void { const std::lock_guard lock(mutex_); - if (current_) { - played_.push_front(*current_); + if (enqueued_.empty()) { + return; + } + + auto item = enqueued_.front(); + if (std::holds_alternative(item)) { + played_.push_front(std::get(item)); + enqueued_.pop_front(); + } + if (std::holds_alternative>(item)) { + auto src = std::get>(item); + played_.push_front(*src->Current()); + if (!src->Advance()) { + enqueued_.pop_front(); + } } - if (!upcoming_.empty()) { - current_ = upcoming_.front(); - upcoming_.pop_front(); - } else { - current_.reset(); + if (std::holds_alternative>( + item)) { + auto src = std::get>(item); + if (!src->Advance()) { + played_.push_back(src); + enqueued_.pop_front(); + } } + events::Dispatch({}); } auto TrackQueue::Previous() -> void { const std::lock_guard lock(mutex_); - if (current_) { - upcoming_.push_front(*current_); + if (!enqueued_.empty() && + std::holds_alternative>( + enqueued_.front())) { + auto src = std::get>( + enqueued_.front()); + if (src->Previous()) { + events::Dispatch({}); + return; + } + } + + if (played_.empty()) { + return; } - if (!played_.empty()) { - current_ = played_.front(); - played_.pop_front(); - } else { - current_.reset(); + + auto item = played_.front(); + if (std::holds_alternative(item)) { + enqueued_.push_front(std::get(item)); + } else if (std::holds_alternative< + std::shared_ptr>(item)) { + enqueued_.push_front( + std::get>(item)); } + played_.pop_front(); + events::Dispatch({}); } auto TrackQueue::Clear() -> void { const std::lock_guard lock(mutex_); played_.clear(); - upcoming_.clear(); - current_.reset(); - events::Dispatch({}); -} - -auto TrackQueue::RemoveUpcoming(database::TrackId t) -> void { - const std::lock_guard lock(mutex_); - for (auto it = upcoming_.begin(); it != upcoming_.end(); it++) { - if (*it == t) { - upcoming_.erase(it); - return; - } - } + enqueued_.clear(); events::Dispatch({}); } -- cgit v1.2.3