Skip to content

Commit

Permalink
Use Result<T, Error> instead of panicking.
Browse files Browse the repository at this point in the history
Affects Sdl2Input, Sdl2Output, and WavDecoder constructors.
  • Loading branch information
thoren-d committed Oct 14, 2020
1 parent 2b4df5d commit 2b82df9
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 50 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ programming, but should be flexible enough for other applications as well.
fn main() -> Result<(), Box<dyn std::error::Error>> {
use std::time::Duration;
use timbre::prelude::*;

// SDL setup.
let sdl = sdl2::init()?;
let audio = sdl.audio()?;

// Inputs
let mut microphone = timbre::drivers::Sdl2Input::new(&audio);
let mut microphone = timbre::drivers::Sdl2Input::new(&audio)?;
microphone.resume();
let music = timbre::decoders::WavDecoder::from_file("./music.wav");
let music = timbre::decoders::WavDecoder::from_file("./assets/music-stereo-f32.wav")?;

// Apply effects
let microphone = timbre::effects::Echo::new(microphone.source(),
Expand All @@ -39,12 +40,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
mixer.add_source(music.into_shared());

// Output
let mut speaker = timbre::drivers::Sdl2Output::new(&audio);
let mut speaker = timbre::drivers::Sdl2Output::new(&audio)?;
speaker.set_source(mixer.into_shared());
speaker.resume();

std::thread::sleep(Duration::from_secs_f32(10.0));

Ok(())
}
```
Expand Down
6 changes: 3 additions & 3 deletions examples/effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ fn main() -> Result<(), Box<dyn Error>> {
let sdl = sdl2::init()?;
let audio = sdl.audio()?;

let track1 = WavDecoder::from_file("./assets/music-stereo-f32.wav");
let track2 = WavDecoder::new(std::fs::File::open("./assets/music-stereo-i16.wav")?);
let track1 = WavDecoder::from_file("./assets/music-stereo-f32.wav")?;
let track2 = WavDecoder::new(std::fs::File::open("./assets/music-stereo-i16.wav")?)?;

let low_pass = LowPass::new(track1.into_shared(), 300.0);
let high_pass = HighPass::new(track2.into_shared(), 4000.0);
Expand All @@ -26,7 +26,7 @@ fn main() -> Result<(), Box<dyn Error>> {

let echo = Echo::new(mixer.into_shared(), Duration::from_secs_f32(0.5), 0.7);

let mut output = Sdl2Output::new(&audio);
let mut output = Sdl2Output::new(&audio)?;
output.set_source(echo.into_shared());
output.resume();

Expand Down
4 changes: 2 additions & 2 deletions examples/listen_to_mic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fn main() -> Result<(), Box<dyn Error>> {
let sdl = sdl2::init()?;
let audio = sdl.audio()?;

let mut mic = Sdl2Input::new(&audio);
let mut output = Sdl2Output::new(&audio);
let mut mic = Sdl2Input::new(&audio)?;
let mut output = Sdl2Output::new(&audio)?;

mic.resume();
output.set_source(mic.source());
Expand Down
35 changes: 19 additions & 16 deletions src/decoders/wav_decoder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{core::AudioBuffer, AudioFormat, AudioSource, ReadResult};
use crate::{core::AudioBuffer, AudioFormat, AudioSource, Error, ReadResult};

use sdl2::{
audio::{AudioFormatNum, AudioSpecWAV},
Expand All @@ -21,65 +21,68 @@ pub struct WavDecoder {
impl WavDecoder {
/// Construct a WavDecoder that reads from a [`std::io::Read`](std::io::Read).
///
/// # Panics
/// # Errors
///
/// If the WAV file in `read` in corrupted or empty.
/// If the WAV file in `read` in corrupted or empty, will return the underlying SDL error.
///
/// # Examples
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use timbre::decoders::WavDecoder;
///
/// let decoder = WavDecoder::new(std::fs::File::open("./assets/music-mono-f32.wav")?);
/// let decoder = WavDecoder::new(std::fs::File::open("./assets/music-mono-f32.wav")?)?;
/// # Ok(())
/// # }
/// ```
#[instrument(name = "WavDecoder::new", skip(read))]
pub fn new<R: Read>(mut read: R) -> Self {
pub fn new<R: Read>(mut read: R) -> Result<Self, Error> {
let mut read_buffer = Vec::new();
let mut rwops = RWops::from_read(&mut read, &mut read_buffer).unwrap();
let wav_data = AudioSpecWAV::load_wav_rw(&mut rwops).unwrap();
let mut rwops = RWops::from_read(&mut read, &mut read_buffer).map_err(Error::from_sdl)?;
let wav_data = AudioSpecWAV::load_wav_rw(&mut rwops).map_err(Error::from_sdl)?;
let data = convert_samples(wav_data.buffer(), wav_data.format);

let format = AudioFormat {
channels: wav_data.channels,
sample_rate: wav_data.freq as u32,
};

WavDecoder {
Ok(WavDecoder {
data,
format,
position: 0,
}
})
}

/// Construct a WavDecoder the file given by `path`.
///
/// # Panics
/// # Errors
///
/// If the file cannot be opened or is not a valid WAV file.
/// If the file cannot be opened or is not a valid WAV file, will return the underlying SDL error.
///
/// # Examples
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use timbre::decoders::WavDecoder;
///
/// let decoder = WavDecoder::from_file("./assets/music-stereo-i16.wav");
/// let decoder = WavDecoder::from_file("./assets/music-stereo-i16.wav")?;
/// # Ok(())
/// }
/// ```
#[instrument(name = "WavDecoder::from_file")]
pub fn from_file(path: &str) -> Self {
let wav_data = AudioSpecWAV::load_wav(path).unwrap();
pub fn from_file(path: &str) -> Result<Self, Error> {
let wav_data = AudioSpecWAV::load_wav(path).map_err(Error::from_sdl)?;
let data = convert_samples(wav_data.buffer(), wav_data.format);

let format = AudioFormat {
channels: wav_data.channels,
sample_rate: wav_data.freq as u32,
};

WavDecoder {
Ok(WavDecoder {
data,
format,
position: 0,
}
})
}
}

Expand Down
25 changes: 14 additions & 11 deletions src/drivers/sdl2_input.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
core::{AudioBuffer, SharedAudioSource},
AudioFormat, AudioSource, ReadResult,
AudioFormat, AudioSource, Error, ReadResult,
};

use std::collections::VecDeque;
Expand All @@ -19,8 +19,8 @@ use tracing::{info, instrument};
/// let sdl = sdl2::init()?;
/// let audio = sdl.audio()?;
///
/// let mut microphone = Sdl2Input::new(&audio);
/// let mut speaker = Sdl2Output::new(&audio);
/// let mut microphone = Sdl2Input::new(&audio)?;
/// let mut speaker = Sdl2Output::new(&audio)?;
/// microphone.resume();
/// speaker.set_source(microphone.source());
/// speaker.resume();
Expand Down Expand Up @@ -59,7 +59,7 @@ impl Sdl2Input {
///
/// * `subsystem` -- An SDL [`AudioSubystem`](sdl2::AudioSubsystem) used to create a capture device.
///
/// # Panics
/// # Errors
///
/// If SDL fails to open the device.
///
Expand All @@ -71,11 +71,11 @@ impl Sdl2Input {
/// let sdl = sdl2::init()?;
/// let audio = sdl.audio()?;
///
/// let microphone = Sdl2Input::new(&audio);
/// let microphone = Sdl2Input::new(&audio)?;
/// # Ok(())
/// # }
/// ```
pub fn new(subsystem: &sdl2::AudioSubsystem) -> Self {
pub fn new(subsystem: &sdl2::AudioSubsystem) -> Result<Self, Error> {
Sdl2Input::with_format(
subsystem,
AudioFormat {
Expand All @@ -94,7 +94,7 @@ impl Sdl2Input {
/// * `subsystem` -- An SDL [`AudioSubystem`](sdl2::AudioSubsystem) used to create a capture device.
/// * `format` -- The format to request for this input device.
///
/// # Panics
/// # Errors
///
/// If SDL fails to open the device.
///
Expand All @@ -107,11 +107,14 @@ impl Sdl2Input {
/// let audio = sdl.audio()?;
///
/// let format = AudioFormat { channels: 2, sample_rate: 44100 };
/// let microphone = Sdl2Input::with_format(&audio, format);
/// let microphone = Sdl2Input::with_format(&audio, format)?;
/// # Ok(())
/// # }
/// ```
pub fn with_format(subsystem: &sdl2::AudioSubsystem, format: AudioFormat) -> Self {
pub fn with_format(
subsystem: &sdl2::AudioSubsystem,
format: AudioFormat,
) -> Result<Self, Error> {
let desired_spec = AudioSpecDesired {
freq: Some(format.sample_rate as i32),
channels: Some(format.channels),
Expand All @@ -129,9 +132,9 @@ impl Sdl2Input {
format: spec.into(),
}
})
.unwrap();
.map_err(Error::from_sdl)?;

Sdl2Input { device, buffer }
Ok(Sdl2Input { device, buffer })
}

/// Return the device's chosen format.
Expand Down
25 changes: 14 additions & 11 deletions src/drivers/sdl2_output.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
core::{AudioBuffer, SharedAudioSource},
AudioFormat, StreamState,
AudioFormat, Error, StreamState,
};

use sdl2::audio::{AudioCallback, AudioFormatNum, AudioSpecDesired};
Expand Down Expand Up @@ -47,8 +47,8 @@ impl AudioCallback for Callback {
/// let sdl = sdl2::init()?;
/// let audio = sdl.audio()?;
///
/// let mut microphone = Sdl2Input::new(&audio);
/// let mut speaker = Sdl2Output::new(&audio);
/// let mut microphone = Sdl2Input::new(&audio)?;
/// let mut speaker = Sdl2Output::new(&audio)?;
/// microphone.resume();
/// speaker.set_source(microphone.source());
/// speaker.resume();
Expand All @@ -68,7 +68,7 @@ impl Sdl2Output {
///
/// * `subsystem` -- An SDL [`AudioSubystem`](sdl2::AudioSubsystem) used to create an output device.
///
/// # Panics
/// # Errors
///
/// If SDL fails to open the device.
///
Expand All @@ -80,11 +80,11 @@ impl Sdl2Output {
/// let sdl = sdl2::init()?;
/// let audio = sdl.audio()?;
///
/// let speaker = Sdl2Output::new(&audio);
/// let speaker = Sdl2Output::new(&audio)?;
/// # Ok(())
/// # }
/// ```
pub fn new(subsystem: &sdl2::AudioSubsystem) -> Sdl2Output {
pub fn new(subsystem: &sdl2::AudioSubsystem) -> Result<Self, Error> {
Sdl2Output::with_format(
subsystem,
AudioFormat {
Expand All @@ -103,7 +103,7 @@ impl Sdl2Output {
/// * `subsystem` -- An SDL [`AudioSubystem`](sdl2::AudioSubsystem) used to create an output device.
/// * `format` -- The format to request for this output device.
///
/// # Panics
/// # Errors
///
/// If SDL fails to open the device.
///
Expand All @@ -115,11 +115,14 @@ impl Sdl2Output {
/// let sdl = sdl2::init()?;
/// let audio = sdl.audio()?;
///
/// let speaker = Sdl2Output::new(&audio);
/// let speaker = Sdl2Output::new(&audio)?;
/// # Ok(())
/// # }
/// ```
pub fn with_format(subsystem: &sdl2::AudioSubsystem, format: AudioFormat) -> Sdl2Output {
pub fn with_format(
subsystem: &sdl2::AudioSubsystem,
format: AudioFormat,
) -> Result<Self, Error> {
let desired_spec = AudioSpecDesired {
freq: Some(format.sample_rate as i32),
channels: Some(format.channels),
Expand All @@ -135,9 +138,9 @@ impl Sdl2Output {
source: None,
}
})
.unwrap();
.map_err(Error::from_sdl)?;

Sdl2Output { device }
Ok(Sdl2Output { device })
}

/// Set the source of audio to output.
Expand Down
28 changes: 28 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// Unified error type.
#[derive(Debug)]
pub enum Error {
/// Wraps a [`std::io::Error`](std::io::Error), such as file not found, etc.
IoError(std::io::Error),
/// Wraps an error from SDL2.
SdlError(String),
}

impl Error {
pub(crate) fn from_sdl(err: String) -> Error {
Error::SdlError(err)
}
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}", self))
}
}

impl std::error::Error for Error {}

impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Self {
Error::IoError(error)
}
}
9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
//! # std::env::set_var("SDL_AUDIODRIVER", "dummy");
//! use std::time::Duration;
//! use timbre::prelude::*;
//!
//! // SDL setup.
//! let sdl = sdl2::init()?;
//! let audio = sdl.audio()?;
//!
//! // Inputs
//! let mut microphone = timbre::drivers::Sdl2Input::new(&audio);
//! let mut microphone = timbre::drivers::Sdl2Input::new(&audio)?;
//! microphone.resume();
//! let music = timbre::decoders::WavDecoder::from_file("./assets/music-stereo-f32.wav");
//! let music = timbre::decoders::WavDecoder::from_file("./assets/music-stereo-f32.wav")?;
//!
//! // Apply effects
//! let microphone = timbre::effects::Echo::new(microphone.source(),
Expand All @@ -32,7 +33,7 @@
//! mixer.add_source(music.into_shared());
//!
//! // Output
//! let mut speaker = timbre::drivers::Sdl2Output::new(&audio);
//! let mut speaker = timbre::drivers::Sdl2Output::new(&audio)?;
//! speaker.set_source(mixer.into_shared());
//! speaker.resume();
//!
Expand All @@ -41,6 +42,8 @@
mod core;
pub use crate::core::*;
mod error;
pub use crate::error::*;

pub mod decoders;
pub mod drivers;
Expand Down

0 comments on commit 2b82df9

Please sign in to comment.