diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-07-17 16:54:35 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-07-17 16:54:35 +1000 |
| commit | 7197da21f6bcc1aaa5d1905228e0e2ec1caf3fa8 (patch) | |
| tree | f24f81cba08160d45d7e994dc31f48506e823e49 /src/audio/track_queue.cpp | |
| parent | b6bc6b9e47605ede9bffe50445d1afe3acf0ab49 (diff) | |
| download | tangara-fw-7197da21f6bcc1aaa5d1905228e0e2ec1caf3fa8.tar.gz | |
Basic playlists for upcoming
Beware under-testing and bugs. Just getting something barebones in so
that I can do rN+1 bringup
Diffstat (limited to 'src/audio/track_queue.cpp')
| -rw-r--r-- | src/audio/track_queue.cpp | 168 |
1 files changed, 113 insertions, 55 deletions
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 <algorithm> #include <mutex> +#include <variant> #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<database::TrackId> { const std::lock_guard<std::mutex> lock(mutex_); - return current_; + if (enqueued_.empty()) { + return {}; + } + auto item = enqueued_.front(); + if (std::holds_alternative<database::TrackId>(item)) { + return std::get<database::TrackId>(item); + } + if (std::holds_alternative<std::shared_ptr<playlist::ISource>>(item)) { + return std::get<std::shared_ptr<playlist::ISource>>(item)->Current(); + } + if (std::holds_alternative<std::shared_ptr<playlist::IResetableSource>>( + item)) { + return std::get<std::shared_ptr<playlist::IResetableSource>>(item) + ->Current(); + } + return {}; } auto TrackQueue::GetUpcoming(std::size_t limit) const -> std::vector<database::TrackId> { const std::lock_guard<std::mutex> lock(mutex_); std::vector<database::TrackId> 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<database::TrackId>(*it)) { + it++; + } + + while (limit > 0 && it != enqueued_.end()) { + auto item = *it; + if (std::holds_alternative<database::TrackId>(item)) { + ret.push_back(std::get<database::TrackId>(item)); + limit--; + } else if (std::holds_alternative<std::shared_ptr<playlist::ISource>>( + item)) { + limit -= + std::get<std::shared_ptr<playlist::ISource>>(item)->Peek(limit, &ret); + } else if (std::holds_alternative< + std::shared_ptr<playlist::IResetableSource>>(item)) { + limit -= + std::get<std::shared_ptr<playlist::IResetableSource>>(item)->Peek( + limit, &ret); + } + it++; + } + return ret; } auto TrackQueue::AddNext(database::TrackId t) -> void { const std::lock_guard<std::mutex> lock(mutex_); - if (!current_) { - current_ = t; - } else { - upcoming_.push_front(t); - } + enqueued_.push_front(t); + events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); +} +auto TrackQueue::AddNext(std::shared_ptr<playlist::ISource> src) -> void { + const std::lock_guard<std::mutex> lock(mutex_); + enqueued_.push_front(src); events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); } -auto TrackQueue::AddNext(const std::vector<database::TrackId>& t) -> void { +auto TrackQueue::IncludeNext(std::shared_ptr<playlist::IResetableSource> src) + -> void { const std::lock_guard<std::mutex> 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<QueueUpdate, AudioState, ui::UiState>({}); } auto TrackQueue::AddLast(database::TrackId t) -> void { const std::lock_guard<std::mutex> lock(mutex_); - if (!current_) { - current_ = t; - } else { - upcoming_.push_back(t); - } + enqueued_.push_back(t); + events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); +} +auto TrackQueue::AddLast(std::shared_ptr<playlist::ISource> src) -> void { + const std::lock_guard<std::mutex> lock(mutex_); + enqueued_.push_back(src); events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); } -auto TrackQueue::AddLast(const std::vector<database::TrackId>& t) -> void { +auto TrackQueue::IncludeLast(std::shared_ptr<playlist::IResetableSource> src) + -> void { const std::lock_guard<std::mutex> 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<QueueUpdate, AudioState, ui::UiState>({}); } auto TrackQueue::Next() -> void { const std::lock_guard<std::mutex> lock(mutex_); - if (current_) { - played_.push_front(*current_); + if (enqueued_.empty()) { + return; + } + + auto item = enqueued_.front(); + if (std::holds_alternative<database::TrackId>(item)) { + played_.push_front(std::get<database::TrackId>(item)); + enqueued_.pop_front(); + } + if (std::holds_alternative<std::shared_ptr<playlist::ISource>>(item)) { + auto src = std::get<std::shared_ptr<playlist::ISource>>(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<std::shared_ptr<playlist::IResetableSource>>( + item)) { + auto src = std::get<std::shared_ptr<playlist::IResetableSource>>(item); + if (!src->Advance()) { + played_.push_back(src); + enqueued_.pop_front(); + } } + events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); } auto TrackQueue::Previous() -> void { const std::lock_guard<std::mutex> lock(mutex_); - if (current_) { - upcoming_.push_front(*current_); + if (!enqueued_.empty() && + std::holds_alternative<std::shared_ptr<playlist::IResetableSource>>( + enqueued_.front())) { + auto src = std::get<std::shared_ptr<playlist::IResetableSource>>( + enqueued_.front()); + if (src->Previous()) { + events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); + 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<database::TrackId>(item)) { + enqueued_.push_front(std::get<database::TrackId>(item)); + } else if (std::holds_alternative< + std::shared_ptr<playlist::IResetableSource>>(item)) { + enqueued_.push_front( + std::get<std::shared_ptr<playlist::IResetableSource>>(item)); } + played_.pop_front(); + events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); } auto TrackQueue::Clear() -> void { const std::lock_guard<std::mutex> lock(mutex_); played_.clear(); - upcoming_.clear(); - current_.reset(); - events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); -} - -auto TrackQueue::RemoveUpcoming(database::TrackId t) -> void { - const std::lock_guard<std::mutex> lock(mutex_); - for (auto it = upcoming_.begin(); it != upcoming_.end(); it++) { - if (*it == t) { - upcoming_.erase(it); - return; - } - } + enqueued_.clear(); events::Dispatch<QueueUpdate, AudioState, ui::UiState>({}); } |
