free-audio / clap

Audio Plugin API
https://cleveraudio.org/
MIT License
1.79k stars 102 forks source link

Define rules for plugin Id #159

Closed falkTX closed 1 year ago

falkTX commented 2 years ago

The id of a plugin as seen in https://github.com/free-audio/clap/blob/main/include/clap/plugin.h#L17 seems to be quite an important value. It does not have any documentation or rules whatsoever though, only an example.

What values are valid here? Is this meant to be a global, unique id? Should hosts use this value to refer to plugins? (or is binary name preferred?) What happens if 2 different plugins end up with the same id?

robbert-vdh commented 2 years ago

What values are valid here?

The idea is to use reverse URIs here, but in the end it's just a string and any random UTF-8 C-string should be valid.

Is this meant to be a global, unique id?

Yes, it's the same thing as the 32-bit uniqueID in VST2, the 128-bit CID in VST3, and the plugin URI in LV2.

Should hosts use this value to refer to plugins? (or is binary name preferred?)

Like with the above mentioned equivalents in VST2, VST3, and LV2, the host should use this to refer to the plugin. Binary names should not be taken into account. So if I save a project with a CLAP plugin, close the DAW, and rename the .clap file to something else, the project should still load.

What happens if 2 different plugins end up with the same id?

The same thing as when two VST2 plugins have the same integer ID, two VST3 plugins have the same UID, or two LV2 plugins have the same plugin URI. The host probably either prioritizes the first or the last one it scanned, or it will show an error message to the user and completely refuse to load either.

baconpaul commented 2 years ago

I think adding a line to the documentation encouraging a reverse uri is smart though

falkTX commented 2 years ago

Thanks for the clarifications!

What happens if 2 different plugins end up with the same id?

The same thing as when two VST2 plugins have the same integer ID, two VST3 plugins have the same UID, or two LV2 plugins have the same plugin URI. The host probably either prioritizes the first or the last one it scanned, or it will show an error message to the user and completely refuse to load either.

This is not quite correct for the LV2 case. When the same LV2 plugin is available from 2 places, due to versioning the host loads whichever has the highest version, if such thing is provided by the plugin.

CLAP can show versions, but only as a string. So reliable version comparisons aren't possible. I will open a separate issue about this later.

Back on the topic, would be great to have a guideline for what constitutes a valid id, before plugins start using random things. Consistency will be nice. VST uses numbers, so we always end up with valid values, LV2 just reuses URIs so can use those definitions.

For reverse URIs, is this a standard? Perhaps we can just have API docs say something like "id is a reverse URI as defined by RFC 1234". Referring to an existing naming scheme / standard also helps in validating plugins.

baconpaul commented 2 years ago

https://en.m.wikipedia.org/wiki/Reverse_domain_name_notation is probably the most concise reference but Java standards and the apple document it links seem like good ones too and I think we should encourage authors to use that in the doc.

but any utf8 string is valid. And we don’t enforce anything other than valid utf8.

baconpaul commented 2 years ago

We can also make the validator spout a warning if you don’t have foo.bar.blahblab where bar.foo is dns resolvable perhaps?

robbert-vdh commented 2 years ago

We can also make the validator spout a warning if you don’t have foo.bar.blahblab where bar.foo is dns resolvable perhaps?

I don't think this needs to be enforced, does it? It's for instance also fairly a common convention to use something like me.username.foo if you don't have or want a website or something for your project foo. And in the end, while the intended and most common kind of plugin ID is a reverse DNS, as long it's valid UTF-8 (and the validator does implicitly check for that) the host doesn't really have a reason to care about the specifics.

I guess it could do checks like that for the manual and support URLs, but these kinds of checks may be prone to spurious failures and I don't know if it's important enough to warrant pulling in an entire HTTP library.

falkTX commented 2 years ago

I disagree with online checks too. even for LV2 where the URI can look like a real URL, it is never mandated it needs to be a real thing that exists. Otherwise it becomes more than just an id.

Still think we need a set of rules here. Otherwise we will end up with ids that have spaces, emojis and other random stuff. I mean, it is all valid utf-8 but having "🐕" as valid id feels very very wrong.

robbert-vdh commented 2 years ago

":dog2:" is a completely valid domain name though, so even if there'd be a rule that plugin IDs must be valid (reverse) domain names then that would still be allowed. I don't see much point in mandating anything other than valid UTF-8 here. The DAW doesn't care if they're reverse domain names or haikus when it inserts it in a hash map for future lookups.

sagamusix commented 2 years ago

If the only intent for the ID is to be unique, why not go for UUIDs? Unless you deliberately copy an existing UUID, it's pretty much guaranteed to be unique, because that's what they were made for, while I can imagine that more than one developer will use "CoolSynth" or "my.cool.synth" (or something along those lines, you get the idea) as an ID if the only encouragement from documentation is to use a random string or reverse domain name.

IDEs like Visual Studio have single-click solutions to insert UUIDs into code, and for everyone who doesn't use such IDEs, a link to a website like https://www.uuidgenerator.net/ could be placed in the docs.

robbert-vdh commented 2 years ago

Because they're human readable. I know that org.surge-synth-team.surge-xt is Surge XT. I wouldn't be able to tell which plugin 263362425623591446280099228865684080719 is if that is a randomly generated number.

sagamusix commented 2 years ago

But you already know that from the name and vendor field, don't you? Why does the ID need to be human-readable?

robbert-vdh commented 2 years ago

How do I get the name and vendor fields when all I have is an ID? DAWs could store all of the plugin's metadata instead of just an ID, but having human readable IDs is a good compromise and the reverse domain name convention protects against clashes better than a random fixed size ID would.

baconpaul commented 2 years ago

I disagree with online checks too. even for LV2 where the URI can look like a real URL, it is never mandated it needs to be a real thing that exists. Otherwise it becomes more than just an id.

Still think we need a set of rules here. Otherwise we will end up with ids that have spaces, emojis and other random stuff. I mean, it is all valid utf-8 but having "🐕" as valid id feels very very wrong.

You should totally add this as a test case to every host. (True: It broke bitwig when we tried and bitwig tested it).

There's no reason that people can't use UTF8 strings for any string in CLAP.

baconpaul commented 2 years ago

If the only intent for the ID is to be unique, why not go for UUIDs?

Nothing stops you doing that. A UUID is a valid UTF-8 string.

abique commented 2 years ago

Hi,

Plugin id, this is a null terminated string that should be unique enough to not clash with other plugins. I personally don't mind what the plugin id look like, it just need to be "unique". If it is a string encoded uuid, then it won't be convenient when debugging, hacking a project file or simply showing it to the user, but it isn't an issue for me, and it is up to the plugin vendor to decide.

u-he could have named their plugins u-he:diva that would have worked too, and another company could have name them com.company.Plug.

Version, yes it is an arbitrary string, but 99% will follow common patterns, so I'm not very concerned here, and worst case if you can't decide which version to pick, then you can still delegate that question to the user.

Cheers, Alex

defiantnerd commented 2 years ago

I agree with @abique, I would suggest using a reverse URI identifier. Try to be consistent, since the plugin_id is also being used to generate UUIDs for the wrappers.