aboutsummaryrefslogtreecommitdiffstats
path: root/mumd
diff options
context:
space:
mode:
authorEskil Queseth <eskilq@kth.se>2020-11-02 20:31:50 +0100
committerEskil Queseth <eskilq@kth.se>2020-11-02 20:31:50 +0100
commit46861ce465d6f1d86e80007742a850fd1cfa9bad (patch)
treedd57d0237227a6de2c34512a0aee3b51d48f009e /mumd
parent8fb4edd72dfcb2b71e91eedc5861360101374967 (diff)
downloadmum-46861ce465d6f1d86e80007742a850fd1cfa9bad.tar.gz
add mumd support for volume adjustment
Diffstat (limited to 'mumd')
-rw-r--r--mumd/src/audio.rs41
-rw-r--r--mumd/src/audio/output.rs10
-rw-r--r--mumd/src/state.rs27
3 files changed, 68 insertions, 10 deletions
diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs
index ad4a762..9f837f7 100644
--- a/mumd/src/audio.rs
+++ b/mumd/src/audio.rs
@@ -19,6 +19,10 @@ pub struct Audio {
input_channel_receiver: Option<mpsc::Receiver<VoicePacketPayload>>,
input_volume_sender: watch::Sender<f32>,
+ output_volume_sender: watch::Sender<f32>,
+
+ user_volumes: Arc<Mutex<HashMap<u32, f32>>>,
+
client_streams: Arc<Mutex<HashMap<u32, output::ClientStream>>>,
}
@@ -65,21 +69,36 @@ impl Audio {
let err_fn = |err| error!("An error occurred on the output audio stream: {}", err);
+ let user_volumes = Arc::new(Mutex::new(HashMap::new()));
+ let (output_volume_sender, output_volume_receiver) = watch::channel::<f32>(1.0);
+
let client_streams = Arc::new(Mutex::new(HashMap::new()));
let output_stream = match output_supported_sample_format {
SampleFormat::F32 => output_device.build_output_stream(
&output_config,
- output::curry_callback::<f32>(Arc::clone(&client_streams)),
+ output::curry_callback::<f32>(
+ Arc::clone(&client_streams),
+ output_volume_receiver,
+ Arc::clone(&user_volumes),
+ ),
err_fn,
),
SampleFormat::I16 => output_device.build_output_stream(
&output_config,
- output::curry_callback::<i16>(Arc::clone(&client_streams)),
+ output::curry_callback::<i16>(
+ Arc::clone(&client_streams),
+ output_volume_receiver,
+ Arc::clone(&user_volumes),
+ ),
err_fn,
),
SampleFormat::U16 => output_device.build_output_stream(
&output_config,
- output::curry_callback::<u16>(Arc::clone(&client_streams)),
+ output::curry_callback::<u16>(
+ Arc::clone(&client_streams),
+ output_volume_receiver,
+ Arc::clone(&user_volumes),
+ ),
err_fn,
),
}
@@ -109,7 +128,7 @@ impl Audio {
input_encoder,
input_sender,
input_config.sample_rate.0,
- input_volume_receiver.clone(),
+ input_volume_receiver,
4, // 10 ms
),
err_fn,
@@ -120,7 +139,7 @@ impl Audio {
input_encoder,
input_sender,
input_config.sample_rate.0,
- input_volume_receiver.clone(),
+ input_volume_receiver,
4, // 10 ms
),
err_fn,
@@ -131,7 +150,7 @@ impl Audio {
input_encoder,
input_sender,
input_config.sample_rate.0,
- input_volume_receiver.clone(),
+ input_volume_receiver,
4, // 10 ms
),
err_fn,
@@ -148,6 +167,8 @@ impl Audio {
input_volume_sender,
input_channel_receiver: Some(input_receiver),
client_streams,
+ output_volume_sender,
+ user_volumes,
}
}
@@ -203,4 +224,12 @@ impl Audio {
pub fn set_input_volume(&self, input_volume: f32) {
self.input_volume_sender.broadcast(input_volume).unwrap();
}
+
+ pub fn set_output_volume(&self, output_volume: f32) {
+ self.output_volume_sender.broadcast(output_volume).unwrap();
+ }
+
+ pub fn set_user_volume(&self, id: u32, volume: f32) {
+ self.user_volumes.lock().unwrap().insert(id, volume);
+ }
}
diff --git a/mumd/src/audio/output.rs b/mumd/src/audio/output.rs
index 94e4b21..78dba02 100644
--- a/mumd/src/audio/output.rs
+++ b/mumd/src/audio/output.rs
@@ -4,6 +4,7 @@ use opus::Channels;
use std::collections::{HashMap, VecDeque};
use std::ops::AddAssign;
use std::sync::{Arc, Mutex};
+use tokio::sync::watch;
pub struct ClientStream {
buffer: VecDeque<f32>, //TODO ring buffer?
@@ -72,17 +73,22 @@ impl SaturatingAdd for u16 {
pub fn curry_callback<T: Sample + AddAssign + SaturatingAdd>(
buf: Arc<Mutex<HashMap<u32, ClientStream>>>,
+ output_volume_receiver: watch::Receiver<f32>,
+ user_volumes: Arc<Mutex<HashMap<u32, f32>>>
) -> impl FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static {
move |data: &mut [T], _info: &OutputCallbackInfo| {
for sample in data.iter_mut() {
*sample = Sample::from(&0.0);
}
+ let volume = *output_volume_receiver.borrow();
+
let mut lock = buf.lock().unwrap();
- for client_stream in lock.values_mut() {
+ for (id, client_stream) in &mut *lock {
+ let user_volume = user_volumes.lock().unwrap().get(id).cloned().unwrap_or(1.0);
for sample in data.iter_mut() {
*sample = sample.saturating_add(Sample::from(
- &client_stream.buffer.pop_front().unwrap_or(0.0),
+ &(client_stream.buffer.pop_front().unwrap_or(0.0) * volume * user_volume),
));
}
}
diff --git a/mumd/src/state.rs b/mumd/src/state.rs
index 81b6c98..2060845 100644
--- a/mumd/src/state.rs
+++ b/mumd/src/state.rs
@@ -209,12 +209,35 @@ impl State {
.unwrap();
now!(Ok(None))
}
+ Command::ConfigReload => {
+ self.reload_config();
+ now!(Ok(None))
+ }
Command::InputVolumeSet(volume) => {
self.audio.set_input_volume(volume);
now!(Ok(None))
}
- Command::ConfigReload => {
- self.reload_config();
+ Command::OutputVolumeSet(volume) => {
+ self.audio.set_output_volume(volume);
+ now!(Ok(None))
+ }
+ Command::UserVolumeSet(string, volume) => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+ let user_id = match self
+ .server()
+ .unwrap()
+ .users()
+ .iter()
+ .find(|e| e.1.name() == &string)
+ .map(|e| *e.0)
+ {
+ None => return now!(Err(Error::InvalidUsernameError(string))),
+ Some(v) => v,
+ };
+
+ self.audio.set_user_volume(user_id, volume);
now!(Ok(None))
}
}