Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ dpi = "0.1.2"
x11rb = { version = "0.13.2", features = ["cursor", "resource_manager", "allow-unsafe-code", "dl-libxcb"], default-features = false }
xkbcommon-dl = { version = "0.4.2", features = ["x11"] }
x11-dl = { version = "2.21.0" }
polling = "3.11.0"
calloop = "0.14.4"
percent-encoding = "2.3.2"
bytemuck = "1.25.0"

Expand Down Expand Up @@ -91,7 +91,7 @@ objc2-app-kit = { version = "0.3.2", default-features = false, features = [
] }

[workspace]
members = ["examples/open_parented", "examples/open_window", "examples/render_femtovg", "examples/render_wgpu"]
members = ["examples/open_parented", "examples/open_window", "examples/plugin_clack", "examples/render_femtovg", "examples/render_wgpu"]

[lints.clippy]
missing-safety-doc = "allow"
Expand Down
19 changes: 10 additions & 9 deletions examples/open_parented/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use baseview::dpi::LogicalSize;
use baseview::{
Event, EventStatus, Window, WindowContext, WindowHandle, WindowHandler, WindowOpenOptions,
WindowSize,
Event, EventStatus, Window, WindowBuilder, WindowContext, WindowHandler, WindowSize,
};
use std::cell::{Cell, RefCell};
use std::num::NonZeroU32;
Expand All @@ -10,7 +9,7 @@ struct ParentWindowHandler {
surface: RefCell<softbuffer::Surface<WindowContext, WindowContext>>,
damaged: Cell<bool>,

_child_window: Option<WindowHandle>,
_child_window: Option<Window>,
}

impl ParentWindowHandler {
Expand All @@ -22,12 +21,12 @@ impl ParentWindowHandler {
.resize(NonZeroU32::new(size.width).unwrap(), NonZeroU32::new(size.height).unwrap())
.unwrap();

let window_open_options = WindowOpenOptions::new()
let window_open_options = WindowBuilder::new()
.with_size(LogicalSize::new(256, 256))
.with_title("baseview child");
.with_title("baseview child")
.with_parent(&window);

let child_window =
Window::open_parented(&window, window_open_options, ChildWindowHandler::new);
let child_window = baseview::create_window(window_open_options, ChildWindowHandler::new);

Self { surface: surface.into(), damaged: true.into(), _child_window: Some(child_window) }
}
Expand Down Expand Up @@ -120,7 +119,9 @@ impl WindowHandler for ChildWindowHandler {
}

fn main() {
let window_open_options = WindowOpenOptions::new().with_size(LogicalSize::new(512.0, 512.0));
let window_open_options = WindowBuilder::new().with_size(LogicalSize::new(512.0, 512.0));

Window::open_blocking(window_open_options, ParentWindowHandler::new);
baseview::create_window(window_open_options, ParentWindowHandler::new)
.run_until_closed()
.unwrap();
}
11 changes: 6 additions & 5 deletions examples/open_window/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use rtrb::{Consumer, RingBuffer};
use baseview::copy_to_clipboard;
use baseview::dpi::{LogicalSize, PhysicalPosition};
use baseview::{
Event, EventStatus, MouseEvent, Window, WindowContext, WindowHandler, WindowOpenOptions,
WindowSize,
Event, EventStatus, MouseEvent, WindowBuilder, WindowContext, WindowHandler, WindowSize,
};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -136,7 +135,7 @@ impl WindowHandler for OpenWindowExample {
}

fn main() {
let window_open_options = WindowOpenOptions::new().with_size(LogicalSize::new(512.0, 512.0));
let window_open_options = WindowBuilder::new().with_size(LogicalSize::new(512.0, 512.0));

let (mut tx, rx) = RingBuffer::new(128);

Expand All @@ -148,7 +147,7 @@ fn main() {
}
});

Window::open_blocking(window_open_options, |window| {
baseview::create_window(window_open_options, |window| {
let ctx = softbuffer::Context::new(window.clone()).unwrap();
let mut surface = softbuffer::Surface::new(&ctx, window.clone()).unwrap();
let size = window.size().physical;
Expand All @@ -164,7 +163,9 @@ fn main() {
is_cursor_inside: false.into(),
damaged: true.into(),
}
});
})
.run_until_closed()
.unwrap();
}

fn log_event(event: &Event) {
Expand Down
11 changes: 11 additions & 0 deletions examples/plugin_clack/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "plugin_clack"
version = "0.1.0"
edition = "2024"

[dependencies]
clack-plugin = "0.1.0"
clack-extensions = { version = "0.1.0", features = ["gui", "clack-plugin", "raw-window-handle_06"] }
baseview = { path = "../.." }
softbuffer = "0.4.8"
raw-window-handle = "0.6.2"
31 changes: 31 additions & 0 deletions examples/plugin_clack/src/audio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::ExamplePluginMainThread;
use clack_plugin::prelude::*;

pub struct ExamplePluginAudioProcessor;

impl<'a> PluginAudioProcessor<'a, (), ExamplePluginMainThread> for ExamplePluginAudioProcessor {
fn activate(
_host: HostAudioProcessorHandle<'a>, _main_thread: &mut ExamplePluginMainThread,
_shared: &'a (), _audio_config: PluginAudioConfiguration,
) -> Result<Self, PluginError> {
Ok(Self)
}

fn process(
&mut self, _process: Process, mut audio: Audio, _events: Events,
) -> Result<ProcessStatus, PluginError> {
for mut port in audio.port_pairs() {
let channels = port.channels()?.into_f32().expect("Expected f32 channels");

for channel_pair in channels {
match channel_pair {
ChannelPair::OutputOnly(o) => o.fill(0.0),
ChannelPair::InputOutput(i, o) => o.copy_from_slice(i),
_ => {}
}
}
}

Ok(ProcessStatus::Continue)
}
}
137 changes: 137 additions & 0 deletions examples/plugin_clack/src/gui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use crate::ExamplePluginMainThread;
use crate::window_handler::OpenWindowExample;
use baseview::dpi::{LogicalSize, PhysicalSize, Size};
use baseview::{Window, WindowBuilder};
use clack_extensions::gui::{
AspectRatioStrategy, GuiApiType, GuiConfiguration, GuiResizeHints, GuiSize, PluginGuiImpl,
Window as ClapWindow,
};
use clack_plugin::plugin::PluginError;
use raw_window_handle::HasRawWindowHandle;

pub struct ExamplePluginGui {
handle: Window,
}

impl PluginGuiImpl for ExamplePluginMainThread {
fn is_api_supported(&mut self, configuration: GuiConfiguration) -> bool {
!configuration.is_floating
&& Some(configuration.api_type) == GuiApiType::default_for_current_platform()
}

fn get_preferred_api(&mut self) -> Option<GuiConfiguration<'_>> {
Some(GuiConfiguration {
api_type: GuiApiType::default_for_current_platform()?,
is_floating: false,
})
}

fn create(&mut self, _configuration: GuiConfiguration) -> Result<(), PluginError> {
let handle = baseview::create_window(WindowBuilder::new(), OpenWindowExample::new);

self.gui = Some(ExamplePluginGui { handle });

Ok(())
}

fn destroy(&mut self) {
let Some(gui) = self.gui.take() else { return };

gui.handle.close()
}

fn set_scale(&mut self, scale: f64) -> Result<(), PluginError> {
let Some(gui) = &self.gui else {
return Err(PluginError::Message("Invalid GUI call: GUI is not created"));
};

gui.handle.suggest_fallback_scale(Some(scale));
Ok(())
}

fn get_size(&mut self) -> Option<GuiSize> {
let Some(gui) = &self.gui else {
return None;
};

let uses_logical =
matches!(GuiApiType::default_for_current_platform(), Some(a) if a.uses_logical_size());

let size = gui.handle.size();

if uses_logical {
let size = size.logical.cast();
Some(GuiSize { width: size.width, height: size.height })
} else {
Some(GuiSize { width: size.physical.width, height: size.physical.height })
}
}

fn can_resize(&mut self) -> bool {
true // Non-resizeable windows not supported yet
}

fn get_resize_hints(&mut self) -> Option<GuiResizeHints> {
Some(GuiResizeHints {
can_resize_horizontally: true,
can_resize_vertically: true,
strategy: AspectRatioStrategy::Disregard,
})
}

fn adjust_size(&mut self, size: GuiSize) -> Option<GuiSize> {
Some(size) // Not supported yet
}

fn set_size(&mut self, size: GuiSize) -> Result<(), PluginError> {
let Some(gui) = &self.gui else {
return Err(PluginError::Message("Invalid GUI call: GUI is not created"));
};

let size = size_from_clap(size);
gui.handle.resize(size);
Ok(())
}

fn set_parent(&mut self, window: ClapWindow) -> Result<(), PluginError> {
let Some(gui) = &self.gui else {
return Err(PluginError::Message("Invalid GUI call: GUI is not created"));
};

let handle = window.raw_window_handle()?;

let handle = unsafe { raw_window_handle::WindowHandle::borrow_raw(handle) };
gui.handle.set_parent(&handle);

Ok(())
}

fn set_transient(&mut self, window: ClapWindow) -> Result<(), PluginError> {
todo!() // Not supported yet
}

fn suggest_title(&mut self, title: &str) {
if let Some(gui) = &self.gui {
gui.handle.set_title(title);
}
}

fn show(&mut self) -> Result<(), PluginError> {
todo!()
}

fn hide(&mut self) -> Result<(), PluginError> {
todo!()
}
}

fn size_from_clap(size: GuiSize) -> Size {
let uses_logical =
matches!(GuiApiType::default_for_current_platform(), Some(a) if a.uses_logical_size());

if uses_logical {
Size::Logical(LogicalSize::new(size.width as _, size.height as _))
} else {
Size::Physical(PhysicalSize::new(size.width, size.height))
}
}
54 changes: 54 additions & 0 deletions examples/plugin_clack/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::audio::ExamplePluginAudioProcessor;
use crate::gui::ExamplePluginGui;
use clack_extensions::gui::PluginGui;
use clack_plugin::prelude::*;

mod audio;
mod gui;
mod window_handler;

/// The type that represents our plugin in Clack.
///
/// This is what implements the [`Plugin`] trait, where all the other subtypes are attached.
pub struct ExamplePlugin;

impl Plugin for ExamplePlugin {
type AudioProcessor<'a> = ExamplePluginAudioProcessor;
type Shared<'a> = ();
type MainThread<'a> = ExamplePluginMainThread;

fn declare_extensions(builder: &mut PluginExtensions<Self>, _shared: Option<&()>) {
builder.register::<PluginGui>();
}
}

impl DefaultPluginFactory for ExamplePlugin {
fn get_descriptor() -> PluginDescriptor {
use clack_plugin::plugin::features::*;

PluginDescriptor::new("org.rust-audio.clack.gain-egui", "Clack Gain EGUI Example")
.with_features([AUDIO_EFFECT, STEREO])
}

fn new_shared(_host: HostSharedHandle<'_>) -> Result<Self::Shared<'_>, PluginError> {
Ok(())
}

fn new_main_thread<'a>(
_host: HostMainThreadHandle<'a>, _shared: &'a Self::Shared<'a>,
) -> Result<Self::MainThread<'a>, PluginError> {
Ok(Self::MainThread { gui: None })
}
}

/// The data that belongs to the main thread of our plugin.
pub struct ExamplePluginMainThread {
/// The plugin's GUI state and context
gui: Option<ExamplePluginGui>,
}

impl<'a> PluginMainThread<'a, ()> for ExamplePluginMainThread {
fn on_main_thread(&mut self) {}
}

clack_export_entry!(SinglePluginEntry<ExamplePlugin>);
Loading
Loading