1use cue_sdk_sys as ffi;
3
4mod id;
5
6use crate::device::DeviceIndex;
7use crate::errors::{get_last_error, CueSdkError, CueSdkErrorResult};
8use crate::internal::CuePropertyValueHolder;
9use crate::led::CheckColorError::{LedColorError, SdkError};
10use failure::_core::ops::Range;
11
12pub use id::{
13 CommanderLedId, DeviceLedId, GraphicsCardLedId, HeadsetLedId, HeadsetStandLedId,
14 IntegratedLedId, KeyboardLedId, LedId, MotherboardLedId, MouseMatLedId,
15};
16
17#[derive(Debug, Clone, PartialEq)]
21pub struct CueLed {
22 pub id: LedId,
23 pub position: LedPosition,
24 pub(crate) device_index: DeviceIndex,
25 pub last_checked_color: Option<LedColor>,
26 pub last_buffed_color: Option<LedColor>,
27}
28
29#[derive(Debug, Clone, Fail, PartialEq)]
31pub enum CheckColorError {
32 #[fail(display = "Failed to check the color, error: {:?}.", _0)]
33 SdkError(Option<CueSdkError>),
34 #[fail(display = "Error creating valid LedColor, error: {:?}", _0)]
35 LedColorError(LedColorFromFfiError),
36}
37
38impl CueLed {
39 pub(crate) fn with_device_data_from_ffi(
40 device_index: DeviceIndex,
41 led: &ffi::CorsairLedPosition,
42 ) -> Self {
43 let id: LedId = led.ledId.into();
44 let position = LedPosition {
45 height: led.height,
46 left: led.left,
47 top: led.top,
48 width: led.width,
49 };
50 CueLed {
51 device_index,
52 id,
53 position,
54 last_checked_color: None,
55 last_buffed_color: None,
56 }
57 }
58
59 pub fn check_color(&mut self) -> Result<(), CheckColorError> {
62 let mut vh = CuePropertyValueHolder::new_with_initial_value(ffi::CorsairLedColor {
63 ledId: self.id.into(),
64 r: -1,
65 g: -1,
66 b: -1,
67 });
68 let was_successful = unsafe {
69 ffi::CorsairGetLedsColorsByDeviceIndex(self.device_index as i32, 1, vh.mut_ptr())
70 };
71 if was_successful {
72 let color = LedColor::from_ffi(&vh.value()).map_err(|e| LedColorError(e))?;
73 self.last_checked_color = Some(color);
74 Ok(())
75 } else {
76 self.last_checked_color = None;
77 Err(SdkError(get_last_error()))
78 }
79 }
80
81 pub fn update_color_buffer(&mut self, new_color: LedColor) -> CueSdkErrorResult {
84 let mut ffi_color = ffi::CorsairLedColor {
85 ledId: self.id.into(),
86 r: new_color.red as i32,
87 g: new_color.green as i32,
88 b: new_color.blue as i32,
89 };
90
91 let was_successful = unsafe {
92 ffi::CorsairSetLedsColorsBufferByDeviceIndex(
93 self.device_index as i32,
94 1,
95 &mut ffi_color as *mut ffi::CorsairLedColor,
96 )
97 };
98
99 if was_successful {
100 self.last_buffed_color = Some(new_color);
101 Ok(())
102 } else {
103 Err(get_last_error())
104 }
105 }
106}
107
108#[derive(Debug, Clone, Copy, PartialEq)]
114pub struct LedColor {
115 pub red: u8,
116 pub blue: u8,
117 pub green: u8,
118}
119
120#[derive(Debug, Clone, PartialEq, Fail)]
122#[fail(
123 display = "Received invalid color values, should all be between 0-255, instead received red: {}, green: {}, blue:{}",
124 _0, _1, _2
125)]
126pub struct LedColorFromFfiError(i32, i32, i32);
127
128const VALUE_RGB_RANGE: &Range<i32> = &(0..256);
129
130impl LedColor {
131 pub(crate) fn from_ffi(color: &ffi::CorsairLedColor) -> Result<Self, LedColorFromFfiError> {
132 if !VALUE_RGB_RANGE.contains(&color.r)
133 || !VALUE_RGB_RANGE.contains(&color.b)
134 || !VALUE_RGB_RANGE.contains(&color.g)
135 {
136 Err(LedColorFromFfiError(color.r, color.b, color.g))
137 } else {
138 Ok(LedColor {
139 red: color.r as u8,
140 blue: color.b as u8,
141 green: color.g as u8,
142 })
143 }
144 }
145}
146
147#[derive(Debug, Clone, Copy, PartialEq)]
152pub struct LedPosition {
153 pub top: f64,
154 pub left: f64,
155 pub height: f64,
156 pub width: f64,
157}