1use {
4 crate::{juce, Result, JUCE},
5 slotmap::SlotMap,
6 std::{
7 ops::{Index, IndexMut},
8 pin::Pin,
9 },
10};
11
12pub struct InputAudioSampleBuffer<'a> {
14 buffer: &'a juce::AudioSampleBuffer,
15}
16
17impl<'a> InputAudioSampleBuffer<'a> {
18 pub(crate) fn new(buffer: &'a juce::AudioSampleBuffer) -> Self {
19 Self { buffer }
20 }
21
22 pub fn channels(&self) -> usize {
24 self.buffer.get_num_channels() as usize
25 }
26
27 pub fn samples(&self) -> usize {
29 self.buffer.get_num_samples() as usize
30 }
31}
32
33impl Index<usize> for InputAudioSampleBuffer<'_> {
34 type Output = [f32];
35
36 fn index(&self, channel: usize) -> &Self::Output {
37 if self.channels() < channel {
38 panic!("channel out of bounds");
39 }
40
41 let ptr = self.buffer.get_read_pointer(channel as i32);
42 let len = self.samples();
43
44 unsafe { std::slice::from_raw_parts(ptr, len) }
45 }
46}
47
48pub struct OutputAudioSampleBuffer<'a> {
50 buffer: Pin<&'a mut juce::AudioSampleBuffer>,
51}
52
53impl<'a> OutputAudioSampleBuffer<'a> {
54 pub(crate) fn new(buffer: Pin<&'a mut juce::AudioSampleBuffer>) -> Self {
55 Self { buffer }
56 }
57
58 pub fn channels(&self) -> usize {
60 self.buffer.get_num_channels() as usize
61 }
62
63 pub fn samples(&self) -> usize {
65 self.buffer.get_num_samples() as usize
66 }
67
68 pub fn clear(&mut self) {
70 self.buffer.as_mut().clear();
71 }
72}
73
74impl Index<usize> for OutputAudioSampleBuffer<'_> {
75 type Output = [f32];
76
77 fn index(&self, channel: usize) -> &Self::Output {
78 if self.channels() < channel {
79 panic!("channel out of bounds");
80 }
81
82 let ptr = self.buffer.get_read_pointer(channel as i32);
83 let len = self.samples();
84
85 unsafe { std::slice::from_raw_parts(ptr, len) }
86 }
87}
88
89impl IndexMut<usize> for OutputAudioSampleBuffer<'_> {
90 fn index_mut(&mut self, channel: usize) -> &mut Self::Output {
91 if self.channels() < channel {
92 panic!("channel out of bounds");
93 }
94
95 let ptr = self.buffer.as_mut().get_write_pointer(channel as i32);
96 let len = self.samples();
97
98 unsafe { std::slice::from_raw_parts_mut(ptr, len) }
99 }
100}
101
102pub struct AudioDeviceSetup(cxx::UniquePtr<juce::AudioDeviceSetup>);
104
105unsafe impl Send for AudioDeviceSetup {}
106
107impl Default for AudioDeviceSetup {
108 fn default() -> Self {
109 Self(juce::create_audio_device_setup())
110 }
111}
112
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum ChannelCount {
116 Default,
118
119 Custom(i32),
121}
122
123unsafe impl Send for ChannelCount {}
124
125impl AudioDeviceSetup {
126 pub fn output_device_name(&self) -> &str {
128 self.0.output_device_name()
129 }
130
131 pub fn with_output_device_name(mut self, name: impl AsRef<str>) -> Self {
133 self.0.pin_mut().set_output_device_name(name.as_ref());
134 self
135 }
136
137 pub fn input_device_name(&self) -> &str {
139 self.0.input_device_name()
140 }
141
142 pub fn with_input_device_name(mut self, name: impl AsRef<str>) -> Self {
144 self.0.pin_mut().set_input_device_name(name.as_ref());
145 self
146 }
147
148 pub fn sample_rate(&self) -> f64 {
150 self.0.sample_rate()
151 }
152
153 pub fn with_sample_rate(mut self, sample_rate: f64) -> Self {
155 self.0.pin_mut().set_sample_rate(sample_rate);
156 self
157 }
158
159 pub fn buffer_size(&self) -> usize {
161 self.0.buffer_size() as usize
162 }
163
164 pub fn with_buffer_size(mut self, buffer_size: usize) -> Self {
166 self.0.pin_mut().set_buffer_size(buffer_size as i32);
167 self
168 }
169
170 pub fn input_channels(&self) -> ChannelCount {
172 if self.0.using_default_input_channels() {
173 ChannelCount::Default
174 } else {
175 ChannelCount::Custom(self.0.number_of_input_channels())
176 }
177 }
178
179 pub fn with_input_channels(mut self, channels: ChannelCount) -> Self {
181 match channels {
182 ChannelCount::Default => {
183 self.0.pin_mut().use_default_input_channels(true);
184 }
185 ChannelCount::Custom(count) => {
186 self.0.pin_mut().use_default_input_channels(false);
187 self.0.pin_mut().set_number_of_input_channels(count);
188 }
189 }
190
191 self
192 }
193
194 pub fn output_channels(&self) -> ChannelCount {
196 if self.0.using_default_output_channels() {
197 ChannelCount::Default
198 } else {
199 ChannelCount::Custom(self.0.number_of_output_channels())
200 }
201 }
202
203 pub fn with_output_channels(mut self, channels: ChannelCount) -> Self {
205 match channels {
206 ChannelCount::Default => {
207 self.0.pin_mut().use_default_output_channels(true);
208 }
209 ChannelCount::Custom(count) => {
210 self.0.pin_mut().use_default_output_channels(false);
211 self.0.pin_mut().set_number_of_output_channels(count);
212 }
213 }
214
215 self
216 }
217}
218
219slotmap::new_key_type! {
220 struct AudioCallbackKey;
221}
222
223pub struct AudioDeviceManager {
225 device_manager: cxx::UniquePtr<juce::AudioDeviceManager>,
226 callbacks: SlotMap<AudioCallbackKey, cxx::UniquePtr<juce::AudioCallbackWrapper>>,
227 _juce: JUCE,
228}
229
230impl AudioDeviceManager {
231 pub fn new(juce: &JUCE) -> Self {
233 Self {
234 device_manager: juce::create_audio_device_manager(),
235 callbacks: SlotMap::with_key(),
236 _juce: juce.clone(),
237 }
238 }
239
240 pub fn initialise(&mut self, input_channels: usize, output_channels: usize) -> Result<()> {
242 self.device_manager
243 .pin_mut()
244 .initialise_with_default_devices(input_channels as i32, output_channels as i32)
245 }
246
247 pub fn audio_device_setup(&self) -> AudioDeviceSetup {
249 AudioDeviceSetup(self.device_manager.get_audio_device_setup())
250 }
251
252 pub fn set_audio_device_setup(&mut self, setup: &AudioDeviceSetup) {
254 self.device_manager
255 .pin_mut()
256 .set_audio_device_setup(&setup.0);
257 }
258
259 pub fn play_test_sound(&mut self) {
261 self.device_manager.pin_mut().play_test_sound();
262 }
263
264 pub fn device_types(&mut self) -> Vec<impl AudioIODeviceType + '_> {
266 let available_device_types = self.device_manager.pin_mut().get_available_device_types();
267
268 (0..available_device_types.size())
269 .map(|i| available_device_types.get_unchecked(i))
270 .collect()
271 }
272
273 pub fn current_device_type(&self) -> Option<impl AudioIODeviceType + '_> {
275 let device_type = self.device_manager.get_current_device_type_object();
276 if !device_type.is_null() {
277 Some(device_type)
278 } else {
279 None
280 }
281 }
282
283 pub fn current_device(&self) -> Option<impl AudioIODevice + '_> {
285 let current_device = self.device_manager.get_current_audio_device();
286 if !current_device.is_null() {
287 Some(current_device)
288 } else {
289 None
290 }
291 }
292
293 pub fn add_audio_callback(
295 &mut self,
296 callback: impl AudioIODeviceCallback + 'static,
297 ) -> AudioCallbackHandle {
298 let callback = Box::new(callback);
299 let callback = juce::wrap_audio_callback(Box::new(callback));
300
301 self.device_manager.pin_mut().add_audio_callback(&callback);
302 let key = self.callbacks.insert(callback);
303
304 AudioCallbackHandle { key }
305 }
306
307 pub fn remove_audio_callback(&mut self, handle: AudioCallbackHandle) {
309 if let Some(callback) = self.callbacks.remove(handle.key) {
310 self.device_manager
311 .pin_mut()
312 .remove_audio_callback(&callback);
313 }
314 }
315
316 pub fn add_audio_device_type(&mut self, device_type: impl AudioIODeviceType + 'static) {
318 let device_type = Box::new(device_type);
319 self.device_manager
320 .pin_mut()
321 .add_audio_device_type(Box::new(device_type));
322 }
323
324 pub fn set_current_audio_device_type(&mut self, device_type: &str) {
326 self.device_manager
327 .pin_mut()
328 .set_current_audio_device_type(device_type);
329 }
330}
331
332pub trait AudioIODeviceCallback: Send {
338 fn about_to_start(&mut self, device: &mut dyn AudioIODevice);
340
341 fn process_block(
343 &mut self,
344 input: &InputAudioSampleBuffer<'_>,
345 output: &mut OutputAudioSampleBuffer<'_>,
346 );
347
348 fn stopped(&mut self);
350}
351
352pub(crate) type BoxedAudioIODeviceCallback = Box<dyn AudioIODeviceCallback>;
353pub(crate) type BoxedAudioIODeviceType = Box<dyn AudioIODeviceType>;
354pub(crate) type BoxedAudioIODevice = Box<dyn AudioIODevice>;
355
356#[must_use]
358pub struct AudioCallbackHandle {
359 key: AudioCallbackKey,
360}
361
362pub trait AudioIODeviceType {
364 fn name(&self) -> String;
366
367 fn scan_for_devices(&mut self);
369
370 fn input_devices(&self) -> Vec<String>;
372
373 fn output_devices(&self) -> Vec<String>;
375
376 fn create_device(
378 &mut self,
379 input_device_name: &str,
380 output_device_name: &str,
381 ) -> Option<Box<dyn AudioIODevice>>;
382}
383
384impl AudioIODeviceType for *mut juce::AudioIODeviceType {
385 fn name(&self) -> String {
386 if self.is_null() {
387 return String::default();
388 }
389
390 let this = unsafe { &*self.cast_const() };
391 juce::get_type_name(this)
392 }
393
394 fn scan_for_devices(&mut self) {
395 if let Some(this) = unsafe { self.as_mut().map(|ptr| Pin::new_unchecked(ptr)) } {
396 this.scan_for_devices();
397 }
398 }
399
400 fn input_devices(&self) -> Vec<String> {
401 if self.is_null() {
402 return vec![];
403 }
404
405 let this = unsafe { &*self.cast_const() };
406 juce::get_input_device_names(this)
407 }
408
409 fn output_devices(&self) -> Vec<String> {
410 if self.is_null() {
411 return vec![];
412 }
413
414 let this = unsafe { &*self.cast_const() };
415 juce::get_output_device_names(this)
416 }
417
418 fn create_device(
419 &mut self,
420 input_device_name: &str,
421 output_device_name: &str,
422 ) -> Option<Box<dyn AudioIODevice>> {
423 unsafe { self.as_mut().map(|ptr| Pin::new_unchecked(ptr)) }
424 .map(|this| juce::new_device(this, input_device_name, output_device_name))
425 .filter(|device| !device.is_null())
426 .map(|device| Box::new(device) as _)
427 }
428}
429
430pub trait AudioIODevice {
432 fn name(&self) -> &str;
434
435 fn type_name(&self) -> &str;
437
438 fn sample_rate(&mut self) -> f64;
440
441 fn buffer_size(&mut self) -> usize;
443
444 fn available_sample_rates(&mut self) -> Vec<f64>;
446
447 fn available_buffer_sizes(&mut self) -> Vec<usize>;
449
450 fn open(&mut self, sample_rate: f64, buffer_size: usize) -> Result<()>;
452
453 fn close(&mut self);
455
456 fn input_channels(&self) -> i32;
458
459 fn output_channels(&self) -> i32;
461}
462
463impl AudioIODevice for *mut juce::AudioIODevice {
464 fn name(&self) -> &str {
465 unsafe { self.as_ref() }
466 .map(juce::get_device_name)
467 .unwrap_or_default()
468 }
469
470 fn type_name(&self) -> &str {
471 unsafe { self.as_ref() }
472 .map(juce::get_device_type_name)
473 .unwrap_or_default()
474 }
475
476 fn sample_rate(&mut self) -> f64 {
477 unsafe { self.as_mut().map(|this| Pin::new_unchecked(this)) }
478 .map(|this| this.get_current_sample_rate())
479 .unwrap_or_default()
480 }
481
482 fn buffer_size(&mut self) -> usize {
483 unsafe { self.as_mut().map(|this| Pin::new_unchecked(this)) }
484 .map(|this| this.get_current_buffer_size_samples() as usize)
485 .unwrap_or_default()
486 }
487
488 fn available_sample_rates(&mut self) -> Vec<f64> {
489 unsafe { self.as_mut().map(|this| Pin::new_unchecked(this)) }
490 .map(juce::get_available_sample_rates)
491 .unwrap_or_default()
492 }
493
494 fn available_buffer_sizes(&mut self) -> Vec<usize> {
495 unsafe { self.as_mut().map(|this| Pin::new_unchecked(this)) }
496 .map(juce::get_available_buffer_sizes)
497 .unwrap_or_default()
498 }
499
500 fn open(&mut self, sample_rate: f64, buffer_size: usize) -> Result<()> {
501 if let Some(this) = unsafe { self.as_mut().map(|this| Pin::new_unchecked(this)) } {
502 juce::open(this, sample_rate, buffer_size)?;
503 }
504
505 Ok(())
506 }
507
508 fn close(&mut self) {
509 if let Some(this) = unsafe { self.as_mut().map(|this| Pin::new_unchecked(this)) } {
510 this.close();
511 }
512 }
513
514 fn input_channels(&self) -> i32 {
515 unsafe { self.as_ref() }
516 .map(juce::count_active_input_channels)
517 .unwrap_or_default()
518 }
519
520 fn output_channels(&self) -> i32 {
521 unsafe { self.as_ref() }
522 .map(juce::count_active_output_channels)
523 .unwrap_or_default()
524 }
525}
526
527impl AudioIODevice for Pin<&mut juce::AudioIODevice> {
528 fn name(&self) -> &str {
529 juce::get_device_name(self)
530 }
531
532 fn type_name(&self) -> &str {
533 juce::get_device_type_name(self)
534 }
535
536 fn sample_rate(&mut self) -> f64 {
537 juce::AudioIODevice::get_current_sample_rate(self.as_mut())
538 }
539
540 fn buffer_size(&mut self) -> usize {
541 juce::AudioIODevice::get_current_buffer_size_samples(self.as_mut()) as usize
542 }
543
544 fn available_sample_rates(&mut self) -> Vec<f64> {
545 juce::get_available_sample_rates(self.as_mut())
546 }
547
548 fn available_buffer_sizes(&mut self) -> Vec<usize> {
549 juce::get_available_buffer_sizes(self.as_mut())
550 }
551
552 fn open(&mut self, sample_rate: f64, buffer_size: usize) -> Result<()> {
553 juce::open(self.as_mut(), sample_rate, buffer_size)
554 }
555
556 fn close(&mut self) {
557 juce::AudioIODevice::close(self.as_mut());
558 }
559
560 fn input_channels(&self) -> i32 {
561 juce::count_active_input_channels(self)
562 }
563
564 fn output_channels(&self) -> i32 {
565 juce::count_active_output_channels(self)
566 }
567}
568
569impl AudioIODevice for cxx::UniquePtr<juce::AudioIODevice> {
570 fn name(&self) -> &str {
571 self.as_ref().map(juce::get_device_name).unwrap_or_default()
572 }
573
574 fn type_name(&self) -> &str {
575 self.as_ref()
576 .map(juce::get_device_type_name)
577 .unwrap_or_default()
578 }
579
580 fn sample_rate(&mut self) -> f64 {
581 self.as_mut()
582 .map(|this| this.get_current_sample_rate())
583 .unwrap_or_default()
584 }
585
586 fn buffer_size(&mut self) -> usize {
587 self.as_mut()
588 .map(|this| this.get_current_buffer_size_samples() as usize)
589 .unwrap_or_default()
590 }
591
592 fn available_sample_rates(&mut self) -> Vec<f64> {
593 self.as_mut()
594 .map(juce::get_available_sample_rates)
595 .unwrap_or_default()
596 }
597
598 fn available_buffer_sizes(&mut self) -> Vec<usize> {
599 self.as_mut()
600 .map(juce::get_available_buffer_sizes)
601 .unwrap_or_default()
602 }
603
604 fn open(&mut self, sample_rate: f64, buffer_size: usize) -> Result<()> {
605 if let Some(this) = self.as_mut() {
606 juce::open(this, sample_rate, buffer_size)?;
607 }
608
609 Ok(())
610 }
611
612 fn close(&mut self) {
613 if let Some(this) = self.as_mut() {
614 this.close();
615 }
616 }
617
618 fn input_channels(&self) -> i32 {
619 self.as_ref()
620 .map(juce::count_active_input_channels)
621 .unwrap_or_default()
622 }
623
624 fn output_channels(&self) -> i32 {
625 self.as_ref()
626 .map(juce::count_active_output_channels)
627 .unwrap_or_default()
628 }
629}
630
631pub(crate) mod ffi {
632 use super::*;
633
634 pub mod audio_io_device_callback {
635 use super::*;
636
637 pub fn about_to_start(
638 mut self_: Pin<&mut BoxedAudioIODeviceCallback>,
639 mut device: Pin<&mut juce::AudioIODevice>,
640 ) {
641 self_.about_to_start(&mut device.as_mut());
642 }
643
644 pub fn process_block(
645 mut self_: Pin<&mut BoxedAudioIODeviceCallback>,
646 input: &juce::AudioSampleBuffer,
647 output: Pin<&mut juce::AudioSampleBuffer>,
648 ) {
649 let input = InputAudioSampleBuffer::new(input);
650 let mut output = OutputAudioSampleBuffer::new(output);
651
652 self_.process_block(&input, &mut output);
653 }
654
655 pub fn stopped(mut self_: Pin<&mut BoxedAudioIODeviceCallback>) {
656 self_.stopped()
657 }
658 }
659
660 pub mod audio_io_device_type {
661 use {super::*, std::ptr::null_mut};
662
663 pub fn name(self_: &BoxedAudioIODeviceType) -> String {
664 self_.name()
665 }
666
667 pub fn scan_for_devices(mut self_: Pin<&mut BoxedAudioIODeviceType>) {
668 self_.scan_for_devices()
669 }
670
671 pub fn get_device_names(self_: &BoxedAudioIODeviceType, input: bool) -> Vec<String> {
672 if input {
673 self_.input_devices()
674 } else {
675 self_.output_devices()
676 }
677 }
678
679 pub fn create_device(
680 mut self_: Pin<&mut BoxedAudioIODeviceType>,
681 input_name: &str,
682 output_name: &str,
683 ) -> *mut BoxedAudioIODevice {
684 let device = self_.as_mut().create_device(input_name, output_name);
685
686 device
687 .map(|device| Box::into_raw(Box::new(device)))
688 .unwrap_or(null_mut())
689 }
690
691 pub fn destroy_device(device: *mut BoxedAudioIODevice) {
692 if device.is_null() {
693 return;
694 }
695
696 let _ = unsafe { Box::from_raw(device) };
697 }
698 }
699
700 pub mod audio_io_device {
701 use super::*;
702
703 pub fn device_name(self_: &BoxedAudioIODevice) -> String {
704 self_.name().to_string()
705 }
706
707 pub fn device_type_name(self_: &BoxedAudioIODevice) -> String {
708 self_.type_name().to_string()
709 }
710
711 pub fn device_sample_rate(mut self_: Pin<&mut BoxedAudioIODevice>) -> f64 {
712 self_.sample_rate()
713 }
714
715 pub fn device_buffer_size(mut self_: Pin<&mut BoxedAudioIODevice>) -> usize {
716 self_.buffer_size()
717 }
718
719 pub fn device_available_sample_rates(mut self_: Pin<&mut BoxedAudioIODevice>) -> Vec<f64> {
720 self_.available_sample_rates()
721 }
722
723 pub fn device_available_buffer_sizes(
724 mut self_: Pin<&mut BoxedAudioIODevice>,
725 ) -> Vec<usize> {
726 self_.available_buffer_sizes()
727 }
728
729 pub fn device_open(
730 mut self_: Pin<&mut BoxedAudioIODevice>,
731 sample_rate: f64,
732 buffer_size: usize,
733 ) -> String {
734 match self_.open(sample_rate, buffer_size) {
735 Ok(()) => String::default(),
736 Err(error) => error.to_string(),
737 }
738 }
739
740 pub fn device_close(mut self_: Pin<&mut BoxedAudioIODevice>) {
741 self_.close()
742 }
743 }
744}
745
746pub struct SystemAudioVolume;
748
749impl SystemAudioVolume {
750 pub fn get_gain() -> f32 {
752 juce::get_gain()
753 }
754
755 pub fn set_gain(gain: f32) {
757 juce::set_gain(gain.clamp(0.0, 1.0))
758 }
759
760 pub fn is_muted() -> bool {
762 juce::is_muted()
763 }
764
765 pub fn mute() {
767 juce::set_muted(true);
768 }
769
770 pub fn unmute() {
772 juce::set_muted(false);
773 }
774}