diff --git a/app.js b/app.js index f65a20d..35a04fb 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,8 @@ let logger = require('morgan'); let lessMiddleware = require('less-middleware'); let path = require('path'); +require('./modules/profiler.js').init("./tmp"); + const EventEmitter = require('events'); let config = require("./config.js"); @@ -25,9 +27,7 @@ let LocalStrategy = require('passport-local').Strategy; let User = require("./modules/db.js"); passport.use("local", new LocalStrategy( - { - - }, + {}, function (username, password, cb) { User.findByUsername(username, function (err, user) { if (err) { @@ -64,13 +64,15 @@ if (config.mediaServer) { nms.run(); } -passport.serializeUser(function(user, cb) { +passport.serializeUser(function (user, cb) { cb(null, user.id); }); -passport.deserializeUser(function(id, cb) { +passport.deserializeUser(function (id, cb) { User.findById(id, function (err, user) { - if (err) { return cb(err); } + if (err) { + return cb(err); + } cb(null, user); }); }); @@ -103,9 +105,9 @@ i18next caches: false, // ['cookie'] // optional expire and domain for set cookie - // cookieExpirationDate: new Date(), - // cookieDomain: 'myDomain', - // cookieSecure: true // if need secure cookie + // cookieExpirationDate: new Date(), + // cookieDomain: 'myDomain', + // cookieSecure: true // if need secure cookie } }); @@ -120,7 +122,7 @@ app.use(express.urlencoded({extended: false})); app.use(cookieParser()); app.use(lessMiddleware(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, 'public'))); -app.use(require('express-session')({ secret: config.sessionKey, resave: false, saveUninitialized: true })); +app.use(require('express-session')({secret: config.sessionKey, resave: false, saveUninitialized: true})); // Initialize Passport and restore authentication state, if any, from the // session. diff --git a/data/bundles/default/bundle.json b/data/bundles/default/bundle.json index 8df663a..778b2b6 100644 --- a/data/bundles/default/bundle.json +++ b/data/bundles/default/bundle.json @@ -1,7 +1,7 @@ { "displayName": "default", "background": "bg.jpg", - "duration": 30, + "duration": 15, "transition": "tiles3d", "useWebFonts": false, "displayTime": true, diff --git a/modules/admin.js b/modules/admin.js index 08ab749..41aa27c 100644 --- a/modules/admin.js +++ b/modules/admin.js @@ -56,11 +56,10 @@ class admin { dispatcher.on("updateBundles", function () { io.emit("callback.dashboard.updateBundles", { - "bundleDirs": self.bundleManager.getBundleInfos() + "bundleDirs": bundleManager.getBundleInfos() }); }); - io.on("connection", function (socket) { cli.success("WS " + socket.conn.remoteAddress + " connect with id:" + socket.id); @@ -143,14 +142,13 @@ class admin { } view.io.emit("callback.load", view.getSlideData()); self.updateDashboard(io); + + view = null; + serverOptions = null; }); - socket.on('controls.blackout', function () { - let view = self.getView(); - view.serverOptions.blackout = view.serverOptions.blackout === false; - - view.io.emit("callback.blackout", {serverOptions: view.serverOptions}); + self.screenView.toggleBlackout(); self.updateDashboard(io); }); @@ -173,23 +171,23 @@ class admin { } catch (err) { cli.error("preview instance not found"); } - + bundle = null; }); socket.on("controls.skipTo", function (data) { - let bundleSettings = self.getView().getBundle(); + let bundleSettings = self.screenView.getBundle(); let slides = bundleSettings.enabledSlides; let idx = slides.indexOf(data.fileName); if (idx >= 0) { self.getServerOptions().loopIndex = idx; } - self.getView().mainLoop(); + self.screenView.mainLoop(); }); socket.on('controls.toggle', function (data) { let fileName = data.fileName; - let bundleSettings = self.getView().getBundle(); + let bundleSettings = self.screenView.getBundle(); let idx = bundleSettings.disabledSlides.indexOf(fileName); if (idx > -1) { @@ -197,8 +195,8 @@ class admin { } else { bundleSettings.setSlideStatus(fileName, false); } - self.updateDashboard(socket); + bundleSettings = null; }); // announce @@ -210,8 +208,7 @@ class admin { } dispatcher.emit("all.override", data); } else { - let view = self.getView(); - view.overrideSlide(data.json, data.png, data.duration, data.transition); + self.screenView.overrideSlide(data.json, data.png, data.duration, data.transition); } } catch (err) { cli.error("error, admin.override", err); @@ -225,16 +222,12 @@ class admin { } dispatcher.emit("all.override", data); } else { - let view = self.getView(); - view.overrideSlide(data.json, data.png, data.duration, data.transition); + self.screenView.overrideSlide(data.json, data.png, data.duration, data.transition); } - }); socket.on('admin.setBundle', function (data) { - let view = self.getView(); - view.changeBundle(data.bundle); - view.displayCurrentSlide(); + self.screenView.changeBundle(data.bundle); self.updateDashboard(io); }); @@ -253,27 +246,9 @@ class admin { socket.on('admin.reorderSlides', function (data) { - let bundle = bundleManager.getBundle(data.bundleName); - - let i = 0; - for (let uuid of data.sortedIDs) { - bundle.setIndex(uuid, i); - i += 1; - } - - // calculate next slide order for all displays which has the bundle selected - let display = screenView; - if (display.serverOptions.currentBundle === data.bundleName) { - for (let slide of bundle.allSlides) { - // calculate new index for next slide; - if (slide.uuid === display.serverOptions.currentFile) { - display.serverOptions.loopIndex = slide.index + 1; - } - } - } - - bundle.save(); - self.updateSlides(io, bundle.name, bundle); + bundleManager.reorderSlides(data.bundleName, data.sortedIDs); + dispatcher.emit("display.recalcBundleData", data.bundleName); + self.updateSlides(); }); /** remove slide **/ @@ -281,7 +256,7 @@ class admin { try { let bundle = bundleManager.getBundle(data.bundleName); bundle.removeUuid(data.uuid); - self.updateSlides(io, bundle.name, bundle); + self.updateSlides(); self.announce(null, "callback.removeSlide", data); } catch (err) { cli.error("error while removing slide", err); @@ -290,8 +265,6 @@ class admin { socket.on("admin.createBundle", function (data) { - cli.info("@ create Bundle"); - try { if (!fs.existsSync("data/bundles" + data.dir)) { fs.mkdirSync("data/bundles/" + data.dir); @@ -372,7 +345,7 @@ class admin { cli.success("save web link"); socket.emit("callback.saveLink", {}); - self.updateSlides(io, data.bundleName, bundle); + self.updateSlides(); } catch (err) { cli.error(err, "save web link"); @@ -402,7 +375,7 @@ class admin { try { let bundle = bundleManager.getBundle(data.bundleName); bundle.setName(data.uuid, data.name); - self.updateSlides(io, data.bundleName, bundle); + self.updateSlides(); } catch (err) { cli.error("error while renaming slide", err); } @@ -482,8 +455,8 @@ class admin { bundleName: data.bundleName, uuid: filename }); - self.updateSlides(io, data.bundleName, bundle); - + self.updateSlides(); + self.dispatcher.emit("lobbyUpdate"); } catch (err) { cli.error(err, "save new slide date"); socket.emit("callback.save", {error: err}); @@ -521,7 +494,6 @@ class admin { socket.emit("callback.edit.updateFileList", {error: err}); } }); - }); // io } @@ -531,19 +503,21 @@ class admin { * @param {object} socket */ updateDashboard(socket) { - let view = this.getView(); - let serverOptions = view.serverOptions; - let bundleSettings = view.getBundle(); + let bundleSettings = this.screenView.getBundle(); socket.emit("callback.dashboard.update", { bundleSettings: bundleSettings, allSlides: bundleSettings.allSlides, - serverOptions: serverOptions, + serverOptions: this.screenView.serverOptions, displayId: this.displayId }); - this.dispatcher.emit("dashboard.update", {displayId: this.displayId, serverOptions: serverOptions}); + this.dispatcher.emit("dashboard.update", { + displayId: this.displayId, + serverOptions: this.screenView.serverOptions + }); + bundleSettings = null; } /** helper function to call announce easier **/ @@ -551,23 +525,21 @@ class admin { this.dispatcher.emit("announce", {screens: screens, event: event, data: data}); } - updateSlides(socket, bundlename, bundle) { - socket.emit("callback.dashboard.updateSlides", { - bundleName: bundlename, - bundleSettings: bundle + updateSlides() { + let bundleName = this.getServerOptions().currentBundle; + let bundle = this.getView().getBundle(); + this.io.emit("callback.dashboard.updateSlides", { + bundleName: bundleName, + bundleSettings: bundle, }); } syncDashboard(socket) { this.previewInstances.push({adminId: socket.id, preview: {}, currentView: {}}); - let serverOptions = this.getView().serverOptions; - let bundleDirs = this.bundleManager.getBundleInfos(); - - socket.emit("callback.dashboard.sync", { displayId: this.displayId, - bundleDirs: bundleDirs, - serverOptions: serverOptions, + bundleDirs: this.bundleManager.getBundleInfos(), + serverOptions: this.screenView.serverOptions, displays: config.displays }); } @@ -585,7 +557,7 @@ class admin { * @return infoscreen3/display.serverOptions */ getServerOptions() { - return this.getView().serverOptions; + return this.screenView.serverOptions; } /** @@ -597,28 +569,29 @@ class admin { controls(action) { + let view = this.getView(); switch (action) { case "previous": - let view = this.getView(); view.serverOptions.loopIndex -= 2; view.mainLoop(); break; case "play": - this.getServerOptions().loop = true; - this.getView().mainLoop(); + view.serverOptions.loop = true; + view.mainLoop(); this.updateDashboard(this.io); break; case "pause": - this.getView().clearTimers(); - this.getServerOptions().loop = false; + view.clearTimers(); + view.serverOptions.loop = false; this.updateDashboard(this.io); break; case "next": - this.getView().mainLoop(); + view.mainLoop(); break; } + view = null; + } - } // // admin } diff --git a/modules/adminLobby.js b/modules/adminLobby.js new file mode 100644 index 0000000..b84bae0 --- /dev/null +++ b/modules/adminLobby.js @@ -0,0 +1,126 @@ +let cli = require(`./cli.js`); + +class adminLobby { + + /** + * @param sharedIO + * @param dispatcher + * @param screenView + * @param adminView + * @param bundleManager + */ + constructor(sharedIO, dispatcher, screenView, adminView, bundleManager) { + let io = sharedIO.of("/admin"); + this.io = io; + this.dispatcher = dispatcher; + this.screenView = screenView; + this.adminView = adminView; + this.bundleManager = bundleManager; + let self = this; + + // create overview admin lobby + io.on("connection", function (socket) { + + let arr = []; + for (let display of screenView) { + arr.push({displayId: display.serverOptions.displayId, serverOptions: display.serverOptions}); + } + socket.emit("callback.serverOptions", arr); + + // handle other events + cli.info("WS/" + socket.conn.remoteAddress + " connect"); + socket.on('error', function (error) { + cli.error(error, "WS/ error"); + }); + socket.on('disconnect', function (reason) { + cli.info("WS/ " + reason + " " + socket.conn.remoteAddress); + }); + + socket.on('admin.reorderSlides', function (data) { + bundleManager.reorderSlides(data.bundleName, data.sortedIDs); + dispatcher.emit("display.recalcBundleData", data.bundleName); + let bundle = bundleManager.getBundle(data.bundleName); + updateSlides(data.bundleName, bundle); + }); + + socket.on('admin.removeSlide', function (data) { + try { + let bundle = bundleManager.getBundle(data.bundleName); + bundle.removeUuid(data.uuid); + updateSlides(data.bundleName, bundle); + self.announce(null, "callback.removeSlide", data); + } catch (err) { + cli.error("error while removing slide", err); + } + }); + + /** rename **/ + socket.on('admin.renameSlide', function (data) { + try { + let bundle = bundleManager.getBundle(data.bundleName); + bundle.setName(data.uuid, data.name); + updateSlides(data.bundleName, bundle); + } catch (err) { + cli.error("error while renaming slide", err); + } + }); + + + socket.on('controls.previous', function (data) { + getAdminView(data.displayId).controls("previous"); + }); + + socket.on('controls.play', function (data) { + getAdminView(data.displayId).controls("play"); + }); + + socket.on('controls.next', function (data) { + getAdminView(data.displayId).controls("next"); + }); + + socket.on('controls.pause', function (data) { + getAdminView(data.displayId).controls("pause"); + }); + + dispatcher.on("dashboard.update", function (data) { + socket.emit("callback.serverOptions", [data]); + }); + + }); + + function updateSlides(bundleName, bundleData) { + for (let aView of adminView) { + aView.updateSlides(); + } + // update admin lobby + io.emit("callback.dashboard.updateSlides", { + bundleName: bundleName, + bundleSettings: bundleData + }); + } + + /** + * @return admin + */ + function getAdminView(index) { + try { + return adminView[index]; + } catch (err) { + cli.log(err); + } + } + + } + + announce(screens, event, data) { + /** + * @event event:announce + */ + this.dispatcher.emit("announce", {screens: screens, event: event, data: data}); + } + +} + +module.exports = adminLobby; + + diff --git a/modules/bundle.js b/modules/bundle.js index 765d92b..24e246f 100644 --- a/modules/bundle.js +++ b/modules/bundle.js @@ -119,21 +119,15 @@ class bundleClass { } } - toJson() { - this.sync(); - return JSON.stringify(this.allSlides, null, "\t"); - } - save() { this.sync(); try { - fs.writeFileSync("./data/bundles/" + this.name + "/slides.json", this.toJson()); + fs.writeFileSync("./data/bundles/" + this.name + "/slides.json", JSON.stringify(this.allSlides, null, "\t")); fs.writeFileSync("./data/bundles/" + this.name + "/bundle.json", JSON.stringify(this.bundleData, null, "\t")); } catch (e) { cli.error("error while saving file:", e); } } - } /** @@ -166,4 +160,4 @@ function sortByProperty(property) { * * @type {bundleClass} */ -module.exports = bundleClass; \ No newline at end of file +module.exports = bundleClass; diff --git a/modules/bundleManager.js b/modules/bundleManager.js index cfb379a..df6158f 100644 --- a/modules/bundleManager.js +++ b/modules/bundleManager.js @@ -51,6 +51,16 @@ class bundleManager { } } + reorderSlides(bundleName, sortedIDs) { + let bundle = this.getBundle(bundleName); + let i = 0; + for (let uuid of sortedIDs) { + bundle.setIndex(uuid, i); + i += 1; + } + bundle.save(); + } + /** * * @return {Array} @@ -90,4 +100,4 @@ function getJson(file) { /** * @type {bundleManager} */ -module.exports = bundleManager; \ No newline at end of file +module.exports = bundleManager; diff --git a/modules/display.js b/modules/display.js index 55c6309..f8a456c 100644 --- a/modules/display.js +++ b/modules/display.js @@ -1,3 +1,4 @@ +'use strict' let fs = require("fs"); let cli = require(`./cli.js`); let bundleManager = require(`./bundleManager.js`); @@ -16,16 +17,6 @@ class display { */ constructor(sharedIO, dispatcher, meta, displayId, bundleManager) { cli.info("Starting display with id " + displayId + " ..."); - - /** @property {Array} timeoutId - holds setTimeout id's for mainLoop */ - this.timeoutId = []; - - /** - * @type {bundleManager|module:infoscreen3/bundleManager} - */ - this.bundleManager = bundleManager; - let self = this; - /** * @property {number} displayId - this display id * @property {number} currentId - index number @see getBundle() @@ -59,11 +50,20 @@ class display { displayTime: true }; + /** @property {Array} timeoutId - holds setTimeout id's for mainLoop */ + this.timeoutId = null; + + /** + * @type {bundleManager|module:infoscreen3/bundleManager} + */ + this.bundleManager = bundleManager; + let io = sharedIO.of("/display-" + displayId.toString()); this.io = io; this.name = meta.name; this.dispatcher = dispatcher; this.id = displayId; + let self = this; /** * helper callback for global announce @@ -76,10 +76,20 @@ class display { self.displayCurrentSlide(); }); + dispatcher.on("display.recalcBundleData", function (bundleName) { + if (self.serverOptions.currentBundle === bundleName) { + for (let slide of self.getBundle().allSlides) { + // calculate new index for next slide; + if (slide.uuid === self.serverOptions.currentFile) { + self.serverOptions.loopIndex = slide.index + 1; + } + } + } + }); + dispatcher.on("announce", function (obj) { // if global announce, ie screens is null if (obj.screens === null) { - console.log("announcing: " + this.serverOptions.displayId); io.emit(obj.event, obj.data); } else { // screens is array @@ -141,6 +151,7 @@ class display { this.serverOptions.transition = bundle.getBundleData().transition; this.serverOptions.loop = true; this.io.emit("callback.load", this.getSlideData()); + bundle = null; this.mainLoop(); } @@ -153,10 +164,7 @@ class display { * clears timers */ clearTimers() { - for (let i in this.timeoutId) { - clearTimeout(this.timeoutId[i]); - delete this.timeoutId[i]; - } + clearTimeout(this.timeoutId); } /** @@ -166,6 +174,10 @@ class display { return this.bundleManager.getBundle(this.serverOptions.currentBundle); } + toggleBlackout() { + this.serverOptions.blackout = this.serverOptions.blackout === false; + this.io.emit("callback.blackout", {serverOptions: this.serverOptions}); + } /** * emits custom event for screens @@ -208,8 +220,6 @@ class display { } if (this.serverOptions.loop) { - let that = this; - // override slide timeout if set by slide let slideTimeout = this.serverOptions.slideDuration * 1000; if (this.serverOptions.currentMeta.duration > 5) { @@ -217,11 +227,7 @@ class display { } if (slideTimeout >= 5000) { - this.timeoutId.push( - setTimeout(function () { - that.mainLoop(); - }, slideTimeout)); - + this.timeoutId = setTimeout(this.mainLoop.bind(this), slideTimeout); } else { this.serverOptions.loop = false; } @@ -231,6 +237,8 @@ class display { this.displayCurrentSlide(); this.serverOptions.loopIndex += 1; } + + bundle = null; } overrideSlide(json, pngData, duration, transition) { @@ -244,20 +252,17 @@ class display { if (json.type === "image") { fs.writeFileSync("./tmp/display_" + this.serverOptions.displayId + ".png", pngData.replace(/^data:image\/png;base64,/, ""), "base64"); } - let that = this; + if (duration && duration >= 5) { this.serverOptions.loop = true; - this.timeoutId.push( - setTimeout(function () { - that.mainLoop(); - }, duration * 1000)); + this.timeoutId = setTimeout(this.mainLoop.bind(this), duration * 1000); } this.displayCurrentSlide(); this.serverOptions.transition = _transition; } displayCurrentSlide() { - this.announce([this.serverOptions.displayId, "admin"], "callback.update", this.getSlideData()); + this.announce([this.id, "admin"], "callback.update", this.getSlideData()); } } diff --git a/modules/profiler.js b/modules/profiler.js new file mode 100644 index 0000000..60de4b2 --- /dev/null +++ b/modules/profiler.js @@ -0,0 +1,25 @@ +var prevValue = 0; +let cli = require('./cli.js'); +module.exports.init = function (datadir) { + setInterval(tickHeapDump, 1000); +}; + +/** + * Schedule a heapdump by the end of next tick + */ +function tickHeapDump() { + setImmediate(function () { + heapDump(); + }); +} + +/** + * Creates a heap dump if the currently memory threshold is exceeded + */ +function heapDump() { + var memMB = (process.memoryUsage().rss / 1048576).toFixed(1); + if (prevValue != memMB) { + cli.info("Memory: " + memMB + 'Mb'); + prevValue = memMB; + } +} diff --git a/modules/websocket.js b/modules/websocket.js index c38e7af..b85f26d 100644 --- a/modules/websocket.js +++ b/modules/websocket.js @@ -1,13 +1,12 @@ let availableDisplays = require(`../config.js`).displays; let display = require(`./display.js`); let admin = require(`./admin.js`); +let adminLobby = require(`./adminLobby.js`); let cli = require(`./cli.js`); let _bundleManager = require(`./bundleManager.js`); let chalk = require('chalk'); let fs = require('fs'); - - /** * @param server * @param app @@ -70,46 +69,7 @@ module.exports = function (server, app, io, dispatcher) { screenId += 1; } - // create overview admin lobby - io.of("/admin").on("connection", function (socket) { - - let arr = []; - for (let display of screenView) { - arr.push({displayId: display.serverOptions.displayId, serverOptions: display.serverOptions}); - } - socket.emit("callback.serverOptions", arr); - - - // handle other events - cli.info("WS/" + socket.conn.remoteAddress + " connect"); - socket.on('error', function (error) { - cli.error(error, "WS/ error"); - }); - socket.on('disconnect', function (reason) { - cli.info("WS/ " + reason + " " + socket.conn.remoteAddress); - }); - - socket.on('controls.previous', function (data) { - getAdminView(data.displayId).controls("previous"); - }); - - socket.on('controls.play', function (data) { - getAdminView(data.displayId).controls("play"); - }); - - socket.on('controls.next', function (data) { - getAdminView(data.displayId).controls("next"); - }); - - socket.on('controls.pause', function (data) { - getAdminView(data.displayId).controls("pause"); - }); - - dispatcher.on("dashboard.update", function (data) { - socket.emit("callback.serverOptions", [data]); - }); - - }); + let adminLobby1 = new adminLobby(io, dispatcher, screenView, adminView, bundleManager); // create lobby io.of("/lobby").on("connection", function (socket) { @@ -136,17 +96,6 @@ module.exports = function (server, app, io, dispatcher) { }); }); - /** - * @return admin - */ - function getAdminView(index) { - try { - return adminView[index]; - } catch (err) { - cli.log(err); - } - } - return {screenView: screenView, adminView: adminView, bundleManager: bundleManager}; }; diff --git a/public/img/wait.png b/public/img/wait.png new file mode 100644 index 0000000..54e7288 Binary files /dev/null and b/public/img/wait.png differ diff --git a/public/js/display.js b/public/js/display.js index 99bead9..569df62 100644 --- a/public/js/display.js +++ b/public/js/display.js @@ -15,19 +15,16 @@ function symmetricDifference(a1, a2) { var connectionTimeoutId; +window.f = new flux.slider('#slider', { + controls: false, + captions: false, + autoplay: false, + pagination: false, + width: $(window).width(), + height: $(window).height(), +}); + $(function () { - if (!flux.browser.supportsTransitions) - alert("Flux Slider requires a browser that supports CSS3 transitions"); - - window.f = new flux.slider('#slider', { - controls: false, - captions: false, - autoplay: false, - pagination: false, - width: $(window).width(), - height: $(window).height(), - }); - $(window).resize(function () { if (this.resizeTO) clearTimeout(this.resizeTO); this.resizeTO = setTimeout(function () { @@ -113,15 +110,7 @@ socket.on('callback.time', function (data) { socket.on('callback.load', function (data) { serverOptions = data.serverOptions; bundleData = data.bundleData; - preloadImages(data.slides); - checkBlackout(); - setTimeout(function () { - setBackground(data.bundleData.background); - if (checkStream(serverOptions) === false) { - nextSlide(data); - } - }, 1000); - + preloadImages(data); }); @@ -150,7 +139,6 @@ socket.on('callback.reloadImage', function (data) { socket.on('callback.announce', function (data) { checkBlackout(); nextSlide(data); - }); socket.on('callback.forceSlide', function (data) { @@ -258,15 +246,14 @@ function nextSlide(data) { transition = serverOptions.currentMeta.transition; } - $("#" + getWebLayer()).addClass("fadeOut").removeClass("fadeIn").contents().empty(); - $("#" + getWebLayer(1)).addClass("fadeOut").removeClass("fadeIn").contents().empty(); + $("#" + getWebLayer()).addClass("fadeOut").removeClass("fadeIn"); + $("#" + getWebLayer(1)).addClass("fadeOut").removeClass("fadeIn"); + $("#slider").show(); + window.f.showImageById(serverOptions.currentFile, transition); setTimeout(function () { clearIFrame(getWebLayer()); clearIFrame(getWebLayer(1)); }, 2500); - - $("#slider").show(); - window.f.showImageById(serverOptions.currentFile, transition); break; } } @@ -348,15 +335,19 @@ function checkStream(serverOptions) { } return false; } - return false; + return true; } /** * preload images - * @param allSlides + * @param data */ -function preloadImages(allSlides) { +function preloadImages(data) { window.f.clearImages(); + + var allSlides = data.slides; + var count = allSlides.length; + var counter = 0; for (var i in allSlides) { try { if (allSlides[i].type === "slide") { @@ -364,6 +355,13 @@ function preloadImages(allSlides) { image.id = imageId; window.f.images.push(image); window.f.imageData.push(imageData); + counter++; + if (counter >= count) { + setBackground(bundleData.background); + if (checkStream(serverOptions) === false) { + nextSlide(data); + } + } }); } } catch (err) { @@ -484,9 +482,9 @@ function getDataUri(url, imageId, callback) { var canvas = document.createElement('canvas'); canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size - canvas.getContext('2d').drawImage(this, 0, 0); callback(imageId, canvas.toDataURL('image/png'), {src: url}); + canvas = null; }; image.src = url; } diff --git a/views/display.twig b/views/display.twig index 11ac63e..2cd23d2 100644 --- a/views/display.twig +++ b/views/display.twig @@ -28,7 +28,7 @@