aboutsummaryrefslogtreecommitdiffstats
path: root/mumd
diff options
context:
space:
mode:
Diffstat (limited to 'mumd')
-rw-r--r--mumd/src/audio.rs25
-rw-r--r--mumd/src/network/tcp.rs1
-rw-r--r--mumd/src/state.rs50
3 files changed, 61 insertions, 15 deletions
diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs
index edc2f7f..828942b 100644
--- a/mumd/src/audio.rs
+++ b/mumd/src/audio.rs
@@ -13,13 +13,13 @@ use std::ops::AddAssign;
use std::sync::Arc;
use std::sync::Mutex;
use tokio::sync::mpsc::{self, Receiver, Sender};
+use tokio::sync::watch;
struct ClientStream {
buffer: VecDeque<f32>, //TODO ring buffer?
opus_decoder: opus::Decoder,
}
-//TODO remove pub where possible
pub struct Audio {
pub output_config: StreamConfig,
pub output_stream: Stream,
@@ -27,12 +27,12 @@ pub struct Audio {
pub input_config: StreamConfig,
pub input_stream: Stream,
pub input_buffer: Arc<Mutex<VecDeque<f32>>>,
- input_channel_receiver: Option<Receiver<VoicePacketPayload>>, //TODO unbounded? mbe ring buffer and drop the first packet
+ input_channel_receiver: Option<Receiver<VoicePacketPayload>>,
+ input_volume_sender: watch::Sender<f32>,
- client_streams: Arc<Mutex<HashMap<u32, ClientStream>>>, //TODO move to user state
+ client_streams: Arc<Mutex<HashMap<u32, ClientStream>>>,
}
-//TODO split into input/output
impl Audio {
pub fn new() -> Self {
let host = cpal::default_host();
@@ -99,6 +99,8 @@ impl Audio {
.unwrap();
let (input_sender, input_receiver) = mpsc::channel(100);
+ let (input_volume_sender, input_volume_receiver) = watch::channel::<f32>(1.0);
+
let input_buffer = Arc::new(Mutex::new(VecDeque::new()));
let input_stream = match input_supported_sample_format {
SampleFormat::F32 => input_device.build_input_stream(
@@ -107,6 +109,7 @@ impl Audio {
input_encoder,
input_sender,
input_config.sample_rate.0,
+ input_volume_receiver.clone(),
4, // 10 ms
),
err_fn,
@@ -117,6 +120,7 @@ impl Audio {
input_encoder,
input_sender,
input_config.sample_rate.0,
+ input_volume_receiver.clone(),
4, // 10 ms
),
err_fn,
@@ -127,6 +131,7 @@ impl Audio {
input_encoder,
input_sender,
input_config.sample_rate.0,
+ input_volume_receiver.clone(),
4, // 10 ms
),
err_fn,
@@ -142,6 +147,7 @@ impl Audio {
input_config,
input_stream,
input_buffer,
+ input_volume_sender,
input_channel_receiver: Some(input_receiver),
client_streams,
}
@@ -195,6 +201,10 @@ impl Audio {
pub fn clear_clients(&mut self) {
self.client_streams.lock().unwrap().clear();
}
+
+ pub fn set_input_volume(&self, input_volume: f32) {
+ self.input_volume_sender.broadcast(input_volume).unwrap();
+ }
}
impl ClientStream {
@@ -280,6 +290,7 @@ fn input_callback<T: Sample>(
mut opus_encoder: opus::Encoder,
mut input_sender: Sender<VoicePacketPayload>,
sample_rate: u32,
+ input_volume_receiver: watch::Receiver<f32>,
opus_frame_size_blocks: u32, // blocks of 2.5ms
) -> impl FnMut(&[T], &InputCallbackInfo) + Send + 'static {
if !(opus_frame_size_blocks == 1
@@ -297,7 +308,10 @@ fn input_callback<T: Sample>(
let buf = Arc::new(Mutex::new(VecDeque::new()));
move |data: &[T], _info: &InputCallbackInfo| {
let mut buf = buf.lock().unwrap();
- let out: Vec<f32> = data.iter().map(|e| e.to_f32()).collect();
+ let input_volume = *input_volume_receiver.borrow();
+ let out: Vec<f32> = data.iter().map(|e| e.to_f32())
+ .map(|e| e * input_volume)
+ .collect();
buf.extend(out);
while buf.len() >= opus_frame_size as usize {
let tail = buf.split_off(opus_frame_size as usize);
@@ -308,7 +322,6 @@ fn input_callback<T: Sample>(
opus_buf.truncate(result);
let bytes = Bytes::copy_from_slice(&opus_buf);
match input_sender.try_send(VoicePacketPayload::Opus(bytes, false)) {
- //TODO handle full buffer / disconnect
Ok(_) => {}
Err(_e) => {
//warn!("Error sending audio packet: {:?}", e);
diff --git a/mumd/src/network/tcp.rs b/mumd/src/network/tcp.rs
index ea4ef86..88d2b59 100644
--- a/mumd/src/network/tcp.rs
+++ b/mumd/src/network/tcp.rs
@@ -233,7 +233,6 @@ async fn listen(
break;
}
Some(Some(packet)) => {
- //TODO handle types separately
match packet.unwrap() {
ControlPacket::TextMessage(msg) => {
info!(
diff --git a/mumd/src/state.rs b/mumd/src/state.rs
index 1c964b3..55fd8ae 100644
--- a/mumd/src/state.rs
+++ b/mumd/src/state.rs
@@ -6,7 +6,7 @@ use mumble_protocol::control::msgs;
use mumble_protocol::control::ControlPacket;
use mumble_protocol::voice::Serverbound;
use mumlib::command::{Command, CommandResponse};
-use mumlib::error::Error;
+use mumlib::error::{ChannelIdentifierError, Error};
use serde::{Deserialize, Serialize};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
@@ -50,18 +50,38 @@ impl State {
command: Command,
) -> (bool, mumlib::error::Result<Option<CommandResponse>>) {
match command {
- Command::ChannelJoin { channel_id } => {
+ Command::ChannelJoin { channel_identifier } => {
if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
return (false, Err(Error::DisconnectedError));
}
- let server = self.server.as_ref().unwrap();
- if !server.channels().contains_key(&channel_id) {
- return (false, Err(Error::InvalidChannelIdError(channel_id)));
- }
+
+ let channels = self.server()
+ .unwrap()
+ .channels();
+
+ let matches = channels.iter()
+ .map(|e| (e.0, e.1.path(channels)))
+ .filter(|e| e.1.ends_with(&channel_identifier))
+ .collect::<Vec<_>>();
+ let id = match matches.len() {
+ 0 => {
+ let soft_matches = channels.iter()
+ .map(|e| (e.0, e.1.path(channels).to_lowercase()))
+ .filter(|e| e.1.ends_with(&channel_identifier.to_lowercase()))
+ .collect::<Vec<_>>();
+ match soft_matches.len() {
+ 0 => return (false, Err(Error::ChannelIdentifierError(channel_identifier, ChannelIdentifierError::Invalid))),
+ 1 => *soft_matches.get(0).unwrap().0,
+ _ => return (false, Err(Error::ChannelIdentifierError(channel_identifier, ChannelIdentifierError::Invalid))),
+ }
+ },
+ 1 => *matches.get(0).unwrap().0,
+ _ => return (false, Err(Error::ChannelIdentifierError(channel_identifier, ChannelIdentifierError::Ambiguous))),
+ };
let mut msg = msgs::UserState::new();
- msg.set_session(server.session_id.unwrap());
- msg.set_channel_id(channel_id);
+ msg.set_session(self.server.as_ref().unwrap().session_id.unwrap());
+ msg.set_channel_id(id);
self.packet_sender.send(msg.into()).unwrap();
(false, Ok(None))
}
@@ -141,6 +161,10 @@ impl State {
.unwrap();
(false, Ok(None))
}
+ Command::InputVolumeSet(volume) => {
+ self.audio.set_input_volume(volume);
+ (false, Ok(None))
+ }
}
}
@@ -192,6 +216,9 @@ impl State {
pub fn phase_receiver(&self) -> watch::Receiver<StatePhase> {
self.phase_watcher.1.clone()
}
+ pub fn server(&self) -> Option<&Server> {
+ self.server.as_ref()
+ }
pub fn server_mut(&mut self) -> Option<&mut Server> {
self.server.as_mut()
}
@@ -347,6 +374,13 @@ impl Channel {
pub fn name(&self) -> &str {
&self.name
}
+
+ pub fn path(&self, channels: &HashMap<u32, Channel>) -> String {
+ match &self.parent {
+ Some(t) => format!("{}/{}", channels.get(t).unwrap().path(channels), self.name),
+ None => self.name.clone(),
+ }
+ }
}
#[derive(Debug)]