Improved time upkeep for playing and pausing.
This commit is contained in:
parent
5100d18ac6
commit
0bfbc36952
@ -2,7 +2,8 @@ class Session {
|
|||||||
#id = null;
|
#id = null;
|
||||||
#started = null;
|
#started = null;
|
||||||
#current = null;
|
#current = null;
|
||||||
#lastScrobble = null;
|
lastScrobbleTimestamp = 0;
|
||||||
|
lastUpdateTimestamp = 0;
|
||||||
pauseDuration = 0;
|
pauseDuration = 0;
|
||||||
playDuration = 0;
|
playDuration = 0;
|
||||||
|
|
||||||
@ -26,14 +27,6 @@ class Session {
|
|||||||
get started() {
|
get started() {
|
||||||
return this.#started;
|
return this.#started;
|
||||||
}
|
}
|
||||||
|
|
||||||
get lastScrobbleTimestamp() {
|
|
||||||
return this.#lastScrobble;
|
|
||||||
}
|
|
||||||
|
|
||||||
set lastScrobbleTimestamp(value) {
|
|
||||||
this.#lastScrobble = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Session;
|
module.exports = Session;
|
@ -8,7 +8,6 @@ class Recorder {
|
|||||||
#scrobblers = [];
|
#scrobblers = [];
|
||||||
#config = null;
|
#config = null;
|
||||||
#logger = null;
|
#logger = null;
|
||||||
#lastTick = null;
|
|
||||||
|
|
||||||
constructor(sessions, trackers, scrobblers, config, logger) {
|
constructor(sessions, trackers, scrobblers, config, logger) {
|
||||||
this.#sessions = sessions;
|
this.#sessions = sessions;
|
||||||
@ -17,12 +16,10 @@ class Recorder {
|
|||||||
this.#scrobblers = scrobblers;
|
this.#scrobblers = scrobblers;
|
||||||
this.#config = config;
|
this.#config = config;
|
||||||
this.#logger = logger;
|
this.#logger = logger;
|
||||||
this.#lastTick = Date.now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async record() {
|
async record() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const timeDiff = now - this.#lastTick;
|
|
||||||
const media = await this.#trackers.poll();
|
const media = await this.#trackers.poll();
|
||||||
const contexts = media.map(m => this.#fetchContext(m));
|
const contexts = media.map(m => this.#fetchContext(m));
|
||||||
|
|
||||||
@ -31,25 +28,30 @@ class Recorder {
|
|||||||
const stopped = sessionIds.filter(sessionId => !contexts.some(context => sessionId == context.session.id))
|
const stopped = sessionIds.filter(sessionId => !contexts.some(context => sessionId == context.session.id))
|
||||||
.map(sessionId => this.#sessions.get(sessionId))
|
.map(sessionId => this.#sessions.get(sessionId))
|
||||||
.map(session => this.#fetchContext(session.playing));
|
.map(session => this.#fetchContext(session.playing));
|
||||||
const contextEnded = stopped.filter(context => this.#canScrobble(context.session, null, context.session.playing, now));
|
const contextEnded = stopped.filter(context => this.#canScrobble(context.session, null, context.session.playing));
|
||||||
|
|
||||||
for (let context of contextEnded)
|
for (let context of contextEnded)
|
||||||
context.session.playDuration = now - (context.session.lastScrobbleTimestamp || context.session.started) - context.session.pauseDuration;
|
context.session.playDuration = now - (context.session.lastScrobbleTimestamp || context.session.started) - context.session.pauseDuration;
|
||||||
|
|
||||||
// Find ongoing sessions that have moved on to the next song.
|
// Find ongoing sessions that have moved on to the next song.
|
||||||
const finishedPlaying = contexts.filter(context => this.#listen(context, now, timeDiff));
|
const finishedPlaying = contexts.filter(context => this.#listen(context, now));
|
||||||
|
|
||||||
// Scrobble
|
// Scrobble
|
||||||
const scrobbling = finishedPlaying.concat(contextEnded);
|
const scrobbling = finishedPlaying.concat(contextEnded);
|
||||||
for (let context of scrobbling)
|
for (let context of scrobbling) {
|
||||||
await this.#scrobble(context);
|
await this.#scrobble(context);
|
||||||
|
|
||||||
|
if (context.session.playing == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
context.session.playDuration = context.extraDuration;
|
||||||
|
context.session.pauseDuration = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove dead sessions.
|
// Remove dead sessions.
|
||||||
for (let context of stopped) {
|
for (let context of stopped) {
|
||||||
this.#sessions.remove(context.session.id);
|
this.#sessions.remove(context.session.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#lastTick = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#fetchContext(media) {
|
#fetchContext(media) {
|
||||||
@ -60,39 +62,41 @@ class Recorder {
|
|||||||
this.#sessions.add(session);
|
this.#sessions.add(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { session, media, tracker }
|
return { session, media, tracker, extraDuration: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#listen(context, timestamp, timeDiff) {
|
#listen(context, timestamp) {
|
||||||
const session = context.session;
|
const session = context.session;
|
||||||
const current = context.media;
|
const current = context.media;
|
||||||
const previous = context.session.playing;
|
const previous = context.session.playing;
|
||||||
session.playing = current;
|
session.playing = current;
|
||||||
session.playDuration = timestamp - (session.lastScrobbleTimestamp || session.started) - session.pauseDuration;
|
|
||||||
|
|
||||||
if (!previous) {
|
if (!previous) {
|
||||||
this.#logger.info(current, "A new session has started.");
|
this.#logger.info(current, "A new session has started.");
|
||||||
|
session.lastUpdateTimestamp = timestamp;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session.playing.state == "paused" || previous.state == "paused")
|
const updated = current.progress != previous.progress || current.id != previous.id || current.state != previous.state;
|
||||||
session.pauseDuration += timeDiff - (session.playing.progress - previous.progress);
|
if (!updated)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (this.#canScrobble(session, current, previous, timestamp)) {
|
const timeDiff = timestamp - session.lastUpdateTimestamp;
|
||||||
session.pauseDuration = 0;
|
const progressDiff = Math.max(0, Math.min(current.progress - previous.progress, timeDiff));
|
||||||
session.lastScrobbleTimestamp = timestamp - (timeDiff - (previous.duration - previous.progress));
|
session.playDuration += progressDiff;
|
||||||
return true;
|
session.pauseDuration += timeDiff - progressDiff;
|
||||||
} else if (current.progress < previous.progress && session.playing.id != previous.id) {
|
|
||||||
session.pauseDuration = 0;
|
const canScrobble = this.#canScrobble(session, current, previous);
|
||||||
if (current.progress < timeDiff)
|
if (canScrobble || current.id != previous.id) {
|
||||||
session.lastScrobbleTimestamp = timestamp - session.playing.progress;
|
context.extraDuration = Math.min(current.progress, timeDiff - (previous.duration - previous.progress));
|
||||||
else
|
session.lastScrobbleTimestamp = timestamp;
|
||||||
session.lastScrobbleTimestamp = timestamp;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
session.lastUpdateTimestamp = timestamp;
|
||||||
|
return canScrobble;
|
||||||
}
|
}
|
||||||
|
|
||||||
#canScrobble(session, current, previous, timestamp) {
|
#canScrobble(session, current, previous) {
|
||||||
if (previous == null)
|
if (previous == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user