1use std::ptr::NonNull;
6
7use crate::{
8 audio_buffer::{AudioBuffer, AudioBufferMut},
9 events::{Header, InputEvents, OutputEvents, Transport},
10 ffi::{
11 CLAP_PROCESS_CONTINUE, CLAP_PROCESS_CONTINUE_IF_NOT_QUIET, CLAP_PROCESS_SLEEP,
12 CLAP_PROCESS_TAIL, clap_process, clap_process_status,
13 },
14};
15
16pub struct Process {
17 clap_process: NonNull<clap_process>,
18}
19
20impl Process {
21 #[doc(hidden)]
37 pub const unsafe fn new_unchecked(clap_process: NonNull<clap_process>) -> Self {
38 #[cfg(debug_assertions)]
39 {
40 let clap_process = unsafe { clap_process.as_ref() };
41 assert!(clap_process.audio_inputs_count == 0 || !clap_process.audio_inputs.is_null());
42 assert!(clap_process.audio_outputs_count == 0 || !clap_process.audio_outputs.is_null());
43
44 assert!(!clap_process.in_events.is_null());
45 let in_events = unsafe { &*clap_process.in_events };
46 assert!(in_events.size.is_some() && in_events.get.is_some());
47
48 assert!(!clap_process.out_events.is_null());
49 let out_events = unsafe { &*clap_process.out_events };
50 assert!(out_events.try_push.is_some());
51 }
52
53 Self { clap_process }
54 }
55
56 const fn clap_process(&self) -> &clap_process {
57 unsafe { self.clap_process.as_ref() }
60 }
61
62 const fn clap_process_mut(&mut self) -> &mut clap_process {
63 unsafe { self.clap_process.as_mut() }
66 }
67
68 pub const fn steady_time(&self) -> i64 {
69 self.clap_process().steady_time
70 }
71
72 pub const fn frames_count(&self) -> u32 {
73 self.clap_process().frames_count
74 }
75
76 pub const fn transport(&self) -> Option<Transport<'_>> {
81 let Some(transport) = (unsafe { self.clap_process().transport.as_ref() }) else {
84 return None;
85 };
86 let header = unsafe { Header::new_unchecked(&transport.header) };
90 Some(unsafe { Transport::new_unchecked(header) })
92 }
93
94 pub const fn audio_inputs_count(&self) -> u32 {
95 self.clap_process().audio_inputs_count
96 }
97
98 const unsafe fn audio_inputs_unchecked(&self, n: u32) -> AudioBuffer<'_> {
104 debug_assert!(n < self.audio_inputs_count());
105 let clap_audio_buffer = unsafe { self.clap_process().audio_inputs.add(n as usize) };
108 unsafe { AudioBuffer::new_unchecked(self, clap_audio_buffer) }
109 }
110
111 pub const fn audio_inputs(&self, n: u32) -> AudioBuffer<'_> {
116 assert!(
117 n < self.audio_inputs_count(),
118 "audio input number must be less than the number of available input ports"
119 );
120
121 unsafe { self.audio_inputs_unchecked(n) }
123 }
124
125 pub const fn audio_outputs_count(&self) -> u32 {
126 self.clap_process().audio_outputs_count
127 }
128
129 const unsafe fn audio_outputs_unchecked(&mut self, n: u32) -> AudioBufferMut<'_> {
135 debug_assert!(n < self.audio_outputs_count());
136 let clap_audio_buffer = unsafe { self.clap_process_mut().audio_outputs.add(n as usize) };
139 let clap_audio_buffer = unsafe { NonNull::new_unchecked(clap_audio_buffer) };
140 unsafe { AudioBufferMut::new_unchecked(self, clap_audio_buffer) }
141 }
142
143 pub const fn audio_outputs(&mut self, n: u32) -> AudioBufferMut<'_> {
148 assert!(
149 n < self.audio_outputs_count(),
150 "audio output number must be less than the number of available output ports"
151 );
152
153 unsafe { self.audio_outputs_unchecked(n) }
155 }
156
157 pub const fn in_events(&self) -> InputEvents {
158 let in_events = unsafe { &*self.clap_process().in_events };
160 unsafe { InputEvents::new_unchecked(in_events) }
162 }
163
164 pub fn out_events(&self) -> OutputEvents {
165 let out_events = unsafe { &*self.clap_process().out_events };
167 unsafe { OutputEvents::new_unchecked(out_events) }
169 }
170}
171
172#[derive(Debug, Copy, Clone)]
173pub enum Status {
174 Continue,
175 ContinueIfNotQuiet,
176 Tail,
177 Sleep,
178}
179
180impl From<Status> for clap_process_status {
181 fn from(value: Status) -> Self {
182 use Status::*;
183 match value {
184 Continue => CLAP_PROCESS_CONTINUE,
185 ContinueIfNotQuiet => CLAP_PROCESS_CONTINUE_IF_NOT_QUIET,
186 Tail => CLAP_PROCESS_TAIL,
187 Sleep => CLAP_PROCESS_SLEEP,
188 }
189 }
190}