micdah / RtMidi.Core

RtMidi for .Net Standard
https://rtmidicore.micdah.dk/
Other
36 stars 12 forks source link

Problems with port names ending with a number. #30

Open GuruGurra opened 1 year ago

GuruGurra commented 1 year ago

If a port name ends with a number that coincides with the port number, the number is stripped from the name.

Example:

If I have two ports named (their real names) "Port 1" and "Port 2", they will both be reported as "Port" in the port list and hence cannot be used.

Edit: The problem seems to be a macOS problem only. I can't see that port names have any numbers appended on macOS, causing the real port name to be truncated if it ends with the same number as the internal port number.

micdah commented 1 year ago

The name is resolved using rtmidi actually, so I suspect either rtmidi or the underlying macOS specific API might be doing some truncations, I simple use a provided GetPortName(...) method in the underlying library.

But rtmidi enumerates devices by a unique port number (uint) which is currently not exposed in RtMidi.Core, which might help in this case?

I suspect you are storing the name of the device you want to connect to, and then using MidiDeviceManager to find it?

MidiDeviceManager.Default.InputDevices.SingleOrDefault(dev => dev.Name == "Name");

If the port number is exposed, this may help disambiguating two devices with the same name (albeit it, having it not being truncated would be preferred). I'm just unsure whether the port number is persistent across restarts, I suspect it's just tied to whichever order the devices are enumerated. I.e. connecting / disconnecting devices may change device numbering I suspect.

My best suggestion would be to have a look over in rtmidi and see if you can figure out where the truncation happens

GuruGurra commented 1 year ago

...I simple use a provided GetPortName(...) method in the underlying library.

No, you don't. In RtMidiDeviceInfo, you set the name to:

Name = name.EndsWith(port.ToString())
    ? name.Substring(0, name.LastIndexOf(port.ToString(), StringComparison.Ordinal))
    : name;

If I change that like this, it works on both Windows and macOS.

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
{
    Name = name.EndsWith(port.ToString())
    ? name.Substring(0, name.LastIndexOf(port.ToString(), StringComparison.Ordinal))
    : name;
}
else { Name = name; }
micdah commented 1 year ago

My bad, you are correct. 👍

I see you have also identified the changes needed, a PR would be much appreciated - I'll have a look shortly at reviving the build pipeline as the current isn't active anymore and then I can merge your PR and get a new build out.

Great find. 🚀