rusty_patio/streamdeck/client/
mod.rs1use std::collections::HashMap;
2
3use anyhow::Result;
4use base64::{engine::general_purpose, Engine as _};
5use serde::Serialize;
6use serde_json::Value;
7
8use crate::payloads::{
9 event_context::StreamDeckEventContextMessage, log_message::StreamDeckLogMessage,
10 open_url::StreamDeckOpenUrlMessage, register::StreamDeckPluginRegister,
11 send_to_pi::StreamDeckSendToPIMessage, send_to_plugin::StreamDeckSendToPluginMessage,
12 set_feedback::StreamDeckSetFeedbackMessage,
13 set_feedback_layout::StreamDeckSetFeedbackLayoutMessage, set_image::StreamDeckSetImageMessage,
14 set_settings::StreamDeckSetSettingsMessage, set_state::StreamDeckSetStateMessage,
15 set_title::StreamDeckSetTitleMessage, switch_to_profile::StreamDeckSwitchToProfileMessage,
16};
17
18use super::events::{event_received::EventReceived, event_title::StreamDeckEventTitle};
19
20#[derive(Clone)]
21pub struct StreamDeckClientTransmitter {
22 transmit_message: tokio::sync::mpsc::UnboundedSender<String>,
23}
24
25impl StreamDeckClientTransmitter {
26 pub fn new(transmit_message: tokio::sync::mpsc::UnboundedSender<String>) -> Self {
27 StreamDeckClientTransmitter { transmit_message }
28 }
29
30 async fn send_message(&mut self, message: String) -> Result<()> {
31 self.transmit_message.send(message).map_err(|e| e.into())
32 }
33
34 async fn send_json_message<T: Sized + Serialize>(&mut self, message: T) -> Result<()> {
35 self.send_message(serde_json::to_string(&message).unwrap())
36 .await
37 }
38
39 pub async fn register_plugin(&mut self, event: &String, uuid: &String) {
40 self.send_json_message(StreamDeckPluginRegister::new(event, uuid))
41 .await
42 .unwrap();
43 }
44
45 pub async fn log_message(&mut self, message: String) -> Result<()> {
46 self.send_json_message(StreamDeckLogMessage::new(message))
47 .await
48 }
49
50 pub async fn set_image(
51 &mut self,
52 context: String,
53 image_path: String,
54 target: u8,
55 state: Option<u8>,
56 ) -> Result<()> {
57 let image_bytes = tokio::fs::read(&image_path).await?;
58 let encoded = general_purpose::STANDARD.encode(&image_bytes);
59 let mime_type = mime_guess::from_path(&image_path).first();
60
61 if let Some(mime_type) = mime_type {
62 self.send_json_message(StreamDeckSetImageMessage::new(
63 context,
64 format!("data:{};base64,{}", mime_type, encoded),
65 target,
66 state,
67 ))
68 .await
69 } else {
70 Err(anyhow::anyhow!("Could not determine mime type"))
71 }
72 }
73
74 pub async fn switch_to_profile(
75 &mut self,
76 context: String,
77 device: String,
78 profile: String,
79 ) -> Result<()> {
80 self.send_json_message(StreamDeckSwitchToProfileMessage::new(
81 context, device, profile,
82 ))
83 .await
84 }
85
86 pub async fn send_to_property_inspector(
87 &mut self,
88 context: String,
89 action: String,
90 payload: HashMap<String, Value>,
91 ) -> Result<()> {
92 self.send_json_message(StreamDeckSendToPIMessage::new(action, context, payload))
93 .await
94 }
95
96 pub async fn set_title(
97 &mut self,
98 context: String,
99 title: String,
100 target: u8,
101 state: Option<u8>,
102 ) -> Result<()> {
103 self.send_json_message(StreamDeckSetTitleMessage::new(
104 context, title, target, state,
105 ))
106 .await
107 }
108
109 pub async fn set_settings<T: Sized + Serialize>(
110 &mut self,
111 context: String,
112 payload: T,
113 ) -> Result<()> {
114 self.send_json_message(StreamDeckSetSettingsMessage {
115 event: StreamDeckEventTitle::SET_SETTINGS.to_string(),
116 context,
117 payload,
118 })
119 .await
120 }
121
122 pub async fn set_global_settings<T: Sized + Serialize>(
123 &mut self,
124 context: String,
125 payload: T,
126 ) -> Result<()> {
127 self.send_json_message(StreamDeckSetSettingsMessage {
128 event: StreamDeckEventTitle::SET_GLOBAL_SETTINGS.to_string(),
129 context,
130 payload,
131 })
132 .await
133 }
134
135 pub async fn open_url(&mut self, url: String) -> Result<()> {
136 self.send_json_message(StreamDeckOpenUrlMessage::new(url))
137 .await
138 }
139
140 pub async fn get_settings(&mut self, context: String) -> Result<()> {
141 self.send_json_message(StreamDeckEventContextMessage {
142 event: StreamDeckEventTitle::GET_SETTINGS.to_string(),
143 context,
144 })
145 .await
146 }
147
148 pub async fn get_global_settings(&mut self, context: String) -> Result<()> {
149 self.send_json_message(StreamDeckEventContextMessage {
150 event: StreamDeckEventTitle::GET_GLOBAL_SETTINGS.to_string(),
151 context,
152 })
153 .await
154 }
155
156 pub async fn show_alert(&mut self, context: String) -> Result<()> {
157 self.send_json_message(StreamDeckEventContextMessage {
158 event: StreamDeckEventTitle::SHOW_ALERT.to_string(),
159 context,
160 })
161 .await
162 }
163
164 pub async fn show_ok(&mut self, context: String) -> Result<()> {
165 self.send_json_message(StreamDeckEventContextMessage {
166 event: StreamDeckEventTitle::SHOW_OK.to_string(),
167 context,
168 })
169 .await
170 }
171
172 pub async fn set_feedback(&mut self, context: String, payload: HashMap<String, Value>) {
173 self.send_json_message(StreamDeckSetFeedbackMessage::new(context, payload))
174 .await
175 .unwrap();
176 }
177
178 pub async fn set_feedback_layout(&mut self, context: String, layout: String) {
179 self.send_json_message(StreamDeckSetFeedbackLayoutMessage::new(context, layout))
180 .await
181 .unwrap();
182 }
183
184 pub async fn set_state(&mut self, context: String, state: u8) {
185 self.send_json_message(StreamDeckSetStateMessage::new(context, state))
186 .await
187 .unwrap();
188 }
189
190 pub async fn send_to_plugin(
191 &mut self,
192 context: String,
193 action: String,
194 payload: HashMap<String, Value>,
195 ) {
196 self.send_json_message(StreamDeckSendToPluginMessage::new(context, action, payload))
197 .await
198 .unwrap();
199 }
200}
201
202pub struct StreamDeckClient {
203 pub received_events: tokio::sync::mpsc::UnboundedReceiver<EventReceived>,
204 pub transmitter: StreamDeckClientTransmitter,
205}
206
207impl StreamDeckClient {
208 pub fn new(
209 received_events: tokio::sync::mpsc::UnboundedReceiver<EventReceived>,
210 transmit_message: tokio::sync::mpsc::UnboundedSender<String>,
211 ) -> Self {
212 StreamDeckClient {
213 received_events,
214 transmitter: StreamDeckClientTransmitter::new(transmit_message),
215 }
216 }
217}