mirror of
https://github.com/vale981/doccam-pi
synced 2025-03-04 17:01:40 -05:00
compatibility
This commit is contained in:
parent
379e6bf9d7
commit
d451ea6dd4
42 changed files with 6304 additions and 552 deletions
496
#main.js#
Executable file
496
#main.js#
Executable file
|
@ -0,0 +1,496 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Main Module - Communicates with the Server and Orchestrates the other Moules. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const sock = require('socket.io-client');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const WMStrm = require(__dirname + '/lib/memWrite.js');
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const spawnP = require('child_process').spawn;
|
||||
|
||||
/**
|
||||
* Custom Modules
|
||||
* Yet to be initialized.
|
||||
*/
|
||||
const logger = require('src/logger.js');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Force a Stop.
|
||||
let mustBe = false;
|
||||
|
||||
// Restart the stream after it stopped.
|
||||
let restart = false;
|
||||
|
||||
// Central State Variable
|
||||
// NOTE: Could be done with redux!
|
||||
let status = {
|
||||
status: 0,
|
||||
error: -1
|
||||
}
|
||||
|
||||
// Minor declarations.
|
||||
let config, source, snapSource, stopTimeout;
|
||||
|
||||
let spawn = function() {
|
||||
source = 'rtsp://' + config.camIP + ':' + config.camPort + '/' + config.camProfile;
|
||||
ffmpeg.setFfmpegPath(config.ffmpegPath);
|
||||
delete cmd;
|
||||
cmd = ffmpeg({
|
||||
source: source,
|
||||
stdoutLines: 20
|
||||
});
|
||||
if (config.customOutputOptions !== "")
|
||||
cmd.outputOptions(config.customOutputOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
if (config.customAudioOptions !== "")
|
||||
cmd.outputOptions(config.customAudioOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.AudioCodec('copy');
|
||||
if (config.customVideoOptions !== "")
|
||||
cmd.outputOptions(config.customVideoOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.videoCodec('copy');
|
||||
|
||||
cmd.on('start', function(commandLine) {
|
||||
status.running = 0;
|
||||
logger.log(logger.importance[4], 'Spawned Ffmpeg with command: ' + commandLine);
|
||||
})
|
||||
.on('end', function(o, e) {
|
||||
imDead('Normal Stop.', e);
|
||||
})
|
||||
.on('error', function(err, o, e) {
|
||||
if (err.message.indexOf(source) > -1)
|
||||
criticalProblem(0, e, handleDisc, config.camIP, config.camPort);
|
||||
else if (err.message.indexOf(source + 'Input/output error') > -1 || err.message.indexOf('rtmp://a.rtmp.youtube.com/live2/' + config.key) > -1)
|
||||
criticalProblem(1, e, handleDisc, 'a.rtmp.youtube.com/live2/', 1935);
|
||||
else if (err.message.indexOf('spawn') > -1 || err.message.indexOf('niceness') > -1)
|
||||
criticalProblem(2, e, function() {});
|
||||
else if (err.message.indexOf('SIGINT') > -1 || err.message.indexOf('SIGKILL') > -1)
|
||||
imDead('Normal Stop.', e);
|
||||
else
|
||||
imDead(err.message, e);
|
||||
})
|
||||
.outputFormat('flv')
|
||||
.outputOptions(['-bufsize 50000k', '-tune film'])
|
||||
.output('rtmp://a.rtmp.youtube.com/live2/' + config.key);
|
||||
|
||||
status.error = -1;
|
||||
socket.emit('change', {
|
||||
type: 'startStop',
|
||||
change: {
|
||||
running: 0,
|
||||
error: -1
|
||||
}
|
||||
});
|
||||
cmd.run();
|
||||
};
|
||||
|
||||
let getSnap = function(cb) {
|
||||
snapSource = 'rtsp://' + config.camIP + ':' + config.camPort + '/' + config.snapProfile;
|
||||
let picBuff = new WMStrm();
|
||||
recCmd = ffmpeg(snapSource)
|
||||
.on('start', function(commandLine) {
|
||||
logger.log(logger.importance[4], 'Snapshot ' + commandLine);
|
||||
})
|
||||
.on('error', function(err, o, e) {})
|
||||
.outputFormat('mjpeg')
|
||||
.frames(1)
|
||||
.stream(picBuff, {
|
||||
end: true
|
||||
});
|
||||
picBuff.on('finish', function() {
|
||||
try {
|
||||
cb(picBuff.memStore.toString('base64'));
|
||||
delete pickBuff;
|
||||
} catch (e) {
|
||||
cb(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function imDead(why, e = '') {
|
||||
if (stopTimeout) {
|
||||
clearTimeout(stopTimeout);
|
||||
stopTimeout = false;
|
||||
}
|
||||
|
||||
status.running = 1;
|
||||
socket.emit('change', {
|
||||
type: 'startStop',
|
||||
change: {
|
||||
running: 1
|
||||
}
|
||||
});
|
||||
if (restart) {
|
||||
spawn();
|
||||
restart = false;
|
||||
}
|
||||
if (!mustBe) {
|
||||
logger.log(logger.importance[2], 'Crash! ' + e);
|
||||
setTimeout(function() {
|
||||
spawn();
|
||||
}, 1000);
|
||||
}
|
||||
mustBe = false;
|
||||
}
|
||||
|
||||
function criticalProblem(err, e, handler, ...args) {
|
||||
if (!mustBe) {
|
||||
setTimeout(function() {
|
||||
status.running = 2;
|
||||
status.error = err;
|
||||
logger.log(logger.importance[3], 'Critical Problem: ' + errors[err] + '\n' + e);
|
||||
socket.emit('change', {
|
||||
type: 'error',
|
||||
change: {
|
||||
running: 2,
|
||||
error: err
|
||||
}
|
||||
});
|
||||
handler(args)
|
||||
}, 1000);
|
||||
}
|
||||
mustBe = false;
|
||||
}
|
||||
|
||||
function handleDisc(info) {
|
||||
let [host, port] = info;
|
||||
isReachable(host, port, is => {
|
||||
if (is) {
|
||||
spawn();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
handleDisc(info);
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isReachable(host, port, callback) {
|
||||
http.get({
|
||||
host: host.split('/')[0],
|
||||
port: port
|
||||
}, function(res) {
|
||||
callback(true);
|
||||
}).on("error", function(e) {
|
||||
if (e.message == "socket hang up") {
|
||||
setTimeout(function() {
|
||||
callback(true);
|
||||
}, 1000);
|
||||
} else
|
||||
callback(false);
|
||||
});
|
||||
}
|
||||
|
||||
function stopFFMPEG() {
|
||||
cmd.kill('SIGINT');
|
||||
stopTimeout = setTimeout(() => {
|
||||
logger.log(logger.importance[3], "Force Stop!");
|
||||
cmd.kill();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
var commandHandlers = function commandHandlers(command, cb) {
|
||||
var handlers = {
|
||||
startStop: function() {
|
||||
if (restart)
|
||||
return;
|
||||
|
||||
if (status.running !== 2)
|
||||
if (status.running === 0) {
|
||||
logger.log(logger.importance[1], "Stop Command!");
|
||||
mustBe = true;
|
||||
stopFFMPEG();
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Stopped!'
|
||||
}
|
||||
}, command.sender);
|
||||
} else {
|
||||
logger.log(logger.importance[1], "Start Command!");
|
||||
spawn();
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Started!'
|
||||
}
|
||||
}, command.sender);
|
||||
}
|
||||
},
|
||||
snap: function() {
|
||||
getSnap(snap => {
|
||||
socket.emit('data', {
|
||||
type: 'snap',
|
||||
data: snap,
|
||||
}, command.sender);
|
||||
});
|
||||
},
|
||||
config: function() {
|
||||
socket.emit('data', {
|
||||
type: 'config',
|
||||
data: config,
|
||||
}, command.sender);
|
||||
},
|
||||
changeSettings: function() {
|
||||
for (let set in command.data) {
|
||||
if (typeof config[set] !== 'undefined')
|
||||
config[set] = command.data[set];
|
||||
}
|
||||
let oldConfigured;
|
||||
if (config.configured === true)
|
||||
oldConfigured = true;
|
||||
config.configured = true;
|
||||
fs.writeFile(__dirname + '/config.js',
|
||||
JSON.stringify(config,
|
||||
undefined, 2),
|
||||
function(err) {
|
||||
if (err) {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Error',
|
||||
type: 'error',
|
||||
text: 'Can\'t save the Settings!\n' + err.message
|
||||
}
|
||||
}, command.sender);
|
||||
} else {
|
||||
restartSSH(() => {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Settings Saved!'
|
||||
}
|
||||
}, command.sender);
|
||||
if (oldConfigured) {
|
||||
socket.emit('change', {
|
||||
type: 'settings',
|
||||
change: {
|
||||
config: command.data
|
||||
}
|
||||
});
|
||||
stopFFMPEG();
|
||||
spawn();
|
||||
} else {
|
||||
socket.disconnect();
|
||||
init();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
restart: function() {
|
||||
if (status.running === 0) {
|
||||
logger.log(logger.importance[1], "Restart Command!");
|
||||
mustBe = true;
|
||||
restart = true;
|
||||
stopFFMPEG();
|
||||
} else {
|
||||
logger.log(logger.importance[1], "Start Command!");
|
||||
spawn();
|
||||
}
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Restarted!'
|
||||
}
|
||||
}, command.sender);
|
||||
},
|
||||
restartSSH: function() {
|
||||
restartSSH(() => {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Restarted SSH Tunnels!'
|
||||
}
|
||||
}, command.sender);
|
||||
});
|
||||
},
|
||||
getLogs: function() {
|
||||
logger.query({
|
||||
limit: 100
|
||||
}, function(err, data) {
|
||||
data = data.file;
|
||||
if (err) {
|
||||
data = [];
|
||||
} else
|
||||
if (data.length === 0)
|
||||
data = [];
|
||||
socket.emit('data', {
|
||||
type: 'logs',
|
||||
data: data
|
||||
}, command.sender);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//call the handler
|
||||
var call = handlers[command.command];
|
||||
if (call)
|
||||
call();
|
||||
}
|
||||
|
||||
function restartSSH(cb) {
|
||||
exec('forever stop SSH-Serv', () => {
|
||||
connectSSH(() => {
|
||||
socket.emit('change', {
|
||||
change: {
|
||||
ssh: {
|
||||
port: status.ssh.port,
|
||||
camForwardPort: status.ssh.camForwardPort
|
||||
}
|
||||
}
|
||||
});
|
||||
cb();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleKill() {
|
||||
process.stdin.resume();
|
||||
logger.log(logger.importance[0], "Received Shutdown Command");
|
||||
mustBe = true;
|
||||
cmd.kill();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.on('SIGTERM', function() {
|
||||
handleKill();
|
||||
});
|
||||
|
||||
//let's go
|
||||
function init() {
|
||||
config = readConfig();
|
||||
|
||||
if (config.configured) {
|
||||
socket = sock(config.master + '/pi');
|
||||
initSocket();
|
||||
status.name = config.name;
|
||||
if (!cmd)
|
||||
spawn();
|
||||
} else {
|
||||
socket = sock(config.master + '/pi', {
|
||||
query: "unconfigured=true"
|
||||
});
|
||||
status.running = 2;
|
||||
initSocket();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initSSH(cb) {
|
||||
status.ssh = {
|
||||
// that Could come from the Master server!
|
||||
user: config['ssh-user'],
|
||||
localUser: config['ssh-local-user'],
|
||||
masterPort: config['ssh-port']
|
||||
};
|
||||
|
||||
checkSSH((alive) => {
|
||||
if (alive)
|
||||
cb();
|
||||
else
|
||||
connectSSH(cb);
|
||||
});
|
||||
}
|
||||
|
||||
function connectSSH(cb = function() {
|
||||
socket.emit('change', {
|
||||
change: {
|
||||
ssh: {
|
||||
port: status.ssh.port,
|
||||
camForwardPort: status.ssh.camForwardPort
|
||||
}
|
||||
}
|
||||
});
|
||||
}) {
|
||||
socket.emit('getSSHPort', ports => {
|
||||
[status.ssh.port, status.ssh.camForwardPort] = ports;
|
||||
let ssh = exec(`forever start -a --killSignal=SIGINT --uid SSH-Serv sshManager.js ${status.ssh.port} ${status.ssh.camForwardPort} ${config.camPanelPort}`, {
|
||||
detached: true,
|
||||
shell: true,
|
||||
cwd: __dirname
|
||||
});
|
||||
ssh.on('error', (err) => {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Error',
|
||||
type: 'error',
|
||||
text: 'Could not start SSH tunnels!'
|
||||
}
|
||||
}, command.sender);
|
||||
});
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
function checkSSH(cb) {
|
||||
let m, pid, alive;
|
||||
let re = /SSH-Serv.*?sshManager\.js\s([0-9]+)\s([0-9]+).*log.*[^STOPPED]+/g;
|
||||
exec('forever list', (error, stdout, stderr) => {
|
||||
if (error)
|
||||
throw error;
|
||||
let alive = false;
|
||||
while ((m = re.exec(stdout)) !== null) {
|
||||
if (m.index === re.lastIndex) {
|
||||
re.lastIndex++;
|
||||
}
|
||||
if (alive) {
|
||||
exec('forever stop SSH-Serv');
|
||||
cb(false)
|
||||
return;
|
||||
} else {
|
||||
[, status.ssh.port, status.ssh.camForwardPort] = m;
|
||||
alive = true;
|
||||
}
|
||||
}
|
||||
cb(alive);
|
||||
});
|
||||
}
|
||||
|
||||
function initSocket() {
|
||||
socket.on('connect', function() {
|
||||
logger.log(logger.importance[0], 'Connected to Master: ' + config.master + '.');
|
||||
if (config['ssh-user'])
|
||||
initSSH(err => {
|
||||
if (err)
|
||||
throw err;
|
||||
socket.emit('meta', status);
|
||||
});
|
||||
else {
|
||||
socket.emit('meta', status);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnect', function() {
|
||||
socket.disconnect();
|
||||
init();
|
||||
});
|
||||
|
||||
socket.on('command', (command, cb) => {
|
||||
commandHandlers(command, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function readConfig() {
|
||||
return JSON.parse(fs.readFileSync(__dirname + '/config.js'));
|
||||
}
|
||||
|
||||
init();
|
|
@ -1 +0,0 @@
|
|||
hiro@ArLeenUX.857:1492754930
|
|
@ -1 +1 @@
|
|||
46703
|
||||
38259
|
60
main_new.js
Normal file
60
main_new.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* @module Main
|
||||
* @description The main module and entry point.
|
||||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
const ReduxThunk = require('redux-thunk').default;
|
||||
const communicator = require('./src/communicator.js');
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Redux //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Inital State for the app.
|
||||
* @property { Object } stream Stream Status.
|
||||
* @property { bool } stream.running Indicates wether the stream is running.
|
||||
* @property { number | bool } stream.error Error code. Any number outside the range of the Error array in @see ffmpeg-command.js will be treated as non error. Most conveniently set: false.
|
||||
* @property { bool | string } stream.errorHandling Indicates wether the program tries to handle an error.
|
||||
* @property { bool } stream.restaring Indicades wether the stream is currently being restarted.
|
||||
* @property { Object } config Configuration of the camera.
|
||||
*/
|
||||
let initialState = {
|
||||
name: 'Unnamed',
|
||||
stream: {
|
||||
running: 'STOPPED',
|
||||
error: false,
|
||||
reconnecting: false,
|
||||
handleError: false,
|
||||
restaring: false
|
||||
},
|
||||
config: false
|
||||
};
|
||||
|
||||
// Reducer
|
||||
const reducer = require('./src/reducers');
|
||||
|
||||
// Reference to the store of the application state.
|
||||
const store = redux.createStore(reducer, initialState, redux.applyMiddleware(ReduxThunk, communicator.middleware));
|
||||
|
||||
// The dispatch function for the state.
|
||||
const dispatch = store.dispatch;
|
||||
|
||||
// The function to get the state.
|
||||
const getState = store.getState;
|
||||
|
||||
// Simple Action creators
|
||||
const creators = require('./src/actions.js').creators;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Load the Config
|
||||
store.dispatch(creators.updateConfig());
|
||||
|
||||
//const Commander = require('./src/commander.js')(getState);
|
||||
|
||||
// The server Communication
|
||||
const Communicator = new communicator(getState);
|
55
main_new.js~
Normal file
55
main_new.js~
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* @module Main
|
||||
* @description The main module and entry point.
|
||||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
const ReduxThunk = require('redux-thunk').default;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Redux //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Inital State for the app.
|
||||
* @property { Object } stream Stream Status.
|
||||
* @property { bool } stream.running Indicates wether the stream is running.
|
||||
* @property { number | bool } stream.error Error code. Any number outside the range of the Error array in @see ffmpeg-command.js will be treated as non error. Most conveniently set: false.
|
||||
* @property { bool | string } stream.errorHandling Indicates wether the program tries to handle an error.
|
||||
* @property { bool } stream.restaring Indicades wether the stream is currently being restarted.
|
||||
* @property { Object } config Configuration of the camera.
|
||||
*/
|
||||
let initialState = {
|
||||
stream: {
|
||||
running: 'STOPPED',
|
||||
error: false,
|
||||
reconnecting: false,
|
||||
handleError: false,
|
||||
restaring: false
|
||||
},
|
||||
config: {}
|
||||
};
|
||||
|
||||
// Reducer
|
||||
const reducer = require('./src/reducers');
|
||||
|
||||
// Reference to the store of the application state.
|
||||
const store = redux.createStore(reducer, initialState, redux.applyMiddleware(ReduxThunk));
|
||||
|
||||
// The dispatch function for the state.
|
||||
const dispatch = store.dispatch;
|
||||
|
||||
// The function to get the state.
|
||||
const getState = store.getState;
|
||||
|
||||
// Simple Action creators
|
||||
const creators = require('./src/actions.js').creators;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Load the Config
|
||||
store.dispatch(creators.updateConfig());
|
||||
console.log(store.getState());
|
||||
//const Commander = require('./src/commander.js')(getState);
|
|
@ -50,13 +50,13 @@
|
|||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-State.html">State</a></li></ul>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Sat Apr 22 2017 12:09:23 GMT+1200 (NZST)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
|
|
100
out/main_new.js.html
Normal file
100
out/main_new.js.html
Normal file
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: main_new.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: main_new.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* @module Main
|
||||
* @description The main module and entry point.
|
||||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
const ReduxThunk = require('redux-thunk').default;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Redux //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Inital State for the app.
|
||||
* @property { Object } stream Stream Status.
|
||||
* @property { bool } stream.running Indicates wether the stream is running.
|
||||
* @property { number | bool } stream.error Error code. Any number outside the range of the Error array in @see ffmpeg-command.js will be treated as non error. Most conveniently set: false.
|
||||
* @property { bool | string } stream.errorHandling Indicates wether the program tries to handle an error.
|
||||
* @property { bool } stream.restaring Indicades wether the stream is currently being restarted.
|
||||
* @property { Object } config Configuration of the camera.
|
||||
*/
|
||||
let initialState = {
|
||||
stream: {
|
||||
running: 'STOPPED',
|
||||
error: false,
|
||||
reconnecting: false,
|
||||
handleError: false,
|
||||
restaring: false
|
||||
},
|
||||
config: {}
|
||||
};
|
||||
|
||||
// Reducer
|
||||
const reducer = require('./reducers');
|
||||
|
||||
// Reference to the store of the application state.
|
||||
const store = redux.createStore(reducer, initialState);
|
||||
|
||||
// The dispatch function for the state.
|
||||
const dispatch = store.dispatch;
|
||||
|
||||
// The function to get the state.
|
||||
const getState = store.getState;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const Commander = require('./src/commander.js')(getState);
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
295
out/module-Actions.html
Normal file
295
out/module-Actions.html
Normal file
|
@ -0,0 +1,295 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: Actions</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: Actions</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Outsourced definition of the actions and simple action creators for simple actions.</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_actions.js.html">src/actions.js</a>, <a href="src_actions.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-todo">To Do:</dt>
|
||||
<dd class="tag-todo">
|
||||
<ul>
|
||||
<li>allowed values</li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Members</h3>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~actions"><span class="type-signature">(inner) </span>actions<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Actions
|
||||
The action definitions.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_actions.js.html">src/actions.js</a>, <a href="src_actions.js.html#line13">line 13</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~creators"><span class="type-signature">(inner) </span>creators<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Trivial Action Creators
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_actions.js.html">src/actions.js</a>, <a href="src_actions.js.html#line27">line 27</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
320
out/module-Commander-Commander.html
Normal file
320
out/module-Commander-Commander.html
Normal file
|
@ -0,0 +1,320 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Class: Commander</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Class: Commander</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
<h2>
|
||||
<span class="ancestors"><a href="module-Commander.html">Commander</a>~</span>Commander</h2>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="Commander"><span class="type-signature"></span>new Commander<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Interface to the ffmpeg process. Uses fluent-ffmpeg.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line46">line 46</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~createCommand"><span class="type-signature">(inner) </span>createCommand<span class="signature">(config)</span><span class="type-signature"> → {Object}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
(Re)Create the ffmpeg command and configure it.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>config</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">The configuration for the stream.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line62">line 62</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
The fluent-ffmpeg command object.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:46 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
649
out/module-Commander.html
Normal file
649
out/module-Commander.html
Normal file
|
@ -0,0 +1,649 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: Commander</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: Commander</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">A Wrapper for Fluent-FFMPEG with a custom command.</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Classes</h3>
|
||||
|
||||
<dl>
|
||||
<dt><a href="module-Commander-Commander.html">Commander</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Members</h3>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~cmd"><span class="type-signature">(inner) </span>cmd<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
The FFMPEG command.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line22">line 22</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~crashed"><span class="type-signature">(inner) </span>crashed<span class="signature">(error, stdout, stderr)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Log and handle crashes. Notify the main module.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>error</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Error object from the crash.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>stdout</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">String</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>stderr</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">String</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line174">line 174</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~stopped"><span class="type-signature">(inner) </span>stopped<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Utilities
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line138">line 138</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~tryReconnect"><span class="type-signature">(inner) </span>tryReconnect<span class="signature">(host, port)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Probe the connection to the host on the port and restart the stream afterwards.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>host</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>port</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">number</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_commander.js.html">src/commander.js</a>, <a href="src_commander.js.html#line211">line 211</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
423
out/module-Main.html
Normal file
423
out/module-Main.html
Normal file
|
@ -0,0 +1,423 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: Main</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: Main</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">The main module and entry point.</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="main_new.js.html">main_new.js</a>, <a href="main_new.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Members</h3>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~initialState"><span class="type-signature">(inner) </span>initialState<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Inital State for the app.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5 class="subsection-title">Properties:</h5>
|
||||
|
||||
|
||||
|
||||
<table class="props">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>stream</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Stream Status.
|
||||
<h6>Properties</h6>
|
||||
|
||||
<table class="props">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>running</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">bool</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Indicates wether the stream is running.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>error</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">number</span>
|
||||
|
|
||||
|
||||
<span class="param-type">bool</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Error code. Any number outside the range of the Error array in @see ffmpeg-command.js will be treated as non error. Most conveniently set: false.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>errorHandling</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">bool</span>
|
||||
|
|
||||
|
||||
<span class="param-type">string</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Indicates wether the program tries to handle an error.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>restaring</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">bool</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Indicades wether the stream is currently being restarted.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>config</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">Configuration of the camera.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="main_new.js.html">main_new.js</a>, <a href="main_new.js.html#line22">line 22</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:46 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
581
out/module-Reducers.html
Normal file
581
out/module-Reducers.html
Normal file
|
@ -0,0 +1,581 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: Reducers</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: Reducers</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Outsourced definition of the Reducers for redux.</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_reducers.js.html">src/reducers.js</a>, <a href="src_reducers.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-see">See:</dt>
|
||||
<dd class="tag-see">
|
||||
<ul>
|
||||
<li><a href="http://redux.js.org/docs/basics/Reducers.html">http://redux.js.org/docs/basics/Reducers.html</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~config"><span class="type-signature">(inner) </span>config<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Updates the config state.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_reducers.js.html">src/reducers.js</a>, <a href="src_reducers.js.html#line81">line 81</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~error"><span class="type-signature">(inner) </span>error<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Set the error code. @see ffmpegCommand.js for the error code descriptions.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_reducers.js.html">src/reducers.js</a>, <a href="src_reducers.js.html#line21">line 21</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~handleError"><span class="type-signature">(inner) </span>handleError<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Set the error handling procedure.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_reducers.js.html">src/reducers.js</a>, <a href="src_reducers.js.html#line36">line 36</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~running"><span class="type-signature">(inner) </span>running<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Set the running flag.
|
||||
It can either be RUNNING, STARTING, STOPPING or STOPPED
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_reducers.js.html">src/reducers.js</a>, <a href="src_reducers.js.html#line53">line 53</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~stream"><span class="type-signature">(inner) </span>stream<span class="signature">()</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Stream Root Reducer.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_reducers.js.html">src/reducers.js</a>, <a href="src_reducers.js.html#line68">line 68</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:46 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
460
out/module-Streamer-Streamer.html
Normal file
460
out/module-Streamer-Streamer.html
Normal file
|
@ -0,0 +1,460 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Class: Streamer</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Class: Streamer</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
<h2>
|
||||
<span class="ancestors"><a href="module-Streamer.html">Streamer</a>~</span>Streamer</h2>
|
||||
|
||||
<div class="class-description">Streamer
|
||||
The central control Object (singleton for now) which has the permission to change state.</div>
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Constructor</h2>
|
||||
|
||||
|
||||
<h4 class="name" id="Streamer"><span class="type-signature"></span>new Streamer<span class="signature">(communicator)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
<th>Default</th>
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>communicator</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="default">
|
||||
|
||||
false
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td class="description last">A communicator object. @see communicator.js - Optional //TODO: Find proper tag.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line59">line 59</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="getConfig"><span class="type-signature"></span>getConfig<span class="signature">()</span><span class="type-signature"> → {*}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Get the current config.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line91">line 91</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
The current config.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">*</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="setCommunicator"><span class="type-signature"></span>setCommunicator<span class="signature">(communicator)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Set the communicator object and enable the state sync with the server.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>communicator</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">A communicator object. @see communicator.js</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line80">line 80</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:46 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: State</title>
|
||||
<title>JSDoc: Module: Streamer</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: State</h1>
|
||||
<h1 class="page-title">Module: Streamer</h1>
|
||||
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
|||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Redux Wrapper to hold the state and communicate with the Server</div>
|
||||
<div class="description">The central interface to the streaming process.</div>
|
||||
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@
|
|||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="status.js.html">status.js</a>, <a href="status.js.html#line1">line 1</a>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
@ -122,6 +122,13 @@
|
|||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Classes</h3>
|
||||
|
||||
<dl>
|
||||
<dt><a href="module-Streamer-Streamer.html">Streamer</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -132,13 +139,13 @@
|
|||
|
||||
|
||||
|
||||
<h4 class="name" id="~ActionDispatchers"><span class="type-signature">(inner) </span>Action Dispatchers<span class="type-signature"></span></h4>
|
||||
<h4 class="name" id="~_communicator"><span class="type-signature">(inner) </span>_communicator<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
The central redux state manager. The module exposes central action dispatchers. Updates to the state get communicated to the server.
|
||||
The socket.io connection from the main-module.
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -176,7 +183,7 @@
|
|||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="status.js.html">status.js</a>, <a href="status.js.html#line54">line 54</a>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line35">line 35</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
@ -407,7 +414,7 @@
|
|||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="status.js.html">status.js</a>, <a href="status.js.html#line23">line 23</a>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line22">line 22</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
@ -424,24 +431,14 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~reducer"><span class="type-signature">(inner, constant) </span>reducer<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="~applyDispatchers"><span class="type-signature">(inner) </span>applyDispatchers<span class="signature">(creators)</span><span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Adds prototypes for the action dispatchers to the State.
|
||||
Redux Actions
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -450,61 +447,6 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>creators</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last"></td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
@ -534,7 +476,7 @@
|
|||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="status.js.html">status.js</a>, <a href="status.js.html#line114">line 114</a>
|
||||
<a href="src_streamer.js.html">src/streamer.js</a>, <a href="src_streamer.js.html#line41">line 41</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
@ -550,46 +492,9 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Throws:</h5>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<div class="param-desc">
|
||||
If a method with the creators name already exists. @see actionCreators.js
|
||||
</div>
|
||||
</dt>
|
||||
<dd></dd>
|
||||
<dt>
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Error</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
</dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -605,13 +510,13 @@
|
|||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-State.html">State</a></li></ul>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Sat Apr 22 2017 12:09:23 GMT+1200 (NZST)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:46 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
423
out/module-Utilities_Config.html
Normal file
423
out/module-Utilities_Config.html
Normal file
|
@ -0,0 +1,423 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Module: Utilities/Config</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Module: Utilities/Config</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
|
||||
<header>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<div class="container-overview">
|
||||
|
||||
|
||||
<div class="description">Config read/write utilities.</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_utility_config.js.html">src/utility/config.js</a>, <a href="src_utility_config.js.html#line1">line 1</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3 class="subsection-title">Methods</h3>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id=".read"><span class="type-signature">(static) </span>read<span class="signature">()</span><span class="type-signature"> → {Object|bool}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Read the JSON config file.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_utility_config.js.html">src/utility/config.js</a>, <a href="src_utility_config.js.html#line18">line 18</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
Returns the parsed config or false in case of an error.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
|
||||
|
||||
<span class="param-type">bool</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id=".write"><span class="type-signature">(static) </span>write<span class="signature">(state)</span><span class="type-signature"> → {Promise}</span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="description">
|
||||
Writes the config to disk.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Parameters:</h5>
|
||||
|
||||
|
||||
<table class="params">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>state</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">Object</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">A function to retrieve the current state. This makes it harder to accidentially write arbitrary code.</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="src_utility_config.js.html">src/utility/config.js</a>, <a href="src_utility_config.js.html#line32">line 32</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5>Returns:</h5>
|
||||
|
||||
|
||||
<div class="param-desc">
|
||||
A promise for writing the configuration.
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
Type
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
<span class="param-type">Promise</span>
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:46 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
137
out/src_actions.js.html
Normal file
137
out/src_actions.js.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: src/actions.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: src/actions.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** Outsourced definition of the actions and simple action creators for simple actions.
|
||||
* @module Actions
|
||||
* @todo allowed values
|
||||
*/
|
||||
|
||||
const Promise = require('promise');
|
||||
const writeConfig = require('./utility/config.js').write;
|
||||
|
||||
/**
|
||||
* Actions
|
||||
* The action definitions.
|
||||
*/
|
||||
let actions = {
|
||||
UPDATE_CONFIG: 'UPDATE_CONFIG',
|
||||
REQUEST_START: 'REQUEST_START',
|
||||
SET_STARTED: 'SET_STATED',
|
||||
REQUEST_STOP: 'REQUEST_STOP',
|
||||
SET_STOPPED: 'SET_STOPPED',
|
||||
REQUEST_RESTART: 'REQUEST_RESTART',
|
||||
SET_ERROR: 'SET_ERROR',
|
||||
TRY_RECONECT: 'TRY_RECONNECT'
|
||||
};
|
||||
|
||||
/**
|
||||
* Trivial Action Creators
|
||||
*/
|
||||
let creators = {};
|
||||
|
||||
creators.updateConfig = function(update) {
|
||||
return function(dispatch, getState) {
|
||||
dispatch({
|
||||
type: actions.UPDATE_CONFIG,
|
||||
data: update
|
||||
});
|
||||
|
||||
return writeConfig(getState());
|
||||
};
|
||||
};
|
||||
|
||||
creators.requestStart = function() {
|
||||
return {
|
||||
type: actions.REQUEST_START
|
||||
};
|
||||
};
|
||||
|
||||
creators.requestStop = function() {
|
||||
return {
|
||||
type: actions.REQUEST_STOP
|
||||
};
|
||||
};
|
||||
|
||||
creators.setStarted = function() {
|
||||
return {
|
||||
type: actions.SET_STARTED
|
||||
};
|
||||
};
|
||||
|
||||
creators.setStopped = function() {
|
||||
return {
|
||||
type: actions.SET_STOPPED
|
||||
};
|
||||
};
|
||||
|
||||
creators.requestRestart = function() {
|
||||
return {
|
||||
type: actions.REQUEST_RESTART
|
||||
};
|
||||
};
|
||||
|
||||
creators.setError = function(error) {
|
||||
return {
|
||||
type: actions.SET_ERROR,
|
||||
data: error
|
||||
};
|
||||
};
|
||||
|
||||
creators.tryReconnect = function() {
|
||||
return {
|
||||
type: actions.TRY_RECONECT
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
actions,
|
||||
creators
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
294
out/src_commander.js.html
Normal file
294
out/src_commander.js.html
Normal file
|
@ -0,0 +1,294 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: src/commander.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: src/commander.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/**
|
||||
* @module Commander
|
||||
* @description A Wrapper for Fluent-FFMPEG with a custom command.
|
||||
*/
|
||||
|
||||
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const http = require('http');
|
||||
const logger = require('./logger');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Reference to itself. (Object oriented this. Only used to call public methods.)
|
||||
let self = false;
|
||||
|
||||
/**
|
||||
* The FFMPEG command.
|
||||
* @member
|
||||
*/
|
||||
let cmd = ffmpeg({
|
||||
stdoutLines: 20
|
||||
});
|
||||
|
||||
// The Config, Logger and a handle for the kill timeout.
|
||||
let _config, _stopHandle = false, _connectHandle = false;
|
||||
|
||||
// Error Texts //TODO put them into separate module
|
||||
let errorDescriptions = ['Camera Disconnected',
|
||||
'YoutTube Disconnected',
|
||||
'Wrong ffmpeg executable.',
|
||||
'Unknown Error - Restarting'];
|
||||
|
||||
// The stream source url. Yet to be set.
|
||||
let source = "";
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Interface to the ffmpeg process. Uses fluent-ffmpeg.
|
||||
* @constructor
|
||||
*/
|
||||
let Commander = function(){
|
||||
// singleton
|
||||
if(self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if(!(this instanceof Commander))
|
||||
return new Commander();
|
||||
|
||||
self = this;
|
||||
|
||||
/**
|
||||
* (Re)Create the ffmpeg command and configure it.
|
||||
* @param { Object } config The configuration for the stream.
|
||||
* @returns { Object } The fluent-ffmpeg command object.
|
||||
*/
|
||||
let createCommand = function(config) {
|
||||
// Clear inputs
|
||||
cmd._inputs = [];
|
||||
|
||||
// TODO: Multi Protocol
|
||||
source = 'rtsp://' + config.camIP + ':' + config.camPort + '/' + config.camProfile;
|
||||
cmd.input(source);
|
||||
|
||||
// Custom config if any.
|
||||
if (config.customOutputOptions !== "")
|
||||
cmd.outputOptions(config.customOutputOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
|
||||
if (config.customAudioOptions !== "")
|
||||
cmd.outputOptions(config.customAudioOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.AudioCodec('copy');
|
||||
|
||||
if (config.customVideoOptions !== "")
|
||||
cmd.outputOptions(config.customVideoOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.videoCodec('copy');
|
||||
|
||||
// Output Options.
|
||||
cmd.outputFormat('flv')
|
||||
.outputOptions(['-bufsize 50000k', '-tune film'])
|
||||
.output('rtmp://a.rtmp.youtube.com/live2/' + config.key);
|
||||
|
||||
// Register events.
|
||||
cmd.on('start', started);
|
||||
|
||||
cmd.on('end', stopped);
|
||||
|
||||
cmd.on('error', crashed);
|
||||
|
||||
return cmd;
|
||||
};
|
||||
|
||||
let ffmpegCommand = function() {
|
||||
return cmd;
|
||||
};
|
||||
|
||||
// NOTE: Maybe better error resolving strategy.
|
||||
// Start streaming.
|
||||
let start = function() {
|
||||
// Ignore if we try to reconnect.
|
||||
if(_connectHandle)
|
||||
return;
|
||||
|
||||
cmd.run();
|
||||
};
|
||||
|
||||
// Restart the stream;
|
||||
let restart = function() {
|
||||
if(status.streaming) {
|
||||
restart = true; // NOTE: not very nice
|
||||
this.stop();
|
||||
} else
|
||||
this.start();
|
||||
};
|
||||
|
||||
// Stop streaming.
|
||||
let stop = function() {
|
||||
cmd.kill('SIGINT');
|
||||
|
||||
_stopHandle = setTimeout(() => {
|
||||
logger.log(logger.importance[3], "Force Stop!");
|
||||
cmd.kill();
|
||||
}, 3000);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
// Handle Stop and Restart
|
||||
function stopped() {
|
||||
status.streaming = false;
|
||||
|
||||
// Clear force kill Timeout
|
||||
if(stopTimeout) {
|
||||
clearTimeout(stopTimeout);
|
||||
stopTimeout = false;
|
||||
}
|
||||
|
||||
// Restart the stream;
|
||||
if (restart) {
|
||||
self.start();
|
||||
}
|
||||
|
||||
cmd.emit('stopped');
|
||||
}
|
||||
|
||||
// TODO: Restart = false in stopped?
|
||||
// Hande Stat
|
||||
function started() {
|
||||
cmd.emit(restart ? 'restarted' : 'started');
|
||||
restart = false;
|
||||
status.error = false;
|
||||
status.streaming = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error Handling
|
||||
*/
|
||||
|
||||
/**
|
||||
* Log and handle crashes. Notify the main module.
|
||||
* @param { Object } error - Error object from the crash.
|
||||
* @param { String } stdout
|
||||
* @param { String } stderr
|
||||
*/
|
||||
function crashed(error, stdout, stderr){
|
||||
// Can't connect to the
|
||||
if (err.message.indexOf(source) > -1)
|
||||
status.error = 0;
|
||||
|
||||
// Can't connect to the Internet / YouTube
|
||||
else if (err.message.indexOf(source + 'Input/output error') > -1 || err.message.indexOf('rtmp://a.rtmp.youtube.com/live2/' + _config.key) > -1)
|
||||
status.error = 1;
|
||||
|
||||
// Wrong FFMPEG Executable
|
||||
else if (err.message.indexOf('spawn') > -1 || err.message.indexOf('niceness') > -1)
|
||||
status.error = 2;
|
||||
|
||||
// Stopped by us - SIGINT Shouldn't lead to a crash.
|
||||
else if (err.message.indexOf('SIGINT') > -1 || err.message.indexOf('SIGKILL') > -1){
|
||||
stopped();
|
||||
return;
|
||||
}
|
||||
|
||||
// Some unknown Problem, just try to restart.
|
||||
else {
|
||||
status.error = 3;
|
||||
|
||||
// Just restart in a Second
|
||||
setTimeout(function(){
|
||||
self.start();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
logger.log(logger.importance[2], `Crashed: ${erro}\nSTDERR: ${stderr}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe the connection to the host on the port and restart the stream afterwards.
|
||||
* @param { string } host
|
||||
* @param { number } port
|
||||
*/
|
||||
function tryReconnect( host, port ){
|
||||
if (!host || !port)
|
||||
return;
|
||||
|
||||
http.get({
|
||||
host: host.split('/')[0],
|
||||
port: port
|
||||
}, function(res) {
|
||||
// We have a response! Connection works.
|
||||
setTimeout(function() {
|
||||
// NOTE: Ugly!
|
||||
|
||||
// We have a response! Connection works.
|
||||
_connectHandle = false;
|
||||
self.start();
|
||||
}, 1000);
|
||||
}).on("error", function(e) {
|
||||
if (e.message == "socket hang up") {
|
||||
setTimeout(function() {
|
||||
// NOTE: Ugly!
|
||||
|
||||
// We have a response! Connection works.
|
||||
_connectHandle = false;
|
||||
self.start();
|
||||
}, 1000);
|
||||
} else {
|
||||
// try again
|
||||
_connectHandle = setTimeout(function(){
|
||||
tryReconnect(host, port);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
130
out/src_logger.js.html
Normal file
130
out/src_logger.js.html
Normal file
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: src/logger.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: src/logger.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>///////////////////////////////////////////////////////////////////////////////
|
||||
// Winston Logger Wrapper with Custom Colors and Transports //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let winston = require('winston');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
// Custom log levels.
|
||||
const customLevels = {
|
||||
levels: {
|
||||
normal: 0,
|
||||
info: 1,
|
||||
warning: 2,
|
||||
danger: 3,
|
||||
success: 4
|
||||
},
|
||||
colors: {
|
||||
normal: 'white',
|
||||
info: 'blue',
|
||||
warning: 'orange',
|
||||
danger: 'red',
|
||||
success: 'green'
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Monkey Patching.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Calls the logging function with arguments, if the node enviroment isn't in production mode.
|
||||
*/
|
||||
winston.Logger.prototype.dbgmsg = function() {
|
||||
if (process.env.NODE_ENV !== 'production')
|
||||
this.log.apply(undefined, arguments);
|
||||
};
|
||||
|
||||
// Set the Colors
|
||||
winston.addColors(customLevels.colors);
|
||||
|
||||
let logger = (function() {
|
||||
if(!self)
|
||||
self = new(winston.Logger)({
|
||||
levels: customLevels.levels,
|
||||
transports: [
|
||||
new(winston.transports.Console)({
|
||||
level: 'success'
|
||||
}),
|
||||
new(winston.transports.File)({
|
||||
filename: __dirname + '/process.log',
|
||||
colorize: true,
|
||||
timestamp: true,
|
||||
level: 'success',
|
||||
json: true,
|
||||
maxsize: 500000,
|
||||
maxFiles: 10
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
return self;
|
||||
})();
|
||||
|
||||
logger.importance = ['normal', 'info', 'warning', 'danger', 'success'];
|
||||
|
||||
// Export the Logger
|
||||
module.exports = logger;
|
||||
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
146
out/src_reducers.js.html
Normal file
146
out/src_reducers.js.html
Normal file
|
@ -0,0 +1,146 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: src/reducers.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: src/reducers.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** Outsourced definition of the Reducers for redux.
|
||||
* @see {@link http://redux.js.org/docs/basics/Reducers.html}
|
||||
* @module Reducers
|
||||
*/
|
||||
|
||||
const redux = srequire('redux');
|
||||
const { UPDATE_CONFIG,
|
||||
REQUEST_START,
|
||||
SET_STARTED,
|
||||
REQUEST_STOP,
|
||||
SET_STOPPED,
|
||||
REQUEST_RESTART,
|
||||
SET_ERROR,
|
||||
TRY_RECONECT}= require('./actions');
|
||||
|
||||
let reducers = {};
|
||||
|
||||
/**
|
||||
* Set the error code. @see ffmpegCommand.js for the error code descriptions.
|
||||
*/
|
||||
function error(state = false, action) {
|
||||
switch (action.type) {
|
||||
case SET_ERROR:
|
||||
return action.data;
|
||||
case SET_STARTED:
|
||||
return false;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Add central definition
|
||||
/**
|
||||
* Set the error handling procedure.
|
||||
*/
|
||||
function handleError(state = false, action) {
|
||||
switch (action.type) {
|
||||
case SET_STARTED:
|
||||
return false;
|
||||
case TRY_RECONECT:
|
||||
return 'RECONNECTING';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the running flag.
|
||||
* It can either be RUNNING, STARTING, STOPPING or STOPPED
|
||||
*/
|
||||
function running(state = 'STOPPED', action) {
|
||||
switch (action.type) {
|
||||
case REQUEST_START:
|
||||
return 'STARTING';
|
||||
case SET_STARTED:
|
||||
return 'RUNNING';
|
||||
case REQUEST_STOP:
|
||||
return 'STOPPING';
|
||||
case SET_STOPPED:
|
||||
return 'STOPPED';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @function stream
|
||||
* @description Stream Root Reducer.
|
||||
*/
|
||||
reducers.stream = function(state = {}, action){
|
||||
return {
|
||||
running: running(state, action),
|
||||
error: error(state, action),
|
||||
handleError: handleError(state, action),
|
||||
restarting: restarting(state, action)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @function config
|
||||
* @description Updates the config state.
|
||||
*/
|
||||
reducers.config = function(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case UPDATE_CONFIG:
|
||||
return Object.assign({}, state, action.data);
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = redux.combineReducers(reducers);
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: status.js</title>
|
||||
<title>JSDoc: Source: src/streamer.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: status.js</h1>
|
||||
<h1 class="page-title">Source: src/streamer.js</h1>
|
||||
|
||||
|
||||
|
||||
|
@ -26,11 +26,10 @@
|
|||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** Redux Wrapper to hold the state and communicate with the Server
|
||||
* @module State
|
||||
<pre class="prettyprint source linenums"><code>/** The central interface to the streaming process.
|
||||
* @module Streamer
|
||||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
const logger = require('./logger');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -50,23 +49,22 @@ let self = false;
|
|||
*/
|
||||
let initialState = {
|
||||
stream: {
|
||||
running: false,
|
||||
running: 'STOPPED',
|
||||
error: -1,
|
||||
reconnecting: false
|
||||
reconnecting: false,
|
||||
restarting: false
|
||||
},
|
||||
config: {}
|
||||
}; // NOTE: Maybe in main.js
|
||||
|
||||
// The socket.io connection from the main-module.
|
||||
/**
|
||||
* The socket.io connection from the main-module.
|
||||
*/
|
||||
let _communicator;
|
||||
|
||||
// Actions
|
||||
const actions = require('./actions');
|
||||
|
||||
// Action Creators
|
||||
const creators = require('./actionCreators');
|
||||
const dispatchers = redux.bindActionCreators(creators);
|
||||
|
||||
|
||||
/**
|
||||
* Redux Actions
|
||||
*/
|
||||
// Reducer
|
||||
const reducer = require('./reducers');
|
||||
|
||||
|
@ -80,20 +78,20 @@ const store = redux.createStore(reducer, initialState);
|
|||
// TODO: Log state changes.
|
||||
|
||||
/**
|
||||
* The central redux state manager. The module exposes central action dispatchers. Updates to the state get communicated to the server.
|
||||
*
|
||||
* @class Streamer
|
||||
* The central control Object (singleton for now) which has the permission to change state.
|
||||
*
|
||||
* @constructor
|
||||
* @member [Action Dispatchers] The action creators (@see actionCreators.js) are bound to the dispatch function and made member of the State object.
|
||||
* @param { Object } communicator A communicator object. @see communicator.js - Optional //TODO: Find proper tag.
|
||||
*/
|
||||
function State(communicator = false) {
|
||||
function Streamer(communicator = false) {
|
||||
// singleton
|
||||
if (self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if (!(this instanceof State))
|
||||
return new State(_communicator);
|
||||
if (!(this instanceof Streamer))
|
||||
return new Streamer(_communicator);
|
||||
|
||||
_communicator = communicator;
|
||||
|
||||
|
@ -101,58 +99,31 @@ function State(communicator = false) {
|
|||
return this;
|
||||
};
|
||||
|
||||
applyDispatchers(creators);
|
||||
module.exports = Streamer;
|
||||
|
||||
/**
|
||||
* Set the communicator object and enable the state sync with the server.
|
||||
* @param {Object} communicator A communicator object. @see communicator.js
|
||||
*/
|
||||
State.prototype.setCommunicator = function(communicator) {
|
||||
Streamer.prototype.setCommunicator = function(communicator) {
|
||||
if (_communicator)
|
||||
_communicator = communicator;
|
||||
else
|
||||
logger.dbgmsdg("Invalid Communicator");
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper for redux.
|
||||
* @returns { Object } The current state.
|
||||
*/
|
||||
State.prototype.getState = function(){
|
||||
return store.getState();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current config.
|
||||
* @returns { * } The current config.
|
||||
*/
|
||||
State.prototype.getConfig = function(){
|
||||
return store.getState().config;
|
||||
Streamer.prototype.getConfig = function(){
|
||||
return store.getStreamer().config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds prototypes for the action dispatchers to the State.
|
||||
* @param { Object } creators
|
||||
* @throws { Error } If a method with the creators name already exists. @see actionCreators.js
|
||||
*/
|
||||
function applyDispatchers( creators ){
|
||||
for(let creator in creators){
|
||||
if(State.prototype[creator])
|
||||
throw new Error(`State has already a meber '${creator}'.`);
|
||||
|
||||
State.prototype[creator] = function(){
|
||||
store.dispatch(creators[creator].apply(undefined, arguments));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = State;
|
||||
|
||||
|
||||
|
||||
</code></pre>
|
||||
|
@ -165,13 +136,13 @@ module.exports = State;
|
|||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-State.html">State</a></li></ul>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Sat Apr 22 2017 12:09:23 GMT+1200 (NZST)
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
94
out/src_utility_config.js.html
Normal file
94
out/src_utility_config.js.html
Normal file
|
@ -0,0 +1,94 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>JSDoc: Source: src/utility/config.js</title>
|
||||
|
||||
<script src="scripts/prettify/prettify.js"> </script>
|
||||
<script src="scripts/prettify/lang-css.js"> </script>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
||||
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<h1 class="page-title">Source: src/utility/config.js</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section>
|
||||
<article>
|
||||
<pre class="prettyprint source linenums"><code>/** Config read/write utilities.
|
||||
* @module Utilities/Config
|
||||
*/
|
||||
|
||||
const Promise = require('promise');
|
||||
const fs = require('fs');
|
||||
const logger = require('./logger.js');
|
||||
|
||||
// TODO: Config path in defs
|
||||
|
||||
module.exports = {};
|
||||
|
||||
// TODO Default CFG
|
||||
/**
|
||||
* Read the JSON config file.
|
||||
* @returns { Object | bool } Returns the parsed config or false in case of an error.
|
||||
*/
|
||||
module.exports.read = function() {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(__dirname + '/config.js'));
|
||||
} catch (e) {
|
||||
logger.dbgmsg(e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes the config to disk.
|
||||
* @param {Object} state A function to retrieve the current state. This makes it harder to accidentially write arbitrary code.
|
||||
* @returns { Promise } A promise for writing the configuration.
|
||||
*/
|
||||
module.exports.write = function( getState ){
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(__dirname + '/config.js',
|
||||
JSON.stringify(getState().config, undefined, 2),
|
||||
err => {
|
||||
if(err)
|
||||
reject(err);
|
||||
else
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Actions.html">Actions</a></li><li><a href="module-Commander.html">Commander</a></li><li><a href="module-Main.html">Main</a></li><li><a href="module-Reducers.html">Reducers</a></li><li><a href="module-Streamer.html">Streamer</a></li><li><a href="module-Utilities_Config.html">Utilities/Config</a></li></ul><h3>Classes</h3><ul><li><a href="module-Commander-Commander.html">Commander</a></li><li><a href="module-Streamer-Streamer.html">Streamer</a></li></ul>
|
||||
</nav>
|
||||
|
||||
<br class="clear">
|
||||
|
||||
<footer>
|
||||
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Mon Apr 24 2017 18:52:45 GMT+1200 (NZST)
|
||||
</footer>
|
||||
|
||||
<script> prettyPrint(); </script>
|
||||
<script src="scripts/linenumber.js"> </script>
|
||||
</body>
|
||||
</html>
|
|
@ -10,7 +10,9 @@
|
|||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"fluent-ffmpeg": "^2.1.0",
|
||||
"promise": "^7.1.1",
|
||||
"redux": "^3.6.0",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"socket.io-client": "^1.4.8",
|
||||
"winston": "^2.2.0"
|
||||
}
|
||||
|
|
72
src/#logger.js#
Normal file
72
src/#logger.js#
Normal file
|
@ -0,0 +1,72 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Winston Logger Wrapper with Custom Colors and Transports //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let winston = require('winston');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
// Custom log levels.
|
||||
const customLevels = {
|
||||
levels: {
|
||||
normal: 0,
|
||||
info: 1,
|
||||
warning: 2,
|
||||
danger: 3,
|
||||
success: 4
|
||||
},
|
||||
colors: {
|
||||
normal: 'white',
|
||||
info: 'blue',
|
||||
warning: 'orange',
|
||||
danger: 'red',
|
||||
success: 'green'
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Monkey Patching.
|
||||
|
||||
/**
|
||||
* Calls the logging function with arguments, if the node enviroment isn't in production mode.
|
||||
*/
|
||||
|
||||
// Set the Colors
|
||||
winston.addColors(customLevels.colors);
|
||||
|
||||
let logger = (function() {
|
||||
if(!self)
|
||||
self = new(winston.Logger)({
|
||||
levels: customLevels.levels,
|
||||
transports: [
|
||||
new(winston.transports.Console)({
|
||||
p level: 'success'
|
||||
}),
|
||||
new(winston.transports.File)({
|
||||
filename: __dirname + '/process.log',
|
||||
colorize: true,
|
||||
timestamp: true,
|
||||
level: 'success',
|
||||
json: true,
|
||||
maxsize: 500000,
|
||||
maxFiles: 10
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
return self;
|
||||
})();
|
||||
|
||||
logger.importance = ['normal', 'info', 'warning', 'danger', 'success'];
|
||||
|
||||
// Export the Logger
|
||||
module.exports = logger;
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Reducers //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const redux = require('redux');
|
||||
const actions = require('./actions');
|
||||
|
||||
let reducers = {};
|
||||
|
||||
/**
|
||||
* Set the streaming/error state.
|
||||
*/
|
||||
reducers.error = function(state = -1, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_ERROR:
|
||||
if((typeof action.data) == 'undefined') {
|
||||
return action.data;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the streaming state.
|
||||
*/
|
||||
|
||||
reducers.streaming = function(state = 'STOPPED', action) {
|
||||
switch (action.type) {
|
||||
case actions.REQUEST_START:
|
||||
case actions.REQEST_STOP:
|
||||
return 'STOPPING'
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the restart flag.
|
||||
*
|
||||
* The restart flag get's automaticly unset, as soon as the start action gets reduced.
|
||||
*/
|
||||
|
||||
reducers.restart = function(state = false, action) {
|
||||
switch (action.type) {
|
||||
case actions.RESTART:
|
||||
return true;
|
||||
case actions.START:
|
||||
return false;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Update the config.
|
||||
*/
|
||||
reducers.config = function(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case actions.UPDATE_CONFIG:
|
||||
return Object.assign({}, state, action.data);
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = redux.combineReducers(reducers);
|
71
src/#streamer.js#
Normal file
71
src/#streamer.js#
Normal file
|
@ -0,0 +1,71 @@
|
|||
/** The central interface to the streaming process.
|
||||
* @module Streamer
|
||||
*/
|
||||
|
||||
const logger = require('./logger');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: Log state changes.
|
||||
|
||||
/**
|
||||
* @class Streamer
|
||||
* The central control Object (singleton for now) which has the permission to change state.
|
||||
*
|
||||
* @constructor
|
||||
* @param { Object } communicator A communicator object. @see communicator.js - Optional //TODO: Find proper tag.
|
||||
*/
|
||||
function Streamer(communicator = false) {
|
||||
// singleton
|
||||
if (self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if (!(this instanceof Streamer))
|
||||
return new Streamer(_communicator);
|
||||
|
||||
_communicator = communicator;
|
||||
|
||||
self = this;
|
||||
return this;
|
||||
};
|
||||
|
||||
module.exports = Streamer;
|
||||
|
||||
/**
|
||||
* Set the communicator object and enable the state sync with the server.
|
||||
* @param {Object} communicator A communicator object. @see communicator.js
|
||||
*/
|
||||
Streamer.prototype.setCommunicator = function(communicator) {
|
||||
if (_communicator)
|
||||
_communicator = communicator;
|
||||
else
|
||||
logger.dbgmsdg("Invalid Communicator");
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current config.
|
||||
* @returns { * } The current config.
|
||||
*/
|
||||
Streamer.prototype.getConfig = function(){
|
||||
return store.getStreamer().config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
|
||||
|
1
src/.#logger.js
Symbolic link
1
src/.#logger.js
Symbolic link
|
@ -0,0 +1 @@
|
|||
hiro@ArLeenUX.3138:1493100086
|
|
@ -1 +0,0 @@
|
|||
hiro@ArLeenUX.857:1492754930
|
|
@ -1,66 +0,0 @@
|
|||
/**
|
||||
* Action Creators
|
||||
*
|
||||
* The action creators create actions to alter the state. In this implementation they have no side effects.
|
||||
*/
|
||||
|
||||
const actions = require('./actions');
|
||||
let creators = {};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a start action.
|
||||
* @returns { Oject } Action
|
||||
*/
|
||||
creators.start = function() {
|
||||
return {
|
||||
type: actions.START
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a stop action.
|
||||
* @returns { Oject } Action
|
||||
*/
|
||||
creators.stop = function() {
|
||||
return {
|
||||
type: actions.STOP
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a restart action.
|
||||
* @returns { Oject } Action
|
||||
*/
|
||||
creators.restart = function() {
|
||||
return {
|
||||
type: actions.RESTART
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an action to set the Error.
|
||||
* @param { Number } error The error code. @see ffmpegCommand.js
|
||||
* @returns { Object } Action
|
||||
*/
|
||||
creators.setError = function(error) {
|
||||
return {
|
||||
type: actions.SET_ERROR,
|
||||
data: error
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an action to update the config.
|
||||
* @param { Object } configUpdate The changes to the config.
|
||||
* @returns { Object } Action
|
||||
*/
|
||||
creators.updateConfig = function(configUpdate) {
|
||||
return {
|
||||
type: actions.UPDATE_CONFIG,
|
||||
data: configUpdate
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = creators;
|
114
src/actions.js
114
src/actions.js
|
@ -1,8 +1,16 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The Actions to change the State //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/** Outsourced definition of the actions and simple action creators for trivial actions.
|
||||
* @module Actions
|
||||
* @todo allowed values
|
||||
*/
|
||||
|
||||
let actions = module.exports = {
|
||||
const Promise = require('promise');
|
||||
const writeConfig = require('./utility/config.js').write;
|
||||
const readConfig = require('./utility/config.js').read;
|
||||
/**
|
||||
* Actions
|
||||
* The action definitions.
|
||||
*/
|
||||
let actions = {
|
||||
UPDATE_CONFIG: 'UPDATE_CONFIG',
|
||||
REQUEST_START: 'REQUEST_START',
|
||||
SET_STARTED: 'SET_STATED',
|
||||
|
@ -10,5 +18,101 @@ let actions = module.exports = {
|
|||
SET_STOPPED: 'SET_STOPPED',
|
||||
REQUEST_RESTART: 'REQUEST_RESTART',
|
||||
SET_ERROR: 'SET_ERROR',
|
||||
TRY_RECONECT: 'TRY_RECONNECT'
|
||||
TRY_RECONECT: 'TRY_RECONNECT',
|
||||
SET_NAME: 'SET_NAME',
|
||||
|
||||
// Master Server Related
|
||||
HYDRATE: 'HYDRATE'
|
||||
};
|
||||
|
||||
/**
|
||||
* Trivial Action Creators
|
||||
*/
|
||||
let creators = {};
|
||||
|
||||
/**
|
||||
* Updates or initializes the configuration state. Updating and initializing are sync actions. The disk write happens asynchronously. Also sets the name if it is mentioned in the update.
|
||||
* @param { Object } update The new (partial) config. If it is undefined, then the configuration will be read from disk.
|
||||
* @returns { Function } A thunk for redux-thunk.
|
||||
* @throws { Error } In case the Config can't be read.
|
||||
*/
|
||||
creators.updateConfig = function(update) {
|
||||
return (dispatch, getState) => {
|
||||
let init = false;
|
||||
|
||||
if(!update) {
|
||||
init = true;
|
||||
|
||||
update = readConfig();
|
||||
|
||||
// TODO: Proper handling.
|
||||
if(!update)
|
||||
throw new Error('Could not load config.');
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: actions.UPDATE_CONFIG,
|
||||
data: update
|
||||
});
|
||||
|
||||
if(update.name)
|
||||
dispatch(creators.setName(update.name));
|
||||
|
||||
return init ? Promise.resolve() : writeConfig(getState);
|
||||
};
|
||||
};
|
||||
|
||||
creators.requestStart = function() {
|
||||
return {
|
||||
type: actions.REQUEST_START
|
||||
};
|
||||
};
|
||||
|
||||
creators.requestStop = function() {
|
||||
return {
|
||||
type: actions.REQUEST_STOP
|
||||
};
|
||||
};
|
||||
|
||||
creators.setStarted = function() {
|
||||
return {
|
||||
type: actions.SET_STARTED
|
||||
};
|
||||
};
|
||||
|
||||
creators.setStopped = function() {
|
||||
return {
|
||||
type: actions.SET_STOPPED
|
||||
};
|
||||
};
|
||||
|
||||
creators.requestRestart = function() {
|
||||
return {
|
||||
type: actions.REQUEST_RESTART
|
||||
};
|
||||
};
|
||||
|
||||
creators.setError = function(error) {
|
||||
return {
|
||||
type: actions.SET_ERROR,
|
||||
data: error
|
||||
};
|
||||
};
|
||||
|
||||
creators.tryReconnect = function() {
|
||||
return {
|
||||
type: actions.TRY_RECONECT
|
||||
};
|
||||
};
|
||||
|
||||
creators.setName = function(name) {
|
||||
return {
|
||||
type: actions.SET_NAME,
|
||||
data: name
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
actions,
|
||||
creators
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// A Wrapper for Fluent-FFMPEG with a custom command. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* @module Commander
|
||||
* @description A Wrapper for Fluent-FFMPEG with a custom command.
|
||||
*/
|
||||
|
||||
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const http = require('http');
|
||||
|
@ -13,7 +15,10 @@ const logger = require('./logger');
|
|||
// Reference to itself. (Object oriented this. Only used to call public methods.)
|
||||
let self = false;
|
||||
|
||||
// The Variable for the FFMpeg command.
|
||||
/**
|
||||
* The FFMPEG command.
|
||||
* @member
|
||||
*/
|
||||
let cmd = ffmpeg({
|
||||
stdoutLines: 20
|
||||
});
|
||||
|
@ -21,7 +26,7 @@ let cmd = ffmpeg({
|
|||
// The Config, Logger and a handle for the kill timeout.
|
||||
let _config, _stopHandle = false, _connectHandle = false;
|
||||
|
||||
// Error Texts
|
||||
// Error Texts //TODO put them into separate module
|
||||
let errorDescriptions = ['Camera Disconnected',
|
||||
'YoutTube Disconnected',
|
||||
'Wrong ffmpeg executable.',
|
||||
|
@ -30,8 +35,8 @@ let errorDescriptions = ['Camera Disconnected',
|
|||
// The stream source url. Yet to be set.
|
||||
let source = "";
|
||||
|
||||
// The State Object.
|
||||
let State;
|
||||
// The function to get the State.
|
||||
let getState;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
|
@ -39,29 +44,29 @@ let State;
|
|||
|
||||
/**
|
||||
* Interface to the ffmpeg process. Uses fluent-ffmpeg.
|
||||
* @param {Object} config Configuration for the stream. @see config.js.example
|
||||
* @constructor
|
||||
*/
|
||||
let Commander = function(State){
|
||||
let Commander = function(_getState){
|
||||
// singleton
|
||||
if(self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if(!(this instanceof Commander))
|
||||
return new Commander(config, logger);
|
||||
|
||||
|
||||
// TODO: Better Error Checkinglet
|
||||
if(!config)
|
||||
throw new Error("Invalid Config");
|
||||
|
||||
if(!logger)
|
||||
throw new Error("Invalid Logger");
|
||||
return new Commander();
|
||||
|
||||
if (!_getState) {
|
||||
throw new Error('Invalid getState() function.');
|
||||
}
|
||||
|
||||
getState = _getState;
|
||||
self = this;
|
||||
|
||||
// (Re)Create the ffmpeg command and configure it.
|
||||
/**
|
||||
* (Re)Create the ffmpeg command and configure it.
|
||||
* @param { Object } config The configuration for the stream.
|
||||
* @returns { Object } The fluent-ffmpeg command object.
|
||||
*/
|
||||
let createCommand = function() {
|
||||
// Clear inputs
|
||||
cmd._inputs = [];
|
||||
|
@ -131,16 +136,20 @@ let Commander = function(State){
|
|||
cmd.kill();
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
let setConfig = function(_conf) {
|
||||
config = _conf;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the current config.
|
||||
* @returns {}
|
||||
*/
|
||||
function config() {
|
||||
return getState().config;
|
||||
}
|
||||
|
||||
// Handle Stop and Restart
|
||||
function stopped() {
|
||||
status.streaming = false;
|
259
src/commander.js~
Normal file
259
src/commander.js~
Normal file
|
@ -0,0 +1,259 @@
|
|||
/**
|
||||
* @module Commander
|
||||
* @description A Wrapper for Fluent-FFMPEG with a custom command.
|
||||
*/
|
||||
|
||||
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const http = require('http');
|
||||
const logger = require('./logger');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Reference to itself. (Object oriented this. Only used to call public methods.)
|
||||
let self = false;
|
||||
|
||||
/**
|
||||
* The FFMPEG command.
|
||||
* @member
|
||||
*/
|
||||
let cmd = ffmpeg({
|
||||
stdoutLines: 20
|
||||
});
|
||||
|
||||
// The Config, Logger and a handle for the kill timeout.
|
||||
let _config, _stopHandle = false, _connectHandle = false;
|
||||
|
||||
// Error Texts //TODO put them into separate module
|
||||
let errorDescriptions = ['Camera Disconnected',
|
||||
'YoutTube Disconnected',
|
||||
'Wrong ffmpeg executable.',
|
||||
'Unknown Error - Restarting'];
|
||||
|
||||
// The stream source url. Yet to be set.
|
||||
let source = "";
|
||||
|
||||
// The function to get the State.
|
||||
let getState;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Interface to the ffmpeg process. Uses fluent-ffmpeg.
|
||||
* @constructor
|
||||
*/
|
||||
let Commander = function(_getState){
|
||||
// singleton
|
||||
if(self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if(!(this instanceof Commander))
|
||||
return new Commander();
|
||||
|
||||
if (!_getState) {
|
||||
throw new Error('Invalid getState() function.');
|
||||
}
|
||||
|
||||
getState = _getState;
|
||||
self = this;
|
||||
|
||||
/**
|
||||
* (Re)Create the ffmpeg command and configure it.
|
||||
* @param { Object } config The configuration for the stream.
|
||||
* @returns { Object } The fluent-ffmpeg command object.
|
||||
*/
|
||||
let createCommand = function() {
|
||||
// Clear inputs
|
||||
cmd._inputs = [];
|
||||
|
||||
// TODO: Multi Protocol
|
||||
source = 'rtsp://' + config.camIP + ':' + config.camPort + '/' + config.camProfile;
|
||||
cmd.input(source);
|
||||
|
||||
// Custom config if any.
|
||||
if (config.customOutputOptions !== "")
|
||||
cmd.outputOptions(config.customOutputOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
|
||||
if (config.customAudioOptions !== "")
|
||||
cmd.outputOptions(config.customAudioOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.AudioCodec('copy');
|
||||
|
||||
if (config.customVideoOptions !== "")
|
||||
cmd.outputOptions(config.customVideoOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.videoCodec('copy');
|
||||
|
||||
// Output Options.
|
||||
cmd.outputFormat('flv')
|
||||
.outputOptions(['-bufsize 50000k', '-tune film'])
|
||||
.output('rtmp://a.rtmp.youtube.com/live2/' + config.key);
|
||||
|
||||
// Register events.
|
||||
cmd.on('start', started);
|
||||
|
||||
cmd.on('end', stopped);
|
||||
|
||||
cmd.on('error', crashed);
|
||||
|
||||
return cmd;
|
||||
};
|
||||
|
||||
let ffmpegCommand = function() {
|
||||
return cmd;
|
||||
};
|
||||
|
||||
// NOTE: Maybe better error resolving strategy.
|
||||
// Start streaming.
|
||||
let start = function() {
|
||||
// Ignore if we try to reconnect.
|
||||
if(_connectHandle)
|
||||
return;
|
||||
|
||||
cmd.run();
|
||||
};
|
||||
|
||||
// Restart the stream;
|
||||
let restart = function() {
|
||||
if(status.streaming) {
|
||||
restart = true; // NOTE: not very nice
|
||||
this.stop();
|
||||
} else
|
||||
this.start();
|
||||
};
|
||||
|
||||
// Stop streaming.
|
||||
let stop = function() {
|
||||
cmd.kill('SIGINT');
|
||||
|
||||
_stopHandle = setTimeout(() => {
|
||||
logger.log(logger.importance[3], "Force Stop!");
|
||||
cmd.kill();
|
||||
}, 3000);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the current config.
|
||||
* @returns {}
|
||||
*/
|
||||
function config() {
|
||||
return getState().config;
|
||||
}
|
||||
|
||||
// Handle Stop and Restart
|
||||
function stopped() {
|
||||
status.streaming = false;
|
||||
|
||||
// Clear force kill Timeout
|
||||
if(stopTimeout) {
|
||||
clearTimeout(stopTimeout);
|
||||
stopTimeout = false;
|
||||
}
|
||||
|
||||
// Restart the stream;
|
||||
if (restart) {
|
||||
self.start();
|
||||
}
|
||||
|
||||
cmd.emit('stopped');
|
||||
}
|
||||
|
||||
// TODO: Restart = false in stopped?
|
||||
// Hande Stat
|
||||
function started() {
|
||||
cmd.emit(restart ? 'restarted' : 'started');
|
||||
restart = false;
|
||||
status.error = false;
|
||||
status.streaming = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error Handling
|
||||
*/
|
||||
|
||||
/**
|
||||
* Log and handle crashes. Notify the main module.
|
||||
* @param { Object } error - Error object from the crash.
|
||||
* @param { String } stdout
|
||||
* @param { String } stderr
|
||||
*/
|
||||
function crashed(error, stdout, stderr){
|
||||
// Can't connect to the
|
||||
if (err.message.indexOf(source) > -1)
|
||||
status.error = 0;
|
||||
|
||||
// Can't connect to the Internet / YouTube
|
||||
else if (err.message.indexOf(source + 'Input/output error') > -1 || err.message.indexOf('rtmp://a.rtmp.youtube.com/live2/' + _config.key) > -1)
|
||||
status.error = 1;
|
||||
|
||||
// Wrong FFMPEG Executable
|
||||
else if (err.message.indexOf('spawn') > -1 || err.message.indexOf('niceness') > -1)
|
||||
status.error = 2;
|
||||
|
||||
// Stopped by us - SIGINT Shouldn't lead to a crash.
|
||||
else if (err.message.indexOf('SIGINT') > -1 || err.message.indexOf('SIGKILL') > -1){
|
||||
stopped();
|
||||
return;
|
||||
}
|
||||
|
||||
// Some unknown Problem, just try to restart.
|
||||
else {
|
||||
status.error = 3;
|
||||
|
||||
// Just restart in a Second
|
||||
setTimeout(function(){
|
||||
self.start();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
logger.log(logger.importance[2], `Crashed: ${erro}\nSTDERR: ${stderr}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Probe the connection to the host on the port and restart the stream afterwards.
|
||||
* @param { string } host
|
||||
* @param { number } port
|
||||
*/
|
||||
function tryReconnect( host, port ){
|
||||
if (!host || !port)
|
||||
return;
|
||||
|
||||
http.get({
|
||||
host: host.split('/')[0],
|
||||
port: port
|
||||
}, function(res) {
|
||||
// We have a response! Connection works.
|
||||
setTimeout(function() {
|
||||
// NOTE: Ugly!
|
||||
|
||||
// We have a response! Connection works.
|
||||
_connectHandle = false;
|
||||
self.start();
|
||||
}, 1000);
|
||||
}).on("error", function(e) {
|
||||
if (e.message == "socket hang up") {
|
||||
setTimeout(function() {
|
||||
// NOTE: Ugly!
|
||||
|
||||
// We have a response! Connection works.
|
||||
_connectHandle = false;
|
||||
self.start();
|
||||
}, 1000);
|
||||
} else {
|
||||
// try again
|
||||
_connectHandle = setTimeout(function(){
|
||||
tryReconnect(host, port);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
232
src/communicator.js
Normal file
232
src/communicator.js
Normal file
|
@ -0,0 +1,232 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// A socket.js wrapper to abstract the communication with the server. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* @module Communicator
|
||||
* @description Abstracts the communication with the master server.
|
||||
*/
|
||||
|
||||
const socketio = require('socket.io-client');
|
||||
const logger = require('./logger.js');
|
||||
/*const { HYDRATE } = require('./actions').actions[C]*/
|
||||
|
||||
const { UPDATE_CONFIG,
|
||||
REQUEST_START,
|
||||
SET_STARTED,
|
||||
REQUEST_STOP,
|
||||
SET_STOPPED,
|
||||
REQUEST_RESTART,
|
||||
SET_ERROR,
|
||||
TRY_RECONECT,
|
||||
SET_NAME,
|
||||
HYDRATE}= require('./actions').actions;;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
/**
|
||||
* The socket.io client connection.
|
||||
*/
|
||||
let socket;
|
||||
|
||||
// Get the current application state.
|
||||
let getState;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Communicator {
|
||||
constructor(_getState) {
|
||||
// singleton
|
||||
if (self)
|
||||
return self;
|
||||
|
||||
if (!_getState) {
|
||||
throw new Error('Invalid getState() function.');
|
||||
}
|
||||
|
||||
if(!_getState().config)
|
||||
throw new Error('Invalid Config. Initialize config first!'); // TODO: Lookup if implemented everywhere
|
||||
|
||||
self = this;
|
||||
|
||||
// define the locals
|
||||
getState = _getState;
|
||||
|
||||
initSocket();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection status getter. Forwards the socket-io status.
|
||||
* @returns { Bool } Connection status.
|
||||
*/
|
||||
get connected() {
|
||||
return socket.connected;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Relay an action to the server.
|
||||
* @param {Object} action The action object.
|
||||
*/
|
||||
Communicator.prototype.sendAction = function(action){
|
||||
if(!this.connected || !action.type)
|
||||
return;
|
||||
|
||||
// TODO: Filter
|
||||
/*
|
||||
socket.emit('action', action);
|
||||
[C]*/
|
||||
|
||||
let type, change, state = getState();
|
||||
|
||||
switch (action.type) {
|
||||
case SET_STARTED:
|
||||
case SET_STOPPED:
|
||||
type = 'startStop',
|
||||
change = {
|
||||
running: state.stream.runnning ? 1 : 0,
|
||||
error: state.stream.error || -1
|
||||
};
|
||||
break;
|
||||
|
||||
case SET_ERROR:
|
||||
type = 'error';
|
||||
change = {
|
||||
running: 2,
|
||||
error: state.stream.error
|
||||
};
|
||||
break;
|
||||
case UPDATE_CONFIG:
|
||||
type = 'settings';
|
||||
change = {
|
||||
config: state.config
|
||||
};
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('change', {type, change});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a message to a command issuer on the web-interface.
|
||||
* @param {String} title Title of the message.
|
||||
* @param {String} type Type of the message.
|
||||
* @param {String} text The message text.
|
||||
* @param {String} to Recepient (socket id).
|
||||
*/
|
||||
Communicator.prototype.sendMessage = function(title, type, text, to){
|
||||
if(!this.connected)
|
||||
return;
|
||||
|
||||
/*socket.emit('message', {
|
||||
title,
|
||||
type,
|
||||
text
|
||||
}, to);[C]*/
|
||||
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Error',
|
||||
type: 'error',
|
||||
text: 'Could not start SSH tunnels!'
|
||||
}
|
||||
}, to);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a snapshot to a command issuer on the web-interface.
|
||||
* @param {Object} snapshot Snapshot to send.
|
||||
* @param {String} to Recepient (socket id).
|
||||
*/
|
||||
Communicator.prototype.sendSnapshot = function(snapshot, to){
|
||||
if(!this.connected)
|
||||
return;
|
||||
|
||||
socket.emit('data', {
|
||||
type: 'snap', //TODO New with new software
|
||||
data: snapshot
|
||||
}, to);
|
||||
};
|
||||
|
||||
module.exports = Communicator;
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize the socket connection and register the events.
|
||||
*/
|
||||
function initSocket() {
|
||||
// Savety it will be called only once anyway.
|
||||
|
||||
socket = socketio(getState().config.master + '/pi', {
|
||||
query: getState().config.unconfigured ? "unconfigured=true" : undefined
|
||||
});
|
||||
|
||||
socket.on('connect', socketConnected);
|
||||
socket.on('command', handleCommand);
|
||||
socket.on('disconnect', socketDisconnected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event Handlers
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle an established connection.
|
||||
*/
|
||||
function socketConnected() {
|
||||
logger.log(logger.importance[4], 'Connected to the master server.');
|
||||
|
||||
// Handle SSH Connection //TODO Implement - Action to set SSH. Auto Retry //TODO central DEFINITION
|
||||
//ssh.connect();
|
||||
|
||||
self.sendAction({
|
||||
type: HYDRATE,
|
||||
data: getState()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a disconnection.
|
||||
*/
|
||||
function socketDisconnected() {
|
||||
socket.disconnect();
|
||||
|
||||
// And just reconnect.
|
||||
logger.log(logger.importance[2], 'Lost connection to the master server.');
|
||||
initSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Commands //TODO Implement
|
||||
*/
|
||||
function handleCommand() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Redux Middleware
|
||||
*/
|
||||
|
||||
Communicator.middleware = store => next => action => {
|
||||
let result = next(action);
|
||||
|
||||
if(self && self.connected){
|
||||
console.log("self");
|
||||
self.sendAction(action); //TODO: Filter
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
|
@ -11,8 +11,36 @@ const socketio = require('socket.io-client');
|
|||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
// Get the current application state.
|
||||
let getState;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module.exports = function Communicator(){};
|
||||
module.exports = function Communicator(_getState){
|
||||
// singleton
|
||||
if(self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if(!(this instanceof Communicator))
|
||||
return new Communicator();
|
||||
|
||||
if (!_getState) {
|
||||
throw new Error('Invalid getState() function.');
|
||||
}
|
||||
|
||||
// define the locals
|
||||
getState = _getState;
|
||||
|
||||
init();
|
||||
self = this;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
|
@ -33,18 +33,11 @@ const customLevels = {
|
|||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Monkey Patching.
|
||||
*/
|
||||
|
||||
// Monkey Patching.
|
||||
|
||||
/**
|
||||
* Calls the logging function with arguments, if the node enviroment isn't in production mode.
|
||||
*/
|
||||
winston.Logger.prototype.dbgmsg = function() {
|
||||
if (process.env.NODE_ENV !== 'production')
|
||||
this.log.apply(undefined, arguments);
|
||||
};
|
||||
|
||||
// Set the Colors
|
||||
winston.addColors(customLevels.colors);
|
||||
|
|
147
src/reducers.js
147
src/reducers.js
|
@ -1,70 +1,119 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Reducers //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/** Outsourced definition of the Reducers for redux.
|
||||
* @see {@link http://redux.js.org/docs/basics/Reducers.html}
|
||||
* @module Reducers
|
||||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
const actions = require('./actions');
|
||||
const { UPDATE_CONFIG,
|
||||
REQUEST_START,
|
||||
SET_STARTED,
|
||||
REQUEST_STOP,
|
||||
SET_STOPPED,
|
||||
REQUEST_RESTART,
|
||||
SET_ERROR,
|
||||
TRY_RECONECT,
|
||||
SET_NAME}= require('./actions').actions;
|
||||
|
||||
let reducers = {};
|
||||
|
||||
/**
|
||||
* Set the streaming/error state.
|
||||
* Set the error code. @see ffmpegCommand.js for the error code descriptions.
|
||||
*/
|
||||
reducers.error = function(state = -1, action) {
|
||||
function error(state = false, action) {
|
||||
switch (action.type) {
|
||||
case actions.SET_ERROR:
|
||||
if((typeof action.data) == 'undefined') {
|
||||
return action.data;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the streaming state.
|
||||
*/
|
||||
|
||||
reducers.streaming = function(state = 'STOPPED', action) {
|
||||
switch (action.type) {
|
||||
case actions.START:
|
||||
case actions.STOP:
|
||||
return action.type == actions.START;
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the restart flag.
|
||||
*
|
||||
* The restart flag get's automaticly unset, as soon as the start action gets reduced.
|
||||
*/
|
||||
|
||||
reducers.restart = function(state = false, action) {
|
||||
switch (action.type) {
|
||||
case actions.RESTART:
|
||||
return true;
|
||||
case actions.START:
|
||||
case SET_ERROR:
|
||||
return action.data;
|
||||
case SET_STARTED:
|
||||
return false;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Add central definition
|
||||
/**
|
||||
* Set the error handling procedure.
|
||||
*/
|
||||
function handleError(state = false, action) {
|
||||
switch (action.type) {
|
||||
case SET_STARTED:
|
||||
return false;
|
||||
case TRY_RECONECT:
|
||||
return 'RECONNECTING';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the config.
|
||||
* Set the running flag.
|
||||
* It can either be RUNNING, STARTING, STOPPING or STOPPED
|
||||
*/
|
||||
reducers.config = function(state = {}, action) {
|
||||
function running(state = 'STOPPED', action) {
|
||||
switch (action.type) {
|
||||
case actions.UPDATE_CONFIG:
|
||||
return Object.assign({}, state, action.data);
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
case REQUEST_START:
|
||||
return 'STARTING';
|
||||
case SET_STARTED:
|
||||
return 'RUNNING';
|
||||
case REQUEST_STOP:
|
||||
return 'STOPPING';
|
||||
case SET_STOPPED:
|
||||
return 'STOPPED';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the restarting flag.
|
||||
*/
|
||||
function restarting(state = false, action) {
|
||||
switch (action.type) {
|
||||
case REQUEST_RESTART:
|
||||
return true;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @function stream
|
||||
* @description Stream Root Reducer.
|
||||
*/
|
||||
reducers.stream = function(state = {}, action){
|
||||
return {
|
||||
running: running(state.running, action),
|
||||
error: error(state.error, action),
|
||||
handleError: handleError(state.handleError, action),
|
||||
restarting: restarting(state.restarting, action)
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @function config
|
||||
* @description Updates the config state.
|
||||
*/
|
||||
reducers.config = function(state = false, action) {
|
||||
switch (action.type) {
|
||||
case UPDATE_CONFIG:
|
||||
return Object.assign({}, state, action.data);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @function name
|
||||
* @description Set the name state.
|
||||
*/
|
||||
reducers.name = function(state = 'Unnamed', action) {
|
||||
switch (action.type) {
|
||||
case SET_NAME:
|
||||
return action.data;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
109
src/state.js
109
src/state.js
|
@ -1,109 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Redux Wrapper to hold the state and communicate with the Server. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* All actions are proxied via Socket.js
|
||||
*
|
||||
* The connection is managed by the main module.
|
||||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
// Reference to the store.
|
||||
let store = false;
|
||||
|
||||
/**
|
||||
* Inital State for the app.
|
||||
* @property { bool } streaming Indicates if the streaming process is running.
|
||||
* @property { number } error Error code. Any number outside the range of the Error array in @see ffmpeg-command.js will be treated as non error. Most conveniently set: -1.
|
||||
* @property { bool } configured Indicates if the camera is configured or not.
|
||||
*/
|
||||
let initialState = {
|
||||
streaming: false,
|
||||
error: -1,
|
||||
config: {}
|
||||
}; // NOTE: Maybe in main.js
|
||||
|
||||
// Reducer
|
||||
let streaming, error, config;
|
||||
const reducers = redux.combineReducers({
|
||||
streaming,
|
||||
error,
|
||||
config
|
||||
});
|
||||
|
||||
// The socket.io connection from the main-module.
|
||||
let _socket;
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
|
||||
let SEND_MESSAGE = 'SEND_MESSAGE';
|
||||
let UPDATE_CONFIG = 'UPDATE_CONFIG';
|
||||
let START_STOP = 'START_STOP';
|
||||
let SET_ERROR = 'SET_ERROR';
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Wrapper to expose action creators and the store.
|
||||
* @param { Object } socket Socket.io instance from the main module..
|
||||
*/
|
||||
module.exports = function state( socket ){
|
||||
// singleton
|
||||
if(self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if(!(this instanceof createStore))
|
||||
return new createStore(_socket);
|
||||
|
||||
_socket = socket;
|
||||
self = this;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reducers
|
||||
*/
|
||||
|
||||
// TODO: share the code!
|
||||
|
||||
/**
|
||||
* Set the streaming/error state.
|
||||
*/
|
||||
streaming = error = function(state, action) {
|
||||
switch(action) {
|
||||
case SET_ERROR:
|
||||
case START_STOP:
|
||||
return action.data;
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the config.
|
||||
*/
|
||||
config = function(state, action) {
|
||||
switch(action) {
|
||||
case UPDATE_CONFIG:
|
||||
return Object.assign({}, state, action.data);
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Wrapper to hold the status object and the master server about changes. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let _socket;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Wrapper to hold the status object and the master server about changes.
|
||||
* @param {Object} _socket - Socket.io instance from the main module..
|
||||
*/
|
||||
module.exports = function( _socket ){};
|
100
src/streamer.js
Normal file
100
src/streamer.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
/** The central interface to the streaming process.
|
||||
* @module Streamer
|
||||
*/
|
||||
|
||||
const logger = require('./logger');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declarations //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Object oriented `this`.
|
||||
let self = false;
|
||||
|
||||
/**
|
||||
* Inital State for the app.
|
||||
* @property { Object } stream Stream Status.
|
||||
* @property { bool } stream.running Indicates wether the stream is running.
|
||||
* @property { number } stream.error Error code. Any number outside the range of the Error array in @see ffmpeg-command.js will be treated as non error. Most conveniently set: -1.
|
||||
* @property { bool } stream.reconnecting Indicates wether the program tries to reconnect to the camera or the internet.
|
||||
* @property { Object } config Configuration of the camera.
|
||||
*/
|
||||
let initialState = {
|
||||
stream: {
|
||||
running: 'STOPPED',
|
||||
error: -1,
|
||||
reconnecting: false,
|
||||
restarting: false
|
||||
},
|
||||
config: {}
|
||||
}; // NOTE: Maybe in main.js
|
||||
|
||||
/**
|
||||
* The socket.io connection from the main-module.
|
||||
*/
|
||||
let _communicator;
|
||||
|
||||
/**
|
||||
* Redux Actions
|
||||
*/
|
||||
// Reducer
|
||||
const reducer = require('./reducers');
|
||||
|
||||
// Reference to the store of the application state.
|
||||
const store = redux.createStore(reducer, initialState);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Code //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: Log state changes.
|
||||
|
||||
/**
|
||||
* @class Streamer
|
||||
* The central control Object (singleton for now) which has the permission to change state.
|
||||
*
|
||||
* @constructor
|
||||
* @param { Object } communicator A communicator object. @see communicator.js - Optional //TODO: Find proper tag.
|
||||
*/
|
||||
function Streamer(communicator = false) {
|
||||
// singleton
|
||||
if (self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if (!(this instanceof Streamer))
|
||||
return new Streamer(_communicator);
|
||||
|
||||
_communicator = communicator;
|
||||
|
||||
self = this;
|
||||
return this;
|
||||
};
|
||||
|
||||
module.exports = Streamer;
|
||||
|
||||
/**
|
||||
* Set the communicator object and enable the state sync with the server.
|
||||
* @param {Object} communicator A communicator object. @see communicator.js
|
||||
*/
|
||||
Streamer.prototype.setCommunicator = function(communicator) {
|
||||
if (_communicator)
|
||||
_communicator = communicator;
|
||||
else
|
||||
logger.dbgmsdg("Invalid Communicator");
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current config.
|
||||
* @returns { * } The current config.
|
||||
*/
|
||||
Streamer.prototype.getConfig = function(){
|
||||
return store.getStreamer().config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
*/
|
||||
|
||||
const redux = require('redux');
|
||||
const ReduxThunk = require('redux-thunk').default;
|
||||
|
||||
const logger = require('./logger');
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -22,23 +24,20 @@ let self = false;
|
|||
*/
|
||||
let initialState = {
|
||||
stream: {
|
||||
running: false,
|
||||
running: 'STOPPED',
|
||||
error: -1,
|
||||
reconnecting: false
|
||||
reconnecting: false,
|
||||
restarting: false
|
||||
},
|
||||
config: {}
|
||||
}; // NOTE: Maybe in main.js
|
||||
|
||||
// The socket.io connection from the main-module.
|
||||
let _communicator;
|
||||
|
||||
// Actions
|
||||
const actions = require('./actions');
|
||||
|
||||
// Action Creators
|
||||
const creators = require('./actionCreators');
|
||||
const dispatchers = redux.bindActionCreators(creators);
|
||||
|
||||
|
||||
/**
|
||||
* Redux Actions
|
||||
*/
|
||||
// Reducer
|
||||
const reducer = require('./reducers');
|
||||
|
||||
|
@ -52,20 +51,20 @@ const store = redux.createStore(reducer, initialState);
|
|||
// TODO: Log state changes.
|
||||
|
||||
/**
|
||||
* The central redux state manager. The module exposes central action dispatchers. Updates to the state get communicated to the server.
|
||||
*
|
||||
* @class Streamer
|
||||
* The central control Object (singleton for now) which has the permission to change state.
|
||||
*
|
||||
* @constructor
|
||||
* @member [Action Dispatchers] The action creators (@see actionCreators.js) are bound to the dispatch function and made member of the State object.
|
||||
* @param { Object } communicator A communicator object. @see communicator.js - Optional //TODO: Find proper tag.
|
||||
*/
|
||||
function State(communicator = false) {
|
||||
function Streamer(communicator = false) {
|
||||
// singleton
|
||||
if (self)
|
||||
return self;
|
||||
|
||||
// Make `new` optional.
|
||||
if (!(this instanceof State))
|
||||
return new State(_communicator);
|
||||
if (!(this instanceof Streamer))
|
||||
return new Streamer(_communicator);
|
||||
|
||||
_communicator = communicator;
|
||||
|
||||
|
@ -79,7 +78,7 @@ applyDispatchers(creators);
|
|||
* Set the communicator object and enable the state sync with the server.
|
||||
* @param {Object} communicator A communicator object. @see communicator.js
|
||||
*/
|
||||
State.prototype.setCommunicator = function(communicator) {
|
||||
Streamer.prototype.setCommunicator = function(communicator) {
|
||||
if (_communicator)
|
||||
_communicator = communicator;
|
||||
else
|
||||
|
@ -90,16 +89,16 @@ State.prototype.setCommunicator = function(communicator) {
|
|||
* Wrapper for redux.
|
||||
* @returns { Object } The current state.
|
||||
*/
|
||||
State.prototype.getState = function(){
|
||||
return store.getState();
|
||||
Streamer.prototype.getStreamer = function(){
|
||||
return store.getStreamer();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current config.
|
||||
* @returns { * } The current config.
|
||||
*/
|
||||
State.prototype.getConfig = function(){
|
||||
return store.getState().config;
|
||||
Streamer.prototype.getConfig = function(){
|
||||
return store.getStreamer().config;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -107,23 +106,23 @@ State.prototype.getConfig = function(){
|
|||
*/
|
||||
|
||||
/**
|
||||
* Adds prototypes for the action dispatchers to the State.
|
||||
* Adds prototypes for the action dispatchers to the Streamer.
|
||||
* @param { Object } creators
|
||||
* @throws { Error } If a method with the creators name already exists. @see actionCreators.js
|
||||
*/
|
||||
function applyDispatchers( creators ){
|
||||
for(let creator in creators){
|
||||
if(State.prototype[creator])
|
||||
throw new Error(`State has already a meber '${creator}'.`);
|
||||
if(Streamer.prototype[creator])
|
||||
throw new Error(`Streamer has already a meber '${creator}'.`);
|
||||
|
||||
State.prototype[creator] = function(){
|
||||
Streamer.prototype[creator] = function(){
|
||||
store.dispatch(creators[creator].apply(undefined, arguments));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = State;
|
||||
module.exports = Streamer;
|
||||
|
||||
|
||||
|
42
src/utility/config.js~
Normal file
42
src/utility/config.js~
Normal file
|
@ -0,0 +1,42 @@
|
|||
/** Config read/write utilities.
|
||||
* @module Utilities/Config
|
||||
*/
|
||||
|
||||
const Promise = require('promise');
|
||||
const fs = require('fs');
|
||||
const logger = require('../logger.js');
|
||||
|
||||
// TODO: Config path in defs
|
||||
|
||||
module.exports = {};
|
||||
|
||||
// TODO Default CFG
|
||||
/**
|
||||
* Read the JSON config file.
|
||||
* @returns { Object | bool } Returns the parsed config or false in case of an error.
|
||||
*/
|
||||
module.exports.read = function() {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(__dirname + '/../../config.js')); //TODO: Nicer
|
||||
} catch (e) {
|
||||
return false; // Log that.
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes the config to disk.
|
||||
* @param {Object} state A function to retrieve the current state. This makes it harder to accidentially write arbitrary code.
|
||||
* @returns { Promise } A promise for writing the configuration.
|
||||
*/
|
||||
module.exports.write = function( getState ){
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.writeFile(__dirname + '/config.js',
|
||||
JSON.stringify(getState().config, undefined, 2),
|
||||
err => {
|
||||
if(err)
|
||||
reject(err);
|
||||
else
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
518
test.js
Normal file
518
test.js
Normal file
|
@ -0,0 +1,518 @@
|
|||
const sock = require('socket.io-client');
|
||||
const ffmpeg = require('fluent-ffmpeg');
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const WMStrm = require(__dirname + '/lib/memWrite.js');
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const spawnP = require('child_process').spawn;
|
||||
|
||||
let mustBe = false;
|
||||
let restart = false;
|
||||
let config, source, snapSource, stopTimeout;
|
||||
|
||||
const importance = ['normal', 'info', 'warning', 'danger', 'success'];
|
||||
var customLevels = {
|
||||
levels: {
|
||||
normal: 0,
|
||||
info: 1,
|
||||
warning: 2,
|
||||
danger: 3,
|
||||
success: 4
|
||||
},
|
||||
colors: {
|
||||
normal: 'white',
|
||||
info: 'blue',
|
||||
warning: 'orange',
|
||||
danger: 'red',
|
||||
success: 'green'
|
||||
}
|
||||
};
|
||||
|
||||
let winston = require('winston');
|
||||
let logger = new(winston.Logger)({
|
||||
levels: customLevels.levels,
|
||||
transports: [
|
||||
new(winston.transports.Console)({
|
||||
level: 'success'
|
||||
}),
|
||||
new(winston.transports.File)({
|
||||
filename: __dirname + '/process.log',
|
||||
colorize: true,
|
||||
timestamp: true,
|
||||
level: 'success',
|
||||
json: true,
|
||||
maxsize: 500000,
|
||||
maxFiles: 10
|
||||
})
|
||||
]
|
||||
});
|
||||
winston.addColors(customLevels.colors);
|
||||
|
||||
let dir = '/home';
|
||||
let status = {
|
||||
status: 0,
|
||||
error: -1
|
||||
}
|
||||
|
||||
let errors = ['Camera Disconnected', 'YoutTube Disconnected', 'Wrong ffmpeg executable.'];
|
||||
let cmd;
|
||||
|
||||
let spawn = function() {
|
||||
source = 'rtsp://' + config.camIP + ':' + config.camPort + '/' + config.camProfile;
|
||||
ffmpeg.setFfmpegPath(config.ffmpegPath);
|
||||
delete cmd;
|
||||
cmd = ffmpeg({
|
||||
source: source,
|
||||
stdoutLines: 20
|
||||
});
|
||||
if (config.customOutputOptions !== "")
|
||||
cmd.outputOptions(config.customOutputOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
if (config.customAudioOptions !== "")
|
||||
cmd.outputOptions(config.customAudioOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.AudioCodec('copy');
|
||||
if (config.customVideoOptions !== "")
|
||||
cmd.outputOptions(config.customVideoOptions.replace(/\s+\,\s+/g, ',').replace(/\s+\-/g, ',-').split(','));
|
||||
else
|
||||
cmd.videoCodec('copy');
|
||||
|
||||
cmd.on('start', function(commandLine) {
|
||||
status.running = 0;
|
||||
logger.log(importance[4], 'Spawned Ffmpeg with command: ' + commandLine);
|
||||
})
|
||||
.on('end', function(o, e) {
|
||||
imDead('Normal Stop.', e);
|
||||
})
|
||||
.on('error', function(err, o, e) {
|
||||
if (err.message.indexOf(source) > -1)
|
||||
criticalProblem(0, e, handleDisc, config.camIP, config.camPort);
|
||||
else if (err.message.indexOf(source + 'Input/output error') > -1 || err.message.indexOf('rtmp://a.rtmp.youtube.com/live2/' + config.key) > -1)
|
||||
criticalProblem(1, e, handleDisc, 'a.rtmp.youtube.com/live2/', 1935);
|
||||
else if (err.message.indexOf('spawn') > -1 || err.message.indexOf('niceness') > -1)
|
||||
criticalProblem(2, e, function() {});
|
||||
else if (err.message.indexOf('SIGINT') > -1 || err.message.indexOf('SIGKILL') > -1)
|
||||
imDead('Normal Stop.', e);
|
||||
else
|
||||
imDead(err.message, e);
|
||||
})
|
||||
.outputFormat('flv')
|
||||
.outputOptions(['-bufsize 50000k', '-tune film'])
|
||||
.output('rtmp://a.rtmp.youtube.com/live2/' + config.key);
|
||||
|
||||
status.error = -1;
|
||||
socket.emit('change', {
|
||||
type: 'startStop',
|
||||
change: {
|
||||
running: 0,
|
||||
error: -1
|
||||
}
|
||||
});
|
||||
cmd.run();
|
||||
}
|
||||
|
||||
let getSnap = function(cb) {
|
||||
snapSource = 'rtsp://' + config.camIP + ':' + config.camPort + '/' + config.snapProfile;
|
||||
let picBuff = new WMStrm();
|
||||
recCmd = ffmpeg(snapSource)
|
||||
.on('start', function(commandLine) {
|
||||
logger.log(importance[4], 'Snapshot ' + commandLine);
|
||||
})
|
||||
.on('error', function(err, o, e) {})
|
||||
.outputFormat('mjpeg')
|
||||
.frames(1)
|
||||
.stream(picBuff, {
|
||||
end: true
|
||||
});
|
||||
picBuff.on('finish', function() {
|
||||
try {
|
||||
cb(picBuff.memStore.toString('base64'));
|
||||
delete pickBuff;
|
||||
} catch (e) {
|
||||
cb(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function imDead(why, e = '') {
|
||||
if(stopTimeout) {
|
||||
clearTimeout(stopTimeout);
|
||||
stopTimeout = false;
|
||||
}
|
||||
|
||||
status.running = 1;
|
||||
socket.emit('change', {
|
||||
type: 'startStop',
|
||||
change: {
|
||||
running: 1
|
||||
}
|
||||
});
|
||||
if (restart) {
|
||||
spawn();
|
||||
restart = false;
|
||||
}
|
||||
if (!mustBe) {
|
||||
logger.log(importance[2], 'Crash! ' + e);
|
||||
setTimeout(function() {
|
||||
spawn();
|
||||
}, 1000);
|
||||
}
|
||||
mustBe = false;
|
||||
}
|
||||
|
||||
function criticalProblem(err, e, handler, ...args) {
|
||||
if (!mustBe) {
|
||||
setTimeout(function() {
|
||||
status.running = 2;
|
||||
status.error = err;
|
||||
logger.log(importance[3], 'Critical Problem: ' + errors[err] + '\n' + e);
|
||||
socket.emit('change', {
|
||||
type: 'error',
|
||||
change: {
|
||||
running: 2,
|
||||
error: err
|
||||
}
|
||||
});
|
||||
handler(args)
|
||||
}, 1000);
|
||||
}
|
||||
mustBe = false;
|
||||
}
|
||||
|
||||
function handleDisc(info) {
|
||||
let [host, port] = info;
|
||||
isReachable(host, port, is => {
|
||||
if (is) {
|
||||
spawn();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
handleDisc(info)
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function isReachable(host, port, callback) {
|
||||
http.get({
|
||||
host: host.split('/')[0],
|
||||
port: port
|
||||
}, function(res) {
|
||||
callback(true);
|
||||
}).on("error", function(e) {
|
||||
if (e.message == "socket hang up") {
|
||||
setTimeout(function() {
|
||||
callback(true);
|
||||
}, 1000);
|
||||
} else
|
||||
callback(false);
|
||||
});
|
||||
}
|
||||
|
||||
function stopFFMPEG() {
|
||||
cmd.kill('SIGINT');
|
||||
stopTimeout = setTimeout(() => {
|
||||
logger.log(importance[3], "Force Stop!");
|
||||
cmd.kill();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
var commandHandlers = function commandHandlers(command, cb) {
|
||||
var handlers = {
|
||||
startStop: function() {
|
||||
if(restart)
|
||||
return;
|
||||
|
||||
if (status.running !== 2)
|
||||
if (status.running === 0) {
|
||||
logger.log(importance[1], "Stop Command!");
|
||||
mustBe = true;
|
||||
stopFFMPEG();
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Stopped!'
|
||||
}
|
||||
}, command.sender);
|
||||
} else {
|
||||
logger.log(importance[1], "Start Command!");
|
||||
spawn();
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Started!'
|
||||
}
|
||||
}, command.sender);
|
||||
}
|
||||
},
|
||||
snap: function() {
|
||||
getSnap(snap => {
|
||||
socket.emit('data', {
|
||||
type: 'snap',
|
||||
data: snap,
|
||||
}, command.sender);
|
||||
});
|
||||
},
|
||||
config: function() {
|
||||
socket.emit('data', {
|
||||
type: 'config',
|
||||
data: config,
|
||||
}, command.sender);
|
||||
},
|
||||
changeSettings: function() {
|
||||
for (let set in command.data) {
|
||||
if (typeof config[set] !== 'undefined')
|
||||
config[set] = command.data[set];
|
||||
}
|
||||
let oldConfigured;
|
||||
if (config.configured === true)
|
||||
oldConfigured = true;
|
||||
config.configured = true;
|
||||
fs.writeFile(__dirname + '/config.js',
|
||||
JSON.stringify(config,
|
||||
undefined, 2),
|
||||
function(err) {
|
||||
if (err) {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Error',
|
||||
type: 'error',
|
||||
text: 'Can\'t save the Settings!\n' + err.message
|
||||
}
|
||||
}, command.sender);
|
||||
} else {
|
||||
restartSSH(() => {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Settings Saved!'
|
||||
}
|
||||
}, command.sender);
|
||||
if (oldConfigured) {
|
||||
socket.emit('change', {
|
||||
type: 'settings',
|
||||
change: {
|
||||
config: command.data
|
||||
}
|
||||
});
|
||||
stopFFMPEG();
|
||||
spawn();
|
||||
} else {
|
||||
socket.disconnect();
|
||||
init();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
restart: function() {
|
||||
if (status.running === 0) {
|
||||
logger.log(importance[1], "Restart Command!");
|
||||
mustBe = true;
|
||||
restart = true;
|
||||
stopFFMPEG();
|
||||
} else {
|
||||
logger.log(importance[1], "Start Command!");
|
||||
spawn();
|
||||
}
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Restarted!'
|
||||
}
|
||||
}, command.sender);
|
||||
},
|
||||
restartSSH: function() {
|
||||
restartSSH(() => {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Success',
|
||||
type: 'success',
|
||||
text: 'Restarted SSH Tunnels!'
|
||||
}
|
||||
}, command.sender);
|
||||
});
|
||||
},
|
||||
getLogs: function() {
|
||||
logger.query({limit: 100}, function (err, data) {
|
||||
data = data.file;
|
||||
if (err) {
|
||||
data = [];
|
||||
} else
|
||||
if (data.length === 0)
|
||||
data = [];
|
||||
socket.emit('data', {
|
||||
type: 'logs',
|
||||
data: data
|
||||
}, command.sender);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//call the handler
|
||||
var call = handlers[command.command];
|
||||
if (call)
|
||||
call();
|
||||
}
|
||||
|
||||
function restartSSH(cb) {
|
||||
exec('forever stop SSH-Serv', () => {
|
||||
connectSSH(() => {
|
||||
socket.emit('change', {
|
||||
change: {
|
||||
ssh: {
|
||||
port: status.ssh.port,
|
||||
camForwardPort: status.ssh.camForwardPort
|
||||
}
|
||||
}
|
||||
});
|
||||
cb();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleKill() {
|
||||
process.stdin.resume();
|
||||
logger.log(importance[0], "Received Shutdown Command");
|
||||
mustBe = true;
|
||||
cmd.kill();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.on('SIGTERM', function() {
|
||||
handleKill();
|
||||
});
|
||||
|
||||
//let's go
|
||||
function init() {
|
||||
config = readConfig();
|
||||
|
||||
if (config.configured) {
|
||||
socket = sock(config.master + '/pi');
|
||||
console.log('test');
|
||||
initSocket();
|
||||
status.name = config.name;
|
||||
if (!cmd)
|
||||
spawn();
|
||||
} else {
|
||||
console.log('test');
|
||||
socket = sock(config.master + '/pi', {
|
||||
query: "unconfigured=true"
|
||||
});
|
||||
status.running = 2;
|
||||
initSocket();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function initSSH(cb) {
|
||||
status.ssh = {
|
||||
// that Could come from the Master server!
|
||||
user: config['ssh-user'],
|
||||
localUser: config['ssh-local-user'],
|
||||
masterPort: config['ssh-port']
|
||||
};
|
||||
|
||||
checkSSH((alive) => {
|
||||
if (alive)
|
||||
cb();
|
||||
else
|
||||
connectSSH(cb);
|
||||
});
|
||||
}
|
||||
|
||||
function connectSSH(cb = function() {
|
||||
socket.emit('change', {
|
||||
change: {
|
||||
ssh: {
|
||||
port: status.ssh.port,
|
||||
camForwardPort: status.ssh.camForwardPort
|
||||
}
|
||||
}
|
||||
});
|
||||
}) {
|
||||
socket.emit('getSSHPort', ports => {
|
||||
[status.ssh.port, status.ssh.camForwardPort] = ports;
|
||||
let ssh = exec(`forever start -a --killSignal=SIGINT --uid SSH-Serv sshManager.js ${status.ssh.port} ${status.ssh.camForwardPort} ${config.camPanelPort}`, {
|
||||
detached: true,
|
||||
shell: true,
|
||||
cwd: __dirname
|
||||
});
|
||||
ssh.on('error', (err) => {
|
||||
socket.emit('data', {
|
||||
type: 'message',
|
||||
data: {
|
||||
title: 'Error',
|
||||
type: 'error',
|
||||
text: 'Could not start SSH tunnels!'
|
||||
}
|
||||
}, command.sender);
|
||||
});
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
function checkSSH(cb) {
|
||||
let m, pid, alive;
|
||||
let re = /SSH-Serv.*?sshManager\.js\s([0-9]+)\s([0-9]+).*log.*[^STOPPED]+/g;
|
||||
exec('forever list', (error, stdout, stderr) => {
|
||||
if (error)
|
||||
throw error;
|
||||
let alive = false;
|
||||
while ((m = re.exec(stdout)) !== null) {
|
||||
if (m.index === re.lastIndex) {
|
||||
re.lastIndex++;
|
||||
}
|
||||
if (alive) {
|
||||
exec('forever stop SSH-Serv');
|
||||
cb(false)
|
||||
return;
|
||||
} else {
|
||||
[, status.ssh.port, status.ssh.camForwardPort] = m;
|
||||
alive = true;
|
||||
}
|
||||
}
|
||||
cb(alive);
|
||||
});
|
||||
}
|
||||
|
||||
function initSocket() {
|
||||
socket.on('connect', function() {
|
||||
console.log('herde')
|
||||
logger.log(importance[0], 'Connected to Master: ' + config.master + '.');
|
||||
if (config['ssh-user'])
|
||||
initSSH(err => {
|
||||
if (err)
|
||||
throw err;
|
||||
socket.emit('meta', status);
|
||||
});
|
||||
else {
|
||||
socket.emit('meta', status);
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnect', function() {
|
||||
socket.disconnect();
|
||||
init();
|
||||
});
|
||||
|
||||
socket.on('command', (command, cb) => {
|
||||
commandHandlers(command, cb);
|
||||
});
|
||||
}
|
||||
|
||||
function readConfig() {
|
||||
return JSON.parse(fs.readFileSync(__dirname + '/config.js'));
|
||||
}
|
||||
|
||||
init();
|
Loading…
Add table
Reference in a new issue