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 89b58447..1652f6d4 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 d9297135..c068289f 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 24d364c2..17e2b450 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 00000000..effe2ad4 --- /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 00000000..e13acb5a --- /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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 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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 Mak^$yg3ciT07o2kssI20 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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 PgQ|A*k?aI+W(EcTtYME* literal 0 HcmV?d00001 diff --git a/src/sound/start_talk_remote.mp3 b/src/sound/start_talk_remote.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..4e241021027d6cfc4764932aa0c2d972c17c6234 GIT binary patch literal 5268 zcmeZtF=k-^0p*b3U{?kP27U$xW}n2eG*e4GLo+=?0|SsG6#xJI0LsEmdFG|%LyTcy zVPFtRXGp^VX5s>8aDo500LV2yiDk(kH(P)>Fs#CK1Hu$Z7Z;f10AY`kqaiRF0@MnD z|GyukFfeeOY}zYYtiUw=LwLgi6NXeieId)g3`~8l51AP*Ffgb$XRSUm<5)(hG-pIw zg66V><-Qx|JS|Fo9{BZt`r9jWO>boeX{ab9DGIhSa0nV?xID38#>U&d)QQV( z=^S0A5{Ld>hnHFB9pF}r-9GnAI{z_~@ABXO#owCLaU{u5diyGG>E+vt%=u5hz0zYp z>Ew3BJ9E}+_g=nz)%MrK&a{^=fBQ@K9(!E!<;%~9o*L7Fifz97`{(ak>FIgKQoHx` z`zsrF9N9ec`H#di=5hD4f`W>If{g=yTU(la^If#w*h`?)~eV%=W z(yR-_8n$p8I3(1Q7BAO)A(2hMjU~a2T}h?ki=M*G8IJ`U8%%{i%x@~=yrG*|EzH;= z;dsJJO3AawB8usQ8uNuIdg9z24iXGJOb0A_m=%(HxC4sLL>^J=k#%_J<8HdJ$3x)* zk7dG#ez8Pp9tWdXKh5d?e3BMiX=XlXVCm3qkbj`rK+K`Wko7Sl9$2{dqt?KIQ*2#0uOIyBvm;H79|9|f*f?`%r+d8-J`D&9drk4Nrzg;!m;Qaen<-4E1 zx6Q8q?;rF}X04~{lI2e`S!Z3JbyT<0)c7YTQogTG&kle2X`}z=l1;lJXI#0<4-&og zWOJ~{t&J_auKcyFQQXCQupT7(Ke%@Oi&vL|%7Rv^&0g~RVsMaMQj_b`Ws@|NW?fv% z(y!|_SzAJ@*YlE9`fIx_GFLNJs)WqG9^2ial9Mq}>FH@G2%&h*1fnTrDwDLPZrCT6?ZCbOws4`XyQ`lGdO%f|A8gr z9bYd0ANM+L)TH)o3OFF&>Bz3edL)ESU|?gs!S3*Y`Lt2ff*p*F zA6yt4cQCp%8Em-1-`2jA-z>0GM(5R))2^Nys}3G^=h-^TDsXMZR=26?Pv!pqew1R_ zAr{l@DqhRLuxvtx?t?81;ZmI9>%X#dCmoVIAo6%Yn%=UHn@d()`*1nzSM<6Mo6EKq z$HW@%-RhsOU0S?v;&=J~*8|UA|NsBK%-6&B@04!c^!sR`fZhELDY@)5Ck`!&4EZWu zq!Y^{$i;ufSEbiR%X6EO!=*I`4USyNvYz(kwq)D&9M#QTay97cy?aY{UCU@* z$ucda(B!hiTUVvZ$81H#;>S0xl({l1BQHQxn9cFy6i!H=3h9LUdYSNeCgT#G& zr!ti+eO zM-Ba1&lr2_IW+m4czM!LvbUv!e}Grtb?Fo{ zOVJUva6t{P#Py~5p)cR;E~@giDr`NK>wGia+M4}pmFB~5B2RZ0^B;c89zM-&ahP1W zZjWhaTh~WxK9R;l)5G|b78Zz4vOKTK&Et42>{1Bp=@QA?%T78p2Z(m+&I0GTPxevut)B8DFXvj=jk;r z3@R*w4L=wg8|N{fY+Azhv1J~wWfzZf;O1nX#5kN$k~G7GfXT^9i@aqDv9{6F8{|2IGSzyA9D@UNf$|1bXdHM%C_ zy^oP~g}mtfGoeu~0Zk{BB-RL2%!$Z8uzKe+3C|$OBSDznQLbqm$pQ4+TD)B;kidIU2V1Wc?l{M zHgJ4f*nA}Wx6^_b8>TO1o$*57j9YO1+li;A9g=GhOJ2}ucA`D2jw*q^-+CJhtyW1)?wB&Cx2ED?2Y*C| zgj4E6grKA)OE|{vo$k=0guU@Axdi(#d1~&E&x^3JGRM@y0EZH~@$UNg& zq5VvQ^FZ2({>{q|B>K0xB%EoJ*RXvipmBnY|Ab|m!~)Yct^!>)4gpp-_8Z#Ecq?q4 z@oA_pV|&1y#`;6)8JCA<8pjW*CF#!vH`K=+U#gJi_?$JNQo`NgOwy6%!dVrj&;F$) z^|BipRBT@MuF5GRho9}ojVu<&VBzp=vyj4N!kWHjW|L!`wdD;DFZS{>aXR>LvYeH% zva*(#{>k?KnVyz??F%k;a!Yz@_O`55<`6Pi(DX&6vZZZCg+)SA`wR}t=B8!4ZS)o~ z$Q@&7X?f8Y8I`Tm9+K(P@kMau=jjA zMcH1t@9w;P+|(`{Vzc=7_sG@CQzv-cTDAJq?=2oD9|g~lcs%XT>BUAC&oz0{>>gzV zOXyV|()ke~B6WdXNJ*M`>Y28G_y7Nl;rV>~?7rkm)~UXERr@S!)=E9LJ94A#%o+vZ z5ZSqshMcC+>PnoCf)6L1{CP6;=*z4v2aNS+&k^JE%8XIfs##SYdS@1!=gJ8^vjYC` zt!DN;rb|Ux>CBawQnYN&PMybB+1(1WD=r#xyFx++MOsX)F>HV^)w{s>vD!^DoYfZ`GUJ1M+b1dD!puL zIqRa})yVK^9v7ItC~V{qz3eIExKb-=&a;GtHVmds9&Cw<^9E;5*Q%4Zx_%UHqj zT7#h}^yyy%W*>{iLX3stCWqOXSu-0hxXCzX$2$FIa8TG{H&u12-kG^YtHO4D)tofj z>g-kh$&%ap*JvGW7y8NRz0K#&RHIiDO{TWS8lU4jn!2TLvQ^#ceP>?jIz8Dslljfz znWsMo-fCZZSvPgvdHc0#vU`Qv7l$nhxDsuVdbd4uf%-S?6<1cxYW-WEzA|yfnYUS& zUVmDVCAZs{?{v0vz+1gQjjGr=#yqDt_ngXkWhyn@*KPj0`#qPAEPUznR`g8~wpQR?o z-lA=D#2-#~mlA1S@0~4Mm}ERD^7=~Og+XC2uHJAupSkXJ)XBdMQqeI*^D?q5KAzP# zwWta`otQdt>zQ|L84L{!sTNKGXGIR0tDn&=;0?MzgXhS)e|<^Lca9&Ldg5Q}5?lVr zkhqMjY*A0nz$JIC%qp^ys*~lK$r5g>IoZHwnQ#}cPQlCtE0hu!n5>!8v(;?HRD&N6 zZgx#H61UDjSXO$vQa&&!$5^NHT=LwRIkrj0yrnyiDz5r+PGl8BaQe^r8;|?G&GgwG zym6b?`CCn^_Um&^S-PlsdvEU!BgvpcON%O2ROKmHGOVp-;5rmHP3NJ4=p|RxGzY83 z4K8Y1K7>cykq|B7-O1taa!H{<>bH4km4m20%SP>P7lVLBJn4d*yPcv>{$pC>ICYcd z%m~(n-7nTjvh{xKQ+zd3Qexp^k1oldayvV@6eT(NKhDzFEpe3Z=b=2AT{qXMO8t0I z(%9b7QO1>6Hnn5VVn?Q#2B*FDHgdW%2u{DHv4c}&@vE2f7Qd?2f6f}Tv1Ofi3LiIX zoVe!tg{qSn9X7D;i`4phDEq>#S!3VC6t6Qe z+rq%b;Im#hW30Yd!-6wvb+S_f&bZExOr9!JI(KH*=b&A>M^gE}tUcKzS$yb1;L{vE zGwz#A%c6BI&N<92S+lKY=A6|V}D6K@zyt9>?3NxBTEN)t+Buw;_YE-&1`Q-5x6SLNx zpQ^iJ&La1gE}zb8PovZ`cN7Po4nBFK=){45i3`-0TWna`@r&0+Y`JL;TV_l|Lf+X8 zGV>n)z1mqjk;`SR*j1${?W_%_WL8A9O;FlX70CLcX)1fePRS=z@}*LyG)pc!S)xFfoJuFS6C(N;l37^h_f7h)wme6urS}fKgAmtPw`B=v3T=pADCm+Ek86%(Q z)2hW26qhV;>WJ28yf7h@0i>bbu|lM!%aKE|Mb$Q9QnR`(hhj^IWravfCP+-ci9@jk zOt@NROlnqlp;|qlrey1I?n%7uzD7L7WdIU7HS-y~I zIi#b})pW#Qhgb`XsYXxJ6N3|1nz@}iW;J`7{*Y=(cdQVD*rDR+F`=2w@q|Q+n`6YJ zW;V+mA}yyKS4g#JS#rp?D43*(GE87#Sg=T=Ymo+*fYc@~h7$}70uF&9#|vdnPLw&h zQHGm?HC` z3IhYj0*kJt5nW3&x}JCRakR9pVPa@tU|?Zj5HN8LwsD{0ay}&V`nKHLNGN(*sw7yu z0|SG=rOdRIY#j#7l5F63;9y{A5bQEI(f|wO1_>{|MVxCb@6UO>Ad+vE*G5a(IUZXp zC(Z8KY59Ck@wt=F<`|x{d_HHcYGINAM+!cFwPMdw< zsO9rH{>NV4n&=>rK3)$#LmcG@8);xws1e~?k9tjH0HN6&*{m%0FtmZ9YQQ2#^26<^Nof53W9i@iGe|(MZgJUU66<7F^S?cmM>JM2*A9_!N9;! zAmR>AZ=Rb}yf3Moy`>FH&(2QgIDZaW4XgZUYY}bY%`3s<;;EoW5iN@#95d+snbO;U$nl0~!Gg z3_K?{h@8GC<13_kHApu!Sodm>>($^;LcsU3iLWpRZzLzf1V)Al0>Qev$7XSMt0Y~@ zTD>5dC+N-6jUHO*TeqJwY?as=C)GYBP@sCHN^+Ou8QmopG}YE#3vp@{Su!J8OEict zNWmnfl|f(@k@{Z1_Le2!3!8gz|OHGn-swwh3f`@+qOv?b=|&|G`D@f(?>gHi0ZQ7pdVd zO58cBcSMAM00V=-0|o|x1Vs_4O-c+M!VCo-LMoh-Sk5wgOk?$JUUtxgaZ;+|?k z`*tX~2rlD9=t5?3Ffd3IFfec!EaZW^$)YQjk)h$S#WYq1hQ7xUVhjus(^R_{7!o39 zX}}wF$cB)@Mzv6gp@WH`K%*;_@%Toa2Nu&t6uE_TY5Rf zH?%ZXp=(*@tW~R4t>bp_7x4`ajlEvl_`Gvb=Bibzcj*cEUJeNjEsc$21G#Y3>r+M! zp`lkxW5cI0g0#HewTUMn^m=J*|X28J7r%nUagTLUsqcrhsOGc*{ufhui3r6nTC=PcC)gSrf#&zbCH_-sz` zIZsW=;xm@dmrMaSd4jw^VwRdq!R?+YL0-@26#IE;sw~6%vz@A35kGJCt=|^^*JQyS7}`rb-irj8yXtB zNe3L3uXY)Lg6(=~EF{o&>E%R&LM>Ht+uBvDUhUe%6LY;Z_2#rjo!#r++}gyz@PUP$ zVF8nLn7f6h6t|8^iYlnSbdYGC;KZSrD&WMW*fJ%EgA*nB3o&@GGBEUPyasAeU2{lZ zyA{N0I0NP)h@fnU1Xz|xLU-vDNDB?zOoI@t48KAx7=GB_*kENy1f=Io)qM@_G(0r;mRe~qPo`}OX~5|+;SzV+fYn7$9Lt{8(FJ2N+f4%>28ro z?m5a4pOT}y>{b@M}eg0ZIl-f_f~U%_-({;#e5cWq1tCQk>EQN??`iLGgwx@OJnI05onKT<&r5NR*;j1;?yZY;9iub>XIoz zT#7A0P8DzDk-ZlGBhxNOKgP(1{M}biweYN zVFCBCSzhpfjb{M$u|eWjmG7FfYK53LUD)HYze0TD1^s!qLWKi-SQSE!E-Krd_5MNK zN2X7%(}L8#|NkF&{1J=uRN+~Xc869^dHP6x&wHylqtoscQ#Zx@Y5u`2ry07te|Ih8VPKH!x))`x z+0yc$wjtolwOyWyDlG4r19pJ*BNGlQmU1yT)NrUgdr>OJz_2gVuI;|c{&gyQwqM9I zJA3@Y>?hZ!wtN@6byn1p!)WEoaF!5P4^hz20N9W&i6qlEZHs;1hVf{J^%y1{?F!5` z?cEmbyL{!gt4pekqHHB=yLtB=WxIZGE%WZly@#wWoJ{+mYxct|Y`5Inc|BqN%k~^) zJIb@~=$)!9yX4L;o6J~uEXM5R%Vv%Qrt~wZljqrWFqjpvofZufIpDQ3Ce(w&$>XBK z#)%$>Iu;4G3%V4a z%T_*mIcHAQ`Jw~Dt{=qN)=fY8(!n6EsH#QvPU7@=dwHsVMe42p$Y+$GUu5-n%j>M` a`Fjpes+RKLDQ8=5%wQwV=+!WjmjM8`!D^2H literal 0 HcmV?d00001 diff --git a/src/sound/usePttSounds.ts b/src/sound/usePttSounds.ts new file mode 100644 index 00000000..4084096e --- /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 effe2ad4..cd680f5b 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 17e2b450..0d8f106e 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);