node-midi icon indicating copy to clipboard operation
node-midi copied to clipboard

Method to list devices and listen for device changes

Open awwright opened this issue 7 years ago • 3 comments

There should be a method dedicated to listing the available devices, that doesn't require creating a (stateful) midi.input or midi.output instance.

There should a also be a way to listen for changes to the device list, so the application can act when a device is detected or removed.

awwright avatar Feb 25 '17 00:02 awwright

Having events would be nice but it doesn't look like something the library we wrap supports: http://www.music.mcgill.ca/~gary/rtmidi/

drewish avatar Feb 25 '17 00:02 drewish

Listing the devices is certainly possible though, even if I have to do a for() loop over the devices. And right now, I'm also scanning for new devices at regular intervals.

Mere polling like this could be implemented until upstream gets support for device change events.

awwright avatar Feb 25 '17 00:02 awwright

@awwright, I agree, but you could do that by yourself. I needed the same, so I made the following script:

// midi.js
const midi = require( 'midi' );

module.exports = {
  /**
   * Use property to store kind of a global input object,
   * so we won't create a new MIDI instance all the time
   */
  input: null,

  /**
   * Returns a list of device names
   */
  list: function() {
    if ( !this.input ) {
      this.input = new midi.input();
    }
    const devices = [];
    const size = this.input.getPortCount();

    for ( let i = 0; i < size; i += 1 ) {
      devices.push( this.input.getPortName( i ) );
    }

    return devices;
  },
};
// midiInputChangeListener.js
const midi = require( './midi' );

function checkDeviceListChange( callback = () => {}, length = 0 ) {
  const newDeviceList = midi.list();
  let newLength = length;

  if ( newLength !== newDeviceList.length ) {
    newLength = newDeviceList.length;
    callback( newDeviceList );
  }

  setTimeout( () => { // this line should be changed to be more async
    process.nextTick( () => { checkDeviceListChange( callback, newLength ) } );
  }, 100 );
}

module.exports = function( callback = () => {} ) {
  let deviceList = [];

  checkDeviceListChange( ( newDeviceList ) => {
    oldDeviceList = [ ...deviceList ];
    deviceList = newDeviceList;
    callback( deviceList, oldDeviceList );
  } );
}

lumio avatar May 30 '17 09:05 lumio