#[cfg(feature = "symphonia")]
mod error;
mod playback_position;
pub mod static_sound;
#[cfg(not(target_arch = "wasm32"))]
pub mod streaming;
#[cfg(feature = "symphonia")]
mod symphonia;
mod transport;
use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
#[cfg(feature = "symphonia")]
pub use error::*;
pub use playback_position::*;
use crate::{frame::Frame, info::Info};
pub trait SoundData {
type Error;
type Handle;
#[allow(clippy::type_complexity)]
fn into_sound(self) -> Result<(Box<dyn Sound>, Self::Handle), Self::Error>;
}
#[allow(unused_variables)]
pub trait Sound: Send {
fn on_start_processing(&mut self) {}
fn process(&mut self, out: &mut [Frame], dt: f64, info: &Info);
fn process_one(&mut self, dt: f64, info: &Info) -> Frame {
let mut out = [Frame::ZERO];
self.process(&mut out, dt, info);
out[0]
}
#[must_use]
fn finished(&self) -> bool;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum PlaybackState {
Playing,
Pausing,
Paused,
WaitingToResume,
Resuming,
Stopping,
Stopped,
}
impl PlaybackState {
pub fn is_advancing(self) -> bool {
match self {
PlaybackState::Playing => true,
PlaybackState::Pausing => true,
PlaybackState::Paused => false,
PlaybackState::WaitingToResume => false,
PlaybackState::Resuming => true,
PlaybackState::Stopping => true,
PlaybackState::Stopped => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Region {
pub start: PlaybackPosition,
pub end: EndPosition,
}
impl<T: Into<PlaybackPosition>> From<RangeFrom<T>> for Region {
fn from(range: RangeFrom<T>) -> Self {
Self {
start: range.start.into(),
end: EndPosition::EndOfAudio,
}
}
}
impl<T: Into<PlaybackPosition>> From<Range<T>> for Region {
fn from(range: Range<T>) -> Self {
Self {
start: range.start.into(),
end: EndPosition::Custom(range.end.into()),
}
}
}
impl<T: Into<PlaybackPosition>> From<RangeTo<T>> for Region {
fn from(range: RangeTo<T>) -> Self {
Self {
start: PlaybackPosition::Samples(0),
end: EndPosition::Custom(range.end.into()),
}
}
}
impl From<RangeFull> for Region {
fn from(_: RangeFull) -> Self {
Self {
start: PlaybackPosition::Samples(0),
end: EndPosition::EndOfAudio,
}
}
}
pub trait IntoOptionalRegion {
#[must_use]
fn into_optional_region(self) -> Option<Region>;
}
impl<T: Into<Region>> IntoOptionalRegion for T {
fn into_optional_region(self) -> Option<Region> {
Some(self.into())
}
}
impl IntoOptionalRegion for Option<Region> {
fn into_optional_region(self) -> Option<Region> {
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum EndPosition {
#[default]
EndOfAudio,
Custom(PlaybackPosition),
}