Fabien,
I may be missing something, but I think I understand what you want to do, and I think it will not work. On the MIDI input side, PortMidi delivers data from an input device to a FIFO using a system-provided thread or callback. The client runs asynchronously to read from the FIFO. Let's call these threads the "system" and the "client". The sysex_in_progress thread is set/cleared by the system. Since this is independent of the client, the system can begin processing a sysex message, set sysex_in_progress, finish the sysex processing, and clear sysex_in_progress, all before a client thread wakes up.

There are a couple of ways to split sysex and non-sysex messages safely. One method is to have the non-sysex client read everything. When sysex messages are received, copy the data into (yet another) fifo for the sysex client. (You'll probably want to copy the data into your application's data structures and strip out any 1-byte real-time messages, which PortMidi is allowed to embed in sysex messages, so by folding in this formatting with the copy, this scheme should only add a small amount of net overhead).

A second method will require a mutex lock to call Pm_Read and a structure of type PmEvent. Both the sysex and non_sysex threads are free to read at any time, but if one accidentally reads a message of the wrong type, the message is left in the PmEvent for the other thread, and reading does not proceed until the other thread takes the message. In psuedo-code, the non-sysex client looks like:

non_sysex_read()
   get_the_lock
   if pmevent.message == 0 // no data, look for some
       if Pm_Read(stream, &pmevent, 1) <= 0
           release_the_lock
           return "nothing -- try again later"
   // message to handle is in pmevent
   if pmevent has non-sysex data
       result = pmevent
       pmevent.message = 0 // clear the buffer
       release_the_lock
       return result
   else // need to wait for sysex thread to read this
           release_the_lock
           return "nothing -- try again later"

The sysex_read looks the same except "pmevent has non-sysex data" is replace by "pmevent has sysex data". This scheme suffers from the need for locks, the possibility to have two threads busy-waiting on the fifo, and the fact that the sysex thread is going to have to filter out non-sysex realtime messages and do something with them. You could fix the busy waiting with condition variables, but that's only one of the problems.

You *could* modify PortMidi to use separate FIFOs for sysex and non-sysex data, and this would actually simplify the handling of realtime messages embedded in sysex messages (the system thread could simply distribute the bytes into the appropriate fifo). Some midi systems do this, but it requires every client to poll two fifos instead of one and it gives you two buffers to potentially overflow.

I hope this helps.

-Roger

Fabien Costantini wrote:
I handle simultaneously several midi in/out sources  in real time,
all those peripherals exchange standard midi events as well as custom mixing automation events encapsulated in midi sysex in real time.
I must re-route and treat some of these mixed events but different threads 
treat sysex events and non sysex event.
It's a multiple producer /multiple consumer scheme, where consumers are 
selective
 (those consuming sysex don't consume non sysex data and vice versa).
I would be more than happy if I could select a different message queue (i.e: 2 
independant queues) for non sysex data
and sysex data but don't think it's possible with pm ?
So my solution based on 'listening' before consuming messages is fast and easy 
to manage.
(I could have read the unified midi buffer an splitted it myself into 2 sysex and non sysex queues but it's more work and will slow down things unnecessarily)

Thanks,
Fabien

I don't understand what you are doing. The sysex_in_progress flag is set and cleared asynchronously by the midi input handler. If your client code is doing something that depends on this flag, it seems likely that
t>here is a race condition. I'm not opposed to extending the API to
enable a different way to structure client code if there really is a correct way to use sysex_in_progress.
-Roger
Fabien Costantini wrote:
In my current code, I must sadly rely on on PmInternal real structure which is very dirty.
Thus, I am constrained either to give the portmidi/pm_common include path to my 
project
or duplicate the type definition, both alternative are just as bad.

But the only thing I use/need in PmInternal is the sysex_in_progress flag.
...

_______________________________________________
media_api mailing list
media_api@create.ucsb.edu
http://lists.create.ucsb.edu/mailman/listinfo/media_api

Reply via email to