Discussion:
[linux-audio-dev] LADSPA 2
Steve Harris
2006-04-22 09:53:58 UTC
Permalink
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.

Anyway, I finally got round to making a sketch plugin and .h file:
http://plugin.org.uk/ladspa2/

The .ladspa2 plugin is a "bundle", ie. a directory with all the data the
plugin needs in it. This idea is nicked from OPENSTEP. I'm not 100%
convinced it's a good idea, but I think it makes sense for plugins.

The dsp core (amp.c) is just a LADSPA 1.1 plugin with all the fixed data
fields taken out, and a URI field added, to allow for working
identification. I also dropped the runAdding method, as I dont think it
is used enough to justify the effort of supporting it. The plugin is
untested, but it compiles and nm reports sane contents for it.

The data is in the amp.ttl file (it's in Turtle
http://www.dajobe.org/2004/01/turtle/ an easy to hand-write RDF syntax).
We could mandate a particular syntax for the spec.

There's a shell script (show-data.sh) which, if you have raptor and rasqal
installed will do something similar to what analyseplugin does for LADSPA
1.x, but it's very crude.

Overall I think this is a much better approach than LADSPA 1.x, it has
usable identifiers, a clear route for extensions without compatibility
problems and each plugin is quite a lot simpler.

- Steve
Lars Luthman
2006-04-22 10:19:42 UTC
Permalink
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
http://plugin.org.uk/ladspa2/
Nice. The header and the plugin code really looks a lot cleaner without
all the metadata embedded in it.
Post by Steve Harris
The data is in the amp.ttl file (it's in Turtle
http://www.dajobe.org/2004/01/turtle/ an easy to hand-write RDF syntax).
We could mandate a particular syntax for the spec.
It looks a lot nicer than the XML syntax.
Post by Steve Harris
Overall I think this is a much better approach than LADSPA 1.x, it has
usable identifiers, a clear route for extensions without compatibility
problems and each plugin is quite a lot simpler.
What type of extensions are you talking about here, and what is the
clear route?
--
Lars Luthman
PGP key: http://www.student.nada.kth.se/~d00-llu/pgp_key.php
Fingerprint: FCA7 C790 19B9 322D EB7A E1B3 4371 4650 04C7 7E2E
Jack O'Quin
2006-04-22 16:46:28 UTC
Permalink
Post by Lars Luthman
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
http://plugin.org.uk/ladspa2/
Nice. The header and the plugin code really looks a lot cleaner without
all the metadata embedded in it.
Agreed. I really like getting all that XML out of the C sources. Much
cleaner and more accessible.

A minor suggestion: how about moving that SYMBOL_EXPORT definition
into ladspa-2.h, presumably with a LADSPA_ prefix?

#ifdef WIN32
#define SYMBOL_EXPORT __declspec(dllexport)
#else
#define SYMBOL_EXPORT
#endif

--
joq
Steve Harris
2006-04-22 16:55:56 UTC
Permalink
Post by Jack O'Quin
Post by Lars Luthman
Nice. The header and the plugin code really looks a lot cleaner without
all the metadata embedded in it.
Agreed. I really like getting all that XML out of the C sources. Much
cleaner and more accessible.
The XML+C thing was a Steve-brand hack, not part of the spec, I dont think
anyone else was doing it. The metadata was generally static C char *'s,
but that was very limiting, and led to a lot of tedious cut-and-paste
code, compatibility dead-ends and i18n excitement.
Post by Jack O'Quin
A minor suggestion: how about moving that SYMBOL_EXPORT definition
into ladspa-2.h, presumably with a LADSPA_ prefix?
#ifdef WIN32
#define SYMBOL_EXPORT __declspec(dllexport)
#else
#define SYMBOL_EXPORT
#endif
Not a bad idea, I could go for that.

- Steve
Steve Harris
2006-04-22 17:30:30 UTC
Permalink
Post by Lars Luthman
Post by Steve Harris
Overall I think this is a much better approach than LADSPA 1.x, it has
usable identifiers, a clear route for extensions without compatibility
problems and each plugin is quite a lot simpler.
What type of extensions are you talking about here, and what is the
clear route?
Extensions to the metadata, eg. port groups, new kinds of port (assuming
they can still be float *s), additional hints etc.

The clear route is the RDF namespacing mechanism, if someone wants to try
a new extension they can just start using it under thier own namespace,
then it can be added to the core spec if it's popular.

- Steve
Sampo Savolainen
2006-04-22 11:44:22 UTC
Permalink
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
http://plugin.org.uk/ladspa2/
Great!

The .ttl file syntax looks really good.

I have a few suggestions, though:

- GUI support. A standardized, well defined way for plugins
to supply a graphical user interface of it's own.

- Port units should be defined in a way that plugin hosts know
what these units are. The label is not good enough for hosts.

Instead of:
ladspa:units "dB"

We could have:
ladspa:units#db
rdfs:label "dB"
(thanks for the syntax Steve. I hope I understood correctly)

If hosts understand which units are used it gives the them a possibility
to create better GUIs for the plugins. For example, if a parameter is in
dB, the host can provide a widget more suitable for gain entry.

But this would offer even greater benefits than widget selection: hosts
could give users the possibility to give time values relative to
beats/bars. (Without any need for the plugin to know about the tempo).
Think delays synchronized with the song tempo, for example.

The plugin could also give hints if a parameter should/could be given in
beats/bars or absolute time.
--
Sampo Savolainen <***@iki.fi>
Steve Harris
2006-04-22 16:10:34 UTC
Permalink
Post by Sampo Savolainen
Post by Steve Harris
http://plugin.org.uk/ladspa2/
Great!
The .ttl file syntax looks really good.
Yes, it's nice to write, unlike RDF/XML, which is a PITA. There aren't as
many RDF librries tha can read it, but the majority (including raptor) can.
Post by Sampo Savolainen
- GUI support. A standardized, well defined way for plugins
to supply a graphical user interface of it's own.
I would advocate the DSSI protocol, and placing the executable in the
bundle.
Post by Sampo Savolainen
- Port units should be defined in a way that plugin hosts know
what these units are. The label is not good enough for hosts.
ladspa:units "dB"
ladspa:units#db
rdfs:label "dB"
(thanks for the syntax Steve. I hope I understood correctly)
I think you have, to be perfectly clear, I think you mean (in longhand):

In the plugin file
<some plugin> ladspa:unit units:db .

and then in the schema file:
units:db rdfs:label "dB" .

ie. label the plugins with a URI (symbol) and then annotate the symbol
with its name globally.

I thought about doing that in the example, but I though maybe the extra
level of indirection would put people off. It would let the hosts do more
intelligent things with control ports though, like you suggested.

- Steve
Thorsten Wilms
2006-04-22 12:26:57 UTC
Permalink
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
I'm not competent to comment on header files or implementation details.
But via Om, I'm a LADSPA power user and would like to bring up
some issues ;)


Distribution / finding plugins:
I would like to have an app, where I can put checkmarks to all plugins
and they will be fetched and installed (buidling from source / binaries
as option).
But just a way to get from the host not finding a plugin to the name
of the collection it's in would be nice already (so an app like Om can
not only say plugin-x not found, but also point to the package).


Stability:
There are some plugins that will die if fed with values out of their
range (and this happens easily in a modular system). Maybe some mechanism
to protect against this could be build into the framework?


Control/audio rate:
Having several variations of the same plugin to allow varying audio/
control rate port setups makes for unnecessary long plugin lists and
requires the user to delete and insert a different one, should he find
out some port should be audio, not control rate. Just look at the
sine oscillator(s) ...
The rate of a port should be switchable (at leat in all cases where
we have both versions now).


Port grouping:
Hosts should be able to see, wether 2 ports are independent, or happen
to be a stereo pair (or any multi-channel setup).
Also a way to specify that things like frequency and amount ports of
an EQ form pairs might be nice. Should be helpful for generative plugin
GUIs.


Port Roles:
Ports could have roles assigned to them, like signal_input, sidechain,
latency or bpm (the last for transport awareness and to make it possible
hosts assign values to it automaticaly).


Referencing:
There needs to be a safe way to reference plugins and their ports.
Portnames make for human readable patch files, but this doesn't
work with i18n, when Attack becomes Einschwingzeit ;)


Hints:
Maybe I just didn't see it, but shouldn't there be a hint for lists?
Like for plugins that have modes/presets?


Presets:
Cross-host preset loading/saving.


Help / Discription:
A way to bring up a short discription of a plugin and what the
ports are about.


MIDI/OSC
Don't know if the new LADSPAs should be able to handle MIDI/OSC,
but there should be plugins that do it ;)


GUI lib:
There could be 1 or 2 (GTK, QT) libs for generative plugin GUIs,
for hosts not having to reinvent the wheel and for consistency.


---
Thorsten Wilms
fons adriaensen
2006-04-22 12:56:35 UTC
Permalink
Post by Thorsten Wilms
MIDI/OSC
To which I'd add:

Polyphony/Multiple channels:

Plugin instances should be able to discover that they are
part of a group sharing control parameters. In many cases
the calculation of internal parameters from user supplied
ones and their interpolation takes more CPU than the rest
of the code. That work should be performed once in poly
setups.


The new syntax lools a lot cleaner than the existing system,
to the point that I'd support it :-)
--
FA

Follie! Follie! Delirio vano e' questo!
Lars Luthman
2006-04-22 13:01:26 UTC
Permalink
Post by fons adriaensen
Post by Thorsten Wilms
MIDI/OSC
Plugin instances should be able to discover that they are
part of a group sharing control parameters. In many cases
the calculation of internal parameters from user supplied
ones and their interpolation takes more CPU than the rest
of the code. That work should be performed once in poly
setups.
I'm not sure that all of this belongs in LADSPA (the Simple Plugin
Architecture). DSSI has support for presets, MIDI in, GUIs and some
support for polyphony (you can run several plugin instances as a
polyphony group with a single call to run_multiple() which lets you do
common calculations once).

About referencing: isn't the port index the common way to identify
LADSPA ports?
--
Lars Luthman
PGP key: http://www.student.nada.kth.se/~d00-llu/pgp_key.php
Fingerprint: FCA7 C790 19B9 322D EB7A E1B3 4371 4650 04C7 7E2E
Thorsten Wilms
2006-04-22 13:14:28 UTC
Permalink
Post by Lars Luthman
I'm not sure that all of this belongs in LADSPA (the Simple Plugin
Architecture). DSSI has support for presets, MIDI in, GUIs and some
support for polyphony (you can run several plugin instances as a
polyphony group with a single call to run_multiple() which lets you do
common calculations once).
I was about generated GUIs, not plugin specific ones.
What's the reason that Om can treat DSSIs only as monophonic nodes
again?
Post by Lars Luthman
About referencing: isn't the port index the common way to identify
LADSPA ports?
Might be. A human readable, not to be translated english name per
port would be nice, though.


---
Thorsten Wilms
Lars Luthman
2006-04-22 13:25:43 UTC
Permalink
Post by Thorsten Wilms
Post by Lars Luthman
I'm not sure that all of this belongs in LADSPA (the Simple Plugin
Architecture). DSSI has support for presets, MIDI in, GUIs and some
support for polyphony (you can run several plugin instances as a
polyphony group with a single call to run_multiple() which lets you do
common calculations once).
I was about generated GUIs, not plugin specific ones.
I meant generated GUIs too - I've seen at least one generic (as in works
for any plugin) DSSI GUI somewhere, although I don't remember where at
the moment.
Post by Thorsten Wilms
What's the reason that Om can treat DSSIs only as monophonic nodes
again?
As far as I know there isn't a hard reason.
--
Lars Luthman
PGP key: http://www.student.nada.kth.se/~d00-llu/pgp_key.php
Fingerprint: FCA7 C790 19B9 322D EB7A E1B3 4371 4650 04C7 7E2E
Dave Robillard
2006-04-22 16:37:09 UTC
Permalink
Post by Thorsten Wilms
Post by Lars Luthman
I'm not sure that all of this belongs in LADSPA (the Simple Plugin
Architecture). DSSI has support for presets, MIDI in, GUIs and some
support for polyphony (you can run several plugin instances as a
polyphony group with a single call to run_multiple() which lets you do
common calculations once).
I was about generated GUIs, not plugin specific ones.
What's the reason that Om can treat DSSIs only as monophonic nodes
again?
Steve Harris
2006-04-22 17:10:45 UTC
Permalink
Post by Thorsten Wilms
Post by Lars Luthman
About referencing: isn't the port index the common way to identify
LADSPA ports?
Might be. A human readable, not to be translated english name per
port would be nice, though.
I dont see enough value to justify making plugin authors come up with a
neutral string that will never be displayed to users.

- Steve
fons adriaensen
2006-04-22 13:22:57 UTC
Permalink
Post by Lars Luthman
...
support for polyphony (you can run several plugin instances as a
polyphony group with a single call to run_multiple() which lets you do
common calculations once).
That's not the point. Even in that case each plugin instance does
all the calculations, while they should be able to share some.
--
FA

Follie! Follie! Delirio vano e' questo!
Steve Harris
2006-04-22 16:33:25 UTC
Permalink
Post by fons adriaensen
Plugin instances should be able to discover that they are
part of a group sharing control parameters. In many cases
the calculation of internal parameters from user supplied
ones and their interpolation takes more CPU than the rest
of the code. That work should be performed once in poly
setups.
Agreed. But I'd like to spec out a 2.0 that is no more capable than 1.1
first, then think about extensions seperatly. That sounds quite complex,
and I think its the sort of the DSSI addresses, as it has instancing and
polyphony control - at some level.
Post by fons adriaensen
The new syntax lools a lot cleaner than the existing system,
to the point that I'd support it :-)
Wow, praise indeed :)

- Steve
Steve Harris
2006-04-22 16:30:51 UTC
Permalink
Post by Thorsten Wilms
I'm not competent to comment on header files or implementation details.
But via Om, I'm a LADSPA power user and would like to bring up
some issues ;)
*gulp* ;)
Post by Thorsten Wilms
I would like to have an app, where I can put checkmarks to all plugins
and they will be fetched and installed (buidling from source / binaries
as option).
But just a way to get from the host not finding a plugin to the name
of the collection it's in would be nice already (so an app like Om can
not only say plugin-x not found, but also point to the package).
So... that is one thing that using RDF/web tech /can/ give you. eg. the
URI for the example plugin is http://plugin.org.uk/swh-plugins/amp/ if you
dereference that (ie. click on it ;) you will see some docs, but if you
use HTTP content negotiation and ask for it in Trutle you will get the RDF
description back, which /could/ have a machine readable bit telling you
where to get the package.

In combination with bundles that gives you the possibility to install
individual plugins.

It's a little bit sci-fi, but hopeful you can see that it's not too far
off.
Post by Thorsten Wilms
There are some plugins that will die if fed with values out of their
range (and this happens easily in a modular system). Maybe some mechanism
to protect against this could be build into the framework?
It would be 100% opposed to that. Plugins that crash when given odd values
are buggy (spec says they mustn't), and should be fixed. Use demolition,
report bugs.
Post by Thorsten Wilms
Having several variations of the same plugin to allow varying audio/
control rate port setups makes for unnecessary long plugin lists and
requires the user to delete and insert a different one, should he find
out some port should be audio, not control rate. Just look at the
sine oscillator(s) ...
The rate of a port should be switchable (at leat in all cases where
we have both versions now).
I might consider that for the future, but not for 2.0. I think its
important to get a more capable platform, before adding features.
Post by Thorsten Wilms
Hosts should be able to see, wether 2 ports are independent, or happen
to be a stereo pair (or any multi-channel setup).
Also a way to specify that things like frequency and amount ports of
an EQ form pairs might be nice. Should be helpful for generative plugin
GUIs.
This has been propsed using labels, eg "OSC 1/frequency" and "OSC
1/amplitude", that's an informal part of the spec IIRC. You could encode
it in RDF if you wanted to:

[ # port defintion
ladspa:index 1 ;
ladspa:label "frequency" ;
ladspa:inGroup <groupO1>
] , [
ladspa:index 1 ;
ladspa:label "frequency" ;
ladspa:inGroup <groupO1>
] .

<groupO1> ladspa:label "OSC 1" .

But I dint think it offers much more.
Post by Thorsten Wilms
Ports could have roles assigned to them, like signal_input, sidechain,
latency or bpm (the last for transport awareness and to make it possible
hosts assign values to it automaticaly).
Ugh. Maybe sometime in the future. That sounds hard to use. c.f. 2.0
plans.
Post by Thorsten Wilms
There needs to be a safe way to reference plugins and their ports.
Portnames make for human readable patch files, but this doesn't
work with i18n, when Attack becomes Einschwingzeit ;)
Plugins have URIs! And ports have uniqe identifying numbers within the
plugin. We could assign URIs to ports too, but I think thats going too
far.
Post by Thorsten Wilms
Maybe I just didn't see it, but shouldn't there be a hint for lists?
Like for plugins that have modes/presets?
Yes, there is, but I didnt show it in that example as the simple amp
doesnt need it. It looks like:

# ... inside port defn
ladspa:scalePoint [
ladspa:label "sine" ;
ladspa:value 0.0 .
], [
ladspa:label "square" ;
ladspa:value 1.0 .
], [
ladspa:label "saw" ;
ladspa:value 2.0 .
]
Post by Thorsten Wilms
Cross-host preset loading/saving.
Right, there are some obvious ways to do it. Later.
Post by Thorsten Wilms
A way to bring up a short discription of a plugin and what the
ports are about.
Just dereference the plugin URI as text/html or text/plain.
Post by Thorsten Wilms
MIDI/OSC
Don't know if the new LADSPAs should be able to handle MIDI/OSC,
but there should be plugins that do it ;)
DSSI. If this gets momentum retorfitting LADSPA 2 to DSSI will be easy. It
was designed with that in mind.
Post by Thorsten Wilms
There could be 1 or 2 (GTK, QT) libs for generative plugin GUIs,
for hosts not having to reinvent the wheel and for consistency.
Nope. Too hard, use the DSSI protocol.

- Steve
Dave Robillard
2006-04-22 17:06:26 UTC
Permalink
Post by Steve Harris
Post by Thorsten Wilms
There needs to be a safe way to reference plugins and their ports.
Portnames make for human readable patch files, but this doesn't
work with i18n, when Attack becomes Einschwingzeit ;)
Plugins have URIs! And ports have uniqe identifying numbers within the
plugin. We could assign URIs to ports too, but I think thats going too
far.
I'm not going to suggest ID numbers go away, but I do think ports should
have a uniquely identifying string label. Primary reason being OSC
control, and using plugins in language bindings (ie python) - both
things that are getting much more prevalent now than when LADSPA first
arrived.

Noone wants to set the frequency of an oscillator with the OSC message
"/set oscillator/4 440" when they could "/set oscillator/freq 440". Or
plugin.port(4).set_value(440) when it could be
plugin.port("frequency").set_value(440). Code (or OSC messages) using
plugin indexes as IDs is completely unreadable.

This is actually very important to me, I would very much like unique
port string ID's for the above reasons unless there's a good reason
there can't be.


-DR-
Steve Harris
2006-04-22 17:25:11 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
Post by Thorsten Wilms
There needs to be a safe way to reference plugins and their ports.
Portnames make for human readable patch files, but this doesn't
work with i18n, when Attack becomes Einschwingzeit ;)
Plugins have URIs! And ports have uniqe identifying numbers within the
plugin. We could assign URIs to ports too, but I think thats going too
far.
I'm not going to suggest ID numbers go away, but I do think ports should
have a uniquely identifying string label. Primary reason being OSC
control, and using plugins in language bindings (ie python) - both
things that are getting much more prevalent now than when LADSPA first
arrived.
OK, that's an argument I could buy. i'm still not completly convinced, but
it does make some sense.
Post by Dave Robillard
Noone wants to set the frequency of an oscillator with the OSC message
"/set oscillator/4 440" when they could "/set oscillator/freq 440". Or
plugin.port(4).set_value(440) when it could be
plugin.port("frequency").set_value(440). Code (or OSC messages) using
plugin indexes as IDs is completely unreadable.
This is actually very important to me, I would very much like unique
port string ID's for the above reasons unless there's a good reason
there can't be.
I guess you mean unique in plugin scope? It would also have to have some
restriction on what values it could take, eg. [a-zA-Z][a-zA-Z0-9_]+ some
kind of lowest common denominator between symbols for various languages
would make sense.

- Steve
Dave Robillard
2006-04-22 17:47:40 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
Post by Thorsten Wilms
There needs to be a safe way to reference plugins and their ports.
Portnames make for human readable patch files, but this doesn't
work with i18n, when Attack becomes Einschwingzeit ;)
Plugins have URIs! And ports have uniqe identifying numbers within the
plugin. We could assign URIs to ports too, but I think thats going too
far.
I'm not going to suggest ID numbers go away, but I do think ports should
have a uniquely identifying string label. Primary reason being OSC
control, and using plugins in language bindings (ie python) - both
things that are getting much more prevalent now than when LADSPA first
arrived.
OK, that's an argument I could buy. i'm still not completly convinced, but
it does make some sense.
It's not useful from the perspective of writing a LADSPA host in C, but
I think the above two (actual real world) examples of where port ID's
are user exposed are justification enough.
Post by Steve Harris
I guess you mean unique in plugin scope? It would also have to have some
restriction on what values it could take, eg. [a-zA-Z][a-zA-Z0-9_]+ some
kind of lowest common denominator between symbols for various languages
would make sense.
Yeah, just unique to the plugin. (Though I guess that would imply the
port could have a URI like pluginuri/porturi but whatever).

I think the regexp you mentioned there is fine, though I think we should
add one separator character other than underscore for various reasons.
":" maybe?

As a side effect of this, what is now "label" should become
"description" and implicitly be Nice Human Readable Text, not
ugly_c_looking_identifiers (and units definitely need to be seperated).
"Description" is metadata though, so I guess it doesn't belong in the C
file.

-DR-
Steve Harris
2006-04-22 18:20:50 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
I guess you mean unique in plugin scope? It would also have to have some
restriction on what values it could take, eg. [a-zA-Z][a-zA-Z0-9_]+ some
kind of lowest common denominator between symbols for various languages
would make sense.
Yeah, just unique to the plugin. (Though I guess that would imply the
port could have a URI like pluginuri/porturi but whatever).
You could do pluginUri#portShortName, it's a fairly common convention (eg.
in HTML). But youre only allowed a small set of characters after the #.
Post by Dave Robillard
I think the regexp you mentioned there is fine, though I think we should
add one separator character other than underscore for various reasons.
":" maybe?
I'd rather not, I'm not sure its legal in Pd (they get bitten by the port
name thing too), and its not in C. Pure selfinterest, but My LADSPA code
is about 50% generated from XML, and I use short names internally for C
symbols.
Post by Dave Robillard
As a side effect of this, what is now "label" should become
"description" and implicitly be Nice Human Readable Text, not
ugly_c_looking_identifiers (and units definitely need to be seperated).
"Description" is metadata though, so I guess it doesn't belong in the C
file.
The C now only contains the function pointers, a vector of float pointers
and a URI char *. All this stuff belongs outside.

- Steve
Dave Robillard
2006-04-22 18:47:33 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
I guess you mean unique in plugin scope? It would also have to have some
restriction on what values it could take, eg. [a-zA-Z][a-zA-Z0-9_]+ some
kind of lowest common denominator between symbols for various languages
would make sense.
Yeah, just unique to the plugin. (Though I guess that would imply the
port could have a URI like pluginuri/porturi but whatever).
You could do pluginUri#portShortName, it's a fairly common convention (eg.
in HTML). But youre only allowed a small set of characters after the #.
Post by Dave Robillard
I think the regexp you mentioned there is fine, though I think we should
add one separator character other than underscore for various reasons.
":" maybe?
I'd rather not, I'm not sure its legal in Pd (they get bitten by the port
name thing too), and its not in C. Pure selfinterest, but My LADSPA code
is about 50% generated from XML, and I use short names internally for C
symbols.
Well, at least one kind of separator character is required (for big
plugins). If it can't be ":", then I don't know what, but there needs
to be something. Maybe "."? If you want to keep it as a valid C
identifier I guess we're pretty much screwed, aside from defining __ to
be interpreted as a sort of heirarchialish separator.

master_amp:vol
master_amp.vol
master_amp__vol

"." is definitely prettiest... is there anything other than "__" we can
use that's as safe?
Post by Steve Harris
Post by Dave Robillard
As a side effect of this, what is now "label" should become
"description" and implicitly be Nice Human Readable Text, not
ugly_c_looking_identifiers (and units definitely need to be seperated).
"Description" is metadata though, so I guess it doesn't belong in the C
file.
The C now only contains the function pointers, a vector of float pointers
and a URI char *. All this stuff belongs outside.
I'm fully in support of putting any and all metadata outside the C file,
but the unique identifier isn't metadata, it should be in the code. A
trivial OSC controlled plugin host (which would make a good bundled
example client for the SDK) would need it.

-DR-
Steve Harris
2006-04-22 20:10:08 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
You could do pluginUri#portShortName, it's a fairly common convention (eg.
in HTML). But youre only allowed a small set of characters after the #.
Post by Dave Robillard
I think the regexp you mentioned there is fine, though I think we should
add one separator character other than underscore for various reasons.
":" maybe?
I'd rather not, I'm not sure its legal in Pd (they get bitten by the port
name thing too), and its not in C. Pure selfinterest, but My LADSPA code
is about 50% generated from XML, and I use short names internally for C
symbols.
Well, at least one kind of separator character is required (for big
plugins). If it can't be ":", then I don't know what, but there needs
to be something. Maybe "."? If you want to keep it as a valid C
identifier I guess we're pretty much screwed, aside from defining __ to
be interpreted as a sort of heirarchialish separator.
I'm missing the need for heirachicalness. : is probably not safe in OSC
either.
Post by Dave Robillard
I'm fully in support of putting any and all metadata outside the C file,
but the unique identifier isn't metadata, it should be in the code. A
trivial OSC controlled plugin host (which would make a good bundled
example client for the SDK) would need it.
It's only /a/ unique identifier. We can't loose the index number as thats
the efficent way you access the LADSPA_Data pointers. Only one can be
canonical.

- Steve
Dave Robillard
2006-04-22 20:48:28 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
You could do pluginUri#portShortName, it's a fairly common convention (eg.
in HTML). But youre only allowed a small set of characters after the #.
Post by Dave Robillard
I think the regexp you mentioned there is fine, though I think we should
add one separator character other than underscore for various reasons.
":" maybe?
I'd rather not, I'm not sure its legal in Pd (they get bitten by the port
name thing too), and its not in C. Pure selfinterest, but My LADSPA code
is about 50% generated from XML, and I use short names internally for C
symbols.
Well, at least one kind of separator character is required (for big
plugins). If it can't be ":", then I don't know what, but there needs
to be something. Maybe "."? If you want to keep it as a valid C
identifier I guess we're pretty much screwed, aside from defining __ to
be interpreted as a sort of heirarchialish separator.
I'm missing the need for heirachicalness. : is probably not safe in OSC
either.
voice_1_osc_1_volume
voice_2_osc_3_volume

Or metaplugins (which ability to load libraries will surely spawn).

subplug_1_param1
subplug_2_param4

... ugh

voice_1.osc_1.volume

... oh so much nicer. There already exists a few DSSI plugins with
ports like this. Surely there's got to be /one/ more sensible character
we can add? (It needs to be valid as a jack port name as well)
Post by Steve Harris
Post by Dave Robillard
I'm fully in support of putting any and all metadata outside the C file,
but the unique identifier isn't metadata, it should be in the code. A
trivial OSC controlled plugin host (which would make a good bundled
example client for the SDK) would need it.
It's only /a/ unique identifier. We can't loose the index number as thats
the efficent way you access the LADSPA_Data pointers. Only one can be
canonical.
I think the above case of a trivial C host requiring it is justification
enough to have it in the code. Think about an engine/client split
system (where the engine might be something that doesn't have the
resources to load metadata and parse RDF etc, eg a DSP). The metadata
would be client-side, but the plugin engine-side, so the engine needs
access to the label in order to provide the nicer (eg) OSC namespace.

Not having it in the code makes a device like this impossible (think
Nord Modular or Plugzilla). That'd be a shame ;)


-DR-
Luis Garrido
2006-04-22 21:43:07 UTC
Permalink
It is good (tm) to define broad standards that encompass a variety of
situations. But usually broad means also thin, which results in it
being less helpful for each specific situation it pretends to be
applied to.

And no matter how broad you try to make it, I bet someone comes up
with a feature that is absolutely essential for his/her purposes that
the standard should cover but fails to.

How broad do we want it? Wouldn't it be a good idea to survey what
people are doing with LADSPA and what are they missing in it?

Personally, I don't need any more modular synths, thanks.

I miss the most in LADSPA:
- Sensible GUIs.
-
Dave Robillard
2006-04-22 22:31:29 UTC
Permalink
Post by Luis Garrido
It is good (tm) to define broad standards that encompass a variety of
situations. But usually broad means also thin, which results in it
being less helpful for each specific situation it pretends to be
applied to.
And no matter how broad you try to make it, I bet someone comes up
with a feature that is absolutely essential for his/her purposes that
the standard should cover but fails to.
How broad do we want it? Wouldn't it be a good idea to survey what
people are doing with LADSPA and what are they missing in it?
Personally, I don't need any more modular synths, thanks.
I'm going to assume this is a shot at me for rather obvious reasons.
Since you must know, my thoughts are mostly with Ardour, which will soon
be OSC controlled. You may have noticed that Ardour isn't a modular
synth. Fancy that.
Post by Luis Garrido
- Sensible GUIs.
*sigh* someone just had to do it, didn't they?

We don't need another inifinitely long GUI toolkit pissing match thread
that is guaranteed to lead absolutely nowhere, thanks.

LAD_S_PA2 is not going to have GUIs. http://dssi.sf.net. Enjoy.

Now can we please have a productive discussion about fixing very real
problems with LADSPA without /that/ *&%$% topic ruining everything, yet
again, thanks?

-DR-
Luis Garrido
2006-04-22 23:10:34 UTC
Permalink
Post by Dave Robillard
I'm going to assume this is a shot at me for rather obvious reasons.
No, I was more thinking in Phil Frost's contribution to this
discussion (contribution that I find very interesting and pertinent,
but as a musician I am not interested in LADSPA becoming another low
level LEGO api to build modular synths, there are already some good
solutions to that problem).
Post by Dave Robillard
*sigh* someone just had to do it, didn't they?
GUIs appeared in the thread long before my post.
Post by Dave Robillard
LAD_S_PA2 is not going to have GUIs. http://dssi.sf.net. Enjoy.
I am well aware of that. Thanks for the pointer, anyway.

http://flam.sf.net

But still there are some parts of LADSPA that have to provide
information for effective (auto)building of GUIs.
Post by Dave Robillard
Now can we please have a productive discussion about fixing very real
problems with LADSPA without /that/ *&%$% topic ruining everything, yet
again, thanks?
My apologies for bothering you. I will just return silently to my
playground
Dave Robillard
2006-04-22 23:35:42 UTC
Permalink
Post by Luis Garrido
Post by Dave Robillard
I'm going to assume this is a shot at me for rather obvious reasons.
No, I was more thinking in Phil Frost's contribution to this
discussion (contribution that I find very interesting and pertinent,
but as a musician I am not interested in LADSPA becoming another low
level LEGO api to build modular synths, there are already some good
solutions to that problem).
My apologies then. I've become accustomed to knee-jerk anti modular
reactions whenever I use anything remotely modular as an example for
something. :)

Frankly I don't understand the phenomenon at all, your comments are a
perfect example. The source code idea would mostly be beneficial for
building stand-alone static (ie non modular) synths. The UI
for /creating/ them would be modular probably, since that's really the
only really reasonable UI for doing so, but it wouldn't /have/ to be.

Yet, you say the word "modular" and the idea is automatically cast aside
by everyone. You make the exact same point without saying the magic M
word, and my, what an interesting idea!

I Don't Get It(TM), but whatever. I suppose it's like math, non math
people see one Sigma and their brains just turn off immediately.

I just make sure not to say the magic M word wherever possible to avoid
it. ;)

[/digression]
Post by Luis Garrido
Post by Dave Robillard
*sigh* someone just had to do it, didn't they?
GUIs appeared in the thread long before my post.
Post by Dave Robillard
LAD_S_PA2 is not going to have GUIs. http://dssi.sf.net. Enjoy.
I am well aware of that. Thanks for the pointer, anyway.
http://flam.sf.net
But still there are some parts of LADSPA that have to provide
information for effective (auto)building of GUIs.
I am of the opinion that auto generated UIs is not the way to go in
general, but regardless that's the beauty of external metadata. You can
experiment with whatever added data you like, if it works well people
will start using it and it might become part of the standard eventually.

LADSPA has long been hindered by the draconian pre-defined nature of C
ABIs. With rigorously seperated metadata we'll finally be able to
experiment with things like this without breaking things and LADSPA can
evolve...

-DR-
Steve Harris
2006-04-23 06:56:16 UTC
Permalink
Post by Luis Garrido
- Sensible GUIs.
- Tempo awareness.
I should have been clear before, but I'm not interested in adding more
features to LADSPA, right now. I want to replace the cruft-filled C ABI
metadata system with something generic. Ideally I would like LADSPA 2.0 to
be exactly as capable as LADSPA 1.1. There are some things that need ABI
changes, but lets minime that.

Once LADSPA 2.0 has been finalised, extensions can be tried, and
eventaully added without changing 2.0.

- Steve
Steve Harris
2006-04-23 06:53:19 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
Well, at least one kind of separator character is required (for big
plugins). If it can't be ":", then I don't know what, but there needs
to be something. Maybe "."? If you want to keep it as a valid C
identifier I guess we're pretty much screwed, aside from defining __ to
be interpreted as a sort of heirarchialish separator.
I'm missing the need for heirachicalness. : is probably not safe in OSC
either.
voice_1_osc_1_volume
voice_2_osc_3_volume
That looks fine to me...
Post by Dave Robillard
Or metaplugins (which ability to load libraries will surely spawn).
subplug_1_param1
subplug_2_param4
... ugh
voice_1.osc_1.volume
Hum, that looks suspiciously like its expressing some semantics that don't
exist to me, and could potentially conflict with the port name (UI)
semantics "Osc 1/Frequency" etc.
Post by Dave Robillard
... oh so much nicer. There already exists a few DSSI plugins with
ports like this. Surely there's got to be /one/ more sensible character
we can add? (It needs to be valid as a jack port name as well)
But you're not talking about anything hard, its just a symbol name, used
to refer to the port, sometimes... I'm starting to go off this idea, noone
else has spoken in defense of it, and it raises some issues.
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
I'm fully in support of putting any and all metadata outside the C file,
but the unique identifier isn't metadata, it should be in the code. A
trivial OSC controlled plugin host (which would make a good bundled
example client for the SDK) would need it.
It's only /a/ unique identifier. We can't loose the index number as thats
the efficent way you access the LADSPA_Data pointers. Only one can be
canonical.
I think the above case of a trivial C host requiring it is justification
enough to have it in the code. Think about an engine/client split
system (where the engine might be something that doesn't have the
resources to load metadata and parse RDF etc, eg a DSP). The metadata
would be client-side, but the plugin engine-side, so the engine needs
access to the label in order to provide the nicer (eg) OSC namespace.
It would use the index numbers. DSP chips and trivial C hosts are not going
to strcmp() to match ports up. You can't run a LADSPA2 plugin without some
part of the system being able to parse some data anyway, because you dont
know what the ports are for. It's OK, the host CPU can do it, and pass the
information to the DSP chip.

- Steve
Dave Robillard
2006-04-23 15:25:59 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
Well, at least one kind of separator character is required (for big
plugins). If it can't be ":", then I don't know what, but there needs
to be something. Maybe "."? If you want to keep it as a valid C
identifier I guess we're pretty much screwed, aside from defining __ to
be interpreted as a sort of heirarchialish separator.
I'm missing the need for heirachicalness. : is probably not safe in OSC
either.
voice_1_osc_1_volume
voice_2_osc_3_volume
That looks fine to me...
Post by Dave Robillard
Or metaplugins (which ability to load libraries will surely spawn).
subplug_1_param1
subplug_2_param4
... ugh
voice_1.osc_1.volume
Hum, that looks suspiciously like its expressing some semantics that don't
exist to me, and could potentially conflict with the port name (UI)
semantics "Osc 1/Frequency" etc.
Post by Dave Robillard
... oh so much nicer. There already exists a few DSSI plugins with
ports like this. Surely there's got to be /one/ more sensible character
we can add? (It needs to be valid as a jack port name as well)
But you're not talking about anything hard, its just a symbol name, used
to refer to the port, sometimes... I'm starting to go off this idea, noone
else has spoken in defense of it, and it raises some issues.
*shrug* All I want is one character that would be useful for organizing
port names in a much nicer looking fashion. I can live without if it's
really a big deal and there's no safe character, it'd just make for much
nicer looking port names on complicated plugins is all. Dropped.
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
I'm fully in support of putting any and all metadata outside the C file,
but the unique identifier isn't metadata, it should be in the code. A
trivial OSC controlled plugin host (which would make a good bundled
example client for the SDK) would need it.
It's only /a/ unique identifier. We can't loose the index number as thats
the efficent way you access the LADSPA_Data pointers. Only one can be
canonical.
I think the above case of a trivial C host requiring it is justification
enough to have it in the code. Think about an engine/client split
system (where the engine might be something that doesn't have the
resources to load metadata and parse RDF etc, eg a DSP). The metadata
would be client-side, but the plugin engine-side, so the engine needs
access to the label in order to provide the nicer (eg) OSC namespace.
It would use the index numbers. DSP chips and trivial C hosts are not going
to strcmp() to match ports up. You can't run a LADSPA2 plugin without some
part of the system being able to parse some data anyway, because you dont
know what the ports are for. It's OK, the host CPU can do it, and pass the
information to the DSP chip.
It wouldn't use the index numbers if it wants to provide the sensible
OSC namespace (as for strcmp you can do the symbol thing w/ (perfect)
hashing to make it fast). Ditto for a language providing a sensible
API. The label is not metadata, it is a unique identifier.

But anyway, why can't it go in the code? I want to keep the C part
minimal as well, but this is a unique identifier, the sole thing that
actually does belong in the code. I need this to create an app/device
like the above. What's the better reason it's a bad idea? Plugins have
a unique string ID, and I need ports to as well.

If any LADSPA devs are opposed (or not) to giving each port a unique
label in the code, feel free weigh in...

-DR-
Steve Harris
2006-04-23 18:23:15 UTC
Permalink
Post by Dave Robillard
But anyway, why can't it go in the code? I want to keep the C part
minimal as well, but this is a unique identifier, the sole thing that
actually does belong in the code. I need this to create an app/device
like the above. What's the better reason it's a bad idea? Plugins have
a unique string ID, and I need ports to as well.
Theres no advantage to it being in the code, it means allocating an array
of strings, which means repeating the same code in every plugin. Also, you
can't get the strings unless you load and link the plugin, which is one of
the things were trying to get away from.

- Steve
Dave Robillard
2006-04-23 19:45:05 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
But anyway, why can't it go in the code? I want to keep the C part
minimal as well, but this is a unique identifier, the sole thing that
actually does belong in the code. I need this to create an app/device
like the above. What's the better reason it's a bad idea? Plugins have
a unique string ID, and I need ports to as well.
Theres no advantage to it being in the code, it means allocating an array
of strings, which means repeating the same code in every plugin. Also, you
can't get the strings unless you load and link the plugin, which is one of
the things were trying to get away from.
The advantage is the mentioned use case which your suggestion destroys.
The array can be static anyway, there's not really any "code" added.

Are you proposing to put the port index numbers in the metadata as well?
Otherwise you couldn't get at them without loading and linking the
plugin.

So the plugin URI should exclusively go in the metadata file as well?
Why is that in the code?

-DR-
Steve Harris
2006-04-23 18:39:52 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
But anyway, why can't it go in the code? I want to keep the C part
minimal as well, but this is a unique identifier, the sole thing that
actually does belong in the code. I need this to create an app/device
like the above. What's the better reason it's a bad idea? Plugins have
a unique string ID, and I need ports to as well.
Theres no advantage to it being in the code, it means allocating an array
of strings, which means repeating the same code in every plugin. Also, you
can't get the strings unless you load and link the plugin, which is one of
the things were trying to get away from.
The advantage is the mentioned use case which your suggestion destroys.
The array can be static anyway, there's not really any "code" added.
I don't see how it affects the usecase. You /always/ need to read at least
some of the data somehwere to use the plugin.
Post by Dave Robillard
Are you proposing to put the port index numbers in the metadata as well?
Otherwise you couldn't get at them without loading and linking the
plugin.
Of course, it's ladspa:index if the numbers aren't there then theres
nothing to link the port data to the float *.
Post by Dave Robillard
So the plugin URI should exclusively go in the metadata file as well?
Why is that in the code?
It has to be in the struct, otherwise you don't know what functions to
call to get a particular plugin.

- Steve
Dave Robillard
2006-04-23 20:26:03 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
But anyway, why can't it go in the code? I want to keep the C part
minimal as well, but this is a unique identifier, the sole thing that
actually does belong in the code. I need this to create an app/device
like the above. What's the better reason it's a bad idea? Plugins have
a unique string ID, and I need ports to as well.
Theres no advantage to it being in the code, it means allocating an array
of strings, which means repeating the same code in every plugin. Also, you
can't get the strings unless you load and link the plugin, which is one of
the things were trying to get away from.
The advantage is the mentioned use case which your suggestion destroys.
The array can be static anyway, there's not really any "code" added.
I don't see how it affects the usecase. You /always/ need to read at least
some of the data somehwere to use the plugin.
Well, the plugin should be at least runnable without the metadata. Sure
you'll know almost nothing about it, but you should be able to run it
(eg in fixed code where you know the parameters and whatnot you're using
are fine). (No user interacting app could feasibly do so though)

The "somewhere" part is my point. This 'device' can not read metadata
files, yet it needs to know the port IDs. Therefore the port IDs need
to be in the code.
Post by Steve Harris
Post by Dave Robillard
Are you proposing to put the port index numbers in the metadata as well?
Otherwise you couldn't get at them without loading and linking the
plugin.
Of course, it's ladspa:index if the numbers aren't there then theres
nothing to link the port data to the float *.
Post by Dave Robillard
So the plugin URI should exclusively go in the metadata file as well?
Why is that in the code?
It has to be in the struct, otherwise you don't know what functions to
call to get a particular plugin.
In other words it's there because it's a unique identifier for the
plugin, used to reference it. I say port IDs need to be there for the
same reason. Ports should be first class citizens with a proper
identifier and all, IMO.

Anyway, putting IDs in the metadata implies that, well, they're
metadata, and can be fiddled with without breaking things. This is not
true. They are unique identifiers (along with their plugin's URIs they
define a URI) and as such are set in stone and must not change. They're
just not metadata.

But I want to emphasize the 'device' (or trivial host app, etc) over
arguments about word definitions etc. I really don't want to have to
fork LADSPA into an ABI incompatible derivative over something silly
like this.

-DR-
Steve Harris
2006-04-23 21:37:32 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
The advantage is the mentioned use case which your suggestion destroys.
The array can be static anyway, there's not really any "code" added.
I don't see how it affects the usecase. You /always/ need to read at least
some of the data somehwere to use the plugin.
Well, the plugin should be at least runnable without the metadata. Sure
you'll know almost nothing about it, but you should be able to run it
(eg in fixed code where you know the parameters and whatnot you're using
are fine). (No user interacting app could feasibly do so though)
Sure, but that doesn't require you to be able to load the shortnames from
the plugin binary.
Post by Dave Robillard
The "somewhere" part is my point. This 'device' can not read metadata
files, yet it needs to know the port IDs. Therefore the port IDs need
to be in the code.
It can't speak OSC either, so the integers are just fine.
Post by Dave Robillard
Post by Steve Harris
It has to be in the struct, otherwise you don't know what functions to
call to get a particular plugin.
In other words it's there because it's a unique identifier for the
plugin, used to reference it. I say port IDs need to be there for the
same reason. Ports should be first class citizens with a proper
identifier and all, IMO.
They are, they have integers. The integers map to something very real in
the plugin structure. Shortnames are just shortnames, you can't map them
to ports unless they appear in the external data or you load and link the
plugin.
Post by Dave Robillard
Anyway, putting IDs in the metadata implies that, well, they're
metadata, and can be fiddled with without breaking things. This is not
true. They are unique identifiers (along with their plugin's URIs they
define a URI) and as such are set in stone and must not change. They're
just not metadata.
Please dont use the word metadata, it's confusing, what's meta depends on
your context. Not all the data can be fiddled with without breaking
things. If you change the URI all your presets will stop working, if you
change the port indexes then the structure of the plugin changes, etc.

- Steve
Dave Robillard
2006-04-23 22:40:32 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
Post by Dave Robillard
But anyway, why can't it go in the code? I want to keep the C part
minimal as well, but this is a unique identifier, the sole thing that
actually does belong in the code. I need this to create an app/device
like the above. What's the better reason it's a bad idea? Plugins have
a unique string ID, and I need ports to as well.
Theres no advantage to it being in the code, it means allocating an array
of strings, which means repeating the same code in every plugin. Also, you
can't get the strings unless you load and link the plugin, which is one of
the things were trying to get away from.
The advantage is the mentioned use case which your suggestion destroys.
The array can be static anyway, there's not really any "code" added.
I don't see how it affects the usecase. You /always/ need to read at least
some of the data somehwere to use the plugin.
Well, the plugin should be at least runnable without the metadata. Sure
you'll know almost nothing about it, but you should be able to run it
(eg in fixed code where you know the parameters and whatnot you're using
are fine). (No user interacting app could feasibly do so though)
The "somewhere" part is my point. This 'device' can not read metadata
files, yet it needs to know the port IDs. Therefore the port IDs need
to be in the code.
Post by Steve Harris
Post by Dave Robillard
Are you proposing to put the port index numbers in the metadata as well?
Otherwise you couldn't get at them without loading and linking the
plugin.
Of course, it's ladspa:index if the numbers aren't there then theres
nothing to link the port data to the float *.
Post by Dave Robillard
So the plugin URI should exclusively go in the metadata file as well?
Why is that in the code?
It has to be in the struct, otherwise you don't know what functions to
call to get a particular plugin.
In other words it's there because it's a unique identifier for the
plugin, used to reference it. I say port IDs need to be there for the
same reason. Ports should be first class citizens with a proper
identifier and all, IMO.
Anyway, putting IDs in the metadata implies that, well, they're
metadata, and can be fiddled with without breaking things. This is not
true. They are unique identifiers (along with their plugin's URIs they
define a URI) and as such are set in stone and must not change. They're
just not metadata.
But I want to emphasize the 'device' (or trivial host app, etc) over
arguments about word definitions etc. I really don't want to have to
fork LADSPA into an ABI incompatible derivative over something silly
like this.
For the sake of the record, it's been duked out on IRC and Steve
wins :). (Specifically, ports will be required to have a unique string
ID, but it will live in the data file, not the code).

The RDF file is required to run the plugin anyway, since port type and
direction etc. is contained there, making my argument about keeping the
data file parsing off the 'server side' invalid.

The data file is not a "metadata" file, it's required to execute the
plugin at all (and I fully agree with this now, even if it does throw a
bit of a monkey wrench in some embedded development plans of mine; it's
for the greater good....)

-DR-
Steve Harris
2006-04-24 07:57:57 UTC
Permalink
Post by Dave Robillard
For the sake of the record, it's been duked out on IRC and Steve
wins :). (Specifically, ports will be required to have a unique string
ID, but it will live in the data file, not the code).
Actually I didn't mean to say that they /will/ be required, just that I
don't have a problem with it. I've not heard anyone else speak in favour
of this, and it is a feature. If theres a critical mass of support I'm OK
with adding it, as it should make the lives of some hosts much easier.

At the risk of upsetting Dave, it can be added a a 3rd party extension
without anything really bad happening. It just means that the Pd messages
/ OSC paths / whatever for some plugins will be ugly. "Market pressure"
will ensire that all plugins support it if its useful to enough users.

- Steve
Dave Robillard
2006-04-24 12:58:07 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
For the sake of the record, it's been duked out on IRC and Steve
wins :). (Specifically, ports will be required to have a unique string
ID, but it will live in the data file, not the code).
Actually I didn't mean to say that they /will/ be required, just that I
don't have a problem with it. I've not heard anyone else speak in favour
of this, and it is a feature. If theres a critical mass of support I'm OK
with adding it, as it should make the lives of some hosts much easier.
At the risk of upsetting Dave, it can be added a a 3rd party extension
without anything really bad happening. It just means that the Pd messages
/ OSC paths / whatever for some plugins will be ugly. "Market pressure"
will ensire that all plugins support it if its useful to enough users.
Not so much a new feature as a clearer definition of existing things
(port labels).

It's a "feature" perhaps, but just something that needs to be defined in
the data file. The features we need to avoid here are ones that mess
with the code IMO. There are a few new bits of data that experience has
shown we need to add to the data file (not mandatory like this one, just
possible keys). Given how easy and un-breakey it is to do so (which is
the entire point of doing this after all), we should take advantage.

Anyway, at this point that's not very important, just definition of
possible keys in the data file. We can discuss those once we're sure
the code side of things (and existing data bits) is sound.

-DR-
Steve Harris
2006-04-24 14:53:54 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
At the risk of upsetting Dave, it can be added a a 3rd party extension
without anything really bad happening. It just means that the Pd messages
/ OSC paths / whatever for some plugins will be ugly. "Market pressure"
will ensire that all plugins support it if its useful to enough users.
Anyway, at this point that's not very important, just definition of
possible keys in the data file. We can discuss those once we're sure
the code side of things (and existing data bits) is sound.
Yep. Seems reasonable.

- Steve
tom christie
2006-04-24 16:21:58 UTC
Permalink
I've been following the LAD mailing list for a while now,
mostly to keep an eye the development of LADSPA.
Now seems an appropriate time to voice my thoughts.


Separating out the metadata is certainly (IMHO) the right thing to do,
(I think Steve's proposal is a great step forward)
It mitigates the problem of making LADSPA easily extensible by moving
as much information as possible out of the fixed binary format.
However the problem remains that the core API still cannot be
extended without breaking backwards compatibility.

Surely with LADSPA 2.0 it's time to change the struct based API
to a library call based API.


# ie. the currently proposed API looks like...

ladspa_descriptor(index)

descriptor {
uri
port_count
implementation_data
instantiate(descriptor, ...)

connect_port(instance, ...)
activate(instance)
run(instance, ...)
deactivate(instance)
cleanup(instance)
}


# a function call based API would look like...

ladspa2_descriptor(index)

uri(descriptor)
port_count(descriptor)
instantiate(descriptor, ...)

connect_port(instance, ...)
activate(instance)
run(instance, ...)
deactivate(instance)
cleanup(instance)


In the former, any change in the descriptor structure will always break
backwards compatibility.
In the later, new functions can extend the core functionality without
breaking backwards compatibility in any way.


I'd be very interested in hearing people's opinions on this.

Regards,

Tom
Jesse Chappell
2006-04-24 20:12:11 UTC
Permalink
Post by tom christie
In the former, any change in the descriptor structure will always break
backwards compatibility.
In the later, new functions can extend the core functionality without
breaking backwards compatibility in any way.
Actually, just adding a large-ish chunk of reserved padding at the end
of the descriptor struct can accomplish the same goal, as long as you
are only adding new functions to the API. That, along with a version
field also in the struct.

jlc
Steve Harris
2006-04-25 08:46:46 UTC
Permalink
Post by Jesse Chappell
Post by tom christie
In the former, any change in the descriptor structure will always break
backwards compatibility.
In the later, new functions can extend the core functionality without
breaking backwards compatibility in any way.
Actually, just adding a large-ish chunk of reserved padding at the end
of the descriptor struct can accomplish the same goal, as long as you
are only adding new functions to the API. That, along with a version
field also in the struct.
The pluin is responsibe for allocating the descriptor, so its not
neccesary to add padding.

- Steve
tom christie
2006-04-25 10:28:47 UTC
Permalink
Okay, I ought to have qualified my 'will always break...' that's
clearly not true.
But there is still real inflexibility in using a struct based API.

eg. Say a developer comes up with a nice extension (perhaps to allow a
plugin to deal with multi-channel IO / non-causal audio effects /
alter the audio frequency / support an 'end of stream' marker / midi /
GUI / accessing metadata via function calls / or whatever...)

With the struct based API the only way(*) for that extension to make
it into LADSPA is for it to be part of the the struct in the next
version of LADSPA. We want to keep LADSPA simple, so that's unlikely
to happen.

With the library call based API the developer defines and advertises
the functions that make up the extension, and if it is useful hosts
will start to implement it. If it proves it's worth it can be adopted
as an official LADSPA *extension*, which hosts can choose (or not) to
implement.

The core API remains simple and unbloated, but LADSPA can still develop.

(*) Yes there is trickery that could be played with, eg. using
multiple discovery functions, but that's just icky.
Steve Harris
2006-04-25 11:59:26 UTC
Permalink
Sorry, I just dont feel that motivated by this. We have a bunch of code
and experience around the struct format, and we know were going to need
something equivalent for the forseeable future, so I dont see the point in
changing it over just for the sake of it.

Sure, for some possible future ABI-incomaptible extension we might want to
add functions, but equally we might not.

- Steve
Post by tom christie
Okay, I ought to have qualified my 'will always break...' that's
clearly not true.
But there is still real inflexibility in using a struct based API.
eg. Say a developer comes up with a nice extension (perhaps to allow a
plugin to deal with multi-channel IO / non-causal audio effects /
alter the audio frequency / support an 'end of stream' marker / midi /
GUI / accessing metadata via function calls / or whatever...)
With the struct based API the only way(*) for that extension to make
it into LADSPA is for it to be part of the the struct in the next
version of LADSPA. We want to keep LADSPA simple, so that's unlikely
to happen.
With the library call based API the developer defines and advertises
the functions that make up the extension, and if it is useful hosts
will start to implement it. If it proves it's worth it can be adopted
as an official LADSPA *extension*, which hosts can choose (or not) to
implement.
The core API remains simple and unbloated, but LADSPA can still develop.
(*) Yes there is trickery that could be played with, eg. using
multiple discovery functions, but that's just icky.
tom christie
2006-04-25 16:40:59 UTC
Permalink
Post by Steve Harris
Sorry, I just dont feel that motivated by this.
No problem :) just wanted to know if anyone else thought it was an
important point.


Two other concerns...


A) There is no built-in way of a host distinguishing between a LADSPA
1.1 and a LADSPA 2.x plugin. (Unless I'm missing something?)


Would it make sense to change the name of the discovery function?
eg... ladspa2_descriptor() instead of ladspa_descriptor()

That way there's no chance of a 2.0 host thinking it has a 2.0 plugin
when in fact it has a 1.1 plugin. (Or vice versa with a 1.1 host)
Either case would cause the host to crash when it calls the
instantiate() function.


B) There is no way of a host distinguishing between a LADSPA 2.x and a
LADSPA 2.y plugin.

Would it make sense for the initial few bytes of the struct to
explicitly declare that this really is a LADSPA struct and give the
major and minor versions for which it was written? This would allow
the struct to change in the future if neccessary without breaking
things and without needing to change the name of the discovery
function again.

char ladspa_string[7]; // plugin must set this to "LADSPA\0"
unsigned short major_version; // plugin must set this to 2
unsigned short minor_version; // plugin must set this to 0

The host should check for the null terminated "LADSPA" string, and
should ensure that it's version is less than or equal that which the
host supports before attempting to access the plugin.


thoughts?...
Post by Steve Harris
Sorry, I just dont feel that motivated by this. We have a bunch of code
and experience around the struct format, and we know were going to need
something equivalent for the forseeable future, so I dont see the point in
changing it over just for the sake of it.
Sure, for some possible future ABI-incomaptible extension we might want to
add functions, but equally we might not.
- Steve
Post by tom christie
Okay, I ought to have qualified my 'will always break...' that's
clearly not true.
But there is still real inflexibility in using a struct based API.
eg. Say a developer comes up with a nice extension (perhaps to allow a
plugin to deal with multi-channel IO / non-causal audio effects /
alter the audio frequency / support an 'end of stream' marker / midi /
GUI / accessing metadata via function calls / or whatever...)
With the struct based API the only way(*) for that extension to make
it into LADSPA is for it to be part of the the struct in the next
version of LADSPA. We want to keep LADSPA simple, so that's unlikely
to happen.
With the library call based API the developer defines and advertises
the functions that make up the extension, and if it is useful hosts
will start to implement it. If it proves it's worth it can be adopted
as an official LADSPA *extension*, which hosts can choose (or not) to
implement.
The core API remains simple and unbloated, but LADSPA can still develop.
(*) Yes there is trickery that could be played with, eg. using
multiple discovery functions, but that's just icky.
Lars Luthman
2006-04-25 16:58:18 UTC
Permalink
Post by tom christie
A) There is no built-in way of a host distinguishing between a LADSPA
1.1 and a LADSPA 2.x plugin. (Unless I'm missing something?)
Would it make sense to change the name of the discovery function?
eg... ladspa2_descriptor() instead of ladspa_descriptor()
That makes sense to me. You could of course say that all LADSPA2
plugins/bundles/directories should be stored in different directories
from LADSPA1 (e.g. /usr/lib/ladspa2 instead of /usr/lib/ladspa) but
since the user is free to set $LADSPA_PATH to whatever he wants and
hosts are free to search whatever directories they want that wouldn't be
a very stable solution. Having a separate discovery function is a good
idea.
Post by tom christie
B) There is no way of a host distinguishing between a LADSPA 2.x and a
LADSPA 2.y plugin.
Would it make sense for the initial few bytes of the struct to
explicitly declare that this really is a LADSPA struct and give the
major and minor versions for which it was written? This would allow
the struct to change in the future if neccessary without breaking
things and without needing to change the name of the discovery
function again.
char ladspa_string[7]; // plugin must set this to "LADSPA\0"
unsigned short major_version; // plugin must set this to 2
unsigned short minor_version; // plugin must set this to 0
I don't think that the string is needed - if the host got the descriptor
from a ladspa2_descriptor() discovery function, that should be enough to
be sure that it is a LADSPA2 descriptor. A version number might be good
though - even if the goal is to add extensions without breaking the ABI
it could still be necessary to break it at some point in the future. One
version number should be enough though, and it doesn't have to match the
actual version of the LADSPA spec. Like the DSSI_API_Version in the DSSI
descriptor.
--
Lars Luthman
PGP key: http://www.student.nada.kth.se/~d00-llu/pgp_key.php
Fingerprint: FCA7 C790 19B9 322D EB7A E1B3 4371 4650 04C7 7E2E
Steve Harris
2006-04-25 21:37:28 UTC
Permalink
Post by tom christie
Post by Steve Harris
Sorry, I just dont feel that motivated by this.
No problem :) just wanted to know if anyone else thought it was an
important point.
Two other concerns...
A) There is no built-in way of a host distinguishing between a LADSPA
1.1 and a LADSPA 2.x plugin. (Unless I'm missing something?)
I was imagining they would be in a different path, and as they will be in
.ladspa2 directories, and the .so files are discoverable via the RDF
manifest, theres no real reason why you would find one and not be sure
what version it was, however...
Post by tom christie
Would it make sense to change the name of the discovery function?
eg... ladspa2_descriptor() instead of ladspa_descriptor()
That way there's no chance of a 2.0 host thinking it has a 2.0 plugin
when in fact it has a 1.1 plugin. (Or vice versa with a 1.1 host)
Either case would cause the host to crash when it calls the
instantiate() function.
Right, I can't see any reason not to do this.
Post by tom christie
B) There is no way of a host distinguishing between a LADSPA 2.x and a
LADSPA 2.y plugin.
Would it make sense for the initial few bytes of the struct to
explicitly declare that this really is a LADSPA struct and give the
major and minor versions for which it was written? This would allow
the struct to change in the future if neccessary without breaking
things and without needing to change the name of the discovery
function again.
char ladspa_string[7]; // plugin must set this to "LADSPA\0"
unsigned short major_version; // plugin must set this to 2
unsigned short minor_version; // plugin must set this to 0
I made a version of the .h that does this (the version thing, not the
header), but I couldn't think if any cases where it was useful - if it
gets as far as the time you fetch the descriptor from the .so before you
find out what the version is thats problaby a mistake. You should be
able to reject descriptors you cant handle before that stage, otherwise it
will annoy users. user: "I want that one", host: "oh, sorry, I dont
understand it"

One of my aims for LADSPA 2 is to remove the need to dlload the plugin
(expensive in CPU+memory, potentially dangerous) until you need to pass
data through it.

- Steve
tom christie
2006-04-26 08:48:01 UTC
Permalink
Post by Lars Luthman
don't think that the string is needed
I think that's fair.
Post by Lars Luthman
One version number should be enough though,
and it doesn't have to match the actual version of the LADSPA spec
Both those points (especially the second) sound simple and sensible.

Okay, so on reflection...

There's a case to be made that some version information ought to go
into the struct, since it directly affects how the struct may be
properly accessed.

There are two case where you would need version information
to correctly access the struct.

1) A future version extends the struct. (does not break backwards compatibility)
version information is needed so that eg. a 2.1 host does not try to
use 2.1 functionality in a 2.0 plugin.

2) A future version modifies the struct. (breaking backwards compatibility)

case 2) is very unlikely to occur anytime soon, so let's just forget about that
(it can be solved by using a new discovery function anyhow)

case 1) could most simply be addressed like this:
The struct starts with a single unsigned short.
The host must check the version number at the start...

If the plugin version >= host version:
No problem - the host knows it's functionality is fully supported.

If the plugin version < host version:
The host may access the plugin normally and is aware of what
functionality the plugin does not support.


Why is this useful?

Well, it provides a _built-in_ way of ensuring that the struct is
properly accessed,
even if the metadata file is corrupted or lost.
Say a user meddles with the metadata file to make a 2.0 plugin look
like a 2.1 plugin. The host attempts to access 2.1 functionality and
core dumps.
Say the metadata file has been lost - the plugin contains sufficient
information to remain accessible although it no longer has any
associated metadata.

I realise that the LADSPA library should mostly enforce keeping things
okay, but it seems like a nice idea to have a protected way of making
sure that we don't accidentally attempt to access invalid memory when
things go wrong.

I would suggest then: A single unsigned short at the start of the
struct, starting at '0' for ladspa 2.0 plugins and incrementing if and
when the struct is extended.
The LADSPA major and minor versions would stay in the metadata.


Any milege in this?...
Steve Harris
2006-04-26 09:38:50 UTC
Permalink
On Wed, Apr 26, 2006 at 09:48:01 +0100, tom christie wrote:
...
Post by tom christie
Well, it provides a _built-in_ way of ensuring that the struct is
properly accessed,
even if the metadata file is corrupted or lost.
Say a user meddles with the metadata file to make a 2.0 plugin look
like a 2.1 plugin. The host attempts to access 2.1 functionality and
core dumps.
Say the metadata file has been lost - the plugin contains sufficient
information to remain accessible although it no longer has any
associated metadata.
It's not metadata. If the data is corrupt or missing then youre SOL. It's
just as vital as the arrays of structs were in LADSPA 1; if you dont have
the data theres no way to use the plugin without causing segfaults.

This is why the "plugin" is really a directory, all the stuff in there is
neccesary.

- Steve
tom christie
2006-04-26 11:54:43 UTC
Permalink
It's really just an extra layer of protection...
I realise that the binary and data files will be accessed as a single unit,
but a corrupt data file should never cause a segfault.

Without a built-in struct version identifier the host (or LADSPA library)
may segfault by incorrectly accessing the struct. (if the data file is corrupt)

With a built-in struct version identifier the host (or LADSPA library)
can ensure it will never access the struct in a way which will cause a segfault.
(even if the data file is corrupt.)

Okay, I'll hold my peace now ;)
Post by Steve Harris
...
Post by tom christie
Well, it provides a _built-in_ way of ensuring that the struct is
properly accessed,
even if the metadata file is corrupted or lost.
Say a user meddles with the metadata file to make a 2.0 plugin look
like a 2.1 plugin. The host attempts to access 2.1 functionality and
core dumps.
Say the metadata file has been lost - the plugin contains sufficient
information to remain accessible although it no longer has any
associated metadata.
It's not metadata. If the data is corrupt or missing then youre SOL. It's
just as vital as the arrays of structs were in LADSPA 1; if you dont have
the data theres no way to use the plugin without causing segfaults.
This is why the "plugin" is really a directory, all the stuff in there is
neccesary.
- Steve
Steve Harris
2006-04-26 14:56:28 UTC
Permalink
Post by tom christie
It's really just an extra layer of protection...
I realise that the binary and data files will be accessed as a single unit,
but a corrupt data file should never cause a segfault.
That's somewhat like saying a corrupt binary should never cause a
segfault... if the data file gets corrupted in a way that breaks the
syntax, then there wont be enouhg data for hte host to attempt to load the
plugin and it will refuse, but if through some miracle
ladspa:InputControPort becomes ladspa:OutputControlPort then all kinds of
crazy shit will go down.
Post by tom christie
Without a built-in struct version identifier the host (or LADSPA library)
may segfault by incorrectly accessing the struct. (if the data file is corrupt)
I'm not interested in the case the data file is corrupt, its too much of a
special case, and theres nothing sensible you can do about it.

No-ones seriously interested in guarding against the caes where the .so is
corrupt. If you care that much, ship a sha1 checksum with your plugin.
Post by tom christie
With a built-in struct version identifier the host (or LADSPA library)
can ensure it will never access the struct in a way which will cause a segfault.
(even if the data file is corrupt.)
No it can't :) If the data file is currupt in any plausible way the host wont
have enough information to even attept to open the plugin anyway.

- Steve
tom christie
2006-04-26 16:48:32 UTC
Permalink
Post by Steve Harris
That's somewhat like saying a corrupt binary
should never cause a segfault...
No, not at all.
The data file is accessed as an input stream (to the host / LADSPA library).
It's fine for a bad data file to cause the library to fail to be able
to load it, or to load it and produce unexpected output, but it should
*never* cause it to segfault.
Post by Steve Harris
No-ones seriously interested in guarding against the caes
where the .so is corrupt.
Agreed, and neither am I.


All I'm saying is that if the discovery function may potentially
return differing structs from one LADSPA version to another, then it
ought also provide a mechanism of determining exactly which struct it
is returning.

If it does that, then the worst that can ever happen is that the
binary is accessed with duff input (no segfaulting).


Okay, I really will shut it now, I begin to suspect I'm labouring the point :)

t.
Steve Harris
2006-04-26 16:55:38 UTC
Permalink
Post by tom christie
Post by Steve Harris
That's somewhat like saying a corrupt binary
should never cause a segfault...
No, not at all.
The data file is accessed as an input stream (to the host / LADSPA library).
It's fine for a bad data file to cause the library to fail to be able
to load it, or to load it and produce unexpected output, but it should
*never* cause it to segfault.
the only situation it can cause a segfault is where its mangled in a
somehow still structurally and syntaxically correct way (too unlikly to be
worth considering) or if the host pushes on without enough information.

The point I was making is that you will get segfaults if you try to us the
struct without the data, even if you know the version number, so dont.
Post by tom christie
All I'm saying is that if the discovery function may potentially
return differing structs from one LADSPA version to another, then it
ought also provide a mechanism of determining exactly which struct it
is returning.
Sure, but its easier to version the struct in the data.

- Steve
Dave Robillard
2006-04-26 17:14:06 UTC
Permalink
Post by Steve Harris
Post by tom christie
Post by Steve Harris
That's somewhat like saying a corrupt binary
should never cause a segfault...
No, not at all.
The data file is accessed as an input stream (to the host / LADSPA library).
It's fine for a bad data file to cause the library to fail to be able
to load it, or to load it and produce unexpected output, but it should
*never* cause it to segfault.
the only situation it can cause a segfault is where its mangled in a
somehow still structurally and syntaxically correct way (too unlikly to be
worth considering) or if the host pushes on without enough information.
The point I was making is that you will get segfaults if you try to us the
struct without the data, even if you know the version number, so dont.
Post by tom christie
All I'm saying is that if the discovery function may potentially
return differing structs from one LADSPA version to another, then it
ought also provide a mechanism of determining exactly which struct it
is returning.
Sure, but its easier to version the struct in the data.
Thinking about this I was worried about parallel installed multiple
versions of the same plugin, but as long as the URI refers to a
compatible version of the plugin, we don't need versioning in the struct
itself, since the URI between two versions of a plugin (one of which is
LADSPA2.0 and one which is binary incompatible LADSPA2.2 or whatever)
must change since it's incompatible, right?

We need to make absolutely sure multiple versions of a plugin can be
installed at once, including new incompatible versions of the spec, is
my point. I /think/ it's okay as stands though.

-DR-
Steve Harris
2006-04-26 18:29:52 UTC
Permalink
Post by Dave Robillard
Thinking about this I was worried about parallel installed multiple
versions of the same plugin, but as long as the URI refers to a
compatible version of the plugin, we don't need versioning in the struct
itself, since the URI between two versions of a plugin (one of which is
LADSPA2.0 and one which is binary incompatible LADSPA2.2 or whatever)
must change since it's incompatible, right?
Yes, the URI changes whenever the effective ABI changes, ie add, remove or
change semantics of ports, or new struct ABI.
Post by Dave Robillard
We need to make absolutely sure multiple versions of a plugin can be
installed at once, including new incompatible versions of the spec, is
my point. I /think/ it's okay as stands though.
Yes, you just need to make sure the URIs and and bundle names change as
appropriate.

- Steve
Leonard "paniq" Ritter
2006-04-26 18:15:04 UTC
Permalink
Post by Steve Harris
That's somewhat like saying a corrupt binary should never cause a
segfault... if the data file gets corrupted in a way that breaks the
syntax, then there wont be enouhg data for hte host to attempt to load the
plugin and it will refuse, but if through some miracle
ladspa:InputControPort becomes ladspa:OutputControlPort then all kinds of
crazy shit will go down.
segfaults will only be ok as long as there are no security advisories.
beware the rdf exploits. :)
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Dave Robillard
2006-04-26 15:18:13 UTC
Permalink
Post by Steve Harris
This is why the "plugin" is really a directory, all the stuff in there is
neccesary.
On the plugin bundle thing, I've got working C code that takes a path to
the directory, parses manifest.ttl, gleams the available plugin DLLs and
data files from that, and enumerates all the plugins in the DLL.

We need to clarify some things about bundles themselves:

- What is the significance of the bundle name itself? (We need to avoid
clashes somehow)
- Do they contain one plugin variant, or any number?
- One DLL or many?
- What's the relation between the two above points?

I'm not sure about number-of-plugins-per-bundle (though putting all of,
say, swh-plugins in one bundle seems counter to the intent to me?) but I
will suggest we reccommend that one DLL contains only variants of one
plugin (or a group of very similar plugins). Reasoning is to avoid
things like cmt.so which has a huge number of completely unrelated
plugins in one lib, meaning a host has to link in all that crap just to
use a simple amplifier plugin, which is no good.

-DR-
Steve Harris
2006-04-26 18:06:01 UTC
Permalink
Post by Dave Robillard
Post by Steve Harris
This is why the "plugin" is really a directory, all the stuff in there is
neccesary.
On the plugin bundle thing, I've got working C code that takes a path to
the directory, parses manifest.ttl, gleams the available plugin DLLs and
data files from that, and enumerates all the plugins in the DLL.
It shouldn't be neccesary to actually dlload() the .so file, if it is then
theres a mistake somewhere.
Post by Dave Robillard
- What is the significance of the bundle name itself? (We need to avoid
clashes somehow)
Yes, its a bit awkward. It would be nice to be able to use URIs, but thats
not going to wash.

I was planning something like
[abbreviated plugin name]-[collection name].whatever/
eg. Amp-swh.ladspa2

Assuming the number of collections doesnt grow to much, the current thing
of people using thier initials or similar should work fine. The maintainer
of each colleaction is responsible for making sure noone else uses the
same collection name, and that none of thier abbreviated names collide.

If we wanted to go overboard we could do something like
[abbreviated plugin name]-[64bit hash of URI of one plugin].whatever/
eg. amp-5491370f050fa849.ladspa2/
which guarantees uniqueness, but its a bit of a pain, and the plugin bundle
names will be a bit ugly.
Post by Dave Robillard
- Do they contain one plugin variant, or any number?
Probably leave it as a matter of taste. Though discouraging the cmt thing
is a good idea IMHO.
Post by Dave Robillard
- One DLL or many?
As many as you want / need.
Post by Dave Robillard
I'm not sure about number-of-plugins-per-bundle (though putting all of,
say, swh-plugins in one bundle seems counter to the intent to me?) but I
will suggest we reccommend that one DLL contains only variants of one
plugin (or a group of very similar plugins). Reasoning is to avoid
things like cmt.so which has a huge number of completely unrelated
plugins in one lib, meaning a host has to link in all that crap just to
use a simple amplifier plugin, which is no good.
My intention was to have a pretty much 1:1 correspondance between .so's I
have now and bundles in the future. ie. most plugins are on thier own, but
logically grouped ones are in one .so. eg. a buch ov very similar
oscialltors, filters etc.

I dont think its neccesary to specify this though, the best natural level
usually settles out. ie. people see cmt.so, and go "arrrghhh!".

- Steve
Dave Robillard
2006-04-26 18:53:05 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Steve Harris
This is why the "plugin" is really a directory, all the stuff in there is
neccesary.
On the plugin bundle thing, I've got working C code that takes a path to
the directory, parses manifest.ttl, gleams the available plugin DLLs and
data files from that, and enumerates all the plugins in the DLL.
It shouldn't be neccesary to actually dlload() the .so file, if it is then
theres a mistake somewhere.
Sorry, to be clearer loading the DLL was my goal (not the means towards
enumerating the available plugins). Enumerating what indexes
ladspa_descriptor returns is just what I happened to write to be sure I
really did load the DLL successfully.
Post by Steve Harris
Post by Dave Robillard
- What is the significance of the bundle name itself? (We need to avoid
clashes somehow)
Yes, its a bit awkward. It would be nice to be able to use URIs, but thats
not going to wash.
I was planning something like
[abbreviated plugin name]-[collection name].whatever/
eg. Amp-swh.ladspa2
Assuming the number of collections doesnt grow to much, the current thing
of people using thier initials or similar should work fine. The maintainer
of each colleaction is responsible for making sure noone else uses the
same collection name, and that none of thier abbreviated names collide.
If we wanted to go overboard we could do something like
[abbreviated plugin name]-[64bit hash of URI of one plugin].whatever/
eg. amp-5491370f050fa849.ladspa2/
which guarantees uniqueness, but its a bit of a pain, and the plugin bundle
names will be a bit ugly.
That is overboard, but I guess there's no real good solution to this
that doesn't involve having a URI of some variety as the name, which is
far too ugly.

We do need to prevent people from doing stupid things like calling the
directory "amp" though, so at least a recommendation in the spec is in
order.
Post by Steve Harris
Post by Dave Robillard
- Do they contain one plugin variant, or any number?
Probably leave it as a matter of taste. Though discouraging the cmt thing
is a good idea IMHO.
Post by Dave Robillard
- One DLL or many?
As many as you want / need.
Post by Dave Robillard
I'm not sure about number-of-plugins-per-bundle (though putting all of,
say, swh-plugins in one bundle seems counter to the intent to me?) but I
will suggest we reccommend that one DLL contains only variants of one
plugin (or a group of very similar plugins). Reasoning is to avoid
things like cmt.so which has a huge number of completely unrelated
plugins in one lib, meaning a host has to link in all that crap just to
use a simple amplifier plugin, which is no good.
My intention was to have a pretty much 1:1 correspondance between .so's I
have now and bundles in the future. ie. most plugins are on thier own, but
logically grouped ones are in one .so. eg. a buch ov very similar
oscialltors, filters etc.
I dont think its neccesary to specify this though, the best natural level
usually settles out. ie. people see cmt.so, and go "arrrghhh!".
They go arrrrggghhh, but cmt.so remains with no settling in sight :)

I guess in the interests of defining as little as neccessary, it should
go unspecified (though as above a recommendation would be good). Large
bundles are okay because they ease the burden on the user, but I don't
see any benefit of a huge chunk of completely unrelated plugins being in
one .so

As long as we have this nice bundle format, I suppose both a LADSPA repo
site and a 'master package' of all LADSPA plugins can exist (both things
that are requested pretty often), though they would only be able to
usefully distribute binary builds, not source. :/

This is why I'm tempted to suggest that a bundle only contains related
plugins, so a user could easily just install the SWH amp (say on a
resource limited system). There's a lot of plugins out there that are
totally useless for some people, it would be nice if /users/ could
decide what plugins they want installed. But then of course the
directory name problem becomes a bigger one that'd need to be solved
properly..

-DR-
Leonard "paniq" Ritter
2006-04-25 21:58:23 UTC
Permalink
Ok, some thoughts about the headerfile:

- i would find it helpful if the header also contained a definition of
a valid LADSPA URI, along with some examples.

- passing the HostFeatures in instantiate is a bit too late. i wouldnt
want to instantiate a plugin first to find out if they match i.e. when i
enumerate plugins to display them in a menu. furthermore i'm not sure if
it is an audio plugins duty to check the validity of a host. rather the
host should analyze a static string pointed member containing required
host features. this way the host programmer can choose the quickest
method to do a match check. at least i think so.

- why does the plugin require its own bundle path for instantiation?
this can usually be deduced from the dl's own runtime image information,
no? otherwise, an explanation of this choice in the comment would be
nice.

- comments still contain references to set_run_adding_gain

- LADSPA is an ugly name ;)

after reading this i do not see why a new ladspa header is required.
there are barely any changes in 2. i think this is going to become more
confusing than helpful, especially since it will not be possible to load
ladspa 1+2 plugins in the same host with ease (yes, people do not like
to fix orphaned code and recompile binaries, imagine!).

furthermore, DSSI builds upon ladspa. a ladspa 2 enforces also a DSSI 2.
again, looking at the slight changes that ladspa underwent, i dont see
what the big fuzz is about.

grumpily yours,
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Dave Robillard
2006-04-25 21:58:08 UTC
Permalink
[snip]
Post by Leonard "paniq" Ritter
after reading this i do not see why a new ladspa header is required.
there are barely any changes in 2. i think this is going to become more
confusing than helpful, especially since it will not be possible to load
ladspa 1+2 plugins in the same host with ease (yes, people do not like
to fix orphaned code and recompile binaries, imagine!).
You are completely missing the entire point of LADSPA2. All the
unecessary data has been removed from the header file (ie the plugin
code).

Look at the example plugin's code, it will be painfully obvious what the
advantage is.

-DR-
Steve Harris
2006-04-25 22:04:21 UTC
Permalink
Post by Dave Robillard
[snip]
Post by Leonard "paniq" Ritter
after reading this i do not see why a new ladspa header is required.
there are barely any changes in 2. i think this is going to become more
confusing than helpful, especially since it will not be possible to load
ladspa 1+2 plugins in the same host with ease (yes, people do not like
to fix orphaned code and recompile binaries, imagine!).
You are completely missing the entire point of LADSPA2. All the
unecessary data has been removed from the header file (ie the plugin
code).
Look at the example plugin's code, it will be painfully obvious what the
advantage is.
Well, with sufficeint use of calloc and careful spec wording its possible
to get the same affect with no change to the struct, but I just dont see
the point. The plugin and host code has to change anyway, and its less
ugly if its removed.

If we ever have an ABI change in the future then the LADSPA 1
pseudo-compatibility will be lost anyway.

- Steve
Leonard "paniq" Ritter
2006-04-25 22:35:14 UTC
Permalink
Post by Steve Harris
If we ever have an ABI change in the future then the LADSPA 1
pseudo-compatibility will be lost anyway.
there is a difference between fixing and recompiling code ;)
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Alfons Adriaensen
2006-05-02 11:50:31 UTC
Permalink
Post by Dave Robillard
You are completely missing the entire point of LADSPA2. All the
unecessary data has been removed from the header file (ie the plugin
code).
Look at the example plugin's code, it will be painfully obvious what the
advantage is.
A lot of plugins create what is essentially a block of constants by
dynamically allocating and initialising every bit of it. ISTR there was
(is) even an 'offical' plugin example source doing it that way.
Compared to that the new code is indeed simpler. But it's a braindead
way of doing it really, and that makes the comparison totally invalid.

I really don't see what is 'complex' or 'difficult' about e.g.


static const LADSPA_PortDescriptor pdesc0 [Ladspa_G2reverb::NPORT] =
{
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
....
};


Further, you can't really remove all of this data. Most of it
will be required by the plugin code itself, and you can't expect
it to go and read it from the RDF.
--
FA

Follie! Follie! Delirio vano e' questo!
Dave Robillard
2006-05-02 19:49:59 UTC
Permalink
Post by Alfons Adriaensen
Post by Dave Robillard
You are completely missing the entire point of LADSPA2. All the
unecessary data has been removed from the header file (ie the plugin
code).
Look at the example plugin's code, it will be painfully obvious what the
advantage is.
A lot of plugins create what is essentially a block of constants by
dynamically allocating and initialising every bit of it. ISTR there was
(is) even an 'offical' plugin example source doing it that way.
Compared to that the new code is indeed simpler. But it's a braindead
way of doing it really, and that makes the comparison totally invalid.
I really don't see what is 'complex' or 'difficult' about e.g.
static const LADSPA_PortDescriptor pdesc0 [Ladspa_G2reverb::NPORT] =
{
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO,
LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL,
....
};
That would be a valid point if all the data that people wanted to
associate with plugins was strictly defined right now (which is
impossible). That is the whole problem with LADSPA1 that we need to fix
here, hence the external data file.
Post by Alfons Adriaensen
Further, you can't really remove all of this data. Most of it
will be required by the plugin code itself, and you can't expect
it to go and read it from the RDF.
Since the plugin author writes both and they are strongly associated
with (and depend on) each other, the plugin can 'assume' eg. the type of
it's ports. Plugin code definitely won't be reading the RDF file.

-DR-
Steve Harris
2006-05-02 19:32:39 UTC
Permalink
Post by Dave Robillard
Post by Alfons Adriaensen
Further, you can't really remove all of this data. Most of it
will be required by the plugin code itself, and you can't expect
it to go and read it from the RDF.
Since the plugin author writes both and they are strongly associated
with (and depend on) each other, the plugin can 'assume' eg. the type of
it's ports. Plugin code definitely won't be reading the RDF file.S
I've not yet seen a plugin that introspects its own port hints either, but
don't take that as a challenge ;)

- Steve
Dave Robillard
2006-05-02 20:34:14 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
Post by Alfons Adriaensen
Further, you can't really remove all of this data. Most of it
will be required by the plugin code itself, and you can't expect
it to go and read it from the RDF.
Since the plugin author writes both and they are strongly associated
with (and depend on) each other, the plugin can 'assume' eg. the type of
it's ports. Plugin code definitely won't be reading the RDF file.S
I've not yet seen a plugin that introspects its own port hints either, but
don't take that as a challenge ;)
I suppose it does have a path to it's own bundle, and could
theoretically parse manifest.ttl to find it's own data file and do what
it wants with it.

But.. I mean... just.. no! :)

(I did actually consider adding plugin-side hooks to my ladspa2 library
but decided against it)

--

Speaking of the library, status update: I have successfully processed
data with the example plugin in about 5 lines of C code. Plugins can be
'loaded' with one LOC using only the URI (finding and loading the plugin
is all automagic), and instantiated with one more LOC.

-DR-

Steve Harris
2006-04-25 22:02:28 UTC
Permalink
Post by Leonard "paniq" Ritter
- i would find it helpful if the header also contained a definition of
a valid LADSPA URI, along with some examples.
Yes, we were discussing this on IRC an hour or so ago. Any URI is a valid
LADSPA URI, but there are some helpful recommendations.

NB, the header file is just a hacked about ladspa.h, it's far from
finished.
Post by Leonard "paniq" Ritter
- passing the HostFeatures in instantiate is a bit too late. i wouldnt
want to instantiate a plugin first to find out if they match i.e. when i
enumerate plugins to display them in a menu. furthermore i'm not sure if
it is an audio plugins duty to check the validity of a host. rather the
host should analyze a static string pointed member containing required
host features. this way the host programmer can choose the quickest
method to do a match check. at least i think so.
I think the easiest thing would be for the plugin to list its required
features in the data file, then the host can weed them out without even
getting that far.

The plugin may just choose to modify its behaviour, not refuse, so the
featuers list still should be passed to instantiate IMHO.
Post by Leonard "paniq" Ritter
- why does the plugin require its own bundle path for instantiation?
this can usually be deduced from the dl's own runtime image information,
no? otherwise, an explanation of this choice in the comment would be
nice.
Can it? I wasn't aware of that, in that case its redundant.
Post by Leonard "paniq" Ritter
- comments still contain references to set_run_adding_gain
Cheers, I'l fix that.
Post by Leonard "paniq" Ritter
- LADSPA is an ugly name ;)
Yep.
Post by Leonard "paniq" Ritter
after reading this i do not see why a new ladspa header is required.
there are barely any changes in 2. i think this is going to become more
confusing than helpful, especially since it will not be possible to load
ladspa 1+2 plugins in the same host with ease (yes, people do not like
to fix orphaned code and recompile binaries, imagine!).
It should be perfectly possible to load both. Personally I prefer to
remove obsolete cruft, but its a matter of taste. I did consder just
ignoring the obsolete fields and resusing label as the uri, but its kinda
ugly.
Post by Leonard "paniq" Ritter
furthermore, DSSI builds upon ladspa. a ladspa 2 enforces also a DSSI 2.
again, looking at the slight changes that ladspa underwent, i dont see
what the big fuzz is about.
Yes, but that's desirable anyway. With some of the (potential) new
capbilities there are less ugly ways to do some of the things DSSI does,
DSSI 2 should be much less complex that 1.

- Steve
Leonard "paniq" Ritter
2006-04-25 22:33:50 UTC
Permalink
Post by Steve Harris
I think the easiest thing would be for the plugin to list its required
features in the data file, then the host can weed them out without even
getting that far.
yup.
Post by Steve Harris
The plugin may just choose to modify its behaviour, not refuse, so the
featuers list still should be passed to instantiate IMHO.
if it never refuses then its ok with me ;)
Post by Steve Harris
Post by Leonard "paniq" Ritter
- why does the plugin require its own bundle path for instantiation?
this can usually be deduced from the dl's own runtime image information,
no? otherwise, an explanation of this choice in the comment would be
nice.
Can it? I wasn't aware of that, in that case its redundant.
i assume the lib file resides in the bundle path or the bundle path has
been compiled into the lib. on win32, GetModulePath can be used to get
the path to the current module, i do not know the posix equivalent to do
that.

alternatively the host could be required to chdir to the bundle folder
before the plugin is being instantiated?
Post by Steve Harris
It should be perfectly possible to load both. Personally I prefer to
remove obsolete cruft, but its a matter of taste. I did consder just
ignoring the obsolete fields and resusing label as the uri, but its kinda
ugly.
i just had a discussion with dave robillard on irc regarding this topic.
my original (silly) wish of just changing the name has now a pragmatical
basis. from my point of view, ladspa 2 is something different than
ladspa 1. _replacing_ ladspa will immediately invalidate any non-updated
plugin on the system. counting the mass of different plugins already
available, it might take up to a year until distros catch up. you could
avoid these migration issues if ladspa 2 had an entirely different name.
none of the previous binaries have to be rebuilt, and can happily bitrot
until no distro is supporting them anymore.

it is maybe neccessary to support future api changes from the start, to
allow soft migrations?
Post by Steve Harris
Yes, but that's desirable anyway. With some of the (potential) new
capbilities there are less ugly ways to do some of the things DSSI does,
DSSI 2 should be much less complex that 1.
how are parameter boundaries determined now? are all parameters clamped
to 0..1 (as vst does)? if yes, shouldnt this be mentioned in the
comments?
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Dave Robillard
2006-04-25 22:46:41 UTC
Permalink
Post by Leonard "paniq" Ritter
Post by Steve Harris
I think the easiest thing would be for the plugin to list its required
features in the data file, then the host can weed them out without even
getting that far.
yup.
++

Definitely shouldn't have to instantiate a plugin to see if you even
want it, especially since (as mentioned) this would make the user
experience awful.
Post by Leonard "paniq" Ritter
Post by Steve Harris
The plugin may just choose to modify its behaviour, not refuse, so the
featuers list still should be passed to instantiate IMHO.
if it never refuses then its ok with me ;)
Plugins must be able to refuse hosts and hosts must be able to refuse
plugins. It's the only way to allow extensions. I _guarantee_ plugins
will exist that some hosts just don't want (they already do with
LADSPA1), and some plugins will exists that require features hosts are
not required to provide. This is a Good Thing.
Post by Leonard "paniq" Ritter
i just had a discussion with dave robillard on irc regarding this topic.
my original (silly) wish of just changing the name has now a pragmatical
basis. from my point of view, ladspa 2 is something different than
ladspa 1. _replacing_ ladspa will immediately invalidate any non-updated
plugin on the system. counting the mass of different plugins already
available, it might take up to a year until distros catch up. you could
avoid these migration issues if ladspa 2 had an entirely different name.
none of the previous binaries have to be rebuilt, and can happily bitrot
until no distro is supporting them anymore.
While I am with you on the name thing, you don't understand. LADSPA2
will be completely installable in parallel with LADSPA1. Obviously it
will not "replace" LADSPA1 on a system and immediately break all the
installed plugins!
Post by Leonard "paniq" Ritter
how are parameter boundaries determined now? are all parameters clamped
to 0..1 (as vst does)? if yes, shouldnt this be mentioned in the
comments?
This, like most everything else, is in the data file. You really need
to read more than the header before commenting further ;)

-DR-
Leonard "paniq" Ritter
2006-04-25 23:23:27 UTC
Permalink
Post by Dave Robillard
Plugins must be able to refuse hosts and hosts must be able to refuse
plugins. It's the only way to allow extensions. I _guarantee_ plugins
will exist that some hosts just don't want (they already do with
LADSPA1), and some plugins will exists that require features hosts are
not required to provide. This is a Good Thing.
maybe in a Perfect World. in practice, we are going to face irritations
when plugins demand weird non-unified URIs to be passed in order to run
at all. from what i see, no new URIs can be invented without requiring
immediate support in all available hosts, and plugins that initially
only work for one host are not that cool. ergo, the "feature" of
blocking instantiation for a host not passing a required URI will be
rarely used, for the simple reason that it might not work with all
hosts. thus, do not allow it by spec.

from my point of view, host features should be seen as "hints", which
are not required, but of a suggestive nature.

my argumentation is chaotic. decipher the obvious!
Post by Dave Robillard
While I am with you on the name thing, you don't understand. LADSPA2
will be completely installable in parallel with LADSPA1. Obviously it
will not "replace" LADSPA1 on a system and immediately break all the
installed plugins!
i hope this is taken care of! the new header suggests replacement, not
complementation.
Post by Dave Robillard
This, like most everything else, is in the data file. You really need
to read more than the header before commenting further ;)
the trusty header should be all documentation required... there was also
no reference to additional documents in it. how about adding it? :o)
Post by Dave Robillard
-DR-
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Dave Robillard
2006-04-25 23:59:16 UTC
Permalink
Post by Leonard "paniq" Ritter
Post by Dave Robillard
Plugins must be able to refuse hosts and hosts must be able to refuse
plugins. It's the only way to allow extensions. I _guarantee_ plugins
will exist that some hosts just don't want (they already do with
LADSPA1), and some plugins will exists that require features hosts are
not required to provide. This is a Good Thing.
maybe in a Perfect World. in practice, we are going to face irritations
when plugins demand weird non-unified URIs to be passed in order to run
at all. from what i see, no new URIs can be invented without requiring
immediate support in all available hosts
Where did you get this crazy idea? The whole point is that different
hosts can provide different features.
Post by Leonard "paniq" Ritter
and plugins that initially
only work for one host are not that cool. ergo, the "feature" of
blocking instantiation for a host not passing a required URI will be
rarely used, for the simple reason that it might not work with all
hosts. thus, do not allow it by spec.
You want to impose plugins work on the lowest common denominator of
hosts. Basically this amounts to mandating that certain plugins simply
can not exist. Why would you want to do that?
Post by Leonard "paniq" Ritter
from my point of view, host features should be seen as "hints", which
are not required, but of a suggestive nature.
Plugins are free to interpret them as such and not /require/ the
feature. It's totally up to the plugin.
Post by Leonard "paniq" Ritter
my argumentation is chaotic. decipher the obvious!
Post by Dave Robillard
While I am with you on the name thing, you don't understand. LADSPA2
will be completely installable in parallel with LADSPA1. Obviously it
will not "replace" LADSPA1 on a system and immediately break all the
installed plugins!
i hope this is taken care of! the new header suggests replacement, not
complementation.
The fact that you even considered that someone would really do this is
frightening. Not an issue ;)
Post by Leonard "paniq" Ritter
Post by Dave Robillard
This, like most everything else, is in the data file. You really need
to read more than the header before commenting further ;)
the trusty header should be all documentation required... there was also
no reference to additional documents in it. how about adding it? :o)
If you think the header should be all the documentation required, then
you completely Don't Get It on a fundamental level. Read the example
plugin - all of it.


-DR-
Leonard "paniq" Ritter
2006-04-26 01:11:10 UTC
Permalink
Post by Dave Robillard
Post by Leonard "paniq" Ritter
Post by Dave Robillard
Plugins must be able to refuse hosts and hosts must be able to refuse
plugins. It's the only way to allow extensions. I _guarantee_ plugins
will exist that some hosts just don't want (they already do with
LADSPA1), and some plugins will exists that require features hosts are
not required to provide. This is a Good Thing.
maybe in a Perfect World. in practice, we are going to face irritations
when plugins demand weird non-unified URIs to be passed in order to run
at all. from what i see, no new URIs can be invented without requiring
immediate support in all available hosts
Where did you get this crazy idea? The whole point is that different
hosts can provide different features.
i agree. but i suppose this is a misunderstanding. why do you think it
is a crazy idea?
Post by Dave Robillard
Post by Leonard "paniq" Ritter
and plugins that initially
only work for one host are not that cool. ergo, the "feature" of
blocking instantiation for a host not passing a required URI will be
rarely used, for the simple reason that it might not work with all
hosts. thus, do not allow it by spec.
You want to impose plugins work on the lowest common denominator of
hosts. Basically this amounts to mandating that certain plugins simply
can not exist. Why would you want to do that?
no i do not want to do that. this is a misunderstanding. please explain
how you got this impression.
Post by Dave Robillard
Post by Leonard "paniq" Ritter
i hope this is taken care of! the new header suggests replacement, not
complementation.
The fact that you even considered that someone would really do this is
frightening. Not an issue ;)
i have seen things you humans will never understand.
Post by Dave Robillard
If you think the header should be all the documentation required, then
you completely Don't Get It on a fundamental level. Read the example
plugin - all of it.
i was able to implement a working ladspa host implementation only from
the header, and that was a good experience. i would like it if it could
stay that way. a tiny reference to an additional document that should be
read in the header would also be cool. not mentioning required
literature is unfriendly ;)
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Phil Frost
2006-04-26 02:05:25 UTC
Permalink
Post by Leonard "paniq" Ritter
Post by Dave Robillard
If you think the header should be all the documentation required, then
you completely Don't Get It on a fundamental level. Read the example
plugin - all of it.
i was able to implement a working ladspa host implementation only from
the header, and that was a good experience. i would like it if it could
stay that way. a tiny reference to an additional document that should be
read in the header would also be cool. not mentioning required
literature is unfriendly ;)
You are not alone on this one. I think it's great to have as much data
as possible in a place that need not be dlopened to access. However, if
I have to learn to use some whizz-bang library to read yet another
markup language, spend an hour at w3c to learn about all these
web-inspired formats, and grok some ladspa-specific schema to manipulate
a plugin, I think this Simple Plugin API has missed the mark.

Now, obviously the current example is incomplete, but whenever this
stuff is done, I shouldn't have to write more than 5 lines of C to shove
some bits through a plugin, and it shouldn't take me more than 5 minutes
from the time I google "ladspa documentation" to learn to do it.

If browsing or using ladspa plugins would require more than 5 lines of C
or learning some new technology or library that does far more than I
care about, I suggest the ladspa sdk include a well documented, simple
convenience library to do the things that any ladspa host would want to
do. This includes things like finding available plugins, and querying
them for version, description, documentation references, and loading.

If everything I need to know to use ladspa won't reasonably fit in a
header, it isn't simple.
Paul Davis
2006-04-26 02:55:55 UTC
Permalink
Post by Phil Frost
You are not alone on this one. I think it's great to have as much data
as possible in a place that need not be dlopened to access. However, if
I have to learn to use some whizz-bang library to read yet another
markup language, spend an hour at w3c to learn about all these
web-inspired formats, and grok some ladspa-specific schema to manipulate
a plugin, I think this Simple Plugin API has missed the mark.
Now, obviously the current example is incomplete, but whenever this
stuff is done, I shouldn't have to write more than 5 lines of C to shove
some bits through a plugin, and it shouldn't take me more than 5 minutes
from the time I google "ladspa documentation" to learn to do it.
it takes *way* more lines of code than that to use a ladspa plugin in
this way, and thats for the existing header-only specification.

one the design goals of a good plugin API is to make life simple for
plugins, because there are lots of them and presumably quite a few
authors too, at a certain expense to hosts, because there are relatively
few of them and their authors are likely to be more skilled at what they
are doing.

there are lots of little gotchas even with the amazingly simple API that
LADSPA 1 represents, and quite a few of these will become simpler or
will vanish with the metadata scheme that steve has outlined.

--p
Florian Paul Schmidt
2006-04-26 10:06:00 UTC
Permalink
On Tue, 25 Apr 2006 22:55:55 -0400
Post by Paul Davis
it takes *way* more lines of code than that to use a ladspa plugin in
this way, and thats for the existing header-only specification.
one the design goals of a good plugin API is to make life simple for
plugins, because there are lots of them and presumably quite a few
authors too, at a certain expense to hosts, because there are relatively
few of them and their authors are likely to be more skilled at what they
are doing.
there are lots of little gotchas even with the amazingly simple API that
LADSPA 1 represents, and quite a few of these will become simpler or
will vanish with the metadata scheme that steve has outlined.
Erm, just to voice my opinion on this LADSPA 2 thing i kinda hijack your
post to

Vote++;

@Phil: Look at the example plugin. Life does get easier with this.

Flo
--
Palimm Palimm!
http://tapas.affenbande.org
Dave Robillard
2006-04-26 03:16:30 UTC
Permalink
Post by Phil Frost
Post by Leonard "paniq" Ritter
Post by Dave Robillard
If you think the header should be all the documentation required, then
you completely Don't Get It on a fundamental level. Read the example
plugin - all of it.
i was able to implement a working ladspa host implementation only from
the header, and that was a good experience. i would like it if it could
stay that way. a tiny reference to an additional document that should be
read in the header would also be cool. not mentioning required
literature is unfriendly ;)
You are not alone on this one. I think it's great to have as much data
as possible in a place that need not be dlopened to access. However, if
I have to learn to use some whizz-bang library to read yet another
markup language, spend an hour at w3c to learn about all these
web-inspired formats, and grok some ladspa-specific schema to manipulate
a plugin, I think this Simple Plugin API has missed the mark.
Now, obviously the current example is incomplete, but whenever this
stuff is done, I shouldn't have to write more than 5 lines of C to shove
some bits through a plugin, and it shouldn't take me more than 5 minutes
from the time I google "ladspa documentation" to learn to do it.
If browsing or using ladspa plugins would require more than 5 lines of C
or learning some new technology or library that does far more than I
care about, I suggest the ladspa sdk include a well documented, simple
convenience library to do the things that any ladspa host would want to
do. This includes things like finding available plugins, and querying
them for version, description, documentation references, and loading.
If everything I need to know to use ladspa won't reasonably fit in a
header, it isn't simple.
You're in luck. I'm already in the process of writing said library. :)

Loading and using a LADSPA2 plugin (using the library) will be
significantly less code than loading a LADSPA1, and certainly be a _lot_
more readable.

-DR-
Steve Harris
2006-04-26 05:48:32 UTC
Permalink
Post by Leonard "paniq" Ritter
Post by Steve Harris
I think the easiest thing would be for the plugin to list its required
features in the data file, then the host can weed them out without even
getting that far.
yup.
Post by Steve Harris
The plugin may just choose to modify its behaviour, not refuse, so the
featuers list still should be passed to instantiate IMHO.
if it never refuses then its ok with me ;)
It's certainly allowed to refuse, it would just be bad manners, unless the
host has ignored the required features list.
Post by Leonard "paniq" Ritter
Post by Steve Harris
Post by Leonard "paniq" Ritter
- why does the plugin require its own bundle path for instantiation?
this can usually be deduced from the dl's own runtime image information,
no? otherwise, an explanation of this choice in the comment would be
nice.
Can it? I wasn't aware of that, in that case its redundant.
i assume the lib file resides in the bundle path or the bundle path has
been compiled into the lib. on win32, GetModulePath can be used to get
the path to the current module, i do not know the posix equivalent to do
that.
thats platform specific though, seems like the plugins shouldn't be full
of #ifdef WIN32 ... code.
Post by Leonard "paniq" Ritter
alternatively the host could be required to chdir to the bundle folder
before the plugin is being instantiated?
Thats likely to cause all manner of excitement.
Post by Leonard "paniq" Ritter
Post by Steve Harris
It should be perfectly possible to load both. Personally I prefer to
remove obsolete cruft, but its a matter of taste. I did consder just
ignoring the obsolete fields and resusing label as the uri, but its kinda
ugly.
i just had a discussion with dave robillard on irc regarding this topic.
my original (silly) wish of just changing the name has now a pragmatical
basis. from my point of view, ladspa 2 is something different than
ladspa 1. _replacing_ ladspa will immediately invalidate any non-updated
plugin on the system. counting the mass of different plugins already
available, it might take up to a year until distros catch up. you could
avoid these migration issues if ladspa 2 had an entirely different name.
none of the previous binaries have to be rebuilt, and can happily bitrot
until no distro is supporting them anymore.
There is no LADSPA "system", its just a specification, so theres nothing
to be replaced. All LADSPA 1.x software will be unaffected.
Post by Leonard "paniq" Ritter
it is maybe neccessary to support future api changes from the start, to
allow soft migrations?
Perhaps, I think that can be done in the data though.
Post by Leonard "paniq" Ritter
Post by Steve Harris
Yes, but that's desirable anyway. With some of the (potential) new
capbilities there are less ugly ways to do some of the things DSSI does,
DSSI 2 should be much less complex that 1.
how are parameter boundaries determined now? are all parameters clamped
to 0..1 (as vst does)? if yes, shouldnt this be mentioned in the
comments?
Thier specified by range hints, allowing natural values, and the plugins
are required to accept any value, though not neccesarily do anything
sensibe with it.

We Like It That Way.

- Steve
Leonard "paniq" Ritter
2006-04-26 18:04:35 UTC
Permalink
Post by Steve Harris
Post by Leonard "paniq" Ritter
if it never refuses then its ok with me ;)
It's certainly allowed to refuse, it would just be bad manners, unless the
host has ignored the required features list.
so required features have to be checked on both sides. isn't that
redundant?

furthermore, surely there are other reasons why instantiation could
fail. how can the host determine the reason for which a plugin refused
to instantiate?
Post by Steve Harris
thats platform specific though, seems like the plugins shouldn't be full
of #ifdef WIN32 ... code.
yes, of course, that would be nonsense. but in case there is a posix
equivalent, it will be available on win32 as well. but i dont know
anything more about this.
Post by Steve Harris
Post by Leonard "paniq" Ritter
alternatively the host could be required to chdir to the bundle folder
before the plugin is being instantiated?
Thats likely to cause all manner of excitement.
the erotic kind of excitement? ;)
--
-- leonard "paniq" ritter
-- http://www.mjoo.org
-- http://www.paniq.org
Dave Robillard
2006-04-26 18:05:20 UTC
Permalink
Post by Leonard "paniq" Ritter
Post by Steve Harris
Post by Leonard "paniq" Ritter
if it never refuses then its ok with me ;)
It's certainly allowed to refuse, it would just be bad manners, unless the
host has ignored the required features list.
so required features have to be checked on both sides. isn't that
redundant?
The plugin (obviously) needs to check the features anyway, since it
needs to (or may want to) use them. Can't use something if you don't
even know if it's there.

-DR-
Steve Harris
2006-04-26 18:08:26 UTC
Permalink
Post by Leonard "paniq" Ritter
Post by Steve Harris
Post by Leonard "paniq" Ritter
if it never refuses then its ok with me ;)
It's certainly allowed to refuse, it would just be bad manners, unless the
host has ignored the required features list.
so required features have to be checked on both sides. isn't that
redundant?
SupportedFeatures is not just fo requirements. eg. Fon's plyphonic control
ports can work around the case where the host doesnt support it.
Post by Leonard "paniq" Ritter
furthermore, surely there are other reasons why instantiation could
fail. how can the host determine the reason for which a plugin refused
to instantiate?
It can't. Meh.
Post by Leonard "paniq" Ritter
Post by Steve Harris
Post by Leonard "paniq" Ritter
alternatively the host could be required to chdir to the bundle folder
before the plugin is being instantiated?
Thats likely to cause all manner of excitement.
the erotic kind of excitement? ;)
More the running around screaming kind ;)

- Steve
Hans Fugal
2006-04-24 23:53:42 UTC
Permalink
Post by Steve Harris
Post by Dave Robillard
For the sake of the record, it's been duked out on IRC and Steve
wins :). (Specifically, ports will be required to have a unique string
ID, but it will live in the data file, not the code).
Actually I didn't mean to say that they /will/ be required, just that I
don't have a problem with it. I've not heard anyone else speak in favour
of this, and it is a feature. If theres a critical mass of support I'm OK
with adding it, as it should make the lives of some hosts much easier.
Well then let me weigh in. I have in the past cursed the insensibility
of referencing a port with its arbitrary (from the human's POV)
numerical ID. I want human-friendly port IDs.
Post by Steve Harris
At the risk of upsetting Dave, it can be added a a 3rd party extension
without anything really bad happening. It just means that the Pd messages
/ OSC paths / whatever for some plugins will be ugly. "Market pressure"
will ensire that all plugins support it if its useful to enough users.
Ick. I'm all for market pressure, but this is not the place for it, IMHO.
--
Hans Fugal ; http://hans.fugal.net

There's nothing remarkable about it. All one has to do is hit the
right keys at the right time and the instrument plays itself.
-- Johann Sebastian Bach
Loki Davison
2006-04-25 00:26:09 UTC
Permalink
Post by Hans Fugal
Post by Steve Harris
Post by Dave Robillard
For the sake of the record, it's been duked out on IRC and Steve
wins :). (Specifically, ports will be required to have a unique string
ID, but it will live in the data file, not the code).
Actually I didn't mean to say that they /will/ be required, just that I
don't have a problem with it. I've not heard anyone else speak in favour
of this, and it is a feature. If theres a critical mass of support I'm OK
with adding it, as it should make the lives of some hosts much easier.
Well then let me weigh in. I have in the past cursed the insensibility
of referencing a port with its arbitrary (from the human's POV)
numerical ID. I want human-friendly port IDs.
Me too.
Steve Harris
2006-04-25 09:00:07 UTC
Permalink
Post by Loki Davison
Post by Hans Fugal
Post by Steve Harris
Post by Dave Robillard
For the sake of the record, it's been duked out on IRC and Steve
wins :). (Specifically, ports will be required to have a unique string
ID, but it will live in the data file, not the code).
Actually I didn't mean to say that they /will/ be required, just that I
don't have a problem with it. I've not heard anyone else speak in favour
of this, and it is a feature. If theres a critical mass of support I'm OK
with adding it, as it should make the lives of some hosts much easier.
Well then let me weigh in. I have in the past cursed the insensibility
of referencing a port with its arbitrary (from the human's POV)
numerical ID. I want human-friendly port IDs.
Me too.
OK, given that no-one has spoken out against it, I'm happy to include
a required shortname for ports, that must be [_a-zA-Z][_a-zA-Z0-9]* or
similar.

It's a burdon on all plugin authors, but host authors can ignore it.

I've tentatively added ladspa:shortname to the stawman plugin's ports.

- Steve
Taybin Rutkin
2006-04-25 04:38:16 UTC
Permalink
Post by Hans Fugal
Post by Steve Harris
At the risk of upsetting Dave, it can be added a a 3rd party
extension
without anything really bad happening. It just means that the Pd messages
/ OSC paths / whatever for some plugins will be ugly. "Market
pressure"
will ensire that all plugins support it if its useful to enough users.
Ick. I'm all for market pressure, but this is not the place for it, IMHO.
Why not? I think it's a great way of organically growing the spec by
testing popularity and usage in the real world first.

Taybin
Phil Frost
2006-04-22 15:41:16 UTC
Permalink
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
[...]
In my experience developing modular synths, it would be a huge benefit
to performance if modules had the option of including source code in the
bundle. This is especially useful if the module can provide a function
that calculates the outputs one sample at a time. I reckon most modules
which do not do any frequency domain calculations can do this.

The reason it's so great is because it allows the host to inline those
functions and call on a C compiler to optimize them together. For some
simple functions, constant folding can make a huge difference. Perhaps
more importantly, the sample buffer between the modules can be
eliminated. When each module does something simple, say a low order IIR,
an oscilator, or a multiplier, the load and store is much slower than
the calculation that happens between them. If the result can be left in
a register for the next module to process, the system becomes much more
efficient. When the process functions are inlined, there is not even the
overhead of a call.

Also, included source is simply convienent if one wishes to tinker with
the module, or run it on a different platform. Perhaps the compiled
version should have a platform-unique name within the bundle, and be
marked with a hash of the source, so that it can be rebuilt when needed,
preferably with some shared ladspa build tool.

Lastly, I'm not saying bundles-as-directories is a bad idea, but an
alternative to an openstep bundle is an ar archive. It works like tar,
only it is designed for nonsequential access of members. ".a" static
libraries and ".deb" debian packages are really just ar archives.
Dave Robillard
2006-04-22 16:43:54 UTC
Permalink
Post by Phil Frost
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
[...]
In my experience developing modular synths, it would be a huge benefit
to performance if modules had the option of including source code in the
bundle. This is especially useful if the module can provide a function
that calculates the outputs one sample at a time. I reckon most modules
which do not do any frequency domain calculations can do this.
It would definitely be a really, really cool thing if we could do this.
LADSPA plugins would be useful in so many more domains if "hosts" could
get at the code...

The downside is that we would have to mandate a standard build system
and FS layout of some variety. I'm generally not for such dictatorial
things, but in this case I think it's justified. Having some sort of
standard build system/directory layout/etc (ie a completely standardized
plugin package inc. source code) would allow a good LADSPA repository
site to be easily built as well - something else I think is sorely
needed. The current "system" of LADSPA distribution definitely sucks.

-DR-
Steve Harris
2006-04-22 16:47:49 UTC
Permalink
Post by Phil Frost
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
[...]
In my experience developing modular synths, it would be a huge benefit
to performance if modules had the option of including source code in the
bundle. This is especially useful if the module can provide a function
that calculates the outputs one sample at a time. I reckon most modules
which do not do any frequency domain calculations can do this.
That's too big a departure from LADSPA 1.x for me to consider right now.
Post by Phil Frost
Lastly, I'm not saying bundles-as-directories is a bad idea, but an
alternative to an openstep bundle is an ar archive. It works like tar,
only it is designed for nonsequential access of members. ".a" static
libraries and ".deb" debian packages are really just ar archives.
Yes, also jar/xpi zip files are possible. I've nothing against them, but
they mean more work for plugin and host authors, and its slightly more
work for curious users to find out what's in a plugin. The advantage being
that its a single file to pass around.

I did give it some thought, and came to the comclusion that directories
were /slightly/ better overall. My mind is not set in concrete though.

- Steve
Ralf Beck
2006-04-23 07:12:25 UTC
Permalink
Since people seem to see the necessity for some more functionality
within plugins, i want
to present LACPA (Linux Audio Cluster Plugin Api), which was intended to
be the
plugin api of the linux audio cluster (which i never finished due to the
lack of time).

Its main features:
* usable for midi/audio plugins (one plugin could be a host for other
plugins as well)
* sampleaccurate timeinfo for sequencers, tempo-synched
effects/instruments, video
* fixed size audiobuffers (good for use with networks and frequency
domain effects)
* extensible while keeping binary downward compatability
* no dependencies between host's and plugin's gui (plugins guis are
supposed to run in their own process)


BTW, by adding a control type "message", the realtime message part of
LACPA could be easily
added to LADSPA without breaking existing hosts .

Ralf
Florian Schmidt
2006-04-23 11:10:55 UTC
Permalink
On Sat, 22 Apr 2006 10:53:58 +0100
Post by Steve Harris
Almost two years ago at the LA conference a bunch of us agreed that
something need to be done to improve LADSPA, and on the approximate
direction it should take.
http://plugin.org.uk/ladspa2/
Hi,

thanks for taking the initiative on this! I would like to see a way for
the host to pass its native buffer size to the plugin though. I know,
this is really kind of contrary to how LADSPA is supposed to work (i.e.
the run () function should be able to handle an arbitrary number of
frames), but it has some serious advantages for fft-based algorithms.
And i think it should be possible to merge the two approaches somewhat.

A hint which the plugin could set that it needs power of two periodsizes
for optimal operation would be nice, too. The host should be free to
ignore this and the plugin should still work (doing what it sees fit.
i.e. use non power of two fft window sizes or use double buffering
again), but at least the host could notify the user that this plugin
might work suboptimal.

The approach of chopping up the period into smaller chunks (i.e. to
update control data at non period boundaries) would still be available,
but the plugin should be able to rely on the chunks being i.e. in this
form:

---> time
|128 |128 |
| | | | | | | | |

Native buffer size being 128 frames [upper row] and the lower row is how
it is chopped up [as an example]. We see that all chopped up chunks add
up to the native period size. This enables an fft based plugin to
collect data over a whole period and do its stuff once for all these
samples, without the need for extra double buffering which is a problem
with current ladspa and dssi.

There would be an additional requirement put on the host: It has to use
a fixed underlying buffersize [optimally a power of two] even if it's
not bound to do this by the hardware/soundinterface it uses. I.e. a host
that does the processing freewheeling.

What do you think?

Flo
--
Palimm Palimm!
http://tapas.affenbande.org
Steve Harris
2006-04-23 12:39:52 UTC
Permalink
Post by Florian Schmidt
thanks for taking the initiative on this! I would like to see a way for
the host to pass its native buffer size to the plugin though. I know,
this is really kind of contrary to how LADSPA is supposed to work (i.e.
the run () function should be able to handle an arbitrary number of
frames), but it has some serious advantages for fft-based algorithms.
And i think it should be possible to merge the two approaches somewhat.
Thats a new feature. It'll have to wait til after 2.0 as far as I'm
concerned.

- Steve
Florian Schmidt
2006-04-23 15:04:18 UTC
Permalink
On Sun, 23 Apr 2006 13:39:52 +0100
Post by Steve Harris
Post by Florian Schmidt
thanks for taking the initiative on this! I would like to see a way for
the host to pass its native buffer size to the plugin though. I know,
this is really kind of contrary to how LADSPA is supposed to work (i.e.
the run () function should be able to handle an arbitrary number of
frames), but it has some serious advantages for fft-based algorithms.
And i think it should be possible to merge the two approaches somewhat.
Thats a new feature. It'll have to wait til after 2.0 as far as I'm
concerned.
I tend to disagree as it is kinda orthogonal to the other proposed
changes. What time other than a major version change is better to add
such a feature?

Aw hell, i'll try to get this into DSSI 2 then ;)

Regards,
Flo
--
Palimm Palimm!
http://tapas.affenbande.org
Lars Luthman
2006-04-23 15:16:11 UTC
Permalink
Post by Florian Schmidt
On Sun, 23 Apr 2006 13:39:52 +0100
Post by Steve Harris
Post by Florian Schmidt
thanks for taking the initiative on this! I would like to see a way for
the host to pass its native buffer size to the plugin though. I know,
this is really kind of contrary to how LADSPA is supposed to work (i.e.
the run () function should be able to handle an arbitrary number of
frames), but it has some serious advantages for fft-based algorithms.
And i think it should be possible to merge the two approaches somewhat.
Thats a new feature. It'll have to wait til after 2.0 as far as I'm
concerned.
I tend to disagree as it is kinda orthogonal to the other proposed
changes. What time other than a major version change is better to add
such a feature?
Aw hell, i'll try to get this into DSSI 2 then ;)
Couldn't it be done as an extension using the "features" parameter to
the instantiation function? If the host supports fixed buffer sizes it
can pass "FIXEDSIZE" or something in the features array, and the plugin
can add some sort of flag in the TTL file that says that it wants to be
called with a fixed buffer size. No need to add it explicitly in the
LADSPA2 specification.

Then, when the plugin sees that the host has the "FIXEDSIZE" feature, it
will know that the buffer size will always be the same. Hosts that don't
support this extension will ignore the flag in the TTL file and will not
pass the "FIXEDSIZE" feature to the instantiation function, and the
plugin can then either return NULL from that function, or switch
automatically to less efficient code that does not need a fixed buffer
size.
--
Lars Luthman
PGP key: http://www.student.nada.kth.se/~d00-llu/pgp_key.php
Fingerprint: FCA7 C790 19B9 322D EB7A E1B3 4371 4650 04C7 7E2E
Steve Harris
2006-04-23 18:46:04 UTC
Permalink
Post by Florian Schmidt
On Sun, 23 Apr 2006 13:39:52 +0100
Post by Steve Harris
Post by Florian Schmidt
thanks for taking the initiative on this! I would like to see a way for
the host to pass its native buffer size to the plugin though. I know,
this is really kind of contrary to how LADSPA is supposed to work (i.e.
the run () function should be able to handle an arbitrary number of
frames), but it has some serious advantages for fft-based algorithms.
And i think it should be possible to merge the two approaches somewhat.
Thats a new feature. It'll have to wait til after 2.0 as far as I'm
concerned.
I tend to disagree as it is kinda orthogonal to the other proposed
changes. What time other than a major version change is better to add
such a feature?
Generally, I'd agree, but in this case I think it's a bad time. We need to
make sure we dont introduce anything that wierds the spec.

It changes both plugin and host code, so it will be easier to add things
once both have settled down, and the rought edges have been knocked off.

- Steve
Loading...