On Wed, 2007-11-28 at 16:45 +0000, Krzysztof Foltman wrote:
There is also a possible middle ground - an event type
declaration in
rdf would say not just what URI it corresponds to, but also if it
contains any "unsafe" data (like pointers, handles etc).
Just to possibly prevent a hypothetical transparent network/interprocess
bridge from trying to smuggle pointers between process boundaries, which
could lead to unexplained crashes :)
_Any_ structure that isn't just a dumb array of bytes will be unsafe to
move between machines because of endianness. If the host doesn't know
exactly what the internal structure of the event buffer is it can't do
anything like that (unless it has a serialisation callback like in your
object event proposal) and if it does it can, so having a separate flag
for that is probably redundant.
No argument
with any of this. Passing around reference counted opaque
objects can certainly be useful and I can imagine lots of sexy
applications, I just don't think it needs to be in the event transport
specification when it works just as well outside it.
Good. So let's postpone that part for now, it will go into different
extension(s).
OK, so what we have now is something like this:
struct Event_Port_Buffer {
uint32_t capacity; // number of elements in the array
uint32_t used_size; // number of _used_ elements
uint32_t event_count; // number of events (different from
// used_size if there are large events -
// would this really be needed?)
struct Event* events; // an array allocated by the host
};
struct Event {
uint32_t timestamp;
uint16_t size;
uint16_t event_type;
uint8_t data[8]; // or a union or whatever, as long
// as it's 8 bytes
};
A pointer to an Event_Port_Buffer is passed to connect_port() for every
event port etc. And in the RDF file for the plugin there would be
something like this:
<http://myplugin.example.com> a lv2:Plugin;
lv2:requiredFeature <http://lv2.example.com/midi-event-type>;
lv2:port [
a lv2:InputPort, <http://lv2.example.com/event-port>;
...
];
...
The host won't instantiate the plugin unless it knows how to handle
event ports and MIDI events, and the plugin will fail to instantiate
unless the host passes a URI -> integer map to instantiate using a
LV2_Feature with the URI <http://lv2.example.com/uri-map> and a
NULL-terminated array of event type URIs as data. The integer associated
to each URI is simply the array index (my earlier suggestion was just a
brain dump from a thought-in-progress, a simple array seems a lot
cleaner).
Assuming that the host only supports MIDI events the data passed for
this feature will be { "http://lv2.example.com/midi-event-type", NULL },
the plugin will store the index 0 as the MIDI event identifier somewhere
in its state, and everything is good to go. A basic loop for processing
input events in a plugin could look something like this:
Event_Port_Buffer* buf = ports[EVENT_PORT];
uint32_t index;
uint32_t next_frame;
uint32_t frames_done = 0
while (index < buf->used_size) {
next_frame = events[index].timestamp >> 16;
render_audio(frames_done, next_frame);
frames_done = next_frame;
handle_event(events[index]);
index += 1 + (events[index].size - 8) / 16;
}
render_audio(frames_done, nframes);
Should plugins have to list <http://lv2.example.com/uri-map> as a
required feature, or should that be implicit whenever a plugin has an
event port? Both methods have some drawbacks - if plugins are required
to list it there is some redundancy, if they are not we have a required
feature that isn't listed as one which can be a bit confusing.
Does anyone else see any other problems with this type of event port?
Steve, Dave, Nedko?
--ll