use std::sync::mpsc::{self, Sender}; use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; use super::utility::map_optional; use crate::settings::MinMax; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, GpuMessage}; pub fn set_ppt( 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 |fast: u64, slow: u64| { sender .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::SetPpt(Some(fast), Some(slow)))) .expect("set_ppt send failed") }; move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(fast_ppt)) = params_in.get(0) { if let Some(&Primitive::F64(slow_ppt)) = params_in.get(1) { setter(fast_ppt as u64, slow_ppt as u64); vec![(fast_ppt as u64).into(), (slow_ppt as u64).into()] } else { vec!["set_ppt missing parameter 1".into()] } } else { vec!["set_ppt missing parameter 0".into()] } } } pub fn get_ppt(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 |ppt: (Option, Option)| { tx.send(ppt).expect("get_ppt callback send failed") }; sender2 .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::GetPpt(Box::new(callback)))) .expect("get_ppt send failed"); rx.recv().expect("get_ppt callback recv failed") } }; super::async_utils::AsyncIshGetter { set_get: getter, trans_getter: |(fast, slow): (Option, Option)| { vec![ fast.map(|x| x.into()).unwrap_or(Primitive::Empty), slow.map(|x| x.into()).unwrap_or(Primitive::Empty), ] }, } } pub fn unset_ppt( 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 || { sender .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::SetPpt(None, None))) .expect("set_ppt send failed") }; move |_: super::ApiParameterType| { setter(); vec![true.into()] } } 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 |value: MinMax| { sender .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::SetClockLimits(Some(value)))) .expect("set_clock_limits send failed") }; move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(min)) = params_in.get(0) { if let Some(&Primitive::F64(max)) = params_in.get(1) { let safe_max = if max < min { min } else { max }; let safe_min = if min > max { max } else { min }; setter(MinMax { min: Some(safe_min as _), max: Some(safe_max as _), }); vec![(safe_min as u64).into(), (safe_max as u64).into()] } else { vec!["set_clock_limits missing parameter 1".into()] } } else { vec!["set_clock_limits missing parameter 0".into()] } } // TODO allow param 0 and/or 1 to be Primitive::Empty } pub fn get_clock_limits(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 |clocks: Option>| { tx.send(clocks) .expect("get_clock_limits callback send failed") }; sender2 .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::GetClockLimits(Box::new( callback, )))) .expect("get_clock_limits send failed"); rx.recv().expect("get_clock_limits callback recv failed") } }; super::async_utils::AsyncIshGetter { set_get: getter, trans_getter: |clocks: Option>| { clocks .map(|x| vec![map_optional(x.min), map_optional(x.max)]) .unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty]) }, } } 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 || { sender .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::SetClockLimits(None))) .expect("unset_clock_limits send failed") }; move |_: super::ApiParameterType| { setter(); vec![true.into()] } } pub fn set_slow_memory( 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 |value: u64| { sender .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::SetMemoryClock(Some(value)))) .expect("unset_clock_limits send failed") }; move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(mem_clock)) = params_in.get(0) { setter(mem_clock as _); vec![mem_clock.into()] } else { vec!["set_slow_memory missing parameter 0".into()] } } } pub fn get_slow_memory(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 |value: Option| { tx.send(value) .expect("get_slow_memory callback send failed") }; sender2 .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::GetMemoryClock(Box::new( callback, )))) .expect("get_slow_memory send failed"); rx.recv().expect("get_slow_memory callback recv failed") } }; super::async_utils::AsyncIshGetter { set_get: getter, trans_getter: |value: Option| vec![super::utility::map_optional(value)], } } pub fn unset_slow_memory( 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 || { sender .lock() .unwrap() .send(ApiMessage::Gpu(GpuMessage::SetMemoryClock(None))) .expect("unset_slow_memory send failed") }; move |_: super::ApiParameterType| { setter(); vec![true.into()] } }