From 43537798108ce240f1d1131db8611d0bf11a3e0c Mon Sep 17 00:00:00 2001 From: ailurux Date: Thu, 12 Sep 2024 17:35:22 +1000 Subject: [PATCH] WIP: Add last_position field to track data and start on implementation --- src/tangara/audio/audio_fsm.cpp | 25 +++++++++++++++++++++++++ src/tangara/audio/audio_fsm.hpp | 2 ++ src/tangara/database/database.cpp | 19 +++++++++++++++++++ src/tangara/database/database.hpp | 5 ++++- src/tangara/database/records.cpp | 4 ++++ src/tangara/database/track.hpp | 8 +++++--- 6 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/tangara/audio/audio_fsm.cpp b/src/tangara/audio/audio_fsm.cpp index 5a91c6f9..d9b81832 100644 --- a/src/tangara/audio/audio_fsm.cpp +++ b/src/tangara/audio/audio_fsm.cpp @@ -80,6 +80,10 @@ auto AudioState::emitPlaybackUpdate(bool paused) -> void { current.first->start_offset.value_or(0); } + if (position) { + // Update position if the duration has been long enough + } + PlaybackUpdate event{ .current_track = current.first, .track_position = position, @@ -374,6 +378,27 @@ void AudioState::react(const OutputModeChanged& ev) { } } +auto AudioState::updateSavedPosition(std::string uri, uint32_t position) + -> void { + sServices->bg_worker().Dispatch([=]() { + auto db = sServices->database().lock(); + if (!db) { + return; + } + auto id = db->getTrackID(uri); + if (!id) { + return; + } + auto track = db->getTrack(*id); + if (!track) { + return; + } + database::TrackData data = track->data(); + data.last_position = position; + db->setTrackData(*id, data); + }); +} + auto AudioState::commitVolume() -> void { auto mode = sServices->nvs().OutputMode(); auto vol = sOutput->GetVolume(); diff --git a/src/tangara/audio/audio_fsm.hpp b/src/tangara/audio/audio_fsm.hpp index 0644375f..0c8f4d26 100644 --- a/src/tangara/audio/audio_fsm.hpp +++ b/src/tangara/audio/audio_fsm.hpp @@ -73,6 +73,8 @@ class AudioState : public tinyfsm::Fsm { auto emitPlaybackUpdate(bool paused) -> void; auto commitVolume() -> void; + auto updateSavedPosition(std::string uri, uint32_t position) -> void; + static std::shared_ptr sServices; static std::shared_ptr sStreamFactory; diff --git a/src/tangara/database/database.cpp b/src/tangara/database/database.cpp index 64451f48..9d0de695 100644 --- a/src/tangara/database/database.cpp +++ b/src/tangara/database/database.cpp @@ -44,6 +44,7 @@ #include "memory_resource.hpp" #include "result.hpp" #include "tasks.hpp" +#include "database.hpp" namespace database { @@ -269,6 +270,24 @@ auto Database::getTrack(TrackId id) -> std::shared_ptr { return std::make_shared(data, tags); } +auto Database::getTrackID(std::string path) -> std::optional { + std::string raw_data; + if (!db_->Get(leveldb::ReadOptions(), EncodePathKey(path), &raw_data).ok()) { + return {}; + } + return BytesToTrackId(raw_data); +} + +auto Database::setTrackData(TrackId id, const TrackData& data) -> void { + std::string key = EncodeDataKey(id); + std::string raw_val = EncodeDataValue(data); + + auto res = db_->Put(leveldb::WriteOptions(), key, raw_val); + if (!res.ok()) { + ESP_LOGI(kTag, "Updating track data failed for track ID: %lu", id); + } +} + auto Database::getIndexes() -> std::vector { // TODO(jacqueline): This probably needs to be async? When we have runtime // configurable indexes, they will need to come from somewhere. diff --git a/src/tangara/database/database.hpp b/src/tangara/database/database.hpp index 18070353..6dd13b0d 100644 --- a/src/tangara/database/database.hpp +++ b/src/tangara/database/database.hpp @@ -37,7 +37,7 @@ namespace database { -const uint8_t kCurrentDbVersion = 7; +const uint8_t kCurrentDbVersion = 8; struct SearchKey; class Record; @@ -78,6 +78,9 @@ class Database { auto getTrackPath(TrackId id) -> std::optional; auto getTrack(TrackId id) -> std::shared_ptr; + auto getTrackID(std::string path) -> std::optional; + + auto setTrackData(TrackId id, const TrackData& data) -> void; auto getIndexes() -> std::vector; auto updateIndexes() -> void; diff --git a/src/tangara/database/records.cpp b/src/tangara/database/records.cpp index 17009cd8..9e898c0b 100644 --- a/src/tangara/database/records.cpp +++ b/src/tangara/database/records.cpp @@ -93,6 +93,7 @@ auto EncodeDataValue(const TrackData& track) -> std::string { cppbor::Uint{track.modified_at.first}, cppbor::Uint{track.modified_at.second}, tag_hashes, + cppbor::Uint{track.last_position}, }; return val.toString(); } @@ -127,6 +128,9 @@ auto ParseDataValue(const leveldb::Slice& slice) -> std::shared_ptr { auto tag = static_cast(entry.first->asUint()->unsignedValue()); res->individual_tag_hashes[tag] = entry.second->asUint()->unsignedValue(); } + + res->last_position = vals->get(7)->asUint()->unsignedValue(); + return res; } diff --git a/src/tangara/database/track.hpp b/src/tangara/database/track.hpp index 6501e31f..2bcf4db1 100644 --- a/src/tangara/database/track.hpp +++ b/src/tangara/database/track.hpp @@ -159,7 +159,8 @@ struct TrackData { tags_hash(0), individual_tag_hashes(&memory::kSpiRamResource), is_tombstoned(false), - modified_at() {} + modified_at(), + last_position(0) {} TrackId id; std::pmr::string filepath; @@ -167,9 +168,10 @@ struct TrackData { std::pmr::unordered_map individual_tag_hashes; bool is_tombstoned; std::pair modified_at; + uint32_t last_position; - TrackData(TrackData&& other) = delete; - TrackData& operator=(TrackData& other) = delete; + TrackData(const TrackData& other) = default; + TrackData& operator=(TrackData& other) = default; bool operator==(const TrackData&) const = default; };