use core::marker::PhantomData;
use crate::{
color::{ColorCorrection, FromColor},
driver::Driver as DriverTrait,
layout::LayoutForDim,
markers::{Blocking, Dim1d, Dim2d, Dim3d},
pattern::Pattern as PatternTrait,
};
#[cfg(feature = "async")]
use crate::{driver::DriverAsync as DriverAsyncTrait, markers::Async};
pub struct Control<Dim, Exec, Layout, Pattern, Driver> {
dim: PhantomData<Dim>,
exec: PhantomData<Exec>,
layout: PhantomData<Layout>,
pattern: Pattern,
driver: Driver,
brightness: f32,
correction: ColorCorrection,
}
impl<Dim, Exec, Layout, Pattern, Driver> Control<Dim, Exec, Layout, Pattern, Driver> {
pub fn new(pattern: Pattern, driver: Driver) -> Self {
Self {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern,
driver,
brightness: 1.,
correction: ColorCorrection::default(),
}
}
pub fn set_brightness(&mut self, brightness: f32) {
self.brightness = brightness;
}
pub fn set_color_correction(&mut self, correction: ColorCorrection) {
self.correction = correction;
}
}
impl<Dim, Layout, Pattern, Driver> Control<Dim, Blocking, Layout, Pattern, Driver>
where
Layout: LayoutForDim<Dim>,
Pattern: PatternTrait<Dim, Layout>,
Driver: DriverTrait,
Driver::Color: FromColor<Pattern::Color>,
{
pub fn tick(&mut self, time_in_ms: u64) -> Result<(), Driver::Error> {
let pixels = self.pattern.tick(time_in_ms);
self.driver.write(pixels, self.brightness, self.correction)
}
}
#[cfg(feature = "async")]
impl<Dim, Layout, Pattern, Driver> Control<Dim, Async, Layout, Pattern, Driver>
where
Layout: LayoutForDim<Dim>,
Pattern: PatternTrait<Dim, Layout>,
Driver: DriverAsyncTrait,
Driver::Color: FromColor<Pattern::Color>,
{
pub async fn tick(&mut self, time_in_ms: u64) -> Result<(), Driver::Error> {
let pixels = self.pattern.tick(time_in_ms);
self.driver
.write(pixels, self.brightness, self.correction)
.await
}
}
pub struct ControlBuilder<Dim, Exec, Layout, Pattern, Driver> {
dim: PhantomData<Dim>,
exec: PhantomData<Exec>,
layout: PhantomData<Layout>,
pattern: Pattern,
driver: Driver,
}
impl ControlBuilder<(), (), (), (), ()> {
pub fn new_1d() -> ControlBuilder<Dim1d, Blocking, (), (), ()> {
ControlBuilder {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern: (),
driver: (),
}
}
}
#[cfg(feature = "async")]
impl ControlBuilder<(), (), (), (), ()> {
pub fn new_1d_async() -> ControlBuilder<Dim1d, Async, (), (), ()> {
ControlBuilder {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern: (),
driver: (),
}
}
}
impl ControlBuilder<(), (), (), (), ()> {
pub fn new_2d() -> ControlBuilder<Dim2d, Blocking, (), (), ()> {
ControlBuilder {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern: (),
driver: (),
}
}
}
#[cfg(feature = "async")]
impl ControlBuilder<(), (), (), (), ()> {
pub fn new_2d_async() -> ControlBuilder<Dim2d, Async, (), (), ()> {
ControlBuilder {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern: (),
driver: (),
}
}
}
impl ControlBuilder<(), (), (), (), ()> {
pub fn new_3d() -> ControlBuilder<Dim3d, Blocking, (), (), ()> {
ControlBuilder {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern: (),
driver: (),
}
}
}
#[cfg(feature = "async")]
impl ControlBuilder<(), (), (), (), ()> {
pub fn new_3d_async() -> ControlBuilder<Dim3d, Async, (), (), ()> {
ControlBuilder {
dim: PhantomData,
exec: PhantomData,
layout: PhantomData,
pattern: (),
driver: (),
}
}
}
impl<Dim, Exec, Pattern, Driver> ControlBuilder<Dim, Exec, (), Pattern, Driver> {
pub fn with_layout<Layout>(self) -> ControlBuilder<Dim, Exec, Layout, Pattern, Driver>
where
Layout: LayoutForDim<Dim>,
{
ControlBuilder {
dim: self.dim,
exec: self.exec,
layout: PhantomData,
pattern: self.pattern,
driver: self.driver,
}
}
}
impl<Dim, Exec, Layout, Driver> ControlBuilder<Dim, Exec, Layout, (), Driver>
where
Layout: LayoutForDim<Dim>,
{
pub fn with_pattern<Pattern>(
self,
params: Pattern::Params,
) -> ControlBuilder<Dim, Exec, Layout, Pattern, Driver>
where
Pattern: PatternTrait<Dim, Layout>,
{
let pattern = Pattern::new(params);
ControlBuilder {
dim: self.dim,
exec: self.exec,
layout: self.layout,
pattern,
driver: self.driver,
}
}
}
impl<Dim, Layout, Pattern> ControlBuilder<Dim, Blocking, Layout, Pattern, ()> {
pub fn with_driver<Driver>(
self,
driver: Driver,
) -> ControlBuilder<Dim, Blocking, Layout, Pattern, Driver>
where
Driver: DriverTrait,
{
ControlBuilder {
dim: self.dim,
exec: self.exec,
layout: self.layout,
pattern: self.pattern,
driver,
}
}
}
#[cfg(feature = "async")]
impl<Dim, Layout, Pattern> ControlBuilder<Dim, Async, Layout, Pattern, ()> {
pub fn with_driver<Driver>(
self,
driver: Driver,
) -> ControlBuilder<Dim, Async, Layout, Pattern, Driver>
where
Driver: DriverAsyncTrait,
{
ControlBuilder {
dim: self.dim,
exec: self.exec,
layout: self.layout,
pattern: self.pattern,
driver,
}
}
}
impl<Dim, Layout, Pattern, Driver> ControlBuilder<Dim, Blocking, Layout, Pattern, Driver>
where
Layout: LayoutForDim<Dim>,
Pattern: PatternTrait<Dim, Layout>,
Driver: DriverTrait,
Driver::Color: FromColor<Pattern::Color>,
{
pub fn build(self) -> Control<Dim, Blocking, Layout, Pattern, Driver> {
Control::new(self.pattern, self.driver)
}
}
#[cfg(feature = "async")]
impl<Dim, Layout, Pattern, Driver> ControlBuilder<Dim, Async, Layout, Pattern, Driver>
where
Layout: LayoutForDim<Dim>,
Pattern: PatternTrait<Dim, Layout>,
Driver: DriverAsyncTrait,
Driver::Color: FromColor<Pattern::Color>,
{
pub fn build(self) -> Control<Dim, Async, Layout, Pattern, Driver> {
Control::new(self.pattern, self.driver)
}
}