cmajor/performer/
mod.rs

1//! The Cmajor performer for running programs.
2
3mod endpoints;
4
5pub use endpoints::{
6    event::{InputEvent, OutputEvent},
7    stream::{InputStream, OutputStream},
8    value::{InputValue, OutputValue},
9    Endpoint,
10};
11use {
12    crate::{
13        endpoint::{EndpointHandle, EndpointInfo},
14        ffi::PerformerPtr,
15        performer::endpoints::{
16            event::{fetch_events, post_event},
17            stream::{read_stream, write_stream, StreamType},
18            value::{GetOutputValue, SetInputValue},
19        },
20        value::{StringHandle, ValueRef},
21    },
22    sealed::sealed,
23    std::collections::HashMap,
24};
25
26/// A Cmajor performer.
27pub struct Performer {
28    ptr: PerformerPtr,
29    endpoints: HashMap<EndpointHandle, EndpointInfo>,
30    buffer: Vec<u8>,
31    console: Option<Endpoint<OutputEvent>>,
32}
33
34impl Performer {
35    pub(crate) fn new(
36        performer: PerformerPtr,
37        endpoints: HashMap<EndpointHandle, EndpointInfo>,
38        console: Option<Endpoint<OutputEvent>>,
39    ) -> Self {
40        let size_of_largest_type = endpoints
41            .values()
42            .flat_map(|endpoint| endpoint.types().iter().map(|ty| ty.size()).max())
43            .max()
44            .unwrap_or(0);
45
46        Performer {
47            ptr: performer,
48            endpoints,
49            buffer: vec![0; size_of_largest_type],
50            console,
51        }
52    }
53}
54
55impl Performer {
56    /// Sets the block size of the performer.
57    pub fn set_block_size(&mut self, num_frames: u32) {
58        self.ptr.set_block_size(num_frames);
59    }
60
61    /// Renders the next block of frames.
62    pub fn advance(&mut self) {
63        self.ptr.advance();
64
65        if let Some(console) = self.console {
66            let _ = fetch_events(self, console, |_, value| match value {
67                ValueRef::String(StringHandle(handle)) => {
68                    println!("{}", self.ptr.get_string_for_handle(handle).unwrap_or("?"));
69                }
70                value => println!("{value:?}"),
71            });
72        }
73    }
74
75    /// Returns information about a given endpoint.
76    pub fn endpoint_info<T>(&self, Endpoint(endpoint): Endpoint<T>) -> Option<&EndpointInfo>
77    where
78        T: EndpointType,
79    {
80        self.endpoints.get(&endpoint.handle())
81    }
82
83    /// Set the value of an endpoint.
84    pub fn set<T>(&mut self, endpoint: Endpoint<InputValue<T>>, value: T) -> T::Output
85    where
86        T: SetInputValue,
87    {
88        SetInputValue::set_input_value(self, endpoint, value)
89    }
90
91    /// Get the value of an endpoint.
92    pub fn get<T>(&mut self, endpoint: Endpoint<OutputValue<T>>) -> T::Output<'_>
93    where
94        T: GetOutputValue,
95    {
96        T::get_output_value(self, endpoint)
97    }
98
99    /// Post an event to an endpoint.
100    pub fn post<'a>(
101        &mut self,
102        endpoint: Endpoint<InputEvent>,
103        event: impl Into<ValueRef<'a>>,
104    ) -> Result<(), EndpointError> {
105        post_event(self, endpoint, event.into())
106    }
107
108    /// Fetch the events received from an endpoint.
109    pub fn fetch(
110        &mut self,
111        endpoint: Endpoint<OutputEvent>,
112        callback: impl FnMut(usize, ValueRef<'_>),
113    ) -> Result<(), EndpointError> {
114        fetch_events(self, endpoint, callback)
115    }
116
117    /// Read frames from an input stream.
118    pub fn read<T>(&self, endpoint: Endpoint<OutputStream<T>>, buffer: &mut [T])
119    where
120        T: StreamType,
121    {
122        read_stream(self, endpoint, buffer)
123    }
124
125    /// Write frames to an output stream.
126    pub fn write<T>(&self, endpoint: Endpoint<InputStream<T>>, buffer: &[T])
127    where
128        T: StreamType,
129    {
130        write_stream(self, endpoint, buffer)
131    }
132
133    /// Returns the number of times the performer has over/under-run.
134    pub fn get_xruns(&self) -> usize {
135        self.ptr.get_xruns()
136    }
137
138    /// Returns the maximum number of frames that can be processed in a single call to `advance`.
139    pub fn get_max_block_size(&self) -> u32 {
140        self.ptr.get_max_block_size()
141    }
142
143    /// Returns the performers internal latency in frames.
144    pub fn get_latency(&self) -> f64 {
145        self.ptr.get_latency()
146    }
147
148    /// Returns the string associated with a handle.
149    pub fn get_string(&self, StringHandle(value): StringHandle) -> Option<&str> {
150        self.ptr.get_string_for_handle(value)
151    }
152}
153
154/// An error that can occur when interacting with performer endpoints.
155#[derive(Debug, thiserror::Error)]
156pub enum EndpointError {
157    /// The endpoint does not exist.
158    #[error("no such endpoint")]
159    EndpointDoesNotExist,
160
161    /// The direction of the endpoint does not match the expected direction.
162    #[error("direction mismatch")]
163    DirectionMismatch,
164
165    /// The type of the endpoint does not match the expected type.
166    #[error("type mismatch")]
167    EndpointTypeMismatch,
168
169    /// The data type does not match the expected type.
170    #[error("data type mismatch")]
171    DataTypeMismatch,
172}
173
174#[doc(hidden)]
175#[sealed(pub(crate))]
176pub trait EndpointType {
177    fn make(
178        handle: EndpointHandle,
179        endpoint: EndpointInfo,
180    ) -> Result<Endpoint<Self>, EndpointError>
181    where
182        Self: Sized;
183
184    fn handle(&self) -> EndpointHandle;
185}