|
| 1 | +use std::marker::PhantomData; |
| 2 | +use std::time::{Duration, Instant}; |
| 3 | + |
| 4 | +extern crate oboe; |
| 5 | + |
| 6 | +use super::convert::{stream_instant, to_stream_instant}; |
| 7 | +use crate::{Data, InputCallbackInfo, InputStreamTimestamp, Sample, SampleRate, StreamError}; |
| 8 | + |
| 9 | +pub struct CpalInputCallback<I, C> { |
| 10 | + data_cb: Box<dyn FnMut(&Data, &InputCallbackInfo) + Send + 'static>, |
| 11 | + error_cb: Box<dyn FnMut(StreamError) + Send + 'static>, |
| 12 | + sample_rate: SampleRate, |
| 13 | + created: Instant, |
| 14 | + phantom_channel: PhantomData<C>, |
| 15 | + phantom_input: PhantomData<I>, |
| 16 | +} |
| 17 | + |
| 18 | +impl<I, C> CpalInputCallback<I, C> { |
| 19 | + pub fn new<D, E>(data_cb: D, error_cb: E, sample_rate: SampleRate) -> Self |
| 20 | + where |
| 21 | + D: FnMut(&Data, &InputCallbackInfo) + Send + 'static, |
| 22 | + E: FnMut(StreamError) + Send + 'static, |
| 23 | + { |
| 24 | + Self { |
| 25 | + data_cb: Box::new(data_cb), |
| 26 | + error_cb: Box::new(error_cb), |
| 27 | + sample_rate, |
| 28 | + created: Instant::now(), |
| 29 | + phantom_channel: PhantomData, |
| 30 | + phantom_input: PhantomData, |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + fn make_callback_info( |
| 35 | + &self, |
| 36 | + audio_stream: &mut dyn oboe::AudioInputStream, |
| 37 | + ) -> InputCallbackInfo { |
| 38 | + InputCallbackInfo { |
| 39 | + timestamp: InputStreamTimestamp { |
| 40 | + callback: to_stream_instant(self.created.elapsed()), |
| 41 | + capture: stream_instant(audio_stream), |
| 42 | + }, |
| 43 | + } |
| 44 | + } |
| 45 | +} |
| 46 | + |
| 47 | +impl<T: Sample, C: oboe::IsChannelCount> oboe::AudioInputCallback for CpalInputCallback<T, C> |
| 48 | +where |
| 49 | + (T, C): oboe::IsFrameType, |
| 50 | +{ |
| 51 | + type FrameType = (T, C); |
| 52 | + |
| 53 | + fn on_audio_ready( |
| 54 | + &mut self, |
| 55 | + audio_stream: &mut dyn oboe::AudioInputStream, |
| 56 | + audio_data: &[<<Self as oboe::AudioInputCallback>::FrameType as oboe::IsFrameType>::Type], |
| 57 | + ) -> oboe::DataCallbackResult { |
| 58 | + let cb_info = self.make_callback_info(audio_stream); |
| 59 | + let channel_count = if C::CHANNEL_COUNT == oboe::ChannelCount::Mono { |
| 60 | + 1 |
| 61 | + } else { |
| 62 | + 2 |
| 63 | + }; |
| 64 | + (self.data_cb)( |
| 65 | + &unsafe { |
| 66 | + Data::from_parts( |
| 67 | + audio_data.as_ptr() as *mut _, |
| 68 | + audio_data.len() * channel_count, |
| 69 | + T::FORMAT, |
| 70 | + ) |
| 71 | + }, |
| 72 | + &cb_info, |
| 73 | + ); |
| 74 | + oboe::DataCallbackResult::Continue |
| 75 | + } |
| 76 | + |
| 77 | + fn on_error_before_close( |
| 78 | + &mut self, |
| 79 | + _audio_stream: &mut dyn oboe::AudioInputStream, |
| 80 | + error: oboe::Error, |
| 81 | + ) { |
| 82 | + (self.error_cb)(StreamError::from(error)) |
| 83 | + } |
| 84 | + |
| 85 | + fn on_error_after_close( |
| 86 | + &mut self, |
| 87 | + _audio_stream: &mut dyn oboe::AudioInputStream, |
| 88 | + error: oboe::Error, |
| 89 | + ) { |
| 90 | + (self.error_cb)(StreamError::from(error)) |
| 91 | + } |
| 92 | +} |
0 commit comments