diff options
| -rw-r--r-- | Cargo.lock | 6 | ||||
| -rw-r--r-- | changelog/0.2.txt | 44 | ||||
| -rw-r--r-- | mumctl/Cargo.toml | 2 | ||||
| -rw-r--r-- | mumctl/src/main.rs | 227 | ||||
| -rw-r--r-- | mumd/Cargo.toml | 2 | ||||
| -rw-r--r-- | mumd/src/audio.rs | 34 | ||||
| -rw-r--r-- | mumlib/Cargo.toml | 2 | ||||
| -rw-r--r-- | mumlib/src/config.rs | 67 |
8 files changed, 272 insertions, 112 deletions
@@ -742,7 +742,7 @@ dependencies = [ [[package]] name = "mumctl" -version = "0.1.0" +version = "0.2.0" dependencies = [ "clap", "colored", @@ -753,7 +753,7 @@ dependencies = [ [[package]] name = "mumd" -version = "0.1.0" +version = "0.2.0" dependencies = [ "argparse", "bytes", @@ -776,7 +776,7 @@ dependencies = [ [[package]] name = "mumlib" -version = "0.1.0" +version = "0.2.0" dependencies = [ "colored", "fern", diff --git a/changelog/0.2.txt b/changelog/0.2.txt new file mode 100644 index 0000000..d7f7200 --- /dev/null +++ b/changelog/0.2.txt @@ -0,0 +1,44 @@ +778ea0b 0.2 version bump +768fc7c Merge branch command-alias into main (eskil) +ee46fd5 Merge branch config-home into main (eskil) +cd3c1ad Merge branch tcp-event-macro into main (eskil) +64eca3b Merge branch readme into main (gustav) +161f58f Merge branch refactor-state into main (gustav) +92d64a4 Merge branch network-rework into main (gustav) +b268bec Merge branch refactor-audio into main (gustav) +685eb0e Merge branch audio-new-clients into main (gustav) +ff6103c Merge branch lock-cpal into main (gustav) +34bf730 Merge branch getters into main (gustav) +d58c2aa Merge branch config-file into main (gustav) +d688a68 Merge branch port-configuration into main (eskil) +cf25e78 Merge branch file-logging into main (eskil) +f30b372 Merge branch socket into main (eskil) +ccc5f76 Merge branch pretty-print into main (eskil) +7675171 Merge branch channel-name into main (eskil) +4e8402c Merge branch input-volume into main (gustav) +27d8b16 Merge branch error-handling into main (eskil) +18a3c0b Merge branch cli into main (gustav) +8e4eb0a Merge branch audio-refactor into main (eskil) +a40d365 Merge branch commands into main (eskil) +dd8ebae initial commit + +git diff --stat dd8ebae..v0.2 --stat=80 -- **/*.rs + mumctl/src/main.rs | 450 ++++++++++++++++++++++++++++++++++++++++++++++ + mumd/src/audio.rs | 194 ++++++++++++++++++++ + mumd/src/audio/input.rs | 52 ++++++ + mumd/src/audio/output.rs | 90 ++++++++++ + mumd/src/command.rs | 38 ++++ + mumd/src/main.rs | 92 ++++++++++ + mumd/src/network.rs | 21 +++ + mumd/src/network/tcp.rs | 370 ++++++++++++++++++++++++++++++++++++++ + mumd/src/network/udp.rs | 227 +++++++++++++++++++++++ + mumd/src/state.rs | 287 +++++++++++++++++++++++++++++ + mumd/src/state/channel.rs | 184 +++++++++++++++++++ + mumd/src/state/server.rs | 123 +++++++++++++ + mumd/src/state/user.rs | 145 +++++++++++++++ + mumlib/src/command.rs | 28 +++ + mumlib/src/config.rs | 144 +++++++++++++++ + mumlib/src/error.rs | 40 +++++ + mumlib/src/lib.rs | 49 +++++ + mumlib/src/state.rs | 200 +++++++++++++++++++++ + 18 files changed, 2734 insertions(+) diff --git a/mumctl/Cargo.toml b/mumctl/Cargo.toml index c955afa..8483042 100644 --- a/mumctl/Cargo.toml +++ b/mumctl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mumctl" -version = "0.1.0" +version = "0.2.0" authors = ["Gustav Sörnäs <gustav@sornas.net>", "Eskil Queseth <eskilq@kth.se>"] license = "MIT" diff --git a/mumctl/src/main.rs b/mumctl/src/main.rs index 7f74077..77340c0 100644 --- a/mumctl/src/main.rs +++ b/mumctl/src/main.rs @@ -7,6 +7,7 @@ use mumlib::config::ServerConfig; use mumlib::setup_logger; use mumlib::state::Channel; use std::{fs, io, iter}; +use std::io::BufRead; const INDENTATION: &str = " "; @@ -21,9 +22,6 @@ macro_rules! err_print { fn main() { setup_logger(io::stderr(), true); let mut config = config::read_default_cfg(); - if config.is_none() { - println!("{} unable to find config file", "error:".red()); - } let mut app = App::new("mumctl") .setting(AppSettings::ArgRequiredElseHelp) @@ -33,7 +31,7 @@ fn main() { .subcommand( SubCommand::with_name("connect") .arg(Arg::with_name("host").required(true)) - .arg(Arg::with_name("username").required(true)) + .arg(Arg::with_name("username")) .arg(Arg::with_name("port") .long("port") .short("p") @@ -42,7 +40,7 @@ fn main() { SubCommand::with_name("disconnect")) .subcommand( SubCommand::with_name("config") - .arg(Arg::with_name("server_name").required(true)) + .arg(Arg::with_name("server_name")) .arg(Arg::with_name("var_name")) .arg(Arg::with_name("var_value"))) .subcommand( @@ -97,25 +95,17 @@ fn main() { if let Some(matches) = matches.subcommand_matches("server") { if let Some(matches) = matches.subcommand_matches("connect") { - match_server_connect(matches); + match_server_connect(matches, &config); } else if let Some(_) = matches.subcommand_matches("disconnect") { err_print!(send_command(Command::ServerDisconnect)); } else if let Some(matches) = matches.subcommand_matches("config") { - if let Some(config) = &mut config { - match_server_config(matches, config); - } + match_server_config(matches, &mut config); } else if let Some(matches) = matches.subcommand_matches("rename") { - if let Some(config) = &mut config { - match_server_rename(matches, config); - } + match_server_rename(matches, &mut config); } else if let Some(matches) = matches.subcommand_matches("remove") { - if let Some(config) = &mut config { - match_server_remove(matches, config); - } + match_server_remove(matches, &mut config); } else if let Some(matches) = matches.subcommand_matches("add") { - if let Some(config) = &mut config { - match_server_add(matches, config); - } + match_server_add(matches, &mut config); } } else if let Some(matches) = matches.subcommand_matches("channel") { if let Some(_matches) = matches.subcommand_matches("list") { @@ -172,26 +162,67 @@ fn main() { }; if let Some(config) = config { - config.write_default_cfg().unwrap(); + if !config::cfg_exists() { + println!("Config file not found. Create one in {}? [Y/n]", config::get_creatable_cfg_path()); + let stdin = std::io::stdin(); + let response = stdin.lock().lines().next(); + match response.map(|e| e.map(|e| &e == "Y")) { + Some(Ok(true)) => { + config.write_default_cfg(true).unwrap(); + } + _ => {}, + } + } else { + config.write_default_cfg(false).unwrap(); + } } } -fn match_server_connect(matches : &clap::ArgMatches<'_>) { +fn match_server_connect(matches : &clap::ArgMatches<'_>, config: &Option<mumlib::config::Config>) { let host = matches.value_of("host").unwrap(); - let username = matches.value_of("username").unwrap(); + let username = matches.value_of("username"); let port = match matches.value_of("port").map(|e| e.parse()) { None => Some(64738), Some(Err(_)) => None, Some(Ok(v)) => Some(v), }; if let Some(port) = port { - match send_command(Command::ServerConnect { - host: host.to_string(), - port, - username: username.to_string(), - accept_invalid_cert: true, //TODO - }) { - Ok(e) => { + let response = match config + .as_ref() + .and_then(|e| e.servers + .as_ref() + .and_then(|e| e.iter() + .find(|e| e.name == host))) { + Some(config) => { + let host = config.host.as_str(); + let port = config.port.unwrap_or(port); + let username = config.username.as_ref().map(|e| e.as_str()).or(username); + if username.is_none() { + println!("{} no username specified", "error:".red()); + return; + } + send_command(Command::ServerConnect { + host: host.to_string(), + port, + username: username.unwrap().to_string(), + accept_invalid_cert: true, //TODO + }).map(|e| (e, host)) + } + None => { + if username.is_none() { + println!("{} no username specified", "error:".red()); + return + } + send_command(Command::ServerConnect { + host: host.to_string(), + port, + username: username.unwrap().to_string(), + accept_invalid_cert: true, //TODO + }).map(|e| (e, host)) + } + }; + match response { + Ok((e, host)) => { if let Some(CommandResponse::ServerConnect { welcome_message }) = e { println!("Connected to {}", host); if let Some(message) = welcome_message { @@ -206,65 +237,83 @@ fn match_server_connect(matches : &clap::ArgMatches<'_>) { } } -fn match_server_config(matches: &clap::ArgMatches<'_>, config: &mut mumlib::config::Config) { - let server_name = matches.value_of("server_name").unwrap(); - if let Some(servers) = &mut config.servers { - let server = servers - .iter_mut() - .find(|s| s.name == server_name); - if let Some(server) = server { - if let Some(var_name) = matches.value_of("var_name") { - if let Some(var_value) = matches.value_of("var_value") { - // save var_value in var_name (if it is valid) - match var_name { - "name" => { - println!("{} use mumctl server rename instead!", "error:".red()); - }, - "host" => { - server.host = var_value.to_string(); - }, - "port" => { - server.port = Some(var_value.parse().unwrap()); - }, - "username" => { - server.username = Some(var_value.to_string()); - }, - "password" => { - server.password = Some(var_value.to_string()); //TODO ask stdin if empty - }, - _ => { - println!("{} variable {} not found", "error:".red(), var_name); - }, - }; - } else { // var_value is None - // print value of var_name - println!("{}", match var_name { - "name" => { server.name.to_string() }, - "host" => { server.host.to_string() }, - "port" => { server.port.map(|s| s.to_string()).unwrap_or(format!("{} not set", "error:".red())) }, - "username" => { server.username.as_ref().map(|s| s.to_string()).unwrap_or(format!("{} not set", "error:".red())) }, - "password" => { server.password.as_ref().map(|s| s.to_string()).unwrap_or(format!("{} not set", "error:".red())) }, - _ => { format!("{} unknown variable", "error:".red()) }, - }); +fn match_server_config(matches: &clap::ArgMatches<'_>, config: &mut Option<mumlib::config::Config>) { + if config.is_none() { + *config = Some(mumlib::config::Config::default()); + } + + let config = config.as_mut().unwrap(); + + if let Some(server_name) = matches.value_of("server_name") { + if let Some(servers) = &mut config.servers { + let server = servers + .iter_mut() + .find(|s| s.name == server_name); + if let Some(server) = server { + if let Some(var_name) = matches.value_of("var_name") { + if let Some(var_value) = matches.value_of("var_value") { + // save var_value in var_name (if it is valid) + match var_name { + "name" => { + println!("{} use mumctl server rename instead!", "error:".red()); + } + "host" => { + server.host = var_value.to_string(); + } + "port" => { + server.port = Some(var_value.parse().unwrap()); + } + "username" => { + server.username = Some(var_value.to_string()); + } + "password" => { + server.password = Some(var_value.to_string()); //TODO ask stdin if empty + } + _ => { + println!("{} variable {} not found", "error:".red(), var_name); + } + }; + } else { // var_value is None + // print value of var_name + println!("{}", match var_name { + "name" => { server.name.to_string() } + "host" => { server.host.to_string() } + "port" => { server.port.map(|s| s.to_string()).unwrap_or(format!("{} not set", "error:".red())) } + "username" => { server.username.as_ref().map(|s| s.to_string()).unwrap_or(format!("{} not set", "error:".red())) } + "password" => { server.password.as_ref().map(|s| s.to_string()).unwrap_or(format!("{} not set", "error:".red())) } + _ => { format!("{} unknown variable", "error:".red()) } + }); + } + } else { // var_name is None + // print server config + print!("{}{}{}{}", + format!("host: {}\n", server.host.to_string()), + server.port.map(|s| format!("port: {}\n", s)).unwrap_or("".to_string()), + server.username.as_ref().map(|s| format!("username: {}\n", s)).unwrap_or("".to_string()), + server.password.as_ref().map(|s| format!("password: {}\n", s)).unwrap_or("".to_string()), + ) } - } else { // var_name is None - // print server config - print!("{}{}{}{}", - format!("host: {}\n", server.host.to_string()), - server.port.map(|s| format!("port: {}\n", s)).unwrap_or("".to_string()), - server.username.as_ref().map(|s| format!("username: {}\n", s)).unwrap_or("".to_string()), - server.password.as_ref().map(|s| format!("password: {}\n", s)).unwrap_or("".to_string()), - ) + } else { // server is None + println!("{} server {} not found", "error:".red(), server_name); } - } else { // server is None - println!("{} server {} not found", "error:".red(), server_name); + } else { // servers is None + println!("{} no servers found in configuration", "error:".red()); + } + } else { + for server in config.servers.iter().flat_map(|e| e.iter()) { + println!("{}", server.name); } - } else { // servers is None - println!("{} no servers found in configuration", "error:".red()); } } -fn match_server_rename(matches: &clap::ArgMatches<'_>, config: &mut mumlib::config::Config) { +fn match_server_rename(matches: &clap::ArgMatches<'_>, config: &mut Option<mumlib::config::Config>) { + if config.is_none() { + *config = Some(mumlib::config::Config::default()); + } + + let config = config.as_mut().unwrap(); + + if let Some(servers) = &mut config.servers { let prev_name = matches.value_of("prev_name").unwrap(); let next_name = matches.value_of("next_name").unwrap(); @@ -278,7 +327,13 @@ fn match_server_rename(matches: &clap::ArgMatches<'_>, config: &mut mumlib::conf } } -fn match_server_remove(matches: &clap::ArgMatches<'_>, config: &mut mumlib::config::Config) { +fn match_server_remove(matches: &clap::ArgMatches<'_>, config: &mut Option<mumlib::config::Config>) { + if config.is_none() { + *config = Some(mumlib::config::Config::default()); + } + + let config = config.as_mut().unwrap(); + let name = matches.value_of("name").unwrap(); if let Some(servers) = &mut config.servers { match servers.iter().position(|server| server.name == name) { @@ -294,7 +349,13 @@ fn match_server_remove(matches: &clap::ArgMatches<'_>, config: &mut mumlib::conf } } -fn match_server_add(matches: &clap::ArgMatches<'_>, config: &mut mumlib::config::Config) { +fn match_server_add(matches: &clap::ArgMatches<'_>, config: &mut Option<mumlib::config::Config>) { + if config.is_none() { + *config = Some(mumlib::config::Config::default()); + } + + let mut config = config.as_mut().unwrap(); + let name = matches.value_of("name").unwrap().to_string(); let host = matches.value_of("host").unwrap().to_string(); // optional arguments map None to None diff --git a/mumd/Cargo.toml b/mumd/Cargo.toml index c59c32b..350d81e 100644 --- a/mumd/Cargo.toml +++ b/mumd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mumd" -version = "0.1.0" +version = "0.2.0" authors = ["Gustav Sörnäs <gustav@sornas.net>", "Eskil Queseth <eskilq@kth.se>"] license = "MIT" diff --git a/mumd/src/audio.rs b/mumd/src/audio.rs index 8609a91..7a673ff 100644 --- a/mumd/src/audio.rs +++ b/mumd/src/audio.rs @@ -24,30 +24,40 @@ pub struct Audio { impl Audio { pub fn new() -> Self { + let sample_rate = SampleRate(48000); + let host = cpal::default_host(); let output_device = host .default_output_device() .expect("default output device not found"); - let mut output_supported_configs_range = output_device + let output_supported_config = output_device .supported_output_configs() - .expect("error querying output configs"); - let output_supported_config = output_supported_configs_range - .next() - .expect("no supported output config??") - .with_sample_rate(SampleRate(48000)); + .expect("error querying output configs") + .find_map(|c| + if c.min_sample_rate() <= sample_rate && c.max_sample_rate() >= sample_rate { + Some(c) + } else { + None + }) + .unwrap() + .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"); - let mut input_supported_configs_range = input_device + let input_supported_config = input_device .supported_input_configs() - .expect("error querying input configs"); - let input_supported_config = input_supported_configs_range - .next() - .expect("no supported input config??") - .with_sample_rate(SampleRate(48000)); + .expect("error querying output configs") + .find_map(|c| + if c.min_sample_rate() <= sample_rate && c.max_sample_rate() >= sample_rate { + Some(c) + } else { + None + }) + .unwrap() + .with_sample_rate(sample_rate); let input_supported_sample_format = input_supported_config.sample_format(); let input_config: StreamConfig = input_supported_config.into(); diff --git a/mumlib/Cargo.toml b/mumlib/Cargo.toml index 471a1fe..59feb75 100644 --- a/mumlib/Cargo.toml +++ b/mumlib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mumlib" -version = "0.1.0" +version = "0.2.0" authors = ["Gustav Sörnäs <gustav@sornas.net>", "Eskil Queseth <eskilq@kth.se>"] edition = "2018" diff --git a/mumlib/src/config.rs b/mumlib/src/config.rs index aa8a8ed..5c37a2b 100644 --- a/mumlib/src/config.rs +++ b/mumlib/src/config.rs @@ -1,9 +1,9 @@ -use log::*; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use std::fs; use toml::Value; use toml::value::Array; +use std::path::Path; #[derive(Debug, Deserialize, Serialize)] struct TOMLConfig { @@ -11,15 +11,15 @@ struct TOMLConfig { servers: Option<Array>, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct Config { pub audio: Option<AudioConfig>, pub servers: Option<Vec<ServerConfig>>, } impl Config { - pub fn write_default_cfg(&self) -> Result<(), std::io::Error> { - let path = get_cfg_path(); + pub fn write_default_cfg(&self, create: bool) -> Result<(), std::io::Error> { + let path = if create { get_creatable_cfg_path() } else { get_cfg_path() }; let path = std::path::Path::new(&path); // Possible race here. It's fine since it shows when: // 1) the file doesn't exist when checked and is then created @@ -29,12 +29,11 @@ impl Config { // should work. Unless the file is removed AND the permissions // change, but then we don't have permissions so we can't // do anything anyways. - if !path.exists() { - warn!("config file {} does not exist, ignoring", path.display()); - Ok(()) - } else { - fs::write(path, toml::to_string(&TOMLConfig::from(self.clone())).unwrap()) + if !create && !path.exists() { + return Ok(()); } + + fs::write(path, toml::to_string(&TOMLConfig::from(self.clone())).unwrap()) } } @@ -52,8 +51,54 @@ pub struct ServerConfig { pub password: Option<String>, } -fn get_cfg_path() -> String { - ".mumdrc".to_string() //TODO XDG_CONFIG and whatever +pub fn get_cfg_path() -> String { + if let Ok(var) = std::env::var("XDG_CONFIG_HOME") { + let path = format!("{}/mumdrc", var); + if Path::new(&path).exists() { + return path; + } + } else if let Ok(var) = std::env::var("HOME") { + let path = format!("{}/.config/mumdrc", var); + if Path::new(&path).exists() { + return path; + } + } + + "/etc/mumdrc".to_string() +} + +pub fn get_creatable_cfg_path() -> String { + if let Ok(var) = std::env::var("XDG_CONFIG_HOME") { + let path = format!("{}/mumdrc", var); + if !Path::new(&path).exists() { + return path; + } + } else if let Ok(var) = std::env::var("HOME") { + let path = format!("{}/.config/mumdrc", var); + if !Path::new(&path).exists() { + return path; + } + } + + "/etc/mumdrc".to_string() +} + +pub fn cfg_exists() -> bool { + if let Ok(var) = std::env::var("XDG_CONFIG_HOME") { + let path = format!("{}/mumdrc", var); + if Path::new(&path).exists() { + return true; + } + } else if let Ok(var) = std::env::var("HOME") { + let path = format!("{}/.config/mumdrc", var); + if Path::new(&path).exists() { + return true; + } + } else if Path::new("/etc/mumdrc").exists() { + return true; + } + + false } impl TryFrom<TOMLConfig> for Config { |
