use std::sync::mpsc::{Sender, self}; use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; use crate::settings::{SettingError, SettingVariant, MinMax}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, CpuMessage}; /// Available CPUs web method pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { super::utility::map_result( crate::settings::steam_deck::Cpus::cpu_count() .map(|x| x as u64) .ok_or_else( || SettingError { msg: "Failed to parse CPU count".to_owned(), setting: SettingVariant::Cpu, } ) ) } /// Generate set CPU online web method pub fn set_cpu_online( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |index: usize, value: bool| sender.lock() .unwrap() .send(ApiMessage::Cpu(CpuMessage::SetCpuOnline(index, value))).expect("set_cpu_online send failed"); move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { //let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); if let Some(&Primitive::Bool(online)) = params_in.get(1) { setter(index as usize, online); vec![online.into()] } else { vec!["set_cpu_online missing parameter 1".into()] } } else { vec!["set_cpu_online missing parameter 0".into()] } } } pub fn set_cpus_online( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |values: Vec| sender.lock() .unwrap() .send(ApiMessage::Cpu(CpuMessage::SetCpusOnline(values))).expect("set_cpus_online send failed"); move |params_in: super::ApiParameterType| { let mut result = Vec::with_capacity(params_in.len()); let mut values = Vec::with_capacity(params_in.len()); for i in 0..params_in.len() { if let Primitive::Bool(online) = params_in[i] { values.push(online); result.push(online.into()); } else { values.push(true); result.push(format!("Invalid parameter {}", i).into()) } } setter(values); result } } /*pub fn get_cpus_online( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let getter = move || { let (tx, rx) = mpsc::channel(); let callback = move |values: Vec| tx.send(values).expect("get_cpus_online callback send failed"); sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed"); rx.recv().expect("get_cpus_online callback recv failed") }; move |_: super::ApiParameterType| { let result = getter(); let mut output = Vec::with_capacity(result.len()); for &status in result.as_slice() { output.push(status.into()); } output } }*/ pub fn set_smt( sender: Sender, ) -> impl AsyncCallable { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let getter = move || { let sender2 = sender.clone(); move |smt: bool| { let (tx, rx) = mpsc::channel(); let callback = move |values: Vec| tx.send(values).expect("set_smt callback send failed"); sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::SetSmt(smt, Box::new(callback)))).expect("set_smt send failed"); rx.recv().expect("set_smt callback recv failed") } }; super::async_utils::AsyncIsh { trans_setter: |params| { if let Some(&Primitive::Bool(smt_value)) = params.get(0) { Ok(smt_value) } else { Err("set_smt missing/invalid parameter 0".to_owned()) } }, set_get: getter, trans_getter: |result| { let mut output = Vec::with_capacity(result.len()); for &status in result.as_slice() { output.push(status.into()); } output } } } pub fn get_cpus_online( sender: Sender, ) -> impl AsyncCallable { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let getter = move || { let sender2 = sender.clone(); move || { let (tx, rx) = mpsc::channel(); let callback = move |values: Vec| tx.send(values).expect("get_cpus_online callback send failed"); sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed"); rx.recv().expect("get_cpus_online callback recv failed") } }; super::async_utils::AsyncIshGetter { set_get: getter, trans_getter: |result| { let mut output = Vec::with_capacity(result.len()); for &status in result.as_slice() { output.push(status.into()); } output } } } pub fn set_clock_limits( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |index: usize, value: MinMax| sender.lock() .unwrap() .send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, Some(value)))).expect("set_clock_limits send failed"); move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(min)) = params_in.get(1) { if let Some(&Primitive::F64(max)) = params_in.get(2) { setter(index as usize, MinMax {min: min as u64, max: max as u64}); vec![min.into(), max.into()] } else { vec!["set_clock_limits missing parameter 2".into()] } } else { vec!["set_clock_limits missing parameter 1".into()] } } else { vec!["set_clock_limits missing parameter 0".into()] } } } pub fn get_clock_limits( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let getter = move |index: usize| { let (tx, rx) = mpsc::channel(); let callback = move |values: Option>| tx.send(values).expect("get_clock_limits callback send failed"); sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetClockLimits(index, Box::new(callback)))).expect("get_clock_limits send failed"); rx.recv().expect("get_clock_limits callback recv failed") }; move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(min_max) = getter(index as usize) { vec![min_max.min.into(), min_max.max.into()] } else { vec![Primitive::Empty, Primitive::Empty] } } else { vec!["get_clock_limits missing parameter 0".into()] } } } pub fn unset_clock_limits( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |index: usize| sender.lock() .unwrap() .send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, None))).expect("unset_clock_limits send failed"); move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { setter(index as usize); vec![true.into()] } else { vec!["get_clock_limits missing parameter 0".into()] } } } pub fn set_cpu_governor( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |index: usize, governor: String| sender.lock() .unwrap() .send(ApiMessage::Cpu(CpuMessage::SetCpuGovernor(index, governor))).expect("set_cpu_governor send failed"); move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(Primitive::String(governor)) = params_in.get(1) { setter(index as usize, governor.to_owned()); vec![(governor as &str).into()] } else { vec!["set_cpu_governor missing parameter 1".into()] } } else { vec!["set_cpu_governor missing parameter 0".into()] } } } pub fn set_cpus_governors( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |governors: Vec| sender.lock() .unwrap() .send(ApiMessage::Cpu(CpuMessage::SetCpusGovernor(governors))).expect("set_cpus_governor send failed"); move |params_in: super::ApiParameterType| { let mut result = Vec::with_capacity(params_in.len()); let mut values = Vec::with_capacity(params_in.len()); for i in 0..params_in.len() { if let Primitive::String(gov) = ¶ms_in[i] { values.push(gov.to_owned()); result.push((gov as &str).into()); } else { //values.push(true); result.push(format!("Invalid parameter {}", i).into()) } } setter(values); result } } pub fn get_cpu_governors( sender: Sender, ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let getter = move || { let (tx, rx) = mpsc::channel(); let callback = move |values: Vec| tx.send(values).expect("get_cpu_governors callback send failed"); sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusGovernor(Box::new(callback)))).expect("get_cpu_governors send failed"); rx.recv().expect("get_cpu_governors callback recv failed") }; move |_: super::ApiParameterType| { let result = getter(); let mut output = Vec::with_capacity(result.len()); for cpu in result.as_slice() { output.push(cpu.clone().into()); } output } }