Skip to main content

clack_plugin/entry/
single.rs

1#![deny(unsafe_code)]
2
3use crate::entry::prelude::*;
4use crate::prelude::*;
5use std::ffi::CStr;
6use std::marker::PhantomData;
7
8/// An [`Entry`] that only exposes a single plugin type to the host.
9///
10/// This is a simplified entry type, which only requires the simple [`DefaultPluginFactory`] trait to be
11/// implemented by the user, and implements an entry and plugin factory around it.
12///
13/// This entry type exists purely for convenience of the users in the common case of having a single
14/// plugin type to expose to the host.
15///
16/// If you actually need to expose more plugin types, or to customize the entry's behavior in some
17/// other way, see the [`Entry`] trait documentation for an example on how to implement your own
18/// custom entry.
19///
20/// # Example
21///
22/// ```
23/// use clack_plugin::entry::DefaultPluginFactory;
24/// use clack_plugin::prelude::*;
25///
26/// pub struct MyPlugin;
27///
28/// impl Plugin for MyPlugin {
29///     type AudioProcessor<'a> = ();
30///     type Shared<'a> = ();
31///     type MainThread<'a> = ();
32/// }
33///
34/// impl DefaultPluginFactory for MyPlugin {
35///     fn get_descriptor() -> PluginDescriptor {
36///         PluginDescriptor::new("my.plugin", "My Plugin")
37///     }
38///
39///     fn new_shared<'a>(
40///         _host: HostSharedHandle<'a>
41///     ) -> Result<Self::Shared<'a>, PluginError> {
42///         Ok(())
43///     }
44///
45///     fn new_main_thread<'a>(
46///         host: HostMainThreadHandle<'a>,
47///         shared: &'a Self::Shared<'a>
48///     ) -> Result<Self::MainThread<'a>, PluginError> {
49///         Ok(())
50///     }
51/// }
52///
53/// clack_export_entry!(SinglePluginEntry::<MyPlugin>);
54/// ```
55pub struct SinglePluginEntry<P: DefaultPluginFactory> {
56    plugin_factory: PluginFactoryWrapper<SinglePluginFactory<P>>,
57}
58
59impl<P: DefaultPluginFactory> Entry for SinglePluginEntry<P> {
60    fn new(_plugin_path: Option<&CStr>) -> Result<Self, EntryLoadError> {
61        Ok(Self {
62            plugin_factory: PluginFactoryWrapper::new(SinglePluginFactory {
63                descriptor: P::get_descriptor(),
64                _plugin: PhantomData,
65            }),
66        })
67    }
68
69    #[inline]
70    fn declare_factories<'a>(&'a self, builder: &mut EntryFactories<'a>) {
71        builder.register_factory(&self.plugin_factory);
72    }
73}
74
75struct SinglePluginFactory<P> {
76    descriptor: PluginDescriptor,
77    _plugin: PhantomData<fn() -> P>,
78}
79
80impl<P: DefaultPluginFactory> PluginFactoryImpl for SinglePluginFactory<P> {
81    #[inline]
82    fn plugin_count(&self) -> u32 {
83        1
84    }
85
86    #[inline]
87    fn plugin_descriptor(&self, index: u32) -> Option<&PluginDescriptor> {
88        match index {
89            0 => Some(&self.descriptor),
90            _ => None,
91        }
92    }
93
94    #[inline]
95    fn create_plugin<'a>(
96        &'a self,
97        host_info: HostInfo<'a>,
98        plugin_id: &CStr,
99    ) -> Option<PluginInstance<'a>> {
100        if plugin_id == self.descriptor.id().unwrap_or_default() {
101            Some(PluginInstance::new::<P>(
102                host_info,
103                &self.descriptor,
104                P::new_shared,
105                P::new_main_thread,
106            ))
107        } else {
108            None
109        }
110    }
111}
112
113/// An optional trait used by [`SinglePluginEntry`] that provides simplified, methods for generic
114/// plugin factories.
115///
116/// Implementing this trait is optional: you can disregard it completely if you use a custom
117/// factory, which also allows you to pass additional parameters to these methods, for e.g. sharing
118/// data across multiple instances.
119///
120/// See the [`SinglePluginEntry`] documentation for more information and examples.
121pub trait DefaultPluginFactory: Plugin {
122    /// Returns a new Plugin Descriptor, which contains metadata about the plugin, such as its name,
123    /// stable identifier, and more.
124    ///
125    /// See the [`PluginDescriptor`] type's documentation for more information.
126    fn get_descriptor() -> PluginDescriptor;
127
128    /// Creates a new instance of this shared data.
129    ///
130    /// This struct receives a thread-safe host handle that can be stored for the lifetime of the plugin.
131    ///
132    /// # Errors
133    /// This operation may fail for any reason, in which case `Err` is returned and the plugin is
134    /// not instantiated.
135    fn new_shared(host: HostSharedHandle<'_>) -> Result<Self::Shared<'_>, PluginError>;
136
137    /// Creates a new instance of the plugin's main thread.
138    ///
139    /// This struct receives an exclusive host handle that can be stored for the lifetime of the plugin.
140    ///
141    /// # Errors
142    /// This operation may fail for any reason, in which case `Err` is returned and the plugin is
143    /// not instantiated.
144    fn new_main_thread<'a>(
145        host: HostMainThreadHandle<'a>,
146        shared: &'a Self::Shared<'a>,
147    ) -> Result<Self::MainThread<'a>, PluginError>;
148}