justinlatimer / node-midi

A node.js wrapper for RtMidi providing MIDI I/O
MIT License
743 stars 118 forks source link

Attempting to receive midi and forward a custom string per UDP #179

Closed martinberlin closed 3 years ago

martinberlin commented 3 years ago

Hello Justin, First of all thanks for this great component it works really great and is very easy to use. I'm simply trying to read the midi using the callback and redirecting a custom interpretation per UDP using dgram (I'm planning to launch some Lights in the other side hearing this with a WiFi ESP32 microchip) And the UDP works when outside the callback but it does not work when is inside the input.on callback. Can you give me a hint on what can be the solution?

Example code:

#!/usr/bin/env node

const yargs = require("yargs");
const midi = require('midi');
const dgram = require('dgram');
var udpclient = dgram.createSocket('udp4');

var DEBUG = true;
var PORT = 49161;       // Default Orca UDP output port
// Set up a new input.
const input = new midi.Input();
// Print port names
let udp_ip = "";
let ports = "ID: Port name\n";
for (let n=0; n<input.getPortCount(); n++){
  ports += n.toString() +': '+input.getPortName(n)+"\n";
}

let options = yargs
 .usage("Usage: -p <MIDI_PORT_ID>")
 .option("p", { alias: "port_id", describe: ports, type: "number", demandOption: true })
 .option("u", { alias: "udp_ip", describe: udp_ip, type: "string", demandOption: true })
 .argv;

console.log("Listening to: "+input.getPortName(options.port_id)+ ' and forwarding to '+options.udp_ip+':'+PORT);

// This send per UDP works
sendPerUdp("Test");

// Configure a midi callback.
input.on('message', (deltaTime, message) => {
  if (message!='248') {
    noteStatus = (message[0]==145) ? '1' : '0';
    noteChord  = message[1].toString(16);  // FF 0 01
    noteVelocity  = (message[2].toString(16).length==1) ?'0'+message[2].toString(16):message[2].toString(16);
    let noteInfo = noteChord+noteStatus+noteVelocity;
    console.log(noteInfo);

    // When called inside the midi callback it simply does not work
    sendPerUdp(noteInfo);
  }
});

// Open the port received per command line -p parameter
input.openPort(options.port_id);
input.ignoreTypes(false, false, false);

function sendPerUdp(noteInfo) {
  // Send per UDP - is not sending 
  var inBuffer = Buffer.from(noteInfo, 'utf8');
  udpclient.send(inBuffer,PORT,options.udp_ip, function(err, bytes) {
    if (err) {
      console.log(err);
      throw err;
    }
    console.log('Sent: ' + inBuffer.toString() + ' to ' + options.udp_ip +':'+ PORT);
  });
}

I've tried on another of my simple updproxy middleware to do an UDP listener that redirect messages also per UDP and it has worked put correctly. It's somehow limited what we can do on the MIDI.on callback?

martinberlin commented 3 years ago

Solved reading one issue in this same repository. Since they are too many issues open I’m closing here. Solution https://github.com/martinberlin/Remora/commit/f17c666df37fc3c0f89b3f1c653f4a135cfc4254