UNPKG

@julusian/midi

Version:
195 lines (166 loc) 4.2 kB
const midi = require("pkg-prebuilds/bindings")( __dirname, require("./binding-options") ); const Stream = require('stream'); // MIDI input inherits from EventEmitter const { EventEmitter } = require('events'); // Bring in the set of constants to reflect MIDI messages and their // parameters, to eliminate the need for magic numbers. /** An instrument list, only valid in the General MIDI standard */ const Instruments = require('./lib/instruments'); /** A drum map, only valid in the General MIDI standard */ const Drums = require('./lib/drums'); /** Note descriptions, with Middle C = C5 = MIDI note 60 */ const Notes = require('./lib/notes'); /** Message names, including CCs */ const Messages = require('./lib/messages'); class Input extends EventEmitter { constructor() { super() this.input = new midi.Input((deltaTime, message) => { this.emit('message', deltaTime, Array.from(message.values())) }) } closePort() { return this.input.closePort() } destroy() { return this.input.destroy() } getPortCount() { return this.input.getPortCount() } getPortName(port) { return this.input.getPortName(port) } isPortOpen() { return this.input.isPortOpen() } ignoreTypes(sysex, timing, activeSensing) { return this.input.ignoreTypes(sysex, timing, activeSensing) } openPort(port) { return this.input.openPort(port) } openPortByName(name) { for(let port=0; port<this.input.getPortCount(); ++port) { if (name === this.input.getPortName(port)) { return this.input.openPort(port); } } return undefined; } openVirtualPort(port) { return this.input.openVirtualPort(port) } setBufferSize(size, count = 4) { return this.input.setBufferSize(size, count) } } class Output { constructor() { this.output = new midi.Output() } closePort() { return this.output.closePort() } destroy() { return this.output.destroy() } getPortCount() { return this.output.getPortCount() } getPortName(port) { return this.output.getPortName(port) } isPortOpen() { return this.output.isPortOpen() } openPort(port) { return this.output.openPort(port) } openPortByName(name) { for(let port=0; port<this.output.getPortCount(); ++port) { if (name === this.output.getPortName(port)) { return this.output.openPort(port); } } return undefined; } openVirtualPort(port) { return this.output.openVirtualPort(port) } send(message) { return this.sendMessage(message) } sendMessage(message) { if (Array.isArray(message)) { message = Buffer.from(message) } if (!Buffer.isBuffer(message)) { throw new Error('First argument must be an array or Buffer') } return this.output.sendMessage(message) } } function createReadStream(input) { input = input || new Input(); var stream = new Stream(); stream.readable = true; stream.paused = false; stream.queue = []; input.on('message', function(deltaTime, message) { var packet = new Buffer.from(message); if (!stream.paused) { stream.emit('data', packet); } else { stream.queue.push(packet); } }); stream.pause = function() { stream.paused = true; }; stream.resume = function() { stream.paused = false; while (stream.queue.length && stream.emit('data', stream.queue.shift())) {} }; return stream; }; function createWriteStream(output) { output = output || new Output(); var stream = new Stream(); stream.writable = true; stream.paused = false; stream.queue = []; stream.write = function(d) { if (Buffer.isBuffer(d)) { d = Array.prototype.slice.call(d, 0); } output.sendMessage(d); return !this.paused; } stream.end = function(buf) { buf && stream.write(buf); stream.writable = false; }; stream.destroy = function() { stream.writable = false; } return stream; }; module.exports = { Input, Output, createReadStream, createWriteStream, Constants: { Instruments, Drums, Notes, Messages, }, // Backwards compatibility. input: Input, output: Output, };