diff --git a/app/html/show.html b/app/html/show.html index ff7780c..4afd5af 100644 --- a/app/html/show.html +++ b/app/html/show.html @@ -23,6 +23,8 @@

+ Loop show continuously? +



@@ -44,7 +46,5 @@ - - diff --git a/app/js/ShowRunner.js b/app/js/ShowRunner.js new file mode 100644 index 0000000..5a2a8a8 --- /dev/null +++ b/app/js/ShowRunner.js @@ -0,0 +1,133 @@ +const fs = parent.require('fs'); +const NanoTimer = parent.require('nanotimer'); +const ShowElementConstructor = parent.require('./js/ShowElement.js'); + +function ShowRunner() { + this.canPlay = false; // bool check for if should go to next sequence + this.repeat = false; + this.showElements = []; + this.showLength = 0; +} + +ShowRunner.prototype.setupShowRunner = async function (sequencePathArray) { + // create show elements with sequence json path + for (let i = 0; i < sequencePathArray.length; i += 1) { + this.showElements.push(new ShowElementConstructor()); + this.showElements[i].setSequenceJson(sequencePathArray[i]); + // TODO make this a promise or something, so we can set up all asyncronously + // eslint-disable-next-line no-await-in-loop + const duration = await this.showElements[i].setUpSequence(); + this.showElements[i].setElementLength(duration); + } + + const elementsLength = this.showElements.map(x => x.elementLength); + this.showLength = elementsLength.reduce((total, elementLength) => total + elementLength, 0); +}; + + +ShowRunner.prototype.setCanPlay = function (canPlay) { + this.canPlay = canPlay; +}; + +ShowRunner.prototype.setRepeat = function (repeat) { + this.repeat = repeat; +}; + +ShowRunner.prototype.stopPlaying = function (showElement) { + // only stop audio if there is audio + if (showElement.getAudio()) { + showElement.getAudio().stop(); + } + showElement.getTimer().clearInterval(); +}; + +ShowRunner.prototype.stopAllShowElements = function () { + for (let j = 0; j < this.showElements.length; j += 1) { + this.stopPlaying(this.showElements[j]); + } +}; + +ShowRunner.prototype.update = function (showElement) { + const index = Math.ceil((new Date() - showElement.getStartTime()) / showElement.getInterval()); + parent.parent.universe.update(showElement.getSequenceData()[index]); + if (index > showElement.getSequenceData().length) { // check for end of song + this.stopPlaying(showElement); + } +}; + +ShowRunner.prototype.playSequence = function (showElement) { + if (showElement.audioPath) { + showElement.getAudio().play(); + } + showElement.setTimer(new NanoTimer()); + showElement.setStartTime(new Date()); + showElement.getTimer().setInterval(this.update, [showElement], '20m'); +}; + +ShowRunner.prototype.checkAudioFinish = function (showElement) { + const index = Math.ceil((new Date() - showElement.getStartTime()) / 50); + if (showElement.getElementLength()) { + if (index > showElement.getElementLength()) { // check for end of song + this.stopPlaying(showElement); + } + } +}; + +ShowRunner.prototype.playAudio = function (showElement) { + if (showElement.audioPath) { + showElement.getAudio().play(); + } + parent.parent.universe.updateAll(0); + showElement.setTimer(new NanoTimer()); + showElement.setStartTime(new Date()); + showElement.getTimer().setInterval(this.checkAudioFinish, [showElement], '20m'); +}; + +ShowRunner.prototype.playElement = function (showElement) { + const sequenceJSON = JSON.parse(fs.readFileSync(showElement.getSequenceJson())); + if (sequenceJSON['Sequence Data Json'].length === 0) { + this.playAudio(showElement); + } else { + this.playSequence(showElement); + } +}; + +ShowRunner.prototype.repeatShow = function (showElement) { + +}; + +ShowRunner.prototype.triggerShow = function () { + const i = 1; + this.playElement(this.showElements[0]); + // recursively waits and plays elements of the show + function playSequenceInShow(ind) { + let k = ind; + if (this.canPlay) { + setTimeout(() => { + if (this.canPlay) { + if (k < elements.length) { + this.playElement(this.showElements[k]); + k += 1; + playShowInSequence(k); + } + } + }, this.showElements[k - 1].getElementLength()); + } + } + playSequenceInShow(i); +}; + +ShowRunner.prototype.playShow = async function () { + if (this.repeat && this.canPlay) { + setTimeout(() => { + this.setCanPlay(false); + this.stopAllShowElements(); + this.setCanPlay(true); + this.playShow(this.showElements); + }, this.showLength); + } + + this.triggerShow(); +}; + +module.exports = ShowRunner; diff --git a/app/js/sendDMX.js b/app/js/sendDMX.js deleted file mode 100644 index 8196ec6..0000000 --- a/app/js/sendDMX.js +++ /dev/null @@ -1,86 +0,0 @@ -const fs = parent.require('fs'); -const DMX = parent.require('dmx'); -const NanoTimer = parent.require('nanotimer'); -const { Howl, Howler } = parent.require('howler'); -const Settings = parent.require('./js/settings'); - -let canPlay = false; // bool check for if should go to next sequence - -function startCanPlay() { - canPlay = true; -} - -function stopCanPlay() { - canPlay = false; -} - -function stopPlaying(showElement) { - showElement.getAudio().stop(); - showElement.getTimer().clearInterval(); -} - -function update(showElement) { - const index = Math.ceil((new Date() - showElement.getStartTime()) / showElement.getInterval()); - parent.parent.universe.update(showElement.getSequenceData()[index]); - if (index > showElement.getSequenceData().length) { // check for end of song - stopPlaying(showElement); - } -} - -function playSequence(showElement) { - if (showElement.audioPath) { - showElement.getAudio().play(); - } - showElement.setTimer(new NanoTimer()); - showElement.setStartTime(new Date()); - showElement.getTimer().setInterval(update, [showElement], '20m'); -} - -function checkAudioFinish(showElement) { - const index = Math.ceil((new Date() - showElement.getStartTime()) / 50); - if (showElement.getElementLength()) { - if (index > showElement.getElementLength()) { // check for end of song - stopPlaying(showElement); - } - } -} - -function playAudio(showElement) { - if (showElement.audioPath) { - showElement.getAudio().play(); - } - parent.parent.universe.updateAll(0); - showElement.setTimer(new NanoTimer()); - showElement.setStartTime(new Date()); - showElement.getTimer().setInterval(checkAudioFinish, [showElement], '20m'); -} - -function playElement(showElement) { - const sequenceJSON = JSON.parse(fs.readFileSync(showElement.getSequenceJson())); - if (sequenceJSON['Sequence Data Json'].length === 0) { - playAudio(showElement); - } else { - playSequence(showElement); - } -} - -async function playShow(elements) { - const i = 1; - playElement(elements[0]); - // recursively waits and plays elements of the show - function playShowInSequence(ind) { - let k = ind; - if (canPlay) { - setTimeout(() => { - if (canPlay) { - if (k < elements.length) { - playElement(elements[k]); - k += 1; - playShowInSequence(k); - } - } - }, elements[k - 1].getElementLength()); - } - } - playShowInSequence(i); -} diff --git a/app/js/show.js b/app/js/show.js index 8233d58..ffcc4e2 100644 --- a/app/js/show.js +++ b/app/js/show.js @@ -1,9 +1,9 @@ +const ShowRunnerConstructor = parent.require('./js/ShowRunner.js'); +const ShowRunner = new ShowRunnerConstructor(); + const table = document.getElementById('tableBody'); -table.value = []; const playButton = document.getElementById('runShow'); -const ShowElementConstructor = parent.require('./js/showElement.js'); -let showElements = []; - +const repeat = document.getElementById('repeatPlay'); // directory of the current show contained in the iframe.value attribute const showDir = window.parent.document.getElementById('frame').value; @@ -11,11 +11,11 @@ const showDataPath = path.join(showDir, 'show.json'); // the json file containing the playlist of the show const showData = JSON.parse(fse.readFileSync(showDataPath)); - const playlistElements = showData.Playlist; // push all playlist items (and associated audio if applicable) // names onto table to be rendered for each show +table.value = []; for (let i = 0; i < playlistElements.length; i += 1) { let filename = playlistElements[i].split(path.sep); filename = filename[filename.length - 1]; @@ -45,38 +45,27 @@ for (let i = 0; i < playlistElements.length; i += 1) { table.appendChild(tableItem); } -function stopAllShowElements() { - for (let j = 0; j < showElements.length; j += 1) { - stopPlaying(showElements[j]); - } -} - playButton.onclick = async function () { - // value property contains the boolean isPlaying + ShowRunner.setupShowRunner(table.value); + if (playButton.value === 'notPlaying') { playButton.innerText = 'Stop'; playButton.value = 'playing'; playButton.style.backgroundColor = 'red'; playButton.style.borderColor = 'red'; - // create show elements with sequence json path - showElements = []; - for (let k = 0; k < table.rows.length; k += 1) { - showElements.push(new ShowElementConstructor()); - showElements[k].setSequenceJson(table.value[k]); - // TODO make this a promise or something, so we can set up all asyncronously - // eslint-disable-next-line no-await-in-loop - const duration = await showElements[k].setUpSequence(); - showElements[k].setElementLength(duration * 1000); - } - startCanPlay(); // lock to determine ability to play - playShow(showElements); + + ShowRunner.setCanPlay(true); // lock to determine ability to play + ShowRunner.setRepeat(repeat.checked); + ShowRunner.playShow(); } else { playButton.innerText = 'Play'; playButton.value = 'notPlaying'; playButton.style.backgroundColor = 'green'; playButton.style.borderColor = 'green'; - stopCanPlay(); // lock to stop play of show - stopAllShowElements(); + + ShowRunner.setCanPlay(false); // lock to stop play of show + ShowRunner.stopAllShowElements(); } }; -window.parent.document.getElementById('frame').onload = stopAllShowElements; + +window.parent.document.getElementById('frame').onload = ShowRunner.stopAllShowElements(); diff --git a/app/js/showElement.js b/app/js/showElement.js index 7cf4e2c..e22ddfb 100644 --- a/app/js/showElement.js +++ b/app/js/showElement.js @@ -13,51 +13,67 @@ function ShowElement() { this.audioPath; this.interval; } + ShowElement.prototype.getSequenceJson = function () { return this.sequenceJsonPath; }; + ShowElement.prototype.setSequenceJson = function (sequenceJsonPath) { this.sequenceJsonPath = sequenceJsonPath; }; + ShowElement.prototype.getInterval = function () { return this.interval; }; + ShowElement.prototype.setInterval = function (interval) { this.interval = interval; }; + ShowElement.prototype.getSequenceData = function () { return this.sequenceData; }; + ShowElement.prototype.setSequenceData = function (sequenceData) { this.sequenceData = sequenceData; }; + ShowElement.prototype.getAudio = function () { return this.audio; }; + ShowElement.prototype.setAudio = function (audio) { this.audio = audio; }; + ShowElement.prototype.getTimer = function () { return this.timer; }; + ShowElement.prototype.setTimer = function (timer) { this.timer = timer; }; + ShowElement.prototype.getAudioPath = function () { return this.audioPath; }; + ShowElement.prototype.getStartTime = function () { return this.startTime; }; + ShowElement.prototype.setStartTime = function (startTime) { this.startTime = startTime; }; + ShowElement.prototype.getElementLength = function () { return this.elementLength; }; + ShowElement.prototype.setElementLength = function (elementLength) { this.elementLength = elementLength; }; + ShowElement.prototype.setUpSequence = async function () { const sequenceJSON = JSON.parse(fs.readFileSync(this.sequenceJsonPath)); this.audioPath = sequenceJSON['Audio File']; @@ -70,16 +86,19 @@ ShowElement.prototype.setUpSequence = async function () { const audioTag = new Audio(this.audioPath); return new Promise(((resolve, reject) => { audioTag.addEventListener('durationchange', () => { - resolve(audioTag.duration); + // convert to milliseconds by multiplying by 1000 + resolve(audioTag.duration * 1000); }); })); } // Didn't have an audio path return new Promise((resolve, reject) => { - resolve(0); + // result is in milliseconds + resolve(sequenceJSON['Sequence Length']); }); }; + ShowElement.prototype.getDuration = function (url) { const audioTag = new Audio(url); return new Promise(((resolve, reject) => { @@ -88,4 +107,5 @@ ShowElement.prototype.getDuration = function (url) { }); })); }; + module.exports = ShowElement;