From 3621a22fd1ff7d50a4f4814d41d7871f237b8d66 Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Thu, 29 Jun 2023 18:19:07 +0200 Subject: [PATCH] feat: prototype wivrn config editor --- src/ui/mod.rs | 1 + src/ui/wivrn_conf_editor.rs | 185 ++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 src/ui/wivrn_conf_editor.rs diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 5daa97f..f721cc1 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -9,3 +9,4 @@ pub mod steam_launch_options_box; pub mod runtime_switcher_box; pub mod profile_editor; pub mod factories; +pub mod wivrn_conf_editor; diff --git a/src/ui/wivrn_conf_editor.rs b/src/ui/wivrn_conf_editor.rs new file mode 100644 index 0000000..cd8f7c5 --- /dev/null +++ b/src/ui/wivrn_conf_editor.rs @@ -0,0 +1,185 @@ +use crate::file_builders::wivrn_config::{dump_wivrn_config, get_wivrn_config, WivrnConfig, Encoder}; +use adw::prelude::*; +use gtk::prelude::*; +use relm4::{factory::FactoryVecDeque, prelude::*}; + +#[tracker::track] +pub struct WivrnConfEditor { + conf: WivrnConfig, + #[tracker::do_not_track] + win: Option, + #[tracker::do_not_track] + scalex_entry: Option, + #[tracker::do_not_track] + scaley_entry: Option, + #[tracker::do_not_track] + encoder_combo: Option, + #[tracker::do_not_track] + bitrate_entry: Option, +} + +#[derive(Debug)] +pub enum WivrnConfEditorMsg { + Present, + Save, +} + +pub struct WivrnConfEditorInit { + pub root_win: gtk::Window, +} + +#[relm4::component(pub)] +impl SimpleComponent for WivrnConfEditor { + type Init = WivrnConfEditorInit; + type Input = WivrnConfEditorMsg; + type Output = (); + + view! { + #[name(win)] + adw::PreferencesWindow { + set_hide_on_close: true, + set_modal: true, + set_transient_for: Some(&init.root_win), + set_title: Some("WiVRn Configuration"), + add: mainpage = &adw::PreferencesPage { + add: scalegrp = &adw::PreferencesGroup { + set_title: "Scale", + set_description: Some("Render resolution scale. 1.0 is 100%."), + #[name(scalex_entry)] + adw::EntryRow { + set_title: "Scale X", + #[track = "model.changed(Self::conf())"] + set_text: match model.conf.scale { + Some([x, _]) => x.to_string(), + None => "".to_string(), + }.as_str(), + set_input_purpose: gtk::InputPurpose::Number, + }, + #[name(scaley_entry)] + adw::EntryRow { + set_title: "Scale Y", + #[track = "model.changed(Self::conf())"] + set_text: match model.conf.scale { + Some([_, y]) => y.to_string(), + None => "".to_string(), + }.as_str(), + set_input_purpose: gtk::InputPurpose::Number, + }, + }, + add: encgrp = &adw::PreferencesGroup { + set_title: "Encoder", + #[name(encoder_combo)] + adw::ComboRow { + set_title: "Encoder", + set_subtitle: "x264: CPU based h264 encoding\n\nNVEnc: Nvidia GPU encoding\n\nVAAPI: Intel or AMD GPU encoding", + set_model: Some(>k::StringList::new( + Encoder::iter() + .map(Encoder::to_string) + .collect::>() + .iter() + .map(String::as_str) + .collect::>() + .as_slice() + )), + #[track = "model.changed(Self::conf())"] + set_selected: model.conf.encoders.get(0).unwrap().encoder.as_number(), + }, + #[name(bitrate_entry)] + adw::EntryRow { + set_title: "Bitrate", + #[track = "model.changed(Self::conf())"] + set_text: match model.conf.encoders.get(0).unwrap().bitrate { + Some(br) => br.to_string(), + None => "".to_string() + }.as_str(), + set_input_purpose: gtk::InputPurpose::Number, + }, + }, + add: save_grp = &adw::PreferencesGroup { + add: save_box = >k::Box { + set_orientation: gtk::Orientation::Vertical, + set_hexpand: true, + gtk::Button { + set_halign: gtk::Align::Center, + set_label: "Save", + add_css_class: "pill", + add_css_class: "suggested-action", + connect_clicked[sender] => move |_| { + sender.input(Self::Input::Save); + }, + }, + } + }, + }, + } + } + + fn update(&mut self, message: Self::Input, sender: ComponentSender) { + self.reset(); + + match message { + Self::Input::Present => { + self.set_conf(get_wivrn_config()); + self.win.as_ref().unwrap().present(); + } + Self::Input::Save => { + let scalex = self.scalex_entry.as_ref().unwrap().text().parse::(); + let scaley = self.scaley_entry.as_ref().unwrap().text().parse::(); + if scalex.is_ok() && scaley.is_ok() { + self.conf.scale = Some([scalex.as_ref().unwrap().clone(), scaley.as_ref().unwrap().clone()]); + } + if scalex.is_ok() || scaley.is_ok() { + let scale = scalex.unwrap_or(scaley.unwrap()); + self.conf.scale = Some([scale, scale]); + } + else { + self.conf.scale = None + } + + let mut enc = self.conf.encoders.remove(0); + let bitrate = self.bitrate_entry.as_ref().unwrap().text().parse::(); + if bitrate.is_ok() { + enc.bitrate = Some(bitrate.unwrap()); + } + let encoders = Encoder::as_vec(); + let encoder = encoders.get( + self.encoder_combo.as_ref().unwrap().selected() as usize + ); + if encoder.is_some() { + enc.encoder = encoder.unwrap().clone(); + } + self.conf.encoders.insert(0, enc); + + + dump_wivrn_config(&self.conf); + self.win.as_ref().unwrap().close(); + } + } + } + + fn init( + init: Self::Init, + root: &Self::Root, + sender: ComponentSender, + ) -> ComponentParts { + let mut model = Self { + conf: get_wivrn_config(), + win: None, + scalex_entry: None, + scaley_entry: None, + bitrate_entry: None, + encoder_combo: None, + tracker: 0, + }; + + let widgets = view_output!(); + + model.win = Some(widgets.win.clone()); + model.scalex_entry = Some(widgets.scalex_entry.clone()); + model.scaley_entry = Some(widgets.scaley_entry.clone()); + model.bitrate_entry = Some(widgets.bitrate_entry.clone()); + model.encoder_combo = Some(widgets.encoder_combo.clone()); + + ComponentParts { model, widgets } + } +}