diff --git a/src/video-grid/VideoTile.tsx b/src/video-grid/VideoTile.tsx index 79f134a..2cef8e2 100644 --- a/src/video-grid/VideoTile.tsx +++ b/src/video-grid/VideoTile.tsx @@ -72,7 +72,7 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>( const { t } = useTranslation(); const toolbarButtons: JSX.Element[] = []; - if (!isLocal) { + if (hasFeed && !isLocal) { toolbarButtons.push( <AudioButton key="localVolume" diff --git a/src/video-grid/VideoTileContainer.tsx b/src/video-grid/VideoTileContainer.tsx index ce23c3a..cb93dbd 100644 --- a/src/video-grid/VideoTileContainer.tsx +++ b/src/video-grid/VideoTileContainer.tsx @@ -68,7 +68,7 @@ export function VideoTileContainer({ } = useCallFeed(item.callFeed); const { rawDisplayName } = useRoomMemberName(item.member); const [tileRef, mediaRef] = useSpatialMediaStream( - stream, + stream ?? null, audioContext, audioDestination, isLocal, @@ -109,7 +109,7 @@ export function VideoTileContainer({ onFullscreen={onFullscreenCallback} {...rest} /> - {videoTileSettingsModalState.isOpen && !maximised && ( + {videoTileSettingsModalState.isOpen && !maximised && item.callFeed && ( <VideoTileSettingsModal {...videoTileSettingsModalProps} feed={item.callFeed} diff --git a/src/video-grid/useAudioOutputDevice.ts b/src/video-grid/useAudioOutputDevice.ts index 71b6b7e..d3c5ee8 100644 --- a/src/video-grid/useAudioOutputDevice.ts +++ b/src/video-grid/useAudioOutputDevice.ts @@ -18,7 +18,7 @@ import { RefObject, useEffect } from "react"; export function useAudioOutputDevice( mediaRef: RefObject<MediaElement>, - audioOutputDevice: string + audioOutputDevice: string | undefined ): void { useEffect(() => { if ( diff --git a/src/video-grid/useCallFeed.ts b/src/video-grid/useCallFeed.ts index 7f66233..229df3c 100644 --- a/src/video-grid/useCallFeed.ts +++ b/src/video-grid/useCallFeed.ts @@ -19,17 +19,18 @@ import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed"; import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventTypes"; interface CallFeedState { - callFeed: CallFeed; + callFeed: CallFeed | undefined; isLocal: boolean; speaking: boolean; videoMuted: boolean; audioMuted: boolean; localVolume: number; - disposed: boolean; - stream: MediaStream; - purpose: SDPStreamMetadataPurpose; + disposed: boolean | undefined; + stream: MediaStream | undefined; + purpose: SDPStreamMetadataPurpose | undefined; } -function getCallFeedState(callFeed: CallFeed): CallFeedState { + +function getCallFeedState(callFeed: CallFeed | undefined): CallFeedState { return { callFeed, isLocal: callFeed ? callFeed.isLocal() : false, @@ -43,7 +44,7 @@ function getCallFeedState(callFeed: CallFeed): CallFeedState { }; } -export function useCallFeed(callFeed: CallFeed): CallFeedState { +export function useCallFeed(callFeed: CallFeed | undefined): CallFeedState { const [state, setState] = useState<CallFeedState>(() => getCallFeedState(callFeed) ); diff --git a/src/video-grid/useMediaStream.ts b/src/video-grid/useMediaStream.ts index aae942d..61c6524 100644 --- a/src/video-grid/useMediaStream.ts +++ b/src/video-grid/useMediaStream.ts @@ -64,8 +64,8 @@ export const useMediaStreamTrackCount = ( }; export const useMediaStream = ( - stream: MediaStream, - audioOutputDevice: string, + stream: MediaStream | null, + audioOutputDevice: string | null, mute = false, localVolume?: number ): RefObject<MediaElement> => { @@ -158,7 +158,7 @@ const createLoopback = async (stream: MediaStream): Promise<MediaStream> => { await loopbackConn.setRemoteDescription(offer); const answer = await loopbackConn.createAnswer(); // Rewrite SDP to be stereo and (variable) max bitrate - const parsedSdp = parseSdp(answer.sdp); + const parsedSdp = parseSdp(answer.sdp!); parsedSdp.media.forEach((m) => m.fmtp.forEach( (f) => (f.config += `;stereo=1;cbr=0;maxaveragebitrate=510000;`) @@ -206,11 +206,11 @@ export const useAudioContext = (): [ } }, []); - return [context.current, destination.current, audioRef]; + return [context.current!, destination.current!, audioRef]; }; export const useSpatialMediaStream = ( - stream: MediaStream, + stream: MediaStream | null, audioContext: AudioContext, audioDestination: AudioNode, mute = false, @@ -219,7 +219,7 @@ export const useSpatialMediaStream = ( const tileRef = useRef<HTMLDivElement>(); const [spatialAudio] = useSpatialAudio(); // We always handle audio separately form the video element - const mediaRef = useMediaStream(stream, undefined, true, undefined); + const mediaRef = useMediaStream(stream, null, true); const [audioTrackCount] = useMediaStreamTrackCount(stream); const gainNodeRef = useRef<GainNode>(); @@ -240,7 +240,7 @@ export const useSpatialMediaStream = ( }); } if (!sourceRef.current) { - sourceRef.current = audioContext.createMediaStreamSource(stream); + sourceRef.current = audioContext.createMediaStreamSource(stream!); } const tile = tileRef.current; @@ -252,12 +252,12 @@ export const useSpatialMediaStream = ( const bounds = tile.getBoundingClientRect(); const windowSize = Math.max(window.innerWidth, window.innerHeight); // Position the source relative to its placement in the window - pannerNodeRef.current.positionX.value = + pannerNodeRef.current!.positionX.value = (bounds.x + bounds.width / 2) / windowSize - 0.5; - pannerNodeRef.current.positionY.value = + pannerNodeRef.current!.positionY.value = (bounds.y + bounds.height / 2) / windowSize - 0.5; // Put the source in front of the listener - pannerNodeRef.current.positionZ.value = -2; + pannerNodeRef.current!.positionZ.value = -2; }; gainNode.gain.value = localVolume;