From dea6d68228aa736d7263458fa76c275b704ebcc1 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Fri, 16 Jan 2026 15:14:36 +0000 Subject: [PATCH] feat(sonos): Better cleanup for for devices --- src/backend/sources/MemorySource.ts | 7 ++++++- src/backend/sources/SonosSource.ts | 22 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/backend/sources/MemorySource.ts b/src/backend/sources/MemorySource.ts index f7b1d1ef..9db83603 100644 --- a/src/backend/sources/MemorySource.ts +++ b/src/backend/sources/MemorySource.ts @@ -29,6 +29,7 @@ import AbstractSource from "./AbstractSource.js"; import { AbstractPlayerState, createPlayerOptions, PlayerStateOptions } from "./PlayerState/AbstractPlayerState.js"; import { GenericPlayerState } from "./PlayerState/GenericPlayerState.js"; import { hashObject } from "../utils/StringUtils.js"; +import { useDebugValue } from "react"; const EXPECTED_NON_DISCOVERED_REASON = 'not added because an identical play with the same timestamp was already discovered.'; @@ -177,6 +178,10 @@ export default class MemorySource extends AbstractSource { return this.players.has(id); } + genPlayerId = (data: PlayObject | PlayerStateDataMaybePlay): string => { + return genGroupIdStr(getPlatformIdFromData(data)); + } + deletePlayer = (id: string, reason?: string) => { if(!this.players.has(id)) { return; @@ -209,7 +214,7 @@ export default class MemorySource extends AbstractSource { // create any new players from incoming data for (const data of datas) { const id = getPlatformIdFromData(data); - const idStr = genGroupIdStr(id); + const idStr = this.genPlayerId(data); if (!this.players.has(idStr)) { this.setNewPlayer(idStr, this.logger, id); diff --git a/src/backend/sources/SonosSource.ts b/src/backend/sources/SonosSource.ts index 71f648a0..ddab9bdf 100644 --- a/src/backend/sources/SonosSource.ts +++ b/src/backend/sources/SonosSource.ts @@ -167,7 +167,7 @@ export class SonosSource extends MemoryPositionalSource { const deviceId = Name === undefined ? NO_DEVICE : `${Name}-${GroupName ?? 'NoGroup'}`; try { - let status = CLIENT_PLAYER_STATE[x.state.transportState]; + let status = CLIENT_PLAYER_STATE[x.state.transportState] ?? REPORTED_PLAYER_STATUSES.unknown; // TODO if status is stopped then drop state if player is also stopped? @@ -226,9 +226,23 @@ export class SonosSource extends MemoryPositionalSource { } continue; } - } else if(this.logEmptyPlayer) { - this.logger.debug(`Player State for -> ${deviceId} <-- is being dropped because it is empty`); - continue; + } else { + let allowOneNonProgress = false; + + const playerId = this.genPlayerId(playerState); + if(this.hasPlayer(playerId) && this.players.get(playerId).isProgressing()) { + // update player state with a stopped/paused/unknown reported state so that player scrobbles any existing play + allowOneNonProgress = true; + } + + if(!allowOneNonProgress) { + // if no player or status is not progressing then drop + // so sonos devices that aren't doing anything get stale/orphaned/pruned + if(this.logEmptyPlayer) { + this.logger.debug(`Player State for -> ${deviceId} <-- is being dropped because it is empty`); + } + continue; + } } playerStates.push(playerState); -- 2.51.2