-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a design/goals document to detail guidelines for the project #99
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with most of the contents of this document. My strongest concern is that implementing the LV2 specifications fully is maybe too ambitious for the resources we have.
are usually user-written, and writing them incorrectly is likely to trigger Undefined Behavior, in both the plugin and | ||
the host. | ||
|
||
Higher-level, more specialized libraries and frameworks that rely on LV2 should probably auto-generate those files based on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would consider what other crates do to be out-of-scope of this document. I would write "Higher-level libraries and frameworks that rely on LV2 can probably auto-generate those files based on plugin code and metadata."
if that makes it less practical to use for direct users of the `lv2` crates. | ||
|
||
## No restrictions coming from C | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Supporting every single possibility of the LV2 specification is a nice goal. I would also like to take into account that we probably don't have a lot of (developer) resources to build and maintain this crate. So I think it would be good to prioritize features based on demand, host support and "contributor eagerness". Also, I'm not sure if we really need everything before version 1.0. E.g. deprecated specifications like Event
are something I would not put any effort in. Also, the LV2 specification is a moving target, so it may not be feasible to have every feature implemented and to keep this crate on par with the LV2 specification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, I absolutely agree there. I should make this more clear, but this is more of a vision/design goals document, not a roadmap or prioritization document.
This means that while I probably won't push for the less-demanded (or supported) features before a little while (read: some years), I will still accept contributions for them.
Deprecated specifications should probably be implemented at least for hosts (when we support them properly), if they want to be compatible with older plugins. However, I agree this is not really a priority for now.
I agree that ideally, we should only need a viable library before reaching 1.0, and we could add the remaining specs on top of it afterwards. However, I've many times had the experience where adding an extra spec breaks many invariants and assumptions that other specs rely on, and require making breaking changes.
For instance, implementing Option
requires a refactor of Atom
to be actually usable, Instance Access
and Data Access
break both the single-threadedness and exclusivity invariants of lv2_core
(basically requiring plugins to be Sync
instead of just Send
, and preventing any form of &mut
reference to ever exist on a plugin instance), and implementing UI
will probably break something that I haven't seen coming yet. 🙃
I will add those clarifications to the document. 🙂
cannot do what they want. Examples of work LV2 plugins should defer to the host are I/O buffers and communication, state | ||
serialization (i.e., presets / session loading and saving), asynchronous processing, or UI communication. | ||
|
||
In that aspect, LV2 plugins and hosts share very similar behaviors with Rust's own |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with futures and executors (i didn't ), so I don't fully understand this section. Would it be possible to reword this section so that people can understand it without knowledge about futures and executors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, re-reading this I realize this is a bit more of me rambling about LV2's API (compared to others like VST) more than anything else. I will reword (if not completely remove), as it's more of an example to illustrate the rest of this section.
is definitely Undefined Behavior. | ||
|
||
In this case, this ergonomic helper is necessary to produce safe code, and is not considered optional: the | ||
`PortCollection` abstraction cannot be bypassed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the PortCollection
abstraction can in fact be bypassed: it can be implemented outside of the lv2
crate. For rsynth
, this is in fact desirable, otherwise it's hard to abstract over different API's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is an unclear wording issue. The PortCollection
trait itself cannot be bypassed: the Plugin
trait (among others) rely heavily on it. However, the PortCollection
derive macro can be bypassed, and you can implement PortCollection
however you like outside of the lv2
crate, which, as you say, is useful if you want to make your own abstraction.
In that specific case, I consider the PortCollection
trait to be necessary for safe operation, and the PortCollection
derive macro to be the optional syntax sugar layer on top (like all derive macros in rust-lv2
are).
Will fix this as well. 🙂
## Extra ergonomics and sugar | ||
Also, while ergonomics and extra utilities are nice to have in this library sometimes, they *must* be optional to use. | ||
Indeed, because of the goal to be a low-level library, we must not prevent the user from doing custom things themselves | ||
at the cost of complexity. At least, as long as it is safe for them to do so. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A safe abstraction usually introduces some ergonomics, so I wouldn't say that this must be optional.
I think designing safe abstractions will very often come with hard choices: a more complicated API, some runtime overhead (see previous section for that), something that is hard to maintain or exposing unsafe methods or traits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, what I meant here was ergonomic*-only* APIs should be optional (like the derive macros cited in the other comment), not all APIs that happen to be more ergonomic that raw LV2's.
Pretty much all safe APIs are more ergonomic than LV2's anyway. 🙃
I agree that API design comes with hard choices. I forgot to make it explicit in the DESIGN
document (which isn't completed anyway), but this is what it is about: the list at the beginning is in order of most important to least important.
For example, when it comes to the lv2
crate, Memory Safety will be chosen in favored of C Parity or Performance, all of which are considered more important than Ergonomics (which is quite low the list).
Again, will fix that. Thanks a lot for your remarks, they are quite helpful! 🙂
With the departure of @Janonard as a maintainer, and new contributors coming in, I thought this might be a good time to write down all of my ideas and goals for the
lv2
crate(s). This way less time can be spent teaching contributors and users what this crate is and isn't supposed to do.I created a
GOALS.md
file detailing all of this (Rendered), and there is also aDESIGN.md
file (Rendered) detailing guidelines for API design, although it is still a WIP for now.As of right now, I do not consider those as final at all. Those are my ideas for now, but any other ideas or discussions about those in the document are welcome to debate and discuss in depth in this PR. 🙂