// nih-plug: plugins, but rewritten in Rust
// Copyright (C) 2022 Robbert van der Helm
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// The VST3 macro generates an `allocate()` function for initializing the struct, so Clippy will
// complain as soon as a struct has more than 8 fields
#![allow(clippy::too_many_arguments)]
use crossbeam::atomic::AtomicCell;
use lazy_static::lazy_static;
use parking_lot::{RwLock, RwLockWriteGuard};
use raw_window_handle::RawWindowHandle;
use std::any::Any;
use std::cmp;
use std::collections::{HashMap, VecDeque};
use std::ffi::{c_void, CStr};
use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::ptr;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use std::sync::Arc;
use vst3_sys::base::{kInvalidArgument, kNoInterface, kResultFalse, kResultOk, tresult, TBool};
use vst3_sys::base::{IBStream, IPluginBase, IPluginFactory, IPluginFactory2, IPluginFactory3};
use vst3_sys::gui::IPlugView;
use vst3_sys::utils::SharedVstPtr;
use vst3_sys::vst::{
IAudioProcessor, IComponent, IComponentHandler, IEditController, IEventList, IParamValueQueue,
IParameterChanges, TChar,
};
use vst3_sys::VST3;
use widestring::U16CStr;
#[macro_use]
mod util;
use crate::buffer::Buffer;
use crate::context::{EventLoop, GuiContext, MainThreadExecutor, OsEventLoop, ProcessContext};
use crate::param::internals::ParamPtr;
use crate::param::range::Range;
use crate::param::Param;
use crate::plugin::{
BufferConfig, BusConfig, Editor, NoteEvent, Plugin, ProcessStatus, Vst3Plugin,
};
use crate::wrapper::state::{ParamValue, State};
use crate::wrapper::util::{hash_param_id, process_wrapper, strlcpy, u16strlcpy};
use crate::ParentWindowHandle;
// Alias needed for the VST3 attribute macro
use vst3_sys as vst3_com;
/// Re-export for the wrapper.
pub use vst3_sys::sys::GUID;
/// The VST3 SDK version this is roughtly based on.
const VST3_SDK_VERSION: &str = "VST 3.6.14";
// Window handle type constants missing from vst3-sys
#[allow(unused)]
const VST3_PLATFORM_HWND: &str = "HWND";
#[allow(unused)]
const VST3_PLATFORM_HIVIEW: &str = "HIView";
#[allow(unused)]
const VST3_PLATFORM_NSVIEW: &str = "NSView";
#[allow(unused)]
const VST3_PLATFORM_UIVIEW: &str = "UIView";
#[allow(unused)]
const VST3_PLATFORM_X11_WINDOW: &str = "X11EmbedWindowID";
/// Right now the wrapper adds its own bypass parameter.
///
/// TODO: Actually use this parameter.
const BYPASS_PARAM_ID: &str = "bypass";
lazy_static! {
static ref BYPASS_PARAM_HASH: u32 = hash_param_id(BYPASS_PARAM_ID);
}
/// The actual wrapper bits. We need this as an `Arc` so we can safely use our event loop API.
/// Since we can't combine that with VST3's interior reference counting this just has to be moved to
/// its own struct.
struct WrapperInner {
/// The wrapped plugin instance.
plugin: RwLock
,
/// The plugin's editor, if it has one. This object does not do anything on its own, but we need
/// to instantiate this in advance so we don't need to lock the entire [Plugin] object when
/// creating an editor.
editor: Option>,
/// The host's `IComponentHandler` instance, if passed through
/// `IEditController::set_component_handler`.
component_handler: RwLock