aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil <eskilq@kth.se>2020-11-06 22:00:24 +0100
committerEskil <eskilq@kth.se>2020-11-06 22:00:24 +0100
commit1b3bcebc895bfa4b6f65697fafc31d482c74b2de (patch)
tree8f3e8fa198747aa260128951eccd54994ca1fdb5
parentd6496cb0f6abba855b04338fa8bc5aaa89487c29 (diff)
parent0220f0372937ed179aa84fa6e2250933cd3e3896 (diff)
downloadmum-1b3bcebc895bfa4b6f65697fafc31d482c74b2de.tar.gz
Merge branch 'mute' into 'main'
Mute Closes #43 See merge request gustav/mum!29
-rw-r--r--mumctl/src/main.rs77
-rw-r--r--mumd/src/audio.rs28
-rw-r--r--mumd/src/audio/output.rs16
-rw-r--r--mumd/src/state.rs99
-rw-r--r--mumd/src/state/server.rs20
-rw-r--r--mumd/src/state/user.rs8
-rw-r--r--mumlib/src/command.rs3
-rw-r--r--mumlib/src/state.rs21
-rw-r--r--usage.org20
9 files changed, 272 insertions, 20 deletions
diff --git a/mumctl/src/main.rs b/mumctl/src/main.rs
index 11c51e6..22e08ec 100644
--- a/mumctl/src/main.rs
+++ b/mumctl/src/main.rs
@@ -110,6 +110,32 @@ fn main() {
)
.arg(Arg::with_name("user").required(true))
.setting(AppSettings::SubcommandsNegateReqs),
+ )
+ .subcommand(
+ SubCommand::with_name("mute")
+ .subcommand(SubCommand::with_name("true").alias("1"))
+ .subcommand(SubCommand::with_name("false").alias("0"))
+ .subcommand(SubCommand::with_name("toggle"))
+ .setting(AppSettings::SubcommandRequiredElseHelp),
+ )
+ .subcommand(
+ SubCommand::with_name("deafen")
+ .subcommand(SubCommand::with_name("true").alias("1"))
+ .subcommand(SubCommand::with_name("false").alias("0"))
+ .subcommand(SubCommand::with_name("toggle"))
+ .setting(AppSettings::SubcommandRequiredElseHelp),
+ )
+ .subcommand(
+ SubCommand::with_name("user")
+ .arg(Arg::with_name("user").required(true))
+ .subcommand(
+ SubCommand::with_name("mute")
+ .subcommand(SubCommand::with_name("true").alias("1"))
+ .subcommand(SubCommand::with_name("false").alias("0"))
+ .subcommand(SubCommand::with_name("toggle"))
+ .setting(AppSettings::SubcommandRequiredElseHelp),
+ )
+ .setting(AppSettings::SubcommandRequiredElseHelp),
);
let matches = app.clone().get_matches();
@@ -128,15 +154,12 @@ fn main() {
} else if let Some(matches) = matches.subcommand_matches("add") {
match_server_add(matches, &mut config);
} else if let Some(_) = matches.subcommand_matches("list") {
- let servers = config
- .as_ref()
- .map(|e| e.servers.as_ref().map(|e| e.clone()).unwrap_or(Vec::new()))
- .unwrap_or(Vec::new());
- if servers.len() == 0 {
+ if config.servers.len() == 0 {
println!("{} No servers in config", "warning:".yellow());
}
- for (server, response) in servers
- .into_iter()
+ for (server, response) in config
+ .servers
+ .iter()
.map(|e| {
let response = send_command(Command::ServerStatus {
host: e.host.clone(),
@@ -230,6 +253,46 @@ fn main() {
//TODO implement me
//needs work on mumd to implement
}
+ } else if let Some(matches) = matches.subcommand_matches("mute") {
+ let command =
+ Command::MuteSelf(if let Some(_matches) = matches.subcommand_matches("true") {
+ Some(true)
+ } else if let Some(_matches) = matches.subcommand_matches("false") {
+ Some(false)
+ } else if let Some(_matches) = matches.subcommand_matches("toggle") {
+ None
+ } else {
+ unreachable!()
+ });
+ err_print!(send_command(command));
+ } else if let Some(matches) = matches.subcommand_matches("deafen") {
+ let command =
+ Command::DeafenSelf(if let Some(_matches) = matches.subcommand_matches("true") {
+ Some(true)
+ } else if let Some(_matches) = matches.subcommand_matches("false") {
+ Some(false)
+ } else if let Some(_matches) = matches.subcommand_matches("toggle") {
+ None
+ } else {
+ unreachable!()
+ });
+ err_print!(send_command(command));
+ } else if let Some(matches) = matches.subcommand_matches("user") {
+ let name = matches.value_of("user").unwrap();
+ if let Some(matches) = matches.subcommand_matches("mute") {
+ let toggle = if let Some(_matches) = matches.subcommand_matches("true") {
+ Some(true)
+ } else if let Some(_matches) = matches.subcommand_matches("false") {
+ Some(false)
+ } else if let Some(_matches) = matches.subcommand_matches("toggle") {
+ None
+ } else {
+ unreachable!()
+ };
+ err_print!(send_command(Command::MuteOther(name.to_string(), toggle)));
+ } else {
+ unreachable!();
+ }
};
if !config::cfg_exists() {
diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs
index 9f837f7..05e3ff5 100644
--- a/mumd/src/audio.rs
+++ b/mumd/src/audio.rs
@@ -21,13 +21,13 @@ pub struct Audio {
output_volume_sender: watch::Sender<f32>,
- user_volumes: Arc<Mutex<HashMap<u32, f32>>>,
+ user_volumes: Arc<Mutex<HashMap<u32, (f32, bool)>>>,
client_streams: Arc<Mutex<HashMap<u32, output::ClientStream>>>,
}
impl Audio {
- pub fn new() -> Self {
+ pub fn new(input_volume: f32, output_volume: f32) -> Self {
let sample_rate = SampleRate(48000);
let host = cpal::default_host();
@@ -70,7 +70,7 @@ 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 (output_volume_sender, output_volume_receiver) = watch::channel::<f32>(output_volume);
let client_streams = Arc::new(Mutex::new(HashMap::new()));
let output_stream = match output_supported_sample_format {
@@ -119,7 +119,7 @@ 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_volume_sender, input_volume_receiver) = watch::channel::<f32>(input_volume);
let input_stream = match input_supported_sample_format {
SampleFormat::F32 => input_device.build_input_stream(
@@ -230,6 +230,24 @@ impl Audio {
}
pub fn set_user_volume(&self, id: u32, volume: f32) {
- self.user_volumes.lock().unwrap().insert(id, volume);
+ match self.user_volumes.lock().unwrap().entry(id) {
+ Entry::Occupied(mut entry) => {
+ entry.get_mut().0 = volume;
+ }
+ Entry::Vacant(entry) => {
+ entry.insert((volume, false));
+ }
+ }
+ }
+
+ pub fn set_mute(&self, id: u32, mute: bool) {
+ match self.user_volumes.lock().unwrap().entry(id) {
+ Entry::Occupied(mut entry) => {
+ entry.get_mut().1 = mute;
+ }
+ Entry::Vacant(entry) => {
+ entry.insert((1.0, mute));
+ }
+ }
}
}
diff --git a/mumd/src/audio/output.rs b/mumd/src/audio/output.rs
index 56da596..ce116a8 100644
--- a/mumd/src/audio/output.rs
+++ b/mumd/src/audio/output.rs
@@ -74,7 +74,7 @@ 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>>>,
+ user_volumes: Arc<Mutex<HashMap<u32, (f32, bool)>>>,
) -> impl FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static {
move |data: &mut [T], _info: &OutputCallbackInfo| {
for sample in data.iter_mut() {
@@ -85,11 +85,17 @@ pub fn curry_callback<T: Sample + AddAssign + SaturatingAdd>(
let mut lock = buf.lock().unwrap();
for (id, client_stream) in &mut *lock {
- let user_volume = user_volumes.lock().unwrap().get(id).cloned().unwrap_or(1.0);
+ let (user_volume, muted) = user_volumes
+ .lock()
+ .unwrap()
+ .get(id)
+ .cloned()
+ .unwrap_or((1.0, false));
for sample in data.iter_mut() {
- *sample = sample.saturating_add(Sample::from(
- &(client_stream.buffer.pop_front().unwrap_or(0.0) * volume * user_volume),
- ));
+ let s = client_stream.buffer.pop_front().unwrap_or(0.0) * volume * user_volume;
+ if !muted {
+ *sample = sample.saturating_add(Sample::from(&s));
+ }
}
}
}
diff --git a/mumd/src/state.rs b/mumd/src/state.rs
index 56ce030..a767d30 100644
--- a/mumd/src/state.rs
+++ b/mumd/src/state.rs
@@ -68,9 +68,13 @@ impl State {
packet_sender: mpsc::UnboundedSender<ControlPacket<Serverbound>>,
connection_info_sender: watch::Sender<Option<ConnectionInfo>>,
) -> Self {
- let audio = Audio::new();
+ let config = mumlib::config::read_default_cfg();
+ let audio = Audio::new(
+ config.audio.input_volume.unwrap_or(1.0),
+ config.audio.output_volume.unwrap_or(1.0),
+ );
let mut state = Self {
- config: mumlib::config::read_default_cfg(),
+ config,
server: None,
audio,
packet_sender,
@@ -229,6 +233,97 @@ impl State {
self.audio.set_output_volume(volume);
now!(Ok(None))
}
+ Command::DeafenSelf(toggle) => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+
+ let action = match toggle {
+ Some(state) => {
+ if self.server().unwrap().deafened() != state {
+ Some(state)
+ } else {
+ None
+ }
+ }
+ None => Some(!self.server().unwrap().deafened()),
+ };
+
+ if let Some(action) = action {
+ if action {
+ self.server_mut().unwrap().set_muted(true);
+ }
+ let mut msg = msgs::UserState::new();
+ msg.set_self_deaf(action);
+ self.packet_sender.send(msg.into()).unwrap();
+ self.server_mut().unwrap().set_deafened(action);
+ }
+
+ now!(Ok(None))
+ }
+ Command::MuteSelf(toggle) => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+
+ let action = match toggle {
+ Some(state) => {
+ if self.server().unwrap().muted() != state {
+ Some(state)
+ } else {
+ None
+ }
+ }
+ None => Some(!self.server().unwrap().muted()),
+ };
+
+ if let Some(action) = action {
+ if !action {
+ self.server_mut().unwrap().set_deafened(false);
+ }
+ let mut msg = msgs::UserState::new();
+ msg.set_self_mute(action);
+ self.packet_sender.send(msg.into()).unwrap();
+ self.server_mut().unwrap().set_muted(action);
+ }
+
+ now!(Ok(None))
+ }
+ Command::MuteOther(string, toggle) => {
+ if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
+ return now!(Err(Error::DisconnectedError));
+ }
+
+ let id = self
+ .server_mut()
+ .unwrap()
+ .users_mut()
+ .iter_mut()
+ .find(|(_, user)| user.name() == &string);
+
+ let (id, user) = match id {
+ Some(id) => (*id.0, id.1),
+ None => return now!(Err(Error::InvalidUsernameError(string))),
+ };
+
+ let action = match toggle {
+ Some(state) => {
+ if user.suppressed() != state {
+ Some(state)
+ } else {
+ None
+ }
+ }
+ None => Some(!user.suppressed()),
+ };
+
+ if let Some(action) = action {
+ user.set_suppressed(action);
+ self.audio.set_mute(id, action);
+ }
+
+ return now!(Ok(None));
+ }
Command::UserVolumeSet(string, volume) => {
if !matches!(*self.phase_receiver().borrow(), StatePhase::Connected) {
return now!(Err(Error::DisconnectedError));
diff --git a/mumd/src/state/server.rs b/mumd/src/state/server.rs
index b99c7e6..a065df0 100644
--- a/mumd/src/state/server.rs
+++ b/mumd/src/state/server.rs
@@ -15,6 +15,8 @@ pub struct Server {
username: Option<String>,
session_id: Option<u32>,
+ muted: bool,
+ deafened: bool,
host: Option<String>,
}
@@ -27,6 +29,8 @@ impl Server {
welcome_text: None,
username: None,
session_id: None,
+ muted: false,
+ deafened: false,
host: None,
}
}
@@ -109,6 +113,22 @@ impl Server {
pub fn username_mut(&mut self) -> &mut Option<String> {
&mut self.username
}
+
+ pub fn muted(&self) -> bool {
+ self.muted
+ }
+
+ pub fn deafened(&self) -> bool {
+ self.deafened
+ }
+
+ pub fn set_muted(&mut self, value: bool) {
+ self.muted = value;
+ }
+
+ pub fn set_deafened(&mut self, value: bool) {
+ self.deafened = value;
+ }
}
impl From<&Server> for mumlib::state::Server {
diff --git a/mumd/src/state/user.rs b/mumd/src/state/user.rs
index 848208c..913f91b 100644
--- a/mumd/src/state/user.rs
+++ b/mumd/src/state/user.rs
@@ -129,6 +129,14 @@ impl User {
pub fn self_deaf(&self) -> bool {
self.self_deaf
}
+
+ pub fn suppressed(&self) -> bool {
+ self.suppress
+ }
+
+ pub fn set_suppressed(&mut self, value: bool) {
+ self.suppress = value;
+ }
}
impl From<&User> for mumlib::state::User {
diff --git a/mumlib/src/command.rs b/mumlib/src/command.rs
index 2fed4f1..675fb7d 100644
--- a/mumlib/src/command.rs
+++ b/mumlib/src/command.rs
@@ -24,6 +24,9 @@ pub enum Command {
host: String,
port: u16,
},
+ DeafenSelf(Option<bool>),
+ MuteSelf(Option<bool>),
+ MuteOther(String, Option<bool>),
}
#[derive(Debug, Deserialize, Serialize)]
diff --git a/mumlib/src/state.rs b/mumlib/src/state.rs
index b6b4039..3b1da56 100644
--- a/mumlib/src/state.rs
+++ b/mumlib/src/state.rs
@@ -130,9 +130,28 @@ pub struct User {
pub deaf: bool, // by admin
}
+macro_rules! true_to_str {
+ ($condition:expr, $res:expr) => {
+ if $condition {
+ $res
+ } else {
+ ""
+ }
+ };
+}
+
impl Display for User {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", self.name)
+ write!(
+ f,
+ "{} {}{}{}{}{}",
+ self.name,
+ true_to_str!(self.suppress, "s"),
+ true_to_str!(self.self_mute, "M"),
+ true_to_str!(self.self_deaf, "D"),
+ true_to_str!(self.mute, "m"),
+ true_to_str!(self.deaf, "d")
+ )
}
}
diff --git a/usage.org b/usage.org
index ca544be..952cc41 100644
--- a/usage.org
+++ b/usage.org
@@ -151,3 +151,23 @@ $ mumctl volume set User1 1.1
$ mumctl volume User1
110%
#+END_SRC
+
+* 0.3
+** mute
+#+BEGIN_SRC bash
+$ mumctl mute true
+$ mumctl mute false
+$ mumctl mute toggle
+#+END_SRC
+** deafen
+#+BEGIN_SRC bash
+$ mumctl deafen true
+$ mumctl deafen false
+$ mumctl deafen toggle
+#+END_SRC
+** user
+#+BEGIN_SRC bash
+$ mumctl user Username mute true
+$ mumctl user Username mute false
+$ mumctl user Username mute toggle
+#+END_SRC