From e5583e529ec8eab90018e6c5fae8fdfc0b378b35 Mon Sep 17 00:00:00 2001 From: ScreenTinker Date: Wed, 5 Aug 2026 14:21:19 -0500 Subject: [PATCH] The Tizen baseline describes a fielded panel, not the one we are shipping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more corrections from the cross-player audit, both mine. audio.volume removed: a fielded Tizen panel has NO set_volume handler — the command falls through to "unknown command" and the dashboard slider does nothing. One of the platform branches adds a handler, and those panels will declare the capability for themselves once they run it; the baseline exists to describe an un-updated display, so it must not borrow credit from a build that has not shipped. remote.screenshot and remote.stream added: both really are implemented in the shipped player (captureAndSend, startStreaming). Omitting them would have hidden working controls on every legacy Tizen display the moment gating went live — the opposite failure, and the more damaging one. That asymmetry is the thing to hold on to: over-claiming shows a dead button, under-claiming removes a working one, and only reading the shipped code tells you which you are doing. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Uaeo9MvzKoyXuN6ZsbhtkL --- server/lib/player-capabilities.js | 9 ++++++++- server/test/player-capabilities.test.js | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/server/lib/player-capabilities.js b/server/lib/player-capabilities.js index c0c2e67..3e24196 100644 --- a/server/lib/player-capabilities.js +++ b/server/lib/player-capabilities.js @@ -68,8 +68,15 @@ const BASELINE = { tizen: [ 'playback.video', 'playback.image', 'playback.widget', 'playback.youtube', 'playback.zones', 'playback.transitions', 'playback.pip', - 'audio.mute', 'audio.volume', + // audio.mute only. A FIELDED Tizen panel has no set_volume handler at all — the command falls + // through to "unknown command", so the dashboard slider does nothing. Updated panels declare + // audio.volume for themselves once they ship a handler; the baseline describes what an + // un-updated one can actually do, which is the whole reason it exists. + 'audio.mute', 'display.rotation', + // Both really are implemented in the shipped player (captureAndSend / startStreaming), so + // omitting them would have hidden working controls on every legacy Tizen panel. + 'remote.screenshot', 'remote.stream', 'remote.input', 'system.restart_player', 'sync.clock', diff --git a/server/test/player-capabilities.test.js b/server/test/player-capabilities.test.js index 4e203ec..7a7baea 100644 --- a/server/test/player-capabilities.test.js +++ b/server/test/player-capabilities.test.js @@ -97,3 +97,15 @@ test('Tizen does NOT claim offline caching — it caches the playlist, not the m assert.equal(caps.supports({ platform: 'Tizen 6.5' }, 'offline.cache'), false); assert.ok(caps.supports({ client_type: 'apk' }, 'offline.cache'), 'Android really does cache media'); }); + +test('the baseline describes a FIELDED player, not the one we are about to ship', () => { + // Tizen's shipped build has no set_volume handler — the command falls through to "unknown + // command" — so a legacy panel must not claim audio.volume even though updated panels will + // declare it themselves. It DOES implement capture and streaming, so those must be claimed or + // working controls disappear from every legacy Tizen display. + const tizen = { platform: 'Tizen 6.5' }; + assert.equal(caps.supports(tizen, 'audio.volume'), false, 'the slider is dead on a fielded panel'); + assert.ok(caps.supports(tizen, 'audio.mute'), 'mute does work'); + assert.ok(caps.supports(tizen, 'remote.screenshot'), 'captureAndSend exists in the shipped player'); + assert.ok(caps.supports(tizen, 'remote.stream'), 'startStreaming exists in the shipped player'); +});