rundsp/stream/run/start.rs
1//! All of the free functions which start the creation of a [`Run`].
2//!
3//! Each of these corresponds to a builder method on [`Run`]; these are purely convenience methods
4//! which are shorthands for `Run::new().method(...)`.
5
6use fundsp::hacker::{U1, U2, multipass};
7
8use crate::{FromStereo, ToStereo};
9
10use super::*;
11
12impl Default for Run {
13 fn default() -> Self {
14 Self::new()
15 }
16}
17
18impl Run {
19 /// Create a new [`Run`] with default parameters.
20 ///
21 /// This cannot be [`run`](Run::run) without a type error until at least one of
22 /// [`input`](Run::input) or [`output`](Run::output) are specified.
23 pub fn new() -> Self {
24 Run {
25 host: None,
26 select_device: Arc::new(|_, _| None),
27 select_config: Arc::new(|_, _| None),
28 input_info: |_| {},
29 output_info: |_| {},
30 timeout: None,
31 start_paused: false,
32 retrying: Arc::new(Mutex::new(|_: &Error| Retry::stop())),
33 control: mpsc::channel(1).1,
34 input: NoInput,
35 output: NoOutput,
36 }
37 }
38}
39
40impl<L, M, I, O> Run<I, O, L, M>
41where
42 L: InputInfo,
43 M: OutputInfo,
44{
45 /// Use the given audio [`Host`].
46 pub fn host(mut self, host: Host) -> Self {
47 self.host = Some(Arc::new(host));
48 self
49 }
50
51 /// Use the specified closure to select which [`Device`] should be used for each end of the
52 /// pipeline.
53 pub fn device(mut self, select_device: impl SelectDevice) -> Self {
54 self.select_device = Arc::new(select_device);
55 self
56 }
57
58 /// Use the specified closure to select which [`SupportedStreamConfig`] should be used for each
59 /// end of the pipeline.
60 pub fn config(mut self, select_config: impl SelectConfig) -> Self {
61 self.select_config = Arc::new(select_config);
62 self
63 }
64
65 /// Use the specified audio node as the input end of the pipeline.
66 ///
67 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
68 /// options may also be specified afterwards.
69 pub fn input<N: StereoInput>(self, input: An<N>) -> Run<An<N>, O, L, M> {
70 let Run {
71 host,
72 select_device,
73 select_config,
74 input_info,
75 output_info,
76 timeout,
77 start_paused,
78 retrying,
79 control,
80 input: _,
81 output,
82 } = self;
83 Run {
84 host,
85 select_device,
86 select_config,
87 input_info,
88 output_info,
89 timeout,
90 start_paused,
91 retrying,
92 control,
93 input,
94 output,
95 }
96 }
97
98 /// Feed the microphone's input directly to the output of the pipeline.
99 ///
100 /// In case of ambiguous type inference, use [`mono_mic`](Run::mono_mic) or
101 /// [`stereo_mic`](Run::stereo_mic) to disambiguate.
102 ///
103 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
104 /// options may also be specified afterwards.
105 pub fn mic<N: FromStereo>(self) -> Run<An<impl StereoInput<Outputs = N>>, O, L, M> {
106 self.input(multipass())
107 }
108
109 /// Feed the microphone's input directly to the output of the pipeline, as *mono* audio.
110 ///
111 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
112 /// options may also be specified afterwards.
113 pub fn mono_mic(self) -> Run<An<impl StereoInput<Outputs = U1>>, O, L, M> {
114 self.mic::<U1>()
115 }
116
117 /// Feed the microphone's input directly to the output of the pipeline, as *stereo* audio.
118 ///
119 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
120 /// options may also be specified afterwards.
121 pub fn stereo_mic(self) -> Run<An<impl StereoInput<Outputs = U2>>, O, L, M> {
122 self.mic::<U2>()
123 }
124
125 /// Use the specified audio node as the output end of the pipeline.
126 ///
127 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
128 /// options may also be specified afterwards.
129 pub fn output<N: StereoOutput>(self, output: An<N>) -> Run<I, An<N>, L, M> {
130 let Run {
131 host,
132 select_device,
133 select_config,
134 input_info,
135 output_info,
136 timeout,
137 start_paused,
138 retrying,
139 control,
140 input,
141 output: _,
142 } = self;
143 Run {
144 host,
145 select_device,
146 select_config,
147 input_info,
148 output_info,
149 timeout,
150 start_paused,
151 retrying,
152 control,
153 input,
154 output,
155 }
156 }
157
158 /// Feed the output of the pipeline directly to the speaker (or headphones).
159 ///
160 /// In case of ambiguous type inference, use [`mono_speaker`](Run::mono_speaker) or
161 /// [`stereo_speaker`](Run::stereo_speaker) to disambiguate.
162 ///
163 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
164 /// options may also be specified afterwards.
165 pub fn speaker<N: ToStereo>(self) -> Run<I, An<impl StereoOutput<Inputs = N>>, L, M> {
166 self.output(multipass())
167 }
168
169 /// Feed the output of the pipeline directly to the speaker (or headphones), as *mono* audio.
170 ///
171 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
172 /// options may also be specified afterwards.
173 pub fn mono_speaker(self) -> Run<I, An<impl StereoOutput<Inputs = U1>>, L, M> {
174 self.speaker::<U1>()
175 }
176
177 /// Feed the output of the pipeline directly to the speaker (or headphones), as *stereo* audio.
178 ///
179 /// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
180 /// options may also be specified afterwards.
181 pub fn stereo_speaker(self) -> Run<I, An<impl StereoOutput<Inputs = U2>>, L, M> {
182 self.speaker::<U2>()
183 }
184
185 /// Call the given closure every time an input buffer is received.
186 ///
187 /// The closure specified should be fast, non-allocating, and non-blocking; otherwise, audio
188 /// glitches may occur.
189 pub fn on_input<X: InputInfo>(self, input_info: X) -> Run<I, O, X, M> {
190 let Run {
191 host,
192 select_device,
193 select_config,
194 input_info: _,
195 output_info,
196 timeout,
197 start_paused,
198 retrying,
199 control,
200 input,
201 output,
202 } = self;
203 Run {
204 host,
205 select_device,
206 select_config,
207 input_info,
208 output_info,
209 timeout,
210 start_paused,
211 retrying,
212 control,
213 input,
214 output,
215 }
216 }
217
218 /// Call the given closure every time an input buffer is produced.
219 ///
220 /// The closure specified should be fast, non-allocating, and non-blocking; otherwise, audio
221 /// glitches may occur.
222 pub fn on_output<X: OutputInfo>(self, output_info: X) -> Run<I, O, L, X> {
223 let Run {
224 host,
225 select_device,
226 select_config,
227 input_info,
228 output_info: _,
229 timeout,
230 start_paused,
231 retrying,
232 control,
233 input,
234 output,
235 } = self;
236 Run {
237 host,
238 select_device,
239 select_config,
240 input_info,
241 output_info,
242 timeout,
243 start_paused,
244 retrying,
245 control,
246 input,
247 output,
248 }
249 }
250
251 /// Use the given closure to determine how to retry in the event of an error while building or
252 /// running a stream. See [`Retrying`] for more information.
253 pub fn on_error<R: Into<Retry>>(mut self, mut retry: impl Retrying<R>) -> Self {
254 self.retrying = Arc::new(Mutex::new(move |error: &Error| retry(error).into()));
255 self
256 }
257
258 /// Start the audio pipeline paused, so that it has to be manually played.
259 pub fn paused(mut self) -> Self {
260 self.start_paused = true;
261 self
262 }
263
264 /// Run the audio pipeline as specified.
265 ///
266 /// This method call will not type-check unless you have specified at least one of
267 /// [`input`](Run::input) or [`output`](Run::output), or equivalently unless you started the
268 /// builder using [`input`] or [`output`].
269 pub fn run(self) -> Running
270 where
271 I: RunWith<O>,
272 {
273 self.run_audio()
274 }
275}
276
277// Free functions to start building a `Run`:
278
279/// Create a new [`Run`] using a given audio [`Host`].
280///
281/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
282/// [`input`](Run::input) or [`output`](Run::output) are specified.
283pub fn host(host: Host) -> Run {
284 Run::new().host(host)
285}
286
287/// Create a new [`Run`] using the given closure to select an audio [`Device`].
288///
289/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
290/// [`input`](Run::input) or [`output`](Run::output) are specified.
291pub fn device(select_device: impl SelectDevice) -> Run {
292 Run::new().device(select_device)
293}
294
295/// Create a new [`Run`] using the given closure to select an audio [`SupportedStreamConfig`].
296///
297/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
298/// [`input`](Run::input) or [`output`](Run::output) are specified.
299pub fn config(select_config: impl SelectConfig) -> Run {
300 Run::new().config(select_config)
301}
302
303/// Create a new [`Run`] using the given audio node as the input end.
304///
305/// The resultant [`Run`] can be immediately [`run`](Run::run), or further options may be specified.
306pub fn input<I: StereoInput>(input: An<I>) -> Run<An<I>, NoOutput> {
307 Run::new().input(input)
308}
309
310/// Create a new [`Run`] that feeds the microphone's input directly to the output of the pipeline.
311///
312/// In case of ambiguous type inference, use [`mono_mic`](Run::mono_mic) or
313/// [`stereo_mic`](Run::stereo_mic) to disambiguate.
314///
315/// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
316/// options may also be specified afterwards.
317pub fn mic<N: FromStereo>() -> Run<An<impl StereoInput<Outputs = N>>, NoOutput> {
318 Run::new().mic()
319}
320
321/// Create a new [`Run`] that feeds the microphone's input directly to the output of the pipeline,
322/// as *mono* audio.
323///
324/// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
325/// options may also be specified afterwards.
326pub fn mono_mic() -> Run<An<impl StereoInput<Outputs = U1>>, NoOutput> {
327 Run::new().mono_mic()
328}
329
330/// Create a new [`Run`] that feeds the microphone's input directly to the output of the pipeline,
331/// as *stereo* audio.
332///
333/// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
334/// options may also be specified afterwards.
335pub fn stereo_mic() -> Run<An<impl StereoInput<Outputs = U2>>, NoOutput> {
336 Run::new().stereo_mic()
337}
338
339/// Create a new [`Run`] using the given audio node as the output end.
340///
341/// The resultant [`Run`] can be immediately [`run`](Run::run), or further options may be specified.
342pub fn output<O: StereoOutput>(output: An<O>) -> Run<NoInput, An<O>> {
343 Run::new().output(output)
344}
345
346/// Create a new [`Run`] that feeds the output of the pipeline directly to the speaker (or
347/// headphones).
348///
349/// In case of ambiguous type inference, use [`mono_speaker`](Run::mono_speaker) or
350/// [`stereo_speaker`](Run::stereo_speaker) to disambiguate.
351///
352/// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
353/// options may also be specified afterwards.
354pub fn speaker<N: ToStereo>() -> Run<NoInput, An<impl StereoOutput<Inputs = N>>> {
355 Run::new().speaker()
356}
357
358/// Create a new [`Run`] that feeds the output of the pipeline directly to the speaker (or
359/// headphones), as *mono* audio.
360///
361/// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
362/// options may also be specified afterwards.
363pub fn mono_speaker() -> Run<NoInput, An<impl StereoOutput<Inputs = U1>>> {
364 Run::new().mono_speaker()
365}
366
367/// Create a new [`Run`] that feeds the output of the pipeline directly to the speaker (or
368/// headphones), as *stereo* audio.
369///
370/// After specifying this, it is now possible to [`run`](Run::run) the pipline, although other
371/// options may also be specified afterwards.
372pub fn stereo_speaker() -> Run<NoInput, An<impl StereoOutput<Inputs = U2>>> {
373 Run::new().stereo_speaker()
374}
375
376/// Create a new [`Run`] which will call the given closure every time an input buffer is received.
377///
378/// The closure specified should be fast, non-allocating, and non-blocking; otherwise, audio
379/// glitches may occur.
380///
381/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
382/// [`input`](Run::input) or [`output`](Run::output) are specified.
383pub fn on_input<I: InputInfo>(input_info: I) -> Run<NoInput, NoOutput, I, FnOutputInfo> {
384 Run::new().on_input(input_info)
385}
386
387/// Create a new [`Run`] which will call the given closure every time an output buffer is produced.
388///
389/// The closure specified should be fast, non-allocating, and non-blocking; otherwise, audio
390/// glitches may occur.
391///
392/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
393/// [`input`](Run::input) or [`output`](Run::output) are specified.
394pub fn on_output<O: OutputInfo>(output_info: O) -> Run<NoInput, NoOutput, FnInputInfo, O> {
395 Run::new().on_output(output_info)
396}
397
398/// Create a new [`Run`] which will use the given closure to determine how to retry in the event of
399/// an error while building or running a stream. See [`Retrying`] for more information.
400///
401/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
402/// [`input`](Run::input) or [`output`](Run::output) are specified.
403pub fn on_error<R: Into<Retry>>(retry: impl Retrying<R>) -> Run {
404 Run::new().on_error(retry)
405}
406
407/// Create a new [`Run`] which will start paused, so that it has to be manually played before audio
408/// will happen.
409///
410/// The resultant [`Run`] cannot be [`run`](Run::run) without a type error until at least one of
411/// [`input`](Run::input) or [`output`](Run::output) are specified.
412pub fn start_paused() -> Run {
413 Run::new().paused()
414}