From 487e884e5187947a1a4f05043a12253a413c12a9 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 14 May 2026 18:54:09 -0400 Subject: [PATCH] fix: pass audio/video URL params to EC for correct initial device state - Camera no longer starts enabled when user disables it in prescreen - When PTT mode is enabled, call starts muted so PTT works immediately without requiring a manual mute first - CallControlState also updated to match the forced-off audio for PTT EC 0.16.x ignores io.element.device_mute for initial state at startup, so audio= and video= URL params are the only reliable way to set the initial device state before the call begins. --- src/app/hooks/useCallEmbed.ts | 14 +++++++++----- src/app/plugins/call/CallEmbed.ts | 6 +++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/app/hooks/useCallEmbed.ts b/src/app/hooks/useCallEmbed.ts index 0421718ee..c7d176994 100644 --- a/src/app/hooks/useCallEmbed.ts +++ b/src/app/hooks/useCallEmbed.ts @@ -45,15 +45,18 @@ export const createCallEmbed = ( themeKind: ElementCallThemeKind, container: HTMLElement, pref?: CallPreferences, - noiseSuppression = true + noiseSuppression = true, + forceAudioOff = false ): CallEmbed => { const rtcSession = mx.matrixRTC.getRoomSession(room); const ongoing = MatrixRTCSession.sessionMembershipsForRoom(room, rtcSession.sessionDescription).length > 0; const intent = CallEmbed.getIntent(dm, ongoing); - const widget = CallEmbed.getWidget(mx, room, intent, themeKind, noiseSuppression); - const controlState = pref && new CallControlState(pref.microphone, pref.video, pref.sound); + const initialAudio = forceAudioOff ? false : (pref?.microphone ?? true); + const initialVideo = pref?.video ?? false; + const widget = CallEmbed.getWidget(mx, room, intent, themeKind, noiseSuppression, initialAudio, initialVideo); + const controlState = pref && new CallControlState(forceAudioOff ? false : pref.microphone, pref.video, pref.sound); const embed = new CallEmbed(mx, room, widget, container, controlState); @@ -66,6 +69,7 @@ export const useCallStart = (dm = false) => { const setCallEmbed = useSetAtom(callEmbedAtom); const callEmbedRef = useCallEmbedRef(); const [callNoiseSuppression] = useSetting(settingsAtom, 'callNoiseSuppression'); + const [pttMode] = useSetting(settingsAtom, 'pttMode'); const startCall = useCallback( (room: Room, pref?: CallPreferences) => { @@ -73,11 +77,11 @@ export const useCallStart = (dm = false) => { if (!container) { throw new Error('Failed to start call, No embed container element found!'); } - const callEmbed = createCallEmbed(mx, room, dm, theme.kind, container, pref, callNoiseSuppression ?? true); + const callEmbed = createCallEmbed(mx, room, dm, theme.kind, container, pref, callNoiseSuppression ?? true, !!pttMode); setCallEmbed(callEmbed); }, - [mx, dm, theme, setCallEmbed, callEmbedRef, callNoiseSuppression] + [mx, dm, theme, setCallEmbed, callEmbedRef, callNoiseSuppression, pttMode] ); return startCall; diff --git a/src/app/plugins/call/CallEmbed.ts b/src/app/plugins/call/CallEmbed.ts index 7902cbd4c..2a42e90f8 100644 --- a/src/app/plugins/call/CallEmbed.ts +++ b/src/app/plugins/call/CallEmbed.ts @@ -60,7 +60,9 @@ export class CallEmbed { room: Room, intent: ElementCallIntent, themeKind: ElementCallThemeKind, - noiseSuppression = true + noiseSuppression = true, + initialAudio = true, + initialVideo = false ): Widget { const userId = mx.getSafeUserId(); const deviceId = mx.getDeviceId() ?? ''; @@ -83,6 +85,8 @@ export class CallEmbed { lang: 'en-EN', theme: themeKind, noiseSuppression: noiseSuppression.toString(), + audio: initialAudio.toString(), + video: initialVideo.toString(), }); const widgetUrl = new URL(