Skip to content
Open
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
2 changes: 1 addition & 1 deletion examples/gain/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ publish = false

[dependencies]
coupler = { workspace = true, features = ["derive"] }
portlight = { git = "https://github.com/coupler-rs/portlight", rev = "fff171e9f3f70a9604102e1e1877ad67d0c2badd" }
portlight = { git = "https://github.com/coupler-rs/portlight", rev = "e517f1e7e1700b70a74523cf905d5c80f81b4e81" }
flicker = { git = "https://github.com/coupler-rs/flicker", rev = "80aca05cb6c7406f8c2a4ba66d85849dc344afaa" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
229 changes: 122 additions & 107 deletions examples/gain/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use std::cell::RefCell;
use std::fmt::{self, Formatter};
use std::io::{self, Read, Write};
use std::rc::Rc;

use std::os::fd::AsRawFd;
use std::os::raw::c_int;
use serde::{Deserialize, Serialize};

use coupler::format::clap::*;
Expand All @@ -14,8 +13,8 @@ use coupler::{buffers::*, bus::*, engine::*, events::*, host::*, params::*, plug
use flicker::Renderer;

use portlight::{
App, AppMode, AppOptions, Bitmap, Cursor, MouseButton, Point, RawWindow, Response, Window,
WindowContext, WindowOptions,
Bitmap, Context, Cursor, EventLoop, EventLoopMode, EventLoopOptions, Key, MouseButton, Point,
RawWindow, Response, Task, TaskHandle, Window, WindowEvent, WindowOptions,
};

#[derive(Params, Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -172,18 +171,20 @@ struct Gesture {

struct ViewState {
host: ViewHost,
params: Rc<RefCell<GainParams>>,
params: GainParams,
window: Option<Window>,
renderer: Renderer,
framebuffer: Vec<u32>,
mouse_pos: Point,
gesture: Option<Gesture>,
}

impl ViewState {
fn new(host: ViewHost, params: Rc<RefCell<GainParams>>) -> ViewState {
fn new(host: ViewHost, params: &GainParams) -> ViewState {
ViewState {
host,
params,
params: params.clone(),
window: None,
renderer: Renderer::new(),
framebuffer: Vec::new(),
mouse_pos: Point { x: -1.0, y: -1.0 },
Expand All @@ -199,92 +200,96 @@ impl ViewState {
window.set_cursor(Cursor::Arrow);
}
}
}

fn handle_event(&mut self, cx: &WindowContext, event: portlight::Event) -> Response {
impl Task for ViewState {
fn event(&mut self, _cx: &Context, _key: Key, event: portlight::Event) -> Response {
use flicker::{Affine, Color, Path, Point};
use portlight::Event;

match event {
Event::Frame => {
let scale = cx.window().scale();
let size = cx.window().size();
let width = (size.width * scale) as usize;
let height = (size.height * scale) as usize;
self.framebuffer.resize(width * height, 0xFF000000);

let mut target = self.renderer.attach(&mut self.framebuffer, width, height);

target.clear(Color::rgba(21, 26, 31, 255));

let transform = Affine::scale(scale as f32);

let value = self.params.borrow().gain;

let center = Point::new(128.0, 128.0);
let radius = 32.0;
let angle1 = 0.75 * std::f32::consts::PI;
let angle2 = angle1 + value * 1.5 * std::f32::consts::PI;
let mut path = Path::new();
path.move_to(center + radius * Point::new(angle1.cos(), angle1.sin()));
path.arc(radius, angle1, angle2);
path.line_to(center + (radius - 4.0) * Point::new(angle2.cos(), angle2.sin()));
path.arc(radius - 4.0, angle2, angle1);
path.close();
target.fill_path(&path, transform, Color::rgba(240, 240, 245, 255));

let center = Point::new(128.0, 128.0);
let radius = 32.0;
let angle = 0.75 * std::f32::consts::PI;
let span = 1.5 * std::f32::consts::PI;
let mut path = Path::new();
path.move_to(center + radius * Point::new(angle.cos(), angle.sin()));
path.arc(radius, angle, angle + span);
path.line_to(center + (radius - 4.0) * Point::new(-angle.cos(), angle.sin()));
path.arc(radius - 4.0, angle + span, angle);
path.close();
target.stroke_path(&path, 1.0, transform, Color::rgba(240, 240, 245, 255));

cx.window().present(Bitmap::new(&self.framebuffer, width, height));
}
Event::MouseMove(pos) => {
self.mouse_pos = pos;
if let Some(gesture) = &self.gesture {
let delta = -0.005 * (pos.y - gesture.start_mouse_pos.y) as f32;
let new_value = (gesture.start_value + delta).clamp(0.0, 1.0);
self.host.set_param(0, new_value as f64);
self.params.borrow_mut().gain = new_value;
} else {
self.update_cursor(cx.window());
if let (Some(window), Event::Window(event)) = (&self.window, event) {
match event {
WindowEvent::Frame => {
let scale = window.scale();
let size = window.size();
let width = (size.width * scale) as usize;
let height = (size.height * scale) as usize;
self.framebuffer.resize(width * height, 0xFF000000);

let mut target = self.renderer.attach(&mut self.framebuffer, width, height);

target.clear(Color::rgba(21, 26, 31, 255));

let transform = Affine::scale(scale as f32);

let value = self.params.gain;

let center = Point::new(128.0, 128.0);
let radius = 32.0;
let angle1 = 0.75 * std::f32::consts::PI;
let angle2 = angle1 + value * 1.5 * std::f32::consts::PI;
let mut path = Path::new();
path.move_to(center + radius * Point::new(angle1.cos(), angle1.sin()));
path.arc(radius, angle1, angle2);
path.line_to(center + (radius - 4.0) * Point::new(angle2.cos(), angle2.sin()));
path.arc(radius - 4.0, angle2, angle1);
path.close();
target.fill_path(&path, transform, Color::rgba(240, 240, 245, 255));

let center = Point::new(128.0, 128.0);
let radius = 32.0;
let angle = 0.75 * std::f32::consts::PI;
let span = 1.5 * std::f32::consts::PI;
let mut path = Path::new();
path.move_to(center + radius * Point::new(angle.cos(), angle.sin()));
path.arc(radius, angle, angle + span);
path.line_to(center + (radius - 4.0) * Point::new(-angle.cos(), angle.sin()));
path.arc(radius - 4.0, angle + span, angle);
path.close();
target.stroke_path(&path, 1.0, transform, Color::rgba(240, 240, 245, 255));

window.present(Bitmap::new(&self.framebuffer, width, height));
}
}
Event::MouseDown(button) => {
if button == MouseButton::Left {
let pos = self.mouse_pos;
if pos.x >= 96.0 && pos.x < 160.0 && pos.y >= 96.0 && pos.y < 160.0 {
cx.window().set_cursor(Cursor::SizeNs);
self.host.begin_gesture(0);
let value = self.params.borrow().gain;
self.host.set_param(0, value as f64);
self.params.borrow_mut().gain = value;
self.gesture = Some(Gesture {
start_mouse_pos: pos,
start_value: value,
});
return Response::Capture;
WindowEvent::MouseMove(pos) => {
self.mouse_pos = pos;
if let Some(gesture) = &self.gesture {
let delta = -0.005 * (pos.y - gesture.start_mouse_pos.y) as f32;
let new_value = (gesture.start_value + delta).clamp(0.0, 1.0);
self.host.set_param(0, new_value as f64);
self.params.gain = new_value;
} else {
self.update_cursor(window);
}
}
}
Event::MouseUp(button) => {
if button == MouseButton::Left {
if self.gesture.is_some() {
self.host.end_gesture(0);
self.gesture = None;
self.update_cursor(cx.window());
return Response::Capture;
WindowEvent::MouseDown(button) => {
if button == MouseButton::Left {
let pos = self.mouse_pos;
if pos.x >= 96.0 && pos.x < 160.0 && pos.y >= 96.0 && pos.y < 160.0 {
window.set_cursor(Cursor::SizeNs);
self.host.begin_gesture(0);
let value = self.params.gain;
self.host.set_param(0, value as f64);
self.params.gain = value;
self.gesture = Some(Gesture {
start_mouse_pos: pos,
start_value: value,
});
return Response::Capture;
}
}
}
WindowEvent::MouseUp(button) => {
if button == MouseButton::Left {
if self.gesture.is_some() {
self.host.end_gesture(0);
self.gesture = None;
self.update_cursor(window);
return Response::Capture;
}
}
}
_ => {}
}
_ => {}
}

Response::Ignore
Expand All @@ -293,9 +298,8 @@ impl ViewState {

pub struct GainView {
#[allow(unused)]
app: App,
window: Window,
params: Rc<RefCell<GainParams>>,
event_loop: EventLoop,
task: TaskHandle<ViewState>,
}

impl GainView {
Expand All @@ -304,35 +308,36 @@ impl GainView {
parent: &ParentWindow,
params: &GainParams,
) -> portlight::Result<GainView> {
let app = AppOptions::new().mode(AppMode::Guest).build()?;
let event_loop = EventLoopOptions::new().mode(EventLoopMode::Guest).build()?;

let task = event_loop.spawn(ViewState::new(host, params));

let mut options = WindowOptions::new();
options.size(portlight::Size::new(256.0, 256.0));
task.with(|state, cx| {
let mut options = WindowOptions::new();
options.size(portlight::Size::new(256.0, 256.0));

let raw_parent = match parent.as_raw() {
RawParent::Win32(window) => RawWindow::Win32(window),
RawParent::Cocoa(view) => RawWindow::Cocoa(view),
RawParent::X11(window) => RawWindow::X11(window),
};
unsafe { options.raw_parent(raw_parent) };
let raw_parent = match parent.as_raw() {
RawParent::Win32(window) => RawWindow::Win32(window),
RawParent::Cocoa(view) => RawWindow::AppKit(view),
RawParent::X11(window) => RawWindow::X11(window),
};
unsafe { options.raw_parent(raw_parent) };

let params = Rc::new(RefCell::new(params.clone()));
let mut state = ViewState::new(host, Rc::clone(&params));
let window = options.open(app.handle(), move |cx, event| state.handle_event(cx, event))?;
let window = options.open(cx, Key(0))?;
window.show();

window.show();
state.window = Some(window);

Ok(GainView {
app,
window,
params,
})
portlight::Result::Ok(())
})?;

Ok(GainView { event_loop, task })
}
}

impl View for GainView {
fn size(&self) -> Size {
let size = self.window.size();
let size = self.task.with(|state, _| state.window.as_ref().unwrap().size());

Size {
width: size.width,
Expand All @@ -341,6 +346,16 @@ impl View for GainView {
}

fn param_changed(&mut self, id: ParamId, value: ParamValue) {
self.params.borrow_mut().set_param(id, value);
self.task.with(|state, _| {
state.params.set_param(id, value);
});
}

fn file_descriptor(&self) -> Option<c_int> {
Some(self.event_loop.as_raw_fd())
}

fn poll(&mut self) {
self.event_loop.poll().unwrap();
}
}
4 changes: 2 additions & 2 deletions src/format/vst3/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ impl<P: Plugin> IEditControllerTrait for Component<P> {
return ptr::null_mut();
}

let view = ComWrapper::new(PlugView::new(&self.main_thread_state));
view.to_com_ptr::<IPlugView>().unwrap().into_raw()
let view = PlugView::new(&self.main_thread_state);
view.into_raw()
}
}
Loading