1pub mod messages;
4
5use std::time::Duration;
6
7use server::{CheckedConn, CheckedPermissions, MessageAllowed};
8
9use crate::messages::*;
10
11#[macro_export]
12macro_rules! use_api {
13 () => {
14 mod rgb_permissions {
15 use $crate::messages::*;
16 #[derive(Clone, Default, server::Permissions)]
17 #[server_name = "os/rgb-server"]
18 pub struct RgbPermissions;
19 }
20 type RgbApi = $crate::RgbApi<rgb_permissions::RgbPermissions>;
21 };
22}
23
24#[derive(Default)]
25pub struct RgbApi<P: CheckedPermissions> {
26 conn: CheckedConn<P>,
27}
28
29impl<P: CheckedPermissions> RgbApi<P> {
30 pub fn try_new_with_timeout(timeout: Duration) -> Option<Self> {
31 Some(Self { conn: CheckedConn::try_connect_with_timeout(timeout)? })
32 }
33
34 pub fn set_all_to(&self, color: RgbColor)
35 where
36 P: MessageAllowed<SetAllTo>,
37 {
38 self.conn.try_send_scalar(SetAllTo(color)).ok();
39 }
40
41 pub fn set_to(&self, index: u32, color: RgbColor)
42 where
43 P: MessageAllowed<SetTo>,
44 {
45 self.conn.try_send_scalar(SetTo(index, color)).ok();
46 }
47
48 pub fn animate_all(&self, animation: RgbAnimation)
49 where
50 P: MessageAllowed<AnimateAllTo>,
51 {
52 self.conn.try_send_scalar(AnimateAllTo(animation)).ok();
53 }
54
55 #[cfg(not(keyos))]
56 pub fn subscribe_color_updates<S>(&self, context: &mut server::ServerContext<S>)
57 where
58 P: MessageAllowed<messages::SubscribeColorUpdates>,
59 S: server::Server + server::ScalarEventHandler<RgbColor>,
60 {
61 self.conn.subscribe_scalar_infallible(messages::SubscribeColorUpdates, context);
62 }
63}
64
65#[derive(Debug, Copy, Clone, PartialEq)]
66pub struct RgbColor {
67 pub r: u8,
68 pub g: u8,
69 pub b: u8,
70}
71
72impl From<u32> for RgbColor {
73 fn from(value: u32) -> Self {
74 let [r, g, b, _] = value.to_le_bytes();
75 Self { r, g, b }
76 }
77}
78
79impl From<RgbColor> for u32 {
80 fn from(value: RgbColor) -> Self {
81 let arr = [value.r, value.g, value.b, 0];
82 Self::from_le_bytes(arr)
83 }
84}
85
86impl RgbColor {
87 pub const BLACK: RgbColor = RgbColor { r: 0, g: 0, b: 0 };
88 pub const RED: RgbColor = RgbColor { r: 0xff, g: 0x00, b: 0x00 };
89 pub const TEAL: RgbColor = RgbColor { r: 0x00, g: 0x9d, b: 0xb9 };
90 pub const WHITE: RgbColor = RgbColor { r: 0xff, g: 0xff, b: 0xff };
91
92 pub const fn new(r: u8, g: u8, b: u8) -> Self { RgbColor { r, g, b } }
93
94 pub fn lerp(self, other: Self, ratio: f32) -> Self {
95 Self {
96 r: (self.r as f32 + (other.r as f32 - self.r as f32) * ratio).round() as u8,
97 g: (self.g as f32 + (other.g as f32 - self.g as f32) * ratio).round() as u8,
98 b: (self.b as f32 + (other.b as f32 - self.b as f32) * ratio).round() as u8,
99 }
100 }
101
102 pub fn scale(self, ratio: f32) -> Self {
103 Self {
104 r: (self.r as f32 * ratio).round() as u8,
105 g: (self.g as f32 * ratio).round() as u8,
106 b: (self.b as f32 * ratio).round() as u8,
107 }
108 }
109}
110
111#[derive(Debug, Copy, Clone)]
112pub struct RgbAnimation {
113 pub from: RgbColor,
114 pub to: RgbColor,
115 pub duration_ms: usize,
116 pub reset: bool,
117}
118
119impl RgbAnimation {
120 pub const fn new(from: RgbColor, to: RgbColor, duration_ms: usize, reset: bool) -> Self {
121 Self { from, to, duration_ms, reset }
122 }
123}