Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ilya-epifanov committed Feb 24, 2024
1 parent b2586de commit bbb5c09
Show file tree
Hide file tree
Showing 16 changed files with 1,979 additions and 1,276 deletions.
2,317 changes: 1,444 additions & 873 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ description = "A simple but modern API-agnostic audio plugin framework"
repository = "https://github.com/robbert-vdh/nih-plug"

[workspace]
resolver = "2"

members = [
"nih_plug_derive",
"nih_plug_egui",
Expand Down
2 changes: 1 addition & 1 deletion nih_plug_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ quote = "1.0"
proc-macro2 = "1.0"

[dev-dependencies]
nih_plug = { path = ".." }
nih_plug = { path = "..", default-features = false }
2 changes: 1 addition & 1 deletion nih_plug_egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ default_fonts = ["egui-baseview/default_fonts"]
rayon = ["egui-baseview/rayon"]

[dependencies]
nih_plug = { path = ".." }
nih_plug = { path = "..", default-features = false }
raw-window-handle = "0.5"
baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "2c1b1a7b0fef1a29a5150a6a8f6fef6a0cbab8c4" }
crossbeam = "0.8"
Expand Down
52 changes: 16 additions & 36 deletions nih_plug_iced/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license = "ISC"
description = "An adapter to use iced GUIs with NIH-plug"

[features]
default = ["opengl"]
default = []

# NOTE: wgpu support has been removed from the iced-baseview fork out because
# this old iced version uses a wgpu version that doesn't pin the web-sys
Expand All @@ -20,53 +20,33 @@ default = ["opengl"]
# wgpu = ["iced_baseview/wgpu", "baseview/opengl"]
# Use OpenGL instead of wgpu for the rendering. This should increase platform
# compatibility at the cost of some iced features not being available.
opengl = ["iced_baseview/glow"]
# opengl = ["iced_baseview/glow"]

# Enables a debug view in native platforms (press F12)
debug = ["iced_baseview/debug"]

# # Enables the `Image` widget, only supported by the wgpu backend
# wgpu_image = ["iced_baseview/wgpu_image"]
# # Enables the `Svg` widget, only supported by the wgpu backend
# wgpu_svg = ["iced_baseview/wgpu_svg"]

# # Enables the `Canvas` widget for the wgpu backend
# wgpu_canvas = ["iced_baseview/wgpu_canvas"]
# Enables the `Canvas` widget for the OpenGL backend
opengl_canvas = ["iced_baseview/glow_canvas"]

# # Enables the `QRCode` widget for the wgpu backend
# wgpu_qr_code = ["iced_baseview/wgpu_qr_code"]
# Enables the `QRCode` widget for the OpenGL backend
opengl_qr_code = ["iced_baseview/glow_qr_code"]

# # Enables using system fonts for the wgpu backend
# wgpu_default_system_font = ["iced_baseview/wgpu_default_system_font"]
# Enables using system fonts for the OpenGL backend
opengl_default_system_font = ["iced_baseview/glow_default_system_font"]

# Enables advanced color conversion via `palette`
palette = ["iced_baseview/palette"]

# Enables `tokio` as the `executor::Default` on native platforms
tokio = ["iced_baseview/tokio"]
# Enables `async-std` as the `executor::Default` on native platforms
async-std = ["iced_baseview/async-std"]
# Enables `smol` as the `executor::Default` on native platforms
smol = ["iced_baseview/smol"]
wgpu = ["iced_baseview/wgpu"]
# Enables the `Image` widget, only supported by the wgpu backend
image = ["iced_baseview/image"]
# Enables the `Svg` widget, only supported by the wgpu backend
svg = ["iced_baseview/svg"]
# Enables the `Canvas` widget for the wgpu backend
canvas = ["iced_baseview/canvas"]

[dependencies]
nih_plug = { path = ".." }
nih_plug = { path = "..", default-features = false }
nih_plug_assets = { git = "https://github.com/robbert-vdh/nih_plug_assets.git" }

# The currently targeted version of baseview uses a different version of
# `raw_window_handle` than NIH-plug, so we need to manually convert between them
raw-window-handle = "0.4"
raw-window-handle = "0.5"

atomic_refcell = "0.1"
baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "1d9806d5bd92275d0d8142d9c9c90198757b9b25" }
baseview = { git = "https://github.com/RustAudio/baseview.git", rev = "fdb43ea" }
crossbeam = "0.8"
# This targets iced 0.4
iced_baseview = { git = "https://github.com/robbert-vdh/iced_baseview.git", branch = "feature/update-baseview", default_features = false }
# This targets iced 0.10
iced_baseview = { git = "https://github.com/BillyDM/iced_baseview.git", rev = "4feacc03bc1135023f73167093aea953a858a7c2", default_features = false }
futures-util = "0.3"

# To make the state persistable
serde = { version = "1.0", features = ["derive"] }
72 changes: 32 additions & 40 deletions nih_plug_iced/src/assets.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,38 @@
//! Binary assets for use with `nih_plug_iced`.
use crate::Font;
use std::borrow::Cow;

use crate::core::Font;

use iced_baseview::runtime::{font, Command};
// This module provides a re-export and simple font wrappers around the re-exported fonts.
pub use nih_plug_assets::*;

pub const NOTO_SANS_REGULAR: Font = Font::External {
name: "Noto Sans Regular",
bytes: fonts::NOTO_SANS_REGULAR,
};

pub const NOTO_SANS_REGULAR_ITALIC: Font = Font::External {
name: "Noto Sans Regular Italic",
bytes: fonts::NOTO_SANS_REGULAR_ITALIC,
};

pub const NOTO_SANS_THIN: Font = Font::External {
name: "Noto Sans Thin",
bytes: fonts::NOTO_SANS_THIN,
};

pub const NOTO_SANS_THIN_ITALIC: Font = Font::External {
name: "Noto Sans Thin Italic",
bytes: fonts::NOTO_SANS_THIN_ITALIC,
};

pub const NOTO_SANS_LIGHT: Font = Font::External {
name: "Noto Sans Light",
bytes: fonts::NOTO_SANS_LIGHT,
};

pub const NOTO_SANS_LIGHT_ITALIC: Font = Font::External {
name: "Noto Sans Light Italic",
bytes: fonts::NOTO_SANS_LIGHT_ITALIC,
};

pub const NOTO_SANS_BOLD: Font = Font::External {
name: "Noto Sans Bold",
bytes: fonts::NOTO_SANS_BOLD,
};

pub const NOTO_SANS_BOLD_ITALIC: Font = Font::External {
name: "Noto Sans Bold Italic",
bytes: fonts::NOTO_SANS_BOLD_ITALIC,
};
pub const NOTO_SANS_REGULAR: Font = Font::with_name("Noto Sans Regular");
pub const NOTO_SANS_REGULAR_ITALIC: Font = Font::with_name("Noto Sans Regular Italic");
pub const NOTO_SANS_THIN: Font = Font::with_name("Noto Sans Thin");
pub const NOTO_SANS_THIN_ITALIC: Font = Font::with_name("Noto Sans Thin Italic");
pub const NOTO_SANS_LIGHT: Font = Font::with_name("Noto Sans Light");
pub const NOTO_SANS_LIGHT_ITALIC: Font = Font::with_name("Noto Sans Light Italic");
pub const NOTO_SANS_BOLD: Font = Font::with_name("Noto Sans Bold");
pub const NOTO_SANS_BOLD_ITALIC: Font = Font::with_name("Noto Sans Bold Italic");

/// Useful for initializing the Settings, like this:
/// ```rust
/// Settings {
/// ...
/// fonts: noto_sans_fonts_data().into_iter().collect(),
/// }
/// ```
pub const fn noto_sans_fonts_data() -> [Cow<'static, [u8]>; 8] {
[
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_REGULAR),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_REGULAR_ITALIC),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_THIN),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_THIN_ITALIC),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_LIGHT),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_LIGHT_ITALIC),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_BOLD),
Cow::Borrowed(nih_plug_assets::fonts::NOTO_SANS_BOLD_ITALIC),
]
}
24 changes: 14 additions & 10 deletions nih_plug_iced/src/editor.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
//! And [`Editor`] implementation for iced.
use baseview::{WindowOpenOptions, WindowScalePolicy};
use ::baseview::{WindowOpenOptions, WindowScalePolicy};
use crossbeam::atomic::AtomicCell;
use crossbeam::channel;
pub use iced_baseview::*;
use iced_baseview::settings::IcedBaseviewSettings;
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use std::sync::atomic::Ordering;
use std::{borrow::Cow, sync::atomic::Ordering};
use std::sync::Arc;

use crate::{wrapper, IcedEditor, IcedState, ParameterUpdate};

pub use iced_baseview::*;

/// An [`Editor`] implementation that renders an iced [`Application`].
pub(crate) struct IcedEditorWrapper<E: IcedEditor> {
pub(crate) iced_state: Arc<IcedState>,
pub(crate) initialization_flags: E::InitializationFlags,
pub(crate) fonts: Vec<Cow<'static, [u8]>>,

/// The scaling factor reported by the host, if any. On macOS this will never be set and we
/// should use the system scaling factor instead.
Expand All @@ -33,17 +36,17 @@ unsafe impl HasRawWindowHandle for ParentWindowHandleAdapter {
fn raw_window_handle(&self) -> RawWindowHandle {
match self.0 {
ParentWindowHandle::X11Window(window) => {
let mut handle = raw_window_handle::XcbHandle::empty();
let mut handle = raw_window_handle::XcbWindowHandle::empty();
handle.window = window;
RawWindowHandle::Xcb(handle)
}
ParentWindowHandle::AppKitNsView(ns_view) => {
let mut handle = raw_window_handle::AppKitHandle::empty();
let mut handle = raw_window_handle::AppKitWindowHandle::empty();
handle.ns_view = ns_view;
RawWindowHandle::AppKit(handle)
}
ParentWindowHandle::Win32Hwnd(hwnd) => {
let mut handle = raw_window_handle::Win32Handle::empty();
let mut handle = raw_window_handle::Win32WindowHandle::empty();
handle.hwnd = hwnd;
RawWindowHandle::Win32(handle)
}
Expand All @@ -62,7 +65,7 @@ impl<E: IcedEditor> Editor for IcedEditorWrapper<E> {

// TODO: iced_baseview does not have gracefuly error handling for context creation failures.
// This will panic if the context could not be created.
let window = IcedWindow::<wrapper::IcedEditorWrapperApplication<E>>::open_parented(
let window = iced_baseview::open_parented::<wrapper::IcedEditorWrapperApplication<E>, _>(
&ParentWindowHandleAdapter(parent),
Settings {
window: WindowOpenOptions {
Expand Down Expand Up @@ -96,8 +99,8 @@ impl<E: IcedEditor> Editor for IcedEditorWrapper<E> {
// FIXME: Rust analyzer always thinks baseview/opengl is enabled even if we
// don't explicitly enable it, so you'd get a compile error if this line
// is missing
#[cfg(not(feature = "opengl"))]
gl_config: None,
// #[cfg(not(feature = "opengl"))]
// gl_config: None,
},
iced_baseview: IcedBaseviewSettings {
ignore_non_modifier_keys: false,
Expand All @@ -109,6 +112,7 @@ impl<E: IcedEditor> Editor for IcedEditorWrapper<E> {
self.parameter_updates_receiver.clone(),
self.initialization_flags.clone(),
),
fonts: self.fonts.clone(),
},
);

Expand Down Expand Up @@ -154,7 +158,7 @@ impl<E: IcedEditor> Editor for IcedEditorWrapper<E> {
/// The window handle used for [`IcedEditorWrapper`].
struct IcedEditorHandle<Message: 'static + Send> {
iced_state: Arc<IcedState>,
window: iced_baseview::WindowHandle<Message>,
window: iced_baseview::window::WindowHandle<Message>,
}

/// The window handle enum stored within 'WindowHandle' contains raw pointers. Is there a way around
Expand Down
38 changes: 27 additions & 11 deletions nih_plug_iced/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,20 @@
//! }
//! ```
use baseview::WindowScalePolicy;
use ::baseview::WindowScalePolicy;
use crossbeam::atomic::AtomicCell;
use crossbeam::channel;
use iced_baseview::core::{Color, Element, Font};
use iced_baseview::futures::{Executor, Subscription};
use iced_baseview::graphics::Antialiasing;
use iced_baseview::runtime::Command;
use iced_baseview::style::application::StyleSheet;
use iced_baseview::widget::renderer::Settings as RendererSettings;
use iced_baseview::window::WindowSubs;
use nih_plug::params::persist::PersistentField;
use nih_plug::prelude::{Editor, GuiContext};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
// This doesn't need to be re-export but otherwise the compiler complains about
// `hidden_glob_reexports`
pub use std::fmt::Debug;
Expand Down Expand Up @@ -126,6 +134,7 @@ mod wrapper;
pub fn create_iced_editor<E: IcedEditor>(
iced_state: Arc<IcedState>,
initialization_flags: E::InitializationFlags,
fonts: Vec<Cow<'static, [u8]>>,
) -> Option<Box<dyn Editor>> {
// We need some way to communicate parameter changes to the `IcedEditor` since parameter updates
// come from outside of the editor's reactive model. This contains only capacity to store only
Expand All @@ -147,6 +156,7 @@ pub fn create_iced_editor<E: IcedEditor>(

parameter_updates_sender,
parameter_updates_receiver: Arc::new(parameter_updates_receiver),
fonts,
}))
}

Expand All @@ -162,6 +172,8 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
type Message: 'static + Clone + Debug + Send;
/// See [`Application::Flags`].
type InitializationFlags: 'static + Clone + Send + Sync;
/// See [`Application::Theme`]
type Theme: Default + StyleSheet;

/// See [`Application::new`]. This also receivs the GUI context in addition to the flags.
fn new(
Expand All @@ -179,7 +191,6 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
/// [`handle_param_message()`][Self::handle_param_message()] to handle the parameter update.
fn update(
&mut self,
window: &mut WindowQueue,
message: Self::Message,
) -> Command<Self::Message>;

Expand All @@ -192,13 +203,21 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
}

/// See [`Application::view`].
fn view(&mut self) -> Element<'_, Self::Message>;
fn view(&self) -> Element<'_, Self::Message, Renderer<Self::Theme>>;

/// See [`Application::background_color`].
fn background_color(&self) -> Color {
Color::WHITE
}

fn theme(&self) -> Self::Theme {
Self::Theme::default()
}

fn title(&self) -> String {
"nih_plug plugin".to_owned()
}

/// See [`Application::scale_policy`].
///
/// TODO: Is this needed? Editors shouldn't change the scale policy.
Expand All @@ -207,16 +226,13 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
}

/// See [`Application::renderer_settings`].
fn renderer_settings() -> iced_baseview::backend::settings::Settings {
iced_baseview::backend::settings::Settings {
fn renderer_settings() -> RendererSettings {
RendererSettings {
// Enable some anti-aliasing by default. Since GUIs are likely very simple and most of
// the work will be on the CPU anyways this should not affect performance much.
antialiasing: Some(iced_baseview::backend::settings::Antialiasing::MSAAx4),
// Use Noto Sans as the default font as that renders a bit more cleanly than the default
// Lato font. This crate also contains other weights and versions of this font you can
// use for individual widgets.
default_font: Some(crate::assets::fonts::NOTO_SANS_REGULAR),
..iced_baseview::backend::settings::Settings::default()
antialiasing: Some(Antialiasing::MSAAx4),
default_font: Font::DEFAULT,
..RendererSettings::default()
}
}

Expand Down
6 changes: 3 additions & 3 deletions nih_plug_iced/src/widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
use nih_plug::prelude::ParamPtr;

pub mod generic_ui;
pub mod param_slider;
// pub mod generic_ui;
// pub mod param_slider;
pub mod peak_meter;
pub mod util;

pub use param_slider::ParamSlider;
// pub use param_slider::ParamSlider;
pub use peak_meter::PeakMeter;

/// A message to update a parameter value. Since NIH-plug manages the parameters, interacting with
Expand Down
Loading

0 comments on commit bbb5c09

Please sign in to comment.