"use strict"; const config = require('./config.json') const glob = require('glob'); const views = require('./jukebox/views')(__dirname + '/templates/'); const express = require('express'); const logger = require('morgan') const MediaPlayer = require('./jukebox/media-player')(config); const TagReader = require('./jukebox/tag-reader')(config); var app = express(); var server = require('http').createServer(); const WebSocket = require('ws'); const WebSocketServer = WebSocket.Server; var wss = new WebSocketServer({server: server}); var play_log = []; function exitHandler(options, err) { console.log('[player] closing children'); if (err) console.log(err.stack); TagReader.kill(); MediaPlayer.kill(); if (options.exit) { process.exit(); } }; process.on('exit', exitHandler.bind(null)); process.on('SIGINT', exitHandler.bind(null, {exit:true})); function setupChildLogging(name, child) { child.on('process_error', (err) => { console.log(`[${name}] error=${err}`); }); child.on('close', (code, signal) => { console.log(`[${name}] process closed:code=${code} signal=${signal}`); }); child.on('error', (data) => { console.log(`[${name}] stderr: ${data}`); }); } setupChildLogging('tagreader', TagReader); setupChildLogging('mediaplayer', MediaPlayer); TagReader.on('message', (data) => { processLine(data); }); if (config.debug) { MediaPlayer.on('message', (data) => { console.log(`[mediaplayer] stdout: ${data}`); }); } var last_tag = null; var debounce_until = 0; function lookup(tag, cb) { if (tag === config.stop_id) { return cb('STOP'); } if (tag === config.pause_id) { return cb('PAUSE', 2); } glob('media/' + tag + ' - *.mp3', function(er, files) { if (files.length > 0) { appendLog(files[0]); return cb("LOAD " + files[0], 5); } appendLog(tag); }); } function appendLog(message) { if (play_log.length > 10) { play_log.pop(); } play_log.unshift(message); var data = { html: views.log.render({ play_log: play_log }), tag: last_tag }; wss.broadcast(JSON.stringify(data)); } function processLine(data) { if (Date.now() / 1000 < debounce_until) { return; } last_tag = String(data).trim(); console.log("[tag] " + last_tag); // min 1 sec debounce debounce_until = Date.now() / 1000 + 1; lookup(last_tag, function(action, wait_sec) { wait_sec = wait_sec || 1; debounce_until = Date.now() / 1000 + wait_sec; if (action) { console.log(`[action] [${action}] for [${last_tag}]`); MediaPlayer.send(action + "\n"); } }); } app.use(logger('dev')) app.use(express.static(__dirname + '/static')) app.get('/', function (req, res, next) { try { var index = views.index.render({ last_tag: last_tag , config: config , play_log: play_log }); 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) { console.log('[websocket] client connected'); ws.on('close', function () { console.log('[websocket] client disconnected'); }); }); server.on('request', app); server.listen(config.port, function () { console.log('[http] listening on http://localhost:' + config.port) }) // vim:ts=2 sw=2 et: