<commit_before>var events = require('events');
var inherits = require('util').inherits;
var bopper = require('./vendor/bopper');
var ditty = require('./vendor/ditty');
var expr = require('dilla-expressions');
var memoize = require('meemo');

var checkValid = require('./lib/checkValid');
var positionHelper = require('./lib/positionHelper');

var loadTime = new Date().valueOf();

var memoSpacer = '//';

function Dilla (audioContext, options) {

  if (!(this instanceof Dilla)){
    return new Dilla(audioContext, options);
  }

  if (!audioContext || typeof audioContext !== 'object' || typeof audioContext.createScriptProcessor !== 'function') {
    throw new Error('Invalid arguments: cannot init without AudioContext');
  }

  events.EventEmitter.call(this);

  options = options || {};

  this.context = audioContext;
  this.clock = bopper(this.context);
  this.scheduler = ditty();

  this.expressions = expr;
  this.expandNote = options.expandNote;

  this.upstartWait = options.upstartWait || 250;
  this.setTempo(options.tempo || 120);
  this.setBeatsPerBar(options.beatsPerBar || 4);
  this.setLoopLength(options.loopLength || 2);

  this._position = '0.0.00';

  this.clock.on('data', this.updatePositionFromClock.bind(this));
  this.clock.pipe(this.scheduler).on('data', this.emitStep.bind(this));

  this._keepAlive = this._keepAlive.bind(this);
}

inherits(Dilla, events.EventEmitter);
var proto = Dilla.prototype;

proto.updatePositionFromClock = function updatePositionFromClock (step) {
  var position = this.getPositionFromTime(step.time);
  if (this._position !== position) {
    this._position = position;
    this.emit('tick', { 'position': this._position, 'context': this.context });
  }
};

proto.getPositionFromTime = function getPositionFromTime (time) {
  var offset = (this.clock._state.cycleLength * this.clock._state.preCycle) * 1;
  var position = this.clock.getPositionAt(time - offset);
  return this.getPositionFromClockPosition(position);
};

proto.getPositionFromClockPosition = function getPositionFromClockPosition (position) {
  checkValid.number('clockPosition', position);
  if (position < 0) {
    return '0.0.00';
  }
  var beatsPerLoop = this._loopLength * this._beatsPerBar;
  var loops = Math.floor(position / beatsPerLoop) || 0;
  position = position - (loops * beatsPerLoop);
  var bars = Math.floor(position / this._beatsPerBar);
  position = position - (bars * this._beatsPerBar);
  var beats = Math.floor(position);
  position = position - beats;
  var ticks = Math.floor(position * 96) + 1;
  if (ticks < 10) {
    ticks = '0' + ticks;
  }
  return (bars + 1) + '.' + (beats + 1) + '.' + ticks;
};

proto.getClockPositionFromPosition = memoize(function getClockPositionFromPosition (position) {
  var parts = position.split('.');
  var bars = parseInt(parts[0], 10) - 1;
  var beats = parseInt(parts[1], 10) - 1;
  var ticks = parseInt(parts[2], 10) - 1;
  return (bars * this._beatsPerBar) + beats + (ticks / 96);
});

proto.getPositionWithOffset = memoize(function getPositionWithOffset (position, offset) {
  if (!checkValid.positionString(position)) {
    throw new Error('Invalid argument: position is not a valid position string');
  }
  if (typeof offset !== 'number' || isNaN(offset) || offset % 1 !== 0) {
    throw new Error('Invalid argument: offset is not a valid number');
  }
  if (!offset) {
    return position;
  }
  var clockPosition = this.getClockPositionFromPosition(position);
  var clockOffset = offset / 96;
  return this.getPositionFromClockPosition(clockPosition + clockOffset);
}, function (position, offset) {
  return position + memoSpacer + offset;
});

proto.getDurationFromTicks = function getDurationFromTicks (ticks) {
  checkValid.positiveNumber('ticks', ticks);
  return (1 / 96) * ticks;
};

proto.emitStep = function emitStep (step) {
  var offset = step.offset = (this.clock._state.cycleLength * this.clock._state.preCycle) * 1;
  var note = step.args;
  step.time = step.time + offset;
  step.clockPosition = step.position;
  step.position = step.event === 'start' ? note.position : note.duration ?  this.getPositionWithOffset(note.position, note.duration) : note.position;
  if (step.event === 'stop'  && step.position === note.position) {
    return;
  }
  step.context = this.context;
  this.emit('step', step);
};

proto.notesForSet = memoize(function notesForSet (id, notes, beatsPerBar, loopLength) {

  var self = this;
  notes.forEach(function (note, index) {
    if (!Array.isArray(note) && typeof note === 'object' && !!note.position) {
      notes[index] = [note.position, note];
    }
  });

  notes = self.expressions(notes, {
    'beatsPerBar': beatsPerBar,
    'barsPerLoop': loopLength
  });

  var filtered = false;

  notes.forEach(function (note, index) {
    if (positionHelper.isPositionWithinBounds(note[0], loopLength, beatsPerBar)) {
      if (self.expandNote) {
        note = self.expandNote(note);
      }
      var normal = positionHelper.normalizeNote(note);
      notes[index] = [self.getClockPositionFromPosition(normal.position), self.getDurationFromTicks(normal.duration || 0), null, null, normal];
    }
    else {
      notes[index] = null;
      filtered = true;
    }
  });

  if (filtered) {
    return notes.filter(function (note) { return !!note; });
  }

  return notes;
}, function (id, notes, beatsPerBar, loopLength) {
  return id + memoSpacer + JSON.stringify(notes) + memoSpacer + beatsPerBar + memoSpacer + loopLength;
});

proto.set = function set (id, notes) {
  var self = this;
  if (typeof id !== 'string') {
    throw new Error('Invalid argument: id is not a valid string');
  }
  if (!notes || !Array.isArray(notes)) {
    throw new Error('Invalid argument: notes is not a valid array');
  }

  this.scheduler.set(id, this.notesForSet(id, notes, this.beatsPerBar(), this.loopLength()), this.beatsPerBar() * this.loopLength());
};

proto.get = function get (id) {
  if (typeof id !== 'string') {
    throw new Error('Invalid argument: id is not a valid string');
  }
  return (this.scheduler.get(id) || []).map(function (note) {
    return note[4];
  });
};

proto.channels = function channels () {
  return this.scheduler.getIds();
};

proto.clear = function clear (id) {
  var self = this;
  if (id) {
    if (typeof id !== 'string') {
      throw new Error('Invalid argument: id is not a valid string');
    }
    this.set(id, []);
  }
  else {
    this.scheduler.getIds().forEach(function (id) {
      self.clear(id);
    });
  }
};

proto._keepAlive = function _keepAlive () {
  if (this.clock._state.playing) {
    window.__lastDillaPosition = this._position;
    setTimeout(window.requestAnimationFrame.bind(null, this._keepAlive), 100);
  }
};

proto.start = function start () {
  var now = new Date().valueOf();
  var waited = now - loadTime;
  if (waited < this.upstartWait) {
    return setTimeout(start.bind(this), this.upstartWait - waited);
  }

  if (!this.clock._state.playing) {
    this.clock.start();
    this._keepAlive();
    this.emit('playing');
  }
};

proto.pause = function pause () {
  if (this.clock._state.playing) {
    this.clock.stop();
    this.emit('paused');
  }
};

proto.stop = function stop () {
  if (this.clock._state.playing) {
    this.clock.stop();
    this.emit('paused');
    this.clock.setPosition(0);
    this._position = '0.0.00';
  }
};

proto.position = function position () {
  return this._position;
};

proto.setPosition = function setPosition (position) {
  if (!positionHelper.isPositionWithinBounds(position, this.loopLength(), this.beatsPerBar())) {
    throw new Error('Invalid argument: position is not valid');
  }
  this._position = position;
  this.clock.setPosition(this.getClockPositionFromPosition(position));
};

proto.tempo = function tempo () {
  return this.clock.getTempo();
};

proto.setTempo = function setTempo (tempo) {
  if (typeof tempo !== 'number' || tempo < 0 || isNaN(tempo)) {
    throw new Error('Invalid argument: tempo is not a valid number');
  }
  this.clock.setTempo(tempo);
};

proto.beatsPerBar = function beatsPerBar () {
  return this._beatsPerBar;
};

proto.setBeatsPerBar = function setBeatsPerBar (beats) {
  checkValid.positiveNumber('beats', beats);
  this._beatsPerBar = beats;
};

proto.loopLength = function loopLength () {
  return this._loopLength;
};

proto.setLoopLength = function setLoopLength (bars) {
  checkValid.positiveNumber('bars', bars);
  this._loopLength = bars;
};

module.exports = Dilla;
<commit_msg>memoizes getClockPositionFromPosition including beats per bar<commit_after>var events = require('events');
var inherits = require('util').inherits;
var bopper = require('./vendor/bopper');
var ditty = require('./vendor/ditty');
var expr = require('dilla-expressions');
var memoize = require('meemo');

var checkValid = require('./lib/checkValid');
var positionHelper = require('./lib/positionHelper');

var loadTime = new Date().valueOf();

var memoSpacer = '//';

function Dilla (audioContext, options) {

  if (!(this instanceof Dilla)){
    return new Dilla(audioContext, options);
  }

  if (!audioContext || typeof audioContext !== 'object' || typeof audioContext.createScriptProcessor !== 'function') {
    throw new Error('Invalid arguments: cannot init without AudioContext');
  }

  events.EventEmitter.call(this);

  options = options || {};

  this.context = audioContext;
  this.clock = bopper(this.context);
  this.scheduler = ditty();

  this.expressions = expr;
  this.expandNote = options.expandNote;

  this.upstartWait = options.upstartWait || 250;
  this.setTempo(options.tempo || 120);
  this.setBeatsPerBar(options.beatsPerBar || 4);
  this.setLoopLength(options.loopLength || 2);

  this._position = '0.0.00';

  this.clock.on('data', this.updatePositionFromClock.bind(this));
  this.clock.pipe(this.scheduler).on('data', this.emitStep.bind(this));

  this._keepAlive = this._keepAlive.bind(this);
}

inherits(Dilla, events.EventEmitter);
var proto = Dilla.prototype;

proto.updatePositionFromClock = function updatePositionFromClock (step) {
  var position = this.getPositionFromTime(step.time);
  if (this._position !== position) {
    this._position = position;
    this.emit('tick', { 'position': this._position, 'context': this.context });
  }
};

proto.getPositionFromTime = function getPositionFromTime (time) {
  var offset = (this.clock._state.cycleLength * this.clock._state.preCycle) * 1;
  var position = this.clock.getPositionAt(time - offset);
  return this.getPositionFromClockPosition(position);
};

proto.getPositionFromClockPosition = function getPositionFromClockPosition (position) {
  checkValid.number('clockPosition', position);
  if (position < 0) {
    return '0.0.00';
  }
  var beatsPerLoop = this._loopLength * this._beatsPerBar;
  var loops = Math.floor(position / beatsPerLoop) || 0;
  position = position - (loops * beatsPerLoop);
  var bars = Math.floor(position / this._beatsPerBar);
  position = position - (bars * this._beatsPerBar);
  var beats = Math.floor(position);
  position = position - beats;
  var ticks = Math.floor(position * 96) + 1;
  if (ticks < 10) {
    ticks = '0' + ticks;
  }
  return (bars + 1) + '.' + (beats + 1) + '.' + ticks;
};

proto.getClockPositionFromPosition = memoize(function getClockPositionFromPosition (position, beatsPerBar) {
  var parts = position.split('.');
  var bars = parseInt(parts[0], 10) - 1;
  var beats = parseInt(parts[1], 10) - 1;
  var ticks = parseInt(parts[2], 10) - 1;
  return (bars * beatsPerBar) + beats + (ticks / 96);
});

proto.getPositionWithOffset = function getPositionWithOffset (position, offset) {
  return this.getPositionWithOffsetAndBeatsPerBar(position, offset, this.beatsPerBar());
};

proto.getPositionWithOffsetAndBeatsPerBar = memoize(function getPositionWithOffsetAndBeatsPerBar (position, offset, beatsPerBar) {
  if (!checkValid.positionString(position)) {
    throw new Error('Invalid argument: position is not a valid position string');
  }
  if (typeof offset !== 'number' || isNaN(offset) || offset % 1 !== 0) {
    throw new Error('Invalid argument: offset is not a valid number');
  }
  if (!offset) {
    return position;
  }
  var clockPosition = this.getClockPositionFromPosition(position, beatsPerBar);
  var clockOffset = offset / 96;
  return this.getPositionFromClockPosition(clockPosition + clockOffset);
}, function (position, offset) {
  return position + memoSpacer + offset;
});

proto.getDurationFromTicks = function getDurationFromTicks (ticks) {
  checkValid.positiveNumber('ticks', ticks);
  return (1 / 96) * ticks;
};

proto.emitStep = function emitStep (step) {
  var offset = step.offset = (this.clock._state.cycleLength * this.clock._state.preCycle) * 1;
  var note = step.args;
  step.time = step.time + offset;
  step.clockPosition = step.position;
  step.position = step.event === 'start' ? note.position : note.duration ?  this.getPositionWithOffsetAndBeatsPerBar(note.position, note.duration, this.beatsPerBar()) : note.position;
  if (step.event === 'stop'  && step.position === note.position) {
    return;
  }
  step.context = this.context;
  this.emit('step', step);
};

proto.notesForSet = memoize(function notesForSet (id, notes, beatsPerBar, loopLength) {

  var self = this;
  notes.forEach(function (note, index) {
    if (!Array.isArray(note) && typeof note === 'object' && !!note.position) {
      notes[index] = [note.position, note];
    }
  });

  notes = self.expressions(notes, {
    'beatsPerBar': beatsPerBar,
    'barsPerLoop': loopLength
  });

  var filtered = false;

  notes.forEach(function (note, index) {
    if (positionHelper.isPositionWithinBounds(note[0], loopLength, beatsPerBar)) {
      if (self.expandNote) {
        note = self.expandNote(note);
      }
      var normal = positionHelper.normalizeNote(note);
      notes[index] = [self.getClockPositionFromPosition(normal.position, beatsPerBar), self.getDurationFromTicks(normal.duration || 0), null, null, normal];
    }
    else {
      notes[index] = null;
      filtered = true;
    }
  });

  if (filtered) {
    return notes.filter(function (note) { return !!note; });
  }

  return notes;
}, function (id, notes, beatsPerBar, loopLength) {
  return id + memoSpacer + JSON.stringify(notes) + memoSpacer + beatsPerBar + memoSpacer + loopLength;
});

proto.set = function set (id, notes) {
  var self = this;
  if (typeof id !== 'string') {
    throw new Error('Invalid argument: id is not a valid string');
  }
  if (!notes || !Array.isArray(notes)) {
    throw new Error('Invalid argument: notes is not a valid array');
  }

  this.scheduler.set(id, this.notesForSet(id, notes, this.beatsPerBar(), this.loopLength()), this.beatsPerBar() * this.loopLength());
};

proto.get = function get (id) {
  if (typeof id !== 'string') {
    throw new Error('Invalid argument: id is not a valid string');
  }
  return (this.scheduler.get(id) || []).map(function (note) {
    return note[4];
  });
};

proto.channels = function channels () {
  return this.scheduler.getIds();
};

proto.clear = function clear (id) {
  var self = this;
  if (id) {
    if (typeof id !== 'string') {
      throw new Error('Invalid argument: id is not a valid string');
    }
    this.set(id, []);
  }
  else {
    this.scheduler.getIds().forEach(function (id) {
      self.clear(id);
    });
  }
};

proto._keepAlive = function _keepAlive () {
  if (this.clock._state.playing) {
    window.__lastDillaPosition = this._position;
    setTimeout(window.requestAnimationFrame.bind(null, this._keepAlive), 100);
  }
};

proto.start = function start () {
  var now = new Date().valueOf();
  var waited = now - loadTime;
  if (waited < this.upstartWait) {
    return setTimeout(start.bind(this), this.upstartWait - waited);
  }

  if (!this.clock._state.playing) {
    this.clock.start();
    this._keepAlive();
    this.emit('playing');
  }
};

proto.pause = function pause () {
  if (this.clock._state.playing) {
    this.clock.stop();
    this.emit('paused');
  }
};

proto.stop = function stop () {
  if (this.clock._state.playing) {
    this.clock.stop();
    this.emit('paused');
    this.clock.setPosition(0);
    this._position = '0.0.00';
  }
};

proto.position = function position () {
  return this._position;
};

proto.setPosition = function setPosition (position) {
  if (!positionHelper.isPositionWithinBounds(position, this.loopLength(), this.beatsPerBar())) {
    throw new Error('Invalid argument: position is not valid');
  }
  this._position = position;
  this.clock.setPosition(this.getClockPositionFromPosition(position, this.beatsPerBar()));
};

proto.tempo = function tempo () {
  return this.clock.getTempo();
};

proto.setTempo = function setTempo (tempo) {
  if (typeof tempo !== 'number' || tempo < 0 || isNaN(tempo)) {
    throw new Error('Invalid argument: tempo is not a valid number');
  }
  this.clock.setTempo(tempo);
};

proto.beatsPerBar = function beatsPerBar () {
  return this._beatsPerBar;
};

proto.setBeatsPerBar = function setBeatsPerBar (beats) {
  checkValid.positiveNumber('beats', beats);
  this._beatsPerBar = beats;
};

proto.loopLength = function loopLength () {
  return this._loopLength;
};

proto.setLoopLength = function setLoopLength (bars) {
  checkValid.positiveNumber('bars', bars);
  this._loopLength = bars;
};

module.exports = Dilla;
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var nodeServer = require('http').Server(app);
//var mongo = require('mongodb');
//var database = require('./database.js');
var io = require('socket.io').listen(nodeServer);
var socketPort = 3000;
app.set('port', process.env.PORT || 5000);
app.use(express.static(__dirname));

app.get('/', function (req, res) {
	res.sendFile(__dirname + req.url);
});

io.on('connection', function (socket) {
	console.log("Someone connected.");
	socket.on('msg', function (msg) {
		console.log('Incoming message: ' + msg);
		socket.broadcast.emit('incoming message', msg);
	});
	socket.on('disconnect', function () {
		console.log('Someone disconnected.');
	});
})

/*app.post('/', function (req, res) {
	console.log("Post request received");
});*/

app.listen(app.get('port'), function () {
  console.log("Node app is running on port:" + app.get('port'));
});

nodeServer.listen(socketPort, function () {
	console.log("Socket.io server is listening to port " + socketPort);
});<commit_msg>Using set instead of direct vars<commit_after>var express = require('express');
var app = express();
var nodeServer = require('http').Server(app);
//var mongo = require('mongodb');
//var database = require('./database.js');
var io = require('socket.io').listen(nodeServer);
var socketPort = 3000;
app.set('socketPort', 3000);
app.set('port', process.env.PORT || 5000);
app.use(express.static(__dirname));

app.get('/', function (req, res) {
	res.sendFile(__dirname + req.url);
});

io.on('connection', function (socket) {
	console.log("Someone connected.");
	socket.on('msg', function (msg) {
		console.log('Incoming message: ' + msg);
		socket.broadcast.emit('incoming message', msg);
	});
	socket.on('disconnect', function () {
		console.log('Someone disconnected.');
	});
})

/*app.post('/', function (req, res) {
	console.log("Post request received");
});*/

app.listen(app.get('port'), function () {
  console.log("Node app is running on port:" + app.get('port'));
});

nodeServer.listen(app.get('socketPort'), function () {
	console.log("Socket.io server is listening to port " + app.get('socketPort');
});<|endoftext|>


<commit_before>const Promise = require("nodegit-promise");
const args = require("./utils/args");

// Unfortunately this list is not exhaustive, so if you find that a method does
// not use a "standard"-ish name, you'll have to extend this list.
var callbacks = ["cb", "callback", "callback_", "done"];

/**
 * Recursively operate over an object locating "asynchronous" functions by
 * inspecting the last argument in the parameter signature for a callback.
 *
 * @param {*} exports - Should be a function or an object, identity other.
 * @param {Function} test - Optional function to identify async methods.
 * @param {String} parentKeyName - Tracks the keyName in a digestable format.
 * @returns {*} exports - Identity.
 */
function processExports(exports, test, cached, parentKeyName) {
  // Return early if this object has already been processed.
  if (cached.indexOf(exports) > -1) {
    return exports;
  }

  // Record this object in the cache.
  cached.push(exports);

  // Pass through if not an object or function.
  if (typeof exports != "object" && typeof exports != "function") {
    return exports;
  }

  var name = exports.name + "#";

  // If a function, simply return it wrapped.
  if (typeof exports === "function") {
    // Find properties added to functions.
    for (var keyName in exports) {
      exports[keyName] = processExports(exports[keyName], test, cached, name);
    }

    // Find methods on the prototype, if there are any.
    if (Object.keys(exports.prototype).length) {
      processExports(exports.prototype, test, cached, name);
    }

    // If a filter function exists, use this to determine if the function
    // is asynchronous.
    if (test) {
      // Pass the function itself, its keyName, and the parent keyName.
      if (!test(exports, keyName, parentKeyName)) {
        return exports;
      }
    }

    // If the callback name exists as the last argument, consider it an
    // asynchronous function.  Brittle? Fragile? Effective.
    else if (callbacks.indexOf(args(exports).slice(-1)[0]) === -1) {
      return exports;
    }

    // Assign the new function in place.
    var wrapped = Promise.denodeify(exports);

    // Attach the augmented prototype.
    wrapped.prototype = exports.prototype;

    // Ensure attached properties to the previous function are accessible.
    wrapped.__proto__ = exports;

    return wrapped;
  }

  Object.keys(exports).map(function(keyName) {
    // Convert to values.
    return [keyName, exports[keyName]];
  }).forEach(function(keyVal) {
    var keyName = keyVal[0];
    var value = keyVal[1];

    // If an object is encountered, recursively traverse.
    if (typeof value === "object") {
      processExports(exports, test, cached, keyName + ".");
    }

    // Wrap this function and reassign.
    exports[keyName] = processExports(value, test, cached, parentKeyName);
  });

  return exports;
}

/**
 * Public API for Promisify.  Will resolve modules names using `require`.
 *
 * @param {*} name - Can be a module name, object, or function.
 * @param {Function} test - Optional function to identify async methods.
 * @returns {*} exports - The resolved value from require or passed in value.
 */
module.exports = function(name, test) {
  var exports = name;

  // If the name argument is a String, will need to resovle using the built in
  // Node require function.
  if (typeof name === "string") {
    exports = require(name);
  }

  // Iterate over all properties and find asynchronous functions to convert to
  // promises.
  return processExports(exports, test, []);
};

// Export callbacks to the module.
module.exports.callbacks = callbacks;
<commit_msg>Revert "Refactor function processExports."<commit_after>const Promise = require("nodegit-promise");
const args = require("./utils/args");

// Unfortunately this list is not exhaustive, so if you find that a method does
// not use a "standard"-ish name, you'll have to extend this list.
var callbacks = ["cb", "callback", "callback_", "done"];

/**
 * Recursively operate over an object locating "asynchronous" functions by
 * inspecting the last argument in the parameter signature for a callback.
 *
 * @param {*} exports - Should be a function or an object, identity other.
 * @param {Function} test - Optional function to identify async methods.
 * @param {String} parentKeyName - Tracks the keyName in a digestable format.
 * @returns {*} exports - Identity.
 */
function processExports(exports, test, cached, parentKeyName) {
  // Return early if this object has already been processed.
  if (cached.indexOf(exports) > -1) {
    return exports;
  }

  // Record this object in the cache.
  cached.push(exports);

  // Pass through if not an object or function.
  if (typeof exports != "object" && typeof exports != "function") {
    return exports;
  }

  var name = exports.name + "#";

  // If a function, simply return it wrapped.
  if (typeof exports === "function") {
    // Find properties added to functions.
    for (var keyName in exports) {
      exports[keyName] = processExports(exports[keyName], test, cached, name);
    }

    // Assign the new function in place.
    var wrapped = Promise.denodeify(exports);

    // Find methods on the prototype, if there are any.
    if (Object.keys(exports.prototype).length) {
      processExports(exports.prototype, test, cached, name);
    }

    // Attach the augmented prototype.
    wrapped.prototype = exports.prototype;

    // Ensure attached properties to the previous function are accessible.
    wrapped.__proto__ = exports;

    return wrapped;
  }

  Object.keys(exports).map(function(keyName) {
    // Convert to values.
    return [keyName, exports[keyName]];
  }).filter(function(keyVal) {
    var keyName = keyVal[0];
    var value = keyVal[1];

    // If an object is encountered, recursively traverse.
    if (typeof value === "object") {
      processExports(exports, test, cached, keyName + ".");
    }
    // Filter to functions with callbacks only.
    else if (typeof value === "function") {
      // If a filter function exists, use this to determine if the function
      // is asynchronous.
      if (test) {
        // Pass the function itself, its keyName, and the parent keyName.
        return test(value, keyName, parentKeyName);
      }

      // If the callback name exists as the last argument, consider it an
      // asynchronous function.  Brittle? Fragile? Effective.
      if (callbacks.indexOf(args(value).slice(-1)[0]) > -1) {
        return true;
      }
    }
  }).forEach(function(keyVal) {
    var keyName = keyVal[0];
    var func = keyVal[1];

    // Wrap this function and reassign.
    exports[keyName] = processExports(func, test, cached, parentKeyName);
  });

  return exports;
}

/**
 * Public API for Promisify.  Will resolve modules names using `require`.
 *
 * @param {*} name - Can be a module name, object, or function.
 * @param {Function} test - Optional function to identify async methods.
 * @returns {*} exports - The resolved value from require or passed in value.
 */
module.exports = function(name, test) {
  var exports = name;

  // If the name argument is a String, will need to resovle using the built in
  // Node require function.
  if (typeof name === "string") {
    exports = require(name);
  }

  // Iterate over all properties and find asynchronous functions to convert to
  // promises.
  return processExports(exports, test, []);
};

// Export callbacks to the module.
module.exports.callbacks = callbacks;
<|endoftext|>


<commit_before>//bedJS - Converts a BED file into a JSON object

//Exports to node
module.exports =
{
	//Read a BED file
	Read: require('./lib/read.js'),

	//Save to a BED file
	Write: require('./lib/write.js'),

	//Work with fasta files
	Fasta: require('./lib/fasta.js'),

	//Collapse bed files
	Collapse: require('./lib/collapse.js')
};
<commit_msg>index.js: fix<commit_after>//Exports to node
module.exports =
{
  //Read a BED file
  Read: require('./lib/read.js'),

  //Save to a BED file
  Write: require('./lib/write.js'),

  //Work with fasta files
  Fasta: require('./lib/fasta.js'),

  //Collapse bed files
  Collapse: require('./lib/collapse.js')
};
<|endoftext|>


<commit_before>'use strict';

var debug   = require('debug')('azurin');
var fs      = require('fs');
var path    = require('path');
var assert  = require('assert');
var request = require('request');
var azure   = require('azure-storage');
var mgmtSQL = require('azure-mgmt-sql');
var mgmtSTG = require('azure-mgmt-storage');

var cloudCredentials, sqlmgmt, storagemgmt;

/**
 * Module entry, set Azure credentials and management clients.
 *
 * @param  {string} certificate    Path to Azure certificate
 * @param  {string} subscriptionId Optionnal Azure subscriptionId, defaults to certificate filename.
 */
module.exports = function (certificate, subscriptionId) {

  subscriptionId = subscriptionId || path.basename(certificate, '.pem');

  cloudCredentials = mgmtSQL.createCertificateCloudCredentials({
    subscriptionId: subscriptionId,
    pem: fs.readFileSync(certificate)
  });

  sqlmgmt     = mgmtSQL.createSqlManagementClient(cloudCredentials);
  storagemgmt = mgmtSTG.createStorageManagementClient(cloudCredentials);

  return {
    backup: exportToBlob,
    restore: importFromBlob,
    requestStatus: requestStatus,
    waitUntilRequestFinish: waitUntilRequestFinish,
    lastImportInBlobStorage: lastImportInBlobStorage,

    // mainly for tests
    deleteDatabase: deleteDatabase,
    deleteContainer: deleteContainer,
    deleteBlob: deleteBlob
  };
};

/**
 * Export database to a blob storage
 *
 * @param  {object}   db       { server, name, user, password }
 * @param  {object}   blob     { name, accountName, accountKey  }
 * @param  {function} callback callback
 *
 * @return {request}  The underlying request
 */
function exportToBlob (db, blob, callback) {

  debug('will backup ' + db.server + '/' + db.name + ' to ' + blob.accountName + '/' + blob.name);

  function processRequest (error, primaryKey) {

    if (error) {
      debug(error);
      return callback(error);
    }

    if (! primaryKey) {
      debug('cannot process without accountKey');
      return callback(new Error('cannot access storage account'));
    }

    db.user   = db.user.match(/@/) ? db.user : db.user + '@' + db.server;
    db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
    blob.uri  = (blob.name.match(/^http/)) ? blob.name :
      'https://' + blob.accountName + '.blob.core.windows.net/' + blob.container + '/' +  blob.name;

    var parameters = {
      connectionInfo: {
        databaseName: db.name,
        password:     db.password,
        serverName:   db.server,
        userName:     db.user
      },
      blobCredentials: {
        storageAccessKey: primaryKey,
        uri: blob.uri
      }
    };

    ensureContainerExists(blob.accountName, primaryKey, blob.container, function (error) {
      if (error) return callback(error);
      return sqlmgmt.dac.exportMethod(db.server.split('.')[0], parameters, function(error, result) {

        if (error) {
          debug('backup queuing failed: ' + error);
          return callback(error);
        }

        debug(blob.uri + ' successfully queued. Guid=' + result.guid);
        callback(null, result.guid);
      });
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}

/**
 * Import database from a blob storage
 *
 * @param  {object}   db       { server, name, user, password }
 * @param  {object}   blob     { name, accountName, accountKey  }
 * @param  {function} callback callback
 *
 * @return {request}  The underlying request
 */
function importFromBlob (db, blob, callback) {

  debug('will restore ' + blob.accountName + '/' + blob.name + ' to ' + db.server + '/' + db.name);

  assert(blob.name,        'You must provide blob.name');
  assert(blob.accountName, 'You must provide blob.accountName');

  assert(db.name,     'You must provide db.name');
  assert(db.password, 'You must provide db.password');
  assert(db.server,   'You must provide db.server');
  assert(db.user,     'You must provide db.user');

  function processRequest (error, primaryKey) {

    if (error) {
      debug(error);
      return callback(error);
    }

    if (! primaryKey) {
      debug('cannot process without accountKey');
      return callback(new Error('cannot access storage account'));
    }

    db.user   = db.user.match(/@/) ? db.user : db.user + '@' + db.server;
    db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
    blob.uri  = (blob.name.match(/^http/)) ? blob.name :
      'https://' + blob.accountName + '.blob.core.windows.net/' + blob.container + '/' +  blob.name;

    var parameters = {
      connectionInfo: {
        databaseName: db.name,
        password:     db.password,
        serverName:   db.server,
        userName:     db.user
      },
      azureEdition: db.edition  || 'Business',
      databaseSizeInGB: db.size || 10,
      blobCredentials: {
        storageAccessKey: primaryKey,
        uri: blob.uri
      }
    };

    return sqlmgmt.dac.importMethod(db.server.split('.')[0], parameters, function(error, result) {

      if (error) {
        debug('restore queuing failed: ' + error);
        return callback(error);
      }

      debug(db.name + ' successfully queued. Guid=' + result.guid);
      callback(null, result.guid);
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}

function requestStatus (db, guid, callback) {
  db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
  return sqlmgmt.dac.getStatus(db.server.split('.')[0], db.server, db.user, db.password, guid, function (error, result) {
    if (error || !result.statusInfoList) { return callback(error); }
    callback(error, result.statusInfoList[0]);
  });
}

function waitUntilRequestFinish (db, guid, callback, eachCallback) {
  function retry () {
    requestStatus (db, guid, function (error, req) {

      if (eachCallback) {eachCallback(error, req);}

      // error
      if (error) {
        debug('error: ' + error);
        return callback(error);
      }

      // finished !
      else if (! error && (!req.status || req.status.toLowerCase() === 'completed')) {
        debug('request ' + guid + ' finished');
        return callback(null);
      }

      // still running
      else {
        debug('still ' + req.status.toLowerCase());
        setTimeout(retry, 10 * 1000);
      }
    });
  }
  retry();
}

function sortBlobs (a, b) {
  return a.properties['last-modified'] > b.properties['last-modified'] ? 1 : -1;
}

function blobAccountKey (accountName, callback) {

  storagemgmt.storageAccounts.getKeys(accountName, function (err, result) {

    if (err) {
      debug(err);
      return callback(err);
    }

    debug('ask for blob accountKey: ' + accountName + ': ' + result.primaryKey);

    callback(err, result.primaryKey);
  });
}

function lastImportInBlobStorage (account, key, container, callback) {
  var service = azure.createBlobService(account, key);
  service.listBlobsSegmented(container, null, function(error, result, response){
    if (error || !result.entries) { return callback(error); }
    result.entries.sort(sortBlobs);
    callback(null, result.entries.pop());
  });
}

function ensureContainerExists (account, key, container, callback) {
  var service = azure.createBlobService(account, key);
  service.createContainerIfNotExists(container, null, function(error, result, response){
    if (error) { return callback(error); }
    debug('%s container %s', container, result ? 'has been created' : 'already exists');
    callback(null);
  });
}

function deleteDatabase (db, callback) {
  db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
  sqlmgmt.databases.deleteMethod(db.server.split('.')[0], db.name, function (error, result) {
    if (error) {
      debug('cannot delete database %s: %s', db.name, error);
    } else {
      debug('successfully deleted database %s', db.name);
    }
    callback(error);
  });
}

function deleteBlob (blob, callback) {
  function processRequest (error, accountKey) {
    var service = azure.createBlobService(blob.accountName, accountKey);
    service.deleteBlob(blob.container, blob.name, function (error, result) {
      if (error) {
        debug('cannot delete blob %s/%s: %s', blob.container, blob.name, error);
      } else {
        debug('successfully deleted blob %s/%s', blob.container, blob.name);
      }
      callback(error);
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}

function deleteContainer (blob, callback) {
  function processRequest (error, accountKey) {
    var service = azure.createBlobService(blob.accountName, accountKey);
    service.deleteContainer(blob.container, function (error, result) {
      if (error) {
        debug('cannot delete container %s: %s', blob.container, error);
      } else {
        debug('successfully deleted container %s', blob.container);
      }
      callback(error);
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}
<commit_msg>fix incorrect message, show error message in request<commit_after>'use strict';

var debug   = require('debug')('azurin');
var fs      = require('fs');
var path    = require('path');
var assert  = require('assert');
var request = require('request');
var azure   = require('azure-storage');
var mgmtSQL = require('azure-mgmt-sql');
var mgmtSTG = require('azure-mgmt-storage');

var cloudCredentials, sqlmgmt, storagemgmt;

/**
 * Module entry, set Azure credentials and management clients.
 *
 * @param  {string} certificate    Path to Azure certificate
 * @param  {string} subscriptionId Optionnal Azure subscriptionId, defaults to certificate filename.
 */
module.exports = function (certificate, subscriptionId) {

  subscriptionId = subscriptionId || path.basename(certificate, '.pem');

  cloudCredentials = mgmtSQL.createCertificateCloudCredentials({
    subscriptionId: subscriptionId,
    pem: fs.readFileSync(certificate)
  });

  sqlmgmt     = mgmtSQL.createSqlManagementClient(cloudCredentials);
  storagemgmt = mgmtSTG.createStorageManagementClient(cloudCredentials);

  return {
    backup: exportToBlob,
    restore: importFromBlob,
    requestStatus: requestStatus,
    waitUntilRequestFinish: waitUntilRequestFinish,
    lastImportInBlobStorage: lastImportInBlobStorage,

    // mainly for tests
    deleteDatabase: deleteDatabase,
    deleteContainer: deleteContainer,
    deleteBlob: deleteBlob
  };
};

/**
 * Export database to a blob storage
 *
 * @param  {object}   db       { server, name, user, password }
 * @param  {object}   blob     { name, accountName, accountKey  }
 * @param  {function} callback callback
 *
 * @return {request}  The underlying request
 */
function exportToBlob (db, blob, callback) {

  debug('will backup ' + db.server + '/' + blob.container + '/' + db.name + ' to ' + blob.accountName + '/' + blob.name);

  function processRequest (error, primaryKey) {

    if (error) {
      debug(error);
      return callback(error);
    }

    if (! primaryKey) {
      debug('cannot process without accountKey');
      return callback(new Error('cannot access storage account'));
    }

    db.user   = db.user.match(/@/) ? db.user : db.user + '@' + db.server;
    db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
    blob.uri  = (blob.name.match(/^http/)) ? blob.name :
      'https://' + blob.accountName + '.blob.core.windows.net/' + blob.container + '/' +  blob.name;

    var parameters = {
      connectionInfo: {
        databaseName: db.name,
        password:     db.password,
        serverName:   db.server,
        userName:     db.user
      },
      blobCredentials: {
        storageAccessKey: primaryKey,
        uri: blob.uri
      }
    };

    ensureContainerExists(blob.accountName, primaryKey, blob.container, function (error) {
      if (error) return callback(error);
      return sqlmgmt.dac.exportMethod(db.server.split('.')[0], parameters, function(error, result) {

        if (error) {
          debug('backup queuing failed: ' + error);
          return callback(error);
        }

        debug(blob.uri + ' successfully queued. Guid=' + result.guid);
        callback(null, result.guid);
      });
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}

/**
 * Import database from a blob storage
 *
 * @param  {object}   db       { server, name, user, password }
 * @param  {object}   blob     { name, accountName, accountKey  }
 * @param  {function} callback callback
 *
 * @return {request}  The underlying request
 */
function importFromBlob (db, blob, callback) {

  debug('will restore ' + blob.accountName + '/' + blob.container + '/' + blob.name + ' to ' + db.server + '/' + db.name);

  assert(blob.name,        'You must provide blob.name');
  assert(blob.accountName, 'You must provide blob.accountName');

  assert(db.name,     'You must provide db.name');
  assert(db.password, 'You must provide db.password');
  assert(db.server,   'You must provide db.server');
  assert(db.user,     'You must provide db.user');

  function processRequest (error, primaryKey) {

    if (error) {
      debug(error);
      return callback(error);
    }

    if (! primaryKey) {
      debug('cannot process without accountKey');
      return callback(new Error('cannot access storage account'));
    }

    db.user   = db.user.match(/@/) ? db.user : db.user + '@' + db.server;
    db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
    blob.uri  = (blob.name.match(/^http/)) ? blob.name :
      'https://' + blob.accountName + '.blob.core.windows.net/' + blob.container + '/' +  blob.name;

    var parameters = {
      connectionInfo: {
        databaseName: db.name,
        password:     db.password,
        serverName:   db.server,
        userName:     db.user
      },
      azureEdition: db.edition  || 'Business',
      databaseSizeInGB: db.size || 10,
      blobCredentials: {
        storageAccessKey: primaryKey,
        uri: blob.uri
      }
    };

    return sqlmgmt.dac.importMethod(db.server.split('.')[0], parameters, function(error, result) {

      if (error) {
        debug('restore queuing failed: ' + error);
        return callback(error);
      }

      debug(db.name + ' successfully queued. Guid=' + result.guid);
      callback(null, result.guid);
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}

function requestStatus (db, guid, callback) {
  db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
  return sqlmgmt.dac.getStatus(db.server.split('.')[0], db.server, db.user, db.password, guid, function (error, result) {
    if (error || !result.statusInfoList) { return callback(error); }
    callback(error, result.statusInfoList[0]);
  });
}

function waitUntilRequestFinish (db, guid, callback, eachCallback) {
  function retry () {
    requestStatus (db, guid, function (error, req) {

      if (eachCallback) {eachCallback(error, req);}

      // error
      if (error) {
        debug('error: ' + error);
        return callback(error);
      }

      // finished !
      else if (! error && (!req.status || req.status.toLowerCase() === 'completed')) {
        debug('request ' + guid + ' finished');
        return callback(null);
      }

      // still running
      else {
        debug('still ' + req.status.toLowerCase() + (req.errorMessage ? ': ' + req.errorMessage : ''));
        setTimeout(retry, 10 * 1000);
      }
    });
  }
  retry();
}

function sortBlobs (a, b) {
  return a.properties['last-modified'] > b.properties['last-modified'] ? 1 : -1;
}

function blobAccountKey (accountName, callback) {

  storagemgmt.storageAccounts.getKeys(accountName, function (err, result) {

    if (err) {
      debug(err);
      return callback(err);
    }

    debug('ask for blob accountKey: ' + accountName + ': ' + result.primaryKey);

    callback(err, result.primaryKey);
  });
}

function lastImportInBlobStorage (account, key, container, callback) {
  var service = azure.createBlobService(account, key);
  service.listBlobsSegmented(container, null, function(error, result, response){
    if (error || !result.entries) { return callback(error); }
    result.entries.sort(sortBlobs);
    callback(null, result.entries.pop());
  });
}

function ensureContainerExists (account, key, container, callback) {
  var service = azure.createBlobService(account, key);
  service.createContainerIfNotExists(container, null, function(error, result, response){
    if (error) { return callback(error); }
    debug('%s container %s', container, result ? 'has been created' : 'already exists');
    callback(null);
  });
}

function deleteDatabase (db, callback) {
  db.server = db.server.match(/database.windows.net/) ? db.server : db.server + '.database.windows.net';
  sqlmgmt.databases.deleteMethod(db.server.split('.')[0], db.name, function (error, result) {
    if (error) {
      debug('cannot delete database %s: %s', db.name, error);
    } else {
      debug('successfully deleted database %s', db.name);
    }
    callback(error);
  });
}

function deleteBlob (blob, callback) {
  function processRequest (error, accountKey) {
    var service = azure.createBlobService(blob.accountName, accountKey);
    service.deleteBlob(blob.container, blob.name, function (error, result) {
      if (error) {
        debug('cannot delete blob %s/%s: %s', blob.container, blob.name, error);
      } else {
        debug('successfully deleted blob %s/%s', blob.container, blob.name);
      }
      callback(error);
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}

function deleteContainer (blob, callback) {
  function processRequest (error, accountKey) {
    var service = azure.createBlobService(blob.accountName, accountKey);
    service.deleteContainer(blob.container, function (error, result) {
      if (error) {
        debug('cannot delete container %s: %s', blob.container, error);
      } else {
        debug('successfully deleted container %s', blob.container);
      }
      callback(error);
    });
  }

  if (blob.accountKey) {
    processRequest(null, blob.accountKey);
  } else {
    blobAccountKey(blob.accountName, processRequest);
  }
}
<|endoftext|>


<commit_before>"use strict";
var window = require("global/window")
var isFunction = require("is-function")
var parseHeaders = require("parse-headers")
var xtend = require("xtend")

module.exports = createXHR
createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest

forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
    createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
        options = initParams(uri, options, callback)
        options.method = method.toUpperCase()
        return _createXHR(options)
    }
})

function forEachArray(array, iterator) {
    for (var i = 0; i < array.length; i++) {
        iterator(array[i])
    }
}

function isEmpty(obj){
    for(var i in obj){
        if(obj.hasOwnProperty(i)) return false
    }
    return true
}

function initParams(uri, options, callback) {
    var params = uri

    if (isFunction(options)) {
        callback = options
        if (typeof uri === "string") {
            params = {uri:uri}
        }
    } else {
        params = xtend(options, {uri: uri})
    }

    params.callback = callback
    return params
}

function createXHR(uri, options, callback) {
    options = initParams(uri, options, callback)
    return _createXHR(options)
}

function _createXHR(options) {
    if(typeof options.callback === "undefined"){
        throw new Error("callback argument missing")
    }

    var called = false
    var callback = function cbOnce(err, response, body){
        if(!called){
            called = true
            options.callback(err, response, body)
        }
    }

    function readystatechange() {
        if (xhr.readyState === 4) {
            loadFunc()
        }
    }

    function getBody() {
        // Chrome with requestType=blob throws errors arround when even testing access to responseText
        var body = undefined

        if (xhr.response) {
            body = xhr.response
        } else {
            body = xhr.responseText || getXml(xhr)
        }

        if (isJson) {
            try {
                body = JSON.parse(body)
            } catch (e) {}
        }

        return body
    }

    function errorFunc(evt) {
        clearTimeout(timeoutTimer)
        if(!(evt instanceof Error)){
            evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
        }
        evt.statusCode = 0
        return callback(evt, failureResponse)
    }

    // will load the data & process the response in a special response object
    function loadFunc() {
        if (aborted) return
        var status
        clearTimeout(timeoutTimer)
        if(options.useXDR && xhr.status===undefined) {
            //IE8 CORS GET successful response doesn't have a status field, but body is fine
            status = 200
        } else {
            status = (xhr.status === 1223 ? 204 : xhr.status)
        }
        var response = failureResponse
        var err = null

        if (status !== 0){
            response = {
                body: getBody(),
                statusCode: status,
                method: method,
                headers: {},
                url: uri,
                rawRequest: xhr
            }
            if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
                response.headers = parseHeaders(xhr.getAllResponseHeaders())
            }
        } else {
            err = new Error("Internal XMLHttpRequest Error")
        }
        return callback(err, response, response.body)
    }

    var xhr = options.xhr || null

    if (!xhr) {
        if (options.cors || options.useXDR) {
            xhr = new createXHR.XDomainRequest()
        }else{
            xhr = new createXHR.XMLHttpRequest()
        }
    }

    var key
    var aborted
    var uri = xhr.url = options.uri || options.url
    var method = xhr.method = options.method || "GET"
    var body = options.body || options.data
    var headers = xhr.headers = options.headers || {}
    var sync = !!options.sync
    var isJson = false
    var timeoutTimer
    var failureResponse = {
        body: undefined,
        headers: {},
        statusCode: 0,
        method: method,
        url: uri,
        rawRequest: xhr
    }

    if ("json" in options && options.json !== false) {
        isJson = true
        headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
        if (method !== "GET" && method !== "HEAD") {
            headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
            body = JSON.stringify(options.json === true ? body : options.json)
        }
    }

    xhr.onreadystatechange = readystatechange
    xhr.onload = loadFunc
    xhr.onerror = errorFunc
    // IE9 must have onprogress be set to a unique function.
    xhr.onprogress = function () {
        // IE must die
    }
    xhr.onabort = function(){
        aborted = true;
    }
    xhr.ontimeout = errorFunc
    xhr.open(method, uri, !sync, options.username, options.password)
    //has to be after open
    if(!sync) {
        xhr.withCredentials = !!options.withCredentials
    }
    // Cannot set timeout with sync request
    // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
    // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
    if (!sync && options.timeout > 0 ) {
        timeoutTimer = setTimeout(function(){
            if (aborted) return
            aborted = true//IE9 may still call readystatechange
            xhr.abort("timeout")
            var e = new Error("XMLHttpRequest timeout")
            e.code = "ETIMEDOUT"
            errorFunc(e)
        }, options.timeout )
    }

    if (xhr.setRequestHeader) {
        for(key in headers){
            if(headers.hasOwnProperty(key)){
                xhr.setRequestHeader(key, headers[key])
            }
        }
    } else if (options.headers && !isEmpty(options.headers)) {
        throw new Error("Headers cannot be set on an XDomainRequest object")
    }

    if ("responseType" in options) {
        xhr.responseType = options.responseType
    }

    if ("beforeSend" in options &&
        typeof options.beforeSend === "function"
    ) {
        options.beforeSend(xhr)
    }

    xhr.send(body)

    return xhr

}

function getXml(xhr) {
    if (xhr.responseType === "document") {
        return xhr.responseXML
    }
    var firefoxBugTakenEffect = xhr.status === 204 && xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
    if (xhr.responseType === "" && !firefoxBugTakenEffect) {
        return xhr.responseXML
    }

    return null
}

function noop() {}
<commit_msg>(re)set body to null if undefined<commit_after>"use strict";
var window = require("global/window")
var isFunction = require("is-function")
var parseHeaders = require("parse-headers")
var xtend = require("xtend")

module.exports = createXHR
createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest

forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
    createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
        options = initParams(uri, options, callback)
        options.method = method.toUpperCase()
        return _createXHR(options)
    }
})

function forEachArray(array, iterator) {
    for (var i = 0; i < array.length; i++) {
        iterator(array[i])
    }
}

function isEmpty(obj){
    for(var i in obj){
        if(obj.hasOwnProperty(i)) return false
    }
    return true
}

function initParams(uri, options, callback) {
    var params = uri

    if (isFunction(options)) {
        callback = options
        if (typeof uri === "string") {
            params = {uri:uri}
        }
    } else {
        params = xtend(options, {uri: uri})
    }

    params.callback = callback
    return params
}

function createXHR(uri, options, callback) {
    options = initParams(uri, options, callback)
    return _createXHR(options)
}

function _createXHR(options) {
    if(typeof options.callback === "undefined"){
        throw new Error("callback argument missing")
    }

    var called = false
    var callback = function cbOnce(err, response, body){
        if(!called){
            called = true
            options.callback(err, response, body)
        }
    }

    function readystatechange() {
        if (xhr.readyState === 4) {
            loadFunc()
        }
    }

    function getBody() {
        // Chrome with requestType=blob throws errors arround when even testing access to responseText
        var body = undefined

        if (xhr.response) {
            body = xhr.response
        } else {
            body = xhr.responseText || getXml(xhr)
        }

        if (isJson) {
            try {
                body = JSON.parse(body)
            } catch (e) {}
        }

        return body
    }

    function errorFunc(evt) {
        clearTimeout(timeoutTimer)
        if(!(evt instanceof Error)){
            evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
        }
        evt.statusCode = 0
        return callback(evt, failureResponse)
    }

    // will load the data & process the response in a special response object
    function loadFunc() {
        if (aborted) return
        var status
        clearTimeout(timeoutTimer)
        if(options.useXDR && xhr.status===undefined) {
            //IE8 CORS GET successful response doesn't have a status field, but body is fine
            status = 200
        } else {
            status = (xhr.status === 1223 ? 204 : xhr.status)
        }
        var response = failureResponse
        var err = null

        if (status !== 0){
            response = {
                body: getBody(),
                statusCode: status,
                method: method,
                headers: {},
                url: uri,
                rawRequest: xhr
            }
            if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
                response.headers = parseHeaders(xhr.getAllResponseHeaders())
            }
        } else {
            err = new Error("Internal XMLHttpRequest Error")
        }
        return callback(err, response, response.body)
    }

    var xhr = options.xhr || null

    if (!xhr) {
        if (options.cors || options.useXDR) {
            xhr = new createXHR.XDomainRequest()
        }else{
            xhr = new createXHR.XMLHttpRequest()
        }
    }

    var key
    var aborted
    var uri = xhr.url = options.uri || options.url
    var method = xhr.method = options.method || "GET"
    var body = options.body || options.data
    var headers = xhr.headers = options.headers || {}
    var sync = !!options.sync
    var isJson = false
    var timeoutTimer
    var failureResponse = {
        body: undefined,
        headers: {},
        statusCode: 0,
        method: method,
        url: uri,
        rawRequest: xhr
    }

    if ("json" in options && options.json !== false) {
        isJson = true
        headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
        if (method !== "GET" && method !== "HEAD") {
            headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
            body = JSON.stringify(options.json === true ? body : options.json)
        }
    }

    xhr.onreadystatechange = readystatechange
    xhr.onload = loadFunc
    xhr.onerror = errorFunc
    // IE9 must have onprogress be set to a unique function.
    xhr.onprogress = function () {
        // IE must die
    }
    xhr.onabort = function(){
        aborted = true;
    }
    xhr.ontimeout = errorFunc
    xhr.open(method, uri, !sync, options.username, options.password)
    //has to be after open
    if(!sync) {
        xhr.withCredentials = !!options.withCredentials
    }
    // Cannot set timeout with sync request
    // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
    // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
    if (!sync && options.timeout > 0 ) {
        timeoutTimer = setTimeout(function(){
            if (aborted) return
            aborted = true//IE9 may still call readystatechange
            xhr.abort("timeout")
            var e = new Error("XMLHttpRequest timeout")
            e.code = "ETIMEDOUT"
            errorFunc(e)
        }, options.timeout )
    }

    if (xhr.setRequestHeader) {
        for(key in headers){
            if(headers.hasOwnProperty(key)){
                xhr.setRequestHeader(key, headers[key])
            }
        }
    } else if (options.headers && !isEmpty(options.headers)) {
        throw new Error("Headers cannot be set on an XDomainRequest object")
    }

    if ("responseType" in options) {
        xhr.responseType = options.responseType
    }

    if ("beforeSend" in options &&
        typeof options.beforeSend === "function"
    ) {
        options.beforeSend(xhr)
    }

    // Microsoft Edge browsers may throw errors when calling xhr.send() with an undefined body, so we set the body to null if body is undefined.
    // See https://github.com/naugtur/xhr/issues/100.
    body = body || null;
    xhr.send(body)

    return xhr

}

function getXml(xhr) {
    if (xhr.responseType === "document") {
        return xhr.responseXML
    }
    var firefoxBugTakenEffect = xhr.status === 204 && xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
    if (xhr.responseType === "" && !firefoxBugTakenEffect) {
        return xhr.responseXML
    }

    return null
}

function noop() {}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var http = require('http'),
	request = require('request'),
	fs = require('fs'),
	domain = require('domain'),
	index = require('zlib').gzipSync(fs.readFileSync('index.html'))
	favicon = require('zlib').gzipSync(fs.readFileSync('favicon.ico'))
	port = process.env.PORT || 8080,
	allowedOriginalHeaders = new RegExp('^' + require('./allowedOriginalHeaders.json').join('|'), 'i')
	bannedUrls = new RegExp(require('./bannedUrls.json').join('|'), 'i')

var server = http.createServer(function (req, res) {
	var d = domain.create();
	d.on('error', function (e){
		console.log('ERROR', e.stack);

		res.statusCode = 500;
		res.end('Error: ' + ((e instanceof TypeError) ? "make sure your URL is correct" : String(e)));
	});

	d.add(req);
	d.add(res);

	d.run(function() {
		handler(req, res);
	});
}).listen(port);

function handler(req, res) {
	switch (req.url) {
		case "/":
		case "/index.html" :
			res.setHeader('content-encoding', 'gzip')
			res.setHeader('content-type', 'text/html')
			res.writeHead(200);
			res.write(index);
			res.end();
		case "/favicon.ico":
			res.setHeader('content-encoding', 'gzip')
			res.setHeader('content-type', 'image/x-icon')
			res.writeHead(200);
			res.write(favicon);
			res.end();
		case "/favicon.ico":
			break;
		default:
			if (bannedUrls.test(req.url)) {
				res.writeHead(403);
				res.end('FORBIDDEN');
			} else {
			try {
				res.setTimeout(25000);
				res.setHeader('Access-Control-Allow-Origin', '*');
				res.setHeader('Access-Control-Allow-Credentials', false);
				res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
				res.setHeader('Expires', new Date(Date.now() + 86400000).toUTCString()); // one day in the future
				var r = request(req.url.slice(1), {encoding: null, rejectUnauthorized: false});
				r.pipefilter = function(response, dest) {
					for (var header in response.headers) {
						if (!allowedOriginalHeaders.test(header)) {
							dest.removeHeader(header);
						}
					}
				};
				r.pipe(res);
			} catch (e) {
				res.end('Error: ' +  ((e instanceof TypeError) ? "make sure your URL is correct" : String(e)));
			}
		}
	}
}
<commit_msg> - Fixed missing break in index switch case (casing switch leakage, and header duplication attempts)  - Added the PNG icon, Chrome and Firefox seemed to be calling it, which was throwing errors to the log  - Brought the request options out into the global scope (save node recreating it every time `handler` is called)<commit_after>#!/usr/bin/env node
var http = require('http'),
	request = require('request'),
	fs = require('fs'),
	domain = require('domain'),
	index = require('zlib').gzipSync(fs.readFileSync('index.html'))
	favicon = require('zlib').gzipSync(fs.readFileSync('favicon.ico'))
	faviconPNG = require('zlib').gzipSync(fs.readFileSync('favicon.png'))
	port = process.env.PORT || 8080,
	allowedOriginalHeaders = new RegExp('^' + require('./allowedOriginalHeaders.json').join('|'), 'i')
	bannedUrls = new RegExp(require('./bannedUrls.json').join('|'), 'i'),
	requestOptions = {
		encoding: null,
		rejectUnauthorized: false,
		headers: {
			'accept-encoding': 'identity'
		}
	},
	server = http.createServer(function (req, res) {
		var d = domain.create();
		d.on('error', function (e){
			console.log('ERROR', e.stack);

			res.statusCode = 500;
			res.end('Error: ' + ((e instanceof TypeError) ? "make sure your URL is correct" : String(e)));
		});

		d.add(req);
		d.add(res);

		d.run(function() {
			handler(req, res);
		});
	}).listen(port),
	handler = function handler(req, res) {
		switch (req.url) {
			case "/":
			case "/index.html" :
				res.setHeader('content-type', 'text/html')
				res.setHeader('content-encoding', 'gzip')
				res.writeHead(200);
				res.write(index);
				res.end();
				break;
			case "/favicon.ico":
				res.setHeader('content-encoding', 'gzip')
				res.setHeader('content-type', 'image/x-icon')
				res.writeHead(200);
				res.write(favicon);
				res.end();
				break;
			case "/favicon.png":
				res.setHeader('content-encoding', 'gzip')
				res.setHeader('content-type', 'image/png')
				res.writeHead(200);
				res.write(faviconPNG);
				res.end();
				break;
			default:
				if (bannedUrls.test(req.url)) {
					res.writeHead(403);
					res.end('FORBIDDEN');
				} else {
				try {
					res.setTimeout(25000);
					res.setHeader('Access-Control-Allow-Origin', '*');
					res.setHeader('Access-Control-Allow-Credentials', false);
					res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
					res.setHeader('Expires', new Date(Date.now() + 86400000).toUTCString()); // one day in the future
					var r = request(req.url.slice(1), requestOptions);
					r.pipefilter = function(response, dest) {
						for (var header in response.headers) {
							if (!allowedOriginalHeaders.test(header)) {
								dest.removeHeader(header);
							}
						}
					};
					r.pipe(res);
				} catch (e) {
					res.end('Error: ' +  ((e instanceof TypeError) ? "make sure your URL is correct" : String(e)));
				}
			}
		}
	}
<|endoftext|>


<commit_before>/**
 * @module jupyter-paths
 *
 * @description Module `jupyter-paths` provides path helpers ported from github.com/jupyter/jupyter_core
 */

var path = require('path');
var child_process = require('child_process');

function JupyterPaths() {
  var pathsResponse;

  try {
    pathsResponse = child_process.spawnSync('jupyter',  ['--paths', '--json']);
    _path = JSON.parse(pathsResponse.stdout.toString());
  } catch(e) {
    console.error(e);
    console.error(pathsResponse.stdout.toString());
    console.error(pathsResponse.stderr.toString());
    return;
  }

  this.paths = _path;

  var dataDir = this.paths.data;

  this.paths.kernelspecs = dataDir.map(function(p){
    return path.join(p, "kernels");
  });

}

module.exports = new JupyterPaths();
<commit_msg>Fix comment.<commit_after>/**
 * @module jupyter-paths
 *
 * @description Module `jupyter-paths` provides path helpers from github.com/jupyter/jupyter_core
 */

var path = require('path');
var child_process = require('child_process');

function JupyterPaths() {
  var pathsResponse;

  try {
    pathsResponse = child_process.spawnSync('jupyter',  ['--paths', '--json']);
    _path = JSON.parse(pathsResponse.stdout.toString());
  } catch(e) {
    console.error(e);
    console.error(pathsResponse.stdout.toString());
    console.error(pathsResponse.stderr.toString());
    return;
  }

  this.paths = _path;

  var dataDir = this.paths.data;

  this.paths.kernelspecs = dataDir.map(function(p){
    return path.join(p, "kernels");
  });

}

module.exports = new JupyterPaths();
<|endoftext|>


<commit_before>'use strict';

/**
 * Export all data from an IndexedDB database
 * @param {IDBDatabase} idbDatabase - to export from
 * @param {function(Object?, string?)} cb - callback with signature (error, jsonString)
 */
function exportToJsonString(idbDatabase, cb) {
  const exportObject = {};
  const objectStoreNamesSet = new Set(idbDatabase.objectStoreNames);
  const size = objectStoreNamesSet.size;
  if (size === 0) {
    cb(null, JSON.stringify(exportObject));
  } else {
    const objectStoreNames = Array.from(objectStoreNamesSet);
    const transaction = idbDatabase.transaction(
        objectStoreNames,
        'readonly'
    );
    transaction.onerror = (event) => cb(event, null);

    objectStoreNames.forEach((storeName) => {
      const allObjects = [];
      transaction.objectStore(storeName).openCursor().onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
          allObjects.push(cursor.value);
          cursor.continue();
        } else {
          exportObject[storeName] = allObjects;
          if (
            objectStoreNames.length ===
            Object.keys(exportObject).length
          ) {
            cb(null, JSON.stringify(exportObject));
          }
        }
      };
    });
  }
}

/**
 * Import data from JSON into an IndexedDB database. This does not delete any existing data
 *  from the database, so keys could clash.
 *
 * Only object stores that already exist will be imported.
 *
 * @param {IDBDatabase} idbDatabase - to import into
 * @param {string} jsonString - data to import, one key per object store
 * @param {function(Object)} cb - callback with signature (error), where error is null on success
 * @return {void}
 */
function importFromJsonString(idbDatabase, jsonString, cb) {
  const objectStoreNamesSet = new Set(idbDatabase.objectStoreNames);
  const size = objectStoreNamesSet.size;
  if (size === 0) {
    cb(null);
  } else {
    const objectStoreNames = Array.from(objectStoreNamesSet);
    const transaction = idbDatabase.transaction(
        objectStoreNames,
        'readwrite'
    );
    transaction.onerror = (event) => cb(event);

    const importObject = JSON.parse(jsonString);

    // Delete keys present in JSON that are not present in database
    Object.keys(importObject).forEach((storeName)=> {
      if (!objectStoreNames.includes(storeName)) {
        delete importObject[storeName];
      }
    });

    if (Object.keys(importObject).length === 0) {
      // no object stores exist to import for
      cb(null);
    }

    objectStoreNames.forEach((storeName) => {
      let count = 0;
      const aux = Array.from(importObject[storeName]);
      if (importObject[storeName] && aux.length > 0) {
        aux.forEach((toAdd) => {
          const request = transaction.objectStore(storeName).add(toAdd);
          request.onsuccess = () => {
            count++;
            if (count === importObject[storeName].length) {
              // added all objects for this store
              delete importObject[storeName];
              if (Object.keys(importObject).length === 0) {
                // added all object stores
                cb(null);
              }
            }
          };
          request.onerror = (event) => {
            console.log(event);
          };
        });
      } else {
        delete importObject[storeName];
        if (Object.keys(importObject).length === 0) {
          // added all object stores
          cb(null);
        }
      }
    });
  }
}

/**
 * Clears a database of all data.
 *
 * The object stores will still exist but will be empty.
 *
 * @param {IDBDatabase} idbDatabase - to delete all data from
 * @param {function(Object)} cb - callback with signature (error), where error is null on success
 * @return {void}
 */
function clearDatabase(idbDatabase, cb) {
  const objectStoreNamesSet = new Set(idbDatabase.objectStoreNames);
  const size = objectStoreNamesSet.size;
  if (size === 0) {
    cb(null);
  } else {
    const objectStoreNames = Array.from(objectStoreNamesSet);
    const transaction = idbDatabase.transaction(
        objectStoreNames,
        'readwrite'
    );
    transaction.onerror = (event) => cb(event);

    let count = 0;
    objectStoreNames.forEach(function(storeName) {
      transaction.objectStore(storeName).clear().onsuccess = () => {
        count++;
        if (count === size) {
          // cleared all object stores
          cb(null);
        }
      };
    });
  }
}

if (typeof module !== 'undefined' && module.exports) {
  // We are running on Node.js so need to export the module
  module.exports = {
    exportToJsonString: exportToJsonString,
    importFromJsonString: importFromJsonString,
    clearDatabase: clearDatabase,
  };
}
<commit_msg>Update index.js<commit_after>'use strict';

/**
 * Export all data from an IndexedDB database
 * @param {IDBDatabase} idbDatabase - to export from
 * @param {function(Object?, string?)} cb - callback with signature (error, jsonString)
 */
function exportToJsonString(idbDatabase, cb) {
  const exportObject = {};
  const objectStoreNamesSet = new Set(idbDatabase.objectStoreNames);
  const size = objectStoreNamesSet.size;
  if (size === 0) {
    cb(null, JSON.stringify(exportObject));
  } else {
    const objectStoreNames = Array.from(objectStoreNamesSet);
    const transaction = idbDatabase.transaction(
        objectStoreNames,
        'readonly'
    );
    transaction.onerror = (event) => cb(event, null);

    objectStoreNames.forEach((storeName) => {
      const allObjects = [];
      transaction.objectStore(storeName).openCursor().onsuccess = (event) => {
        const cursor = event.target.result;
        if (cursor) {
          allObjects.push(cursor.value);
          cursor.continue();
        } else {
          exportObject[storeName] = allObjects;
          if (
            objectStoreNames.length ===
            Object.keys(exportObject).length
          ) {
            cb(null, JSON.stringify(exportObject));
          }
        }
      };
    });
  }
}

/**
 * Import data from JSON into an IndexedDB database. This does not delete any existing data
 *  from the database, so keys could clash.
 *
 * Only object stores that already exist will be imported.
 *
 * @param {IDBDatabase} idbDatabase - to import into
 * @param {string} jsonString - data to import, one key per object store
 * @param {function(Object)} cb - callback with signature (error), where error is null on success
 * @return {void}
 */
function importFromJsonString(idbDatabase, jsonString, cb) {
  const objectStoreNamesSet = new Set(idbDatabase.objectStoreNames);
  const size = objectStoreNamesSet.size;
  if (size === 0) {
    cb(null);
  } else {
    const objectStoreNames = Array.from(objectStoreNamesSet);
    const transaction = idbDatabase.transaction(
        objectStoreNames,
        'readwrite'
    );
    transaction.onerror = (event) => cb(event);

    const importObject = JSON.parse(jsonString);

    // Delete keys present in JSON that are not present in database
    Object.keys(importObject).forEach((storeName)=> {
      if (!objectStoreNames.includes(storeName)) {
        delete importObject[storeName];
      }
    });

    if (Object.keys(importObject).length === 0) {
      // no object stores exist to import for
      cb(null);
    }

    objectStoreNames.forEach((storeName) => {
      let count = 0;

      // setting aux to an empty array if the key doesn't exists in the import object.
      const data_to_import = importObject[storeName] || []
      const aux = Array.from(data_to_import) ;

      if (importObject[storeName] && aux.length > 0) {
        aux.forEach((toAdd) => {
          const request = transaction.objectStore(storeName).add(toAdd);
          request.onsuccess = () => {
            count++;
            if (count === importObject[storeName].length) {
              // added all objects for this store
              delete importObject[storeName];
              if (Object.keys(importObject).length === 0) {
                // added all object stores
                cb(null);
              }
            }
          };
          request.onerror = (event) => {
            console.log(event);
          };
        });
      } else {
        delete importObject[storeName];
        if (Object.keys(importObject).length === 0) {
          // added all object stores
          cb(null);
        }
      }
    });
  }
}

/**
 * Clears a database of all data.
 *
 * The object stores will still exist but will be empty.
 *
 * @param {IDBDatabase} idbDatabase - to delete all data from
 * @param {function(Object)} cb - callback with signature (error), where error is null on success
 * @return {void}
 */
function clearDatabase(idbDatabase, cb) {
  const objectStoreNamesSet = new Set(idbDatabase.objectStoreNames);
  const size = objectStoreNamesSet.size;
  if (size === 0) {
    cb(null);
  } else {
    const objectStoreNames = Array.from(objectStoreNamesSet);
    const transaction = idbDatabase.transaction(
        objectStoreNames,
        'readwrite'
    );
    transaction.onerror = (event) => cb(event);

    let count = 0;
    objectStoreNames.forEach(function(storeName) {
      transaction.objectStore(storeName).clear().onsuccess = () => {
        count++;
        if (count === size) {
          // cleared all object stores
          cb(null);
        }
      };
    });
  }
}

if (typeof module !== 'undefined' && module.exports) {
  // We are running on Node.js so need to export the module
  module.exports = {
    exportToJsonString: exportToJsonString,
    importFromJsonString: importFromJsonString,
    clearDatabase: clearDatabase,
  };
}
<|endoftext|>


<commit_before>/**
 * Create a Player service
 *
 * This holds all of the calls for the player interface and data
 **/

angular.module('spotmop.services.player', [])

.factory("PlayerService", ['$rootScope', '$interval', '$filter', 'SettingsService', 'MopidyService', 'SpotifyService', 'EchonestService', 'NotifyService', 'LastfmService', function( $rootScope, $interval, $filter, SettingsService, MopidyService, SpotifyService, EchonestService, NotifyService, LastfmService ){

	// setup initial states
	var state = {
		playing: false,
		isRepeat: false,
		isRandom: false,
		isMute: false,
		volume: 100,
		playPosition: 0,
		currentTlTrack: false,
		playPositionPercent: function(){
			if( state.currentTlTrack ){
				return ( state.playPosition / state.currentTlTrack.track.length * 100 ).toFixed(2);
			}else{
				return 0;
			}
		}
	}

	// when mopidy connection detected, fetch real states
	$rootScope.$on('mopidy:state:online', function(){
		updateToggles();

		updateCurrentTrack();
		updatePlayerState();
		updateVolume();

		// figure out if we're playing already
		MopidyService.getState().then( function( newState ){
			if( newState == 'playing' )
				state.playing = true;
			else
				state.playing = false;
		});
	});

	// listen for changes from other clients
	$rootScope.$on('mopidy:event:optionsChanged', function(event, options){
		updateToggles();
	});

	$rootScope.$on('mopidy:event:playbackStateChanged', function( event, state ){
		updatePlayerState( state.new_state );
	});

	$rootScope.$on('mopidy:event:seeked', function( event, position ){
		updatePlayPosition( position.time_position );
	});

	$rootScope.$on('mopidy:event:volumeChanged', function( event, volume ){
		if( volume.volume != state.volume )
			updateVolume( volume.volume );
	});

	// update our toggle states from the mopidy server
	function updateToggles(){
        MopidyService.getRepeat().then( function(isRepeat){
            state.isRepeat = isRepeat;
        });
        MopidyService.getRandom().then( function(isRandom){
            state.isRandom = isRandom;
        });
        MopidyService.getMute().then( function(isMute){
            state.isMute = isMute;
        });
	}

	// listen for current track changes
	// TODO: Move this into the MopidyService for sanity
	$rootScope.$on('mopidy:event:trackPlaybackStarted', function( event, tlTrack ){

		// only if our new tlTrack differs from our current one
		if( state.currentTlTrack.track.uri != tlTrack.tl_track.track.uri ){
			state.currentTlTrack = tlTrack.tl_track;
			updateCurrentTrack( tlTrack.tl_track );
			updatePlayerState();
		}
	});

	/**
	 * Set the new play position and, if required, figure it out first
	 * @param newPosition = integer (optional)
	 **/
	function updatePlayPosition( newPosition ){

		// if we haven't been provided with a specific new position
		if( typeof( newPosition ) === 'undefined' ){

			// go get the time position
			MopidyService.getTimePosition().then( function(position){
				state.playPosition = position;
			});

		// we've been parsed the time position, so just use that
		}else{
			state.playPosition = newPosition;
		}
	}

	/**
	 * Update volume
	 * Fetches (if required) the volume from mopidy and sets to state
	 * @param volume = int (optional)
	 **/
	function updateVolume( newVolume ){

		// if we've been told what the new volume is, let's just use that
		if( typeof( newVolume ) !== 'undefined' ){
			state.volume = newVolume;

		// not told what new vol is, so let's fetch and set
		}else{
			MopidyService.getVolume().then(function( volume ){
				state.volume = volume;
			});
		}
	}

	/**
	 * Update the state of the player
	 * @param newState = string (optional)
	 **/
	function updatePlayerState( newState ){

		// if we've been told what the new state is, let's just use that
		if( typeof( newState ) !== 'undefined' ){
			if( newState == 'playing' )
				state.playing = true;
			else
				state.playing = false;

			updateWindowTitle();

		// not sure of new state, so let's find out first
		}else{
			MopidyService.getState().then( function( newState ){
				if( newState == 'playing' )
					state.playing = true;
				else
					state.playing = false;

				updateWindowTitle();
			});
		}

		// commented out due to strange behavior in Mopidy 1.1.1 where on pause, the play position was erratic
		// so let's just rely on our latest play position as factual. When we resume it'll re-fetch anyway.
		// updatePlayPosition();
	};

	/**
	 * Update the current track
	 * This updates all instances of the track with new artwork, seek bar, window title, etc.
	 * @param tlTrack = the new track object (optional)
	 **/
	function updateCurrentTrack( tlTrack ){

		// update all ui uses of the track (window title, player bar, etc)
		var setCurrentTrack = function( tlTrack ){

			// save the current tltrack for global usage
			state.currentTlTrack = tlTrack;

			// if this is a Spotify track, get the track image from Spotify
			if( tlTrack.track.uri.substring(0,8) == 'spotify:' ){
				// now we have track info, let's get the spotify artwork
				SpotifyService.getTrack( tlTrack.track.uri )
					.then(function( response ){
						if( typeof(response.album) !== 'undefined' )
							//state.currentTlTrack.track.album.images = response.album.images;
							state.currentTlTrack.track.image = response.album.images[0].url;
					});

			// not a Spotify track (ie Mopidy-Local), so let's use LastFM to get some artwork
			}else{

				var artist = encodeURIComponent( tlTrack.track.artists[0].name );
				var album = encodeURIComponent( tlTrack.track.album.name );

				if( artist && album )
					LastfmService.albumInfo( artist, album )
						.then( function(response){

								// remove the existing image
								state.currentTlTrack.track.image = false;

								// if we got an album match, plug in the 'extralarge' image to our state()
								if( typeof(response.album) !== 'undefined' ){
									var largest = $filter('filter')(response.album.image, { size: 'extralarge' })[0];
									if( largest )
										state.currentTlTrack.track.image = largest['#text'];
								}
							});
			}

			// update ui
			updatePlayPosition();
			updateWindowTitle();
		}

		// track provided, update pronto garcong!
		if( typeof( tlTrack ) !== 'undefined' ){
			setCurrentTrack( tlTrack );

		// no track provided, so go fetch it first, then proceed
		}else{

			MopidyService.getCurrentTlTrack().then( function( tlTrack ){
				if(tlTrack !== null && tlTrack !== undefined){
					if(tlTrack.track.name.indexOf("[loading]") > -1){
						MopidyService.lookup(tlTrack.track.uri).then(function(result){
							setCurrentTrack(result[0]);
						});
					}else{
						setCurrentTrack(tlTrack);
					}
				}
			});
		}
	};

	/**
	 * Update browser title
	 **/
	function updateWindowTitle(){

		var track = state.currentTlTrack.track;
        var newTitle = 'No track playing';

        if( track ){
            var documentIcon = '\u25A0 ';
            var artistString = '';

            $.each(track.artists, function(key,value){
                if( artistString != '' )
                    artistString += ', ';
                artistString += value.name;
            });

            if( state.playing )
                documentIcon = '\u25B6 ';

            newTitle = documentIcon +' '+ track.name +' - '+ artistString;
        };

		document.title = newTitle;
	}

	/**
	 * Update play progress position slider
	 **/
	$interval(
		function(){
			if( state.playing ){
				state.playPosition += 1000;
			}
		},
		1000
	);

	/**
	 * Shortcut keys
	 **/
	$rootScope.$on('spotmop:keyboardShortcut:space', function( event ){
		if( state.playing ) var icon = 'pause'; else var icon = 'play';
		service.playPause();
		NotifyService.shortcut( icon );
    });
	$rootScope.$on('spotmop:keyboardShortcut:right', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			service.next();
			NotifyService.shortcut( 'forward' );
		}
    });
	$rootScope.$on('spotmop:keyboardShortcut:left', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			service.previous();
			NotifyService.shortcut( 'backward' );
		}
    });
	$rootScope.$on('spotmop:keyboardShortcut:up', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			state.volume += 10;

			// don't let the volume exceed maximum possible, 100%
			if( state.volume >= 100 )
				state.volume = 100;
			service.setVolume( state.volume );
			NotifyService.shortcut( 'volume-up' );
		}
    });
	$rootScope.$on('spotmop:keyboardShortcut:down', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			state.volume -= 10;

			// don't let the volume below minimum possible, 0%
			if( state.volume < 0 )
				state.volume = 0;
			service.setVolume( state.volume );
			NotifyService.shortcut( 'volume-down' );
		}
    });

	/**
	 * Setup response object
	 * This is the object that is available to all controllers
	 **/
	var service = {

		state: function(){
			return state;
		},

		playPause: function(){
			if( state.playing ){
				MopidyService.pause();
				state.playing = false;
			}else{
				MopidyService.play();
				state.playing = true;
			}
		},

		stop: function(){
			MopidyService.stopPlayback();
			state.playing = false;
		},

		next: function(){

			// log this skip (we do this BEFORE moving to the next, as the skip is on the OLD track)
			if( SettingsService.getSetting('echonestenabled',false) )
				EchonestService.addToTasteProfile( 'skip', state.currentTlTrack.track.uri );

			MopidyService.play();
			MopidyService.next();
		},

		previous: function(){
			MopidyService.previous();
		},

		seek: function( time ){
			state.playPosition = time;
			MopidyService.seek( time );
		},

		setVolume: function( percent ){
			state.volume = percent;
			MopidyService.setVolume( percent );
		},

		/**
		 * Playback behavior toggles
		 **/
		toggleRepeat: function(){
			if( state.isRepeat )
				MopidyService.setRepeat( false ).then( function(response){ state.isRepeat = false; } );
			else
				MopidyService.setRepeat( true ).then( function(response){ state.isRepeat = true; } );
			console.log( state );
		},
		toggleRandom: function(){
			if( state.isRandom )
				MopidyService.setRandom( false ).then( function(response){ state.isRandom = false; } );
			else
				MopidyService.setRandom( true ).then( function(response){ state.isRandom = true; } );
		},
		toggleMute: function(){
			if( state.isMute )
				MopidyService.setMute( false ).then( function(response){ state.isMute = false; } );
			else
				MopidyService.setMute( true ).then( function(response){ state.isMute = true; } );
		}

	};

	return service;

}]);

<commit_msg>No track<commit_after>/**
 * Create a Player service
 *
 * This holds all of the calls for the player interface and data
 **/

angular.module('spotmop.services.player', [])

.factory("PlayerService", ['$rootScope', '$interval', '$filter', 'SettingsService', 'MopidyService', 'SpotifyService', 'EchonestService', 'NotifyService', 'LastfmService', function( $rootScope, $interval, $filter, SettingsService, MopidyService, SpotifyService, EchonestService, NotifyService, LastfmService ){

	// setup initial states
	var state = {
		playing: false,
		isRepeat: false,
		isRandom: false,
		isMute: false,
		volume: 100,
		playPosition: 0,
		currentTlTrack: false,
		playPositionPercent: function(){
			if( state.currentTlTrack ){
				return ( state.playPosition / state.currentTlTrack.track.length * 100 ).toFixed(2);
			}else{
				return 0;
			}
		}
	}

	// when mopidy connection detected, fetch real states
	$rootScope.$on('mopidy:state:online', function(){
		updateToggles();

		updateCurrentTrack();
		updatePlayerState();
		updateVolume();

		// figure out if we're playing already
		MopidyService.getState().then( function( newState ){
			if( newState == 'playing' )
				state.playing = true;
			else
				state.playing = false;
		});
	});

	// listen for changes from other clients
	$rootScope.$on('mopidy:event:optionsChanged', function(event, options){
		updateToggles();
	});

	$rootScope.$on('mopidy:event:playbackStateChanged', function( event, state ){
		updatePlayerState( state.new_state );
	});

	$rootScope.$on('mopidy:event:seeked', function( event, position ){
		updatePlayPosition( position.time_position );
	});

	$rootScope.$on('mopidy:event:volumeChanged', function( event, volume ){
		if( volume.volume != state.volume )
			updateVolume( volume.volume );
	});

	// update our toggle states from the mopidy server
	function updateToggles(){
        MopidyService.getRepeat().then( function(isRepeat){
            state.isRepeat = isRepeat;
        });
        MopidyService.getRandom().then( function(isRandom){
            state.isRandom = isRandom;
        });
        MopidyService.getMute().then( function(isMute){
            state.isMute = isMute;
        });
	}

	// listen for current track changes
	// TODO: Move this into the MopidyService for sanity
	$rootScope.$on('mopidy:event:trackPlaybackStarted', function( event, tlTrack ){

		// only if our new tlTrack differs from our current one
		if( typeof(state.currentTlTrack.track) === 'undefined' || state.currentTlTrack.track.uri != tlTrack.tl_track.track.uri ){
			state.currentTlTrack = tlTrack.tl_track;
			updateCurrentTrack( tlTrack.tl_track );
			updatePlayerState();
		}
	});

	/**
	 * Set the new play position and, if required, figure it out first
	 * @param newPosition = integer (optional)
	 **/
	function updatePlayPosition( newPosition ){

		// if we haven't been provided with a specific new position
		if( typeof( newPosition ) === 'undefined' ){

			// go get the time position
			MopidyService.getTimePosition().then( function(position){
				state.playPosition = position;
			});

		// we've been parsed the time position, so just use that
		}else{
			state.playPosition = newPosition;
		}
	}

	/**
	 * Update volume
	 * Fetches (if required) the volume from mopidy and sets to state
	 * @param volume = int (optional)
	 **/
	function updateVolume( newVolume ){

		// if we've been told what the new volume is, let's just use that
		if( typeof( newVolume ) !== 'undefined' ){
			state.volume = newVolume;

		// not told what new vol is, so let's fetch and set
		}else{
			MopidyService.getVolume().then(function( volume ){
				state.volume = volume;
			});
		}
	}

	/**
	 * Update the state of the player
	 * @param newState = string (optional)
	 **/
	function updatePlayerState( newState ){

		// if we've been told what the new state is, let's just use that
		if( typeof( newState ) !== 'undefined' ){
			if( newState == 'playing' )
				state.playing = true;
			else
				state.playing = false;

			updateWindowTitle();

		// not sure of new state, so let's find out first
		}else{
			MopidyService.getState().then( function( newState ){
				if( newState == 'playing' )
					state.playing = true;
				else
					state.playing = false;

				updateWindowTitle();
			});
		}

		// commented out due to strange behavior in Mopidy 1.1.1 where on pause, the play position was erratic
		// so let's just rely on our latest play position as factual. When we resume it'll re-fetch anyway.
		// updatePlayPosition();
	};

	/**
	 * Update the current track
	 * This updates all instances of the track with new artwork, seek bar, window title, etc.
	 * @param tlTrack = the new track object (optional)
	 **/
	function updateCurrentTrack( tlTrack ){

		// update all ui uses of the track (window title, player bar, etc)
		var setCurrentTrack = function( tlTrack ){

			// save the current tltrack for global usage
			state.currentTlTrack = tlTrack;

			// if this is a Spotify track, get the track image from Spotify
			if( tlTrack.track.uri.substring(0,8) == 'spotify:' ){
				// now we have track info, let's get the spotify artwork
				SpotifyService.getTrack( tlTrack.track.uri )
					.then(function( response ){
						if( typeof(response.album) !== 'undefined' )
							//state.currentTlTrack.track.album.images = response.album.images;
							state.currentTlTrack.track.image = response.album.images[0].url;
					});

			// not a Spotify track (ie Mopidy-Local), so let's use LastFM to get some artwork
			}else{

				var artist = encodeURIComponent( tlTrack.track.artists[0].name );
				var album = encodeURIComponent( tlTrack.track.album.name );

				if( artist && album )
					LastfmService.albumInfo( artist, album )
						.then( function(response){

								// remove the existing image
								state.currentTlTrack.track.image = false;

								// if we got an album match, plug in the 'extralarge' image to our state()
								if( typeof(response.album) !== 'undefined' ){
									var largest = $filter('filter')(response.album.image, { size: 'extralarge' })[0];
									if( largest )
										state.currentTlTrack.track.image = largest['#text'];
								}
							});
			}

			// update ui
			updatePlayPosition();
			updateWindowTitle();
		}

		// track provided, update pronto garcong!
		if( typeof( tlTrack ) !== 'undefined' ){
			setCurrentTrack( tlTrack );

		// no track provided, so go fetch it first, then proceed
		}else{

			MopidyService.getCurrentTlTrack().then( function( tlTrack ){
				if(tlTrack !== null && tlTrack !== undefined){
					if(tlTrack.track.name.indexOf("[loading]") > -1){
						MopidyService.lookup(tlTrack.track.uri).then(function(result){
							setCurrentTrack(result[0]);
						});
					}else{
						setCurrentTrack(tlTrack);
					}
				}
			});
		}
	};

	/**
	 * Update browser title
	 **/
	function updateWindowTitle(){

		var track = state.currentTlTrack.track;
        var newTitle = 'No track playing';

        if( track ){
            var documentIcon = '\u25A0 ';
            var artistString = '';

            $.each(track.artists, function(key,value){
                if( artistString != '' )
                    artistString += ', ';
                artistString += value.name;
            });

            if( state.playing )
                documentIcon = '\u25B6 ';

            newTitle = documentIcon +' '+ track.name +' - '+ artistString;
        };

		document.title = newTitle;
	}

	/**
	 * Update play progress position slider
	 **/
	$interval(
		function(){
			if( state.playing ){
				state.playPosition += 1000;
			}
		},
		1000
	);

	/**
	 * Shortcut keys
	 **/
	$rootScope.$on('spotmop:keyboardShortcut:space', function( event ){
		if( state.playing ) var icon = 'pause'; else var icon = 'play';
		service.playPause();
		NotifyService.shortcut( icon );
    });
	$rootScope.$on('spotmop:keyboardShortcut:right', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			service.next();
			NotifyService.shortcut( 'forward' );
		}
    });
	$rootScope.$on('spotmop:keyboardShortcut:left', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			service.previous();
			NotifyService.shortcut( 'backward' );
		}
    });
	$rootScope.$on('spotmop:keyboardShortcut:up', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			state.volume += 10;

			// don't let the volume exceed maximum possible, 100%
			if( state.volume >= 100 )
				state.volume = 100;
			service.setVolume( state.volume );
			NotifyService.shortcut( 'volume-up' );
		}
    });
	$rootScope.$on('spotmop:keyboardShortcut:down', function( event ){
		if( $rootScope.ctrlKeyHeld ){
			state.volume -= 10;

			// don't let the volume below minimum possible, 0%
			if( state.volume < 0 )
				state.volume = 0;
			service.setVolume( state.volume );
			NotifyService.shortcut( 'volume-down' );
		}
    });

	/**
	 * Setup response object
	 * This is the object that is available to all controllers
	 **/
	var service = {

		state: function(){
			return state;
		},

		playPause: function(){
			if( state.playing ){
				MopidyService.pause();
				state.playing = false;
			}else{
				MopidyService.play();
				state.playing = true;
			}
		},

		stop: function(){
			MopidyService.stopPlayback();
			state.playing = false;
		},

		next: function(){

			// log this skip (we do this BEFORE moving to the next, as the skip is on the OLD track)
			if( SettingsService.getSetting('echonestenabled',false) )
				EchonestService.addToTasteProfile( 'skip', state.currentTlTrack.track.uri );

			MopidyService.play();
			MopidyService.next();
		},

		previous: function(){
			MopidyService.previous();
		},

		seek: function( time ){
			state.playPosition = time;
			MopidyService.seek( time );
		},

		setVolume: function( percent ){
			state.volume = percent;
			MopidyService.setVolume( percent );
		},

		/**
		 * Playback behavior toggles
		 **/
		toggleRepeat: function(){
			if( state.isRepeat )
				MopidyService.setRepeat( false ).then( function(response){ state.isRepeat = false; } );
			else
				MopidyService.setRepeat( true ).then( function(response){ state.isRepeat = true; } );
			console.log( state );
		},
		toggleRandom: function(){
			if( state.isRandom )
				MopidyService.setRandom( false ).then( function(response){ state.isRandom = false; } );
			else
				MopidyService.setRandom( true ).then( function(response){ state.isRandom = true; } );
		},
		toggleMute: function(){
			if( state.isMute )
				MopidyService.setMute( false ).then( function(response){ state.isMute = false; } );
			else
				MopidyService.setMute( true ).then( function(response){ state.isMute = true; } );
		}

	};

	return service;

}]);

<|endoftext|>


<commit_before>
module.exports = function (params) {
  return function consul(opts, resilient) {
    var type = 'discovery'

    function in(options, next) {
      next()
    }

    function out(req, res, next) {
      next()
    }

    return {
      in: in,
      out: out,
      type: type
    }
  }
}
<commit_msg>refactor<commit_after>
module.exports = function (params) {
  var type = 'discovery'

  function consul(opts, resilient) {
    function in(options, next) {
      next()
    }

    function out(req, res, next) {
      next()
    }

    return {
      in: in,
      out: out
    }
  }

  consul.type = type

  return consul
}
<|endoftext|>