Skip to content

Commit

Permalink
Document some of the new items
Browse files Browse the repository at this point in the history
  • Loading branch information
prokopyl committed Jun 2, 2024
1 parent 02e262f commit 248f748
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 3 deletions.
9 changes: 9 additions & 0 deletions common/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,16 @@ pub struct PluginAudioConfiguration {

use clap_sys::audio_buffer::clap_audio_buffer;

/// Processing-related information about an audio port.
pub struct AudioPortProcessingInfo {
channel_count: u32,
latency: u32,
constant_mask: ConstantMask,
}

impl AudioPortProcessingInfo {
/// Extracts the processing-related information from a raw, C-FFI compatible audio buffer
/// descriptor.
#[inline]
pub fn from_raw(raw: &clap_audio_buffer) -> Self {
Self {
Expand All @@ -91,16 +94,22 @@ impl AudioPortProcessingInfo {
}
}

/// Returns the number of audio channels this port provides.
#[inline]
pub fn channel_count(&self) -> u32 {
self.channel_count
}

/// Returns the latency to or from the audio interface, in samples.
///
/// Whether this latency is to or from the audio interface depends on which kind of port
/// this describes, an output port or an input port respectively
#[inline]
pub fn latency(&self) -> u32 {
self.latency
}

/// Returns the [`ConstantMask`] of this port, hinting which audio channels are constant.
#[inline]
pub fn constant_mask(&self) -> ConstantMask {
self.constant_mask
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ bitflags! {
}

impl ParamRescanFlags {
/// Returns `true` if any of the given flags that are set imply that a plugin instance's restart
/// is needed before params can be rescanned.
#[inline]
pub fn requires_restart(&self) -> bool {
self.contains(Self::ALL)
Expand Down
4 changes: 2 additions & 2 deletions host/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<H: HostHandlers> PluginInstance<H> {
) -> T
where
D: for<'s> FnOnce(
<H as HostHandlers>::AudioProcessor<'_>,
<H as HostHandlers>::AudioProcessor<'s>,
&mut <H as HostHandlers>::MainThread<'s>,
) -> T,
{
Expand All @@ -101,7 +101,7 @@ impl<H: HostHandlers> PluginInstance<H> {
pub fn try_deactivate_with<T, D>(&mut self, drop_with: D) -> Result<T, PluginInstanceError>
where
D: for<'s> FnOnce(
<H as HostHandlers>::AudioProcessor<'_>,
<H as HostHandlers>::AudioProcessor<'s>,
&mut <H as HostHandlers>::MainThread<'s>,
) -> T,
{
Expand Down
25 changes: 24 additions & 1 deletion host/src/plugin/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ impl<'a> PluginSharedHandle<'a> {
unsafe { Some(E::from_raw(raw)) }
}

/// Safely dereferences a [`RawExtension`] pointer produced by this plugin instance.
///
/// See the documentation of the [`RawExtension`] type for more information about how this works
/// internally.
///
/// # Panics
///
/// This method will panic if the given extension pointer does not match the plugin instance of
/// this handle.
#[inline]
pub fn use_extension<E: Sized>(
&self,
Expand Down Expand Up @@ -234,6 +243,9 @@ impl Debug for PluginAudioProcessorHandle<'_> {
}
}

/// A handle to a plugin instance that may be in the process of initializing.
///
/// In this state, only [querying plugin extensions](Self::get_extension) is allowed.
#[derive(Clone, Eq, PartialEq)]
pub struct InitializingPluginHandle<'a> {
inner: RemoteHandleInner,
Expand Down Expand Up @@ -284,6 +296,16 @@ impl Debug for InitializingPluginHandle<'_> {
}
}

/// A handle to a plugin instance that has finished initializing.
///
/// This handle can be used to obtain a [`PluginSharedHandle`] to then call the plugin's thread-safe
/// method.
///
/// However, this handle can outlive the plugin instance, as host callbacks may be called during
/// the plugin's destruction.
///
/// Therefore, the [`PluginSharedHandle`] can only be accessed through the [`access`](Self::access)
/// method, ensuring no access can be made during or after destruction.
#[derive(Clone, Eq, PartialEq)]
pub struct InitializedPluginHandle<'a> {
inner: RemoteHandleInner,
Expand Down Expand Up @@ -418,7 +440,7 @@ impl DestroyLock {
return None;
}

// Poisoning doesn't matter, we are only reading
// Poisoning doesn't matter, we are only reading a bool
let guard = self.lock.read().unwrap_or_else(|err| err.into_inner());
if *guard {
return None;
Expand All @@ -432,6 +454,7 @@ impl DestroyLock {
}
}

#[cold]
fn mismatched_instance() -> ! {
panic!("Given plugin instance handle doesn't match the extension pointer it was used on.")
}
16 changes: 16 additions & 0 deletions host/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ pub mod audio_buffers;
/// This is a convenience type that can be used where the type-states [`StartedPluginAudioProcessor`] and
/// [`StoppedPluginAudioProcessor`] are not very ergonomic, or to perform operations that are common
/// to both states.
///
/// Note that in order to maintain thread-safety, this type must be either dropped or stopped and
/// passed to either [`PluginInstance::deactivate`] or [`PluginInstance::deactivate_with`], *before*
/// the [`PluginInstance`] itself is dropped. If this is not done, the plugin instance will never
/// be deactivated or destroyed, and will leak all its associated resources.
pub enum PluginAudioProcessor<H: HostHandlers> {
/// The audio processor is in it's `started` state.
Started(StartedPluginAudioProcessor<H>),
Expand Down Expand Up @@ -385,10 +390,16 @@ impl<H: HostHandlers> From<StoppedPluginAudioProcessor<H>> for PluginAudioProces
/// [`access_handler`](Self::access_handler) and [`access_handler_mut`](Self::access_handler_mut)
/// methods.
///
/// Note that in order to maintain thread-safety, this type must be either dropped or stopped and
/// passed to either [`PluginInstance::deactivate`] or [`PluginInstance::deactivate_with`], *before*
/// the [`PluginInstance`] itself is dropped. If this is not done, the plugin instance will never
/// be deactivated or destroyed, and will leak all its associated resources.
///
/// [`process`]: Self::process
/// [`stop_processing`]: Self::stop_processing
/// [shared]: crate::prelude::SharedHandler
/// [audio processor]: crate::prelude::AudioProcessorHandler
/// [`destroy`](PluginInstance::deactivate)
pub struct StartedPluginAudioProcessor<H: HostHandlers> {
inner: Arc<PluginInstanceInner<H>>,
_no_sync: PhantomData<UnsafeCell<()>>,
Expand Down Expand Up @@ -628,6 +639,11 @@ impl<H: HostHandlers> StartedPluginAudioProcessor<H> {
/// [`access_handler`](Self::access_handler) and [`access_handler_mut`](Self::access_handler_mut)
/// methods.
///
/// Note that in order to maintain thread-safety, this type must be either dropped or stopped and
/// passed to either [`PluginInstance::deactivate`] or [`PluginInstance::deactivate_with`], *before*
/// the [`PluginInstance`] itself is dropped. If this is not done, the plugin instance will never
/// be deactivated or destroyed, and will leak all its associated resources.
///
/// [`activate`]: PluginInstance::activate
/// [`process`]: StartedPluginAudioProcessor::process
/// [`start_processing`]: Self::start_processing
Expand Down
38 changes: 38 additions & 0 deletions host/src/process/audio_buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,14 @@ impl<'a> InputAudioBuffers<'a> {
}
}

/// Shortens the [`frames_count`] of these input buffers.
///
/// This does not actually change the underlying buffers themselves, it only reduces the
/// slice that will be exposed to the plugin.
///
/// This method does nothing if `max_buffer_size` is greater or equal than the current [`frames_count`].
///
/// [`frames_count`]: self.frames_count
pub fn truncate(&mut self, max_buffer_size: u32) {
if let Some(frames_count) = self.frames_count {
self.frames_count = Some(frames_count.min(max_buffer_size))
Expand Down Expand Up @@ -413,6 +421,17 @@ impl<'a> InputAudioBuffers<'a> {
self.buffers
}

/// The number of port buffers this [`InputAudioBuffers`] has been given.
#[inline]
pub fn port_count(&self) -> usize {
self.buffers.len()
}

/// The number of frames in these input buffers.
///
/// This is the minimum frame count of all the port buffers this has been given.
///
/// If this has no port buffer (i.e. [`port_count`](self.port_count) is zero), this returns `None`.
#[inline]
pub fn frames_count(&self) -> Option<u32> {
self.frames_count
Expand Down Expand Up @@ -458,6 +477,14 @@ impl<'a> OutputAudioBuffers<'a> {
}
}

/// Shortens the [`frames_count`] of these output buffers.
///
/// This does not actually change the underlying buffers themselves, it only reduces the
/// slice that will be exposed to the plugin.
///
/// This method does nothing if `max_buffer_size` is greater or equal than the current [`frames_count`].
///
/// [`frames_count`]: self.frames_count
pub fn truncate(&mut self, max_buffer_size: u32) {
if let Some(frames_count) = self.frames_count {
self.frames_count = Some(frames_count.min(max_buffer_size))
Expand Down Expand Up @@ -570,6 +597,17 @@ impl<'a> OutputAudioBuffers<'a> {
self.buffers
}

/// The number of port buffers this [`OutputAudioBuffers`] has been given.
#[inline]
pub fn port_count(&self) -> usize {
self.buffers.len()
}

/// The number of frames in these output buffers.
///
/// This is the minimum frame count of all the port buffers this has been given.
///
/// If this has no port buffer (i.e. [`port_count`](self.port_count) is zero), this returns `None`.
#[inline]
pub fn frames_count(&self) -> Option<u32> {
self.frames_count
Expand Down
9 changes: 9 additions & 0 deletions plugin/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ impl<'a> HostSharedHandle<'a> {
}
}

/// Safely dereferences a [`RawExtension`] pointer produced by this host.
///
/// See the documentation of the [`RawExtension`] type for more information about how this works
/// internally.
///
/// # Panics
///
/// This method will panic if the given extension pointer does not match the host
/// this handle came from.
#[inline]
pub fn use_extension<E: Sized>(&self, extension: &RawExtension<HostExtensionSide, E>) -> &'a E {
if self.raw != extension.host_ptr() {
Expand Down
9 changes: 9 additions & 0 deletions plugin/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ pub trait Plugin: 'static {
/// See the [module documentation](crate::plugin) for more information on the thread model.
type MainThread<'a>: PluginMainThread<'a, Self::Shared<'a>>;

/// Declares the extensions this plugin supports.
///
/// This Implemented by calling [`register`] on the given [`PluginExtensions`]
/// builder for every extension type that is supported.
///
/// A reference to the [`Shared`](Self::Shared) type is also given. However, it can be `None`,
/// as the host is allowed to query extensions before the plugin has finished initializing.
///
/// [`register`]: PluginExtensions::register
#[inline]
#[allow(unused_variables)]
fn declare_extensions(builder: &mut PluginExtensions<Self>, shared: Option<&Self::Shared<'_>>) {
Expand Down

0 comments on commit 248f748

Please sign in to comment.