Add a resize request callback to VST3 GuiContext
With some more work in baseview this can be used to resize windows from the plugin.
This commit is contained in:
parent
8d71369b2e
commit
f9db59f4bc
|
@ -44,6 +44,14 @@ pub trait ProcessContext {
|
||||||
// The implementing wrapper can assume that everything is being called from the main thread. Since
|
// The implementing wrapper can assume that everything is being called from the main thread. Since
|
||||||
// NIH-plug doesn't own the GUI event loop, this invariant cannot be part of the interface.
|
// NIH-plug doesn't own the GUI event loop, this invariant cannot be part of the interface.
|
||||||
pub trait GuiContext: Send + Sync + 'static {
|
pub trait GuiContext: Send + Sync + 'static {
|
||||||
|
/// Ask the host to resize the editor window to the size specified by [crate::Editor::size()].
|
||||||
|
/// This will return false if the host somehow didn't like this and rejected the resize, in
|
||||||
|
/// which case the window should revert to its old size. You should only actually resize your
|
||||||
|
/// embedded window once this returns `true`.
|
||||||
|
///
|
||||||
|
/// TODO: Host->Plugin resizing has not been implemented yet
|
||||||
|
fn request_resize(&self) -> bool;
|
||||||
|
|
||||||
/// Inform the host a parameter will be automated. Create a [`ParamSetter`] and use
|
/// Inform the host a parameter will be automated. Create a [`ParamSetter`] and use
|
||||||
/// [`ParamSetter::begin_set_parameter()`] instead for a safe, user friendly API.
|
/// [`ParamSetter::begin_set_parameter()`] instead for a safe, user friendly API.
|
||||||
///
|
///
|
||||||
|
|
|
@ -256,7 +256,7 @@ pub trait Editor: Send + Sync {
|
||||||
// and API agnostic, add a way to ask the GuiContext if the wrapper already provides a
|
// and API agnostic, add a way to ask the GuiContext if the wrapper already provides a
|
||||||
// tick function. If it does not, then the Editor implementation must handle this by
|
// tick function. If it does not, then the Editor implementation must handle this by
|
||||||
// itself. This would also need an associated `PREFERRED_FRAME_RATE` constant.
|
// itself. This would also need an associated `PREFERRED_FRAME_RATE` constant.
|
||||||
// TODO: Resizing
|
// TODO: Host->Plugin resizing
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A raw window handle for platform and GUI framework agnostic editors.
|
/// A raw window handle for platform and GUI framework agnostic editors.
|
||||||
|
|
|
@ -26,6 +26,10 @@ pub(crate) struct WrapperProcessContext<'a, P: ClapPlugin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
|
impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
|
||||||
|
fn request_resize(&self) -> bool {
|
||||||
|
todo!("Implement window resizing for CLAP");
|
||||||
|
}
|
||||||
|
|
||||||
// All of these functions are supposed to be called from the main thread, so we'll put some
|
// All of these functions are supposed to be called from the main thread, so we'll put some
|
||||||
// trust in the caller and assume that this is indeed the case
|
// trust in the caller and assume that this is indeed the case
|
||||||
unsafe fn raw_begin_set_parameter(&self, param: ParamPtr) {
|
unsafe fn raw_begin_set_parameter(&self, param: ParamPtr) {
|
||||||
|
|
|
@ -27,6 +27,13 @@ pub(crate) struct WrapperProcessContext<'a, P: Vst3Plugin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
|
impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
|
||||||
|
fn request_resize(&self) -> bool {
|
||||||
|
match &*self.inner.plug_view.read() {
|
||||||
|
Some(plug_view) => plug_view.request_resize(),
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// All of these functions are supposed to be called from the main thread, so we'll put some
|
// All of these functions are supposed to be called from the main thread, so we'll put some
|
||||||
// trust in the caller and assume that this is indeed the case
|
// trust in the caller and assume that this is indeed the case
|
||||||
unsafe fn raw_begin_set_parameter(&self, param: ParamPtr) {
|
unsafe fn raw_begin_set_parameter(&self, param: ParamPtr) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vst3_com::utils::SharedVstPtr;
|
use vst3_com::utils::SharedVstPtr;
|
||||||
use vst3_sys::base::{kInvalidArgument, kResultFalse, kResultOk, tresult, TBool};
|
use vst3_sys::base::{kInvalidArgument, kResultFalse, kResultOk, tresult, TBool};
|
||||||
use vst3_sys::gui::{IPlugFrame, IPlugView, IPlugViewContentScaleSupport};
|
use vst3_sys::gui::{IPlugFrame, IPlugView, IPlugViewContentScaleSupport, ViewRect};
|
||||||
use vst3_sys::VST3;
|
use vst3_sys::VST3;
|
||||||
|
|
||||||
use super::inner::WrapperInner;
|
use super::inner::WrapperInner;
|
||||||
|
@ -57,6 +57,42 @@ impl<P: Vst3Plugin> WrapperView<P> {
|
||||||
AtomicF32::new(1.0),
|
AtomicF32::new(1.0),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ask the host to resize the view to the size specified by [Editor::size()]. Will return false
|
||||||
|
/// if the host doesn't like you.
|
||||||
|
pub fn request_resize(&self) -> bool {
|
||||||
|
// Don't do anything if the editor is not open, because that would be strange
|
||||||
|
if self
|
||||||
|
.editor_handle
|
||||||
|
.try_read()
|
||||||
|
.map(|e| e.is_none())
|
||||||
|
.unwrap_or(true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match &*self.plug_frame.read() {
|
||||||
|
Some(plug_frame) => {
|
||||||
|
let (unscaled_width, unscaled_height) = self.editor.size();
|
||||||
|
let scaling_factor = self.scaling_factor.load(Ordering::Relaxed);
|
||||||
|
let mut size = ViewRect {
|
||||||
|
right: (unscaled_width as f32 * scaling_factor).round() as i32,
|
||||||
|
bottom: (unscaled_height as f32 * scaling_factor).round() as i32,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// The argument types are a bit wonky here because you can't construct a
|
||||||
|
// `SharedVstPtr`. This _should_ work however.
|
||||||
|
// FIXME: Run this in the `IRonLoop` on Linux. Otherwise REAPER will be very cross
|
||||||
|
// with us.
|
||||||
|
let plug_view: SharedVstPtr<dyn IPlugView> = unsafe { mem::transmute(self) };
|
||||||
|
let result = unsafe { plug_frame.resize_view(plug_view, &mut size) };
|
||||||
|
|
||||||
|
result == kResultOk
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
|
impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
|
||||||
|
@ -179,11 +215,14 @@ impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
|
||||||
kResultOk
|
kResultOk
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_size(&self, size: *mut vst3_sys::gui::ViewRect) -> tresult {
|
unsafe fn get_size(&self, size: *mut ViewRect) -> tresult {
|
||||||
check_null_ptr!(size);
|
check_null_ptr!(size);
|
||||||
|
|
||||||
*size = mem::zeroed();
|
*size = mem::zeroed();
|
||||||
|
|
||||||
|
// TODO: This is technically incorrect during resizing, this should still report the old
|
||||||
|
// size until `.on_size()` has been called. We should probably only bother fixing this
|
||||||
|
// if it turns out to be an issue.
|
||||||
let (unscaled_width, unscaled_height) = self.editor.size();
|
let (unscaled_width, unscaled_height) = self.editor.size();
|
||||||
let scaling_factor = self.scaling_factor.load(Ordering::Relaxed);
|
let scaling_factor = self.scaling_factor.load(Ordering::Relaxed);
|
||||||
let size = &mut *size;
|
let size = &mut *size;
|
||||||
|
@ -195,10 +234,10 @@ impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
|
||||||
kResultOk
|
kResultOk
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_size(&self, new_size: *mut vst3_sys::gui::ViewRect) -> tresult {
|
unsafe fn on_size(&self, new_size: *mut ViewRect) -> tresult {
|
||||||
// TODO: Implement resizing
|
|
||||||
check_null_ptr!(new_size);
|
check_null_ptr!(new_size);
|
||||||
|
|
||||||
|
// TODO: Implement Host->Plugin resizing
|
||||||
let (unscaled_width, unscaled_height) = self.editor.size();
|
let (unscaled_width, unscaled_height) = self.editor.size();
|
||||||
let scaling_factor = self.scaling_factor.load(Ordering::Relaxed);
|
let scaling_factor = self.scaling_factor.load(Ordering::Relaxed);
|
||||||
let (editor_width, editor_height) = (
|
let (editor_width, editor_height) = (
|
||||||
|
@ -231,14 +270,14 @@ impl<P: Vst3Plugin> IPlugView for WrapperView<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn can_resize(&self) -> tresult {
|
unsafe fn can_resize(&self) -> tresult {
|
||||||
// TODO: Implement resizing
|
// TODO: Implement Host->Plugin resizing
|
||||||
kResultFalse
|
kResultFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn check_size_constraint(&self, rect: *mut vst3_sys::gui::ViewRect) -> tresult {
|
unsafe fn check_size_constraint(&self, rect: *mut ViewRect) -> tresult {
|
||||||
check_null_ptr!(rect);
|
check_null_ptr!(rect);
|
||||||
|
|
||||||
// TODO: Add this with the resizing
|
// TODO: Implement Host->Plugin resizing
|
||||||
if (*rect).right - (*rect).left > 0 && (*rect).bottom - (*rect).top > 0 {
|
if (*rect).right - (*rect).left > 0 && (*rect).bottom - (*rect).top > 0 {
|
||||||
kResultOk
|
kResultOk
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue