Skip to content

aidan729/nice-plug-slint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nice-plug-slint

An adapter for using Slint GUIs with nice-plug audio plugins. It uses baseview for windowing and FemtoVG (OpenGL) for rendering.

Example

I took the liberty of creating a simple gain knob VST example project using nice-plug and Nice-Plug-Slint.

please see that here: Gain Knob

Usage

Add the dependency:

[dependencies]
nice_plug_slint = { git = "https://github.com/aidan729/nice-plug-slint" }

In your plugin:

use nice_plug_slint::{SlintEditor, SlintEditorState};
use std::sync::Arc;

#[derive(Params)]
struct MyParams {
    #[persist = "editor-state"]
    editor_state: Arc<SlintEditorState>,
}

impl Default for MyParams {
  fn default() -> Self {
    Self {
      editor_state: Arc::new(SlintEditorState::new(400, 300)),
    }
  }
}

fn editor(&mut self, _async_executor: AsyncExecutor<Self>) -> Option<Box<dyn Editor>> {
    Some(Box::new(
        SlintEditor::new(params.editor_state.clone(), || gui::AppWindow::new())
            .with_setup({
                let params = self.params.clone();
                move |handler, _window| {
                    let component = handler.component();
                    let context = handler.context().clone();

                    // Register UI -> plugin callbacks once when the window opens
                    component.on_gain_changed(move |value| {
                        let setter = ParamSetter::new(&*context);
                        setter.begin_set_parameter(&params.gain);
                        setter.set_parameter_normalized(&params.gain, value);
                        setter.end_set_parameter(&params.gain);
                    });
                }
            })
            .with_event_loop({
                let params = self.params.clone();
                move |handler, _setter, _window| {
                    // Push parameter values to the UI each frame
                    handler.component().set_gain(params.gain.unmodulated_normalized_value());
                }
            }),
    ))
}

API

SlintEditorState

Holds the window size. Construct with Arc::new(SlintEditorState::new(w, h)). It should be stored on your params struct with the #[persist] attribute to persist the state across sessions.

SlintEditor

Created with SlintEditor::new(state, factory).

The first argument is the editor state which comes from the params struct. See SlintEditorState.

The second argument is the factory closure which is called each time the window is opened.

  • .with_setup(handler) - called once when the window opens, before the event loop starts. Use this to register UI → plugin callbacks.
  • .with_event_loop(handler) - called every frame. Use this to push parameter values to the UI (plugin → UI).

WindowHandler

Passed to the event loop handler. Gives you access to:

  • .component() - the Slint component
  • .window() - the Slint window
  • .context() - nice-plug's GuiContext for parameter operations
  • .resize(window, width, height) - resize the window programmatically
  • .queue_resize(width, height) - use this from inside Slint callbacks instead of calling resize directly, since you won't have the &mut Window handy
// Resizing from a Slint callback
let pending = handler.pending_resizes().clone();
component.on_resize(move || {
    pending.borrow_mut().push((800, 600));
});

Architecture

See docs/ARCHITECTURE.md for more detail on how the Slint/baseview bridge works internally.

License

ISC

Credits

About

A Slint Bridge for the Nice-Plug project.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages