On Wed, 2012-08-08 at 05:38 -0400, Jeremy Salwen wrote:
[...]
You emphasized the current state of lilv, saying
"Lilv doesn't really
do anything like this related to run time", and didn't speak further
on the possibilities. To me, this statement coupled with the further
silence on the topic meant that you intended to keep it this way.
Anyway, I'm more pleasantly surprised that this is not the case than I
am bothered by the fact that I misunderstood you.
I completely understand that from an implementational point of view,
midi binding functionality is quite different than what lilv does.
But from a utilizational point of view, midi binding fits right in
with the rest of the API.
Yes, but it is really more of an afterthought to some more fundamental
control things that need to happen. The silence is because I do not see
any interesting questions there. Things just need doing.
I suppose if the contained libraries are parallel
installable,
packagers could still package them independently, but if we want
that... why distribute them in one package upstream in the first
place? To save a tiny (if loud) niche of people from a few commands?
I had a different concept of SDK then you I thought
we were talking
about the scenario above as the default case, where the SDK simply
packaged the various libraries and tools together for convenience.
That the main difference would be the unification of the
documentation, and the implicit pressure on developers to use more of
the libraries. I agree that what you were talking about: monolithic
incompatible versions, would be a mistake.but that seems like an issue
orthogonal to what level of wrapping "magic" goes into the plugin host
library.
This is precisely what I am talking about. Putting libraries in the SDK
makes these issues happen. Libraries have compatibility issues that the
specifications do not.
Even on the
host side of things, I was unsatisfied with the lilv
c++ wrapper, so I wrote lolvmm.
And (unless I'm mistaken) never told me about it until now, so Lilv
remains unimproved. A wonderful example of "collaboration" failing in
practice ;)
Well my wrapper came out of this conversation on the drobilla
tracker:
http://dev.drobilla.net/ticket/756
I then posted a link to my library a few months ago when I finished.
So you did. Apologies, my mistake (I really wish Trac would email about
ticket comments!)
In the SDK model, we *don't want* to see
alternatives develop. We
want
to see *improvements contributed*.
I see contributions and alternatives as two sides of the same coin.
To me it is irrelevant if the alternative code exists on some dude's
website or if it get's standardized and included in the official SDK.
Well, it is not irrelevant at all. "The" way to do things being a
rotten header buried on some impossible to find website somewhere - or
sometimes one that's just gone away entirely - was a massive problem for
LV2 in the past. The extensions that defined properties and such were
even worse.
Tried that, didn't work. In practice, the specs need to be curated and
maintained in the official package.
The point is that Joe the developer still has a
choice in how he
hosts his plugins.
* Control events
* Events for announcing new parameters dynamically (I am
assuming this
is a requirement)
* Appropriate properties for describing the MIDI binding of
parameters
* Events for setting/announcing that as well
* Probably some kind of helper header API to make the above
easier
(i.e. reading/writing those events in a single function call)
* An example plugin that actually uses this stuff (a
multi-band EQ
seems the best candidate)
After all that is done, working, and established... sure, some
library
for automagic MIDI binding. Whatever. Right now, worrying
about that
is putting many carts before the horse.
No! We do not need control events for midi binding. The only thing
we need at this point is
Except everything even remotely related to LV2 is *constantly* held up
by control ports. I am tired of investing effort in a mistake, and I am
definitely not breaking the Lilv API to implement magic support for a
mistake that I constantly deal with griped about.
The sooner those damned ports die the better off we all are.
* Appropriate properties for describing the MIDI
binding of parameters
And that's what I was trying to get working on. I think you're
looking to far into the future. I have, right here, right now, a
synthesizer plugin that desperately wants default midi binding. I am
telling you that if I sat down today, with a set of properties that
describe midi binding, I could build a modified lilv shared library
that implemented default midi binding and without any compatibility
changes, suddenly every single host would support that feature. I
could even add some extra functions so that hosts who are aware of it
could turn it off, or modify the bindings in real time. Again, this
is all with standard control ports. And when event ports come around,
we could implement the exact same binding functionality, and the host
wouldn't even need to know what type of control port it is.
Well, what you say now is considerably different from what you said in
your original email to the lv2 mailing list, and, I will say again, Lilv
does not, will not, and *can not* do this "magic" in this way. You said
you understood this...
In your original email, you were describing some odd hybrid of MIDI
parameters and control ports where the host could switch between them,
and perhaps have GUI controls which send MIDI to the plugin.
Specifically, you said:
I was thinking about the ideal behavior from
the user's point
of view, and a realize that a knob which sends midi CC events
to the plugin would be ideal.
As has been said often in this discussion, this is awful, and no, spec
work will not be done towards it. Controlling plugin parameters via
MIDI is a gigantic step backwards, and spending time bloating
hosts/libraries doing this is ridiculous. Why would you go out of your
way to have a 7-bit controller? I am completely in agreement with Jeff
on this one. It is not only awful on paper, it has been shown to be
awful in practice with other APIs. This is not the way forward.
Now, if you have control ports, and want to describe their default MIDI
bindings in the .ttl file, that is an entirely different thing.
Essentially all that is needed is a single predicate to list the MIDI
binding, since the MIDI extension already defines everything else about
MIDI:
http://lv2plug.in/ns/ext/midi
I do not know which extension is most appropriate to put this predicate,
since it could be used for non-MIDI things as well. In any case,
something like:
<someport> foo:binding [ a midi:Controller ; midi:controllerNumber 27 ]
There are a few main reasons I have not done this yet:
* Nobody actually cared who was intending on actually writing code,
until you right now
* To do this in a utility API for control ports means the API depends on
the plugin instance directly, which means all the advantages of the
event based scheme in my previous mail go away, and much of the whole
thing will have to be rewritten for control events
* Static MIDI bindings don't seem very useful anyway, to me
This is not a new pattern. The theme of "oh, well, it could be done
correctly, but we have these LADSPA things that everybody despises and
suck for all sorts of other reasons, so we can kind of do it half-assed
for now and then re-do it again later" is a recurring one.
If you want to work on the host side portions of this, feel free,
however it can not be "magically" implemented in lilv as you wish (which
you will see if you try despite my suggestion). To be clear, I am not
saying I personally dislike this idea, I am saying it is not possible.
It can however be made simple, at least. Step one, and the most useful
90% of the work, would be to write code that reads that data, generates
some interim structure, which can then match against a MIDI event (i.e.
return true if and only if the MIDI event matches the binding
description). This is a necessary component of any solution. The
interim structure is required because this must be real-time safe so you
can't read from the data every time.
The 'get a value from a MIDI event' part is probably best done in a
static inline header included in the MIDI extension.
Given those two things, all the host has to do in its 'foreach event'
loop (which is usually present anyway, always in the case of hosts
writing from Jack or similar) is check if the event matches the binding
of any port, and if so sets the port value. For acceptable performance
with lots of ports and bindings, the above mentioned structure that does
this matching will have to store a port index and do the search in
log(n_bindings) time.
It is also important to take a look at existing host reality,
which
frankly the GMPI perspective tends to lack: for example, the
two main
large hosts I work on, Ardour and Ingen, would probably not
use this
convenience layer whatsoever, since they already have their
own binding
mechanisms that are specific to the internals of those
particular
programs.
But these are precisely the hosts which don't need default midi
bindings: you can do them manually! It's hosts like lv2_jack_host
that would benefit the most, because they would go from midi bindings
(and in fact any control ports) being unusable, to usable, albeit only
with default settings. That's the power of default midi bindings,
that you can host a plugin with the simplest midi host, and you can
tweak the knobs through your midi keyboard that the host might not
even understand how to vary. I don't see a stronger argument for how
things should be done based on the "existing host reality" than the
practical benefits that this path would offer.
I'm all for event-based control ports, but that's an issue separate
from midi binding libraries, which I think can be handled right now.
Personally I think this use case is a heck of a lot more nichey than you
let on, especially since it means you need to configure your MIDI
controller to match the plugin... unless the plugin is associated with
specific hardware, how many people are about to - or even can - do that?
There is a reason MIDI learn is how it is almost always done, static
bindings on the plugin just aren't very useful in most cases.
That said, sure, support for this would be nice (largely because it can
be re-used when the bindings are more usefully stored elsewhere, but
nice nonetheless). It is unfortunately not possible to have lilv hosts
magically support this without any changes at all, but it can be made
very easy as described above.
As far as what I am about to do goes, there is quite a bit of LV2 work
that needs doing that I consider to be of much higher priority than
this. I will not be concerned with binding until we have something
worth binding, and that big red column of fail in the document that
started this thread turns green. However, patches are welcome.
-dr
P.S. Your mail client is mangling quotes in a way that makes replying
cleanly very difficult and time consuming...