From abe9ece38f41798be4cfbec583b205b2e29ca728 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 11 May 2022 16:28:08 +0100 Subject: [PATCH 1/3] Add push-to-talk sound effects Fixes https://github.com/vector-im/element-call/issues/296 --- .eslintrc.js | 1 + src/room/PTTCallView.tsx | 18 +++++--- src/room/usePTT.ts | 77 ++++++++++++++++++++++++-------- src/sound/PTTClips.module.css | 19 ++++++++ src/sound/PTTClips.tsx | 62 +++++++++++++++++++++++++ src/sound/blocked.mp3 | Bin 0 -> 8403 bytes src/sound/blocked.ogg | Bin 0 -> 6490 bytes src/sound/start_talk_local.mp3 | Bin 0 -> 6313 bytes src/sound/start_talk_local.ogg | Bin 0 -> 4651 bytes src/sound/start_talk_remote.mp3 | Bin 0 -> 5268 bytes src/sound/start_talk_remote.ogg | Bin 0 -> 4549 bytes src/sound/usePttSounds.ts | 70 +++++++++++++++++++++++++++++ 12 files changed, 224 insertions(+), 23 deletions(-) create mode 100644 src/sound/PTTClips.module.css create mode 100644 src/sound/PTTClips.tsx create mode 100644 src/sound/blocked.mp3 create mode 100644 src/sound/blocked.ogg create mode 100644 src/sound/start_talk_local.mp3 create mode 100644 src/sound/start_talk_local.ogg create mode 100644 src/sound/start_talk_remote.mp3 create mode 100644 src/sound/start_talk_remote.ogg create mode 100644 src/sound/usePttSounds.ts diff --git a/.eslintrc.js b/.eslintrc.js index 89b5844..1652f6d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,6 +19,7 @@ module.exports = { // We break this rule in a few places: dial it back to a warning // (and run with max warnings) to tolerate the existing code "react-hooks/exhaustive-deps": ["warn"], + "jsx-a11y/media-has-caption": ["off"], }, overrides: [ { diff --git a/src/room/PTTCallView.tsx b/src/room/PTTCallView.tsx index d929713..c068289 100644 --- a/src/room/PTTCallView.tsx +++ b/src/room/PTTCallView.tsx @@ -17,7 +17,6 @@ limitations under the License. import React from "react"; import useMeasure from "react-use-measure"; import { ResizeObserver } from "@juggle/resize-observer"; -import { OtherUserSpeakingError } from "matrix-js-sdk/src/webrtc/groupCall"; import { useModalTriggerState } from "../Modal"; import { SettingsModal } from "../settings/SettingsModal"; @@ -34,6 +33,8 @@ import { Timer } from "./Timer"; import { Toggle } from "../input/Toggle"; import { getAvatarUrl } from "../matrix-utils"; import { ReactComponent as AudioIcon } from "../icons/Audio.svg"; +import { usePTTSounds } from "../sound/usePttSounds"; +import { PTTClips } from "../sound/PTTClips"; export function PTTCallView({ client, @@ -57,6 +58,9 @@ export function PTTCallView({ const { audioOutput } = useMediaHandler(); + const { startTalkingLocalRef, startTalkingRemoteRef, blockedRef, playClip } = + usePTTSounds(); + const { pttButtonHeld, isAdmin, @@ -65,11 +69,10 @@ export function PTTCallView({ activeSpeakerUserId, startTalking, stopTalking, - unmuteError, - } = usePTT(client, groupCall, userMediaFeeds); + transmitBlocked, + } = usePTT(client, groupCall, userMediaFeeds, playClip); - const showTalkOverError = - pttButtonHeld && unmuteError instanceof OtherUserSpeakingError; + const showTalkOverError = pttButtonHeld && transmitBlocked; const activeSpeakerIsLocalUser = activeSpeakerUserId && client.getUserId() === activeSpeakerUserId; @@ -89,6 +92,11 @@ export function PTTCallView({ return (
+
diff --git a/src/room/usePTT.ts b/src/room/usePTT.ts index 24d364c..17e2b45 100644 --- a/src/room/usePTT.ts +++ b/src/room/usePTT.ts @@ -18,6 +18,9 @@ import { useCallback, useEffect, useState } from "react"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall"; import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed"; +import { logger } from "matrix-js-sdk/src/logger"; + +import { PlayClipFunction, PTTClipID } from "../sound/usePttSounds"; export interface PTTState { pttButtonHeld: boolean; @@ -27,13 +30,14 @@ export interface PTTState { activeSpeakerUserId: string; startTalking: () => void; stopTalking: () => void; - unmuteError: Error; + transmitBlocked: boolean; } export const usePTT = ( client: MatrixClient, groupCall: GroupCall, - userMediaFeeds: CallFeed[] + userMediaFeeds: CallFeed[], + playClip: PlayClipFunction ): PTTState => { const [ { @@ -41,7 +45,7 @@ export const usePTT = ( isAdmin, talkOverEnabled, activeSpeakerUserId, - unmuteError, + transmitBlocked, }, setState, ] = useState(() => { @@ -54,7 +58,7 @@ export const usePTT = ( talkOverEnabled: false, pttButtonHeld: false, activeSpeakerUserId: activeSpeakerFeed ? activeSpeakerFeed.userId : null, - unmuteError: null, + transmitBlocked: false, }; }); @@ -62,6 +66,21 @@ export const usePTT = ( function onMuteStateChanged(...args): void { const activeSpeakerFeed = userMediaFeeds.find((f) => !f.isAudioMuted()); + if (activeSpeakerUserId === null && activeSpeakerFeed.userId !== null) { + if (activeSpeakerFeed.userId === client.getUserId()) { + playClip(PTTClipID.START_TALKING_LOCAL); + } else { + playClip(PTTClipID.START_TALKING_REMOTE); + } + } else if ( + activeSpeakerFeed && + activeSpeakerUserId === client.getUserId() && + activeSpeakerFeed.userId !== client.getUserId() + ) { + // We were talking but we've been cut off + playClip(PTTClipID.BLOCKED); + } + setState((prevState) => ({ ...prevState, activeSpeakerUserId: activeSpeakerFeed @@ -89,33 +108,55 @@ export const usePTT = ( ); } }; - }, [userMediaFeeds]); + }, [userMediaFeeds, activeSpeakerUserId, client, playClip]); const startTalking = useCallback(async () => { - setState((prevState) => ({ - ...prevState, - pttButtonHeld: true, - unmuteError: null, - })); - if (!activeSpeakerUserId || isAdmin || talkOverEnabled) { + if (pttButtonHeld) return; + + let blocked = false; + if (!activeSpeakerUserId || (isAdmin && talkOverEnabled)) { if (groupCall.isMicrophoneMuted()) { try { await groupCall.setMicrophoneMuted(false); } catch (e) { - setState((prevState) => ({ ...prevState, unmuteError: null })); + logger.error("Failed to unmute microphone", e); } } + } else { + playClip(PTTClipID.BLOCKED); + blocked = true; } - }, [groupCall, activeSpeakerUserId, isAdmin, talkOverEnabled, setState]); + setState((prevState) => ({ + ...prevState, + pttButtonHeld: true, + transmitBlocked: blocked, + })); + }, [ + pttButtonHeld, + groupCall, + activeSpeakerUserId, + isAdmin, + talkOverEnabled, + setState, + playClip, + ]); const stopTalking = useCallback(() => { - setState((prevState) => ({ ...prevState, pttButtonHeld: false })); + setState((prevState) => ({ + ...prevState, + pttButtonHeld: false, + unmuteError: null, + })); if (!groupCall.isMicrophoneMuted()) { groupCall.setMicrophoneMuted(true); } - setState((prevState) => ({ ...prevState, pttButtonHeld: false })); + setState((prevState) => ({ + ...prevState, + pttButtonHeld: false, + transmitBlocked: false, + })); }, [groupCall]); useEffect(() => { @@ -147,8 +188,8 @@ export const usePTT = ( } window.addEventListener("keydown", onKeyDown); - window.addEventListener("keyup", onKeyUp); - window.addEventListener("blur", onBlur); + //window.addEventListener("keyup", onKeyUp); + //window.addEventListener("blur", onBlur); return () => { window.removeEventListener("keydown", onKeyDown); @@ -180,6 +221,6 @@ export const usePTT = ( activeSpeakerUserId, startTalking, stopTalking, - unmuteError, + transmitBlocked, }; }; diff --git a/src/sound/PTTClips.module.css b/src/sound/PTTClips.module.css new file mode 100644 index 0000000..effe2ad --- /dev/null +++ b/src/sound/PTTClips.module.css @@ -0,0 +1,19 @@ +/* +Copyright 2022 Matrix.org Foundation C.I.C. + +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. +*/ + +.pttClip { + display: none; +} \ No newline at end of file diff --git a/src/sound/PTTClips.tsx b/src/sound/PTTClips.tsx new file mode 100644 index 0000000..e13acb5 --- /dev/null +++ b/src/sound/PTTClips.tsx @@ -0,0 +1,62 @@ +/* +Copyright 2022 Matrix.org Foundation C.I.C. + +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 React from "react"; + +import startTalkLocalOggUrl from "./start_talk_local.ogg"; +import startTalkLocalMp3Url from "./start_talk_local.mp3"; +import startTalkRemoteOggUrl from "./start_talk_remote.ogg"; +import startTalkRemoteMp3Url from "./start_talk_remote.mp3"; +import blockedOggUrl from "./blocked.ogg"; +import blockedMp3Url from "./blocked.mp3"; +import styles from "./PTTClips.module.css"; + +interface Props { + startTalkingLocalRef: React.RefObject; + startTalkingRemoteRef: React.RefObject; + blockedRef: React.RefObject; +} + +export const PTTClips: React.FC = ({ + startTalkingLocalRef, + startTalkingRemoteRef, + blockedRef, +}) => { + return ( + <> + + + + + ); +}; diff --git a/src/sound/blocked.mp3 b/src/sound/blocked.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..b8b66d6a8b50d65aa6fe4a4ad3998226d6237cf7 GIT binary patch literal 8403 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 literal 0 HcmV?d00001 diff --git a/src/sound/blocked.ogg b/src/sound/blocked.ogg new file mode 100644 index 0000000000000000000000000000000000000000..697bb53a26893591e1bc68cb7898629bb8fef04e GIT binary patch literal 6490 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 b^eJnTW&$7vI}O;#Ha#A^V=;rpZvg)VG+M!R literal 0 HcmV?d00001 diff --git a/src/sound/start_talk_local.mp3 b/src/sound/start_talk_local.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..862cd1746f0e6323112e9aa9fd20aefd8cbc71ca GIT binary patch literal 6313 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 R`F}a|-+J>m@qZkFe*i}ub*caW literal 0 HcmV?d00001 diff --git a/src/sound/start_talk_local.ogg b/src/sound/start_talk_local.ogg new file mode 100644 index 0000000000000000000000000000000000000000..6759a62a05e92062f19b4145b476c9ddb878eeba GIT binary patch literal 4651 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 literal 0 HcmV?d00001 diff --git a/src/sound/start_talk_remote.ogg b/src/sound/start_talk_remote.ogg new file mode 100644 index 0000000000000000000000000000000000000000..53225c121304dc12f1ef8961119c8f7cb6bf9139 GIT binary patch literal 4549 zcmeHLdsLH07N0u#m8GTVa;E2xGWJpTr&jXwDMw=Q%JnwW%?deKf3|N7f9%hhRV4(zaI{muOG5+#Ok)xJokn_HLT?m9C+cF+BW2&*=k^$g8y^$u)*eAVpx)3#(hFRDNq8LKFf=rSphNQvWDP^%+2GzR`nGngKGoBrXb~-_ zm7gs&9xQg?}kS$g(9M&Wht@%l0auc@)2GPH;P@eRC*oId%n=N~8`9n_Uenmf?MEn&kcoBk%6 zuxQUDr)_FJiz>J_6Y7EE$AZ{PNxnJN37F+9J@{Z$^~0ipPD6s$8wprc1ov`5jjnRoszS7E5LB$EN$W`UAZ;D3E(0 z?ndHGSGn0uskMJ0Bp7oggY{~G@&y(M6i5bH1`rDceL}te3y~2D>eW=4#tH@be$T%l z*yEOvZJ^3NSbS-jQtuy4v%A00dYOVdGot_=;DV!+=VOX6tuC zIR*gMrCNgEM*nK%w+_94-USo{L5Ejc_@mGx(%lNoZhcW2I|0rHb`HWucUqE|wOs=@ zeix7cGr`UlzS3J}w5lzE1|)VcDvqwUOqABCFF%gLrrnTlp~@13$`9;n2T!0>`M`W- z6oXxB@3;rb_njmHsS98lvQjPMrFDS@dy~a!Mb0-EU7JaM=M|XI0`$W zl2oel8Medm06L1J!``Z);_omE(4*r)JMMHaNvSH%WEt#gi^JhKH9I7YmMxflB3$QnS4@BLQ33KJj z`h%6ciqrkN*>lB5*-KnBK>%E0*y)Ma1&i5Ms$UnPqe~ZaYy+r+Wkpf0k1k2U;~X=g z8@Vbf%55@vNO_zZ6o5N>UE!}hKL45mu;v1dU=?;~zvXYGXZMN%X{aG&qV}L7WE`eJ zv0Ptxnon3wc*=t+FrJ8O!}A^!s(_i&TM8~m*DDFMnFe5fPD$ zmn!vO>r5yaeibh*e=i`1OTMyY7)z*z#d)xSl;#Hh`l3NG>5JF@hzf?u8J?lN)VP6P zR1x6mn|Dq}UXJZgSqCFZ(7@$>iD6?DQKVd35*bEdM^aivi&P&nfmm;+ZSE}Ul?1VC zhO_u}MV?YFw=+3AfvZDNMQ~e6h2rQjBdTZ~N~sKKvJR(JGMOk0wDLPO(ju*y_RW zKd1uoaH<-8Fhfxl+z&Ag?25#-X>lo45oEK{XKqYQRue{{QaD=}D7+uX3Nu`cM?MOJ zr{I=DHJb@enQQY>xN~$~D3@!aE68jpguEn$`%#@2T$~v8(13yqqsxqd$uUC`=&PEy z{+Rpxh0a|i2j)BtCX^d2EAzK8tc=yGe2U`J42^{p^kx&<%Nj?_`VgJzU{dHfT}qKY zU>2|8l7ed((k_PePT}gKMV@e1lmLyU8UR1Iz$4TK|ppIr*Clc9iVa==7DNSB^M3T3E#J^?QxEVBsPb+dlw- z+qm-z&e8xP(V03hBIuF5-p zjT~5JYmR8|HoHibt{`!lDsQW4pu^=razM?Y*Ly%k#orBf zIHrY$Z_<`?b-K|#n)siG+hf@X@dwxVb1zwOlHx|22N3TjBjc0B@R<5c{l>m;k78K40JBP(or-!bK1lPOD*D?_q6 z4GEjV4z#5!k2kdqS$Bn|t?=DbG3T>R(#RLht``m-xE$Hnz2Q-C_|x#@3k#d;DwE^v z7duIvl+QZ9+I6OV;Z6HN!k@Y_!l$ORcGs=KOWv|a^GT-;bx(-}Zx`;;alTrAsP0qByT7C^{pd%}&~>jDM*j26!;K@` ZE?zOd>nEqYLpr_;M9n8CG>7Mae*w3_YL5T_ literal 0 HcmV?d00001 diff --git a/src/sound/usePttSounds.ts b/src/sound/usePttSounds.ts new file mode 100644 index 0000000..4084096 --- /dev/null +++ b/src/sound/usePttSounds.ts @@ -0,0 +1,70 @@ +/* +Copyright 2022 Matrix.org Foundation C.I.C. + +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 React, { useCallback, useState } from "react"; + +export enum PTTClipID { + START_TALKING_LOCAL, + START_TALKING_REMOTE, + BLOCKED, +} + +export type PlayClipFunction = (clipID: PTTClipID) => void; + +interface PTTSounds { + startTalkingLocalRef: React.RefObject; + startTalkingRemoteRef: React.RefObject; + blockedRef: React.RefObject; + playClip: PlayClipFunction; +} + +export const usePTTSounds = (): PTTSounds => { + const [startTalkingLocalRef] = useState(React.createRef()); + const [startTalkingRemoteRef] = useState(React.createRef()); + const [blockedRef] = useState(React.createRef()); + + const playClip = useCallback( + async (clipID: PTTClipID) => { + let ref: React.RefObject; + + switch (clipID) { + case PTTClipID.START_TALKING_LOCAL: + ref = startTalkingLocalRef; + break; + case PTTClipID.START_TALKING_REMOTE: + ref = startTalkingRemoteRef; + break; + case PTTClipID.BLOCKED: + ref = blockedRef; + break; + } + if (ref.current) { + ref.current.currentTime = 0; + await ref.current.play(); + } else { + console.log("No media element found"); + } + }, + [startTalkingLocalRef, startTalkingRemoteRef, blockedRef] + ); + + return { + startTalkingLocalRef, + startTalkingRemoteRef, + blockedRef, + playClip, + }; +}; From 5a56e46f7b349d40377a377b4a8aa534fb20ef20 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 11 May 2022 16:50:41 +0100 Subject: [PATCH 2/3] Prettier --- src/sound/PTTClips.module.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sound/PTTClips.module.css b/src/sound/PTTClips.module.css index effe2ad..cd680f5 100644 --- a/src/sound/PTTClips.module.css +++ b/src/sound/PTTClips.module.css @@ -15,5 +15,5 @@ limitations under the License. */ .pttClip { - display: none; -} \ No newline at end of file + display: none; +} From 323505fbb45dc8c6a41e4e846981d11dedcfaf13 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 12 May 2022 10:04:14 +0100 Subject: [PATCH 3/3] Put back listeners commented for testing --- src/room/usePTT.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/room/usePTT.ts b/src/room/usePTT.ts index 17e2b45..0d8f106 100644 --- a/src/room/usePTT.ts +++ b/src/room/usePTT.ts @@ -188,8 +188,8 @@ export const usePTT = ( } window.addEventListener("keydown", onKeyDown); - //window.addEventListener("keyup", onKeyUp); - //window.addEventListener("blur", onBlur); + window.addEventListener("keyup", onKeyUp); + window.addEventListener("blur", onBlur); return () => { window.removeEventListener("keydown", onKeyDown);