mirror of
https://github.com/UiO-Gaming/infoscreen3.git
synced 2026-11-05 13:56:52 +01:00
adding video slides support!
This commit is contained in:
1 parent
9cfa332e51
commit
b3f860419d
8 files changed
+339
-29
No files matched your search
@@ -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
@@ -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
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in new issue
Block a user