diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..fe06b3f --- /dev/null +++ b/src/error.rs @@ -0,0 +1,218 @@ +use failure::Fail; + +/// The requested host, although supported on this platform, is unavailable. +#[derive(Clone, Debug, Fail)] +#[fail(display = "the requested host is unavailable")] +pub struct HostUnavailable; + +/// Some error has occurred that is specific to the backend from which it was produced. +/// +/// This error is often used as a catch-all in cases where: +/// +/// - It is unclear exactly what error might be produced by the backend API. +/// - It does not make sense to add a variant to the enclosing error type. +/// - No error was expected to occur at all, but we return an error to avoid the possibility of a +/// `panic!` caused by some unforseen or unknown reason. +/// +/// **Note:** If you notice a `BackendSpecificError` that you believe could be better handled in a +/// cross-platform manner, please create an issue or submit a pull request with a patch that adds +/// the necessary error variant to the appropriate error enum. +#[derive(Clone, Debug, Fail)] +#[fail(display = "A backend-specific error has occurred: {}", description)] +pub struct BackendSpecificError { + pub description: String, +} + +/// An error that might occur while attempting to enumerate the available devices on a system. +#[derive(Debug, Fail)] +pub enum DevicesError { + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// An error that may occur while attempting to retrieve a device name. +#[derive(Debug, Fail)] +pub enum DeviceNameError { + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// Error that can happen when enumerating the list of supported formats. +#[derive(Debug, Fail)] +pub enum SupportedFormatsError { + /// The device no longer exists. This can happen if the device is disconnected while the + /// program is running. + #[fail( + display = "The requested device is no longer available. For example, it has been unplugged." + )] + DeviceNotAvailable, + /// We called something the C-Layer did not understand + #[fail( + display = "Invalid argument passed to the backend. For example, this happens when trying to read capture capabilities when the device does not support it." + )] + InvalidArgument, + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// May occur when attempting to request the default input or output stream format from a `Device`. +#[derive(Debug, Fail)] +pub enum DefaultFormatError { + /// The device no longer exists. This can happen if the device is disconnected while the + /// program is running. + #[fail( + display = "The requested device is no longer available. For example, it has been unplugged." + )] + DeviceNotAvailable, + /// Returned if e.g. the default input format was requested on an output-only audio device. + #[fail(display = "The requested stream type is not supported by the device.")] + StreamTypeNotSupported, + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// Error that can happen when creating a `Stream`. +#[derive(Debug, Fail)] +pub enum BuildStreamError { + /// The device no longer exists. This can happen if the device is disconnected while the + /// program is running. + #[fail( + display = "The requested device is no longer available. For example, it has been unplugged." + )] + DeviceNotAvailable, + /// The required format is not supported. + #[fail(display = "The requested stream format is not supported by the device.")] + FormatNotSupported, + /// We called something the C-Layer did not understand + /// + /// On ALSA device functions called with a feature they do not support will yield this. E.g. + /// Trying to use capture capabilities on an output only format yields this. + #[fail(display = "The requested device does not support this capability (invalid argument)")] + InvalidArgument, + /// Occurs if adding a new Stream ID would cause an integer overflow. + #[fail(display = "Adding a new stream ID would cause an overflow")] + StreamIdOverflow, + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// Errors that might occur when calling `play_stream`. +/// +/// As of writing this, only macOS may immediately return an error while calling this method. This +/// is because both the alsa and wasapi backends only enqueue these commands and do not process +/// them immediately. +#[derive(Debug, Fail)] +pub enum PlayStreamError { + /// The device associated with the stream is no longer available. + #[fail(display = "the device associated with the stream is no longer available")] + DeviceNotAvailable, + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// Errors that might occur when calling `pause_stream`. +/// +/// As of writing this, only macOS may immediately return an error while calling this method. This +/// is because both the alsa and wasapi backends only enqueue these commands and do not process +/// them immediately. +#[derive(Debug, Fail)] +pub enum PauseStreamError { + /// The device associated with the stream is no longer available. + #[fail(display = "the device associated with the stream is no longer available")] + DeviceNotAvailable, + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +/// Errors that might occur while a stream is running. +#[derive(Debug, Fail)] +pub enum StreamError { + /// The device no longer exists. This can happen if the device is disconnected while the + /// program is running. + #[fail( + display = "The requested device is no longer available. For example, it has been unplugged." + )] + DeviceNotAvailable, + /// See the `BackendSpecificError` docs for more information about this error variant. + #[fail(display = "{}", err)] + BackendSpecific { + #[fail(cause)] + err: BackendSpecificError, + }, +} + +impl From for DevicesError { + fn from(err: BackendSpecificError) -> Self { + DevicesError::BackendSpecific { err } + } +} + +impl From for DeviceNameError { + fn from(err: BackendSpecificError) -> Self { + DeviceNameError::BackendSpecific { err } + } +} + +impl From for SupportedFormatsError { + fn from(err: BackendSpecificError) -> Self { + SupportedFormatsError::BackendSpecific { err } + } +} + +impl From for DefaultFormatError { + fn from(err: BackendSpecificError) -> Self { + DefaultFormatError::BackendSpecific { err } + } +} + +impl From for BuildStreamError { + fn from(err: BackendSpecificError) -> Self { + BuildStreamError::BackendSpecific { err } + } +} + +impl From for PlayStreamError { + fn from(err: BackendSpecificError) -> Self { + PlayStreamError::BackendSpecific { err } + } +} + +impl From for PauseStreamError { + fn from(err: BackendSpecificError) -> Self { + PauseStreamError::BackendSpecific { err } + } +} + +impl From for StreamError { + fn from(err: BackendSpecificError) -> Self { + StreamError::BackendSpecific { err } + } +} diff --git a/src/lib.rs b/src/lib.rs index 0089ec5..783fd6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,15 +149,16 @@ extern crate lazy_static; #[macro_use] extern crate stdweb; +pub use error::*; pub use platform::{ ALL_HOSTS, Device, Devices, EventLoop, Host, HostId, SupportedInputFormats, SupportedOutputFormats, StreamId, available_hosts, default_host, host_from_id, }; pub use samples_formats::{Sample, SampleFormat}; -use failure::Fail; use std::ops::{Deref, DerefMut}; +mod error; mod host; pub mod platform; mod samples_formats; @@ -262,165 +263,6 @@ pub enum UnknownTypeOutputBuffer<'a> { F32(OutputBuffer<'a, f32>), } -/// The requested host, although supported on this platform, is unavailable. -#[derive(Clone, Debug, Fail)] -#[fail(display = "the requested host is unavailable")] -pub struct HostUnavailable; - -/// Some error has occurred that is specific to the backend from which it was produced. -/// -/// This error is often used as a catch-all in cases where: -/// -/// - It is unclear exactly what error might be produced by the backend API. -/// - It does not make sense to add a variant to the enclosing error type. -/// - No error was expected to occur at all, but we return an error to avoid the possibility of a -/// `panic!` caused by some unforseen or unknown reason. -/// -/// **Note:** If you notice a `BackendSpecificError` that you believe could be better handled in a -/// cross-platform manner, please create an issue or submit a pull request with a patch that adds -/// the necessary error variant to the appropriate error enum. -#[derive(Clone, Debug, Fail)] -#[fail(display = "A backend-specific error has occurred: {}", description)] -pub struct BackendSpecificError { - pub description: String -} - -/// An error that might occur while attempting to enumerate the available devices on a system. -#[derive(Debug, Fail)] -pub enum DevicesError { - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// An error that may occur while attempting to retrieve a device name. -#[derive(Debug, Fail)] -pub enum DeviceNameError { - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// Error that can happen when enumerating the list of supported formats. -#[derive(Debug, Fail)] -pub enum SupportedFormatsError { - /// The device no longer exists. This can happen if the device is disconnected while the - /// program is running. - #[fail(display = "The requested device is no longer available. For example, it has been unplugged.")] - DeviceNotAvailable, - /// We called something the C-Layer did not understand - #[fail(display = "Invalid argument passed to the backend. For example, this happens when trying to read capture capabilities when the device does not support it.")] - InvalidArgument, - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// May occur when attempting to request the default input or output stream format from a `Device`. -#[derive(Debug, Fail)] -pub enum DefaultFormatError { - /// The device no longer exists. This can happen if the device is disconnected while the - /// program is running. - #[fail(display = "The requested device is no longer available. For example, it has been unplugged.")] - DeviceNotAvailable, - /// Returned if e.g. the default input format was requested on an output-only audio device. - #[fail(display = "The requested stream type is not supported by the device.")] - StreamTypeNotSupported, - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// Error that can happen when creating a `Stream`. -#[derive(Debug, Fail)] -pub enum BuildStreamError { - /// The device no longer exists. This can happen if the device is disconnected while the - /// program is running. - #[fail(display = "The requested device is no longer available. For example, it has been unplugged.")] - DeviceNotAvailable, - /// The required format is not supported. - #[fail(display = "The requested stream format is not supported by the device.")] - FormatNotSupported, - /// We called something the C-Layer did not understand - /// - /// On ALSA device functions called with a feature they do not support will yield this. E.g. - /// Trying to use capture capabilities on an output only format yields this. - #[fail(display = "The requested device does not support this capability (invalid argument)")] - InvalidArgument, - /// Occurs if adding a new Stream ID would cause an integer overflow. - #[fail(display = "Adding a new stream ID would cause an overflow")] - StreamIdOverflow, - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// Errors that might occur when calling `play_stream`. -/// -/// As of writing this, only macOS may immediately return an error while calling this method. This -/// is because both the alsa and wasapi backends only enqueue these commands and do not process -/// them immediately. -#[derive(Debug, Fail)] -pub enum PlayStreamError { - /// The device associated with the stream is no longer available. - #[fail(display = "the device associated with the stream is no longer available")] - DeviceNotAvailable, - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// Errors that might occur when calling `pause_stream`. -/// -/// As of writing this, only macOS may immediately return an error while calling this method. This -/// is because both the alsa and wasapi backends only enqueue these commands and do not process -/// them immediately. -#[derive(Debug, Fail)] -pub enum PauseStreamError { - /// The device associated with the stream is no longer available. - #[fail(display = "the device associated with the stream is no longer available")] - DeviceNotAvailable, - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - -/// Errors that might occur while a stream is running. -#[derive(Debug, Fail)] -pub enum StreamError { - /// The device no longer exists. This can happen if the device is disconnected while the - /// program is running. - #[fail(display = "The requested device is no longer available. For example, it has been unplugged.")] - DeviceNotAvailable, - /// See the `BackendSpecificError` docs for more information about this error variant. - #[fail(display = "{}", err)] - BackendSpecific { - #[fail(cause)] - err: BackendSpecificError, - } -} - impl SupportedFormat { /// Turns this `SupportedFormat` into a `Format` corresponding to the maximum samples rate. #[inline] @@ -571,54 +413,6 @@ impl From for SupportedFormat { } } -impl From for DevicesError { - fn from(err: BackendSpecificError) -> Self { - DevicesError::BackendSpecific { err } - } -} - -impl From for DeviceNameError { - fn from(err: BackendSpecificError) -> Self { - DeviceNameError::BackendSpecific { err } - } -} - -impl From for SupportedFormatsError { - fn from(err: BackendSpecificError) -> Self { - SupportedFormatsError::BackendSpecific { err } - } -} - -impl From for DefaultFormatError { - fn from(err: BackendSpecificError) -> Self { - DefaultFormatError::BackendSpecific { err } - } -} - -impl From for BuildStreamError { - fn from(err: BackendSpecificError) -> Self { - BuildStreamError::BackendSpecific { err } - } -} - -impl From for PlayStreamError { - fn from(err: BackendSpecificError) -> Self { - PlayStreamError::BackendSpecific { err } - } -} - -impl From for PauseStreamError { - fn from(err: BackendSpecificError) -> Self { - PauseStreamError::BackendSpecific { err } - } -} - -impl From for StreamError { - fn from(err: BackendSpecificError) -> Self { - StreamError::BackendSpecific { err } - } -} - // If a backend does not provide an API for retrieving supported formats, we query it with a bunch // of commonly used rates. This is always the case for wasapi and is sometimes the case for alsa. //