lucidstack / ex-portmidi

Elixir bindings to the portmidi library
MIT License
34 stars 12 forks source link

Device list never changes #4

Closed jimm closed 8 years ago

jimm commented 8 years ago

PortMidi.devices never changes its return value while the app is running. If I attach/detach new MIDI devices or open MIDI apps that open MIDI input/output ports, calling PortMidi.devices does not reflect the new list of available devices.

jimm commented 8 years ago

Portmidi itself doesn't do this. I wrote a simple test program in C and verified that if I get all the devices periodically, the list does not change even when I detach MIDI devices/apps. I've copied the test program below in case anybody is interested.

I'm closing this ticket.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "portmidi.h"

void list(const char *title, const PmDeviceInfo *infos[], int num_devices) {
  printf("%s:\n", title);
  for (int i = 0; i < num_devices; ++i)
    if (infos[i] != 0)
      printf("  %s%s\n", infos[i]->name, infos[i]->opened ? " (open)" : "");
}

void list_all_devices() {
  int num_devices = Pm_CountDevices();
  const PmDeviceInfo *inputs[num_devices], *outputs[num_devices];

  for (int i = 0; i < num_devices; ++i) {
    const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
    inputs[i] = info->input ? info : 0;
    outputs[i] = info->output ? info : 0;
  }

  list("Inputs", inputs, num_devices);
  list("Outputs", outputs, num_devices);
}

int main(int argc, char **argv) {
  for (;;) {
    printf("\n\n\n");
    list_all_devices();
    sleep(5);
  }
  exit(0);
}
lucidstack commented 8 years ago

Hi @jimm, thanks for pointing that out. I was having a look at this, and couldn't find any caching points, or similar issues. I might look into the Portmidi source code, to see if there is any way to refresh that list.

jimm commented 8 years ago

Calling Pm_Terminate and Pm_Initialize is part of the solution. The list will be updated, but the device count remains the same. I just tried running this C code:

  for (int i = 0; i < 5; ++i) {
    printf("\n\n\n");
    Pm_Initialize();
    list_all_devices();
    Pm_Terminate();
    sleep(5);
  }

Here is the output, as I quit removed first SimpleSynth then MidiPipe:

Inputs:
   0: IAC Driver Bus 1
   1: MidiPipe Output 1
Outputs:
   2: IAC Driver Bus 1
   3: MidiPipe Input 1
   4: SimpleSynth virtual input

Inputs:
   0: IAC Driver Bus 1
   1: MidiPipe Output 1
Outputs:
   2: IAC Driver Bus 1
   3: MidiPipe Input 1
   4: SimpleSynth virtual input

Inputs:
   0: IAC Driver Bus 1
   1: MidiPipe Output 1
Outputs:
   2: IAC Driver Bus 1
   3: MidiPipe Input 1
   4:

Inputs:
   0: IAC Driver Bus 1
   1:
Outputs:
   2: IAC Driver Bus 1
   3:
   4:

Inputs:
Outputs:

So it looks like the count was updated the last time for some reason.

Looking briefly at the portmidi code, it looks like the global pm_descriptor_index never gets reset to 0 in the code. I wonder if your C interface code could do that before calling Pm_Initialize.

Also, when I added the MIDI apps back during a run, the count never got higher so I didn't see the newly added MIDI ports. I don't have time to poke around any more right now.

thbar commented 5 years ago

I had the same issue today, especially relevant while working with LiveView + PortMIDI (see slides of a talk I gave recently for more context).

If any of you found a proper work-around for this, I'm interested!

thbar commented 5 years ago

From the PortMidi doc, sadly:

Note that MIDI devices added after the Portmidi library has been initializd will not be reflected in the list of descriptions.

http://www.moz.ac.at/sem/lehre/lib/cm/CM.app/Contents/Resources/cm/doc/dict/portmidi-topic.html