diff --git a/package-lock.json b/package-lock.json index fde328e..6046d14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,9 @@ "license": "CC BY-SA 4.0", "dependencies": { "bonjour": "^3.5.0", - "ejs": "^3.1.5", "lodash": "^4.17.20", "md5": "^2.3.0", - "netmask": "^1.0.6", + "netmask": "^2.0.2", "osc": "^2.4.1", "uuid": "^8.3.2" }, @@ -403,15 +402,11 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" }, - "node_modules/async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -491,6 +486,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -666,7 +662,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -882,20 +879,6 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "node_modules/ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", - "dependencies": { - "jake": "^10.6.1" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/electron": { "version": "15.2.0", "resolved": "https://registry.npmjs.org/electron/-/electron-15.2.0.tgz", @@ -1274,14 +1257,6 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "optional": true }, - "node_modules/filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", - "dependencies": { - "minimatch": "^3.0.4" - } - }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -1803,87 +1778,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "node_modules/jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", - "dependencies": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jake/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/jake/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/jake/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/jake/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/jake/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "engines": { - "node": ">=4" - } - }, - "node_modules/jake/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2025,6 +1919,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2098,9 +1993,9 @@ "dev": true }, "node_modules/netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "engines": { "node": ">= 0.4.0" } @@ -2616,9 +2511,9 @@ "optional": true }, "node_modules/simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "optional": true, "dependencies": { "decompress-response": "^4.2.0", @@ -3240,15 +3135,11 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "base64-js": { "version": "1.5.1", @@ -3313,6 +3204,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3440,7 +3332,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -3613,14 +3506,6 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, - "ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", - "requires": { - "jake": "^10.6.1" - } - }, "electron": { "version": "15.2.0", "resolved": "https://registry.npmjs.org/electron/-/electron-15.2.0.tgz", @@ -3912,14 +3797,6 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "optional": true }, - "filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", - "requires": { - "minimatch": "^3.0.4" - } - }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -4313,68 +4190,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", - "requires": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4498,6 +4313,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4562,9 +4378,9 @@ "dev": true }, "netmask": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", - "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" }, "node-abi": { "version": "2.30.1", @@ -4949,9 +4765,9 @@ "optional": true }, "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", "optional": true, "requires": { "decompress-response": "^4.2.0", diff --git a/plugins/eos/eos.js b/plugins/eos/main.js similarity index 100% rename from plugins/eos/eos.js rename to plugins/eos/main.js diff --git a/plugins/eos/eos.css b/plugins/eos/styles.css similarity index 100% rename from plugins/eos/eos.css rename to plugins/eos/styles.css diff --git a/plugins/eos/eos.html b/plugins/eos/template.ejs similarity index 100% rename from plugins/eos/eos.html rename to plugins/eos/template.ejs diff --git a/plugins/pjlink/pjlink.js b/plugins/pjlink/main.js similarity index 100% rename from plugins/pjlink/pjlink.js rename to plugins/pjlink/main.js diff --git a/plugins/pjlink/pjlink.css b/plugins/pjlink/styles.css similarity index 100% rename from plugins/pjlink/pjlink.css rename to plugins/pjlink/styles.css diff --git a/plugins/pjlink/pjlink.html b/plugins/pjlink/template.ejs similarity index 100% rename from plugins/pjlink/pjlink.html rename to plugins/pjlink/template.ejs diff --git a/plugins/qlab/cue.ejs b/plugins/qlab/cue.ejs index 3ebc644..30bb8f2 100644 --- a/plugins/qlab/cue.ejs +++ b/plugins/qlab/cue.ejs @@ -1,4 +1,5 @@ - +<% let playbackPosition = workspace.playbackPosition==cue.uniqueID ? "playback-position" : "" %> + @@ -9,6 +10,9 @@ <% }else if(cue.running){ %> + <% }else if(cue.paused){ %> + + <% }else if(cue.loaded){ %> @@ -79,7 +83,7 @@ <% if(cue.preWait){ %> - <%= prettyFormatTime(cue.preWait) %> + <%= elapsedTime(cue.preWait, cue.preWaitElapsed, "preWait", cue) %> <% }else{ %> 00:00.00 @@ -87,9 +91,9 @@ <% } %> - - <% if(cue.duration || (cue.type=="Group" && cue.mode==3)){ %> - <%= prettyFormatTime(cue.duration) %> + <% let cueTypesWithAction = ["Audio", "Mic", "Video", "Camera", "Text", "Light", "Fade", "Network", "MIDI File", "Timecode", "Wait"]; %> + <% if((cue.type=="Group" && cue.groupMode==3) || cueTypesWithAction.indexOf(cue.type)>=0){ %> + <%= elapsedTime(cue.duration, cue.actionElapsed, "action", cue) %> <% }else{ %> @@ -99,7 +103,7 @@ <% if(cue.postWait){ %> - <%= prettyFormatTime(cue.postWait) %> + <%= elapsedTime(cue.postWait, cue.postWaitElapsed, "postWait", cue) %> <% }else{ %> 00:00.00 @@ -124,6 +128,9 @@ <% function prettyFormatTime(seconds){ + if(!seconds){ + return "00:00.00"; + } var startIndex = 14; if(seconds>=3600){ startIndex = 11; @@ -131,4 +138,40 @@ var string = new Date(seconds * 1000).toISOString() return string.substring(startIndex, string.length-2) } + + function elapsedTime(def, value, type, cue){ + + if(type=="action" && cue.paused){ + value-=cue.preWait; + } + + let border, fill; + if(cue.paused){ + border = "#f6e737"; + fill = "rgba(255, 240, 60, 0.7)"; + }else{ + border = "#48ba41"; + fill = "rgba(0, 200, 50, 0.5)"; + } + + + if(value>0){ + let percent = value/def*100; + let bg = "background: black; background: linear-gradient(90deg, "+fill+" "+percent+"%, transparent "+percent+"%);"; + + if(cue.paused){ + bg+= "outline-color: "+border+";"; + bg+= "color: white;"; + } + + return "
"+prettyFormatTime(Math.min(def, value))+""; + + }else if(type=="postWait" || type=="action"){ + return ""+prettyFormatTime(def)+""; + + }else{ + return prettyFormatTime(def); + + } + } %> \ No newline at end of file diff --git a/plugins/qlab/cuelist.ejs b/plugins/qlab/cuelist.ejs index 72ca72b..4c85c70 100644 --- a/plugins/qlab/cuelist.ejs +++ b/plugins/qlab/cuelist.ejs @@ -42,7 +42,7 @@ function displayCueRow(q){ let html = ""; - html+= rowTemplate({cue: allCues[q.uniqueID], allCues: allCues}); + html+= rowTemplate({cue: allCues[q.uniqueID], allCues: allCues, workspace: workspace}); if(q.cues){ q.cues.forEach(q =>{ diff --git a/plugins/qlab/qlab.js b/plugins/qlab/main.js similarity index 57% rename from plugins/qlab/qlab.js rename to plugins/qlab/main.js index 3bfcad4..ae638f3 100644 --- a/plugins/qlab/qlab.js +++ b/plugins/qlab/main.js @@ -1,13 +1,19 @@ let _ = require('lodash'); +const fs = require('fs'); + +let lastElapsedUpdate = Date.now(); exports.defaultName = 'QLab 4'; exports.connectionType = 'osc'; +exports.heartbeatInterval = 50; +exports.heartbeatTimeout = 2000; exports.searchOptions = { type: 'Bonjour', bonjourName: 'qlab', }; exports.ready = function (device) { + device.send(`/version`); device.send('/workspaces'); }; @@ -17,16 +23,17 @@ exports.data = function (device, oscData) { osc.shift(); let data; - //console.log(address) - if(match(osc, ["reply", "version"])){ // heartbeat response + if(match(osc, ["reply", "version"])){ + + let json = JSON.parse(oscData.args[0]); + device.data.version = json.data; this.deviceInfoUpdate(device, 'status', 'ok'); - }else if(match(osc, ["reply", "workspaces"])){ let json = JSON.parse(oscData.args[0]); @@ -71,7 +78,9 @@ exports.data = function (device, oscData) { addChildrenToWorkspace(workspace, ql); }); + console.log("total device draw 2"); device.draw(); + setTimeout(function(){ json.data.forEach(ql => { @@ -87,14 +96,16 @@ exports.data = function (device, oscData) { let json = JSON.parse(oscData.args[0]); let workspace = device.data.workspaces[json.workspace_id]; let cue_id = osc[2]; + let cue = workspace.cues[cue_id]; - workspace.cueLists[cue_id].cues = json.data; - addChildrenToWorkspace(workspace, workspace.cueLists[cue_id]); + if(!_.isEqual(cue.cues, json.data)){ + workspace.cueLists[cue_id].cues = json.data; + addChildrenToWorkspace(workspace, workspace.cueLists[cue_id]); - device.draw(); - - getValuesForKeys(device, json.workspace_id, workspace.cues[cue_id]); + device.draw(); + getValuesForKeys(device, json.workspace_id, cue); + } }else if(match(osc, ["reply", "cue_id", "*", "valuesForKeys"])){ @@ -118,6 +129,7 @@ exports.data = function (device, oscData) { cue.running = cueValues.isRunning; cue.loaded = cueValues.isLoaded; cue.flagged = cueValues.isFlagged; + cue.paused = cueValues.isPaused; cue.type = cueValues.type; cue.cues = cueValues.children; cue.preWait = cueValues.preWait; @@ -130,6 +142,9 @@ exports.data = function (device, oscData) { cue.cartRows = cueValues.cartRows; cue.cartColumns = cueValues.cartColumns; cue.cartPosition = cueValues.cartPosition; + cue.preWaitElapsed = cueValues.preWaitElapsed; + cue.actionElapsed = cueValues.actionElapsed; + cue.postWaitElapsed = cueValues.postWaitElapsed; let nestedGroupModes = []; let nestedGroupPosition = [0]; @@ -147,9 +162,46 @@ exports.data = function (device, oscData) { cue.nestedGroupModes = nestedGroupModes; cue.nestedGroupPosition = nestedGroupPosition; + //console.log("draw "+cue.number) + device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + }else if(match(osc, ["reply", "cue_id", "*", "preWaitElapsed"])){ + + let json = JSON.parse(oscData.args[0]); + let workspace = device.data.workspaces[json.workspace_id]; + let cue = workspace.cues[osc[2]]; + + cue.preWaitElapsed = json.data; + lastElapsedUpdate = Date.now(); + + device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + + + }else if(match(osc, ["reply", "cue_id", "*", "actionElapsed"])){ + + let json = JSON.parse(oscData.args[0]); + let workspace = device.data.workspaces[json.workspace_id]; + let cue = workspace.cues[osc[2]]; + + cue.actionElapsed = json.data; + lastElapsedUpdate = Date.now(); + + device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + + + }else if(match(osc, ["reply", "cue_id", "*", "postWaitElapsed"])){ + + let json = JSON.parse(oscData.args[0]); + let workspace = device.data.workspaces[json.workspace_id]; + let cue = workspace.cues[osc[2]]; + + cue.postWaitElapsed = json.data; + lastElapsedUpdate = Date.now(); + + device.update("updateCueData", {cue: cue, allCues: workspace.cues, workspace: workspace}); + }else if(match(osc, ["update", "workspace", "*", "cue_id", "*"])){ @@ -157,17 +209,19 @@ exports.data = function (device, oscData) { let cueLists = Object.keys(workspace.cueLists); let cue_id = osc[4]; - if(cueLists.includes(cue_id)){ - device.send(`/workspace/${workspace.uniqueID}/cue_id/${cue_id}/children`); - } + if(cue_id!="[root group of cue lists"){ + if(cueLists.includes(cue_id)){ + device.send(`/workspace/${workspace.uniqueID}/cue_id/${cue_id}/children`); + } - device.send(`/workspace/${osc[2]}/cue_id/${cue_id}/valuesForKeys`, [ - {type: 's', value: valuesForKeysString} - ]); + device.send(`/workspace/${osc[2]}/cue_id/${cue_id}/valuesForKeys`, [ + {type: 's', value: valuesForKeysString} + ]); + + } }else if(match(osc, ["update", "workspace", "*"])){ - // nothing here yet // occurs when cue lists are reordered or a list is deleted device.send(`/workspace/${osc[2]}/cueLists`); @@ -180,8 +234,11 @@ exports.data = function (device, oscData) { let workspace = device.data.workspaces[osc[2]]; let cue = workspace.cues[oscData.args[0]]; + workspace.playbackPosition = oscData.args[0] ? cue.uniqueID : ""; - if(cue) device.update("updatePlaybackPosition", {cue: cue}); + if(cue){ + device.update("updatePlaybackPosition", {cue: cue}); + } }else{ console.log(address) @@ -191,10 +248,57 @@ exports.data = function (device, oscData) { }; + +let cueTemplate = _.template(fs.readFileSync(`./plugins/qlab/cue.ejs`)); +let tileTemplate = _.template(fs.readFileSync(`./plugins/qlab/tile.ejs`)); +let cartTemplate = _.template(fs.readFileSync(`./plugins/qlab/cart.ejs`)); +let listTemplate = _.template(fs.readFileSync(`./plugins/qlab/cuelist.ejs`)); + +exports.update = function(device, doc, updateType, data){ + + if(updateType=="updateCueData"){ + $elem = doc.getElementById(data.cue.uniqueID); + + if($elem){ + + if(data.cue.type=="Cue List"){ + $elem.outerHTML = '

'+data.cue.name+'

'; + + }else if(data.cue.type=="Cart"){ + $elem.outerHTML = cartTemplate({tileTemplate: tileTemplate, cueList: data.cue, allCues: data.workspace.cues}); + + }else if(data.cue.cartPosition && data.cue.cartPosition[0]!=0){ + $elem.outerHTML = tileTemplate(data); + + }else{ + $elem.outerHTML = cueTemplate(data); + } + } + + }else if(updateType=="updatePlaybackPosition"){ + Array.from(doc.getElementsByClassName("playback-position")).forEach( + function($elem, index, array) { + $elem.classList.remove("playback-position"); + }); + + doc.getElementById(data.cue.uniqueID).classList.add("playback-position"); + + } +} + + + + + + + + + const valuesForKeysString = '["uniqueID","number","name","listName","isBroken","isRunning","isLoaded","isFlagged",' +'"type","children","preWait","postWait","currentDuration","colorName","continueMode",' -+'"mode","parent","cartRows","cartColumns","cartPosition","displayName"]'; ++'"mode","parent","cartRows","cartColumns","cartPosition","displayName","preWaitElapsed",' ++'"actionElapsed","postWaitElapsed","isPaused"]'; function addChildrenToWorkspace(workspace, q){ workspace.cues[q.uniqueID] = q; @@ -234,7 +338,24 @@ function match(osc, array){ return out; } - +let interval = 5; +let heartbeatCount = 0; exports.heartbeat = function (device) { - device.send(`/version`); -}; \ No newline at end of file + heartbeatCount++; + + if(Date.now()-lastElapsedUpdate>300){ + interval = 5; + }else{ + interval = 1; + } + + if(heartbeatCount%interval==0){ + device.send(`/cue/active/preWaitElapsed`); + device.send(`/cue/active/actionElapsed`); + device.send(`/cue/active/postWaitElapsed`); + } + +}; + + + diff --git a/plugins/qlab/qlab.html b/plugins/qlab/qlab.html deleted file mode 100644 index 7e930a3..0000000 --- a/plugins/qlab/qlab.html +++ /dev/null @@ -1,99 +0,0 @@ -
-

<%= listName %>

-

<%= data.version || "" %>

-
- -<% - const fs = require('fs'); - let _ = require('lodash'); - - let cueTemplate = _.template(fs.readFileSync(`./plugins/qlab/cue.ejs`)); - let tileTemplate = _.template(fs.readFileSync(`./plugins/qlab/tile.ejs`)); - let cartTemplate = _.template(fs.readFileSync(`./plugins/qlab/cart.ejs`)); - let listTemplate = _.template(fs.readFileSync(`./plugins/qlab/cuelist.ejs`)); - -%> - - - -<% - for(const workspace_id in data.workspaces){ - const workspace = data.workspaces[workspace_id]; - - for(const cueList_id in workspace.cueLists){ - const ql = workspace.cueLists[cueList_id]; -%> - - - - <% if(ql.type=="Cue List"){ %> - - <%= listTemplate({cueList: ql, allCues: workspace.cues, rowTemplate: cueTemplate}) %> - - <% }else if(ql.type=="Cart"){ %> - - <%= cartTemplate({cueList: ql, allCues: workspace.cues, tileTemplate: tileTemplate}) %> - - - <% } %> - - - -<% }} %> - - - - - - - - - - - - - - - - - diff --git a/plugins/qlab/qlab.css b/plugins/qlab/styles.css similarity index 97% rename from plugins/qlab/qlab.css rename to plugins/qlab/styles.css index ef8da5f..ebab570 100644 --- a/plugins/qlab/qlab.css +++ b/plugins/qlab/styles.css @@ -22,21 +22,21 @@ th.no-border { } td { - padding: 0px; + padding: -1px; height: 25px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } td img { - padding-top: 4px; + padding-top: 2px; } tr:nth-child(even) { - background: #2c2c2c; + background: #323232; } tr:nth-child(odd) { - background: #323232; + background: #2c2c2c; } tr:nth-child(even).q-red { @@ -169,6 +169,14 @@ tr.playback-position .q-gray-text { .q-gray-text { color: #424242; } +.q-time-elapsed { + margin: 0px 2px; + outline: #49c042 1px solid; + line-height: 18px; +} + + + .cart{ position: relative; diff --git a/plugins/qlab/template.ejs b/plugins/qlab/template.ejs new file mode 100644 index 0000000..427cb58 --- /dev/null +++ b/plugins/qlab/template.ejs @@ -0,0 +1,45 @@ +
+

<%= listName %>

+

QLab <%= data.version || "" %>

+
+ +<% + const fs = require('fs'); + let _ = require('lodash'); + + let cueTemplate = _.template(fs.readFileSync(`./plugins/qlab/cue.ejs`)); + let tileTemplate = _.template(fs.readFileSync(`./plugins/qlab/tile.ejs`)); + let cartTemplate = _.template(fs.readFileSync(`./plugins/qlab/cart.ejs`)); + let listTemplate = _.template(fs.readFileSync(`./plugins/qlab/cuelist.ejs`)); + +%> + + + +<% + for(const workspace_id in data.workspaces){ + const workspace = data.workspaces[workspace_id]; + + for(const cueList_id in workspace.cueLists){ + const ql = workspace.cueLists[cueList_id]; +%> + + + + <% if(ql.type=="Cue List"){ %> + + <%= listTemplate({cueList: ql, allCues: workspace.cues, rowTemplate: cueTemplate, workspace: workspace}) %> + + <% }else if(ql.type=="Cart"){ %> + + <%= cartTemplate({cueList: ql, allCues: workspace.cues, tileTemplate: tileTemplate}) %> + + + <% } %> + + + +<% }} %> + + + diff --git a/plugins/watchout/watchout.js b/plugins/watchout/main.js similarity index 100% rename from plugins/watchout/watchout.js rename to plugins/watchout/main.js diff --git a/plugins/watchout/watchout.css b/plugins/watchout/styles.css similarity index 100% rename from plugins/watchout/watchout.css rename to plugins/watchout/styles.css diff --git a/plugins/watchout/watchout.html b/plugins/watchout/template.ejs similarity index 100% rename from plugins/watchout/watchout.html rename to plugins/watchout/template.ejs diff --git a/plugins/x32/x32.js b/plugins/x32/main.js similarity index 100% rename from plugins/x32/x32.js rename to plugins/x32/main.js diff --git a/plugins/x32/x32.css b/plugins/x32/styles.css similarity index 100% rename from plugins/x32/x32.css rename to plugins/x32/styles.css diff --git a/plugins/x32/x32.html b/plugins/x32/template.ejs similarity index 100% rename from plugins/x32/x32.html rename to plugins/x32/template.ejs diff --git a/plugins/xair/xair.js b/plugins/xair/main.js similarity index 100% rename from plugins/xair/xair.js rename to plugins/xair/main.js diff --git a/plugins/xair/xair.css b/plugins/xair/styles.css similarity index 100% rename from plugins/xair/xair.css rename to plugins/xair/styles.css diff --git a/plugins/xair/xair.html b/plugins/xair/template.ejs similarity index 100% rename from plugins/xair/xair.html rename to plugins/xair/template.ejs