Skip to content

Commit f308f71

Browse files
authored
Merge pull request #212 from FoxxMD/playerStateCleanup
feat(player): Real time positional player state
2 parents da76945 + c498bde commit f308f71

27 files changed

+645
-343
lines changed

src/backend/common/infrastructure/Atomic.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Dayjs } from "dayjs";
44
import { Request, Response } from "express";
55
import { NextFunction, ParamsDictionary, Query } from "express-serve-static-core";
66
import { FixedSizeList } from 'fixed-size-list';
7-
import { PlayMeta, PlayObject } from "../../../core/Atomic.js";
7+
import { isPlayObject, PlayMeta, PlayObject } from "../../../core/Atomic.js";
88
import TupleMap from "../TupleMap.js";
99

1010
export type SourceType =
@@ -122,13 +122,9 @@ export interface PlayerStateDataMaybePlay {
122122
timestamp?: Dayjs
123123
}
124124

125-
export const asPlayerStateData = (obj: object): obj is PlayerStateData => {
126-
return 'platformId' in obj && 'play' in obj;
127-
}
125+
export const asPlayerStateData = (obj: object): obj is PlayerStateData => asPlayerStateDataMaybePlay(obj) && 'play' in obj && isPlayObject(obj.play)
128126

129-
export const asPlayerStateDataMaybePlay = (obj: object): obj is PlayerStateDataMaybePlay => {
130-
return 'platformId' in obj;
131-
}
127+
export const asPlayerStateDataMaybePlay = (obj: object): obj is PlayerStateDataMaybePlay => 'platformId' in obj
132128

133129
export interface FormatPlayObjectOptions {
134130
newFromSource?: boolean

src/backend/sources/ChromecastSource.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { difference, genGroupIdStr, parseBool } from "../utils.js";
3434
import { findCauseByReference } from "../utils/ErrorUtils.js";
3535
import { discoveryAvahi, discoveryNative } from "../utils/MDNSUtils.js";
3636
import { RecentlyPlayedOptions } from "./AbstractSource.js";
37-
import MemorySource from "./MemorySource.js";
37+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
3838

3939
interface ChromecastDeviceInfo {
4040
mdns: MdnsDeviceInfo
@@ -46,7 +46,7 @@ interface ChromecastDeviceInfo {
4646
applications: Map<string, PlatformApplicationWithContext>
4747
}
4848

49-
export class ChromecastSource extends MemorySource {
49+
export class ChromecastSource extends MemoryPositionalSource {
5050

5151
declare config: ChromecastSourceConfig;
5252

src/backend/sources/JRiverSource.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructur
77
import { JRiverSourceConfig } from "../common/infrastructure/config/source/jriver.js";
88
import { Info, JRiverApiClient, PLAYER_STATE } from "../common/vendor/JRiverApiClient.js";
99
import { RecentlyPlayedOptions } from "./AbstractSource.js";
10-
import MemorySource from "./MemorySource.js";
10+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
1111

12-
export class JRiverSource extends MemorySource {
12+
export class JRiverSource extends MemoryPositionalSource {
1313
declare config: JRiverSourceConfig;
1414

1515
url: URL;

src/backend/sources/JellyfinApiSource.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,11 @@ import {
5252
import { JellyApiSourceConfig } from "../common/infrastructure/config/source/jellyfin.js";
5353
import { combinePartsToString, genGroupIdStr, getPlatformIdFromData, joinedUrl, parseBool, } from "../utils.js";
5454
import { parseArrayFromMaybeString } from "../utils/StringUtils.js";
55-
import MemorySource from "./MemorySource.js";
56-
import { PlayerStateOptions } from "./PlayerState/AbstractPlayerState.js";
57-
import { JellyfinPlayerState } from "./PlayerState/JellyfinPlayerState.js";
55+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
5856

5957
const shortDeviceId = truncateStringToLength(10, '');
6058

61-
export default class JellyfinApiSource extends MemorySource {
59+
export default class JellyfinApiSource extends MemoryPositionalSource {
6260
users: string[] = [];
6361

6462
client: Jellyfin
@@ -476,7 +474,6 @@ export default class JellyfinApiSource extends MemorySource {
476474
}
477475
}
478476

479-
getNewPlayer = (logger: Logger, id: PlayPlatformId, opts: PlayerStateOptions) => new JellyfinPlayerState(logger, id, opts)
480477
}
481478

482479
/**

src/backend/sources/KodiSource.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { FormatPlayObjectOptions, InternalConfig } from "../common/infrastructur
44
import { KodiSourceConfig } from "../common/infrastructure/config/source/kodi.js";
55
import { KodiApiClient } from "../common/vendor/KodiApiClient.js";
66
import { RecentlyPlayedOptions } from "./AbstractSource.js";
7-
import MemorySource from "./MemorySource.js";
7+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
88

9-
export class KodiSource extends MemorySource {
9+
export class KodiSource extends MemoryPositionalSource {
1010
declare config: KodiSourceConfig;
1111

1212
client: KodiApiClient;

src/backend/sources/MPDSource.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from "../common/infrastructure/config/source/mpd.js";
2020
import { isPortReachable } from "../utils/NetworkUtils.js";
2121
import { RecentlyPlayedOptions } from "./AbstractSource.js";
22-
import MemorySource from "./MemorySource.js";
22+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
2323

2424
const mpdClient = mpdapiNS.default;
2525

@@ -29,7 +29,7 @@ const CLIENT_PLAYER_STATE: Record<PlayerState, ReportedPlayerStatus> = {
2929
'stop': REPORTED_PLAYER_STATUSES.stopped,
3030
}
3131

32-
export class MPDSource extends MemorySource {
32+
export class MPDSource extends MemoryPositionalSource {
3333
declare config: MPDSourceConfig;
3434

3535
host?: string
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Logger } from "@foxxmd/logging";
2+
import { PlayPlatformId } from "../common/infrastructure/Atomic.js";
3+
import MemorySource from "./MemorySource.js";
4+
import { PlayerStateOptions } from "./PlayerState/AbstractPlayerState.js";
5+
import { PositionalPlayerState } from "./PlayerState/PositionalPlayerState.js";
6+
7+
export class MemoryPositionalSource extends MemorySource {
8+
getNewPlayer = (logger: Logger, id: PlayPlatformId, opts: PlayerStateOptions) => new PositionalPlayerState(logger, id, opts)
9+
}

src/backend/sources/MemorySource.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export default class MemorySource extends AbstractSource {
9090
return record;
9191
}
9292

93-
getNewPlayer = (logger: Logger, id: PlayPlatformId, opts: PlayerStateOptions) => new GenericPlayerState(logger, id, opts)
93+
getNewPlayer = (logger: Logger, id: PlayPlatformId, opts: PlayerStateOptions): AbstractPlayerState => new GenericPlayerState(logger, id, opts)
9494

9595
setNewPlayer = (idStr: string, logger: Logger, id: PlayPlatformId, opts: PlayerStateOptions = {}) => {
9696
this.players.set(idStr, this.getNewPlayer(this.logger, id, {
@@ -167,7 +167,17 @@ export default class MemorySource extends AbstractSource {
167167
}
168168
incomingData = relevantDatas[0];
169169

170-
const [currPlay, prevPlay] = asPlayerStateDataMaybePlay(incomingData) ? player.setState(incomingData.status, incomingData.play) : player.setState(undefined, incomingData);
170+
let playerState: PlayerStateDataMaybePlay;
171+
if(asPlayerStateDataMaybePlay(incomingData)) {
172+
playerState = incomingData;
173+
} else {
174+
playerState = {play: incomingData, platformId: getPlatformIdFromData(incomingData)};
175+
}
176+
if(playerState.position === undefined && playerState.play !== undefined && playerState.play.meta.trackProgressPosition !== undefined) {
177+
playerState.position = playerState.play.meta?.trackProgressPosition;
178+
}
179+
180+
const [currPlay, prevPlay] = player.update(playerState);
171181
const candidate = prevPlay !== undefined ? prevPlay : currPlay;
172182
const playChanged = prevPlay !== undefined;
173183

src/backend/sources/MopidySource.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ import {
1515
} from "../common/infrastructure/Atomic.js";
1616
import { MopidySourceConfig } from "../common/infrastructure/config/source/mopidy.js";
1717
import { RecentlyPlayedOptions } from "./AbstractSource.js";
18-
import MemorySource from "./MemorySource.js";
18+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
1919

20-
export class MopidySource extends MemorySource {
20+
export class MopidySource extends MemoryPositionalSource {
2121
declare config: MopidySourceConfig;
2222

2323
albumBlacklist: string[] = [];

src/backend/sources/MusikcubeSource.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
} from "../common/infrastructure/config/source/musikcube.js";
2323
import { sleep } from "../utils.js";
2424
import { RecentlyPlayedOptions } from "./AbstractSource.js";
25-
import MemorySource from "./MemorySource.js";
25+
import { MemoryPositionalSource } from "./MemoryPositionalSource.js";
2626

2727
const CLIENT_STATE = {
2828
0: 'connecting',
@@ -31,7 +31,7 @@ const CLIENT_STATE = {
3131
3: 'closed'
3232
}
3333

34-
export class MusikcubeSource extends MemorySource {
34+
export class MusikcubeSource extends MemoryPositionalSource {
3535
declare config: MusikcubeSourceConfig;
3636

3737
url: URL;

0 commit comments

Comments
 (0)