From fb5b17aab48d916d688715d8b6bb1f9fd911a795 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Wed, 7 Oct 2020 00:01:51 +0100 Subject: [PATCH 01/11] Only reload showplan once, don't add multiple listeners. --- src/showplanner/ImporterModal.tsx | 25 +++++++++++++------------ src/showplanner/index.tsx | 28 +++++++++++++++------------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/showplanner/ImporterModal.tsx b/src/showplanner/ImporterModal.tsx index 8d6946d..19583a6 100644 --- a/src/showplanner/ImporterModal.tsx +++ b/src/showplanner/ImporterModal.tsx @@ -14,18 +14,19 @@ export function ImporterModal(props: ImporterProps) { // Add support for closing the modal when the importer wants to reload the show plan. // There is a similar listener in showplanner/index.tsx to actually reload the show plan. useEffect(() => { - window.addEventListener( - "message", - (event) => { - if (!event.origin.includes("ury.org.uk")) { - return; - } - if (event.data === "reload_showplan") { - props.close(); - } - }, - false - ); + function reloadListener(event: MessageEvent) { + if (!event.origin.includes("ury.org.uk")) { + return; + } + if (event.data === "reload_showplan") { + props.close(); + } + } + + window.addEventListener("message", reloadListener); + return () => { + window.removeEventListener("message", reloadListener); + }; }); return ( diff --git a/src/showplanner/index.tsx b/src/showplanner/index.tsx index 426c541..c616426 100644 --- a/src/showplanner/index.tsx +++ b/src/showplanner/index.tsx @@ -374,20 +374,22 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { // Add support for reloading the show plan from the iFrames. // There is a similar listener in showplanner/ImporterModal.tsx to handle closing the iframe. useEffect(() => { - window.addEventListener( - "message", - (event) => { - if (!event.origin.includes("ury.org.uk")) { - return; - } - if (event.data === "reload_showplan") { - session.currentTimeslot !== null && - dispatch(getShowplan(session.currentTimeslot.timeslot_id)); - } - }, - false - ); + function reloadListener(event: MessageEvent) { + if (!event.origin.includes("ury.org.uk")) { + return; + } + if (event.data === "reload_showplan") { + session.currentTimeslot !== null && + dispatch(getShowplan(session.currentTimeslot.timeslot_id)); + } + } + + window.addEventListener("message", reloadListener); + return () => { + window.removeEventListener("message", reloadListener); + }; }); + if (showplan === null) { return ( Date: Wed, 7 Oct 2020 00:12:17 +0100 Subject: [PATCH 02/11] I tried. --- src/showplanner/ImporterModal.tsx | 2 +- src/showplanner/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/showplanner/ImporterModal.tsx b/src/showplanner/ImporterModal.tsx index 19583a6..c16354f 100644 --- a/src/showplanner/ImporterModal.tsx +++ b/src/showplanner/ImporterModal.tsx @@ -27,7 +27,7 @@ export function ImporterModal(props: ImporterProps) { return () => { window.removeEventListener("message", reloadListener); }; - }); + }, [props]); return (
diff --git a/src/showplanner/index.tsx b/src/showplanner/index.tsx index c616426..c591a2c 100644 --- a/src/showplanner/index.tsx +++ b/src/showplanner/index.tsx @@ -388,7 +388,7 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) { return () => { window.removeEventListener("message", reloadListener); }; - }); + }, [dispatch, session.currentTimeslot]); if (showplan === null) { return ( From 9ede742a236644b29461a23c4ee26616c9770a2f Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Mon, 26 Oct 2020 22:04:45 +0000 Subject: [PATCH 03/11] Fixed props. Co-authored-by: Marks Polakovs --- src/showplanner/ImporterModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/showplanner/ImporterModal.tsx b/src/showplanner/ImporterModal.tsx index c16354f..19583a6 100644 --- a/src/showplanner/ImporterModal.tsx +++ b/src/showplanner/ImporterModal.tsx @@ -27,7 +27,7 @@ export function ImporterModal(props: ImporterProps) { return () => { window.removeEventListener("message", reloadListener); }; - }, [props]); + }); return (
From 4e9c57befb136fc3b7c392174fee936627d05e39 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 19:22:21 +0000 Subject: [PATCH 04/11] Fix triggering blinky play. Fixes #120 --- src/showplanner/Player.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/showplanner/Player.tsx b/src/showplanner/Player.tsx index bc463e2..d794ac3 100644 --- a/src/showplanner/Player.tsx +++ b/src/showplanner/Player.tsx @@ -192,9 +192,17 @@ function TimingButtons({ id }: { id: number }) { } export function Player({ id }: { id: number }) { + // Define time remaining (secs) when the play icon should flash. + const SECS_REMAINING_WARNING = 20; + + // We want to force update the selector when we pass the SECS_REMAINING_WARNING barrier. const playerState = useSelector( (state: RootState) => state.mixer.players[id], (a, b) => + !( + a.timeRemaining <= SECS_REMAINING_WARNING && + b.timeRemaining > SECS_REMAINING_WARNING + ) && shallowEqual( omit(a, "timeCurrent", "timeRemaining"), omit(b, "timeCurrent", "timeRemaining") @@ -319,7 +327,7 @@ export function Player({ id }: { id: number }) { onClick={() => dispatch(MixerState.play(id))} className={ playerState.state === "playing" - ? playerState.timeRemaining <= 15 + ? playerState.timeRemaining <= SECS_REMAINING_WARNING ? "sp-state-playing sp-ending-soon" : "sp-state-playing" : "" From 716c3d516e140008374c56d813be7f127fda060e Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 20:40:34 +0000 Subject: [PATCH 05/11] Fix auto advance after timing markers change --- src/mixer/state.ts | 14 +++++++++++--- src/showplanner/Player.tsx | 6 ++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/mixer/state.ts b/src/mixer/state.ts index 9c4cf08..331ca4f 100644 --- a/src/mixer/state.ts +++ b/src/mixer/state.ts @@ -498,7 +498,17 @@ export const load = ( const itsChannel = getState() .showplan.plan!.filter((x) => x.channel === item.channel) .sort((x, y) => x.weight - y.weight); - const itsIndex = itsChannel.indexOf(item); + // Sadly, we can't just do .indexOf() item directly, + // since the player's idea of an item may be changed over it's lifecycle (setting intro/cue/outro etc.) + // Therefore we'll find the updated item from the plan and match that. + const itsChannelItem = itsChannel.filter( + (x) => itemId(x) === itemId(item) + ); + if (itsChannelItem.length !== 1) { + // Somehow we've got 0 or multiple identical timeslotitems (or ghosts), bail out! + return; + } + const itsIndex = itsChannel.indexOf(itsChannelItem[0]); if (itsIndex > -1 && itsIndex !== itsChannel.length - 1) { dispatch(load(player, itsChannel[itsIndex + 1])); } @@ -585,14 +595,12 @@ export const stop = (player: number): AppThunk => (dispatch, getState) => { let cueTime = 0; - console.log(Math.round(playerInstance.currentTime)); if ( state.loadedItem && "cue" in state.loadedItem && Math.round(playerInstance.currentTime) !== Math.round(state.loadedItem.cue) ) { cueTime = state.loadedItem.cue; - console.log(cueTime); } playerInstance.stop(); diff --git a/src/showplanner/Player.tsx b/src/showplanner/Player.tsx index bc463e2..8d09f0d 100644 --- a/src/showplanner/Player.tsx +++ b/src/showplanner/Player.tsx @@ -67,6 +67,8 @@ const setTrackIntro = ( player: number ): AppThunk => async (dispatch, getState) => { try { + // Api only deals with whole seconds. + secs = Math.round(secs); dispatch(MixerState.setLoadedItemIntro(player, secs)); if (getState().settings.saveShowPlanChanges) { await api.setTrackIntro(track.trackid, secs); @@ -84,6 +86,8 @@ const setTrackOutro = ( player: number ): AppThunk => async (dispatch, getState) => { try { + // Api only deals with whole seconds. + secs = Math.round(secs); dispatch(MixerState.setLoadedItemOutro(player, secs)); if (getState().settings.saveShowPlanChanges) { await api.setTrackOutro(track.trackid, secs); @@ -101,6 +105,8 @@ const setTrackCue = ( player: number ): AppThunk => async (dispatch, getState) => { try { + // Api only deals with whole seconds. + secs = Math.round(secs); dispatch(MixerState.setLoadedItemCue(player, secs)); if (getState().settings.saveShowPlanChanges) { await api.setTimeslotItemCue(item.timeslotitemid, secs); From a512f1ac31cbe4d9ef1bb3ec598038720540066a Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 21:43:44 +0000 Subject: [PATCH 06/11] Stop dragging Pro Mode :tm: gain blocking keyboard. --- src/showplanner/ProModeButtons.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/showplanner/ProModeButtons.tsx b/src/showplanner/ProModeButtons.tsx index adadfbf..aad8820 100644 --- a/src/showplanner/ProModeButtons.tsx +++ b/src/showplanner/ProModeButtons.tsx @@ -35,9 +35,10 @@ export default function ProModeButtons({ channel }: { channel: number }) { max={12} step={0.2} value={trimVal.toFixed(1)} - onChange={(e) => - dispatch(setChannelTrim(channel, parseFloat(e.target.value))) - } + onChange={(e) => { + dispatch(setChannelTrim(channel, parseFloat(e.target.value))); + e.target.blur(); // Stop dragging from disabling the keyboard triggers. + }} /> {trimVal} dB From 1390ba1bcdfda9c5ca9d65ea51dfb2e742dcdad8 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 21:46:20 +0000 Subject: [PATCH 07/11] Make pro mode trim button more clickable. Fixes #109 --- src/showplanner/ProModeButtons.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/showplanner/ProModeButtons.tsx b/src/showplanner/ProModeButtons.tsx index aad8820..1303d6a 100644 --- a/src/showplanner/ProModeButtons.tsx +++ b/src/showplanner/ProModeButtons.tsx @@ -18,12 +18,14 @@ export default function ProModeButtons({ channel }: { channel: number }) {
Pro Mode™ {(activeButton === null || activeButton === "trim") && ( - )} {activeButton === "trim" && ( From 500005811c44621cd69718d355d224a427732f5a Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 22:15:44 +0000 Subject: [PATCH 08/11] Fix fader fidgeting volume jumps. Fixes #40 --- src/mixer/audio.ts | 4 ++++ src/mixer/state.ts | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mixer/audio.ts b/src/mixer/audio.ts index 37bbbe2..a29b716 100644 --- a/src/mixer/audio.ts +++ b/src/mixer/audio.ts @@ -125,6 +125,10 @@ class Player extends ((PlayerEmitter as unknown) as { new (): EventEmitter }) { } } + getVolume() { + return this.volume; + } + setVolume(val: number) { this.volume = val; this._applyVolume(); diff --git a/src/mixer/state.ts b/src/mixer/state.ts index 9c4cf08..421e02e 100644 --- a/src/mixer/state.ts +++ b/src/mixer/state.ts @@ -666,7 +666,14 @@ export const setVolume = ( const state = getState().mixer.players[player]; const currentLevel = state.volume; - const currentGain = state.gain; + let currentGain = state.gain; + + // If we can, use the engine's 'real' volume gain. + // This helps when we've interupted a previous fade, so the state gain won't be correct. + if (typeof audioEngine.players[player] !== "undefined") { + currentGain = audioEngine.players[player]!.getVolume(); + } + const volumeTween = new Between(currentLevel, uiLevel) .time(FADE_TIME_SECONDS * 1000) .on("update", (val: number) => { From 75fa42dc831f469c138825eff77dc57ffd50cee1 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 23:43:21 +0000 Subject: [PATCH 09/11] Add total duration for unplayed items. --- src/showplanner/Player.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/showplanner/Player.tsx b/src/showplanner/Player.tsx index bc463e2..dbdcb67 100644 --- a/src/showplanner/Player.tsx +++ b/src/showplanner/Player.tsx @@ -222,11 +222,15 @@ export function Player({ id }: { id: number }) { } }; - var duration: number = 0; + var channel_duration: number = 0; + var channel_unplayed: number = 0; const plan = useSelector((state: RootState) => state.showplan.plan); plan?.forEach((pItem) => { if (pItem.channel === id) { - duration += HHMMTosec(pItem.length); + channel_duration += HHMMTosec(pItem.length); + if (!pItem.played) { + channel_unplayed += HHMMTosec(pItem.length); + } } }); @@ -239,6 +243,10 @@ export function Player({ id }: { id: number }) { } >
+ + Total: {secToHHMM(channel_duration)} - +  Un-played: {secToHHMM(channel_unplayed)} +
Channel Controls -
Total Time: {secToHHMM(duration)}
{proMode && }
From 4b4d96ff757dd5bfab47f00ba723a0b983fbd362 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Tue, 27 Oct 2020 23:53:35 +0000 Subject: [PATCH 10/11] Suggested fixes. --- src/showplanner/Player.tsx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/showplanner/Player.tsx b/src/showplanner/Player.tsx index dbdcb67..8c2f2ac 100644 --- a/src/showplanner/Player.tsx +++ b/src/showplanner/Player.tsx @@ -222,14 +222,14 @@ export function Player({ id }: { id: number }) { } }; - var channel_duration: number = 0; - var channel_unplayed: number = 0; + let channelDuration = 0; + let channelUnplayed = 0; const plan = useSelector((state: RootState) => state.showplan.plan); plan?.forEach((pItem) => { if (pItem.channel === id) { - channel_duration += HHMMTosec(pItem.length); + channelDuration += HHMMTosec(pItem.length); if (!pItem.played) { - channel_unplayed += HHMMTosec(pItem.length); + channelUnplayed += HHMMTosec(pItem.length); } } }); @@ -243,10 +243,14 @@ export function Player({ id }: { id: number }) { } >
- - Total: {secToHHMM(channel_duration)} - -  Un-played: {secToHHMM(channel_unplayed)} - +
+ + Total: {secToHHMM(channelDuration)} + + + Unplayed: {secToHHMM(channelUnplayed)} + +
Channel Controls