Request resizes after loading state
If the editor is open.
This commit is contained in:
parent
c294afbf62
commit
ae3356dca8
|
@ -1784,7 +1784,12 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
let task_posted = self.schedule_gui(Task::ParameterValuesChanged);
|
let task_posted = self.schedule_gui(Task::ParameterValuesChanged);
|
||||||
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
||||||
|
|
||||||
// TODO: Check for GUI size changes and resize accordingly
|
// TODO: Right now there's no way to know if loading the state changed the GUI's size. We
|
||||||
|
// could keep track of the last known size and compare the GUI's current size against
|
||||||
|
// that but that also seems brittle.
|
||||||
|
if self.editor_handle.lock().is_some() {
|
||||||
|
self.request_resize();
|
||||||
|
}
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use crossbeam::channel;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::backend::Backend;
|
use super::backend::Backend;
|
||||||
use super::wrapper::{GuiTask, Task, Wrapper};
|
use super::wrapper::{Task, Wrapper};
|
||||||
use crate::context::gui::GuiContext;
|
use crate::context::gui::GuiContext;
|
||||||
use crate::context::init::InitContext;
|
use crate::context::init::InitContext;
|
||||||
use crate::context::process::{ProcessContext, Transport};
|
use crate::context::process::{ProcessContext, Transport};
|
||||||
|
@ -35,10 +34,6 @@ pub(crate) struct WrapperProcessContext<'a, P: Plugin, B: Backend<P>> {
|
||||||
/// with the host for things like setting parameters.
|
/// with the host for things like setting parameters.
|
||||||
pub(crate) struct WrapperGuiContext<P: Plugin, B: Backend<P>> {
|
pub(crate) struct WrapperGuiContext<P: Plugin, B: Backend<P>> {
|
||||||
pub(super) wrapper: Arc<Wrapper<P, B>>,
|
pub(super) wrapper: Arc<Wrapper<P, B>>,
|
||||||
|
|
||||||
/// This allows us to send tasks to the parent view that will be handled at the start of its
|
|
||||||
/// next frame.
|
|
||||||
pub(super) gui_task_sender: channel::Sender<GuiTask>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: Plugin, B: Backend<P>> InitContext<P> for WrapperInitContext<'_, P, B> {
|
impl<P: Plugin, B: Backend<P>> InitContext<P> for WrapperInitContext<'_, P, B> {
|
||||||
|
@ -110,16 +105,7 @@ impl<P: Plugin, B: Backend<P>> GuiContext for WrapperGuiContext<P, B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_resize(&self) -> bool {
|
fn request_resize(&self) -> bool {
|
||||||
let (unscaled_width, unscaled_height) =
|
self.wrapper.request_resize();
|
||||||
self.wrapper.editor.borrow().as_ref().unwrap().lock().size();
|
|
||||||
|
|
||||||
// This will cause the editor to be resized at the start of the next frame
|
|
||||||
let push_successful = self
|
|
||||||
.gui_task_sender
|
|
||||||
.send(GuiTask::Resize(unscaled_width, unscaled_height))
|
|
||||||
.is_ok();
|
|
||||||
nih_debug_assert!(push_successful, "Could not queue window resize");
|
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
use baseview::{EventStatus, Window, WindowHandler, WindowOpenOptions};
|
use baseview::{EventStatus, Window, WindowHandler, WindowOpenOptions};
|
||||||
use crossbeam::channel;
|
use crossbeam::channel::{self, Sender};
|
||||||
use crossbeam::queue::ArrayQueue;
|
use crossbeam::queue::ArrayQueue;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use raw_window_handle::HasRawWindowHandle;
|
use raw_window_handle::HasRawWindowHandle;
|
||||||
|
@ -46,6 +46,8 @@ pub struct Wrapper<P: Plugin, B: Backend<P>> {
|
||||||
/// to instantiate this in advance so we don't need to lock the entire [`Plugin`] object when
|
/// to instantiate this in advance so we don't need to lock the entire [`Plugin`] object when
|
||||||
/// creating an editor. Wrapped in an `AtomicRefCell` because it needs to be initialized late.
|
/// creating an editor. Wrapped in an `AtomicRefCell` because it needs to be initialized late.
|
||||||
pub editor: AtomicRefCell<Option<Arc<Mutex<Box<dyn Editor>>>>>,
|
pub editor: AtomicRefCell<Option<Arc<Mutex<Box<dyn Editor>>>>>,
|
||||||
|
/// A channel for sending tasks to the GUI window, if the plugin has a GUI. Set in `run()`.
|
||||||
|
gui_tasks_sender: AtomicRefCell<Option<Sender<GuiTask>>>,
|
||||||
|
|
||||||
/// A realtime-safe task queue so the plugin can schedule tasks that need to be run later on the
|
/// A realtime-safe task queue so the plugin can schedule tasks that need to be run later on the
|
||||||
/// GUI thread. See the same field in the VST3 wrapper for more information on why this looks
|
/// GUI thread. See the same field in the VST3 wrapper for more information on why this looks
|
||||||
|
@ -220,6 +222,8 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
params,
|
params,
|
||||||
// Initialized later as it needs a reference to the wrapper for the async executor
|
// Initialized later as it needs a reference to the wrapper for the async executor
|
||||||
editor: AtomicRefCell::new(None),
|
editor: AtomicRefCell::new(None),
|
||||||
|
// Set in `run()`
|
||||||
|
gui_tasks_sender: AtomicRefCell::new(None),
|
||||||
|
|
||||||
// Also initialized later as it also needs a reference to the wrapper
|
// Also initialized later as it also needs a reference to the wrapper
|
||||||
event_loop: AtomicRefCell::new(None),
|
event_loop: AtomicRefCell::new(None),
|
||||||
|
@ -302,6 +306,7 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
/// could not be opened.
|
/// could not be opened.
|
||||||
pub fn run(self: Arc<Self>) -> Result<(), WrapperError> {
|
pub fn run(self: Arc<Self>) -> Result<(), WrapperError> {
|
||||||
let (gui_task_sender, gui_task_receiver) = channel::bounded(512);
|
let (gui_task_sender, gui_task_receiver) = channel::bounded(512);
|
||||||
|
*self.gui_tasks_sender.borrow_mut() = Some(gui_task_sender.clone());
|
||||||
|
|
||||||
// We'll spawn a separate thread to handle IO and to process audio. This audio thread should
|
// We'll spawn a separate thread to handle IO and to process audio. This audio thread should
|
||||||
// terminate together with this function.
|
// terminate together with this function.
|
||||||
|
@ -309,13 +314,12 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
let audio_thread = {
|
let audio_thread = {
|
||||||
let this = self.clone();
|
let this = self.clone();
|
||||||
let terminate_audio_thread = terminate_audio_thread.clone();
|
let terminate_audio_thread = terminate_audio_thread.clone();
|
||||||
let gui_task_sender = gui_task_sender.clone();
|
|
||||||
thread::spawn(move || this.run_audio_thread(terminate_audio_thread, gui_task_sender))
|
thread::spawn(move || this.run_audio_thread(terminate_audio_thread, gui_task_sender))
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.editor.borrow().clone() {
|
match self.editor.borrow().clone() {
|
||||||
Some(editor) => {
|
Some(editor) => {
|
||||||
let context = self.clone().make_gui_context(gui_task_sender);
|
let context = self.clone().make_gui_context();
|
||||||
|
|
||||||
// DPI scaling should not be used on macOS since the OS handles it there
|
// DPI scaling should not be used on macOS since the OS handles it there
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
@ -450,6 +454,20 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
event_loop.schedule_gui(task)
|
event_loop.schedule_gui(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Request the outer window to be resized to the editor's current size.
|
||||||
|
pub fn request_resize(&self) {
|
||||||
|
if let Some(gui_tasks_sender) = self.gui_tasks_sender.borrow().as_ref() {
|
||||||
|
let (unscaled_width, unscaled_height) =
|
||||||
|
self.editor.borrow().as_ref().unwrap().lock().size();
|
||||||
|
|
||||||
|
// This will cause the editor to be resized at the start of the next frame
|
||||||
|
let push_successful = gui_tasks_sender
|
||||||
|
.send(GuiTask::Resize(unscaled_width, unscaled_height))
|
||||||
|
.is_ok();
|
||||||
|
nih_debug_assert!(push_successful, "Could not queue window resize");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The audio thread. This should be called from another thread, and it will run until
|
/// The audio thread. This should be called from another thread, and it will run until
|
||||||
/// `should_terminate` is `true`.
|
/// `should_terminate` is `true`.
|
||||||
fn run_audio_thread(
|
fn run_audio_thread(
|
||||||
|
@ -535,14 +553,8 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_gui_context(
|
fn make_gui_context(self: Arc<Self>) -> Arc<WrapperGuiContext<P, B>> {
|
||||||
self: Arc<Self>,
|
Arc::new(WrapperGuiContext { wrapper: self })
|
||||||
gui_task_sender: channel::Sender<GuiTask>,
|
|
||||||
) -> Arc<WrapperGuiContext<P, B>> {
|
|
||||||
Arc::new(WrapperGuiContext {
|
|
||||||
wrapper: self,
|
|
||||||
gui_task_sender,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_init_context(&self) -> WrapperInitContext<'_, P, B> {
|
fn make_init_context(&self) -> WrapperInitContext<'_, P, B> {
|
||||||
|
@ -623,7 +635,10 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
let task_posted = self.schedule_gui(Task::ParameterValuesChanged);
|
let task_posted = self.schedule_gui(Task::ParameterValuesChanged);
|
||||||
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
||||||
|
|
||||||
// TODO: Check for GUI size changes and resize accordingly
|
// TODO: Right now there's no way to know if loading the state changed the GUI's size. We
|
||||||
|
// could keep track of the last known size and compare the GUI's current size against
|
||||||
|
// that but that also seems brittle.
|
||||||
|
self.request_resize();
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,7 +594,13 @@ impl<P: Vst3Plugin> WrapperInner<P> {
|
||||||
let task_posted = self.schedule_gui(Task::ParameterValuesChanged);
|
let task_posted = self.schedule_gui(Task::ParameterValuesChanged);
|
||||||
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
||||||
|
|
||||||
// TODO: Check for GUI size changes and resize accordingly
|
// TODO: Right now there's no way to know if loading the state changed the GUI's size. We
|
||||||
|
// could keep track of the last known size and compare the GUI's current size against
|
||||||
|
// that but that also seems brittle.
|
||||||
|
if self.plug_view.read().is_some() {
|
||||||
|
let task_posted = self.schedule_gui(Task::RequestResize);
|
||||||
|
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
||||||
|
}
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue