From 97cdbdea1c8b774118545189a047433169e5cab6 Mon Sep 17 00:00:00 2001 From: Moritz Ruth Date: Thu, 11 Jan 2024 20:48:11 +0100 Subject: [PATCH] commit --- .../examples/full/knob-pages/default.toml | 10 ++++----- deckster/src/modes/knob/audio_volume.rs | 21 +++++++++++++++++-- deckster/src/runner/command.rs | 1 + deckster/src/runner/graphics.rs | 21 +++++++++++++++++++ deckster/src/runner/mod.rs | 13 +++++++++++- 5 files changed, 58 insertions(+), 8 deletions(-) diff --git a/deckster/examples/full/knob-pages/default.toml b/deckster/examples/full/knob-pages/default.toml index bebc1a2..655128c 100644 --- a/deckster/examples/full/knob-pages/default.toml +++ b/deckster/examples/full/knob-pages/default.toml @@ -1,8 +1,8 @@ [knobs.right-top] icon = "@ph/microphone-light[scale=0.9]" -indicator.circle.color = "#ffffff" -indicator.circle.width = 2 -indicator.circle.radius = 40 +indicators.circle.color = "#ffffff" +indicators.circle.width = 2 +indicators.circle.radius = 20 mode.audio_volume.direction = "input" mode.audio_volume.regex = "Microphone" @@ -13,7 +13,7 @@ mode.audio_volume.style.inactive.icon = "@ph/microphone-slash-light[alpha=0.9|co [knobs.right-middle] icon = "@apps/discord[scale=0.25]" -indicator.bar.color = "#ffffff" +indicators.bar.color = "#ffffff" mode.audio_volume.regex = "Discord" mode.audio_volume.style.active.label = "{percentage}%" @@ -23,7 +23,7 @@ mode.audio_volume.style.inactive.icon = "@apps/discord[grayscale|alpha=0.9]" [knobs.right-bottom] icon = "@apps/spotify[scale=1.1]" -indicator.bar.color = "#ffffff" +indicators.bar.color = "#ffffff50" mode.audio_volume.regex = "Spotify" mode.audio_volume.style.active.label = "{percentage}%" diff --git a/deckster/src/modes/knob/audio_volume.rs b/deckster/src/modes/knob/audio_volume.rs index bc7d8ea..fa2f3b6 100644 --- a/deckster/src/modes/knob/audio_volume.rs +++ b/deckster/src/modes/knob/audio_volume.rs @@ -7,11 +7,13 @@ use tokio::sync::broadcast; use crate::model::knob_page::StyleByStateMap; use crate::model::position::KnobPath; -use crate::modes::knob::KnobEvent; +use crate::modes::knob::{KnobEvent, RotationDirection}; use crate::runner::command::IoWorkerCommand; #[derive(Debug, Deserialize)] pub struct Config { + #[serde(default = "default_delta")] + pub delta: f32, #[serde(with = "serde_regex")] pub regex: Regex, #[serde(default)] @@ -28,6 +30,10 @@ pub struct Config { pub style: StyleByStateMap, } +fn default_delta() -> f32 { + 0.05 +} + #[derive(Debug, Default, Eq, PartialEq, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum MutedTurnAction { @@ -54,11 +60,22 @@ pub enum State { } pub async fn handle(path: KnobPath, config: Arc, mut events: broadcast::Receiver<(KnobPath, KnobEvent)>, commands: flume::Sender) { + let mut value: f32 = 0.0; + while let Ok((event_path, event)) = events.recv().await { if event_path != path { continue; } - dbg!(path.clone(), event); + if let KnobEvent::Rotate { direction } = event { + let factor = match direction { + RotationDirection::Clockwise => 1.0, + RotationDirection::Counterclockwise => -1.0, + }; + + value = (value + (factor * config.delta)).clamp(0.0, 1.0); + + commands.send(IoWorkerCommand::SetKnobValue { path: path.clone(), value }).unwrap(); + } } } diff --git a/deckster/src/runner/command.rs b/deckster/src/runner/command.rs index 283b044..0e4bd61 100644 --- a/deckster/src/runner/command.rs +++ b/deckster/src/runner/command.rs @@ -12,4 +12,5 @@ pub enum IoWorkerCommand { SetActivePages { key_page_id: String, knob_page_id: String }, SetKeyStyle { path: KeyPath, value: Option }, SetKnobStyle { path: KnobPath, value: Option }, + SetKnobValue { path: KnobPath, value: f32 }, } diff --git a/deckster/src/runner/graphics.rs b/deckster/src/runner/graphics.rs index 71df457..9fb3a5c 100644 --- a/deckster/src/runner/graphics.rs +++ b/deckster/src/runner/graphics.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use bytes::{BufMut, Bytes, BytesMut}; use resvg::usvg::tiny_skia_path::PathBuilder; +use rgb::RGBA; use tiny_skia::{Color, IntSize, LineCap, LineJoin, Paint, Pixmap, PremultipliedColorU8, Rect, Shader, Stroke, Transform}; use loupedeck_serial::util::Endianness; @@ -76,6 +77,26 @@ pub fn render_knob(context: &GraphicsContext, screen_size: IntSize, state: Optio context.label_renderer.borrow_mut().render(&mut pixmap, label); } } + + if let Some(indicators) = &style.indicators { + if let Some(bar) = indicators.bar.as_ref() { + let color = bar.color.unwrap_or(RGBA::new(0xff, 0xff, 0xff, 0x50).into()); + const PADDING: f32 = 20.0; + let max_height: f32 = pixmap.height() as f32 - PADDING * 2.0; + let height = state.value * max_height; + let y = pixmap.height() as f32 - PADDING - height; + + pixmap.fill_rect( + Rect::from_xywh(pixmap.width() as f32 - 10.0, y, 5.0, height).unwrap(), + &Paint { + shader: Shader::SolidColor(Color::from_rgba8(color.r, color.g, color.b, color.a)), + ..Paint::default() + }, + Transform::identity(), + None, + ); + } + } } convert_pixels_to_rgb565(pixmap.pixels(), context.buffer_endianness).freeze() diff --git a/deckster/src/runner/mod.rs b/deckster/src/runner/mod.rs index 0b7d243..4e817f0 100644 --- a/deckster/src/runner/mod.rs +++ b/deckster/src/runner/mod.rs @@ -7,7 +7,7 @@ use std::time::Instant; use color_eyre::eyre::{ContextCompat, WrapErr}; use color_eyre::Result; use enum_ordinalize::Ordinalize; -use log::{info, trace}; +use log::{error, info, trace}; use rgb::RGB8; use tiny_skia::IntSize; use tokio::sync::broadcast; @@ -341,6 +341,17 @@ fn handle_command(context: &IoWorkerContext, state: &mut State, command: IoWorke draw_knob_at_path_if_visible(context, state, path); context.device.refresh_display(&context.device.characteristics().key_grid.display).unwrap(); } + IoWorkerCommand::SetKnobValue { path, value } => { + if !(0.0..=1.0).contains(&value) { + error!("Received SetKnobValue with an out-of-range value: {}", value) + } else { + state.mutate_knob_for_command("SetKnobValue", &path, |k| { + k.value = value; + }); + + draw_knob_at_path_if_visible(context, state, path); + } + } } }