diff --git a/nrtsc140.js b/nrtsc140.js index 0ade848..767b73a 100644 --- a/nrtsc140.js +++ b/nrtsc140.js @@ -1,10 +1,10 @@ /** * Constants. */ -const MAX_RECORDING_SEC = 30; -const SC_SEVER_STARTED_MSG = 'notification is on'; -const SC_SEVER_START_ERR_MSG = 'server failed to start'; -const JACK_DRIVER_IGNORE_MSG = 'JackDriver: max output latency'; +var MAX_RECORDING_SEC = 30; +var SC_SEVER_STARTED_MSG = 'notification is on'; +var SC_SEVER_START_ERR_MSG = 'server failed to start'; +var JACK_DRIVER_IGNORE_MSG = 'JackDriver: max output latency'; /** * Module dependencies. @@ -17,102 +17,88 @@ var sio = require('socket.io') , util = require('util') var NrtSc140 = exports.NrtSc140 = function(socket) { - var _socket = socket; - var _audioDir = path.join(process.cwd(), 'public', 'audio'); - var _curFile = null; - var _generatedFiles = new Array(); - var _timeoutId = null; - var _intervalId = null; - var _sclang = null; - var _sclangStdoutHandler = function(data) { - util.debug('sclang stdout: ' + data); - var msg = '' + data; - if (msg.indexOf(SC_SEVER_STARTED_MSG) != -1) { - _socket.emit('scserverstarted'); - } else if (msg.indexOf(SC_SEVER_START_ERR_MSG) != -1) { - } else if (msg.indexOf(JACK_DRIVER_IGNORE_MSG) != -1) { - // FIXME workaround - // in case other user start sclang - return; // ignore - } - _socket.emit('stdout', msg); - }; - - NrtSc140.prototype.start = function() { - _socket.emit('scserverstarting'); - _sclang = createSclang(_sclangStdoutHandler, _generatedFiles); - _socket.on('validate', this.onValidate); - _socket.on('generate', this.onGenerate); - _socket.on('stop', this.onStop); - _socket.on('restartsclang', this.onRestartSclang); - _socket.on('disconnect', this.onSocketDisconnect); - } - - NrtSc140.prototype.onRestartSclang = function() { - _socket.emit('scserverstarting'); - _sclang.dispose(); - _sclang = createSclang(_sclangStdoutHandler, _generatedFiles); - } - - NrtSc140.prototype.onValidate = function(msg) { - util.debug('validate: ' + msg); - validateScCode(msg, _socket); - } + this._socket = socket; + this._audioDir = path.join(process.cwd(), 'public', 'audio'); + this._curFile = null; + this._generatedFiles = new Array(); + this._timeoutId = null; + this._intervalId = null; + this._sclang = null; +}; + +NrtSc140.prototype.start = function() { + this._socket.emit('scserverstarting'); + this._sclang = this.createSclang(); + this._socket.on('validate', this.onValidate.bind(this)); + this._socket.on('generate', this.onGenerate.bind(this)); + this._socket.on('stop', this.onStop.bind(this)); + this._socket.on('restartsclang', this.onRestartSclang.bind(this)); + this._socket.on('disconnect', this.onSocketDisconnect.bind(this)); +} - NrtSc140.prototype.onGenerate = function(msg) { - util.debug('generate: ' + msg); - if (!validateScCode(msg, _socket)) return; - - var aiffFile; - do { - _curFile = randomString(); - aiffFile = path.join(_audioDir, _curFile + '.aiff'); - util.debug('aiffFile: ' + aiffFile); - } while (path.existsSync(aiffFile)); - //_generatedFiles.push(path.join(_audioDir, _curFile + '.*')); - _sclang.evaluate( - 's.waitForBoot(s.prepareForRecord(\'' - + aiffFile + '\');s.record;' - + msg + '\n);', false); - - var timeRemaining = MAX_RECORDING_SEC + 1; - _timeoutId = setTimeout(function() { - _timeoutId = stopRecording(_sclang, _socket, _audioDir, _curFile); - }, timeRemaining * 1000); - - var timeRecorded = 0; +NrtSc140.prototype.onRestartSclang = function() { + this._socket.emit('scserverstarting'); + if (this._sclang) this._sclang.dispose(); + this._sclang = this.createSclang(); +} + +NrtSc140.prototype.onValidate = function(msg) { + util.debug('validate: ' + msg); + this.validateScCode(msg, this._socket); +} + +NrtSc140.prototype.onGenerate = function(msg) { + util.debug('generate: ' + msg); + if (!this.validateScCode(msg, this._socket)) return; + + var aiffFile; + do { + this._curFile = randomString(); + aiffFile = path.join(this._audioDir, this._curFile + '.aiff'); + util.debug('aiffFile: ' + aiffFile); + } while (path.existsSync(aiffFile)); + //this._generatedFiles.push(path.join(_audioDir, _curFile + '.*')); + this._sclang.evaluate( + 's.waitForBoot(s.prepareForRecord(\'' + + aiffFile + '\');s.record;' + + msg + '\n);', false); + + var timeRemaining = MAX_RECORDING_SEC + 1; + this._timeoutId = setTimeout(function() { + this._timeoutId = this.stopRecording(); + }.bind(this), timeRemaining * 1000); + + var timeRecorded = 0; + util.debug('timerecorded: ' + timeRecorded); + this._socket.emit('timerecorded', '' + timeRecorded); + this._intervalId = setInterval(function() { + timeRecorded++; util.debug('timerecorded: ' + timeRecorded); - _socket.emit('timerecorded', '' + timeRecorded); - _intervalId = setInterval(function() { - timeRecorded++; - util.debug('timerecorded: ' + timeRecorded); - _socket.emit('timerecorded', '' + timeRecorded); - if (timeRecorded >= MAX_RECORDING_SEC) clearInterval(_intervalId); - }, 1000); - }; - - NrtSc140.prototype.onStop = function() { - util.debug('stop'); - if (_timeoutId) clearTimeout(_timeoutId); - if (_intervalId) clearInterval(_intervalId); - _timeoutId = stopRecording(_sclang, _socket, _audioDir, _curFile); - } + this._socket.emit('timerecorded', '' + timeRecorded); + if (timeRecorded >= MAX_RECORDING_SEC) clearInterval(this._intervalId); + }.bind(this), 1000); +}; - NrtSc140.prototype.onSocketDisconnect = function() { - util.debug('disconnect'); - if (_timeoutId) clearTimeout(_timeoutId); - if (_intervalId) clearInterval(_intervalId); - - _sclang.dispose(); - - for (i in _generatedFiles) { - rmFile(_generatedFiles[i]); - } +NrtSc140.prototype.onStop = function() { + util.debug('stop'); + if (this._timeoutId) clearTimeout(this._timeoutId); + if (this._intervalId) clearInterval(this._intervalId); + this._timeoutId = this.stopRecording(); +} + +NrtSc140.prototype.onSocketDisconnect = function() { + util.debug('disconnect'); + if (this._timeoutId) clearTimeout(this._timeoutId); + if (this._intervalId) clearInterval(this._intervalId); + if (this._sclang) this._sclang.dispose(); + for (var i in this._generatedFiles) { + rmFile(this._generatedFiles[i]); } -}; +} -function createSclang(handler, generatedFiles) { - var sclang = new sc.Sclang('/usr/bin/', handler); +NrtSc140.prototype.createSclang = function() { + var sclang = + new sc.Sclang('/usr/bin/', this.onSclangStdoutReceived.bind(this)); sclang.evaluate('Server.default = Server.internal;s = Server.default;s.boot;'); // FIXME workaround @@ -120,7 +106,7 @@ function createSclang(handler, generatedFiles) { do { workaroundTmpFile = '/tmp/nrt-sc140-' + randomString() + '.aiff'; } while (path.existsSync(workaroundTmpFile)); - generatedFiles.push(workaroundTmpFile); + this._generatedFiles.push(workaroundTmpFile); sclang.evaluate( 's.waitForBoot(s.prepareForRecord(\'' + workaroundTmpFile @@ -129,39 +115,52 @@ function createSclang(handler, generatedFiles) { return sclang; } -function validateScCode(msg, socket) { - if (msg.length < 1) { - socket.emit('validationerror', 'code can not be blank.'); - return false; - } - if (msg.length > 140) { - socket.emit('validationerror', 'code can not be over 140.'); - return false; - } - if (msg.indexOf('unixCmd') != -1) { - socket.emit('validationerror', '\'unixCmd\' can not be executed.'); - return false; - } - socket.emit('validationerror', ''); - return true; +NrtSc140.prototype.onSclangStdoutReceived = function(data) { + util.debug('sclang stdout: ' + data); + var msg = '' + data; + if (msg.indexOf(SC_SEVER_STARTED_MSG) != -1) { + this._socket.emit('scserverstarted'); + } else if (msg.indexOf(SC_SEVER_START_ERR_MSG) != -1) { + } else if (msg.indexOf(JACK_DRIVER_IGNORE_MSG) != -1) { + // FIXME workaround + // in case other user start sclang + return; // ignore + } + this._socket.emit('stdout', msg); +} + +NrtSc140.prototype.validateScCode = function(msg) { + if (msg.length < 1) { + this._socket.emit('validationerror', 'code can not be blank.'); + return false; + } + if (msg.length > 140) { + this._socket.emit('validationerror', 'code can not be over 140.'); + return false; + } + if (msg.indexOf('unixCmd') != -1) { + this._socket.emit('validationerror', '\'unixCmd\' can not be executed.'); + return false; + } + this._socket.emit('validationerror', ''); + return true; } -function stopRecording(sclang, socket, audioDir, filename) { - sclang.evaluate('s.stopRecording;', false); - sclang.stopSound(); - var timeoutId = setTimeout(function() { - var aiffFile = path.join(audioDir, filename + '.aiff'); - var mp3File = path.join(audioDir, filename + '.mp3'); +NrtSc140.prototype.stopRecording = function() { + this._sclang.evaluate('s.stopRecording;', false); + this._sclang.stopSound(); + this._timeoutId = setTimeout(function() { + var aiffFile = path.join(this._audioDir, this._curFile + '.aiff'); + var mp3File = path.join(this._audioDir, this._curFile + '.mp3'); convert(aiffFile, mp3File, function(error, stdout, stderr) { util.debug('stdout: ' + stdout); util.debug('stderr: ' + stderr); if (error != null) { util.debug('exec error: ' + error); } - socket.emit('filegenerated', filename); - }); - }, 1000); - return timeoutId; + this._socket.emit('filegenerated', this._curFile); + }.bind(this)); + }.bind(this), 1000); } function randomString() {