刚刚开始在Xcode中使用RtMIDI来制作一些MIDI素材的原型。它运行良好,但遇到了障碍。
在不修改任何内容的情况下使用示例midiout.cpp:
-
如果我将MIDI事件发送到已经存在的MIDI端口,则所有事件都发送正常。
-
如果我将MIDI事件发送到创建的虚拟端口,则所有事件
除了
发送sysex事件。
查看库代码后,除了sysex之外的所有MIDI事件都使用MIDIReceived的os调用发送(在OSX上)。Sysex事件使用MIDISendSysex发送。这是应该的。
现在,没有抛出错误,一切都在按应有的方式执行,MIDISendSysex调用没有失败-只是没有sysex事件到达目标。他们消失在一个黑洞里!
还有人遇到这个问题或有任何帮助、建议或变通办法吗?
谢谢
(Xcode 4.6.2,OSX 10.9.1,使用MIDIMonitor和MIDIPipe监视MIDI端口上的流量,两者都显示了sysex事件未从midiout.cpp到达虚拟端口的相同结果)
好的,这是实际发送的sendMessage路由:
void MidiOutCore :: sendMessage( std::vector *message )
{
// ------------------------------------------------------------------------
// We use the MIDISendSysex() function to asynchronously send sysex
// messages. Otherwise, we use a single CoreMidi MIDIPacket.
// ------------------------------------------------------------------------
// error handling code removed for brevity
MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
CoreMidiData *data = static_cast (apiData_);
OSStatus result;
// ------------------------------------------------------------------------
// IF EVENT IS SYSEX
// ------------------------------------------------------------------------
if ( message->at(0) == 0xF0 ) { // sysex start byte
while ( sysexBuffer != 0 ) usleep( 1000 ); // sleep 1 ms
sysexBuffer = new char[nBytes];
// Copy data to buffer.
for ( unsigned int i=0; iat(i);
// build sysex request
data->sysexreq.destination = data->destinationId; // destinaiondId is valid endpointref
data->sysexreq.data = (Byte *)sysexBuffer;
data->sysexreq.bytesToSend = nBytes;
data->sysexreq.complete = 0;
data->sysexreq.completionProc = sysexCompletionProc;
data->sysexreq.completionRefCon = &(data->sysexreq);
// send the data
// this works when we are connected to a 'real' MIDI port/device, but fails on a virtual port
// destinationId is an endpointref and valid and id is good
// tried to use data->endpoint (also an endpointref with id) but doesn't send either
result = MIDISendSysex( &(data->sysexreq) );
return;
}
// ------------------------------------------------------------------------
// IF EVENT IS NOT SYSEX
// ------------------------------------------------------------------------
MIDIPacketList packetList;
MIDIPacket *packet = MIDIPacketListInit( &packetList );
packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) );
// Send to any destinations that may have connected to us.
// this sends to virtual MIDI ports
if ( data->endpoint ) {
result = MIDIReceived( data->endpoint, &packetList );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
RtMidi::error( RtError::WARNING, errorString_ );
}
}
// And send to an explicit destination port if we're connected.
// this sends to regular real MIDI devices we are connected to, not virtual ports
if ( connected_ ) {
result = MIDISend( data->port, data->destinationId, &packetList );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port.";
RtMidi::error( RtError::WARNING, errorString_ );
}
}
}