Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Refactor errors for consumption
  • Loading branch information
ferjm committed Dec 28, 2018
1 parent 1f5548f commit 0c8f2d6
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 248 deletions.
12 changes: 5 additions & 7 deletions audio/src/context.rs
Expand Up @@ -142,7 +142,8 @@ impl<B: AudioBackend + 'static> AudioContext<B> {
graph,
options,
);
}).unwrap();
})
.unwrap();
Self {
sender,
state: Cell::new(ProcessingState::Suspended),
Expand Down Expand Up @@ -251,11 +252,7 @@ impl<B: AudioBackend + 'static> AudioContext<B> {

/// Asynchronously decodes the audio file data contained in the given
/// buffer.
pub fn decode_audio_data(
&self,
data: Vec<u8>,
callbacks: AudioDecoderCallbacks<<B::Decoder as AudioDecoder>::Error>,
) {
pub fn decode_audio_data(&self, data: Vec<u8>, callbacks: AudioDecoderCallbacks) {
let mut options = AudioDecoderOptions::default();
options.sample_rate = self.sample_rate;
Builder::new()
Expand All @@ -264,7 +261,8 @@ impl<B: AudioBackend + 'static> AudioContext<B> {
let audio_decoder = B::make_decoder();

audio_decoder.decode(data, callbacks, Some(options));
}).unwrap();
})
.unwrap();
}

pub fn set_eos_callback(&self, callback: Box<Fn(Box<AsRef<[f32]>>) + Send + Sync + 'static>) {
Expand Down
41 changes: 26 additions & 15 deletions audio/src/decoder.rs
@@ -1,16 +1,29 @@
use boxfnonce::SendBoxFnOnce;
use std::fmt::Debug;
use std::sync::Mutex;

pub struct AudioDecoderCallbacks<E> {
#[derive(Debug, PartialEq)]
pub enum AudioDecoderError {
/// Backend specific error.
Backend(String),
/// Could not read the audio buffer content.
BufferReadFailed,
/// The media trying to be decoded has an invalid format.
InvalidMediaFormat,
/// An invalid sample was found while decoding the audio.
InvalidSample,
/// Could not move to a different state.
StateChangeFailed,
}

pub struct AudioDecoderCallbacks {
pub eos: Mutex<Option<SendBoxFnOnce<'static, ()>>>,
pub error: Mutex<Option<SendBoxFnOnce<'static, (E,)>>>,
pub error: Mutex<Option<SendBoxFnOnce<'static, (AudioDecoderError,)>>>,
pub progress: Option<Box<Fn(Box<AsRef<[f32]>>, u32) + Send + Sync + 'static>>,
pub ready: Mutex<Option<SendBoxFnOnce<'static, (u32,)>>>,
}

impl<E> AudioDecoderCallbacks<E> {
pub fn new() -> AudioDecoderCallbacksBuilder<E> {
impl AudioDecoderCallbacks {
pub fn new() -> AudioDecoderCallbacksBuilder {
AudioDecoderCallbacksBuilder {
eos: None,
error: None,
Expand All @@ -27,7 +40,7 @@ impl<E> AudioDecoderCallbacks<E> {
};
}

pub fn error(&self, error: E) {
pub fn error(&self, error: AudioDecoderError) {
let callback = self.error.lock().unwrap().take();
match callback {
None => return,
Expand All @@ -51,22 +64,22 @@ impl<E> AudioDecoderCallbacks<E> {
}
}

pub struct AudioDecoderCallbacksBuilder<E> {
pub struct AudioDecoderCallbacksBuilder {
eos: Option<SendBoxFnOnce<'static, ()>>,
error: Option<SendBoxFnOnce<'static, (E,)>>,
error: Option<SendBoxFnOnce<'static, (AudioDecoderError,)>>,
progress: Option<Box<Fn(Box<AsRef<[f32]>>, u32) + Send + Sync + 'static>>,
ready: Option<SendBoxFnOnce<'static, (u32,)>>,
}

impl<E> AudioDecoderCallbacksBuilder<E> {
impl AudioDecoderCallbacksBuilder {
pub fn eos<F: FnOnce() + Send + 'static>(self, eos: F) -> Self {
Self {
eos: Some(SendBoxFnOnce::new(eos)),
..self
}
}

pub fn error<F: FnOnce(E) + Send + 'static>(self, error: F) -> Self {
pub fn error<F: FnOnce(AudioDecoderError) + Send + 'static>(self, error: F) -> Self {
Self {
error: Some(SendBoxFnOnce::new(error)),
..self
Expand All @@ -90,7 +103,7 @@ impl<E> AudioDecoderCallbacksBuilder<E> {
}
}

pub fn build(self) -> AudioDecoderCallbacks<E> {
pub fn build(self) -> AudioDecoderCallbacks {
AudioDecoderCallbacks {
eos: Mutex::new(self.eos),
error: Mutex::new(self.error),
Expand All @@ -113,18 +126,16 @@ impl Default for AudioDecoderOptions {
}

pub trait AudioDecoder {
type Error: Debug;
fn decode(
&self,
data: Vec<u8>,
callbacks: AudioDecoderCallbacks<Self::Error>,
callbacks: AudioDecoderCallbacks,
options: Option<AudioDecoderOptions>,
);
}

pub struct DummyAudioDecoder;

impl AudioDecoder for DummyAudioDecoder {
type Error = ();
fn decode(&self, _: Vec<u8>, _: AudioDecoderCallbacks<()>, _: Option<AudioDecoderOptions>) {}
fn decode(&self, _: Vec<u8>, _: AudioDecoderCallbacks, _: Option<AudioDecoderOptions>) {}
}
2 changes: 1 addition & 1 deletion audio/src/lib.rs
Expand Up @@ -39,5 +39,5 @@ pub trait AudioBackend {
type Decoder: decoder::AudioDecoder;
type Sink: sink::AudioSink;
fn make_decoder() -> Self::Decoder;
fn make_sink() -> Result<Self::Sink, <Self::Sink as sink::AudioSink>::Error>;
fn make_sink() -> Result<Self::Sink, sink::AudioSinkError>;
}
15 changes: 5 additions & 10 deletions audio/src/offline_sink.rs
@@ -1,6 +1,6 @@
use block::{Chunk, FRAMES_PER_BLOCK_USIZE};
use render_thread::AudioRenderThreadMsg;
use sink::AudioSink;
use sink::{AudioSink, AudioSinkError};
use std::cell::{Cell, RefCell};
use std::sync::mpsc::Sender;

Expand Down Expand Up @@ -34,22 +34,17 @@ impl OfflineAudioSink {
}
}

// replace with ! when it stabilizes
#[derive(Debug)]
pub enum OfflineError {}

impl AudioSink for OfflineAudioSink {
type Error = OfflineError;
fn init(&self, _: f32, _: Sender<AudioRenderThreadMsg>) -> Result<(), OfflineError> {
fn init(&self, _: f32, _: Sender<AudioRenderThreadMsg>) -> Result<(), AudioSinkError> {
Ok(())
}

fn play(&self) -> Result<(), OfflineError> {
fn play(&self) -> Result<(), AudioSinkError> {
self.has_enough_data.set(false);
Ok(())
}

fn stop(&self) -> Result<(), OfflineError> {
fn stop(&self) -> Result<(), AudioSinkError> {
self.has_enough_data.set(true);
Ok(())
}
Expand All @@ -59,7 +54,7 @@ impl AudioSink for OfflineAudioSink {
|| (self.rendered_blocks.get() * FRAMES_PER_BLOCK_USIZE >= self.length)
}

fn push_data(&self, mut chunk: Chunk) -> Result<(), OfflineError> {
fn push_data(&self, mut chunk: Chunk) -> Result<(), AudioSinkError> {
let offset = self.rendered_blocks.get() * FRAMES_PER_BLOCK_USIZE;
let (last, copy_len) = if self.length - offset <= FRAMES_PER_BLOCK_USIZE {
(true, self.length - offset)
Expand Down
21 changes: 10 additions & 11 deletions audio/src/render_thread.rs
Expand Up @@ -12,7 +12,7 @@ use node::{BlockInfo, ChannelInfo};
use offline_sink::OfflineAudioSink;
use oscillator_node::OscillatorNode;
use panner_node::PannerNode;
use sink::{AudioSink, DummyAudioSink};
use sink::{AudioSink, AudioSinkError, DummyAudioSink};
use std::sync::mpsc::{Receiver, Sender};

pub enum AudioRenderThreadMsg {
Expand Down Expand Up @@ -41,27 +41,25 @@ pub enum Sink<S: AudioSink> {
}

impl<S: AudioSink> AudioSink for Sink<S> {
type Error = S::Error;

fn init(
&self,
sample_rate: f32,
sender: Sender<AudioRenderThreadMsg>,
) -> Result<(), Self::Error> {
) -> Result<(), AudioSinkError> {
match *self {
Sink::RealTime(ref sink) => sink.init(sample_rate, sender),
Sink::Offline(ref sink) => Ok(sink.init(sample_rate, sender).unwrap()),
}
}

fn play(&self) -> Result<(), Self::Error> {
fn play(&self) -> Result<(), AudioSinkError> {
match *self {
Sink::RealTime(ref sink) => sink.play(),
Sink::Offline(ref sink) => Ok(sink.play().unwrap()),
}
}

fn stop(&self) -> Result<(), Self::Error> {
fn stop(&self) -> Result<(), AudioSinkError> {
match *self {
Sink::RealTime(ref sink) => sink.stop(),
Sink::Offline(ref sink) => Ok(sink.stop().unwrap()),
Expand All @@ -75,7 +73,7 @@ impl<S: AudioSink> AudioSink for Sink<S> {
}
}

fn push_data(&self, chunk: Chunk) -> Result<(), Self::Error> {
fn push_data(&self, chunk: Chunk) -> Result<(), AudioSinkError> {
match *self {
Sink::RealTime(ref sink) => sink.push_data(chunk),
Sink::Offline(ref sink) => Ok(sink.push_data(chunk).unwrap()),
Expand Down Expand Up @@ -109,9 +107,9 @@ impl<S: AudioSink + 'static> AudioRenderThread<S> {
sample_rate: f32,
graph: AudioGraph,
options: AudioContextOptions,
) -> Result<Self, (AudioGraph, S::Error)>
) -> Result<Self, (AudioGraph, AudioSinkError)>
where
F: FnOnce() -> Result<S, S::Error>,
F: FnOnce() -> Result<S, AudioSinkError>,
{
let sink = match options {
AudioContextOptions::RealTimeAudioContext(_) => {
Expand Down Expand Up @@ -152,7 +150,7 @@ impl<S: AudioSink + 'static> AudioRenderThread<S> {
graph: AudioGraph,
options: AudioContextOptions,
) where
F: FnOnce() -> Result<S, S::Error>,
F: FnOnce() -> Result<S, AudioSinkError>,
{
let thread = Self::prepare_thread(make_sink, sender.clone(), sample_rate, graph, options);
match thread {
Expand All @@ -169,7 +167,8 @@ impl<S: AudioSink + 'static> AudioRenderThread<S> {
sample_rate,
graph,
options,
).map_err(|_| ())
)
.map_err(|_| ())
.unwrap();
thread.event_loop(event_queue)
}
Expand Down
29 changes: 18 additions & 11 deletions audio/src/sink.rs
@@ -1,39 +1,46 @@
use block::Chunk;
use render_thread::AudioRenderThreadMsg;
use std::fmt::Debug;
use std::sync::mpsc::Sender;

#[derive(Debug, PartialEq)]
pub enum AudioSinkError {
/// Backend specific error.
Backend(String),
/// Could not push buffer into the audio sink.
BufferPushFailed,
/// Could not move to a different state.
StateChangeFailed,
}

pub trait AudioSink {
type Error: Debug;
fn init(
&self,
sample_rate: f32,
render_thread_channel: Sender<AudioRenderThreadMsg>,
) -> Result<(), Self::Error>;
fn play(&self) -> Result<(), Self::Error>;
fn stop(&self) -> Result<(), Self::Error>;
) -> Result<(), AudioSinkError>;
fn play(&self) -> Result<(), AudioSinkError>;
fn stop(&self) -> Result<(), AudioSinkError>;
fn has_enough_data(&self) -> bool;
fn push_data(&self, chunk: Chunk) -> Result<(), Self::Error>;
fn push_data(&self, chunk: Chunk) -> Result<(), AudioSinkError>;
fn set_eos_callback(&self, callback: Box<Fn(Box<AsRef<[f32]>>) + Send + Sync + 'static>);
}

pub struct DummyAudioSink;

impl AudioSink for DummyAudioSink {
type Error = ();
fn init(&self, _: f32, _: Sender<AudioRenderThreadMsg>) -> Result<(), ()> {
fn init(&self, _: f32, _: Sender<AudioRenderThreadMsg>) -> Result<(), AudioSinkError> {
Ok(())
}
fn play(&self) -> Result<(), ()> {
fn play(&self) -> Result<(), AudioSinkError> {
Ok(())
}
fn stop(&self) -> Result<(), ()> {
fn stop(&self) -> Result<(), AudioSinkError> {
Ok(())
}
fn has_enough_data(&self) -> bool {
true
}
fn push_data(&self, _: Chunk) -> Result<(), ()> {
fn push_data(&self, _: Chunk) -> Result<(), AudioSinkError> {
Ok(())
}
fn set_eos_callback(&self, _: Box<Fn(Box<AsRef<[f32]>>) + Send + Sync + 'static>) {}
Expand Down

0 comments on commit 0c8f2d6

Please sign in to comment.