JoyOfHardware / FastWave2.0

GNU General Public License v3.0
0 stars 0 forks source link

Decoders #14

Closed MartinKavik closed 3 weeks ago

MartinKavik commented 3 weeks ago

Decoders are plugins/extensions/components adding custom functionality to FastWave, primarily extending waveform visualizer. Decoders have been implemented as Wasm components defined by WebAssembly Component Model in this PR. The Model and related libraries have been created by Bytecode Alliance, a nonprofit organization founded 2019 by Mozilla, Fastly, Intel and Red Hat with current members like Amazon, Cisco, Docker or Microsoft. The Component Model and tools for writing and using components are still very young but a major milestone has been achieved January 2024 when a stable release of WASI (WebAssembly System Interface) and the component model has been published. Most Bytecode Alliance tools are written in Rust and Rust seems to be the top priority that's why Rust components work best. Rust components are also most suitable for FastWave because both are written in Rust and the components don't need a runtime like Javascript or Python compoments. There are plans to share language-specific runtimes among components to reduce overhead and component loading time. The host system (Wasmtime by Bytecode Alliance in our case) communicates with Guests (aka Decoders in our case) through interfaces defined in *.wit files with WIT (Wasm Interface Type) language.

In practice, Rust component/decoder Wasm module size is around 27 KB, Javascript component has 10 MB and Python around 35 MB. Loading time of such components seems to correspond to the size of the component and it's much higher in debug mode. Javascript and Python components need linked WASI to work properly, Rust component can be compiled for both wasm32-unknown-unknown andwasm32-wasi` target. I also found a problem with calling host functions in Python, probably caused by a bug in a dispatch mechanism in the Componentize-py tool. That's why I would recommend to focus mainly on Rust components until support for other languages are better. Officially supported languages are currently Rust, Javascript, Python and Go. I wouldn't recommend to switch to alternative plugins systems like Extism because they often already use Wasmtime under the hood and plan to migrate to The Component Model once it's stable enough. Another advantage is that users need only tools native to the component language - e.g. users writing Javascript decoders need only tools published in NPM. Another option would be to integrate language runtimes directly into FastWave but I think it'll be costly in the long run because of maintenance and the need to add support for all languages one by one and it will be much less secure because there won't be Wasm "sandbox" enclosing the code in plugins.

There were two other implementation "surprises":

  1. When calling component methods panics, it fails with error "Cannot start a runtime from within a runtime.". I think it's caused by running Wasmtime runtime inside Tauri runtime but it seems to be a Wasmtime problem and a workaround is to call component methods inside an std thread. It needs more investigation but it isn't a showstopper.
  2. There is a helper function in signal_to_timeline.rs:
    fn type_hint<F>(f: F) -> F
    where
      F: for<'a> FnMut((u32, SignalValue<'a>)) -> (f64, SignalValue<'a>),
    {
      f
    }

    that is used to only provide a type hint to a closure inside async function representing a Tauri command. It seems to be a very annoying Rust compiler issue already described in the main Rust repo. The error message is "Implementation of FnOnce is not general enough" pointing to a different code location.

Decoders are defined by this WIT file: screenshot_world_wit

And there is a video of implemented decoders loaded through FastWave Javascript Command Interface: video_decoders

(Both files are included in README)

Testing decoders are located in testing_files/components in the repo. Each component/decoder contains README describing how to create and build the particular component.