From 2d01814edee6ac243118d09d9281cbfcf4c962d2 Mon Sep 17 00:00:00 2001 From: emeric Date: Wed, 27 Mar 2024 23:42:26 +0100 Subject: [PATCH] Fixed last track not sent to ListenBrainz, fixes #438 --- docroot/js/mediaplayer.js | 18 ++++--- src/lms/ui/LmsApplication.cpp | 95 ++++++++++++++++++----------------- src/lms/ui/MediaPlayer.cpp | 2 +- 3 files changed, 61 insertions(+), 54 deletions(-) diff --git a/docroot/js/mediaplayer.js b/docroot/js/mediaplayer.js index f6f61110..f966e446 100644 --- a/docroot/js/mediaplayer.js +++ b/docroot/js/mediaplayer.js @@ -97,17 +97,21 @@ LMS.mediaplayer = function () { _lastStartPlaying = Date.now(); } - let _stopTimer = function() { + let _pauseTimer = function() { if (_lastStartPlaying != null) { _playedDuration += Date.now() - _lastStartPlaying; + _lastStartPlaying = null; } } let _resetTimer = function() { if (_lastStartPlaying != null) + _pauseTimer(); + + if (_playedDuration > 0) { Wt.emit(_root, "scrobbleListenFinished", _trackId, _playedDuration); - _playedDuration = 0; - _lastStartPlaying = null; + _playedDuration = 0; + } } let _durationToString = function (duration) { @@ -229,7 +233,7 @@ LMS.mediaplayer = function () { navigator.mediaSession.setPositionState({ duration: _duration, playbackRate: 1, - position: _offset + _elems.audio.currentTime, + position: Math.min(_offset + _elems.audio.currentTime, _duration), }); if (_elems.audio.paused) @@ -276,9 +280,9 @@ LMS.mediaplayer = function () { _elems.audio.addEventListener("playing", _updateMediaSessionState); _elems.audio.addEventListener("pause", _updateMediaSessionState); - _elems.audio.addEventListener("pause", _stopTimer); + _elems.audio.addEventListener("pause", _pauseTimer); _elems.audio.addEventListener("playing", _startTimer); - _elems.audio.addEventListener("waiting", _stopTimer); + _elems.audio.addEventListener("waiting", _pauseTimer); _elems.audio.addEventListener("timeupdate", function() { _elems.progress.style.width = "" + ((_offset + _elems.audio.currentTime) / _duration) * 100 + "%"; @@ -286,6 +290,7 @@ LMS.mediaplayer = function () { }); _elems.audio.addEventListener("ended", function() { + _resetTimer(); Wt.emit(_root, "playbackEnded"); }); @@ -366,7 +371,6 @@ LMS.mediaplayer = function () { } let loadTrack = function(params, autoplay) { - _stopTimer(); _resetTimer(); _trackId = params.trackId; diff --git a/src/lms/ui/LmsApplication.cpp b/src/lms/ui/LmsApplication.cpp index f6268ac7..0d06d730 100644 --- a/src/lms/ui/LmsApplication.cpp +++ b/src/lms/ui/LmsApplication.cpp @@ -489,10 +489,12 @@ namespace lms::ui // Events from MediaPlayer _mediaPlayer->playNext.connect([this] { + LMS_LOG(UI, DEBUG, "Received playNext from player"); _playQueue->playNext(); }); _mediaPlayer->playPrevious.connect([this] { + LMS_LOG(UI, DEBUG, "Received playPrevious from player"); _playQueue->playPrevious(); }); @@ -501,58 +503,59 @@ namespace lms::ui LMS_LOG(UI, DEBUG, "Received ScrobbleListenNow from player for trackId = " << trackId.toString()); const scrobbling::Listen listen{ getUserId(), trackId }; core::Service::get()->listenStarted(listen); - }); - _mediaPlayer->scrobbleListenFinished.connect([this](db::TrackId trackId, unsigned durationMs) - { - LMS_LOG(UI, DEBUG, "Received ScrobbleListenFinished from player for trackId = " << trackId.toString() << ", duration = " << (durationMs / 1000) << "s"); - const std::chrono::milliseconds duration{ durationMs }; - const scrobbling::Listen listen{ getUserId(), trackId }; - core::Service::get()->listenFinished(listen, std::chrono::duration_cast(duration)); - }); + }); + _mediaPlayer->scrobbleListenFinished.connect([this](db::TrackId trackId, unsigned durationMs) + { + LMS_LOG(UI, DEBUG, "Received ScrobbleListenFinished from player for trackId = " << trackId.toString() << ", duration = " << (durationMs / 1000) << "s"); + const std::chrono::milliseconds duration{ durationMs }; + const scrobbling::Listen listen{ getUserId(), trackId }; + core::Service::get()->listenFinished(listen, std::chrono::duration_cast(duration)); + }); - _mediaPlayer->playbackEnded.connect([this] - { - _playQueue->onPlaybackEnded(); - }); + _mediaPlayer->playbackEnded.connect([this] + { + LMS_LOG(UI, DEBUG, "Received playbackEnded from player"); + _playQueue->onPlaybackEnded(); + }); - _playQueue->trackSelected.connect([this](db::TrackId trackId, bool play, float replayGain) - { - _mediaPlayer->loadTrack(trackId, play, replayGain); - }); + _playQueue->trackSelected.connect([this](db::TrackId trackId, bool play, float replayGain) + { + _mediaPlayer->loadTrack(trackId, play, replayGain); + }); - _playQueue->trackUnselected.connect([this] - { - _mediaPlayer->stop(); - }); - _playQueue->trackCountChanged.connect([this](std::size_t trackCount) - { - _mediaPlayer->onPlayQueueUpdated(trackCount); - }); - _mediaPlayer->onPlayQueueUpdated(_playQueue->getCount()); + _playQueue->trackUnselected.connect([this] + { + _mediaPlayer->stop(); + }); + _playQueue->trackCountChanged.connect([this](std::size_t trackCount) + { + _mediaPlayer->onPlayQueueUpdated(trackCount); + }); + _mediaPlayer->onPlayQueueUpdated(_playQueue->getCount()); - const bool isAdmin{ getUserType() == db::UserType::ADMIN }; - if (isAdmin) - { - _scannerEvents.scanComplete.connect([this](const scanner::ScanStats& stats) - { - notifyMsg(Notification::Type::Info, - Wt::WString::tr("Lms.Admin.Database.database"), - Wt::WString::tr("Lms.Admin.Database.scan-complete") - .arg(static_cast(stats.nbFiles())) - .arg(static_cast(stats.additions)) - .arg(static_cast(stats.updates)) - .arg(static_cast(stats.deletions)) - .arg(static_cast(stats.duplicates.size())) - .arg(static_cast(stats.errors.size()))); - }); - } + const bool isAdmin{ getUserType() == db::UserType::ADMIN }; + if (isAdmin) + { + _scannerEvents.scanComplete.connect([this](const scanner::ScanStats& stats) + { + notifyMsg(Notification::Type::Info, + Wt::WString::tr("Lms.Admin.Database.database"), + Wt::WString::tr("Lms.Admin.Database.scan-complete") + .arg(static_cast(stats.nbFiles())) + .arg(static_cast(stats.additions)) + .arg(static_cast(stats.updates)) + .arg(static_cast(stats.deletions)) + .arg(static_cast(stats.duplicates.size())) + .arg(static_cast(stats.errors.size()))); + }); + } - internalPathChanged().connect(mainStack, [=] - { - handlePathChange(*mainStack, isAdmin); - }); + internalPathChanged().connect(mainStack, [=] + { + handlePathChange(*mainStack, isAdmin); + }); - handlePathChange(*mainStack, isAdmin); + handlePathChange(*mainStack, isAdmin); } void LmsApplication::notify(const Wt::WEvent& event) diff --git a/src/lms/ui/MediaPlayer.cpp b/src/lms/ui/MediaPlayer.cpp index 9d744997..9d295d68 100644 --- a/src/lms/ui/MediaPlayer.cpp +++ b/src/lms/ui/MediaPlayer.cpp @@ -253,7 +253,7 @@ namespace lms::ui << " trackId :\"" << trackId.toString() << "\"," << " nativeResource: \"" << nativeResource << "\"," << " transcodingResource: \"" << transcodingResource << "\"," - << " duration: " << std::chrono::duration_cast(track->getDuration()).count() << "," + << " duration: " << std::chrono::duration_cast>(track->getDuration()).count() << "," << " replayGain: " << replayGain << "," << " title: \"" << core::stringUtils::jsEscape(track->getName()) << "\"," << " artist: \"" << (!artists.empty() ? core::stringUtils::jsEscape(track->getArtistDisplayName()) : "") << "\","