1use num_traits::FromPrimitive;
2use oboe_sys as ffi;
3use std::{
4 ffi::c_void,
5 fmt::{self, Display},
6 marker::PhantomData,
7 mem::{transmute, MaybeUninit},
8 ops::{Deref, DerefMut},
9};
10
11use super::{
12 audio_stream_base_fmt, wrap_result, wrap_status, AudioApi, AudioStreamBase, FrameTimestamp,
13 Input, IsFrameType, Output, RawAudioInputStream, RawAudioOutputStream, RawAudioStream,
14 RawAudioStreamBase, Result, Status, StreamState, NANOS_PER_MILLISECOND,
15};
16
17pub const DEFAULT_TIMEOUT_NANOS: i64 = 2000 * NANOS_PER_MILLISECOND;
24
25pub trait AudioStreamSafe: AudioStreamBase {
29 fn get_state(&self) -> StreamState;
33
34 fn set_buffer_size_in_frames(&mut self, _requested_frames: i32) -> Result<i32>;
43
44 fn get_xrun_count(&self) -> Result<i32>;
54
55 fn is_xrun_count_supported(&self) -> bool;
59
60 fn get_frames_per_burst(&mut self) -> i32;
64
65 fn get_bytes_per_frame(&mut self) -> i32 {
71 self.get_channel_count() as i32 * self.get_bytes_per_sample()
72 }
73
74 fn get_bytes_per_sample(&mut self) -> i32;
81
82 fn calculate_latency_millis(&mut self) -> Result<f64>;
103
104 fn get_timestamp(&mut self, clock_id: i32) -> Result<FrameTimestamp>;
120
121 fn get_audio_api(&self) -> AudioApi;
125
126 fn uses_aaudio(&self) -> bool {
130 self.get_audio_api() == AudioApi::AAudio
131 }
132
133 fn get_available_frames(&mut self) -> Result<i32>;
137}
138
139pub trait AudioStream: AudioStreamSafe {
143 fn open(&mut self) -> Status {
150 Ok(())
151 }
152
153 fn close(&mut self) -> Status;
157
158 fn start(&mut self) -> Status {
163 self.start_with_timeout(DEFAULT_TIMEOUT_NANOS)
164 }
165
166 fn start_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status;
171
172 fn stop(&mut self) -> Status {
177 self.stop_with_timeout(DEFAULT_TIMEOUT_NANOS)
178 }
179
180 fn stop_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status;
185
186 fn request_start(&mut self) -> Status;
191
192 fn request_stop(&mut self) -> Status;
197
198 fn wait_for_state_change(
224 &mut self,
225 input_state: StreamState,
226 timeout_nanoseconds: i64,
227 ) -> Result<StreamState>;
228
229 fn wait_for_available_frames(
235 &mut self,
236 num_frames: i32,
237 timeout_nanoseconds: i64,
238 ) -> Result<i32>;
239}
240
241pub trait AudioInputStreamSafe: AudioStreamSafe {
245 fn get_frames_read(&mut self) -> i64;
250}
251
252pub trait AudioInputStream: AudioStream + AudioInputStreamSafe {}
256
257pub trait AudioInputStreamSync: AudioInputStream {
261 type FrameType: IsFrameType;
262
263 fn read(
270 &mut self,
271 _buffer: &mut [<Self::FrameType as IsFrameType>::Type],
272 _timeout_nanoseconds: i64,
273 ) -> Result<i32>;
274}
275
276pub trait AudioOutputStreamSafe: AudioStreamSafe {
280 fn get_frames_written(&mut self) -> i64;
285}
286
287pub trait AudioOutputStream: AudioStream + AudioOutputStreamSafe {
291 fn pause(&mut self) -> Status {
296 self.pause_with_timeout(DEFAULT_TIMEOUT_NANOS)
297 }
298
299 fn pause_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status;
304
305 fn flush(&mut self) -> Status {
310 self.flush_with_timeout(DEFAULT_TIMEOUT_NANOS)
311 }
312
313 fn flush_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status;
318
319 fn request_pause(&mut self) -> Status;
324
325 fn request_flush(&mut self) -> Status;
330}
331
332pub trait AudioOutputStreamSync: AudioOutputStream {
336 type FrameType: IsFrameType;
337
338 fn write(
345 &mut self,
346 _buffer: &[<Self::FrameType as IsFrameType>::Type],
347 _timeout_nanoseconds: i64,
348 ) -> Result<i32>;
349}
350
351impl<T: RawAudioStream + RawAudioStreamBase> AudioStreamSafe for T {
352 fn set_buffer_size_in_frames(&mut self, requested_frames: i32) -> Result<i32> {
353 wrap_result(unsafe {
354 ffi::oboe_AudioStream_setBufferSizeInFrames(self._raw_stream_mut(), requested_frames)
355 })
356 }
357
358 fn get_state(&self) -> StreamState {
359 FromPrimitive::from_i32(unsafe {
360 ffi::oboe_AudioStream_getState(self._raw_stream() as *const _ as *mut _)
361 })
362 .unwrap()
363 }
364
365 fn get_xrun_count(&self) -> Result<i32> {
366 wrap_result(unsafe {
367 ffi::oboe_AudioStream_getXRunCount(self._raw_stream() as *const _ as *mut _)
368 })
369 }
370
371 fn is_xrun_count_supported(&self) -> bool {
372 unsafe { ffi::oboe_AudioStream_isXRunCountSupported(self._raw_stream()) }
373 }
374
375 fn get_frames_per_burst(&mut self) -> i32 {
376 unsafe { ffi::oboe_AudioStream_getFramesPerBurst(self._raw_stream_mut()) }
377 }
378
379 fn get_bytes_per_sample(&mut self) -> i32 {
380 unsafe { ffi::oboe_AudioStream_getBytesPerSample(self._raw_stream_mut()) }
381 }
382
383 fn calculate_latency_millis(&mut self) -> Result<f64> {
384 wrap_result(unsafe { ffi::oboe_AudioStream_calculateLatencyMillis(self._raw_stream_mut()) })
385 }
386
387 fn get_timestamp(&mut self, clock_id: i32 ) -> Result<FrameTimestamp> {
388 wrap_result(unsafe {
389 transmute(ffi::oboe_AudioStream_getTimestamp(
390 self._raw_stream_mut() as *mut _ as *mut c_void,
391 clock_id,
392 ))
393 })
394 }
395
396 fn get_audio_api(&self) -> AudioApi {
397 FromPrimitive::from_i32(unsafe { ffi::oboe_AudioStream_getAudioApi(self._raw_stream()) })
398 .unwrap()
399 }
400
401 fn get_available_frames(&mut self) -> Result<i32> {
402 wrap_result(unsafe { ffi::oboe_AudioStream_getAvailableFrames(self._raw_stream_mut()) })
403 }
404}
405
406impl<T: RawAudioStream + RawAudioStreamBase> AudioStream for T {
407 fn open(&mut self) -> Status {
408 wrap_status(unsafe { ffi::oboe_AudioStream_open(self._raw_stream_mut()) })
409 }
410
411 fn close(&mut self) -> Status {
412 wrap_status(unsafe { ffi::oboe_AudioStream_close1(self._raw_stream_mut()) })
413 }
414
415 fn start_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status {
416 wrap_status(unsafe {
417 ffi::oboe_AudioStream_start(
418 self._raw_stream_mut() as *mut _ as *mut c_void,
419 timeout_nanoseconds,
420 )
421 })
422 }
423
424 fn stop_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status {
425 wrap_status(unsafe {
426 ffi::oboe_AudioStream_stop(
427 self._raw_stream_mut() as *mut _ as *mut c_void,
428 timeout_nanoseconds,
429 )
430 })
431 }
432
433 fn request_start(&mut self) -> Status {
434 wrap_status(unsafe { ffi::oboe_AudioStream_requestStart(self._raw_stream_mut()) })
435 }
436
437 fn request_stop(&mut self) -> Status {
438 wrap_status(unsafe { ffi::oboe_AudioStream_requestStop(self._raw_stream_mut()) })
439 }
440
441 fn wait_for_state_change(
442 &mut self,
443 input_state: StreamState,
444 timeout_nanoseconds: i64,
445 ) -> Result<StreamState> {
446 let mut next_state = MaybeUninit::<StreamState>::uninit();
447 wrap_status(unsafe {
448 ffi::oboe_AudioStream_waitForStateChange(
449 self._raw_stream_mut(),
450 input_state as i32,
451 next_state.as_mut_ptr() as *mut i32,
452 timeout_nanoseconds,
453 )
454 })
455 .map(|_| unsafe { next_state.assume_init() })
456 }
457
458 fn wait_for_available_frames(
459 &mut self,
460 num_frames: i32,
461 timeout_nanoseconds: i64,
462 ) -> Result<i32> {
463 wrap_result(unsafe {
464 ffi::oboe_AudioStream_waitForAvailableFrames(
465 self._raw_stream_mut(),
466 num_frames,
467 timeout_nanoseconds,
468 )
469 })
470 }
471}
472
473impl<T: RawAudioInputStream + RawAudioStream + RawAudioStreamBase> AudioInputStreamSafe for T {
474 fn get_frames_read(&mut self) -> i64 {
475 unsafe {
476 ffi::oboe_AudioStream_getFramesRead(self._raw_stream_mut() as *mut _ as *mut c_void)
477 }
478 }
479}
480
481impl<T: RawAudioInputStream + RawAudioStream + RawAudioStreamBase> AudioInputStream for T {}
482
483impl<T: RawAudioOutputStream + RawAudioStream + RawAudioStreamBase> AudioOutputStreamSafe for T {
484 fn get_frames_written(&mut self) -> i64 {
485 unsafe {
486 ffi::oboe_AudioStream_getFramesWritten(self._raw_stream_mut() as *mut _ as *mut c_void)
487 }
488 }
489}
490
491impl<T: RawAudioOutputStream + RawAudioStream + RawAudioStreamBase> AudioOutputStream for T {
492 fn pause_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status {
493 wrap_status(unsafe {
494 ffi::oboe_AudioStream_pause(
495 self._raw_stream_mut() as *mut _ as *mut c_void,
496 timeout_nanoseconds,
497 )
498 })
499 }
500
501 fn flush_with_timeout(&mut self, timeout_nanoseconds: i64) -> Status {
502 wrap_status(unsafe {
503 ffi::oboe_AudioStream_flush(
504 self._raw_stream_mut() as *mut _ as *mut c_void,
505 timeout_nanoseconds,
506 )
507 })
508 }
509
510 fn request_pause(&mut self) -> Status {
511 wrap_status(unsafe { ffi::oboe_AudioStream_requestPause(self._raw_stream_mut()) })
512 }
513
514 fn request_flush(&mut self) -> Status {
515 wrap_status(unsafe { ffi::oboe_AudioStream_requestFlush(self._raw_stream_mut()) })
516 }
517}
518
519pub(crate) fn audio_stream_fmt<T: AudioStreamSafe>(
520 stream: &T,
521 f: &mut fmt::Formatter<'_>,
522) -> fmt::Result {
523 audio_stream_base_fmt(stream, f)?;
524 "Audio API: ".fmt(f)?;
525 fmt::Debug::fmt(&stream.get_audio_api(), f)?;
526 "\nCurrent state: ".fmt(f)?;
527 fmt::Debug::fmt(&stream.get_state(), f)?;
528 "\nXrun count: ".fmt(f)?;
529 match stream.get_xrun_count() {
530 Ok(count) => count.fmt(f)?,
531 Err(error) => fmt::Debug::fmt(&error, f)?,
532 }
533 '\n'.fmt(f)
534}
535
536pub(crate) struct AudioStreamHandle(ffi::oboe_AudioStreamShared);
537
538impl Clone for AudioStreamHandle {
539 fn clone(&self) -> Self {
540 let mut new = Self::default();
542
543 unsafe { ffi::oboe_AudioStreamShared_clone(&self.0, new.as_mut()) };
544
545 new
546 }
547}
548
549impl Drop for AudioStreamHandle {
550 fn drop(&mut self) {
552 unsafe { ffi::oboe_AudioStreamShared_delete(&mut self.0 as *mut _) };
555 }
556}
557
558impl Default for AudioStreamHandle {
559 fn default() -> Self {
560 Self(unsafe { MaybeUninit::zeroed().assume_init() })
561 }
562}
563
564impl AsRef<ffi::oboe_AudioStreamShared> for AudioStreamHandle {
565 fn as_ref(&self) -> &ffi::oboe_AudioStreamShared {
566 &self.0
567 }
568}
569
570impl AsMut<ffi::oboe_AudioStreamShared> for AudioStreamHandle {
571 fn as_mut(&mut self) -> &mut ffi::oboe_AudioStreamShared {
572 &mut self.0
573 }
574}
575
576impl Deref for AudioStreamHandle {
577 type Target = ffi::oboe_AudioStream;
578
579 fn deref(&self) -> &Self::Target {
580 unsafe { &*ffi::oboe_AudioStreamShared_deref(&self.0 as *const _ as *mut _) }
581 }
582}
583
584impl DerefMut for AudioStreamHandle {
585 fn deref_mut(&mut self) -> &mut Self::Target {
586 unsafe { &mut *ffi::oboe_AudioStreamShared_deref(&mut self.0) }
587 }
588}
589
590#[repr(transparent)]
594pub struct AudioStreamRef<'s, D> {
595 raw: &'s mut ffi::oboe_AudioStream,
596 _phantom: PhantomData<D>,
597}
598
599impl<'s, D> fmt::Debug for AudioStreamRef<'s, D> {
600 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
601 audio_stream_fmt(self, f)
602 }
603}
604
605impl<'s, D> AudioStreamRef<'s, D> {
606 pub(crate) fn wrap_raw<'a: 's>(raw: &'a mut ffi::oboe_AudioStream) -> Self {
607 Self {
608 raw,
609 _phantom: PhantomData,
610 }
611 }
612}
613
614impl<'s, D> RawAudioStreamBase for AudioStreamRef<'s, D> {
615 fn _raw_base(&self) -> &ffi::oboe_AudioStreamBase {
616 unsafe { &*ffi::oboe_AudioStream_getBase(self.raw as *const _ as *mut _) }
617 }
618
619 fn _raw_base_mut(&mut self) -> &mut ffi::oboe_AudioStreamBase {
620 unsafe { &mut *ffi::oboe_AudioStream_getBase(self.raw) }
621 }
622}
623
624impl<'s, D> RawAudioStream for AudioStreamRef<'s, D> {
625 fn _raw_stream(&self) -> &ffi::oboe_AudioStream {
626 self.raw
627 }
628
629 fn _raw_stream_mut(&mut self) -> &mut ffi::oboe_AudioStream {
630 self.raw
631 }
632}
633
634impl<'s> RawAudioInputStream for AudioStreamRef<'s, Input> {}
635
636impl<'s> RawAudioOutputStream for AudioStreamRef<'s, Output> {}
637
638pub struct AudioStreamAsync<D, F> {
642 raw: AudioStreamHandle,
643 _phantom: PhantomData<(D, F)>,
644}
645
646impl<D, F> fmt::Debug for AudioStreamAsync<D, F> {
647 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
648 audio_stream_fmt(self, f)
649 }
650}
651
652impl<D, F> AudioStreamAsync<D, F> {
653 pub(crate) fn wrap_handle(raw: AudioStreamHandle) -> Self {
655 Self {
656 raw,
657 _phantom: PhantomData,
658 }
659 }
660}
661
662impl<D, F> Drop for AudioStreamAsync<D, F> {
663 fn drop(&mut self) {
664 let _ = self.close();
667 }
668}
669
670impl<D, T> RawAudioStreamBase for AudioStreamAsync<D, T> {
671 fn _raw_base(&self) -> &ffi::oboe_AudioStreamBase {
672 unsafe { &*ffi::oboe_AudioStream_getBase(&*self.raw as *const _ as *mut _) }
673 }
674
675 fn _raw_base_mut(&mut self) -> &mut ffi::oboe_AudioStreamBase {
676 unsafe { &mut *ffi::oboe_AudioStream_getBase(&mut *self.raw as *mut _) }
677 }
678}
679
680impl<D, F> RawAudioStream for AudioStreamAsync<D, F> {
681 fn _raw_stream(&self) -> &ffi::oboe_AudioStream {
682 &self.raw
683 }
684
685 fn _raw_stream_mut(&mut self) -> &mut ffi::oboe_AudioStream {
686 &mut self.raw
687 }
688}
689
690impl<F> RawAudioInputStream for AudioStreamAsync<Input, F> {}
691
692impl<F> RawAudioOutputStream for AudioStreamAsync<Output, F> {}
693
694pub struct AudioStreamSync<D, F> {
698 raw: AudioStreamHandle,
699 _phantom: PhantomData<(D, F)>,
700}
701
702impl<D, F> fmt::Debug for AudioStreamSync<D, F> {
703 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
704 audio_stream_fmt(self, f)
705 }
706}
707
708impl<D, F> AudioStreamSync<D, F> {
709 pub(crate) fn wrap_handle(raw: AudioStreamHandle) -> Self {
711 Self {
712 raw,
713 _phantom: PhantomData,
714 }
715 }
716}
717
718impl<D, F> Drop for AudioStreamSync<D, F> {
719 fn drop(&mut self) {
720 let _ = self.close();
723 }
724}
725
726impl<D, T> RawAudioStreamBase for AudioStreamSync<D, T> {
727 fn _raw_base(&self) -> &ffi::oboe_AudioStreamBase {
728 unsafe { &*ffi::oboe_AudioStream_getBase(&*self.raw as *const _ as *mut _) }
729 }
730
731 fn _raw_base_mut(&mut self) -> &mut ffi::oboe_AudioStreamBase {
732 unsafe { &mut *ffi::oboe_AudioStream_getBase(&mut *self.raw as *mut _) }
733 }
734}
735
736impl<D, F> RawAudioStream for AudioStreamSync<D, F> {
737 fn _raw_stream(&self) -> &ffi::oboe_AudioStream {
738 &self.raw
739 }
740
741 fn _raw_stream_mut(&mut self) -> &mut ffi::oboe_AudioStream {
742 &mut self.raw
743 }
744}
745
746impl<F> RawAudioInputStream for AudioStreamSync<Input, F> {}
747
748impl<F> RawAudioOutputStream for AudioStreamSync<Output, F> {}
749
750impl<F: IsFrameType> AudioInputStreamSync for AudioStreamSync<Input, F> {
751 type FrameType = F;
752
753 fn read(
754 &mut self,
755 buffer: &mut [<Self::FrameType as IsFrameType>::Type],
756 timeout_nanoseconds: i64,
757 ) -> Result<i32> {
758 wrap_result(unsafe {
759 ffi::oboe_AudioStream_read(
760 &mut *self.raw,
761 buffer.as_mut_ptr() as *mut c_void,
762 buffer.len() as i32,
763 timeout_nanoseconds,
764 )
765 })
766 }
767}
768
769impl<F: IsFrameType> AudioOutputStreamSync for AudioStreamSync<Output, F> {
770 type FrameType = F;
771
772 fn write(
773 &mut self,
774 buffer: &[<Self::FrameType as IsFrameType>::Type],
775 timeout_nanoseconds: i64,
776 ) -> Result<i32> {
777 wrap_result(unsafe {
778 ffi::oboe_AudioStream_write(
779 &mut *self.raw,
780 buffer.as_ptr() as *const c_void,
781 buffer.len() as i32,
782 timeout_nanoseconds,
783 )
784 })
785 }
786}