diff --git a/src/tangara/audio/audio_fsm.cpp b/src/tangara/audio/audio_fsm.cpp index f9823fb3..c6ac75f0 100644 --- a/src/tangara/audio/audio_fsm.cpp +++ b/src/tangara/audio/audio_fsm.cpp @@ -91,7 +91,8 @@ auto AudioState::emitPlaybackUpdate(bool paused) -> void { } // If we've got an elapsed duration and it's more than 5 minutes - // increment a counter. Every 60 counts (ie, every minute) save the current elapsed position + // increment a counter. Every 60 counts (ie, every minute) save the current + // elapsed position if (position && *position > (5 * 60)) { sUpdateCounter++; if (sUpdateCounter >= 60) { @@ -232,6 +233,7 @@ void AudioState::react(const internal::DecodingFinished& ev) { } if (path == ev.track->uri) { queue.finish(); + incrementPlayCount(ev.track->uri); } }); } @@ -399,7 +401,8 @@ void AudioState::react(const OutputModeChanged& ev) { } } -auto AudioState::updateSavedPosition(std::string uri, uint32_t position) +auto AudioState::updateTrackData(std::string uri, + std::function fn) -> void { sServices->bg_worker().Dispatch([=]() { auto db = sServices->database().lock(); @@ -415,11 +418,21 @@ auto AudioState::updateSavedPosition(std::string uri, uint32_t position) return; } auto data = track->data().clone(); - data->last_position = position; + std::invoke(fn, *data); db->setTrackData(*id, *data); }); } +auto AudioState::updateSavedPosition(std::string uri, uint32_t position) + -> void { + updateTrackData( + uri, [&](database::TrackData& data) { data.last_position = position; }); +} + +auto AudioState::incrementPlayCount(std::string uri) -> void { + updateTrackData(uri, [&](database::TrackData& data) { data.play_count++; }); +} + auto AudioState::updateOutputMode() -> void { if (is_in_state() || sIsTtsPlaying) { sOutput->mode(IAudioOutput::Modes::kOnPlaying); diff --git a/src/tangara/audio/audio_fsm.hpp b/src/tangara/audio/audio_fsm.hpp index c765b417..fb42e387 100644 --- a/src/tangara/audio/audio_fsm.hpp +++ b/src/tangara/audio/audio_fsm.hpp @@ -76,6 +76,7 @@ class AudioState : public tinyfsm::Fsm { auto commitVolume() -> void; auto updateSavedPosition(std::string uri, uint32_t position) -> void; + auto incrementPlayCount(std::string uri) -> void; static std::shared_ptr sServices; @@ -94,6 +95,10 @@ class AudioState : public tinyfsm::Fsm { static bool sIsPaused; static uint8_t sUpdateCounter; static bool sIsTtsPlaying; + + private: + auto updateTrackData(std::string uri, + std::function) -> void; }; namespace states { diff --git a/src/tangara/database/records.cpp b/src/tangara/database/records.cpp index b93ed149..addcc13d 100644 --- a/src/tangara/database/records.cpp +++ b/src/tangara/database/records.cpp @@ -95,6 +95,7 @@ auto EncodeDataValue(const TrackData& track) -> std::string { tag_hashes, cppbor::Uint{track.last_position}, cppbor::Uint{static_cast(track.type)}, + cppbor::Uint{track.play_count}, }; return val.toString(); } @@ -147,6 +148,10 @@ auto ParseDataValue(const leveldb::Slice& slice) -> std::shared_ptr { } } + if (vals->size() >= 10 && vals->get(9)->type() == cppbor::UINT) { + res->play_count = vals->get(9)->asUint()->unsignedValue(); + } + return res; } diff --git a/src/tangara/database/track.cpp b/src/tangara/database/track.cpp index 51d50a38..49babb6a 100644 --- a/src/tangara/database/track.cpp +++ b/src/tangara/database/track.cpp @@ -302,6 +302,7 @@ auto database::TrackData::clone() const -> std::shared_ptr { data->is_tombstoned = is_tombstoned; data->modified_at = modified_at; data->last_position = last_position; + data->play_count = play_count; data->type = type; return data; } diff --git a/src/tangara/database/track.hpp b/src/tangara/database/track.hpp index 71f40910..65c5cfec 100644 --- a/src/tangara/database/track.hpp +++ b/src/tangara/database/track.hpp @@ -177,7 +177,9 @@ struct TrackData { individual_tag_hashes(&memory::kSpiRamResource), is_tombstoned(false), modified_at(), - last_position(0) {} + last_position(0), + play_count(0), + type(MediaType::kUnknown) {} TrackId id; std::pmr::string filepath; @@ -186,6 +188,7 @@ struct TrackData { bool is_tombstoned; std::pair modified_at; uint32_t last_position; + uint32_t play_count; MediaType type; TrackData(const TrackData&& other) = delete; diff --git a/src/tangara/lua/lua_database.cpp b/src/tangara/lua/lua_database.cpp index 2e00f427..39179bf3 100644 --- a/src/tangara/lua/lua_database.cpp +++ b/src/tangara/lua/lua_database.cpp @@ -121,6 +121,10 @@ static void pushTrack(lua_State* L, const database::Track& track) { lua_pushliteral(L, "saved_position"); lua_pushinteger(L, track.data().last_position); lua_settable(L, -3); + + lua_pushliteral(L, "play_count"); + lua_pushinteger(L, track.data().play_count); + lua_settable(L, -3); } static auto version(lua_State* L) -> int {