streamdeck_rs/
registration.rs

1use super::{Color, DeviceSize, DeviceType};
2use failure::Fail;
3use serde::de;
4use serde_derive::{Deserialize, Serialize};
5use std::fmt;
6use std::str::FromStr;
7
8/// Information about a connected device.
9///
10/// [Official Documentation](https://developer.elgato.com/documentation/stream-deck/sdk/registration-procedure/#info-parameter)
11#[derive(Deserialize)]
12pub struct RegistrationInfoDevice {
13    /// The ID of the specific device.
14    pub id: String,
15    /// The user-specified name of the device.
16    ///
17    /// Added in Stream Deck software version 4.3.
18    pub name: Option<String>,
19    /// The size of the device.
20    pub size: DeviceSize,
21    /// The type of the device.
22    #[serde(rename = "type")]
23    pub _type: Option<DeviceType>,
24}
25
26/// The language the Stream Deck software is running in.
27///
28/// [Official Documentation](https://developer.elgato.com/documentation/stream-deck/sdk/registration-procedure/#Info-parameter)
29pub enum Language {
30    English,
31    French,
32    German,
33    Spanish,
34    Japanese,
35    /// Unlike the other lanuages which are not specifically localized to a country, Chinese is specifically zh-CN.
36    ChineseChina,
37    /// A language that was not documented in the 4.0.0 SDK.
38    Unknown(String),
39}
40
41impl<'de> de::Deserialize<'de> for Language {
42    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
43    where
44        D: de::Deserializer<'de>,
45    {
46        struct Visitor;
47
48        impl<'de> de::Visitor<'de> for Visitor {
49            type Value = Language;
50
51            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
52                formatter.write_str("a string")
53            }
54
55            fn visit_str<E>(self, value: &str) -> Result<Language, E>
56            where
57                E: de::Error,
58            {
59                Ok(match value {
60                    "en" => Language::English,
61                    "fr" => Language::French,
62                    "de" => Language::German,
63                    "es" => Language::Spanish,
64                    "ja" => Language::Japanese,
65                    "zh_cn" => Language::ChineseChina,
66                    value => Language::Unknown(value.to_string()),
67                })
68            }
69        }
70
71        deserializer.deserialize_str(Visitor)
72    }
73}
74
75/// The platform on which the Stream Deck software is running.
76pub enum Platform {
77    /// Mac OS X
78    Mac,
79    /// Windows
80    Windows,
81    /// A platform not documented in the 4.0.0 SDK.
82    Unknown(String),
83}
84
85impl<'de: 'a, 'a> de::Deserialize<'de> for Platform {
86    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
87    where
88        D: de::Deserializer<'de>,
89    {
90        struct Visitor;
91
92        impl<'de> de::Visitor<'de> for Visitor {
93            type Value = Platform;
94
95            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
96                formatter.write_str("a string")
97            }
98
99            fn visit_str<E>(self, value: &str) -> Result<Platform, E>
100            where
101                E: de::Error,
102            {
103                Ok(match value {
104                    "mac" => Platform::Mac,
105                    "windows" => Platform::Windows,
106                    value => Platform::Unknown(value.to_string()),
107                })
108            }
109        }
110
111        deserializer.deserialize_str(Visitor)
112    }
113}
114
115/// Information about the Stream Deck software.
116///
117/// [Official Documentation](https://developer.elgato.com/documentation/stream-deck/sdk/registration-procedure/#info-parameter)
118#[derive(Deserialize)]
119pub struct RegistrationInfoApplication {
120    pub language: Language,
121    pub platform: Platform,
122    pub version: String,
123}
124
125/// The user's preferred colors
126#[derive(Deserialize, Serialize, Debug)]
127#[serde(rename_all = "camelCase")]
128pub struct UserColors {
129    button_pressed_background_color: Option<Color>,
130    button_pressed_border_color: Option<Color>,
131    button_pressed_text_color: Option<Color>,
132    disabled_color: Option<Color>,
133    highlight_color: Option<Color>,
134    mouse_down_color: Option<Color>,
135}
136
137/// Information about the environment the plugin is being loaded into.
138///
139/// [Official Documentation](https://developer.elgato.com/documentation/stream-deck/sdk/registration-procedure/#info-parameter)
140#[derive(Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct RegistrationInfo {
143    pub application: RegistrationInfoApplication,
144    pub device_pixel_ratio: u8,
145    pub devices: Vec<RegistrationInfoDevice>,
146    pub colors: UserColors,
147}
148
149/// Registration parameters provided to the plugin on startup.
150///
151/// [Official Documentation](https://developer.elgato.com/documentation/stream-deck/sdk/registration-procedure/#compiled-plugin-registration)
152#[derive(Deserialize)]
153pub struct RegistrationParams {
154    /// The web socket port listening for the plugin.
155    pub port: u16,
156    /// The uuid of the plugin.
157    pub uuid: String,
158    /// The event the plugin should send to register with the Stream Deck software.
159    pub event: String,
160    /// Information about the environment the plugin is being loaded into.
161    pub info: RegistrationInfo,
162}
163
164/// An error that occurred while collecting the registration parameters.
165#[derive(Debug, Fail)]
166pub enum RegistrationParamsError {
167    /// The port number was not found.
168    #[fail(display = "port not provided")]
169    NoPort,
170    /// The port number was found but could not be parsed.
171    #[fail(display = "port could not be parsed")]
172    BadPort(#[fail(cause)] std::num::ParseIntError),
173    /// The uuid was not found.
174    #[fail(display = "uuid not provided")]
175    NoUuid,
176    /// The registration event to send was not found.
177    #[fail(display = "event not provided")]
178    NoEvent,
179    /// The registration environment info was not found.
180    #[fail(display = "info not provided")]
181    NoInfo,
182    /// The registration environment info could not be parsed.
183    #[fail(display = "info could not be parsed")]
184    BadInfo(#[fail(cause)] serde_json::Error),
185}
186
187impl RegistrationParams {
188    /// Pull the registration parameters out of a command line.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// RegistrationParams::from_args(env::args())
194    /// ```
195    pub fn from_args<I: IntoIterator<Item = String>>(
196        args: I,
197    ) -> Result<RegistrationParams, RegistrationParamsError> {
198        let mut iter = args.into_iter();
199        let mut port = None;
200        let mut uuid = None;
201        let mut event = None;
202        let mut info = None;
203
204        loop {
205            match iter.next().as_deref() {
206                Some("-port") => port = iter.next().map(|a| u16::from_str(&a)),
207                Some("-pluginUUID") => uuid = iter.next(),
208                Some("-registerEvent") => event = iter.next(),
209                Some("-info") => info = iter.next().map(|a| serde_json::from_str(&a)),
210                Some(_) => {}
211                None => break,
212            }
213        }
214        let port = port
215            .ok_or(RegistrationParamsError::NoPort)?
216            .map_err(RegistrationParamsError::BadPort)?;
217        let uuid = uuid.ok_or(RegistrationParamsError::NoUuid)?;
218        let event = event.ok_or(RegistrationParamsError::NoEvent)?;
219        let info = info
220            .ok_or(RegistrationParamsError::NoInfo)?
221            .map_err(RegistrationParamsError::BadInfo)?;
222
223        Ok(RegistrationParams {
224            port,
225            uuid,
226            event,
227            info,
228        })
229    }
230}