Create PlayLog, move tag identification into MediaLibrary
This commit is contained in:
parent
78f2802dea
commit
43ad5281e3
@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const glob = require('glob');
|
||||
const basename = require('path').basename;
|
||||
|
||||
class FileBackend {
|
||||
constructor(config) {
|
||||
@ -10,8 +11,9 @@ class FileBackend {
|
||||
find(tag, callback) {
|
||||
glob('media/' + tag + ' - *.mp3', (err, files) => {
|
||||
if (files.length > 0) {
|
||||
callback(files[0]);
|
||||
callback(basename(files[0]));
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,34 @@
|
||||
"use strict";
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const tags = require('./tags');
|
||||
|
||||
class Library extends EventEmitter {
|
||||
constructor(config, backend) {
|
||||
super();
|
||||
|
||||
this.log_size = 10;
|
||||
this.config = config;
|
||||
this.backend = backend;
|
||||
this.log = [];
|
||||
}
|
||||
|
||||
find(tag) {
|
||||
if (tag === this.config.stop_id) {
|
||||
this.emit('action', new tags.StopCommand());
|
||||
}
|
||||
|
||||
if (tag === this.config.pause_id) {
|
||||
this.emit('action', new tags.PauseCommand());
|
||||
}
|
||||
|
||||
this.backend.find(tag, path => {
|
||||
if (!path) {
|
||||
this.updateLog(new NotFoundLogEntry(tag));
|
||||
this.emit('action', new tags.NotFoundTag(tag));
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateLog(new FileLogEntry(tag, path));
|
||||
this.emit('action', new tags.FileTag(tag, path));
|
||||
});
|
||||
}
|
||||
|
||||
updateLog(entry) {
|
||||
this.log.unshift(entry);
|
||||
if (this.log.length > this.log_size) {
|
||||
this.log.pop();
|
||||
}
|
||||
this.emit('play', entry);
|
||||
}
|
||||
|
||||
getLastTag() {
|
||||
if (this.log.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.log[0].tag;
|
||||
}
|
||||
|
||||
getLog() {
|
||||
return this.log;
|
||||
}
|
||||
}
|
||||
|
||||
class LogEntry {
|
||||
constructor(tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.tag;
|
||||
}
|
||||
}
|
||||
|
||||
class NotFoundLogEntry extends LogEntry {
|
||||
toString() {
|
||||
return `Unknown media: ${this.tag}`
|
||||
}
|
||||
}
|
||||
|
||||
class FileLogEntry extends LogEntry {
|
||||
constructor(tag, path) {
|
||||
super(tag);
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.Library = Library;
|
||||
|
44
jukebox/library/play-log.js
Normal file
44
jukebox/library/play-log.js
Normal file
@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
|
||||
const tags = require('./tags');
|
||||
|
||||
module.exports.PlayLog = class PlayLog extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.last_tag = undefined;
|
||||
this.log = [];
|
||||
this.log_size = 10;
|
||||
}
|
||||
|
||||
updateLog(tag) {
|
||||
this.last_tag = tag;
|
||||
|
||||
if (tag instanceof tags.NotFoundTag) {
|
||||
this.emit('update', tag);
|
||||
return;
|
||||
}
|
||||
|
||||
this.log.unshift(tag);
|
||||
if (this.log.length > this.log_size) {
|
||||
this.log.pop();
|
||||
}
|
||||
|
||||
this.emit('update', tag);
|
||||
}
|
||||
|
||||
getLastTag() {
|
||||
if (this.log.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.log[0].tag;
|
||||
}
|
||||
|
||||
getLog() {
|
||||
return this.log;
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=2 sw=2 et:
|
45
jukebox/library/tags.js
Normal file
45
jukebox/library/tags.js
Normal file
@ -0,0 +1,45 @@
|
||||
class Tag {
|
||||
constructor(tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.tag;
|
||||
}
|
||||
}
|
||||
|
||||
class StopCommand extends Tag {
|
||||
toString() {
|
||||
return "Command: STOP";
|
||||
}
|
||||
}
|
||||
|
||||
class PauseCommand extends Tag {
|
||||
toString() {
|
||||
return "Command: PAUSE";
|
||||
}
|
||||
}
|
||||
|
||||
class NotFoundTag extends Tag {
|
||||
toString() {
|
||||
return `Unknown tag: ${this.tag}`
|
||||
}
|
||||
}
|
||||
|
||||
class FileTag extends Tag {
|
||||
constructor(tag, path) {
|
||||
super(tag);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.path;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
StopCommand: StopCommand
|
||||
, PauseCommand: PauseCommand
|
||||
, NotFoundTag: NotFoundTag
|
||||
, FileTag: FileTag
|
||||
};
|
@ -1,11 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
const tags = require('./library/tags');
|
||||
|
||||
const throttle = require('throttle-debounce/throttle');
|
||||
|
||||
const ChildProcessEmitter = require('./child-process').ChildProcessEmitter;
|
||||
|
||||
const DEFAULT_PAUSE_THROTTLE = 2000;
|
||||
const DEFAULT_PLAY_THROTTLE = 5000;
|
||||
const DEFAULT_UNKNOWN_THROTTLE = 2000;
|
||||
|
||||
class MediaPlayer extends ChildProcessEmitter {
|
||||
constructor(config, logger) {
|
||||
@ -23,6 +26,8 @@ class MediaPlayer extends ChildProcessEmitter {
|
||||
this._playFile(path);
|
||||
});
|
||||
|
||||
this.unknown = throttle(config.unknown_throttle || DEFAULT_UNKNOWN_THROTTLE, this._unknown);
|
||||
|
||||
// default to unthrottled
|
||||
this.pause = this._pauseFile;
|
||||
this.playFile = this._playFile;
|
||||
@ -33,16 +38,35 @@ class MediaPlayer extends ChildProcessEmitter {
|
||||
this.playFile = this.playFileThrottled;
|
||||
}
|
||||
|
||||
stop() {
|
||||
stop(tag) {
|
||||
this.emit('command', tag);
|
||||
this.send('STOP');
|
||||
}
|
||||
|
||||
_pause() {
|
||||
_pause(tag) {
|
||||
this.emit('command', tag);
|
||||
this.send('PAUSE');
|
||||
}
|
||||
|
||||
_playFile(path) {
|
||||
this.send("LOAD " + path);
|
||||
_playFile(tag) {
|
||||
this.emit('command', tag);
|
||||
this.send("LOAD media/" + tag.path);
|
||||
}
|
||||
|
||||
_unknown(tag) {
|
||||
this.emit('command', tag);
|
||||
}
|
||||
|
||||
handleTag(tag) {
|
||||
if (tag instanceof tags.StopCommand) {
|
||||
this.stop(tag);
|
||||
} else if (tag instanceof tags.PauseCommand) {
|
||||
this.pause(tag);
|
||||
} else if (tag instanceof tags.FileTag) {
|
||||
this.playFile(tag);
|
||||
} else {
|
||||
this.unknown(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
const ChildProcessEmitter = require('./child-process').ChildProcessEmitter;
|
||||
|
||||
class TagReader extends ChildProcessEmitter {
|
||||
constructor(config, logger) {
|
||||
super(config.tag_reader, logger);
|
||||
}
|
||||
constructor(config, logger) {
|
||||
super(config.tag_reader, logger);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function(config, logger) {
|
||||
|
34
player.js
34
player.js
@ -22,6 +22,9 @@ 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();
|
||||
|
||||
MediaPlayer.throttle();
|
||||
|
||||
@ -36,6 +39,9 @@ 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();
|
||||
|
||||
@ -57,28 +63,20 @@ if (config.debug) {
|
||||
});
|
||||
}
|
||||
|
||||
MediaLibrary.on('play', event => {
|
||||
MediaPlayer.on('command', tag => {
|
||||
PlayLog.updateLog(tag);
|
||||
});
|
||||
|
||||
PlayLog.on('update', tag => {
|
||||
var data = {
|
||||
html: views.log.render({ play_log: MediaLibrary.getLog() }),
|
||||
tag: MediaLibrary.getLastTag()
|
||||
html: views.log.render({ play_log: PlayLog.getLog() }),
|
||||
tag: tag.tag
|
||||
};
|
||||
|
||||
wss.broadcast(JSON.stringify(data));
|
||||
});
|
||||
|
||||
MediaLibrary.on('play', event => {
|
||||
if (event.tag === config.stop_id) {
|
||||
MediaPlayer.stop();
|
||||
}
|
||||
|
||||
if (event.tag === config.pause_id) {
|
||||
MediaPlayer.pause();
|
||||
}
|
||||
|
||||
if (event.path) {
|
||||
MediaPlayer.playFile(event.path);
|
||||
}
|
||||
});
|
||||
MediaLibrary.on('action', MediaPlayer.handleTag.bind(MediaPlayer));
|
||||
|
||||
app.use(morgan('dev'))
|
||||
app.use(express.static(__dirname + '/static'))
|
||||
@ -86,9 +84,9 @@ app.use(express.static(__dirname + '/static'))
|
||||
app.get('/', function (req, res, next) {
|
||||
try {
|
||||
var index = views.index.render({
|
||||
last_tag: MediaLibrary.getLastTag()
|
||||
last_tag: PlayLog.getLastTag()
|
||||
, config: config
|
||||
, play_log: MediaLibrary.getLog()
|
||||
, play_log: PlayLog.getLog()
|
||||
});
|
||||
|
||||
var html = views.base.render({
|
||||
|
Loading…
Reference in New Issue
Block a user