如何用 Windows 多媒体唯一标识一台 MIDI 设备?

How does one uniquely identify a MIDI device with Windows Multimedia?

我最近一直在探索 macOS 和 Windows 上可用的 MIDI API(分别是核心 MIDI 和 Windows 多媒体)并注意到:

在 MacOS 上,查询可用来源的数量后,每个来源都可以 唯一地 通过检查 属性 kMIDIPropertyUniqueID 的值来识别。

在 Win32 上,我找不到明确的替代方案 - 输入设备的“ID”似乎只不过是连接设备列表中的索引,它可能会随着新设备的连接而随时更改并断开连接。可以从设备请求的功能结构中的信息也不是特别有区别,因为同时使用两个相同的 MIDI 键盘会导致两个相同的功能集,直到产品名称。

有没有什么方法可以在 WinMM 中唯一标识这些设备?

遗憾的是,WinMM 中没有等效项。

您最多只能打开设备以获取它的句柄。该句柄将是唯一的,并且将始终引用打开的设备,即使添加和删除其他设备也是如此。

获得句柄后,您可以使用 midiInGetID()midiOutGetID() 获取 ID,以防它发生变化。

简短的回答是

WinMM中的设备ID确实只是设备列表中的一个索引。因此,如果您拔下一台设备并插入另一台具有相同属性(例如名称)的设备,您将无法确定您使用的设备是旧设备还是新设备。当然,名称可以相同,所以这不是一个选项。

因此,从编程方面来说,Windows 中无法区分两个具有相同属性的 MIDI 设备。在应用程序中,您可以提供一个按钮,如“刷新设备”或“测试设备”,以便与当前设备保持同步,并能够确定 GUI 中的哪个对象对应于 MIDI 设备。

至于 macOS,kMIDIPropertyUniqueID 是一个选项,但有细微差别。来自documentation上的常量:

The system assigns unique IDs to all objects. You may set this property on virtual endpoints; however, doing so may fail if the ID isn’t unique.

所以在某些情况下你可以获得不唯一的价值。在我看来,在 macOS 中识别设备的最可靠方法是使用其引用。例如,当您获得带有 MIDIGetSource 的源设备时,您会得到 MIDIEndpointRef 作为结果。事实上,它是一个 UInt32 号码,在系统范围内是真正独一无二的。

所以我在我的 .NET 库中 DryWetMIDI 依靠 MIDIEndpointRef 来区分 macOS 中的 MIDI 设备。也可以提供 MIDI 设备观看 (adding/removing)。但是对于 Windows 不幸的是这是不可能的。