diff options
Diffstat (limited to 'mumd/src')
| -rw-r--r-- | mumd/src/audio.rs | 23 | ||||
| -rw-r--r-- | mumd/src/client.rs | 3 | ||||
| -rw-r--r-- | mumd/src/error.rs | 54 | ||||
| -rw-r--r-- | mumd/src/main.rs | 13 | ||||
| -rw-r--r-- | mumd/src/state.rs | 7 |
5 files changed, 84 insertions, 16 deletions
diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs index 1e231e2..82acfee 100644 --- a/mumd/src/audio.rs +++ b/mumd/src/audio.rs @@ -4,6 +4,7 @@ mod noise_gate; use crate::audio::output::SaturatingAdd; use crate::audio::noise_gate::{from_interleaved_samples_stream, OpusEncoder, StreamingNoiseGate, StreamingSignalExt}; +use crate::error::{AudioError, AudioStream}; use crate::network::VoiceStreamType; use crate::state::StatePhase; @@ -85,16 +86,16 @@ pub struct Audio { } impl Audio { - pub fn new(input_volume: f32, output_volume: f32, phase_watcher: watch::Receiver<StatePhase>) -> Self { + pub fn new(input_volume: f32, output_volume: f32, phase_watcher: watch::Receiver<StatePhase>) -> Result<Self, AudioError> { let sample_rate = SampleRate(SAMPLE_RATE); let host = cpal::default_host(); let output_device = host .default_output_device() - .expect("default output device not found"); + .ok_or(AudioError::NoDevice(AudioStream::Output))?; let output_supported_config = output_device .supported_output_configs() - .expect("error querying output configs") + .map_err(|e| AudioError::NoConfigs(AudioStream::Output, e))? .find_map(|c| { if c.min_sample_rate() <= sample_rate && c.max_sample_rate() >= sample_rate { Some(c) @@ -102,17 +103,17 @@ impl Audio { None } }) - .unwrap() //TODO handle panic + .ok_or(AudioError::NoSupportedConfig(AudioStream::Output))? .with_sample_rate(sample_rate); let output_supported_sample_format = output_supported_config.sample_format(); let output_config: StreamConfig = output_supported_config.into(); let input_device = host .default_input_device() - .expect("default input device not found"); + .ok_or(AudioError::NoDevice(AudioStream::Input))?; let input_supported_config = input_device .supported_input_configs() - .expect("error querying output configs") + .map_err(|e| AudioError::NoConfigs(AudioStream::Input, e))? .find_map(|c| { if c.min_sample_rate() <= sample_rate && c.max_sample_rate() >= sample_rate { Some(c) @@ -120,7 +121,7 @@ impl Audio { None } }) - .unwrap() //TODO handle panic + .ok_or(AudioError::NoSupportedConfig(AudioStream::Input))? .with_sample_rate(sample_rate); let input_supported_sample_format = input_supported_config.sample_format(); let input_config: StreamConfig = input_supported_config.into(); @@ -164,7 +165,7 @@ impl Audio { err_fn, ), } - .unwrap(); //TODO handle panic + .map_err(|e| AudioError::InvalidStream(AudioStream::Output, e))?; let (sample_sender, sample_receiver) = futures_channel::mpsc::channel(1_000_000); @@ -199,7 +200,7 @@ impl Audio { err_fn, ), } - .unwrap(); //TODO handle panic + .map_err(|e| AudioError::InvalidStream(AudioStream::Input, e))?; let opus_stream = OpusEncoder::new( 4, @@ -217,7 +218,7 @@ impl Audio { position_info: None, }); - output_stream.play().unwrap(); //TODO handle panic? + output_stream.play().map_err(|e| AudioError::OutputPlayError(e))?; let mut res = Self { output_config, @@ -232,7 +233,7 @@ impl Audio { play_sounds, }; res.load_sound_effects(&[]); - res + Ok(res) } pub fn load_sound_effects(&mut self, sound_effects: &[SoundEffect]) { diff --git a/mumd/src/client.rs b/mumd/src/client.rs index cdae7eb..6b66731 100644 --- a/mumd/src/client.rs +++ b/mumd/src/client.rs @@ -8,6 +8,7 @@ use std::sync::Arc; use tokio::{join, sync::{Mutex, mpsc, oneshot, watch}}; pub async fn handle( + state: State, command_receiver: mpsc::UnboundedReceiver<( Command, oneshot::Sender<mumlib::error::Result<Option<CommandResponse>>>, @@ -24,8 +25,8 @@ pub async fn handle( let (response_sender, response_receiver) = mpsc::unbounded_channel(); - let state = State::new(); let state = Arc::new(Mutex::new(state)); + join!( tcp::handle( Arc::clone(&state), diff --git a/mumd/src/error.rs b/mumd/src/error.rs new file mode 100644 index 0000000..a171f1f --- /dev/null +++ b/mumd/src/error.rs @@ -0,0 +1,54 @@ +use std::fmt; + +pub enum AudioStream { + Input, + Output, +} + +impl fmt::Display for AudioStream { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AudioStream::Input => write!(f, "input"), + AudioStream::Output => write!(f, "output"), + } + } +} + +pub enum AudioError { + NoDevice(AudioStream), + NoConfigs(AudioStream, cpal::SupportedStreamConfigsError), + NoSupportedConfig(AudioStream), + InvalidStream(AudioStream, cpal::BuildStreamError), + OutputPlayError(cpal::PlayStreamError), +} + +impl fmt::Display for AudioError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AudioError::NoDevice(s) => write!(f, "No {} device", s), + AudioError::NoConfigs(s, e) => write!(f, "No {} configs: {}", s, e), + AudioError::NoSupportedConfig(s) => write!(f, "No supported {} config found", s), + AudioError::InvalidStream(s, e) => write!(f, "Invalid {} stream: {}", s, e), + AudioError::OutputPlayError(e) => write!(f, "Playback error: {}", e), + } + } +} + +pub enum StateError { + AudioError(AudioError), +} + +impl From<AudioError> for StateError { + fn from(e: AudioError) -> Self { + StateError::AudioError(e) + } +} + +impl fmt::Display for StateError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + StateError::AudioError(e) => write!(f, "Audio error: {}", e), + } + } +} + diff --git a/mumd/src/main.rs b/mumd/src/main.rs index 276e2ce..42be3f8 100644 --- a/mumd/src/main.rs +++ b/mumd/src/main.rs @@ -1,10 +1,13 @@ mod audio; mod client; mod command; +mod error; mod network; mod notify; mod state; +use crate::state::State; + use futures_util::{SinkExt, StreamExt}; use log::*; use mumlib::command::{Command, CommandResponse}; @@ -53,8 +56,16 @@ async fn main() { let (command_sender, command_receiver) = mpsc::unbounded_channel(); + let state = match State::new() { + Ok(s) => s, + Err(e) => { + error!("Error instantiating mumd: {}", e); + return; + } + }; + join!( - client::handle(command_receiver), + client::handle(state, command_receiver), receive_commands(command_sender), ); } diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 20fe660..858441a 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -3,6 +3,7 @@ pub mod server; pub mod user; use crate::audio::{Audio, NotificationEvents}; +use crate::error::StateError; use crate::network::{ConnectionInfo, VoiceStreamType}; use crate::network::tcp::{TcpEvent, TcpEventData}; use crate::notify; @@ -62,14 +63,14 @@ pub struct State { } impl State { - pub fn new() -> Self { + pub fn new() -> Result<Self, StateError> { let config = mumlib::config::read_default_cfg(); let phase_watcher = watch::channel(StatePhase::Disconnected); let audio = Audio::new( config.audio.input_volume.unwrap_or(1.0), config.audio.output_volume.unwrap_or(1.0), phase_watcher.1.clone(), - ); + ).map_err(|e| StateError::AudioError(e))?; let mut state = Self { config, server: None, @@ -77,7 +78,7 @@ impl State { phase_watcher, }; state.reload_config(); - state + Ok(state) } pub fn handle_command( |
