1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// SPDX-FileCopyrightText: The djio authors
// SPDX-License-Identifier: MPL-2.0

//! Sending control data to actuators like LEDs and motorized platters
//! or for configuring devices.

use std::{
    borrow::Cow,
    ops::{Deref, DerefMut},
};

use strum::FromRepr;
use thiserror::Error;

use crate::{ControlRegister, ControlValue};

#[derive(Debug, Error)]
pub enum OutputError {
    #[error("disconnected")]
    Disconnected,
    #[error("send: {msg}")]
    Send { msg: Cow<'static, str> },
}

pub type OutputResult<T> = std::result::Result<T, OutputError>;

/// Simple LED
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
#[repr(u8)]
pub enum LedOutput {
    Off = 0,
    On = 1,
}

impl From<LedOutput> for ControlValue {
    fn from(value: LedOutput) -> Self {
        Self::from_bits(value as _)
    }
}

impl From<ControlValue> for LedOutput {
    fn from(value: ControlValue) -> Self {
        match value.to_bits() {
            0 => Self::Off,
            _ => Self::On,
        }
    }
}

/// Dimmable LED
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct DimLedOutput {
    brightness: u8,
}

impl From<DimLedOutput> for ControlValue {
    fn from(value: DimLedOutput) -> Self {
        let DimLedOutput { brightness } = value;
        Self::from_bits(u32::from(brightness))
    }
}

impl From<ControlValue> for DimLedOutput {
    fn from(value: ControlValue) -> Self {
        let brightness = (value.to_bits() & 0xff) as u8;
        Self { brightness }
    }
}

/// RGB LED
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RgbLedOutput {
    red: u8,
    green: u8,
    blue: u8,
}

impl From<RgbLedOutput> for ControlValue {
    fn from(value: RgbLedOutput) -> Self {
        let RgbLedOutput { red, green, blue } = value;
        Self::from_bits(u32::from(red) << 16 | u32::from(green) << 8 | u32::from(blue))
    }
}

impl From<ControlValue> for RgbLedOutput {
    fn from(value: ControlValue) -> Self {
        let red = ((value.to_bits() >> 16) & 0xff) as u8;
        let green = ((value.to_bits() >> 8) & 0xff) as u8;
        let blue = (value.to_bits() & 0xff) as u8;
        Self { red, green, blue }
    }
}

/// First error after sending multiple outputs
#[derive(Debug)]
pub struct SendOutputsError {
    /// The number of outputs that have been sent successfully before an error occurred.
    ///
    /// This could only be set if the outputs are sent subsequently and in order.
    /// If `None` then it is unknown which outputs have arrived at their destination
    /// despite the error.
    pub sent_ok: Option<usize>,

    /// The actual error that occurred.
    pub err: OutputError,
}

pub trait ControlOutputGateway {
    /// Send a single output
    fn send_output(&mut self, output: &ControlRegister) -> OutputResult<()>;

    /// Send multiple outputs
    ///
    /// The default implementation sends single outputs subsequently in order.
    fn send_outputs(&mut self, outputs: &[ControlRegister]) -> Result<(), SendOutputsError> {
        let mut sent_ok = 0;
        for output in outputs {
            match self.send_output(output) {
                Ok(()) => {
                    sent_ok += 1;
                }
                Err(err) => {
                    return Err(SendOutputsError {
                        sent_ok: Some(sent_ok),
                        err,
                    });
                }
            }
        }
        debug_assert_eq!(sent_ok, outputs.len());
        Ok(())
    }
}

impl<T> ControlOutputGateway for T
where
    T: DerefMut + ?Sized,
    <T as Deref>::Target: ControlOutputGateway,
{
    fn send_output(&mut self, output: &ControlRegister) -> OutputResult<()> {
        self.deref_mut().send_output(output)
    }

    fn send_outputs(&mut self, outputs: &[ControlRegister]) -> Result<(), SendOutputsError> {
        self.deref_mut().send_outputs(outputs)
    }
}