178 lines
4.1 KiB
JavaScript
178 lines
4.1 KiB
JavaScript
|
|
const config = require('./config.json')
|
|
|
|
const glob = require('glob');
|
|
const spawn = require('child_process').spawn;
|
|
const tag_reader = spawn(config.tag_reader[0], config.tag_reader.slice(1));
|
|
const player = spawn(config.mpg321[0], config.mpg321.slice(1));
|
|
|
|
const express = require('express');
|
|
const logger = require('morgan')
|
|
const mustache = require('mustache');
|
|
|
|
const readFileSync = require('fs').readFileSync;
|
|
|
|
var app = express();
|
|
var server = require('http').createServer();
|
|
|
|
const WebSocket = require('ws');
|
|
const WebSocketServer = WebSocket.Server;
|
|
var wss = new WebSocketServer({server: server});
|
|
|
|
var base_tpl = readFileSync(__dirname + '/source/templates/base.mustache', {encoding: 'utf8'});
|
|
var index_tpl = readFileSync(__dirname + '/source/templates/index.mustache', {encoding: 'utf8'});
|
|
var log_tpl = readFileSync(__dirname + '/source/templates/log.mustache', {encoding: 'utf8'});
|
|
|
|
mustache.parse(index_tpl),
|
|
mustache.parse(log_tpl);
|
|
|
|
var play_log = [];
|
|
|
|
function exitHandler(options, err) {
|
|
console.log('[player] closing children');
|
|
if (err) console.log(err.stack);
|
|
tag_reader.kill();
|
|
player.kill();
|
|
if (options.exit) {
|
|
process.exit();
|
|
}
|
|
}
|
|
|
|
process.on('exit', exitHandler.bind(null));
|
|
process.on('SIGINT', exitHandler.bind(null, {exit:true}));
|
|
|
|
tag_reader.on('error', function(err) {
|
|
console.log(`[tag_reader] error=${err}`);
|
|
});
|
|
|
|
player.on('error', function(err) {
|
|
console.log(`[mpg321] error=${err}`);
|
|
});
|
|
|
|
tag_reader.on('close', function(code, signal) {
|
|
console.log(`[tag_reader] process closed:code=${code} signal=${signal}`);
|
|
});
|
|
|
|
player.on('close', function(code, signal) {
|
|
console.log(`[mpg321] process closed:code=${code} signal=${signal}`);
|
|
});
|
|
|
|
// player.stdin.write("GAIN 100");
|
|
|
|
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: mustache.render(log_tpl, { 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}]`);
|
|
player.stdin.write(action + "\n");
|
|
}
|
|
});
|
|
}
|
|
|
|
tag_reader.stdout.on('data', (data) => {
|
|
var s = data.toString(), lines = s.split(/\n/g);
|
|
for (var i = 0, l = lines.length; i < l; i++) {
|
|
processLine(lines[i]);
|
|
}
|
|
});
|
|
|
|
tag_reader.stderr.on('data', (data) => {
|
|
console.log(`[tag_reader:stderr] ${data}`);
|
|
});
|
|
|
|
player.stderr.on('data', (data) => {
|
|
if (String(data).substr(0, 3) === "@F ") {
|
|
return;
|
|
}
|
|
console.log(`[mpg321] stderr ${data}`);
|
|
});
|
|
|
|
app.use(logger('dev'))
|
|
app.use(express.static(__dirname + '/static'))
|
|
|
|
app.get('/', function (req, res, next) {
|
|
try {
|
|
var html = mustache.render(base_tpl, {
|
|
title: 'Home'
|
|
, last_tag: last_tag
|
|
, play_log: play_log
|
|
, config: config
|
|
}, {
|
|
content: index_tpl
|
|
, log: log_tpl
|
|
})
|
|
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:
|