mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-04-20 19:44:50 +00:00
feat: wivrn config editor
This commit is contained in:
parent
1ace5564de
commit
afd51184ef
6 changed files with 372 additions and 105 deletions
|
@ -9,6 +9,7 @@ use super::job_worker::JobWorker;
|
|||
use super::libsurvive_setup_window::LibsurviveSetupWindow;
|
||||
use super::main_view::MainViewMsg;
|
||||
use super::util::open_with_default_handler;
|
||||
use super::wivrn_conf_editor::{WivrnConfEditor, WivrnConfEditorInit, WivrnConfEditorMsg};
|
||||
use crate::builders::build_basalt::get_build_basalt_jobs;
|
||||
use crate::builders::build_libsurvive::get_build_libsurvive_jobs;
|
||||
use crate::builders::build_mercury::get_build_mercury_job;
|
||||
|
@ -102,6 +103,9 @@ pub struct App {
|
|||
fbt_config_editor: Option<Controller<FbtConfigEditor>>,
|
||||
#[tracker::do_not_track]
|
||||
libmonado: Option<libmonado_rs::Monado>,
|
||||
|
||||
#[tracker::do_not_track]
|
||||
wivrn_conf_editor: Option<Controller<WivrnConfEditor>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -128,6 +132,7 @@ pub enum Msg {
|
|||
ConfigFbt,
|
||||
DebugOpenPrefix,
|
||||
DebugOpenData,
|
||||
OpenWivrnConfig,
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
@ -632,6 +637,15 @@ impl SimpleComponent for App {
|
|||
self.get_selected_profile().prefix
|
||||
));
|
||||
}
|
||||
Msg::OpenWivrnConfig => {
|
||||
let editor = WivrnConfEditor::builder()
|
||||
.launch(WivrnConfEditorInit {
|
||||
root_win: self.app_win.clone().upcast::<gtk::Window>(),
|
||||
})
|
||||
.detach();
|
||||
editor.emit(WivrnConfEditorMsg::Present);
|
||||
self.wivrn_conf_editor = Some(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,6 +683,7 @@ impl SimpleComponent for App {
|
|||
}
|
||||
|
||||
let mut model = App {
|
||||
tracker: 0,
|
||||
application: init.application,
|
||||
app_win: root.clone(),
|
||||
inhibit_id: None,
|
||||
|
@ -687,6 +702,7 @@ impl SimpleComponent for App {
|
|||
MainViewOutMsg::DeleteProfile => Msg::DeleteProfile,
|
||||
MainViewOutMsg::SaveProfile(p) => Msg::SaveProfile(p),
|
||||
MainViewOutMsg::OpenLibsurviveSetup => Msg::OpenLibsurviveSetup,
|
||||
MainViewOutMsg::OpenWivrnConfig => Msg::OpenWivrnConfig,
|
||||
}),
|
||||
debug_view: DebugView::builder().launch(DebugViewInit {}).forward(
|
||||
sender.input_sender(),
|
||||
|
@ -712,7 +728,6 @@ impl SimpleComponent for App {
|
|||
setcap_confirm_dialog,
|
||||
enable_debug_view: config.debug_view_enabled,
|
||||
config,
|
||||
tracker: 0,
|
||||
profiles,
|
||||
xrservice_worker: None,
|
||||
build_worker: None,
|
||||
|
@ -720,6 +735,7 @@ impl SimpleComponent for App {
|
|||
fbt_config_editor: None,
|
||||
restart_xrservice: false,
|
||||
libmonado: None,
|
||||
wivrn_conf_editor: None,
|
||||
};
|
||||
let widgets = view_output!();
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod device_row_factory;
|
||||
pub mod env_var_row_factory;
|
||||
pub mod tracker_role_group_factory;
|
||||
pub mod wivrn_encoder_group_factory;
|
||||
|
|
196
src/ui/factories/wivrn_encoder_group_factory.rs
Normal file
196
src/ui/factories/wivrn_encoder_group_factory.rs
Normal file
|
@ -0,0 +1,196 @@
|
|||
use crate::{
|
||||
file_builders::wivrn_config::{Codec, Encoder, WivrnConfEncoder},
|
||||
ui::{
|
||||
preference_rows::{combo_row, number_entry_row, spin_row},
|
||||
wivrn_conf_editor::WivrnConfEditorMsg,
|
||||
},
|
||||
};
|
||||
use relm4::{
|
||||
adw::prelude::*, factory::AsyncFactoryComponent, gtk::prelude::*, prelude::*,
|
||||
AsyncFactorySender,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WivrnEncoderModel {
|
||||
pub encoder_conf: WivrnConfEncoder,
|
||||
pub uid: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WivrnEncoderModelMsg {
|
||||
EncoderChanged(u32),
|
||||
CodecChanged(u32),
|
||||
BitrateChanged(Option<u32>),
|
||||
WidthChanged(Option<f32>),
|
||||
HeightChanged(Option<f32>),
|
||||
GroupChanged(Option<i32>),
|
||||
Delete,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WivrnEncoderModelOutMsg {
|
||||
Delete(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WivrnEncoderModelInit {
|
||||
pub encoder_conf: Option<WivrnConfEncoder>,
|
||||
}
|
||||
|
||||
#[relm4::factory(async pub)]
|
||||
impl AsyncFactoryComponent for WivrnEncoderModel {
|
||||
type Init = WivrnEncoderModelInit;
|
||||
type Input = WivrnEncoderModelMsg;
|
||||
type Output = WivrnEncoderModelOutMsg;
|
||||
type CommandOutput = ();
|
||||
type ParentInput = WivrnConfEditorMsg;
|
||||
type ParentWidget = adw::PreferencesPage;
|
||||
|
||||
view! {
|
||||
root = adw::PreferencesGroup {
|
||||
set_title: "Encoder",
|
||||
#[wrap(Some)]
|
||||
set_header_suffix: delete_btn = >k::Button {
|
||||
set_label: "Delete",
|
||||
add_css_class: "destructive-action",
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.input(Self::Input::Delete)
|
||||
},
|
||||
},
|
||||
add: encoder_combo = &combo_row(
|
||||
"Encoder",
|
||||
Some("x264: CPU based h264 encoding\nNVEnc: Nvidia GPU encoding\nVAAPI: Intel or AMD GPU encoding"),
|
||||
&self.encoder_conf.encoder.to_string(),
|
||||
Encoder::iter().map(Encoder::to_string).collect::<Vec<String>>(),
|
||||
{
|
||||
let sender = sender.clone();
|
||||
move |row| {
|
||||
sender.input(Self::Input::EncoderChanged(row.selected()));
|
||||
}
|
||||
}
|
||||
) -> adw::ComboRow,
|
||||
add: codec_combo = &combo_row(
|
||||
"Codec",
|
||||
None,
|
||||
&self.encoder_conf.codec.to_string(),
|
||||
Codec::iter().map(Codec::to_string).collect::<Vec<String>>(),
|
||||
{
|
||||
let sender = sender.clone();
|
||||
move |row| {
|
||||
sender.input(Self::Input::CodecChanged(row.selected()));
|
||||
}
|
||||
}
|
||||
) -> adw::ComboRow,
|
||||
add: bitrate_row = &number_entry_row(
|
||||
"Bitrate",
|
||||
&self.encoder_conf.bitrate
|
||||
.and_then(|n| Some(n.to_string()))
|
||||
.unwrap_or_default(),
|
||||
false,
|
||||
{
|
||||
let sender = sender.clone();
|
||||
move |row| {
|
||||
let txt = row.text();
|
||||
sender.input(Self::Input::BitrateChanged(
|
||||
if txt.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(txt.parse::<u32>().unwrap())
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
) -> adw::EntryRow,
|
||||
add: width_row = &spin_row(
|
||||
"Width",
|
||||
None,
|
||||
self.encoder_conf.width.unwrap_or(1.0).into(),
|
||||
0.0,
|
||||
1.0,
|
||||
0.01,
|
||||
{
|
||||
let sender = sender.clone();
|
||||
move |adj| {
|
||||
sender.input(Self::Input::WidthChanged(
|
||||
Some(adj.value() as f32)
|
||||
));
|
||||
}
|
||||
}
|
||||
) -> adw::SpinRow,
|
||||
add: height_row = &spin_row(
|
||||
"Height",
|
||||
None,
|
||||
self.encoder_conf.height.unwrap_or(1.0).into(),
|
||||
0.0,
|
||||
1.0,
|
||||
0.01,
|
||||
{
|
||||
let sender = sender.clone();
|
||||
move |adj| {
|
||||
sender.input(Self::Input::HeightChanged(
|
||||
Some(adj.value() as f32)
|
||||
));
|
||||
}
|
||||
}
|
||||
) -> adw::SpinRow,
|
||||
add: group_row = &spin_row(
|
||||
"Group",
|
||||
None,
|
||||
self.encoder_conf.group.unwrap_or(0).into(),
|
||||
0.0,
|
||||
99999.0,
|
||||
1.0,
|
||||
{
|
||||
let sender = sender.clone();
|
||||
move |adj| {
|
||||
sender.input(Self::Input::GroupChanged(
|
||||
Some(adj.value().trunc() as i32)
|
||||
));
|
||||
}
|
||||
}
|
||||
) -> adw::SpinRow,
|
||||
}
|
||||
}
|
||||
|
||||
async fn update(&mut self, message: Self::Input, sender: AsyncFactorySender<Self>) {
|
||||
match message {
|
||||
Self::Input::EncoderChanged(idx) => {
|
||||
self.encoder_conf.encoder = Encoder::as_vec().get(idx as usize).unwrap().clone();
|
||||
}
|
||||
Self::Input::CodecChanged(idx) => {
|
||||
self.encoder_conf.codec = Codec::as_vec().get(idx as usize).unwrap().clone();
|
||||
}
|
||||
Self::Input::BitrateChanged(val) => {
|
||||
self.encoder_conf.bitrate = val;
|
||||
}
|
||||
Self::Input::WidthChanged(val) => {
|
||||
self.encoder_conf.width = val;
|
||||
}
|
||||
Self::Input::HeightChanged(val) => {
|
||||
self.encoder_conf.height = val;
|
||||
}
|
||||
Self::Input::GroupChanged(val) => {
|
||||
self.encoder_conf.group = val;
|
||||
}
|
||||
Self::Input::Delete => sender.output(Self::Output::Delete(self.uid.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
|
||||
Some(match output {
|
||||
Self::Output::Delete(id) => Self::ParentInput::DeleteEncoder(id),
|
||||
})
|
||||
}
|
||||
|
||||
async fn init_model(
|
||||
init: Self::Init,
|
||||
_index: &DynamicIndex,
|
||||
_sender: AsyncFactorySender<Self>,
|
||||
) -> Self {
|
||||
Self {
|
||||
encoder_conf: init.encoder_conf.unwrap_or_default(),
|
||||
uid: Uuid::new_v4().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ use crate::gpu_profile::{
|
|||
get_amd_gpu_power_profile, get_first_amd_gpu, get_set_amd_vr_pow_prof_cmd, GpuPowerProfile,
|
||||
GpuSysDrm,
|
||||
};
|
||||
use crate::profile::{LighthouseDriver, Profile};
|
||||
use crate::profile::{LighthouseDriver, Profile, XRServiceType};
|
||||
use crate::steamvr_utils::chaperone_info_exists;
|
||||
use crate::ui::app::{
|
||||
AboutAction, BuildProfileAction, BuildProfileCleanAction, BuildProfileCleanDebugAction,
|
||||
|
@ -84,6 +84,7 @@ pub enum MainViewOutMsg {
|
|||
DeleteProfile,
|
||||
SaveProfile(Profile),
|
||||
OpenLibsurviveSetup,
|
||||
OpenWivrnConfig,
|
||||
}
|
||||
|
||||
pub struct MainViewInit {
|
||||
|
@ -338,6 +339,32 @@ impl SimpleComponent for MainView {
|
|||
},
|
||||
model.steam_launch_options_box.widget(),
|
||||
model.install_wivrn_box.widget(),
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_hexpand: true,
|
||||
set_vexpand: false,
|
||||
set_spacing: 12,
|
||||
add_css_class: "card",
|
||||
add_css_class: "padded",
|
||||
#[track = "model.changed(Self::selected_profile())"]
|
||||
set_visible: model.selected_profile.xrservice_type == XRServiceType::Wivrn,
|
||||
gtk::Label {
|
||||
add_css_class: "heading",
|
||||
set_hexpand: true,
|
||||
set_xalign: 0.0,
|
||||
set_label: "Configure WiVRn",
|
||||
set_wrap: true,
|
||||
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||
},
|
||||
gtk::Button {
|
||||
add_css_class: "suggested-action",
|
||||
set_label: "Configure",
|
||||
set_halign: gtk::Align::End,
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(Self::Output::OpenWivrnConfig).expect("Sender output failed");
|
||||
}
|
||||
},
|
||||
},
|
||||
model.steamvr_calibration_box.widget(),
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
|
|
@ -122,6 +122,40 @@ pub fn number_entry_row<F: Fn(&adw::EntryRow) + 'static>(
|
|||
row
|
||||
}
|
||||
|
||||
pub fn spin_row<F: Fn(>k::Adjustment) + 'static>(
|
||||
title: &str,
|
||||
subtitle: Option<&str>,
|
||||
val: f64,
|
||||
min: f64,
|
||||
max: f64,
|
||||
min_increment: f64,
|
||||
cb: F,
|
||||
) -> adw::SpinRow {
|
||||
let adj = gtk::Adjustment::builder()
|
||||
.lower(min)
|
||||
.upper(max)
|
||||
.step_increment(min_increment)
|
||||
.page_increment(min_increment)
|
||||
.value(val)
|
||||
.build();
|
||||
let row = adw::SpinRow::builder()
|
||||
.title(title)
|
||||
.adjustment(&adj)
|
||||
.digits(if min_increment == 1.0 {
|
||||
0
|
||||
} else {
|
||||
min_increment.to_string().len() - 2
|
||||
} as u32)
|
||||
.build();
|
||||
if let Some(sub) = subtitle {
|
||||
row.set_subtitle(sub);
|
||||
}
|
||||
|
||||
adj.connect_value_changed(cb);
|
||||
|
||||
row
|
||||
}
|
||||
|
||||
pub fn path_row<F: Fn(Option<String>) + 'static + Clone>(
|
||||
title: &str,
|
||||
description: Option<&str>,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::file_builders::wivrn_config::{
|
||||
dump_wivrn_config, get_wivrn_config, Encoder, WivrnConfig,
|
||||
use super::factories::wivrn_encoder_group_factory::{WivrnEncoderModel, WivrnEncoderModelInit};
|
||||
use crate::{
|
||||
file_builders::wivrn_config::{dump_wivrn_config, get_wivrn_config, WivrnConfig},
|
||||
ui::preference_rows::spin_row,
|
||||
};
|
||||
use adw::prelude::*;
|
||||
use relm4::prelude::*;
|
||||
use relm4::{factory::AsyncFactoryVecDeque, prelude::*};
|
||||
|
||||
#[tracker::track]
|
||||
pub struct WivrnConfEditor {
|
||||
|
@ -10,19 +12,19 @@ pub struct WivrnConfEditor {
|
|||
#[tracker::do_not_track]
|
||||
win: Option<adw::Window>,
|
||||
#[tracker::do_not_track]
|
||||
scalex_entry: Option<adw::EntryRow>,
|
||||
pub encoder_models: Option<AsyncFactoryVecDeque<WivrnEncoderModel>>,
|
||||
#[tracker::do_not_track]
|
||||
scaley_entry: Option<adw::EntryRow>,
|
||||
pub scalex_row: Option<adw::SpinRow>,
|
||||
#[tracker::do_not_track]
|
||||
encoder_combo: Option<adw::ComboRow>,
|
||||
#[tracker::do_not_track]
|
||||
bitrate_entry: Option<adw::EntryRow>,
|
||||
pub scaley_row: Option<adw::SpinRow>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WivrnConfEditorMsg {
|
||||
Present,
|
||||
Save,
|
||||
AddEncoder,
|
||||
DeleteEncoder(String),
|
||||
}
|
||||
|
||||
pub struct WivrnConfEditorInit {
|
||||
|
@ -70,73 +72,50 @@ impl SimpleComponent for WivrnConfEditor {
|
|||
set_content: pref_page = &adw::PreferencesPage {
|
||||
set_hexpand: true,
|
||||
set_vexpand: true,
|
||||
set_description: "<a href=\"https://github.com/Meumeu/WiVRn#encoders\">WiVRn Configuration Documentation</a>",
|
||||
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::<Vec<String>>()
|
||||
.iter()
|
||||
.map(String::as_str)
|
||||
.collect::<Vec<&str>>()
|
||||
.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);
|
||||
},
|
||||
add: scalex_row = &spin_row(
|
||||
"Scale X",
|
||||
None,
|
||||
match model.conf.scale {
|
||||
Some([x, _]) => x.into(),
|
||||
None => 1.0,
|
||||
},
|
||||
}
|
||||
0.0,
|
||||
1.0,
|
||||
0.01,
|
||||
move |_| {}
|
||||
) -> adw::SpinRow,
|
||||
add: scaley_row = &spin_row(
|
||||
"Scale Y",
|
||||
None,
|
||||
match model.conf.scale {
|
||||
Some([_, y]) => y.into(),
|
||||
None => 1.0,
|
||||
},
|
||||
0.0,
|
||||
1.0,
|
||||
0.01,
|
||||
move |_| {}
|
||||
) -> adw::SpinRow,
|
||||
},
|
||||
add: encodersrgp = &adw::PreferencesGroup {
|
||||
set_title: "Encoders",
|
||||
adw::ActionRow {
|
||||
set_title: "Add encoder",
|
||||
add_suffix: add_encoder_btn = >k::Button {
|
||||
set_halign: gtk::Align::Center,
|
||||
set_valign: gtk::Align::Center,
|
||||
add_css_class: "suggested-action",
|
||||
set_icon_name: "list-add-symbolic",
|
||||
set_tooltip_text: Some("Add encoder"),
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.input(Self::Input::AddEncoder)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -152,34 +131,41 @@ impl SimpleComponent for WivrnConfEditor {
|
|||
self.win.as_ref().unwrap().present();
|
||||
}
|
||||
Self::Input::Save => {
|
||||
let scalex = self.scalex_entry.as_ref().unwrap().text().parse::<f32>();
|
||||
let scaley = self.scaley_entry.as_ref().unwrap().text().parse::<f32>();
|
||||
if scalex.is_ok() && scaley.is_ok() {
|
||||
self.conf.scale = Some([*scalex.as_ref().unwrap(), *scaley.as_ref().unwrap()]);
|
||||
}
|
||||
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::<u32>();
|
||||
if let Ok(br) = bitrate {
|
||||
enc.bitrate = Some(br);
|
||||
}
|
||||
let encoders = Encoder::as_vec();
|
||||
let encoder =
|
||||
encoders.get(self.encoder_combo.as_ref().unwrap().selected() as usize);
|
||||
if let Some(e) = encoder {
|
||||
enc.encoder = e.clone();
|
||||
}
|
||||
self.conf.encoders.insert(0, enc);
|
||||
let x = self.scalex_row.as_ref().unwrap().adjustment().value();
|
||||
let y = self.scaley_row.as_ref().unwrap().adjustment().value();
|
||||
Some([x as f32, y as f32]);
|
||||
|
||||
self.conf.encoders = self
|
||||
.encoder_models
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(Option::is_some)
|
||||
.map(|m| m.as_ref().unwrap().encoder_conf.clone())
|
||||
.collect();
|
||||
dump_wivrn_config(&self.conf);
|
||||
self.win.as_ref().unwrap().close();
|
||||
}
|
||||
Self::Input::AddEncoder => {
|
||||
self.encoder_models
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.guard()
|
||||
.push_back(WivrnEncoderModelInit::default());
|
||||
}
|
||||
Self::Input::DeleteEncoder(id) => {
|
||||
let idx_opt = self
|
||||
.encoder_models
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.position(|m_opt| m_opt.is_some_and(|m| m.uid == id));
|
||||
if let Some(idx) = idx_opt {
|
||||
self.encoder_models.as_mut().unwrap().guard().remove(idx);
|
||||
} else {
|
||||
eprintln!("Couldn't find encoder model with id {id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,21 +176,28 @@ impl SimpleComponent for WivrnConfEditor {
|
|||
) -> ComponentParts<Self> {
|
||||
let mut model = Self {
|
||||
conf: get_wivrn_config(),
|
||||
encoder_models: None,
|
||||
win: None,
|
||||
scalex_entry: None,
|
||||
scaley_entry: None,
|
||||
bitrate_entry: None,
|
||||
encoder_combo: None,
|
||||
scalex_row: None,
|
||||
scaley_row: None,
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
model.scalex_row = Some(widgets.scalex_row.clone());
|
||||
model.scaley_row = Some(widgets.scaley_row.clone());
|
||||
|
||||
let mut encoder_models: AsyncFactoryVecDeque<WivrnEncoderModel> =
|
||||
AsyncFactoryVecDeque::new(widgets.pref_page.clone(), sender.input_sender());
|
||||
for encoder_conf in model.conf.encoders.clone() {
|
||||
encoder_models.guard().push_back(WivrnEncoderModelInit {
|
||||
encoder_conf: Some(encoder_conf),
|
||||
});
|
||||
}
|
||||
model.encoder_models = Some(encoder_models);
|
||||
|
||||
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 }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue