1use serde::{Deserialize, Serialize};
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct IpcRequest {
24 pub jsonrpc: String,
26 pub id: RequestId,
28 pub method: String,
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub params: Option<serde_json::Value>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct IpcResponse {
38 pub jsonrpc: String,
40 pub id: RequestId,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub result: Option<serde_json::Value>,
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub error: Option<IpcError>,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct IpcNotification {
53 pub jsonrpc: String,
55 pub method: String,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub params: Option<serde_json::Value>,
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
64#[serde(untagged)]
65pub enum RequestId {
66 String(String),
67 Number(i64),
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct IpcError {
73 pub code: i32,
75 pub message: String,
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub data: Option<serde_json::Value>,
80}
81
82pub const ERROR_PARSE: i32 = -32700;
88pub const ERROR_INVALID_REQUEST: i32 = -32600;
90pub const ERROR_METHOD_NOT_FOUND: i32 = -32601;
92pub const ERROR_INVALID_PARAMS: i32 = -32602;
94pub const ERROR_INTERNAL: i32 = -32603;
96
97pub const ERROR_PARAM_NOT_FOUND: i32 = -32000;
100pub const ERROR_PARAM_OUT_OF_RANGE: i32 = -32001;
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct GetParameterParams {
114 pub id: String,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct GetParameterResult {
121 pub id: String,
123 pub value: f32,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct SetParameterParams {
134 pub id: String,
136 pub value: f32,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct SetParameterResult {}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct GetAllParametersResult {
151 pub parameters: Vec<ParameterInfo>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct ParameterInfo {
158 pub id: String,
160 pub name: String,
162 #[serde(rename = "type")]
164 pub param_type: ParameterType,
165 pub value: f32,
167 pub default: f32,
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub unit: Option<String>,
172 #[serde(skip_serializing_if = "Option::is_none")]
174 pub group: Option<String>,
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
179#[serde(rename_all = "lowercase")]
180pub enum ParameterType {
181 Float,
182 Bool,
183 Enum,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct ParameterChangedNotification {
193 pub id: String,
195 pub value: f32,
197}
198
199pub const METHOD_GET_PARAMETER: &str = "getParameter";
205pub const METHOD_SET_PARAMETER: &str = "setParameter";
207pub const METHOD_GET_ALL_PARAMETERS: &str = "getAllParameters";
209pub const METHOD_GET_METER_FRAME: &str = "getMeterFrame";
211pub const METHOD_REQUEST_RESIZE: &str = "requestResize";
213pub const NOTIFICATION_PARAMETER_CHANGED: &str = "parameterChanged";
215
216impl IpcRequest {
221 pub fn new(
223 id: RequestId,
224 method: impl Into<String>,
225 params: Option<serde_json::Value>,
226 ) -> Self {
227 Self {
228 jsonrpc: "2.0".to_string(),
229 id,
230 method: method.into(),
231 params,
232 }
233 }
234}
235
236impl IpcResponse {
237 pub fn success(id: RequestId, result: impl Serialize) -> Self {
239 Self {
240 jsonrpc: "2.0".to_string(),
241 id,
242 result: Some(serde_json::to_value(result).unwrap()),
243 error: None,
244 }
245 }
246
247 pub fn error(id: RequestId, error: IpcError) -> Self {
249 Self {
250 jsonrpc: "2.0".to_string(),
251 id,
252 result: None,
253 error: Some(error),
254 }
255 }
256}
257
258impl IpcNotification {
259 pub fn new(method: impl Into<String>, params: impl Serialize) -> Self {
261 Self {
262 jsonrpc: "2.0".to_string(),
263 method: method.into(),
264 params: Some(serde_json::to_value(params).unwrap()),
265 }
266 }
267}
268
269impl IpcError {
270 pub fn new(code: i32, message: impl Into<String>) -> Self {
272 Self {
273 code,
274 message: message.into(),
275 data: None,
276 }
277 }
278
279 pub fn with_data(code: i32, message: impl Into<String>, data: impl Serialize) -> Self {
281 Self {
282 code,
283 message: message.into(),
284 data: Some(serde_json::to_value(data).unwrap()),
285 }
286 }
287
288 pub fn parse_error() -> Self {
290 Self::new(ERROR_PARSE, "Parse error")
291 }
292
293 pub fn invalid_request(reason: impl Into<String>) -> Self {
295 Self::new(
296 ERROR_INVALID_REQUEST,
297 format!("Invalid request: {}", reason.into()),
298 )
299 }
300
301 pub fn method_not_found(method: impl AsRef<str>) -> Self {
303 Self::new(
304 ERROR_METHOD_NOT_FOUND,
305 format!("Method not found: {}", method.as_ref()),
306 )
307 }
308
309 pub fn invalid_params(reason: impl Into<String>) -> Self {
311 Self::new(
312 ERROR_INVALID_PARAMS,
313 format!("Invalid params: {}", reason.into()),
314 )
315 }
316
317 pub fn internal_error(reason: impl Into<String>) -> Self {
319 Self::new(ERROR_INTERNAL, format!("Internal error: {}", reason.into()))
320 }
321
322 pub fn param_not_found(id: impl AsRef<str>) -> Self {
324 Self::new(
325 ERROR_PARAM_NOT_FOUND,
326 format!("Parameter not found: {}", id.as_ref()),
327 )
328 }
329
330 pub fn param_out_of_range(id: impl AsRef<str>, value: f32) -> Self {
332 Self::new(
333 ERROR_PARAM_OUT_OF_RANGE,
334 format!("Parameter '{}' value {} out of range", id.as_ref(), value),
335 )
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 #[test]
344 fn test_request_serialization() {
345 let req = IpcRequest::new(
346 RequestId::Number(1),
347 METHOD_GET_PARAMETER,
348 Some(serde_json::json!({"id": "gain"})),
349 );
350
351 let json = serde_json::to_string(&req).unwrap();
352 assert!(json.contains("\"jsonrpc\":\"2.0\""));
353 assert!(json.contains("\"method\":\"getParameter\""));
354 }
355
356 #[test]
357 fn test_response_serialization() {
358 let resp = IpcResponse::success(
359 RequestId::Number(1),
360 GetParameterResult {
361 id: "gain".to_string(),
362 value: 0.5,
363 },
364 );
365
366 let json = serde_json::to_string(&resp).unwrap();
367 assert!(json.contains("\"jsonrpc\":\"2.0\""));
368 assert!(json.contains("\"result\""));
369 assert!(!json.contains("\"error\""));
370 }
371
372 #[test]
373 fn test_error_response() {
374 let resp = IpcResponse::error(
375 RequestId::String("test".to_string()),
376 IpcError::method_not_found("unknownMethod"),
377 );
378
379 let json = serde_json::to_string(&resp).unwrap();
380 assert!(json.contains("\"error\""));
381 assert!(!json.contains("\"result\""));
382 }
383
384 #[test]
385 fn test_notification_serialization() {
386 let notif = IpcNotification::new(
387 NOTIFICATION_PARAMETER_CHANGED,
388 ParameterChangedNotification {
389 id: "gain".to_string(),
390 value: 0.8,
391 },
392 );
393
394 let json = serde_json::to_string(¬if).unwrap();
395 println!("Notification JSON: {}", json);
396 assert!(json.contains("\"jsonrpc\":\"2.0\""));
397 assert!(json.contains("\"method\":\"parameterChanged\""));
398 }
401}
402
403#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
411pub struct MeterFrame {
412 pub peak_l: f32,
414 pub peak_r: f32,
416 pub rms_l: f32,
418 pub rms_r: f32,
420 pub timestamp: u64,
422}
423
424#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct GetMeterFrameResult {
427 pub frame: Option<MeterFrame>,
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize)]
437pub struct RequestResizeParams {
438 pub width: u32,
440 pub height: u32,
442}
443
444#[derive(Debug, Clone, Serialize, Deserialize)]
446pub struct RequestResizeResult {
447 pub accepted: bool,
449}