From 20d3236e7363e28fd336d5f39b33fb199de243a7 Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Thu, 11 Mar 2021 22:19:21 +0100 Subject: [PATCH 1/8] Fix audio control box appearance --- front/dist/resources/style/style.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/front/dist/resources/style/style.css b/front/dist/resources/style/style.css index 05ff5a03..fda0c9dd 100644 --- a/front/dist/resources/style/style.css +++ b/front/dist/resources/style/style.css @@ -363,10 +363,14 @@ body { justify-content: center; } +.audioplayer > div { + padding-right: 1.2rem; +} + #audioplayerctrl { position: fixed; top: 0; - right: 50%; + right: calc(50% - 120px); padding: 0.3rem 0.5rem; color: white; transition: transform 0.5s; From 5a7e67f5dfa6407b1c6491883d7387916f8600c1 Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Thu, 11 Mar 2021 22:31:06 +0100 Subject: [PATCH 2/8] Reflect volume change in audio control --- front/src/WebRtc/AudioManager.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/front/src/WebRtc/AudioManager.ts b/front/src/WebRtc/AudioManager.ts index 24fb74a1..735c42c3 100644 --- a/front/src/WebRtc/AudioManager.ts +++ b/front/src/WebRtc/AudioManager.ts @@ -9,6 +9,7 @@ enum audioStates { const audioPlayerDivId = "audioplayer"; const audioPlayerCtrlId = "audioplayerctrl"; +const audioPlayerVolId = "audioplayer_volume"; const animationTime = 500; class AudioManager { @@ -17,6 +18,7 @@ class AudioManager { private audioPlayerDiv: HTMLDivElement; private audioPlayerCtrl: HTMLDivElement; private audioPlayerElem: HTMLAudioElement | undefined; + private audioPlayerVol: HTMLInputElement; private volume = 1; private muted = false; @@ -26,16 +28,17 @@ class AudioManager { constructor() { this.audioPlayerDiv = HtmlUtils.getElementByIdOrFail(audioPlayerDivId); this.audioPlayerCtrl = HtmlUtils.getElementByIdOrFail(audioPlayerCtrlId); + this.audioPlayerVol = HtmlUtils.getElementByIdOrFail(audioPlayerVolId); const storedVolume = localStorage.getItem('volume') if (storedVolume === null) { this.setVolume(1); } else { this.volume = parseFloat(storedVolume); - HtmlUtils.getElementByIdOrFail('audioplayer_volume').value = storedVolume; + this.audioPlayerVol.value = storedVolume; } - HtmlUtils.getElementByIdOrFail('audioplayer_volume').value = '' + this.volume; + this.audioPlayerVol.value = '' + this.volume; } public playAudio(url: string|number|boolean, mapDirUrl: string, loop=false): void { @@ -77,6 +80,7 @@ class AudioManager { private changeVolume(talking = false): void { if (!isUndefined(this.audioPlayerElem)) { this.audioPlayerElem.volume = this.naturalVolume(talking && this.decreaseWhileTalking); + this.audioPlayerVol.value = '' + this.audioPlayerElem.volume; this.audioPlayerElem.muted = this.muted; } } @@ -127,8 +131,7 @@ class AudioManager { } } - const volumeElem = HtmlUtils.getElementByIdOrFail('audioplayer_volume'); - volumeElem.oninput = (ev: Event)=> { + this.audioPlayerVol.oninput = (ev: Event)=> { this.setVolume(parseFloat((ev.currentTarget).value)); this.changeVolume(); From 132c6c9ad666e8b3d5cf176752fc23c4729a30c2 Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Thu, 11 Mar 2021 22:51:42 +0100 Subject: [PATCH 3/8] Fix volume auto-reduction in conversations --- front/dist/index.tmpl.html | 2 +- front/src/WebRtc/AudioManager.ts | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html index eeb8bb5b..3d1b784f 100644 --- a/front/dist/index.tmpl.html +++ b/front/dist/index.tmpl.html @@ -97,7 +97,7 @@
diff --git a/front/src/WebRtc/AudioManager.ts b/front/src/WebRtc/AudioManager.ts index 735c42c3..01d978fe 100644 --- a/front/src/WebRtc/AudioManager.ts +++ b/front/src/WebRtc/AudioManager.ts @@ -78,18 +78,21 @@ class AudioManager { } private changeVolume(talking = false): void { - if (!isUndefined(this.audioPlayerElem)) { - this.audioPlayerElem.volume = this.naturalVolume(talking && this.decreaseWhileTalking); - this.audioPlayerVol.value = '' + this.audioPlayerElem.volume; - this.audioPlayerElem.muted = this.muted; + if (isUndefined(this.audioPlayerElem)) { + return; } - } - private naturalVolume(makeSofter: boolean = false): number { - const volume = this.volume - const retVol = makeSofter && !this.volumeReduced ? Math.pow(volume * 0.5, 3) : volume - this.volumeReduced = makeSofter - return retVol; + const reduceVolume = talking && this.decreaseWhileTalking; + if (reduceVolume && !this.volumeReduced) { + this.volume *= 0.5; + } else if (!reduceVolume && this.volumeReduced) { + this.volume *= 2.0; + } + this.volumeReduced = reduceVolume; + + this.audioPlayerElem.volume = this.volume; + this.audioPlayerVol.value = '' + this.volume; + this.audioPlayerElem.muted = this.muted; } private setVolume(volume: number): void { From fdbcd98a9acc7b89e225c8294a881b00b4892d23 Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Thu, 11 Mar 2021 22:34:49 +0100 Subject: [PATCH 4/8] Implement audio volume and loop properties --- front/src/Phaser/Game/GameScene.ts | 10 +++++++--- front/src/WebRtc/AudioManager.ts | 8 ++++---- front/src/WebRtc/LayoutManager.ts | 3 +++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 512319c6..4a8712ae 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -29,7 +29,9 @@ import { ON_ACTION_TRIGGER_BUTTON, TRIGGER_JITSI_PROPERTIES, TRIGGER_WEBSITE_PROPERTIES, - WEBSITE_MESSAGE_PROPERTIES + WEBSITE_MESSAGE_PROPERTIES, + AUDIO_VOLUME_PROPERTY, + AUDIO_LOOP_PROPERTY } from "../../WebRtc/LayoutManager"; import {GameMap} from "./GameMap"; import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; @@ -661,8 +663,10 @@ export class GameScene extends ResizableScene implements CenterListener { this.connection.setSilent(true); } }); - this.gameMap.onPropertyChange('playAudio', (newValue, oldValue) => { - newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl()); + this.gameMap.onPropertyChange('playAudio', (newValue, oldValue, allProps) => { + const volume = allProps.get(AUDIO_VOLUME_PROPERTY) as number|undefined; + const loop = allProps.get(AUDIO_LOOP_PROPERTY) as boolean|undefined; + newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl(), volume, loop); }); this.gameMap.onPropertyChange('playAudioLoop', (newValue, oldValue) => { diff --git a/front/src/WebRtc/AudioManager.ts b/front/src/WebRtc/AudioManager.ts index 01d978fe..924f1fac 100644 --- a/front/src/WebRtc/AudioManager.ts +++ b/front/src/WebRtc/AudioManager.ts @@ -41,7 +41,7 @@ class AudioManager { this.audioPlayerVol.value = '' + this.volume; } - public playAudio(url: string|number|boolean, mapDirUrl: string, loop=false): void { + public playAudio(url: string|number|boolean, mapDirUrl: string, volume: number|undefined, loop=false): void { const audioPath = url as string; let realAudioPath = ''; @@ -53,7 +53,7 @@ class AudioManager { realAudioPath = mapDirUrl + '/' + url; } - this.loadAudio(realAudioPath); + this.loadAudio(realAudioPath, volume); if (loop) { this.loop(); @@ -100,8 +100,7 @@ class AudioManager { localStorage.setItem('volume', '' + volume); } - - private loadAudio(url: string): void { + private loadAudio(url: string, volume: number|undefined): void { this.load(); /* Solution 1, remove whole audio player */ @@ -119,6 +118,7 @@ class AudioManager { this.audioPlayerElem.append(srcElem); this.audioPlayerDiv.append(this.audioPlayerElem); + this.volume = volume ? Math.min(volume, this.volume) : this.volume; this.changeVolume(); this.audioPlayerElem.play(); diff --git a/front/src/WebRtc/LayoutManager.ts b/front/src/WebRtc/LayoutManager.ts index 91d78798..233b5327 100644 --- a/front/src/WebRtc/LayoutManager.ts +++ b/front/src/WebRtc/LayoutManager.ts @@ -31,6 +31,9 @@ export const TRIGGER_JITSI_PROPERTIES = 'jitsiTrigger'; export const WEBSITE_MESSAGE_PROPERTIES = 'openWebsiteTriggerMessage'; export const JITSI_MESSAGE_PROPERTIES = 'jitsiTriggerMessage'; +export const AUDIO_VOLUME_PROPERTY = 'audioVolume'; +export const AUDIO_LOOP_PROPERTY = 'audioLoop'; + /** * This class is in charge of the video-conference layout. * It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode. From 5bd6f49846addd5b10e80be416b1dcd392267d7c Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Thu, 11 Mar 2021 22:39:45 +0100 Subject: [PATCH 5/8] Fix (now legacy) 'playAudioLoop' property --- front/src/Phaser/Game/GameScene.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 4a8712ae..ba87ba23 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -668,11 +668,10 @@ export class GameScene extends ResizableScene implements CenterListener { const loop = allProps.get(AUDIO_LOOP_PROPERTY) as boolean|undefined; newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl(), volume, loop); }); - + // TODO: This legacy property should be removed at some point this.gameMap.onPropertyChange('playAudioLoop', (newValue, oldValue) => { - newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl()); + newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl(), undefined, true); }); - } private getMapDirUrl(): string { From e6accd711d6160016b67bedd70318cc2d3884a51 Mon Sep 17 00:00:00 2001 From: TabascoEye Date: Fri, 29 Jan 2021 14:42:13 +0100 Subject: [PATCH 6/8] Store muted setting of audio player in local storage This commit was originally authored by @TabascoEye, then rebased and improved by @pizkaz: * refactors local user storage, adding audio player settings * stores "muted" state of audio player in local store --- front/src/Connexion/LocalUserStore.ts | 61 +++++++++++++++++---------- front/src/WebRtc/AudioManager.ts | 27 ++++++------ 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/front/src/Connexion/LocalUserStore.ts b/front/src/Connexion/LocalUserStore.ts index 8ac8c7b2..1e4267de 100644 --- a/front/src/Connexion/LocalUserStore.ts +++ b/front/src/Connexion/LocalUserStore.ts @@ -1,12 +1,15 @@ import {LocalUser} from "./LocalUser"; -const characterLayersKey = 'characterLayers'; -const gameQualityKey = 'gameQuality'; -const videoQualityKey = 'videoQuality'; +const playerNameKey = 'playerName'; +const selectedPlayerKey = 'selectedPlayer'; +const customCursorPositionKey = 'customCursorPosition'; +const characterLayersKey = 'characterLayers'; +const gameQualityKey = 'gameQuality'; +const videoQualityKey = 'videoQuality'; +const audioPlayerVolumeKey = 'audioVolume'; +const audioPlayerMuteKey = 'audioMute'; -//todo: add localstorage fallback class LocalUserStore { - saveUser(localUser: LocalUser) { localStorage.setItem('localUser', JSON.stringify(localUser)); } @@ -14,48 +17,62 @@ class LocalUserStore { const data = localStorage.getItem('localUser'); return data ? JSON.parse(data) : null; } - + setName(name:string): void { - window.localStorage.setItem('playerName', name); + localStorage.setItem(playerNameKey, name); } getName(): string { - return window.localStorage.getItem('playerName') ?? ''; + return localStorage.getItem(playerNameKey) || ''; } setPlayerCharacterIndex(playerCharacterIndex: number): void { - window.localStorage.setItem('selectedPlayer', ''+playerCharacterIndex); + localStorage.setItem(selectedPlayerKey, ''+playerCharacterIndex); } getPlayerCharacterIndex(): number { - return parseInt(window.localStorage.getItem('selectedPlayer') || ''); + return parseInt(localStorage.getItem(selectedPlayerKey) || ''); } setCustomCursorPosition(activeRow:number, selectedLayers: number[]): void { - window.localStorage.setItem('customCursorPosition', JSON.stringify({activeRow, selectedLayers})); + localStorage.setItem(customCursorPositionKey, JSON.stringify({activeRow, selectedLayers})); } getCustomCursorPosition(): {activeRow:number, selectedLayers:number[]}|null { - return JSON.parse(window.localStorage.getItem('customCursorPosition') || "null"); + return JSON.parse(localStorage.getItem(customCursorPositionKey) || "null"); } setCharacterLayers(layers: string[]): void { - window.localStorage.setItem(characterLayersKey, JSON.stringify(layers)); + localStorage.setItem(characterLayersKey, JSON.stringify(layers)); } getCharacterLayers(): string[]|null { - return JSON.parse(window.localStorage.getItem(characterLayersKey) || "null"); - } - - getGameQualityValue(): number { - return parseInt(window.localStorage.getItem(gameQualityKey) || '') || 60; + return JSON.parse(localStorage.getItem(characterLayersKey) || "null"); } + setGameQualityValue(value: number): void { localStorage.setItem(gameQualityKey, '' + value); } - - getVideoQualityValue(): number { - return parseInt(window.localStorage.getItem(videoQualityKey) || '') || 20; + getGameQualityValue(): number { + return parseInt(localStorage.getItem(gameQualityKey) || '60'); } + setVideoQualityValue(value: number): void { localStorage.setItem(videoQualityKey, '' + value); } + getVideoQualityValue(): number { + return parseInt(localStorage.getItem(videoQualityKey) || '20'); + } + + setAudioPlayerVolume(value: number): void { + localStorage.setItem(audioPlayerVolumeKey, '' + value); + } + getAudioPlayerVolume(): number { + return parseFloat(localStorage.getItem(audioPlayerVolumeKey) || '1'); + } + + setAudioPlayerMuted(value: boolean): void { + localStorage.setItem(audioPlayerMuteKey, value.toString()); + } + getAudioPlayerMuted(): boolean { + return localStorage.getItem(audioPlayerMuteKey) === 'true'; + } } -export const localUserStore = new LocalUserStore(); \ No newline at end of file +export const localUserStore = new LocalUserStore(); diff --git a/front/src/WebRtc/AudioManager.ts b/front/src/WebRtc/AudioManager.ts index 924f1fac..60255a77 100644 --- a/front/src/WebRtc/AudioManager.ts +++ b/front/src/WebRtc/AudioManager.ts @@ -1,5 +1,6 @@ import {HtmlUtils} from "./HtmlUtils"; import {isUndefined} from "generic-type-guard"; +import {localUserStore} from "../Connexion/LocalUserStore"; enum audioStates { closed = 0, @@ -10,6 +11,7 @@ enum audioStates { const audioPlayerDivId = "audioplayer"; const audioPlayerCtrlId = "audioplayerctrl"; const audioPlayerVolId = "audioplayer_volume"; +const audioPlayerMuteId = "audioplayer_volume_icon_playing"; const animationTime = 500; class AudioManager { @@ -19,6 +21,7 @@ class AudioManager { private audioPlayerCtrl: HTMLDivElement; private audioPlayerElem: HTMLAudioElement | undefined; private audioPlayerVol: HTMLInputElement; + private audioPlayerMute: HTMLInputElement; private volume = 1; private muted = false; @@ -29,16 +32,15 @@ class AudioManager { this.audioPlayerDiv = HtmlUtils.getElementByIdOrFail(audioPlayerDivId); this.audioPlayerCtrl = HtmlUtils.getElementByIdOrFail(audioPlayerCtrlId); this.audioPlayerVol = HtmlUtils.getElementByIdOrFail(audioPlayerVolId); + this.audioPlayerMute = HtmlUtils.getElementByIdOrFail(audioPlayerMuteId); - const storedVolume = localStorage.getItem('volume') - if (storedVolume === null) { - this.setVolume(1); - } else { - this.volume = parseFloat(storedVolume); - this.audioPlayerVol.value = storedVolume; - } - + this.volume = localUserStore.getAudioPlayerVolume(); this.audioPlayerVol.value = '' + this.volume; + + this.muted = localUserStore.getAudioPlayerMuted(); + if (this.muted) { + this.audioPlayerMute.classList.add('muted'); + } } public playAudio(url: string|number|boolean, mapDirUrl: string, volume: number|undefined, loop=false): void { @@ -97,7 +99,7 @@ class AudioManager { private setVolume(volume: number): void { this.volume = volume; - localStorage.setItem('volume', '' + volume); + localUserStore.setAudioPlayerVolume(volume); } private loadAudio(url: string, volume: number|undefined): void { @@ -123,14 +125,15 @@ class AudioManager { this.audioPlayerElem.play(); const muteElem = HtmlUtils.getElementByIdOrFail('audioplayer_mute'); - muteElem.onclick = (ev: Event)=> { + muteElem.onclick = (ev: Event) => { this.muted = !this.muted; this.changeVolume(); + localUserStore.setAudioPlayerMuted(this.muted); if (this.muted) { - HtmlUtils.getElementByIdOrFail('audioplayer_volume_icon_playing').classList.add('muted'); + this.audioPlayerMute.classList.add('muted'); } else { - HtmlUtils.getElementByIdOrFail('audioplayer_volume_icon_playing').classList.remove('muted'); + this.audioPlayerMute.classList.remove('muted'); } } From 599fdd6ceb80695e32a761c6a40bb6b270ec199b Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Fri, 19 Mar 2021 15:03:55 +0100 Subject: [PATCH 7/8] Fix group icons and audio attenuation --- front/src/Phaser/Game/GameScene.ts | 8 ++++---- front/src/WebRtc/SimplePeer.ts | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index ba87ba23..f350aff7 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -457,16 +457,12 @@ export class GameScene extends ResizableScene implements CenterListener { }); this.connection.onGroupUpdatedOrCreated((groupPositionMessage: GroupCreatedUpdatedMessageInterface) => { - audioManager.decreaseVolume(); this.shareGroupPosition(groupPositionMessage); - this.openChatIcon.setVisible(true); }) this.connection.onGroupDeleted((groupId: number) => { - audioManager.restoreVolume(); try { this.deleteGroup(groupId); - this.openChatIcon.setVisible(false); } catch (e) { console.error(e); } @@ -519,11 +515,15 @@ export class GameScene extends ResizableScene implements CenterListener { onConnect(user: UserSimplePeerInterface) { self.presentationModeSprite.setVisible(true); self.chatModeSprite.setVisible(true); + self.openChatIcon.setVisible(true); + audioManager.decreaseVolume(); }, onDisconnect(userId: number) { if (self.simplePeer.getNbConnections() === 0) { self.presentationModeSprite.setVisible(false); self.chatModeSprite.setVisible(false); + self.openChatIcon.setVisible(false); + audioManager.restoreVolume(); } } }) diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 2baeef11..73a87d14 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -63,7 +63,7 @@ export class SimplePeer { } public getNbConnections(): number { - return this.PeerConnectionArray.size; + return this.Users.length; } /** @@ -230,9 +230,6 @@ export class SimplePeer { this.closeScreenSharingConnection(userId); - for (const peerConnectionListener of this.peerConnectionListeners) { - peerConnectionListener.onDisconnect(userId); - } const userIndex = this.Users.findIndex(user => user.userId === userId); if(userIndex < 0){ throw 'Couln\'t delete user'; @@ -250,6 +247,10 @@ export class SimplePeer { this.PeerScreenSharingConnectionArray.delete(userId); } } + + for (const peerConnectionListener of this.peerConnectionListeners) { + peerConnectionListener.onDisconnect(userId); + } } /** From 821f91e996281252ccb1536b0472ad808bcbcca9 Mon Sep 17 00:00:00 2001 From: PizZaKatZe Date: Tue, 9 Feb 2021 21:00:55 +0100 Subject: [PATCH 8/8] Finer steps for audio volume --- front/dist/index.tmpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html index 3d1b784f..55adcebc 100644 --- a/front/dist/index.tmpl.html +++ b/front/dist/index.tmpl.html @@ -92,7 +92,7 @@
- +