Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
prokopyl committed Apr 5, 2024
1 parent 08be143 commit 0345faa
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 121 deletions.
238 changes: 119 additions & 119 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,61 +79,61 @@ use clack_plugin::prelude::*;
pub struct MyGainPlugin;

impl Plugin for MyGainPlugin {
type AudioProcessor<'a> = MyGainPluginAudioProcessor;
type AudioProcessor<'a> = MyGainPluginAudioProcessor;

type Shared<'a> = ();
type MainThread<'a> = ();
type Shared<'a> = ();
type MainThread<'a> = ();
}

impl DefaultPluginFactory for MyGainPlugin {
fn get_descriptor() -> PluginDescriptor {
PluginDescriptor::new("org.rust-audio.clack.gain", "Clack Gain Example")
}
fn get_descriptor() -> PluginDescriptor {
PluginDescriptor::new("org.rust-audio.clack.gain", "Clack Gain Example")
}

fn new_shared(_host: HostHandle) -> Result<Self::Shared<'_>, PluginError> {
Ok(())
}
fn new_shared(_host: HostSharedHandle) -> Result<Self::Shared<'_>, PluginError> {
Ok(())
}

fn new_main_thread<'a>(
_host: HostMainThreadHandle<'a>,
_shared: &'a Self::Shared<'a>,
) -> Result<Self::MainThread<'a>, PluginError> {
Ok(())
}
fn new_main_thread<'a>(
_host: HostMainThreadHandle<'a>,
_shared: &'a Self::Shared<'a>,
) -> Result<Self::MainThread<'a>, PluginError> {
Ok(())
}
}

pub struct MyGainPluginAudioProcessor;

impl<'a> PluginAudioProcessor<'a, (), ()> for MyGainPluginAudioProcessor {
fn activate(_host: HostAudioThreadHandle<'a>, _main_thread: &mut (), _shared: &'a (), _audio_config: AudioConfiguration) -> Result<Self, PluginError> {
Ok(Self)
}

fn process(&mut self, _process: Process, mut audio: Audio, _events: Events) -> Result<ProcessStatus, PluginError> {
for mut port_pair in &mut audio {
// For this example, we'll only care about 32-bit sample data.
let Some(channel_pairs) = port_pair.channels()?.into_f32() else { continue; };

for channel_pair in channel_pairs {
match channel_pair {
ChannelPair::InputOnly(_) => {}
ChannelPair::OutputOnly(buf) => buf.fill(0.0),
ChannelPair::InputOutput(input, output) => {
for (input, output) in input.iter().zip(output) {
*output = input * 2.0
}
}
ChannelPair::InPlace(buf) => {
for sample in buf {
*sample *= 2.0
fn activate(_host: HostAudioThreadHandle<'a>, _main_thread: &mut (), _shared: &'a (), _audio_config: AudioConfiguration) -> Result<Self, PluginError> {
Ok(Self)
}

fn process(&mut self, _process: Process, mut audio: Audio, _events: Events) -> Result<ProcessStatus, PluginError> {
for mut port_pair in &mut audio {
// For this example, we'll only care about 32-bit sample data.
let Some(channel_pairs) = port_pair.channels()?.into_f32() else { continue; };

for channel_pair in channel_pairs {
match channel_pair {
ChannelPair::InputOnly(_) => {}
ChannelPair::OutputOnly(buf) => buf.fill(0.0),
ChannelPair::InputOutput(input, output) => {
for (input, output) in input.iter().zip(output) {
*output = input * 2.0
}
}
ChannelPair::InPlace(buf) => {
for sample in buf {
*sample *= 2.0
}
}
}
}
}
}
}
}

Ok(ProcessStatus::Continue)
}
Ok(ProcessStatus::Continue)
}
}

clack_export_entry!(SinglePluginEntry<MyGainPlugin>);
Expand All @@ -158,93 +158,93 @@ use clack_host::prelude::*;
struct MyHostShared;

impl<'a> HostShared<'a> for MyHostShared {
/* ... */
fn request_restart(&self) { /* ... */ }
fn request_process(&self) { /* ... */ }
fn request_callback(&self) { /* ... */ }
/* ... */
fn request_restart(&self) { /* ... */ }
fn request_process(&self) { /* ... */ }
fn request_callback(&self) { /* ... */ }
}

struct MyHost;

impl Host for MyHost {
type Shared<'a> = MyHostShared;
type Shared<'a> = MyHostShared;

type MainThread<'a> = ();
type AudioProcessor<'a> = ();
type MainThread<'a> = ();
type AudioProcessor<'a> = ();
}

pub fn load_and_process() -> Result<(), Box<dyn std::error::Error>> {
// Information about our totally legit host.
let host_info = HostInfo::new("Legit Studio", "Legit Ltd.", "https://example.com", "4.3.2")?;

let bundle = PluginBundle::load("/home/user/.clap/u-he/libdiva.so")?;
let plugin_factory = bundle.get_plugin_factory().unwrap();

let plugin_descriptor = plugin_factory.plugin_descriptors()
.find(|d| d.id().unwrap().to_bytes() == b"com.u-he.diva")
.unwrap();

let mut plugin_instance = PluginInstance::<MyHost>::new(
|_| MyHostShared,
|_| (),
&bundle,
plugin_descriptor.id().unwrap(),
&host_info
)?;

let audio_configuration = PluginAudioConfiguration {
sample_rate: 48_000.0,
frames_count_range: 4..=4
};
let audio_processor = plugin_instance.activate(|_, _| (), audio_configuration)?;

let note_on_event = NoteOnEvent(NoteEvent::new(EventHeader::new(0), 60, 0, 12, 0, 4.2));
let input_events_buffer = [note_on_event];
let mut output_events_buffer = EventBuffer::new();

let mut input_audio_buffers = [[0.0f32; 4]; 2]; // 2 channels (stereo), 1 port
let mut output_audio_buffers = [[0.0f32; 4]; 2];

let mut input_ports = AudioPorts::with_capacity(2, 1); // 2 channels (stereo), 1 port
let mut output_ports = AudioPorts::with_capacity(2, 1);

// Let's send the audio processor to a dedicated audio processing thread.
let audio_processor = std::thread::scope(|s| s.spawn(|| {
let mut audio_processor = audio_processor.start_processing().unwrap();

let input_events = InputEvents::from_buffer(&input_events_buffer);
let mut output_events = OutputEvents::from_buffer(&mut output_events_buffer);

let mut input_audio = input_ports.with_input_buffers([AudioPortBuffer {
latency: 0,
channels: AudioPortBufferType::f32_input_only(
input_audio_buffers.iter_mut().map(|b| InputChannel::constant(b))
)
}]);

let mut output_audio = output_ports.with_output_buffers([AudioPortBuffer {
latency: 0,
channels: AudioPortBufferType::f32_output_only(
output_audio_buffers.iter_mut().map(|b| b.as_mut_slice())
)
}]);

// Finally do the processing itself.
let status = audio_processor.process(
&input_audio,
&mut output_audio,
&input_events,
&mut output_events,
None,
None
).unwrap();

// Send the audio processor back to be deallocated by the main thread.
audio_processor.stop_processing()
}).join().unwrap());

plugin_instance.deactivate(audio_processor);
Ok(())
// Information about our totally legit host.
let host_info = HostInfo::new("Legit Studio", "Legit Ltd.", "https://example.com", "4.3.2")?;

let bundle = PluginBundle::load("/home/user/.clap/u-he/libdiva.so")?;
let plugin_factory = bundle.get_plugin_factory().unwrap();

let plugin_descriptor = plugin_factory.plugin_descriptors()
.find(|d| d.id().unwrap().to_bytes() == b"com.u-he.diva")
.unwrap();

let mut plugin_instance = PluginInstance::<MyHost>::new(
|_| MyHostShared,
|_| (),
&bundle,
plugin_descriptor.id().unwrap(),
&host_info
)?;

let audio_configuration = PluginAudioConfiguration {
sample_rate: 48_000.0,
frames_count_range: 4..=4
};
let audio_processor = plugin_instance.activate(|_, _| (), audio_configuration)?;

let note_on_event = NoteOnEvent(NoteEvent::new(EventHeader::new(0), 60, 0, 12, 0, 4.2));
let input_events_buffer = [note_on_event];
let mut output_events_buffer = EventBuffer::new();

let mut input_audio_buffers = [[0.0f32; 4]; 2]; // 2 channels (stereo), 1 port
let mut output_audio_buffers = [[0.0f32; 4]; 2];

let mut input_ports = AudioPorts::with_capacity(2, 1); // 2 channels (stereo), 1 port
let mut output_ports = AudioPorts::with_capacity(2, 1);

// Let's send the audio processor to a dedicated audio processing thread.
let audio_processor = std::thread::scope(|s| s.spawn(|| {
let mut audio_processor = audio_processor.start_processing().unwrap();

let input_events = InputEvents::from_buffer(&input_events_buffer);
let mut output_events = OutputEvents::from_buffer(&mut output_events_buffer);

let mut input_audio = input_ports.with_input_buffers([AudioPortBuffer {
latency: 0,
channels: AudioPortBufferType::f32_input_only(
input_audio_buffers.iter_mut().map(|b| InputChannel::constant(b))
)
}]);

let mut output_audio = output_ports.with_output_buffers([AudioPortBuffer {
latency: 0,
channels: AudioPortBufferType::f32_output_only(
output_audio_buffers.iter_mut().map(|b| b.as_mut_slice())
)
}]);

// Finally do the processing itself.
let status = audio_processor.process(
&input_audio,
&mut output_audio,
&input_events,
&mut output_events,
None,
None
).unwrap();

// Send the audio processor back to be deallocated by the main thread.
audio_processor.stop_processing()
}).join().unwrap());

plugin_instance.deactivate(audio_processor);
Ok(())
}
```

Expand Down
2 changes: 1 addition & 1 deletion plugin/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<'a> HostInfo<'a> {
}

/// # Safety
/// Some functions exposed by HostHandle cannot be called until plugin is initialized
/// Some functions exposed by [`HostSharedHandle`] cannot be called until plugin is initializing
#[inline]
pub(crate) unsafe fn to_handle(self) -> HostSharedHandle<'a> {
HostSharedHandle {
Expand Down
2 changes: 1 addition & 1 deletion plugin/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<'a> PluginShared<'a> for () {}
/// See the [module documentation](crate::plugin) for more information on the thread model.
pub trait PluginMainThread<'a, S: PluginShared<'a>>: Sized + 'a {
/// This is called by the host on the main thread, in response to a previous call to
/// [`HostHandle::request_callback`](crate::host::HostSharedHandle::request_callback).
/// [`HostSharedHandle::request_callback`](crate::host::HostSharedHandle::request_callback).
///
/// The default implementation of this method does nothing.
#[inline]
Expand Down

0 comments on commit 0345faa

Please sign in to comment.