"use strict"; const config = require('./config.json') const views = require('./jukebox/views')(__dirname + '/templates/'); const library = require('./jukebox/library'); const MediaLibraryFileBackend = require('./jukebox/library/file-backend')(config); const MediaLibrary = new library.Library(config, MediaLibraryFileBackend); const ScriptRunner = require('./jukebox/scripts')(config); const express = require('express'); const morgan = require('morgan') const { createLogger, format, transports } = require('winston'); const { throttle } = require('throttle-debounce'); var logger = createLogger({ transports: [ new transports.Console() ] }); logger.level = config.debug ? 'debug' : 'info'; const MediaPlayer = require('./jukebox/media-player')(config, logger); const TagReader = require('./jukebox/tag-reader')(config, logger); const play_log = require('./jukebox/library/play-log'); const PlayLog = new play_log.PlayLog(); var app = express(); var server = require('http').createServer(); const WebSocket = require('ws'); const WebSocketServer = WebSocket.Server; var wss = new WebSocketServer({server: server}); function exitHandler(options, err) { logger.debug('closing child tasks'); if (err) logger.debug(err.stack); // FIXME When do we actually need to call this? Adding these seems // to have fixed a problem with orphaned children, but not we get // two sets of "closing child tasks" messages when we shut down. TagReader.kill(); MediaPlayer.kill(); if (options.exit) { process.exit(); } }; process.on('exit', exitHandler.bind(null)); process.on('SIGINT', exitHandler.bind(null, {exit:true})); const throttledTag = throttle(config.global_throttle, true, tag => { ScriptRunner.find(tag).then((fulfilled) => { if (false === fulfilled) { MediaLibrary.find(tag) } }).catch(err => { logger.error("got an error handling the tag: " + err); }); }); TagReader.on('message', tag => { if (tag == 'E1' || tag == 'E2') { logger.debug("tagreader had rfid read error", { tag: tag }); return; } logger.debug("got tag from tagreader", { tag: tag }); throttledTag(tag); }); if (config.debug) { MediaPlayer.on('message', line => { logger.debug("mediaplayer sent message", { line: line }); }); } MediaPlayer.on('command', tag => { PlayLog.updateLog(tag); }); PlayLog.on('update', tag => { var data = { html: views.log.render({ play_log: PlayLog.getLog() }), tag: tag.tag }; wss.broadcast(JSON.stringify(data)); }); MediaLibrary.on('action', MediaPlayer.handleTag.bind(MediaPlayer)); app.use(morgan('dev')) app.use(express.static(__dirname + '/static')) app.get('/', function (req, res, next) { try { var index = views.index.render({ last_tag: PlayLog.getLastTag() , config: config , play_log: PlayLog.getLog() }); var html = views.base.render({ title: 'Home' , content: index }) res.send(html) } catch (e) { next(e) } }); wss.broadcast = function broadcast(data) { wss.clients.forEach(function each(client) { if (client.readyState === WebSocket.OPEN) { client.send(data); } }); }; wss.on('connection', function (ws) { logger.info('websocket client connected'); ws.on('close', function () { logger.info('websocket client disconnected'); }); }); server.on('request', app); server.listen(config.port, function () { logger.info('express listening on http://localhost:' + config.port) }) // vim:ts=2 sw=2 et: