1use std::mem::{self, MaybeUninit};
2use std::str;
3
4use slog::Logger;
5
6use winapi::shared::winerror::E_ACCESSDENIED;
7
8use crate::com::ComObject;
9use crate::ctsndcr::{ISoundCore, Param, ParamInfo, ParamValue};
10use crate::hresult::{check, Win32Error};
11
12#[derive(Clone, Copy, Debug)]
14pub enum SoundCoreParamValue {
15 Float(f32),
17 Bool(bool),
19 U32(u32),
21 I32(i32),
23 None,
25}
26
27#[derive(Debug)]
29pub struct SoundCoreParameter {
30 core: ComObject<ISoundCore>,
31 logger: Logger,
32 context: u32,
33 feature_id: u32,
34 feature_description: String,
35 pub id: u32,
37 pub kind: u32,
39 pub size: Option<u32>,
41 pub min_value: SoundCoreParamValue,
43 pub max_value: SoundCoreParamValue,
45 pub step_size: SoundCoreParamValue,
47 pub attributes: u32,
49 pub description: String,
51}
52
53impl SoundCoreParameter {
54 pub(crate) fn new(
55 core: ComObject<ISoundCore>,
56 feature_description: String,
57 logger: Logger,
58 info: &ParamInfo,
59 ) -> Self {
60 let description_length = info
61 .description
62 .iter()
63 .position(|i| *i == 0)
64 .unwrap_or(info.description.len());
65 Self {
66 core,
67 context: info.param.context,
68 feature_id: info.param.feature,
69 feature_description,
70 logger,
71 id: info.param.param,
72 description: str::from_utf8(&info.description[0..description_length])
73 .unwrap()
74 .to_owned(),
75 attributes: info.param_attributes,
76 kind: info.param_type,
77 size: match info.param_type {
78 5 => Some(info.data_size),
79 _ => None,
80 },
81 min_value: convert_param_value(&info.min_value),
82 max_value: convert_param_value(&info.max_value),
83 step_size: convert_param_value(&info.step_size),
84 }
85 }
86 pub fn get(&self) -> Result<SoundCoreParamValue, Win32Error> {
91 if self.kind == 5 {
93 return Ok(SoundCoreParamValue::None);
94 }
95 unsafe {
96 let param = Param {
97 context: self.context,
98 feature: self.feature_id,
99 param: self.id,
100 };
101 let mut value = MaybeUninit::uninit();
102 trace!(
103 self.logger,
104 "Fetching parameter value .{}.{}.{}...",
105 self.context,
106 self.feature_id,
107 self.id
108 );
109 match check(self.core.GetParamValue(param, value.as_mut_ptr())) {
110 Ok(_) => {}
111 Err(Win32Error { code, .. }) if code == E_ACCESSDENIED => {
112 trace!(
113 self.logger,
114 "Got parameter value .{}.{}.{} = {}",
115 self.context,
116 self.feature_id,
117 self.id,
118 "ACCESSDENIED"
119 );
120 return Ok(SoundCoreParamValue::None);
121 }
122 Err(error) => return Err(error),
123 };
124 let value = value.assume_init();
125 trace!(
126 self.logger,
127 "Got parameter value .{}.{}.{} = {:?}",
128 self.context,
129 self.feature_id,
130 self.id,
131 value
132 );
133 Ok(convert_param_value(&value))
134 }
135 }
136 pub fn set(&mut self, value: &SoundCoreParamValue) -> Result<(), Win32Error> {
141 unsafe {
142 let param = Param {
143 context: self.context,
144 feature: self.feature_id,
145 param: self.id,
146 };
147 let param_value = ParamValue {
148 kind: match *value {
149 SoundCoreParamValue::Float(_) => 0,
150 SoundCoreParamValue::Bool(_) => 1,
151 SoundCoreParamValue::U32(_) => 2,
152 SoundCoreParamValue::I32(_) => 3,
153 _ => panic!("tried to set parameter with nothing"),
154 },
155 value: match *value {
156 SoundCoreParamValue::Float(f) => f.to_bits(),
157 SoundCoreParamValue::Bool(b) => {
158 if b {
159 0xffff_ffff
160 } else {
161 0
162 }
163 }
164 SoundCoreParamValue::U32(u) => u,
165 SoundCoreParamValue::I32(i) => mem::transmute(i),
166 _ => panic!("tried to set parameter with nothing"),
167 },
168 };
169 info!(
170 self.logger,
171 "Setting {}.{} = {:?}", self.feature_description, self.description, value
172 );
173 check(self.core.SetParamValue(param, param_value))?;
174 Ok(())
175 }
176 }
177}
178
179fn convert_param_value(value: &ParamValue) -> SoundCoreParamValue {
180 unsafe {
181 match value.kind {
182 0 => SoundCoreParamValue::Float(f32::from_bits(value.value)),
183 1 => SoundCoreParamValue::Bool(value.value != 0),
184 2 => SoundCoreParamValue::U32(value.value),
185 3 => SoundCoreParamValue::I32(mem::transmute(value.value)),
186 _ => SoundCoreParamValue::None,
187 }
188 }
189}