Используя RtMIDI, MIDISendSysex не отправляет события на виртуальные порты

0

просто начал использовать RtMIDI в Xcode для прототипа некоторых MIDI-материалов. Он отлично работает, но попал в камнем преткновения.

Используя пример midiout.cpp без изменения чего-либо:

  • Если я отправляю MIDI-события на уже существующий MIDI-порт, все события отправляются нормально.
  • Если я отправляю MIDI-события на созданный виртуальный порт, все события, кроме событий sysex, отправляются.

Просмотрев код библиотеки, все MIDI-события, кроме syssex, отправляются (в OSX) с помощью вызова os MIDIReceived. События Sysex отправляются с использованием MIDISendSysex. Это так и должно быть.

Теперь никаких ошибок не возникает, все выполняется, как и должно быть, вызов MIDISendSysex не терпит неудачу - просто, чтобы никакие события сисекса не попадали в пункт назначения. Они просто исчезают в черной дыре!

Кто-нибудь еще сталкивается с этим или имеет какую-либо помощь, предложения, обходные пути?

Благодаря,

(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_ );
        }
      }

    }

  • 0
    Пожалуйста, покажите нам пример кода.
  • 0
    Привет - это использует файл midiout.cpp, который поставляется с библиотекой. Я не уверен, сколько я должен опубликовать? Программа-пример просто позволяет пользователю выбрать существующий порт или создать виртуальный порт и запускает некоторые примеры MIDI-событий для каждого из них. Поставит ссылку до ртмиди через секунду ...
Показать ещё 6 комментариев
Теги:
xcode
macos
midi

1 ответ

0
Лучший ответ

Последующая заметка - это была ошибка в RTMidi, которая должна быть исправлена в следующей версии. Это связано с тем, что в CoreMIDI вызов MIDISendSysex() не отправляется на виртуальные порты, он будет работать только на реальных портах.

Я обновил локальную копию RTMIDI для обработки событий sysex, используя MIDIReceived(), как рекомендовано в этом потоке в списке рассылки CoreAdio: http://lists.apple.com/archives/coreaudio-api/2006/Jan/msg00236.html

Теперь он отправляет sysex в виртуальные порты и ведет себя так, как ожидалось.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню