From 4ad4cff23f912cdc13488b121f5a873decef97e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 14 Jul 2022 16:18:10 +0200 Subject: [PATCH 01/11] Add handling for local volume control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/video-grid/useCallFeed.js | 7 +++++++ src/video-grid/useMediaStream.ts | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/video-grid/useCallFeed.js b/src/video-grid/useCallFeed.js index b294f5897..9ae4e8624 100644 --- a/src/video-grid/useCallFeed.js +++ b/src/video-grid/useCallFeed.js @@ -27,6 +27,7 @@ function getCallFeedState(callFeed) { : true, videoMuted: callFeed ? callFeed.isVideoMuted() : true, audioMuted: callFeed ? callFeed.isAudioMuted() : true, + localVolume: callFeed ? callFeed.getLocalVolume() : 0, stream: callFeed ? callFeed.stream : undefined, purpose: callFeed ? callFeed.purpose : undefined, }; @@ -44,6 +45,10 @@ export function useCallFeed(callFeed) { setState((prevState) => ({ ...prevState, audioMuted, videoMuted })); } + function onLocalVolumeChanged(localVolume) { + setState((prevState) => ({ ...prevState, localVolume })) + } + function onUpdateCallFeed() { setState(getCallFeedState(callFeed)); } @@ -51,6 +56,7 @@ export function useCallFeed(callFeed) { if (callFeed) { callFeed.on(CallFeedEvent.Speaking, onSpeaking); callFeed.on(CallFeedEvent.MuteStateChanged, onMuteStateChanged); + callFeed.on(CallFeedEvent.LocalVolumeChanged, onLocalVolumeChanged); callFeed.on(CallFeedEvent.NewStream, onUpdateCallFeed); } @@ -63,6 +69,7 @@ export function useCallFeed(callFeed) { CallFeedEvent.MuteStateChanged, onMuteStateChanged ); + callFeed.removeListener(CallFeedEvent.LocalVolumeChanged, onLocalVolumeChanged); callFeed.removeListener(CallFeedEvent.NewStream, onUpdateCallFeed); } }; diff --git a/src/video-grid/useMediaStream.ts b/src/video-grid/useMediaStream.ts index 79e8292be..1781b7aba 100644 --- a/src/video-grid/useMediaStream.ts +++ b/src/video-grid/useMediaStream.ts @@ -33,7 +33,8 @@ declare global { export const useMediaStream = ( stream: MediaStream, audioOutputDevice: string, - mute = false + mute = false, + localVolume: number, ): RefObject => { const mediaRef = useRef(); @@ -84,6 +85,13 @@ export const useMediaStream = ( } }, [audioOutputDevice]); + useEffect(() => { + if (!mediaRef.current) return; + if (localVolume === null || localVolume === undefined) return; + + mediaRef.current.volume = localVolume; + }, [localVolume]) + useEffect(() => { const mediaEl = mediaRef.current; @@ -187,7 +195,8 @@ export const useSpatialMediaStream = ( audioOutputDevice: string, audioContext: AudioContext, audioDestination: AudioNode, - mute = false + mute = false, + localVolume: number, ): [RefObject, RefObject] => { const tileRef = useRef(); const [spatialAudio] = useSpatialAudio(); @@ -195,7 +204,8 @@ export const useSpatialMediaStream = ( const mediaRef = useMediaStream( stream, audioOutputDevice, - spatialAudio || mute + spatialAudio || mute, + localVolume, ); const pannerNodeRef = useRef(); From eda8404144e435c75ed6cd5251c7a20737dab2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 15 Jul 2022 11:18:56 +0200 Subject: [PATCH 02/11] Add UI for local volume control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/button/Button.tsx | 18 +++++ src/video-grid/VideoTile.jsx | 10 ++- src/video-grid/VideoTile.module.css | 19 ++++- src/video-grid/VideoTileContainer.jsx | 45 +++++++---- .../VideoTileSettingsModal.module.css | 76 +++++++++++++++++++ src/video-grid/VideoTileSettingsModal.tsx | 73 ++++++++++++++++++ 6 files changed, 222 insertions(+), 19 deletions(-) create mode 100644 src/video-grid/VideoTileSettingsModal.module.css create mode 100644 src/video-grid/VideoTileSettingsModal.tsx diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 83e3697cc..97c6166fe 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -30,6 +30,7 @@ import { ReactComponent as SettingsIcon } from "../icons/Settings.svg"; import { ReactComponent as AddUserIcon } from "../icons/AddUser.svg"; import { ReactComponent as ArrowDownIcon } from "../icons/ArrowDown.svg"; import { TooltipTrigger } from "../Tooltip"; +import { ReactComponent as OverflowIcon } from "../icons/Overflow.svg"; export type ButtonVariant = | "default" @@ -237,3 +238,20 @@ export function InviteButton({ ); } + +export function OptionsButton({ + className, + ...rest +}: { + className?: string; + [index: string]: unknown; +}) { + return ( + + + {() => "Options"} + + ); +} diff --git a/src/video-grid/VideoTile.jsx b/src/video-grid/VideoTile.jsx index 2dd41921c..206f8a46e 100644 --- a/src/video-grid/VideoTile.jsx +++ b/src/video-grid/VideoTile.jsx @@ -20,6 +20,7 @@ import classNames from "classnames"; import styles from "./VideoTile.module.css"; import { ReactComponent as MicMutedIcon } from "../icons/MicMuted.svg"; import { ReactComponent as VideoMutedIcon } from "../icons/VideoMuted.svg"; +import { OptionsButton } from "../button/Button"; export const VideoTile = forwardRef( ( @@ -35,6 +36,8 @@ export const VideoTile = forwardRef( name, showName, mediaRef, + onOptionsPress, + showOptions, ...rest }, ref @@ -62,13 +65,18 @@ export const VideoTile = forwardRef( ) : ( (showName || audioMuted || (videoMuted && !noVideo)) && ( -
+
{audioMuted && !(videoMuted && !noVideo) && } {videoMuted && !noVideo && } {showName && {name}}
) )} + {showOptions && ( +
+ +
+ )}