From 77ba88b76cdd345e8bee016c54f4a5495f69888d Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Mon, 4 Aug 2025 17:46:56 +0200 Subject: [PATCH] Set available devices to empty map on safari. Safari does not allow changing output devices so the output device dialog is confusing. (#3426) * Set available devices to empty map on safari. Signed-off-by: Timo K * better safari check Signed-off-by: Timo K --------- Signed-off-by: Timo K --- src/livekit/MatrixAudioRenderer.tsx | 4 ++-- src/room/InCallView.tsx | 2 +- src/state/MediaDevices.ts | 8 +++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/livekit/MatrixAudioRenderer.tsx b/src/livekit/MatrixAudioRenderer.tsx index d649756f..24975509 100644 --- a/src/livekit/MatrixAudioRenderer.tsx +++ b/src/livekit/MatrixAudioRenderer.tsx @@ -181,7 +181,7 @@ interface StereoPanAudioTrackProps { /** * This wraps `livekit.AudioTrack` to allow adding audio nodes to a track. * It main purpose is to remount the AudioTrack component when switching from - * audiooContext to normal audio playback. + * audioContext to normal audio playback. * As of now the AudioTrack component does not support adding audio nodes while being mounted. * @param param0 * @returns @@ -201,7 +201,7 @@ function AudioTrackWithAudioNodes({ const [trackReady, setTrackReady] = useReactiveState( () => false, // We only want the track to reset once both (audioNodes and audioContext) are set. - // for unsetting the audioContext its enough if one of the the is undefined. + // for unsetting the audioContext its enough if one of the two is undefined. [audioContext && audioNodes], ); diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index f99e368b..5f8e7c28 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -150,7 +150,7 @@ export const ActiveCall: FC = (props) => { ?.disconnect() .then(() => { logger.info( - `[Lifecycle] Disconnected from livekite room, state:${livekitRoom?.state}`, + `[Lifecycle] Disconnected from livekit room, state:${livekitRoom?.state}`, ); }) .catch((e) => { diff --git a/src/state/MediaDevices.ts b/src/state/MediaDevices.ts index f0f49343..2349e361 100644 --- a/src/state/MediaDevices.ts +++ b/src/state/MediaDevices.ts @@ -224,7 +224,7 @@ class AudioOutput this.logger, ).pipe( map((availableRaw) => { - const available: Map = + let available: Map = buildDeviceMap(availableRaw); // Create a virtual default audio output for browsers that don't have one. // Its device ID must be the empty string because that's what setSinkId @@ -234,6 +234,12 @@ class AudioOutput type: "default", name: availableRaw[0]?.label || null, }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const isSafari = !!(window as any).GestureEvent; // non standard api only found on Safari. https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent#browser_compatibility + if (isSafari) { + // set to empty map if we are on Safari, because it does not support setSinkId + available = new Map(); + } // Note: creating virtual default input devices would be another problem // entirely, because requesting a media stream from deviceId "" won't // automatically track the default device.