aboutsummaryrefslogtreecommitdiffstats
path: root/mumd
diff options
context:
space:
mode:
Diffstat (limited to 'mumd')
-rw-r--r--mumd/src/audio.rs23
-rw-r--r--mumd/src/client.rs3
-rw-r--r--mumd/src/error.rs54
-rw-r--r--mumd/src/main.rs13
-rw-r--r--mumd/src/state.rs7
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(