diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 5ff3924..0e9cba1 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -48,6 +48,7 @@ import { useShowInspector } from "../settings/useSetting"; import { useModalTriggerState } from "../Modal"; import { useAudioContext } from "../video-grid/useMediaStream"; import { useFullscreen } from "../video-grid/useFullscreen"; +import { useAudioOutputDevice } from "../video-grid/useAudioOutputDevice"; const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); // There is currently a bug in Safari our our code with cloning and sending MediaStreams @@ -114,6 +115,8 @@ export function InCallView({ const { modalState: feedbackModalState, modalProps: feedbackModalProps } = useModalTriggerState(); + useAudioOutputDevice(audioRef, audioOutput); + const items = useMemo(() => { const participants: Participant[] = []; diff --git a/src/video-grid/useAudioOutputDevice.ts b/src/video-grid/useAudioOutputDevice.ts new file mode 100644 index 0000000..71b6b7e --- /dev/null +++ b/src/video-grid/useAudioOutputDevice.ts @@ -0,0 +1,40 @@ +/* +Copyright 2022 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { RefObject, useEffect } from "react"; + +export function useAudioOutputDevice( + mediaRef: RefObject, + audioOutputDevice: string +): void { + useEffect(() => { + if ( + mediaRef.current && + mediaRef.current !== undefined && + audioOutputDevice + ) { + if (mediaRef.current.setSinkId) { + console.log( + `useMediaStream setting output setSinkId ${audioOutputDevice}` + ); + // Chrome for Android doesn't support this + mediaRef.current.setSinkId(audioOutputDevice); + } else { + console.log("Can't set output - no setsinkid"); + } + } + }, [mediaRef, audioOutputDevice]); +} diff --git a/src/video-grid/useMediaStream.ts b/src/video-grid/useMediaStream.ts index f9c5e47..dc915f1 100644 --- a/src/video-grid/useMediaStream.ts +++ b/src/video-grid/useMediaStream.ts @@ -22,6 +22,7 @@ import { } from "matrix-js-sdk/src/webrtc/audioContext"; import { useSpatialAudio } from "../settings/useSetting"; +import { useAudioOutputDevice } from "./useAudioOutputDevice"; declare global { interface Window { @@ -38,6 +39,8 @@ export const useMediaStream = ( ): RefObject => { const mediaRef = useRef(); + useAudioOutputDevice(mediaRef, audioOutputDevice); + useEffect(() => { console.log( `useMediaStream update stream mediaRef.current ${!!mediaRef.current} stream ${ @@ -67,24 +70,6 @@ export const useMediaStream = ( } }, [stream, mute]); - useEffect(() => { - if ( - mediaRef.current && - audioOutputDevice && - mediaRef.current !== undefined - ) { - if (mediaRef.current.setSinkId) { - console.log( - `useMediaStream setting output setSinkId ${audioOutputDevice}` - ); - // Chrome for Android doesn't support this - mediaRef.current.setSinkId(audioOutputDevice); - } else { - console.log("Can't set output - no setsinkid"); - } - } - }, [audioOutputDevice]); - useEffect(() => { if (!mediaRef.current) return; if (localVolume === null || localVolume === undefined) return; @@ -156,11 +141,11 @@ const createLoopback = async (stream: MediaStream): Promise => { export const useAudioContext = (): [ AudioContext, AudioNode, - RefObject + RefObject ] => { const context = useRef(); const destination = useRef(); - const audioRef = useRef(); + const audioRef = useRef(); useEffect(() => { if (audioRef.current && !context.current) {