I am sending SysEx’s to the device on Xojo using the MIDISysexSendRequestMBS class.
I know it is successful, because SysEx Librarian detects incoming SysEx’s from the device in response to my instructions.
The question is, how to receive these in my own Xojo application?
Try posting to the Add-Ons category for MBS stuff, or to the MBS mailing list for best response.
You would receive them on an MidiEndpointMBS with a packet list.
And I think you join the DataMemory part of all the MidiPacketMBS objects to get the sysEx data.
1 Like
Some data started arriving when I created a Handler for the inputPort’s Read Event.
However, it is broken up into packets of 3 bytes, and sometimes out of sequence! Below is my event Handler for the Read function (packet_list is the variable I use to analyse the Midi messages I am receiving).
readData(port As MidiPortMBS, endpoint As MidiEndpointMBS, list as MidiPacketListMBS)
packet_list = list
endpoint.Recieved(list)
Verifying the input, e.g like so:
p_string = EncodingToHexMBS(packet_list.Item(index).DataString)`
System.DebugLog(p_string)
and then printing the output gives various results in sometimes correct order, e.g. F0 00 02, 1C 4E F7, 02 04 F7.
Meanwhile Sysex Librarian correctly identifies each message as a 9 hex-value sequence.
Hi Dominik. Resurrecting this old message thread. Can you share some code in which the Read event of your MidiEndpointMBS works? The MBS documentation states that one should subclass MidiEndpointMBS in order to gain access to the Read event. I’ve done this, but I simply cannot get the event to fire.
I’ve embarked on a project to create a GUI that never existed for a old piece of MIDI-enabled gear. My XOJO program can select programs/presets on the unit, and I can send Sysex messages, but after countless frustrating hours, I just can’t get my Read event to respond to the incoming Sysex. Both Sysex Librarian and MIDI Monitor show my outgoing Sysex message and the incoming one, so I know the unit is responding as expected.
Thanks for any help you can provide.
You need to create a port for your MidiClientMBS
midiPort=new MyMidiPort // Subclass of MidiPortMBS
MidiClient.CreateInputPort(NewCFStringMBS("My input port"), midiPort)
If midiPort.Handle=0 then
MsgBox "There was an error opening the MIDI port: "+str(midiClient.Lasterror)
Return
end if
and later, like in the ObjectAdded event of MidiClientMBS, connect an endpoint to the port
for srcnum=0 to numsources-1
source = new MidiEndpointMBS
source=me.GetSource(srcnum)
if source<>Nil then
sourcename = Source.StringProperty(me.kMIDIPropertyName).str // debug
if Instr(sourcename,"name of device") <> 0 then // It's the device I want
midiPort.ConnectSource(source)
Julia,
THANK YOU SO MUCH for some working code! I can now see data arriving at the my input port’s Read event. However, I’ve got an issue - only on rare occasion does the Sysex-ending F7 byte appear at the end of the data. All the preceding data appears (in proper sequence) as expected. Any suggestions? MIDI Monitor (open source) program ALWAYS shows the F7 at the end of the data, so I know it’s there (even with its option OFF to force (append?) F7 at the end).
Also, getting back to my original post above, I inquired about getting my MidiClientMBS’s Read event to fire. Does this event fire when the entire data package has been received as opposed to the input port’s Read event which fires 3 bytes at a time?
1 Like
Hi Peter,
Glad my ancient rickety code is helpful
Here’s my endpoint Read event handler:
Sub Read(endpoint as MidiEndpointMBS, list as MidiPacketListMBS) Handles Read
Dim i, n, x, MsgByte as integer
Dim pack as MIDIPacketMBS
Dim data as memoryBlock
// Data is coming in, reset the timeout
RXTimer = Microseconds
// Store incoming sysex messages (each beginning with a SOX and ending with an EOX) into the Messages() buffer.
n = list.Count-1
for i = 0 to n
pack = list.item(i)
data = pack.dataMemory
if not GotSOX then
if data.Byte(0) = &hF0 then // ## this will only find SOX if it's at the beginning of a packet. ##
SysexStr = ""
GotSOX = True // Start the sysex accumulation
end
end
if GotSOX then // accumulate the sysex message
For x=0 to data.Size-1
SysexStr = SysexStr + chrB(data.Byte(x))
If data.Byte(x)=EOX Then // Got EOX - done accumulating, be on the lookout again for new messages
GotSOX = False
Messages.Append(SysexStr)
End If
Next
end
Next
End Sub
It’s been over a decade since I wrote this and I rarely go this deeply into the bowels of the app anymore, but it’s been in continuous use ever since, so it seems I don’t have any trouble getting EOX (0xF7).
As is the case with serial devices, you want to do as little processing as possible in the Read event - just accumulate messages there in a buffer and handle them later e.g. in the Action event of a timer. If you try to do too much processing in the Read event you may miss bytes.
Ok, got it. BUT how did you initialize/setup your EndPointMBS object’s Read event? Did you subclass EndPointMBS to (for example) MyEndPointMBS and then add the Read event to your MyEndPointMBS subclass in the IDE? Or did you do a AddHandler MyMIDIEndpointMBS.Read, WeakAddressOf Read in your code?
Looking at your code in the prior message, if I’m not mistaken, your endpoint’s Read is called AFTER it’s received the entire Sysex message. You then break it down into its individual bytes. Perfect. I would prefer to do it this way (which still isn’t working for me) instead of utilizing my inputport’s Read, which doesn’t get the entire Sysex message at once, but rather in 3 byte chunks (and is almost always missing the F7 at the end of the message, as mentioned).
Yes.
Yeah, it does look that way… probably not how I’d do it now, but it works in my app, which deals mostly (entirely?) with pretty short messages.