diff options
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/video-player.js | 18 | ||||
| -rw-r--r-- | packages/meshbay-hub/tests/test_cast_discovery.py | 15 |
2 files changed, 33 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js index 4fa652b..243e0c2 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js @@ -1471,6 +1471,24 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) { // The scan lives as long as the picker is open: closing it, or picking a // receiver, stops the updates. Receivers are listed as they answer, and the // spinner sits below them so one landing never moves the row being aimed at. + // While casting, the film plays on the receiver; the local element keeps + // playing — its playhead is what paces the stream the relay forwards — but + // silently. It went on with its sound, so a phone in the room doubled the + // television's audio, screen off included. What the viewer had set comes + // back when the cast ends. + const mutedBeforeCastRef = useRef(null); + useEffect(() => { + const v = videoRef.current; + if (!v) return; + if (castActive) { + if (mutedBeforeCastRef.current === null) mutedBeforeCastRef.current = v.muted; + v.muted = true; + } else if (mutedBeforeCastRef.current !== null) { + v.muted = mutedBeforeCastRef.current; + mutedBeforeCastRef.current = null; + } + }, [castActive]); + useEffect(() => { if (!castPickerOpen) return undefined; setCastDevices([]); diff --git a/packages/meshbay-hub/tests/test_cast_discovery.py b/packages/meshbay-hub/tests/test_cast_discovery.py index 9e9ce85..77b0ef6 100644 --- a/packages/meshbay-hub/tests/test_cast_discovery.py +++ b/packages/meshbay-hub/tests/test_cast_discovery.py @@ -106,3 +106,18 @@ def test_a_new_scan_is_not_cut_short_by_the_one_it_replaced(run): assert run["restartedStillScanning"] is True assert run["restartClearedOldDevices"] is True assert run["restartedEnds"] is True + + +def test_the_local_player_is_silent_while_casting(): + """The local element keeps playing while casting — its playhead paces the + stream the relay forwards — so it must not keep its sound: a phone in the + room doubled the television's audio, screen off included. Whatever the + viewer had set comes back when the cast ends.""" + from spa_source import STATIC + player = (STATIC / "video-player.js").read_text(encoding="utf-8") + effect = player.split("const mutedBeforeCastRef = useRef(null);", 1)[1] + effect = effect.split("}, [castActive]);", 1)[0] + assert "v.muted = true;" in effect + assert "mutedBeforeCastRef.current = v.muted;" in effect + assert "v.muted = mutedBeforeCastRef.current;" in effect + assert "pause()" not in effect, "pausing would stop the stream the receiver is playing" |