2017-04-09 15:51:17 +00:00
"use strict" ;
2017-04-08 16:05:39 +00:00
const config = require ( './config.json' )
2017-04-09 20:57:32 +00:00
const library = require ( './jukebox/library' ) ;
2019-12-14 21:19:06 +00:00
const ScriptRunner = require ( './jukebox/scripts' ) ( config ) ;
2017-03-26 01:45:57 +00:00
const express = require ( 'express' ) ;
2019-12-15 16:50:53 +00:00
const morgan = require ( 'morgan' ) ;
const handlebars = require ( 'express-handlebars' ) ;
2019-12-17 17:12:53 +00:00
const multer = require ( 'multer' ) ;
const uuid = require ( 'uuid/v4' ) ;
var storage = multer . diskStorage ( {
destination : function ( req , file , cb ) {
cb ( null , config . media _path )
} ,
filename : function ( req , file , cb ) {
var track _uuid = uuid ( ) ;
cb ( null , track _uuid )
}
} ) ;
var upload = multer ( {
storage : storage ,
} ) ;
2017-03-26 01:45:57 +00:00
2019-12-14 19:20:18 +00:00
const { createLogger , format , transports } = require ( 'winston' ) ;
2019-12-14 21:19:06 +00:00
const { throttle } = require ( 'throttle-debounce' ) ;
2019-12-14 19:20:18 +00:00
var logger = createLogger ( {
2017-04-09 17:55:11 +00:00
transports : [
2019-12-14 19:20:18 +00:00
new transports . Console ( )
2017-04-09 17:55:11 +00:00
]
} ) ;
logger . level = config . debug ? 'debug' : 'info' ;
const MediaPlayer = require ( './jukebox/media-player' ) ( config , logger ) ;
const TagReader = require ( './jukebox/tag-reader' ) ( config , logger ) ;
2017-04-10 02:05:52 +00:00
const play _log = require ( './jukebox/library/play-log' ) ;
2019-12-15 16:50:53 +00:00
const sqlite3 = require ( 'sqlite3' ) ;
var db = new sqlite3 . Database ( config . db ) ;
const MediaLibrarySqliteBackend = require ( './jukebox/library/sqlite-backend' ) ( config , db ) ;
const MediaLibrary = new library . Library ( config , MediaLibrarySqliteBackend ) ;
2017-04-10 02:05:52 +00:00
const PlayLog = new play _log . PlayLog ( ) ;
2017-04-09 13:41:17 +00:00
2017-03-26 01:45:57 +00:00
var app = express ( ) ;
var server = require ( 'http' ) . createServer ( ) ;
const WebSocket = require ( 'ws' ) ;
const WebSocketServer = WebSocket . Server ;
var wss = new WebSocketServer ( { server : server } ) ;
2017-04-09 16:30:20 +00:00
function exitHandler ( options , err ) {
2017-04-09 17:55:11 +00:00
logger . debug ( 'closing child tasks' ) ;
if ( err ) logger . debug ( err . stack ) ;
2017-04-08 02:01:12 +00:00
2017-04-10 02:05:52 +00:00
// 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.
2017-04-09 16:30:20 +00:00
TagReader . kill ( ) ;
MediaPlayer . kill ( ) ;
if ( options . exit ) {
process . exit ( ) ;
}
} ;
process . on ( 'exit' , exitHandler . bind ( null ) ) ;
process . on ( 'SIGINT' , exitHandler . bind ( null , { exit : true } ) ) ;
2019-12-15 02:08:08 +00:00
process . on ( 'SIGUSR2' , exitHandler . bind ( null , { exit : true } ) ) ;
2017-04-08 02:01:12 +00:00
2019-12-14 21:19:06 +00:00
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 ) ;
} ) ;
} ) ;
2017-04-09 20:57:32 +00:00
TagReader . on ( 'message' , tag => {
2017-04-10 02:45:21 +00:00
if ( tag == 'E1' || tag == 'E2' ) {
logger . debug ( "tagreader had rfid read error" , { tag : tag } ) ;
return ;
}
2017-04-10 01:46:18 +00:00
logger . debug ( "got tag from tagreader" , { tag : tag } ) ;
2019-12-14 21:19:06 +00:00
throttledTag ( tag ) ;
2017-04-09 13:41:17 +00:00
} ) ;
2016-11-20 01:13:19 +00:00
2017-04-09 15:52:37 +00:00
if ( config . debug ) {
2017-04-09 19:08:32 +00:00
MediaPlayer . on ( 'message' , line => {
logger . debug ( "mediaplayer sent message" , { line : line } ) ;
2017-04-09 15:52:37 +00:00
} ) ;
}
2017-04-10 02:05:52 +00:00
MediaPlayer . on ( 'command' , tag => {
PlayLog . updateLog ( tag ) ;
} ) ;
2019-12-15 16:50:53 +00:00
var hbs = handlebars . create ( {
extname : ".hbs" ,
2017-04-09 20:57:32 +00:00
} ) ;
2017-03-26 01:45:57 +00:00
2017-04-10 02:05:52 +00:00
MediaLibrary . on ( 'action' , MediaPlayer . handleTag . bind ( MediaPlayer ) ) ;
2017-04-08 02:02:07 +00:00
2019-12-15 16:50:53 +00:00
app . engine ( ".hbs" , hbs . engine ) ;
app . set ( 'view engine' , '.hbs' ) ;
app . set ( 'views' , _ _dirname + '/views' ) ;
2017-04-09 17:55:11 +00:00
app . use ( morgan ( 'dev' ) )
2019-12-17 15:22:58 +00:00
app . use ( express . json ( ) )
2016-11-20 01:13:19 +00:00
app . use ( express . static ( _ _dirname + '/static' ) )
2019-12-15 16:50:53 +00:00
PlayLog . on ( 'update' , tag => {
app . render ( "log" , { layout : false , play _log : PlayLog . getLog ( ) , } , ( err , html ) => {
var data = {
html : html ,
tag : tag . tag
} ;
wss . broadcast ( JSON . stringify ( data ) ) ;
} ) ;
} ) ;
2019-12-17 15:22:58 +00:00
app . get ( '/' , function ( req , res , next ) {
2019-12-15 16:50:53 +00:00
res . render ( 'index' , {
last _tag : PlayLog . getLastTag ( ) ,
config : config ,
play _log : PlayLog . getLog ( ) ,
} ) ;
} ) ;
2019-12-17 15:22:58 +00:00
app . get ( '/api/tags' , function ( req , res , next ) {
2019-12-17 15:41:24 +00:00
db . all ( "SELECT tags.tag, count(library.tag) tag_count FROM (SELECT DISTINCT tag FROM tags) tags LEFT JOIN library ON tags.tag = library.tag GROUP BY tags.tag" , ( err , rows ) => {
2019-12-17 15:22:58 +00:00
res . send ( rows ) ;
} ) ;
} ) ;
2017-04-09 15:51:17 +00:00
2019-12-17 15:22:58 +00:00
app . patch ( '/api/tracks/:track' , function ( req , res , next ) {
var track _uuid = req . params . track ,
label = req . body . label ,
tag = req . body . tag ;
2019-12-17 17:12:53 +00:00
db . run ( "UPDATE library SET label = ?, tag = ? WHERE uuid = ?" , label , tag , track _uuid , err => {
2019-12-17 15:22:58 +00:00
db . get ( "SELECT * FROM library WHERE uuid = ?" , track _uuid , ( err , row ) => {
res . send ( row ) ;
2019-12-15 16:50:53 +00:00
} ) ;
2019-12-17 15:22:58 +00:00
} ) ;
} ) ;
app . get ( '/api/tracks' , function ( req , res , next ) {
db . all ( "SELECT * FROM library ORDER BY label ASC" , ( err , rows ) => {
res . send ( rows ) ;
} ) ;
} ) ;
2017-04-09 15:51:17 +00:00
2019-12-17 17:12:53 +00:00
app . post ( '/api/tracks' , upload . single ( 'track' ) , function ( req , res , next ) {
db . run ( "INSERT INTO library (label, uuid) VALUES (?, ?)" , req . file . originalname , req . file . filename , err => {
res . redirect ( '/library' ) ;
} ) ;
} ) ;
2019-12-17 15:22:58 +00:00
app . get ( '/library' , function ( req , res , next ) {
res . render ( 'library' , {
title : 'Library' ,
2019-12-15 16:50:53 +00:00
} ) ;
2017-03-26 01:45:57 +00:00
} ) ;
wss . broadcast = function broadcast ( data ) {
wss . clients . forEach ( function each ( client ) {
if ( client . readyState === WebSocket . OPEN ) {
client . send ( data ) ;
}
} ) ;
} ;
2019-12-17 15:22:58 +00:00
wss . on ( 'connection' , function ( ws ) {
2017-04-09 17:55:11 +00:00
logger . info ( 'websocket client connected' ) ;
2019-12-17 15:22:58 +00:00
ws . on ( 'close' , function ( ) {
2017-04-09 17:55:11 +00:00
logger . info ( 'websocket client disconnected' ) ;
2017-03-26 01:45:57 +00:00
} ) ;
} ) ;
server . on ( 'request' , app ) ;
2016-11-20 01:13:19 +00:00
2019-12-17 15:22:58 +00:00
server . listen ( config . port , function ( ) {
2017-04-09 17:55:11 +00:00
logger . info ( 'express listening on http://localhost:' + config . port )
2016-11-20 01:13:19 +00:00
} )
2017-04-08 16:05:39 +00:00
// vim:ts=2 sw=2 et: