Thanks Roger, it does help.

I'm unlucky that it seemed to work for me probably because I was scrutating the 
fifo
faster enough not to miss events but now I understand 
why my original approach doesn't work.

I thought about the 2 solutions (fifo splitting and selective Pm_Read())
you mentioned and agree that none of them is really satisfactory at the end.

I believe that even if we would implement 2 fifos in portmidi,
this would solve my problem but would not be elegant.

More precisely, it would not address the need of reading messages ordered,
which is sometimes needed in other midi applications.
What I mean by this is that int the 2 fifos solution ;  it would be ordered 
inside a category (non sysex data or sysex data),
but we may lose the link between the sequencing of all midi messages, 
sysex or not.

So I had a third idea that would need the help of portmidi developers,
 but would be IMHO useful and polyvalent:
Let's suppose we still conserve a unique unified midi fifo, but that we have a
flag associated to the fifo we read from (as opposed to associated with the 
device
like the async sysex_in_progress flag) which gives only the information
that what is to read currently in the fifo is either:
 - nothing
 - a sysex message
 - a non sysex message

This would be great as we would consume only what we need.
If a msg wouldn't be of our thread interest then it would unlock immediately 
and would try later, meanwhile another thread would read these events.
What may be non trivial to determine for the client and that this new code 
would do 
is to achieve a correct response if a long sysex is currently available on the 
fifo
but was splitted into several parts so that reading in the client of the first 
message
would not give anymore the informaton of a sysex SOX for instance, 
in the case of SOX/EOX sysex messages. 

In other words this flag would 'keep track' of previous messages states.
an API would permit to interrogate what is currently available like:
int Pm_Read_Message_Type() that would return the 3 possibilities mentioned 
earlier.

The usefulness of such a code addon would be multiple:
 - use for selective multithreaded Pm_Read()
 - use for  splitting easily fifo in client code

Any thoughts ?

Thanks,
Fabien

------------------------------------------------------------------------------
Roger wrote:
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
_______________________________________________
media_api mailing list
[email protected]
http://lists.create.ucsb.edu/mailman/listinfo/media_api

Reply via email to