如何从MIDISourceCreate()保留虚拟MIDI源的唯一性?

mic*_*ett 6 macos midi core-audio ios coremidi

我正在使用RtMidi作为OS X上CoreMIDI的包装来从应用程序发送MIDI消息.我使用RtMidiOut::openVirtualPort("MyAwesomePort")这样我可以选择我的应用程序作为DAW中的输入源.

但是,如果我的程序关闭并且我再次打开它,我的DAW不会将输入设备识别为相同的端口,尽管给出了相同的名称.

我最初使用的是pyrtmidi,因此用RtMidi直接验证了用C++编写的行为.在这种情况下,"我的DAW"是Reaper 4,但我复制了Pro Tools,Logic和MuLab中的行为.

我知道可以保留虚拟midi端口的一些独特性,因为MidiKeys的行为就像我希望我的应用程序一样:即使MidiKeys在我的DAW仍在运行时关闭并重新打开,我的DAW也会记住它.

所以我挖掘了RtMidi源代码,CoreMIDI封装器看起来很简单.所MIDISourceCreate要求的只是一个字符串.客户端参数是(我在浏览文档后假设的)我的应用程序的标识符,它是CoreMIDI服务的客户端.

void RtMidiOut :: openVirtualPort( std::string portName )
{
  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);

  if ( data->endpoint ) {
    errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!";
    error( RtError::WARNING );
    return;
  }

  // Create a virtual MIDI output source.
  MIDIEndpointRef endpoint;
  OSStatus result = MIDISourceCreate( data->client,
                                      CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),
                                      &endpoint );
  if ( result != noErr ) {
    errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source.";
    error( RtError::DRIVER_ERROR );
  }

  // Save our api-specific connection information.
  data->endpoint = endpoint;
}
Run Code Online (Sandbox Code Playgroud)

所以我查看了MIDISourceCreate文档,并阅读:

创建虚拟源之后,最好为其分配与上次应用程序创建时相同的唯一ID.(尽管您应该在不太可能发生冲突的情况下为此做好准备.)这将允许其他客户端更容易地保留对虚拟源的持久引用.

这似乎正是我正在寻找的.除了我不知道如何为源分配唯一的ID.out参数MIDISourceCreate是a MIDIEndpointRef,根据文档,它只是UInt32对行进行了类型定义.所以我假设也许我应该跟踪这个UInt32,但这似乎是一个坏主意.

在深入了解所有这些之后,我觉得我正在打一点砖墙.如何在我的应用程序运行之间保留MIDI端口的唯一性?

tc.*_*tc. 6

根据文件,

kMIDIPropertyUniqueID

系统为所有对象分配唯一ID.虚拟端点的创建者可以在其端点上设置此属性,但如果所选ID不唯一,则可能会失败.

也许是这样的:

// Try to set the ID if it's saved.
if (savedUniqueId) {
  OSStatus result = MIDIObjectSetIntegerProperty(endpoint, kMIDIPropertyUniqueID, myUniqueId);
  if (result == kMIDIIDNotUnique) {
    savedUniqueId = 0;
  }
}
// If not saved, record the system-assigned ID
if (!savedUniqueId) {
  OSStatus result = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &savedUniqueId);
  // Handle the error?
}
Run Code Online (Sandbox Code Playgroud)

唯一ID是对SInt32的类型定义.我假设0是一个无效的唯一ID,对于连接至少是真的(kMIDIPropertyConnectionUniqueID的文档说它是"不存在的,如果没有连接则为0").

我不确定你如何只用32位保持长期唯一性,但它有望足以重新启动你的应用程序.