Skip to content

Commit 4a8764f

Browse files
committedOct 10, 2021
Version 2.0 with video projector support! File format changed for songs --> redo songs if you have old datas.
1 parent e341b46 commit 4a8764f

19 files changed

+1467
-1525
lines changed
 

‎README.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
# LoistoTxt
1+
# LoistoTxt 2.0
2+
3+
Notice: Songs data format has been changed since version 1.3.1, app will crash if you attempt to load old files...
4+
25
Song lyrics and lower 3rd titles displayer to obs, vmix or any casting software that supports browser source. Additionally you can remote control whitelisted scenes at OBS (additional plugin required for this).
36
Optionally you can control lights on [QLC+ lightdesk app](https://www.qlcplus.org/).
47

@@ -59,14 +62,23 @@ After app starts, it says something like this:
5962
http://localhost:3000/admin
6063

6164
OBS add new "browser source" and use this address:
62-
http://localhost:3000
65+
http://localhost:3000/video
66+
67+
Projectors use this address:
68+
http://localhost:3000/
6369

6470

6571
Admin interface is without any passwords for now, since well, I don't need such at our production, and you should run this at a private network anyway...
6672

6773
And for OBS, like the console window says, add a new `browser source`, and paste the address there. You might need to click refresh source, if you restart the service, but it should auto connect anyway after you get initial connetion.
6874
See wiki article `getting started` for tutorial.
6975

76+
## Video projectors
77+
78+
A new feature is ability to use video projectors in addition to stream view.
79+
Background can be set to the projectors view with backgrounds-tab.
80+
Placing .jpg, .png, or .mp4 files at `data/backgrounds` folder to load, notice if you run this outside of intranet the file sizes must be optimized. Videos will loop.
81+
7082
## QLC+ integration
7183

7284
To enable qlcplus remote control, you must add `--web` to the shortcut that opens the app.

‎app.js

+2-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ const express = require('express');
33
const path = require('path');
44
const cookieParser = require('cookie-parser');
55
const logger = require('morgan');
6-
const sassMiddleware = require('node-sass-middleware');
76
const indexRouter = require('./routes/index');
87
const fs = require('fs');
98
const app = express();
@@ -18,6 +17,7 @@ console.log("LoistoTxt starting...");
1817
CheckDir("./data");
1918
CheckDir("./data/songs");
2019
CheckDir("./data/shows");
20+
CheckDir("./data/backgrounds");
2121

2222
if (config.obs.enabled) {
2323
connectObs();
@@ -35,14 +35,8 @@ app.use(logger('dev'));
3535
app.use(express.json());
3636
app.use(express.urlencoded({ extended: false }));
3737
app.use(cookieParser());
38-
app.use(sassMiddleware({
39-
src: path.join(__dirname, 'public'),
40-
dest: path.join(__dirname, 'public'),
41-
indentedSyntax: true, // true = .sass and false = .scss
42-
sourceMap: true
43-
}));
4438
app.use(express.static(path.join(__dirname, 'public')));
45-
app.use(express.static(path.join(__dirname, 'data/songs')));
39+
app.use("/background/", express.static(path.join(__dirname, 'data/backgrounds')));
4640
app.use('/', indexRouter);
4741

4842
// catch 404 and forward to error handler

‎bin/websocket.js

+23-6
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ class websocket {
1919
currentText: "",
2020
currentShow: "",
2121
currentSong: "",
22+
currentSlideText: "",
2223
showData: {
2324
name: "",
2425
titles: [],
2526
songs: [],
2627
lights: {},
2728
},
28-
29+
blackout: false,
30+
background: "",
2931
showTitle: false,
3032
titles: {
3133
index: -1,
@@ -34,7 +36,8 @@ class websocket {
3436
title2: "",
3537
sub2: ""
3638
}
37-
}
39+
};
40+
3841
this.qlc = qlc || {};
3942
this.obs = obs || {};
4043
this.io = io;
@@ -83,6 +86,8 @@ class websocket {
8386
/** @var {SocketIO.client} client */
8487
client => {
8588
io.emit("updateAll", self.serverOptions);
89+
io.emit("syncClient", self.serverOptions);
90+
8691
if (config.obs.enabled) {
8792
self.getObsStatus(client);
8893
}
@@ -117,21 +122,33 @@ class websocket {
117122

118123
client.on("showTitles", data => {
119124
self.serverOptions.showTitle = true;
120-
self.serverOptions.currentText = "";
125+
// self.serverOptions.currentText = "";
121126
self.serverOptions.titles = data;
122127
io.emit("update", self.serverOptions);
123128
});
124129

130+
client.on("setBackground", data => {
131+
self.serverOptions.background = data;
132+
io.emit("callback.setBackground", self.serverOptions);
133+
});
134+
135+
client.on("toggleBlackout", data => {
136+
self.serverOptions.blackout = !self.serverOptions.blackout;
137+
io.emit("update", self.serverOptions);
138+
});
139+
140+
125141
client.on("hideTitles", data => {
126142
self.serverOptions.showTitle = false;
127-
self.serverOptions.currentText = "";
143+
// self.serverOptions.currentText = "";
128144
self.serverOptions.titles = {};
129145
io.emit("update", self.serverOptions);
130146
});
131147

132148
client.on("setText", data => {
133149
self.serverOptions.showTitle = false;
134-
self.serverOptions.currentText = data.replace("\n", "<br/>");
150+
self.serverOptions.currentText = data.text.replace("\n", "<br/>");
151+
self.serverOptions.currentSlideText = data.slideText.replace("\n", "<br/>");
135152
io.emit("update", self.serverOptions);
136153
})
137154

@@ -279,7 +296,7 @@ class websocket {
279296
});
280297

281298
client.on("loadSong", file => {
282-
self.serverOptions.currentSong = file;
299+
self.serverOptions.currentSong = file;
283300
io.emit("callback.loadSong", self.getSong(file));
284301
});
285302
});

‎bin/www

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,6 @@ function onListening() {
9494
: 'port ' + addr.port;
9595

9696
console.log('\nAdmin interface now available:\nhttp://' + ip.address() + ":" + addr.port + "/admin\n");
97-
console.log('OBS add new "browser source" and use this address:\nhttp://' + ip.address() + ":" + addr.port + "\n");
98-
97+
console.log('OBS add new "browser source" and use this address:\nhttp://' + ip.address() + ":" + addr.port + "/video\n");
98+
console.log('Projectors use this address:\nhttp://' + ip.address() + ":" + addr.port + "\n");
9999
}

‎package-lock.json

+1,089-1,438
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "loistotxt",
3-
"version": "1.3.1",
3+
"version": "2.0.0",
44
"private": true,
55
"scripts": {
66
"start": "node ./bin/www",
@@ -16,7 +16,6 @@
1616
"ip": "1.1.5",
1717
"lodash": "4.17.21",
1818
"morgan": "1.10.0",
19-
"node-sass-middleware": "0.11.0",
2019
"obs-websocket-js": "4.0.2",
2120
"socket.io": "4.0.0",
2221
"twig": "1.15.4",

‎public/images/empty.png

28.1 KB
Loading

‎public/images/wait.png

44.6 KB
Loading

‎public/javascripts/admin.js

+88-24
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,34 @@ $(function () {
105105
});
106106

107107
$(window).trigger('viewportResize');
108+
109+
$.getJSON("/ajax/backgrounds", (payload, err) => {
110+
let output = "";
111+
let idx = 0;
112+
for(filename of payload.data) {
113+
output += `
114+
<div class="ui left aligned gray message inverted item" id="bg_${idx}" data-bg="${filename}">
115+
<div class="ui content noselect">
116+
<button class="ui small basic inverted icon button" onclick="setBackground('${filename}', this)"><i class="play icon"></i></button>${filename}
117+
</div>
118+
</div>`;
119+
idx+=1;
120+
}
121+
122+
$("#backgrounds").html(output);
123+
});
108124
});
109125

110126
socket.on("update", data => {
111127
serverOptions = data;
112128
renderUI();
113129
});
114130

131+
socket.on("callback.setBackground", data => {
132+
serverOptions = data;
133+
renderUI();
134+
});
135+
115136
socket.on("updateAll", data => {
116137
serverOptions = data;
117138
updateSongs();
@@ -138,7 +159,7 @@ socket.on('obs.scenelist', data => {
138159
color = "";
139160
}
140161
output += `
141-
<div class="ui left aligned gray message inverted item" id=scene_${idx}">
162+
<div class="ui left aligned gray message inverted item" id="scene_${idx}">
142163
<div class="ui content noselect">
143164
<button class="ui small basic inverted icon button" ondblclick="setScene('${scene.name}', this)"><i class="play icon"></i></button> ${scene.name}
144165
</div>
@@ -159,6 +180,14 @@ function renameShow() {
159180
socket.emit("renameShow", $("#showTitle").val());
160181
}
161182

183+
function setBackground(file) {
184+
socket.emit("setBackground", file);
185+
}
186+
187+
function blackout() {
188+
socket.emit("toggleBlackout");
189+
}
190+
162191
function openShow() {
163192
$('.fileAction').text("Open");
164193
$("#dialogFilename").val("");
@@ -217,9 +246,9 @@ function saveShow() {
217246
function importSongs() {
218247
$('#songContent').DataTable().destroy();
219248
$('#songContent').DataTable({
220-
paging: false,
249+
paging: true,
221250
scrollCollapse: true,
222-
pageLength: 25,
251+
pageLength: 20,
223252
lengthChange: false,
224253
info: false,
225254
ajax: '/ajax/songs',
@@ -323,20 +352,44 @@ function updateSong(input) {
323352
texts = [];
324353
currentIdx = -1;
325354
let idx = 0;
355+
let songPart = 0;
326356
for (var data of songData.songData) {
327357
output += `<h3>${data.title}</h3>`;
328-
for (var line of data.texts) {
329-
texts.push(line.replace("\n", "<br>"));
358+
songSection = 0;
359+
let temp = "";
360+
for (var line of data.text.split("\n")) {
361+
temp += line + "<br>";
362+
if (songSection >= 1) {
363+
output += `
364+
<div id="text_${idx}" class="ui inverted gray message item" onclick="sendText(${idx}, ${songPart})">
365+
<div class="content noselect">
366+
${temp}
367+
</div>
368+
</div>
369+
`;
370+
texts.push(temp);
371+
temp = "";
372+
idx++;
373+
songSection = -1;
374+
}
375+
songSection += 1;
376+
}
377+
if (temp != "") {
330378
output += `
331-
<div id="text_${idx}" class="ui inverted gray message item" onclick="sendText(${idx})">
379+
<div id="text_${idx}" class="ui inverted gray message item" onclick="sendText(${idx}, ${songPart})">
332380
<div class="content noselect">
333-
${line.replace("\n", '<br>')}
381+
${temp}
334382
</div>
335-
</div>`;
383+
</div>
384+
385+
`;
336386
idx++;
387+
texts.push(temp);
337388
}
389+
songPart += 1;
338390
}
339391

392+
340393
$('#song').html(output);
341394
if (serverOptions.qlc.enabled) {
342395
let qlcValues = [];
@@ -402,19 +455,19 @@ function removeTitle(id) {
402455
}
403456
}
404457

405-
function sendText(idx) {
458+
function sendText(idx, songSection) {
406459
$("#song .item").each(function () {
407460
$(this).removeClass("active");
408461
});
409462

410463
$("#text_" + idx).addClass("active");
411464
if (idx < 0) {
412465
currentIdx = -1;
413-
socket.emit("setText", "");
466+
socket.emit("setText", {text:"", slideText:""});
414467
}
415468
if (idx >= texts.length) {
416469
currentIdx = texts.length;
417-
socket.emit("setText", "");
470+
socket.emit("setText", {text:"", slideText:""});
418471
}
419472
if (currentIdx == idx) {
420473
clearText();
@@ -423,7 +476,7 @@ function sendText(idx) {
423476
}
424477
if (texts[idx]) {
425478
currentIdx = idx;
426-
socket.emit("setText", texts[idx]);
479+
socket.emit("setText", { text: texts[idx], slideText: songData.songData[songSection].text} );
427480
}
428481
}
429482

@@ -436,23 +489,12 @@ function prevText() {
436489
}
437490

438491
function clearText() {
439-
socket.emit("setText", "");
492+
socket.emit("setText", {text: "", slideText: ""});
440493
$("#song .item").each(function () {
441494
$(this).removeClass("active");
442495
});
443496
}
444497

445-
446-
function sendLine(text) {
447-
if (text) {
448-
socket.emit("setText", text);
449-
$("#song .item").each(function () {
450-
$(this).removeClass("active");
451-
});
452-
}
453-
}
454-
455-
456498
function editSong(filename) {
457499
window.open("/admin/editsong?uuid=" + filename, '_blank', 'location=no,height=720,width=600,status=no');
458500
}
@@ -566,6 +608,28 @@ function renderUI() {
566608
$(elem).addClass("active");
567609
}
568610
});
611+
612+
$("#backgrounds .item").each(function (idx, elem) {
613+
$(elem).removeClass("active")
614+
if (elem.dataset.bg == serverOptions.background) {
615+
$(elem).addClass("active");
616+
}
617+
});
618+
}
619+
620+
function changeSource(url) {
621+
let id = $('#preview').embed("get id");
622+
$('#preview').embed('change', null, id, url);
623+
$("#button-projector").removeClass("green");
624+
$("#button-stream").removeClass("green");
625+
switch (url) {
626+
case "/":
627+
$("#button-projector").addClass("green");
628+
break;
629+
case "/video":
630+
$("#button-stream").addClass("green");
631+
break;
632+
}
569633
}
570634

571635
function switchScene(index) {

‎public/javascripts/editor.js

+6-7
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@ $(() => {
1616
</div>
1717
1818
<div class="verseContent" style="margin-top: 1rem;">
19-
`;
20-
for (let line of elem.texts) {
19+
`;
2120
output += `<div class="ui fluid action input" style="margin-top: 0.5rem;">
2221
<div style="margin-left: 3rem;" class="ui icon button handle"><i class="ui icon move"></i></div>
23-
<textarea rows="1" cols="120" class="textarea" oninput="onEdit(this)" onchange="snap">${line}</textarea>
22+
<textarea cols="120" class="textarea" oninput="onEdit(this)" onchange="snap">${elem.text}</textarea>
2423
<button style="margin-left: 0.25rem;" class="ui red icon button" onclick="removeElem(this);"><i class="ui trash icon"></i></button>
2524
<button style="margin-left: 0.25rem;" class="ui red icon button" onclick="duplicateElem(this);"><i class="clone outline icon"></i></button>
2625
</div>`;
27-
}
26+
2827
output += `</div>`;
2928
output += `<button style="margin-top: 1rem;" class="ui center aligned green icon button" onclick="addText(this);"><i class="ui icon add"></i> Add Text</button>`;
3029
output += `</div></div>`;
@@ -125,9 +124,9 @@ function addText(elem) {
125124

126125
function onEdit(ref) {
127126
let lines = ref.value.split("\n");
128-
if (lines.length >= 2) {
129-
ref.value = lines[0] + "\n" + lines[1];
130-
}
127+
/* if (lines.length >= 2) {
128+
ref.value = lines[0] + "\n" + lines[1];
129+
} */
131130
}
132131

133132

‎public/stylesheets/style.css

Whitespace-only changes.

‎public/stylesheets/style.css.map

-9
This file was deleted.

‎public/stylesheets/style.sass

Whitespace-only changes.

‎public/stylesheets/styles.css

+37-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ body {
77
}
88

99
html {
10-
min-height: 100%;
10+
height: 100%;
1111
}
1212

1313
iframe {
@@ -63,7 +63,8 @@ iframe {
6363
}
6464

6565
.textarea {
66-
resize: none;
66+
resize: auto;
67+
height: 9em;
6768
}
6869

6970
#showDialog .ui.list .item {
@@ -88,3 +89,37 @@ iframe {
8889
#songeditor .red.button {
8990
background: maroon;
9091
}
92+
93+
.helper {
94+
position: absolute;
95+
height: 100%;
96+
width: 100%;
97+
padding: 0;
98+
margin: 0;
99+
display: flex;
100+
align-items: center;
101+
justify-content: center;
102+
z-index: 20;
103+
}
104+
105+
#bgvid, #bg, .fsimage {
106+
position: absolute;
107+
top: 0;
108+
left: 0;
109+
width: 100%;
110+
height: 100%;
111+
}
112+
113+
#bgvid, #bg {
114+
z-index: 0;
115+
}
116+
117+
#blackoutLayer {
118+
position: fixed;
119+
top: 0;
120+
left: 0;
121+
width: 100%;
122+
height: 100%;
123+
z-index: 100;
124+
background: black;
125+
}

‎routes/index.js

+29-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
var express = require('express');
2-
var router = express.Router();
3-
var fs = require('fs');
4-
var config = require('../config.json');
1+
const express = require('express');
2+
const router = express.Router();
3+
const fs = require('fs');
4+
const config = require('../config.json');
5+
let songCache = [];
6+
let bgCache = [];
57

6-
router.get('/', function (req, res, next) {
8+
router.get('/video', function (req, res, next) {
79
let titles = fs.readFileSync("./public/images/titles.svg").toString();
8-
res.render('display', { titles: titles });
10+
res.render('displayVideo', { titles: titles });
11+
});
12+
13+
router.get('/', function (req, res, next) {
14+
res.render('displayProjector');
915
});
1016

1117
router.get('/admin', function (req, res, next) {
@@ -21,14 +27,26 @@ router.get('/admin/editsong', function (req, res, next) {
2127
res.render('editsong', { title: '', song: req.query.uuid || "" });
2228
});
2329

30+
router.get('/ajax/backgrounds', function (req, res, next) {
31+
let bg = fs.readdirSync("./data/backgrounds");
32+
if (bgCache.length != bg.length) {
33+
console.log("Background cache!");
34+
bgCache = bg;
35+
}
36+
res.json({ data: bg });
37+
});
38+
2439
router.get('/ajax/songs', function (req, res, next) {
2540
let songs = fs.readdirSync("./data/songs");
26-
let outData = [];
27-
for (song of songs) {
28-
let info = JSON.parse(fs.readFileSync("./data/songs/" + song).toString());
29-
outData.push({ title: info.title, artist: info.artist, file: song, actions: "" });
41+
if (songCache.length != songs.length) {
42+
console.log("Generating song cache!");
43+
songCache = [];
44+
for (song of songs) {
45+
let info = JSON.parse(fs.readFileSync("./data/songs/" + song).toString());
46+
songCache.push({ title: info.title, artist: info.artist, file: song, actions: "" });
47+
}
3048
}
31-
res.json({ data: outData });
49+
res.json({ data: songCache });
3250
});
3351

3452
router.get('/ajax/shows', function (req, res, next) {

‎views/admin.twig

+17-8
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@
5151
</div>
5252
<div style="width: 1rem;"></div>
5353

54-
<div class="ui buttons">
55-
<button id="blackout" class="ui black basic button" onclick="clearText();">
56-
Clear
57-
</button>
58-
</div>
54+
<button id="blackout" class="ui black basic button" onclick="blackout();">
55+
Blackout
56+
</button>
57+
58+
<button id="clear" class="ui black basic button" onclick="clearText();">
59+
Clear
60+
</button>
5961
</div>
6062
</div>
6163
</div>
@@ -74,6 +76,7 @@
7476
<div id="tab" class="ui top attached inverted tabular menu">
7577
<a class="item active" data-tab="first">Songs</a>
7678
<a class="item" data-tab="second">Lyrics</a>
79+
<a class="item" data-tab="backgrounds">Backgrounds</a>
7780
<a class="item" data-tab="third">Titles</a>
7881
{% if config.qlc.enabled %}
7982
<a class="item" data-tab="fourth">Lights</a>
@@ -87,6 +90,10 @@
8790
<!-- LYRICS -->
8891
<div id="song" class="ui list"></div>
8992
</div>
93+
<div class="ui bottom attached inverted tab segment" data-tab="backgrounds">
94+
<!-- BACKGROUNDS -->
95+
<div id="backgrounds" class="ui list"></div>
96+
</div>
9097
<div class="ui bottom attached inverted tab segment" data-tab="third">
9198
<h1 class="ui header">Titles</h1>
9299

@@ -107,8 +114,10 @@
107114
</div>
108115
<div class="ui six wide column">
109116
<div class="row">
110-
<div class="ui inverted basic segment" style="overflow-y: none">
111-
<div id="preview" data-url="/" class="ui 16:9 embed" style="background: gray; border: 1px solid black;">
117+
<div class="ui inverted basic segment" style="overflow-y: none">
118+
<div id="preview" data-url="/" class="ui 16:9 embed" style="background: gray; border: 1px solid black;"></div>
119+
<div style="text-align: center;">
120+
<button id="button-projector" class="ui small green button" onclick="changeSource('/');">Projector</button><button id="button-stream" class="ui small button" onclick="changeSource('/video');" >Stream overlay</button>
112121
</div>
113122
</div>
114123
</div>
@@ -119,7 +128,7 @@
119128
</div>
120129

121130
<!-- file dialog -->
122-
<div id="showDialog" class="ui modal">
131+
<div id="showDialog" class="ui fullscreen modal">
123132
<i class="close icon"></i>
124133
<div class="header">
125134
<span class="fileAction">Open</span>

‎views/displayProjector.twig

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
{% extends 'layout/plain.twig' %}
2+
3+
{% block head %}
4+
<style>
5+
html,
6+
body {
7+
background: none;
8+
overflow: hidden;
9+
background: #000;
10+
}
11+
12+
.helper h1 {
13+
padding: 0;
14+
margin: 0;
15+
font-size: 4vw;
16+
text-align: center;
17+
color: white;
18+
font-family: "Arial";
19+
font-weight: 700;
20+
text-shadow: -1px -1px 3px #000, 1px -1px 3px #000, -1px 1px 3px #000, 1px 1px 3px #000;
21+
width: 100%;
22+
height: max-content;
23+
text-transform: uppercase;
24+
}
25+
26+
.fix {
27+
animation-duration: 2s;
28+
}
29+
30+
#titles {
31+
width: 100%;
32+
height: 100%;
33+
position: absolute;
34+
z-index: 10;
35+
top: 0;
36+
left: 0;
37+
overflow: hidden;
38+
display: none;
39+
}
40+
</style>
41+
{% endblock %}
42+
43+
{% block body %}
44+
<div id="blackoutLayer" class="animated fix"></div>
45+
46+
<div class="helper">
47+
<h1 id="text0"></h1>
48+
<h1 id="text1"></h1>
49+
</div>
50+
51+
<div id="bg">
52+
<img id="bgimg" class="fsimage" src="/images/empty.png"/>
53+
</div>
54+
55+
<video loop autoplay id="bgvid" class="fsimage" poster="">
56+
</video>
57+
58+
<script src="/socket.io/socket.io.js"></script>
59+
<script>
60+
var socket = io.connect();
61+
var serverOptions = {};
62+
var index = 0;
63+
let currentText = "";
64+
65+
socket.on("update", data => {
66+
serverOptions = data;
67+
renderUI()
68+
});
69+
70+
socket.on("syncClient", data => {
71+
serverOptions = data;
72+
renderUI()
73+
});
74+
75+
socket.on("callback.setBackground", data => {
76+
serverOptions = data;
77+
checkBlackout();
78+
setBackground(serverOptions.background);
79+
});
80+
81+
function checkBlackout() {
82+
if (serverOptions.blackout) {
83+
$("#blackoutLayer").fadeIn();
84+
} else {
85+
$("#blackoutLayer").fadeOut();
86+
}
87+
}
88+
89+
function renderUI() {
90+
checkBlackout();
91+
if (serverOptions.currentSlideText != currentText) {
92+
currentText = serverOptions.currentSlideText;
93+
$("#text" + (index % 2)).fadeOut();
94+
index++;
95+
setTimeout(() => {
96+
$("#text" + (index % 2)).html(serverOptions.currentSlideText.replaceAll("\n", "<br>")).fadeIn();
97+
}, 500);
98+
}
99+
setBackground(serverOptions.background);
100+
}
101+
102+
function setBackground(background) {
103+
var video = document.getElementById("bgvid");
104+
var bg = $("#bg");
105+
var bgImage = document.getElementById("bgimg");
106+
107+
if (background == "") {
108+
video.pause();
109+
video.removeAttribute("src");
110+
video.load();
111+
$(video).hide();
112+
bg.fadeIn();
113+
114+
bgImage.src = "/images/empty.png";
115+
return;
116+
}
117+
background = "/background/" + background;
118+
if (background.indexOf(".mp4") !== -1) {
119+
if (parseUrl(video.src) !== background) {
120+
bg.fadeOut();
121+
video.src = background;
122+
video.load();
123+
video.play();
124+
$(video).show();
125+
}
126+
} else {
127+
if (parseUrl(bgImage.src) !== background) {
128+
bgImage.src = background;
129+
bg.fadeIn();
130+
// unload video
131+
video.pause();
132+
video.removeAttribute("src");
133+
video.load();
134+
$(video).hide();
135+
}
136+
}
137+
}
138+
139+
function parseUrl(url) {
140+
return '/background' + url.split('background')[1]
141+
}
142+
143+
</script>
144+
{% endblock %}

‎views/display.twig ‎views/displayVideo.twig

+14-6
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121
text-shadow: -1px -1px 2px #000, 1px -1px 2px #000, -1px 1px 2px #000, 1px 1px 2px #000;
2222
}
2323
24-
.helper {
24+
.helper {
2525
position: absolute;
2626
bottom: 10%;
2727
text-align: center;
28+
height: auto !important;
2829
width: 100%;
2930
}
3031
@@ -69,13 +70,20 @@
6970
var serverOptions = {};
7071
var oldTitleStatus = false;
7172
var index = 0;
73+
74+
socket.on("syncClient", data => {
75+
oldTitleStatus = serverOptions.showTitle;
76+
serverOptions = data;
77+
index++;
78+
renderView();
79+
});
7280
7381
socket.on("update", data => {
74-
oldTitleStatus = serverOptions.showTitle;
75-
serverOptions = data;
76-
$("#text" + (index % 2)).fadeOut();
77-
index++;
78-
renderView();
82+
oldTitleStatus = serverOptions.showTitle;
83+
serverOptions = data;
84+
$("#text" + (index % 2)).fadeOut();
85+
index++;
86+
renderView();
7987
});
8088
8189
function renderView() {

‎views/layout/plain.twig

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<script src="/javascripts/jquery.min.js"></script>
66
<link rel='stylesheet' href='/semantic/semantic.min.css'/>
77
<link rel="stylesheet" href="/stylesheets/animate.css"/>
8+
<link rel="stylesheet" href="/stylesheets/styles.css"/>
89
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>
910
{% block head %}{% endblock %}
1011
</head>

0 commit comments

Comments
 (0)
Please sign in to comment.