123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- var fs = require("fs");
- var pathlib = require("path");
-
- var mimetype = require("./mimetype");
- var error = require("./error");
-
- module.exports = Slideshow;
-
- var htmlPre =
- "<html>"+
- "<head>"+
- "<link rel='stylesheet' href='/slide.css'>"+
- "<meta charset='utf-8'>"+
- "</head>"+
- "<body>"+
- "<div id='_wrapper'>";
-
- var htmlPost =
- "</div>"+
- "</body>"+
- "</html>";
-
- function sendFile(path, res) {
- res.writeHead(200, {
- "content-type": mimetype(path)
- });
-
- fs.createReadStream(path)
- .on("error", err => error(err, res))
- .pipe(res);
- }
-
- function sendIndex(path, res) {
- res.writeHead(200, {
- "content-type": "text/html"
- });
- res.write(htmlPre);
-
- fs.readFile(path, (err, text) => {
- if (err)
- text.write(err.toString());
- else
- res.write(text);
-
- res.end(htmlPost);
- });
- }
-
- // The individual slide
- function Slide(dir) {
- var self = {};
-
- self.dir = dir;
- self.name = pathlib.parse(dir).name;
-
- self.sendIndex = function(res) {
- sendIndex(pathlib.join(self.dir, "index.html"), res);
- }
-
- self.sendFile = function(name, res) {
- sendFile(pathlib.join(self.dir, name), res);
- }
-
- self.serveFiles = function(parts, res) {
-
- // Serve index if /{name} is reuested
- if (parts.pathname.replace(/\//g, "") === self.name) {
-
- // Redirect from /{name} to /{name}/
- if (parts.pathname[parts.pathname.length - 1] !== '/') {
- res.writeHead(302, {
- location: parts.pathname+"/"
- });
- res.end();
-
- // Serve index if it's already /{name}/
- } else {
- self.sendIndex(res);
- }
- } else {
-
- // Serve other files
- var name = parts.pathname.substring(1).replace(self.name, "");
- var path = pathlib.join(dir, name);
- sendFile(path, res);
- }
- }
-
- self.indexExists = function() {
- try {
- fs.accessSync(pathlib.join(dir, "index.html"));
- return true;
- } catch (err) {
- return false;
- }
- }
-
- try {
- self.meta = JSON.parse(
- fs.readFileSync(pathlib.join(dir, "meta.json")));
- } catch (err) {
- if (err.code !== "ENOENT")
- error(err);
-
- self.meta = {};
- }
-
- return self;
- }
-
- // The slideshow, whose job it is to manage all slides
- // and tell the client whether it has to update or not
- function Slideshow(dir, changeInterval) {
- var self = {};
-
- var currentSlide = null;
- var awaiters = [];
- var slides = [];
- var slideIndex = 0;
- var nextTimeout;
-
- self.sendEvent = function(evt, args) {
- var str = JSON.stringify({ evt: evt, args: args });
- awaiters.forEach(res => res.end(str));
- awaiters = [];
- }
-
- // Get the current slide's interval
- function currentInterval() {
- var itv = currentSlide.meta.interval;
- if (itv === undefined)
- itv = changeInterval;
- return itv;
- }
-
- // Return if the current slide is enabled and valid
- function currentEnabled() {
- return currentSlide.indexExists() && !currentSlide.disabled;
- }
-
- self.getSlideName = getSlideName;
- function getSlideName() {
- return currentSlide ? currentSlide.name : ""
- }
-
- self.pushAwaiter = pushAwaiter;
- function pushAwaiter(res) {
- awaiters.push(res);
- }
-
- self.getSlides = getSlides;
- function getSlides() {
- return slides;
- }
-
- self.next = next;
- function next() {
- slideIndex += 1;
-
- // Go to the next slide, or restart
- if (slideIndex >= slides.length) {
- clearTimeout(nextTimeout);
- init();
- } else {
- currentSlide = slides[slideIndex];
-
- nextTimeout = setTimeout(next, currentInterval());
- }
-
- // End all awaiting connections to notify slide change,
- if (currentEnabled()) {
- self.sendEvent("next", { name: currentSlide.name });
-
- // Or go to the next slide if the current one doesn't have an index.html
- // or if the slide is disabled
- } else {
- clearTimeout(nextTimeout);
- setTimeout(next, 0);
- }
- }
-
- // This function starts the slideshow and goes through the slides
- // one by one. When done, it starts again by calling this function again.
- function init() {
- slides = fs.readdirSync(dir)
- .sort()
- .map(file => Slide(pathlib.join(dir, file)));
-
- slideIndex = 0;
- currentSlide = slides[slideIndex];
-
- nextTimeout = setTimeout(next, currentInterval());
- }
- init();
-
- return self;
- }
|