diff --git a/src/config.rs b/src/config.rs index 0a4d237..6542839 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,13 @@ use crate::{ - constants::CMD_NAME, device_prober::get_xr_usb_devices, file_utils::get_writer, - paths::get_config_dir, profile::Profile, + constants::CMD_NAME, + device_prober::get_xr_usb_devices, + file_utils::get_writer, + paths::get_config_dir, + profile::Profile, + profiles::{ + lighthouse::lighthouse_profile, openhmd::openhmd_profile, simulated::simulated_profile, + survive::survive_profile, wivrn::wivrn_profile, wmr::wmr_profile, + }, }; use serde::{Deserialize, Serialize}; use std::{fs::File, io::BufReader}; @@ -87,6 +94,20 @@ impl Config { pub fn set_profiles(&mut self, profiles: &[Profile]) { self.user_profiles = profiles.iter().filter(|p| p.editable).cloned().collect(); } + + pub fn profiles(&self) -> Vec { + let mut profiles = vec![ + lighthouse_profile(), + survive_profile(), + wivrn_profile(), + wmr_profile(), + openhmd_profile(), + simulated_profile(), + ]; + profiles.extend(self.user_profiles.clone()); + profiles.sort_unstable_by(|a, b| a.name.cmp(&b.name)); + profiles + } } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index 78ab24d..5b34f7f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -100,6 +100,9 @@ fn main() -> Result<()> { CmdLineOpts::init(&main_app); let sender = BROKER.sender(); main_app.connect_command_line(move |this, cmdline| { + if CmdLineOpts::handle_non_activating_opts(cmdline) { + return 0; + } this.activate(); sender.emit(Msg::HandleCommandLine(CmdLineOpts::from_cmdline(cmdline))); 0 diff --git a/src/ui/app.rs b/src/ui/app.rs index 5077c98..0e50ccd 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -38,12 +38,6 @@ use crate::linux_distro::LinuxDistro; use crate::log_parser::MonadoLog; use crate::paths::{get_data_dir, get_ipc_file_path}; use crate::profile::{Profile, XRServiceType}; -use crate::profiles::lighthouse::lighthouse_profile; -use crate::profiles::openhmd::openhmd_profile; -use crate::profiles::simulated::simulated_profile; -use crate::profiles::survive::survive_profile; -use crate::profiles::wivrn::wivrn_profile; -use crate::profiles::wmr::wmr_profile; use crate::stateless_action; use crate::ui::build_window::{BuildWindowMsg, BuildWindowOutMsg}; use crate::ui::debug_view::{DebugViewInit, DebugViewOutMsg}; @@ -277,20 +271,6 @@ impl App { .emit(DebugViewMsg::XRServiceActiveChanged(false)); self.xr_devices = vec![]; } - - pub fn profiles_list(config: &Config) -> Vec { - let mut profiles = vec![ - lighthouse_profile(), - survive_profile(), - wivrn_profile(), - wmr_profile(), - openhmd_profile(), - simulated_profile(), - ]; - profiles.extend(config.user_profiles.clone()); - profiles.sort_unstable_by(|a, b| a.name.cmp(&b.name)); - profiles - } } #[derive(Debug)] @@ -637,7 +617,7 @@ impl SimpleComponent for App { if todel.editable { self.config.user_profiles.retain(|p| p.uuid != todel.uuid); self.config.save(); - self.profiles = Self::profiles_list(&self.config); + self.profiles = self.config.profiles(); self.main_view .sender() .emit(MainViewMsg::UpdateSelectedProfile( @@ -739,6 +719,15 @@ impl SimpleComponent for App { self.wivrn_conf_editor = Some(editor); } Msg::HandleCommandLine(opts) => { + if let Some(prof_uuid) = opts.profile_uuid { + if let Some(index) = self.profiles.iter().position(|p| p.uuid == prof_uuid) { + let target = self.profiles.get(index).unwrap(); + sender.input(Msg::ProfileSelected(target.clone())); + self.main_view + .sender() + .emit(MainViewMsg::SetSelectedProfile(index as u32)); + } + } if opts.start { sender.input(Msg::DoStartStopXRService) } @@ -753,7 +742,7 @@ impl SimpleComponent for App { ) -> ComponentParts { let config = Config::get_config(); let win_size = config.win_size; - let profiles = Self::profiles_list(&config); + let profiles = config.profiles(); let setcap_confirm_dialog = adw::MessageDialog::builder() .modal(true) .transient_for(root) diff --git a/src/ui/cmdline_opts.rs b/src/ui/cmdline_opts.rs index c253fed..c7ccd7b 100644 --- a/src/ui/cmdline_opts.rs +++ b/src/ui/cmdline_opts.rs @@ -1,29 +1,72 @@ +use crate::config::Config; use gtk4::{ - gio::{prelude::ApplicationExt, Application, ApplicationCommandLine}, + gio::{ + prelude::{ApplicationCommandLineExt, ApplicationExt}, + Application, ApplicationCommandLine, + }, glib::{self, IsA}, }; -use zoha_vte4::ApplicationCommandLineExt; #[derive(Debug, Clone)] pub struct CmdLineOpts { pub start: bool, + pub profile_uuid: Option, } impl CmdLineOpts { + const OPT_START: (&'static str, char) = ("start", 'S'); + const OPT_LIST_PROFILES: (&'static str, char) = ("list-profiles", 'l'); + const OPT_PROFILE: (&'static str, char) = ("profile", 'p'); + pub fn init(app: &impl IsA) { app.add_main_option( - "start", - glib::Char::try_from('S').unwrap(), + Self::OPT_START.0, + glib::Char::try_from(Self::OPT_START.1).unwrap(), glib::OptionFlags::IN_MAIN, glib::OptionArg::None, "Start the XR Service right away", None, ); + app.add_main_option( + Self::OPT_LIST_PROFILES.0, + glib::Char::try_from(Self::OPT_LIST_PROFILES.1).unwrap(), + glib::OptionFlags::IN_MAIN, + glib::OptionArg::None, + "List the available profiles", + None, + ); + app.add_main_option( + Self::OPT_PROFILE.0, + glib::Char::try_from(Self::OPT_PROFILE.1).unwrap(), + glib::OptionFlags::IN_MAIN, + glib::OptionArg::String, + "Switch to the profile indicated by the UUID", + None, + ); + } + + /// returns true if the application should quit + pub fn handle_non_activating_opts(cmdline: &ApplicationCommandLine) -> bool { + if cmdline.options_dict().contains(Self::OPT_LIST_PROFILES.0) { + println!("Available profiles\nUUID: \"name\""); + let profiles = Config::get_config().profiles(); + profiles.iter().for_each(|p| { + println!("{}: \"{}\"", p.uuid, p.name); + }); + return true; + } + false } pub fn from_cmdline(cmdline: &ApplicationCommandLine) -> Self { + let opts = cmdline.options_dict(); Self { - start: cmdline.options_dict().contains("start"), + start: opts.contains(Self::OPT_START.0), + profile_uuid: match opts.lookup::(Self::OPT_PROFILE.0) { + Err(_) => None, + Ok(None) => None, + Ok(Some(variant)) => Some(variant), + }, } } }