diff --git a/shared b/shared index c7e7d58e..c53faf30 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c7e7d58e8336a6f5d2e8a4fdde0a83cbb2ce7db0 +Subproject commit c53faf30f14bb37cc638e3ee348fd8deb45d6be0 diff --git a/src/extension/companion.ts b/src/extension/companion.ts index bc59ad16..97d93085 100644 --- a/src/extension/companion.ts +++ b/src/extension/companion.ts @@ -2,7 +2,7 @@ import { startPlaylist } from './intermission-player'; import companion from './util/companion'; import { wait } from './util/helpers'; import { get as nodecg } from './util/nodecg'; -import obs, { changeScene } from './util/obs'; +import obs, { canChangeScene, changeScene } from './util/obs'; import { assetsVideos, obsData, streamDeckData, videoPlayer } from './util/replicants'; import { sc } from './util/speedcontrol'; @@ -37,6 +37,7 @@ companion.evt.on('open', (socket) => { }); // Listening for any actions triggered from Companion. +let videoPlayPressedRecently = false; companion.evt.on('action', async (name, value) => { // Controls the nodecg-speedcontrol timer. // Currently the "Stop Timer" state works if there's only 1 team. @@ -114,18 +115,31 @@ companion.evt.on('action', async (name, value) => { // Used to play back a single video in the "Intermission Player" scene, // intended to be used by hosts. } else if (name === 'video_play') { - const val = value as string; - const video = assetsVideos.value.find((v) => v.sum === val); - if (video) { - videoPlayer.value.playlist = [ - { - sum: video.sum, - length: 0, - commercial: false, - }, - ]; - wait(500); // Safety wait - await startPlaylist(); + if (!videoPlayPressedRecently && !videoPlayer.value.playing + && canChangeScene({ scene: config.obs.names.scenes.intermissionPlayer, force: true })) { + videoPlayPressedRecently = true; + setTimeout(() => { videoPlayPressedRecently = false; }, 1000); + const val = value as string; + nodecg().log.debug('[Companion] Message received to play video (sum: %s)', val); + const videos = assetsVideos.value.filter((v) => v.sum === val); + if (videos.length > 1) { + // VIDEO WAS FOUND TWICE, MAKES NO SENSE! + nodecg().log.debug('[Companion] Multiple videos with the same sum found!'); + } else if (!videos.length) { + // VIDEO WAS NOT FOUND + nodecg().log.debug('[Companion] No videos found with that sum!'); + } else { + nodecg().log.debug('[Companion] Video found matching sum: %s', videos[0].name); + videoPlayer.value.playlist = [ + { + sum: videos[0].sum, + length: 0, + commercial: false, + }, + ]; + wait(500); // Safety wait + await startPlaylist(); + } } } }); diff --git a/src/extension/intermission-player.ts b/src/extension/intermission-player.ts index bf4e6030..7303c049 100644 --- a/src/extension/intermission-player.ts +++ b/src/extension/intermission-player.ts @@ -61,7 +61,7 @@ export async function startPlaylist(): Promise { videoPlayer.value.playing = true; // Switch to correct scene depending on if first element has a video or not. if (playlist[0].video) { - await changeScene({ scene: config.obs.names.scenes.intermissionPlayer }); + await changeScene({ scene: config.obs.names.scenes.intermissionPlayer, force: true }); } else { // Does not work if first element is not a video and we're already on the // intermission player scene, but waitForCommercialEnd handles that. @@ -79,7 +79,7 @@ export async function startPlaylist(): Promise { // Return to the intermission scene if there was an issue starting the playlist. await new Promise((res) => { setTimeout(res, 5000); }); // TODO: Should this be commercials scene if available? - await changeScene({ scene: config.obs.names.scenes.intermission }); + await changeScene({ scene: config.obs.names.scenes.intermission, force: true }); } } @@ -144,10 +144,13 @@ videoPlayer.on('change', (newVal, oldVal) => { }); // Used if a user manually switches to the intermission player scene in OBS. -obs.conn.on('TransitionBegin', (data) => { +obs.conn.on('TransitionBegin', async (data) => { if (obs.findScene(config.obs.names.scenes.intermissionPlayer) === data['to-scene'] && !videoPlayer.value.playing) { - startPlaylist(); + await startPlaylist(); + } + if (obs.findScene(config.obs.names.scenes.intermissionPlayer) === data['from-scene']) { + await player.endPlaylistEarly(); } }); diff --git a/src/extension/util/obs.ts b/src/extension/util/obs.ts index 7b37cd4c..afd13eee 100644 --- a/src/extension/util/obs.ts +++ b/src/extension/util/obs.ts @@ -7,6 +7,20 @@ const config = nodecg().bundleConfig.obs; const obs = new OBS(nodecg(), config); let sceneChangeCodeTriggered = 0; +export function canChangeScene( + { scene, force = false }: { scene: string, force?: boolean }, +): boolean { + // Don't change scene if identical, we're currently transitioning, transitioning is disabled, + // or if we triggered a scene change here in the last 2 seconds. + if (sceneChangeCodeTriggered > (Date.now() - 2000) + || obs.isCurrentScene(scene) + || (!force && (obsData.value.transitioning + || obsData.value.disableTransitioning))) { + return false; + } + return true; +} + export async function changeScene( { scene, force = false }: { scene: string, force?: boolean }, ): Promise {