Rust Audio

Rust-lv2 book repository

Hello everyone!

The rust-lv2 project has made some nice progress lately and I would like to begin with the “translation” of the lv2 book, as I’ve done before. Could someone with permission create a repo called rust-lv2-book, please?

This book is a very general guide on how to create LV2 plugins, but since it is written for C applications, it doesn’t really apply to Rust; Especially not to our abstractions. Therefore, I would like to “translate” the book into the rust-lv2 ecosystem to give users a jump start into plugin creation. Translating the book during crate development also acts as a realistic integration test and as an indicator to it’s progress.

1 Like

@doomy , do you know who can help @Janonard with this?

Any progress here? Telling from @Yruama_Lairba’s experience, it would help a lot if the book would move to the RustAudio group.

Hi, to contribute to the Rust-lv2 book, i’m currently trying to adapt the metronome example to rust. Anyone interested to look at it when it will be working ? i’d like to know if i do it in an idiomatic/expected way. I also realize that i could (and i probably will) implement a “lv2_time” crate similar to “lv2_units”, it will be useful for plugin manipulating time data like metronome.

You won’t be able to properly port the metronome to Rust since the required specifications aren’t implemented yet, at least not by the rust-lv2 ecosystem.

However, your will to contribute is very much appreciated! If you want to push the rust-lv2-ecosystem, it would be best if you would try to implement the state or the worker specification. These are current blockers, since all unadapted examples depend on it.

What unimplemented part of the specification is required for metronome ? I think i’m close to make it work, but i may did it in the dirty way. Several part of the framework still obscure to me. In particular, i didn’t understand all the philosophy behind atom.read(urid)

For state or worker i may not enough skilled yet to implement it.

Hi again, i just finished a prototype of the metro example, you can see it here (i forked the rust-lv2-book). I’d like to have a comment about how things was expected to be done, even if some stuff aren’t yet implemented.

2 Likes

First of all, I’m sorry for being conspicuous that you can not implement this example. I’ve stopped implementing examples in the belief that I can not continue without implementing more specifications. Although this was technically true, there is only the Time spec missing for the metronome. I’m sorry!

First of all, the atom.read thing: Internally an atom is a header and a slice of memory. The header contains the length of the atom, as well as it’s type, encoded as a URID. Most of the handles that read atoms have a read method that is generic over the type of atom to read. To identify the atom, this read method needs to know it’s URID since it is generated by the host. Assuming that you have an UnidentifiedAtom called atom and a cache that contains all relevant URIDs, you would expect to write something like this:

let integer: i32 = atom.read::<Int>(cache.int, ()).unwrap();

However, most URIDs have a type parameter, in our case Int, which has to be the same as the type parameter of the method. Since the type parameter of the URID already known, you can elide it. This leads to the following code:

let integer: i32 = atom.read(cache.int, ()).unwrap();

I hope that explains why the atom API is like it is. Now, let’s move on to your plugin: First, you’re basically doing the job of the lv2_time crate, which is fine since it doesn’t exist yet. I would love it if you could flesh it out and contribute it to rust_lv2, it would help both the library as well as the book!

Next, you’re doing pretty standard LV2 plugin stuff, which is nice. However, you could and should put all URIDs into a custom struct and implement URIDCache for it using the derive macro. It looks better and is reusable:

#[derive(URIDCache)]
struct TimeURIDCache {
    position: URID<TimePosition>,
    ...
}

I haven’t looked into your logic with much detail yet, but it looks pretty similar to the one from the C book. If you like, you could also refactor that code to use more of Rust’s features, especially slices and iterators. Some minor detail: In the new method, you should rename _plugin_info to plugin_info. You’re using it, there’s no need for the underscore. Also, you should run the formatter and Clippy over it to align it to the general coding style.

I’ve tried to run it in Carla, but it didn’t create any output. Which plugin host do you use?

I used ardour5 during the development. It also work with jalv. I quickly tested with carla, there an event-in input and an sound output. I think i need to connect something in the event-in to make it work here, but i don’t know what.

I figured it out: You don’t have to connect the plugin to anything, Carla just sends the time information as a Blank instead of an Object. A Blank is basically the same as an Object, but without a class ID. The standard has deprecated it in favor of an Object with a class URID of 0, but Carla still uses it.

I’ve bodged this into your code by implementing the Blank type, which is basically an alias for Object, and uploading it to my repo.

This means several things: Before your example can be pulled into the book, the time specification as well as the Blank atom have to be properly implemented by rust-lv2. I will also test if the current release candidate for Carla has the same behavior and report it as a bug, if this is the case.