adding video slides support!

This commit is contained in:
Reaby committed 2020-06-04 03:04:55 +03:00
1 parent 9cfa332e51
commit b3f860419d
8 files changed
+339 -29

No files matched your search

+9 -1
View File
@@ -23,8 +23,9 @@
"displayTime": "Näytä aika",
"startStream": "Aloita suoratoisto",
"forceReload": "Lataa uudelleen",
"createNew": "Luo Uusi",
"createNew": "Luo Uusi",
"createNewSlide": "Luo uusi dia",
"addVideo": "Lisää Video",
"addWebPage": "Lisää Web-sivu",
"announce": "Ilmoita",
"announceAll": "Ilmoita Kaikille"
@@ -94,6 +95,13 @@
"zoom": "Suurennus",
"duration": "Pituus (sekunneissa), tyhjä on oletusarvo",
"displayTime": "Näytä aika"
},
"addVideo": {
"name": "Name",
"url": "url",
"displayTime": "Näytä aika",
"mute": "Mykistä video",
"loop": "Looppaa video"
},
"tooltip": {
"header": "Lisää otsikko",
+83 -6
View File
@@ -221,10 +221,20 @@ class admin {
}
dispatcher.emit("all.override", data);
} else {
self.screenView.overrideSlide(data.json, data.png, data.duration, data.transition);
self.screenView.overrideSlide(data.json, null, data.duration, data.transition);
}
});
socket.on('admin.overrideVideo', function (data) {
if (data.displayId === null) {
dispatcher.emit("all.override", data);
} else {
self.screenView.overrideSlide(data.json, null, data.json.duration, null);
}
});
socket.on('admin.setBundle', function (data) {
self.screenView.changeBundle(data.bundle);
self.updateDashboard(io);
@@ -288,6 +298,11 @@ class admin {
}
});
socket.on("admin.setStatusMessage", function (message) {
self.getView().serverOptions.statusMessage = message;
self.getView().updateUI();
});
/** edit web links **/
socket.on('admin.editLink', function (data) {
@@ -298,13 +313,8 @@ class admin {
json = bundle.findSlideByUuid(data.fileName);
}
socket.emit("callback.webpage", {bundleData: bundleData, json: json});
});
socket.on("admin.setStatusMessage", function (message) {
self.getView().serverOptions.statusMessage = message;
self.getView().updateUI();
});
socket.on('edit.saveLink', function (data) {
@@ -357,6 +367,73 @@ class admin {
}
});
/** video **/
socket.on('admin.editVideo', function (data) {
let bundle = self.bundleManager.getBundle(data.bundleName);
let bundleData = bundle.getBundleData();
let json = "{}";
if (data.fileName) {
json = bundle.findSlideByUuid(data.fileName);
}
socket.emit("callback.video", {bundleData: bundleData, json: json});
});
socket.on('edit.saveVideo', function (data) {
let filename = data.filename;
if (filename === "") {
filename = uuidv4();
}
if (data.duration === "") {
socket.emit("callback.saveVideo", {erro: "Video duration is not known. Remember to load metadata!"});
return;
}
try {
let bundle = self.bundleManager.getBundle(data.bundleName);
let template = {
uuid: filename,
name: data.name,
duration: data.duration,
enabled: true,
displayTime: data.displayTime,
type: "video",
webUrl: data.url,
mute: data.mute,
loop: data.loop,
index: bundle.allSlides.length,
transition: null
};
let obj = bundle.findSlideByUuid(filename);
if (Object.keys(obj).length === 0 && obj.constructor === Object) {
bundle.allSlides.push(template);
} else {
obj.url = data.url;
obj.name = data.name;
obj.duration = data.duration;
obj.displayTime = data.displayTime;
obj.mute = data.mute;
obj.loop = data.loop;
obj.transition = null;
}
bundle.save();
cli.success("save video link");
socket.emit("callback.saveVideo", {});
self.updateSlides();
} catch (err) {
cli.error(err, "save video link");
socket.emit("callback.saveVideo", {error: err});
}
});
/** edit **/
socket.on('admin.editSlide', function (data) {
+8 -6
View File
@@ -158,7 +158,7 @@ class display {
getSlideData() {
let bundle = this.getBundle();
return {bundleData: bundle.getBundleData(), slides: bundle.allSlides, serverOptions: this.serverOptions};
return { bundleData: bundle.getBundleData(), slides: bundle.allSlides, serverOptions: this.serverOptions };
}
/**
@@ -177,7 +177,7 @@ class display {
toggleBlackout() {
this.serverOptions.blackout = this.serverOptions.blackout === false;
this.io.emit("callback.blackout", {serverOptions: this.serverOptions});
this.io.emit("callback.blackout", { serverOptions: this.serverOptions });
}
/**
@@ -191,7 +191,7 @@ class display {
/**
* @event event:announce
*/
this.dispatcher.emit("announce", {screens: screens, event: event, data: data});
this.dispatcher.emit("announce", { screens: screens, event: event, data: data });
}
/**
@@ -254,18 +254,20 @@ class display {
fs.writeFileSync("./tmp/display_" + this.serverOptions.displayId + ".png", pngData.replace(/^data:image\/png;base64,/, ""), "base64");
}
if (duration && duration >= 5) {
if (duration && duration >= 5 &&
(json.type === "video" && json.loop === false)
) {
this.serverOptions.loop = true;
this.timeoutId = setTimeout(this.mainLoop.bind(this), duration * 1000);
}
this.displayCurrentSlide();
this.serverOptions.transition = _transition;
}
updateUI() {
this.io.emit("callback.updateUI", this.getSlideData());
}
displayCurrentSlide() {
this.announce([this.id, "admin"], "callback.update", this.getSlideData());
}
+8 -1
View File
@@ -192,7 +192,7 @@ $(window).bind("resize", function () {
fixPreview();
});
function createNew() {
function createNewSlide() {
editSlide("", "slide");
}
@@ -200,6 +200,10 @@ function addLink() {
editSlide("", "webpage");
}
function createNewVideo() {
editSlide("", "video");
}
function editSlide(name, type) {
switch (type) {
case "slide":
@@ -208,6 +212,9 @@ function editSlide(name, type) {
case "webpage":
window.open("/admin/edit/link?bundle=" + serverOptions.currentBundle + "&file=" + name + "&displayId=" + displayId, '_blank', 'location=no,height=400,width=600,scrollbars=no,status=no');
break;
case "video":
window.open("/admin/edit/video?bundle=" + serverOptions.currentBundle + "&file=" + name + "&displayId=" + displayId, '_blank', 'location=no,height=600,width=600,scrollbars=no,status=no');
break;
}
}
+46 -14
View File
@@ -73,26 +73,26 @@ $(window).bind("resize", function () {
});
if (isPreview === 0) {
document.addEventListener("keydown", function(e) {
document.addEventListener("keydown", function (e) {
if (e.keyCode == 13) {
toggleFullScreen();
}
}, false);
}
function toggleFullScreen() {
function toggleFullScreen() {
if (isPreview === 0) {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else {
if (document.exitFullscreen) {
document.exitFullscreen();
document.exitFullscreen();
}
}
}
}
function getLayer(offset) {
if (offset === undefined) offset = 0;
@@ -228,13 +228,23 @@ function updateStatusMessage() {
$('#statusMessage').text("");
}
}
function displayVideo(url, loop, mute) {
if (serverOptions.isStreaming) return;
$("#stream").show();
let video = document.getElementById("stream");
video.src = url;
video.loop = loop;
video.volume = mute ? 0.0 : 1.0;
video.load();
video.play();
}
function nextSlide(data) {
serverOptions = data.serverOptions;
bundleData = data.bundleData;
checkTimeDisplay();
updateStatusMessage();
if (serverOptions.isAnnounce) {
if (serverOptions.announceMeta.type === "webPage") {
$("#slider").hide();
@@ -248,6 +258,15 @@ function nextSlide(data) {
displayWebPage(serverOptions.announceMeta.webUrl);
}
if (serverOptions.announceMeta.type === "video") {
if (serverOptions.announceMeta.displayTime) {
$('#time').removeClass('flipOutX').addClass("flipInX");
} else {
$('#time').addClass('flipOutX').removeClass("flipInX");
}
displayVideo(serverOptions.announceMeta.url, serverOptions.announceMeta.loop, serverOptions.announceMeta.mute);
}
if (serverOptions.announceMeta.type === "image") {
$("#" + getWebLayer()).addClass("fadeOut").removeClass("fadeIn");
$("#" + getWebLayer(1)).addClass("fadeOut").removeClass("fadeIn");
@@ -275,11 +294,20 @@ function nextSlide(data) {
switch (serverOptions.currentMeta.type) {
case "webpage":
$("#slider").hide();
let video = document.getElementById("stream");
video.pause();
$("#stream").hide();
$("#" + getWebLayer()).css("transform", "scale(" + serverOptions.currentMeta.zoom + ")");
$("#" + getWebLayer()).addClass("fadeIn").removeClass("fadeOut");
displayWebPage(serverOptions.currentMeta.webUrl);
break;
case "video":
displayVideo(serverOptions.currentMeta.url, serverOptions.currentMeta.loop, serverOptions.currentMeta.mute);
setTimeout(function () {
clearIFrame(getWebLayer());
clearIFrame(getWebLayer(1));
}, 2500);
break;
default:
var transition = serverOptions.transition;
if (serverOptions.currentMeta.transition !== null) {
@@ -288,9 +316,12 @@ function nextSlide(data) {
$("#" + getWebLayer()).addClass("fadeOut").removeClass("fadeIn");
$("#" + getWebLayer(1)).addClass("fadeOut").removeClass("fadeIn");
$("#stream").fadeOut();
$("#slider").show();
window.f.showImageById(serverOptions.currentFile, transition);
setTimeout(function () {
let video = document.getElementById("stream");
video.pause();
clearIFrame(getWebLayer());
clearIFrame(getWebLayer(1));
}, 2500);
@@ -301,6 +332,7 @@ function nextSlide(data) {
setBackground(bundleData.background);
}
function setBackground(background) {
background = encodeURI("/background/" + background);
if (serverOptions.isStreaming) return;
@@ -343,7 +375,7 @@ function checkStream(serverOptions) {
if (serverOptions.isStreaming) {
if (flvjs.isSupported()) {
$("#stream").show();
var videoElement = document.getElementById('stream');
var videoElement = document.getElementById('stream');
flvPlayer = flvjs.createPlayer({
type: 'flv',
url: serverOptions.streamSource
@@ -467,7 +499,7 @@ function checkImages(allSlides) {
getDataUri("/render/" + serverOptions.currentBundle + "/" + allIds[i] + ".png", allIds[i], function (imageId, imageData, image) {
image.id = imageId;
window.f.images.push(image);
// window.f.imageData.push(imageData);
// window.f.imageData.push(imageData);
});
return true;
}
@@ -523,13 +555,13 @@ function clearIFrame(id) {
function getDataUri(url, imageId, callback) {
var image = new Image();
image.onload = function () {
// let canvas = document.createElement('canvas');
// canvas.width = 1920; // or 'width' if you want a special/scaled size
// canvas.height = 1080; // or 'height' if you want a special/scaled size
// canvas.getContext('2d').drawImage(this, 0, 0);
// let canvas = document.createElement('canvas');
// canvas.width = 1920; // or 'width' if you want a special/scaled size
// canvas.height = 1080; // or 'height' if you want a special/scaled size
// canvas.getContext('2d').drawImage(this, 0, 0);
//callback(imageId, canvas.toDataURL('image/png'), this);
callback(imageId, null, this);
// canvas = null;
// canvas = null;
};
image.src = url;
}
+11
View File
@@ -181,6 +181,17 @@ module.exports = function (pluginManager, websocket, dispatcher) {
});
});
router.get('/edit/video', function (req, res, next) {
let bundle = req.query['bundle'];
let file = req.query['file'];
let displayId = req.query['displayId'] || 0;
res.render('admin/video', {
config: config,
bundle: bundle,
displayId: displayId,
file: file
});
});
router.get('/edit/bundleSlides', function (req, res, next) {
var bundle = {};
+3 -1
View File
@@ -81,7 +81,9 @@
{{ t("admin.dashboard.slidesInRotation") }}
</h1>
{% if permission.dashboard.addSlides %}
<button class="ui basic inverted button" onclick="createNew();">{{ t("actions.createNew") }}
<button class="ui basic inverted button" onclick="createNewSlide();">{{ t("actions.createNew") }}
</button>
<button class="ui basic inverted button" onclick="createNewVideo();">{{ t("actions.addVideo") }}
</button>
{% endif %}
{% if permission.dashboard.addWebPage %}
+171
View File
@@ -0,0 +1,171 @@
{% extends 'layout/edit.twig' %}
{% block header %}
<script src="/socket.io/socket.io.js"></script>
<script>
let bundle = "{{ bundle }}";
let file = "{{ file }}";
let displayId = {{ displayId }};
</script>
{% endblock %}
{% block body %}
<div class="ui segment">
<video id="preview" style="width: 300px; display: hidden;"></video>
<form class="ui form">
<div class="field">
<label>{{ t("admin.addVideo.name") }}</label>
<input type="text" id="name" placeholder="Video" required>
</div>
<div class="field">
<label>{{ t("admin.addVideo.url") }}</label>
<div class="ui action input">
<input type="text" id="url" placeholder="http://user:pass@localhost/path/video1.mp4" required onchange="setDisabled();">
<div onclick="loadVideo();" class="ui green button">Load Metadata</div>
</div>
</div>
<div class="field">
<div id="loop" class="ui toggle checkbox">
<input type="checkbox"/>
<label>{{ t("admin.addVideo.loop") }}</label>
</div>
</div>
<div class="field">
<div id="mute" class="ui toggle checkbox">
<input type="checkbox"/>
<label>{{ t("admin.addVideo.mute") }}</label>
</div>
</div>
<div class="field">
<div id="displaytime" class="ui toggle checkbox">
<input type="checkbox"/>
<label>{{ t("admin.addLink.displayTime") }}</label>
</div>
</div>
<div id="save" class="ui disabled green button" onclick="save();">{{ t("actions.save") }}</div>
<div class="ui red basic buttons">
<div onclick="announce({{ displayId }})" class="ui disabled announce button">{{ t("actions.announce") }}</div>
<div class="ui floating dropdown icon disabled announce button" id="dropdownAnnounce">
<i class="dropdown icon"></i>
<div class="menu">
<div onclick="announce(null)" class="item"><i
class="exclamation icon"></i> {{ t("actions.announceAll") }}</div>
</div>
</div>
</div>
<div class="ui basic button" onclick="window.close()">{{ t("actions.cancel") }}</div>
</form>
</div>
<script>
var socket = io.connect("{{ config.serverUrl }}:{{ config.serverListenPort }}/admin-{{ displayId }}");
var videoDuration = 0;
$(function () {
$(".toggle").checkbox();
$("#dropdownAnnounce").dropdown();
});
function loadVideo() {
var video = document.getElementById("preview");
video.src = $('#url').val();
video.onloadedmetadata = function() {
videoDuration = video.duration;
setActive();
};
}
function setActive() {
$(".announce").removeClass("disabled");
$("#save").removeClass("disabled");
}
function setDisabled() {
$(".announce").addClass("disabled");
$("#save").addClass("disabled");
}
function announce(dispId) {
if (videoDuration == 0) {
alert("video duration not set!");
return;
}
var obj = {
json: {
type: "video",
duration: videoDuration,
url: $("#url").val(),
displayTime: $("#displaytime").checkbox('is checked'),
mute: $("#mute").checkbox('is checked'),
loop: $("#loop").checkbox('is checked')
},
displayId: dispId,
transition: null,
};
socket.emit("admin.overrideVideo", obj);
}
function save() {
if (videoDuration == 0) {
alert("video duration not set!");
return;
}
var obj = {
filename: file,
bundleName: bundle,
duration: videoDuration,
name: $("#name").val(),
url: $("#url").val(),
displayTime: $("#displaytime").checkbox('is checked'),
mute: $("#mute").checkbox('is checked'),
loop: $("#loop").checkbox('is checked')
};
socket.emit("edit.saveVideo", obj);
}
socket.on("connect", function () {
socket.emit("admin.editVideo", {bundleName: bundle, fileName: file});
});
socket.on("callback.video", function (data) {
var json = data.json;
$("#name").val(json.name);
$("#url").val(json.url);
if (json.displayTime) {
$("#displaytime").checkbox('set checked', true);
} else {
$("#displaytime").checkbox('set unchecked', false);
}
if (json.mute) {
$("#mute").checkbox('set checked', true);
} else {
$("#mute").checkbox('set unchecked', false);
}
if (json.loop) {
$("#loop").checkbox('set checked', true);
} else {
$("#loop").checkbox('set unchecked', false);
}
});
socket.on("callback.saveVideo", function (data) {
if (!data.err) {
window.close();
} else {
alert(data.err);
}
});
</script>
{% endblock %}