use super::*;
#[derive(Debug, Snafu)]
#[snafu(context(suffix(false)), visibility(pub(crate)))]
pub(crate) enum Error {
#[snafu(display(
"app exited with errors{}",
Self::additional_error_message(additional.len(), " "),
))]
AppExit {
backtrace: Option<Backtrace>,
source: Box<Error>,
additional: Vec<Error>,
},
#[snafu(display("failed to run app"))]
AppRun {
backtrace: Option<Backtrace>,
source: winit::error::EventLoopError,
},
#[snafu(display("failed to build audio input stream"))]
AudioBuildInputStream {
backtrace: Option<Backtrace>,
source: cpal::BuildStreamError,
},
#[snafu(display("failed to get default audio output stream"))]
AudioBuildOutputStream {
backtrace: Option<Backtrace>,
source: cpal::BuildStreamError,
},
#[snafu(display("failed to get default audio input device"))]
AudioDefaultInputDevice { backtrace: Option<Backtrace> },
#[snafu(display("failed to get default audio output device"))]
AudioDefaultOutputDevice { backtrace: Option<Backtrace> },
#[snafu(display("failed to get audio device name"))]
AudioDeviceName {
backtrace: Option<Backtrace>,
source: cpal::DeviceNameError,
},
#[snafu(display("failed to enumerate audio devices"))]
AudioDevices {
backtrace: Option<Backtrace>,
source: cpal::DevicesError,
},
#[snafu(display("failed to play audio input stream"))]
AudioPlayStream {
backtrace: Option<Backtrace>,
source: cpal::PlayStreamError,
},
#[snafu(display("failed to get supported stream config"))]
AudioSupportedStreamConfig { backtrace: Option<Backtrace> },
#[snafu(display("failed to get supported stream configs"))]
AudioSupportedStreamConfigs {
backtrace: Option<Backtrace>,
source: cpal::SupportedStreamConfigsError,
},
#[snafu(display("failed to deserialize config file at `{path}`"))]
ConfigDeserialize {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: serde_yaml::Error,
},
#[snafu(display("failed to create overlay renderer"))]
CreateOverlayRenderer {
backtrace: Option<Backtrace>,
source: vello::Error,
},
#[snafu(display("failed to create surface"))]
CreateSurface {
backtrace: Option<Backtrace>,
source: wgpu::CreateSurfaceError,
},
#[snafu(display("failed to create window"))]
CreateWindow {
backtrace: Option<Backtrace>,
source: winit::error::OsError,
},
#[snafu(display("failed to get current texture"))]
CurrentTexture {
backtrace: Option<Backtrace>,
source: wgpu::SurfaceError,
},
#[snafu(display("failed to get default config"))]
DefaultConfig { backtrace: Option<Backtrace> },
#[snafu(display("failed to build event loop"))]
EventLoopBuild {
backtrace: Option<Backtrace>,
source: winit::error::EventLoopError,
},
#[snafu(display("I/O error at `{path}`"))]
FilesystemIo {
path: Utf8PathBuf,
backtrace: Option<Backtrace>,
source: io::Error,
},
#[snafu(display("could not get home directory"))]
Home { backtrace: Option<Backtrace> },
#[snafu(display("internal error: {message}"))]
Internal {
backtrace: Option<Backtrace>,
message: String,
},
#[snafu(display("failed to initialize MIDI input"))]
MidiInputInit {
backtrace: Option<Backtrace>,
source: midir::InitError,
},
#[snafu(display("failed to connect to MIDI port"))]
MidiInputPortConnect {
backtrace: Option<Backtrace>,
source: midir::ConnectError<midir::MidiInput>,
},
#[snafu(display("failed to initialize MIDI output"))]
MidiOutputInit {
backtrace: Option<Backtrace>,
source: midir::InitError,
},
#[snafu(display("failed to get MIDI port info"))]
MidiPortInfo {
backtrace: Option<Backtrace>,
source: midir::PortInfoError,
},
#[snafu(display("no music directory configured"))]
Music { backtrace: Option<Backtrace> },
#[snafu(display("path not valid unicode: `{}`", path.display()))]
PathUnicode {
backtrace: Option<Backtrace>,
path: std::path::PathBuf,
source: camino::FromPathError,
},
#[snafu(display("failed to decode PNG at `{path}`"))]
PngDecode {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: png::DecodingError,
},
#[snafu(display("PNG has unsupported format {color_type:?} {bit_depth:?}: `{path}`"))]
PngDecodeFormat {
backtrace: Option<Backtrace>,
bit_depth: png::BitDepth,
color_type: png::ColorType,
path: Utf8PathBuf,
},
#[snafu(display("PNG too large to fit in memory: `{path}`"))]
PngDecodeSize {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
},
#[snafu(display("failed to encode PNG: `{path}`"))]
PngEncode {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: png::EncodingError,
},
#[snafu(display("`--record` requires `--fps`"))]
RecordRequiresFps { backtrace: Option<Backtrace> },
#[snafu(display("failed to flush recorded video"))]
RecordingFlush {
backtrace: Option<Backtrace>,
source: io::Error,
},
#[snafu(display("failed to invoke recording command"))]
RecordingInvoke {
backtrace: Option<Backtrace>,
source: io::Error,
},
#[snafu(display("failed to join recording thread"))]
RecordingJoin {
backtrace: Option<Backtrace>,
panic_value: Box<dyn Any + Send + 'static>,
},
#[snafu(display("recording command failed"))]
RecordingStatus {
backtrace: Option<Backtrace>,
status: ExitStatus,
},
#[snafu(display("failed to wait for recording command"))]
RecordingWait {
backtrace: Option<Backtrace>,
source: io::Error,
},
#[snafu(display("failed to write recorded video"))]
RecordingWrite {
backtrace: Option<Backtrace>,
source: io::Error,
},
#[snafu(display(
"rendering failed: {error}{}",
Self::additional_error_message(additional.len(), ""),
))]
Render {
backtrace: Option<Backtrace>,
error: wgpu::Error,
additional: Vec<wgpu::Error>,
},
#[snafu(display("failed to render overlay"))]
RenderOverlay {
backtrace: Option<Backtrace>,
source: vello::Error,
},
#[snafu(display("failed to poll renderer"))]
RenderPoll {
backtrace: Option<Backtrace>,
source: wgpu::PollError,
},
#[snafu(display("failed to get adapter"))]
RequestAdapter {
backtrace: Option<Backtrace>,
source: wgpu::RequestAdapterError,
},
#[snafu(display("failed to get device"))]
RequestDevice {
backtrace: Option<Backtrace>,
source: wgpu::RequestDeviceError,
},
#[snafu(display("sample rate {sample_rate} is not divisible by fps {fps}"))]
SamplesPerFrame {
backtrace: Option<Backtrace>,
fps: Fps,
sample_rate: u32,
},
#[snafu(display("failed to reload shader template from `{path}`"))]
ShaderReload {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: boilerplate::Error,
},
#[snafu(
display(
"more than one match for song: {}",
matches.iter().map(ToString::to_string).collect::<Vec<String>>().join(", ")
)
)]
SongAmbiguous {
backtrace: Option<Backtrace>,
matches: Vec<Utf8PathBuf>,
},
#[snafu(display("could not match song `{song}`"))]
SongMatch {
backtrace: Option<Backtrace>,
song: Regex,
},
#[snafu(display("invalid song regex"))]
SongRegex {
backtrace: Option<Backtrace>,
source: regex::Error,
},
#[snafu(display("I/O error finding song"))]
SongWalk {
backtrace: Option<Backtrace>,
source: walkdir::Error,
},
#[snafu(display("I/O error creating tempdir"))]
TempdirIo {
backtrace: Option<Backtrace>,
source: io::Error,
},
#[snafu(display("failed to spawn thread `{name}`"))]
ThreadSpawn {
backtrace: Option<Backtrace>,
name: String,
source: io::Error,
},
#[snafu(display("Surface not compatible with adapter"))]
UnsupportedSurfaceAdapter { backtrace: Option<Backtrace> },
#[snafu(display("Unsupported surface format `{format}`"))]
UnsupportedSurfaceFormat {
backtrace: Option<Backtrace>,
format: ImageFormat,
},
#[snafu(display("Unsupported surface present mode `{present_mode}`"))]
UnsupportedSurfacePresentMode {
backtrace: Option<Backtrace>,
present_mode: PresentMode,
},
#[snafu(display("default texture format {texture_format:?} not supported"))]
UnsupportedTextureFormat {
backtrace: Option<Backtrace>,
texture_format: TextureFormat,
},
#[snafu(display("failed to create wave writer"))]
WaveCreate {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: hound::Error,
},
#[snafu(display("failed to finalize wave writer"))]
WaveFinalize {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: hound::Error,
},
#[snafu(display("failed to load audio track"))]
WaveLoad {
backtrace: Option<Backtrace>,
source: fundsp::read::WaveError,
},
#[snafu(display("failed to resample audio"))]
WaveResample {
backtrace: Option<Backtrace>,
source: rubato::ResampleError,
},
#[snafu(display("failed to construct audio resampler"))]
WaveResamplerConstruction {
backtrace: Option<Backtrace>,
source: rubato::ResamplerConstructionError,
},
#[snafu(display("wave has fractional sample rate: {sample_rate}"))]
WaveSampleRate {
backtrace: Option<Backtrace>,
sample_rate: f64,
},
#[snafu(display("failed to write wave samples"))]
WaveWrite {
backtrace: Option<Backtrace>,
path: Utf8PathBuf,
source: hound::Error,
},
}
impl Error {
fn additional_error_message(additional: usize, prefix: &str) -> String {
if additional == 0 {
return String::new();
}
let plural = if additional == 1 { "" } else { "s" };
format!("{prefix}{additional} additional error{plural} suppressed")
}
pub(crate) fn internal(message: impl Into<String>) -> Self {
Internal { message }.build()
}
}