commit
This commit is contained in:
parent
102de5504b
commit
97cdbdea1c
5 changed files with 58 additions and 8 deletions
|
@ -1,8 +1,8 @@
|
||||||
[knobs.right-top]
|
[knobs.right-top]
|
||||||
icon = "@ph/microphone-light[scale=0.9]"
|
icon = "@ph/microphone-light[scale=0.9]"
|
||||||
indicator.circle.color = "#ffffff"
|
indicators.circle.color = "#ffffff"
|
||||||
indicator.circle.width = 2
|
indicators.circle.width = 2
|
||||||
indicator.circle.radius = 40
|
indicators.circle.radius = 20
|
||||||
|
|
||||||
mode.audio_volume.direction = "input"
|
mode.audio_volume.direction = "input"
|
||||||
mode.audio_volume.regex = "Microphone"
|
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]
|
[knobs.right-middle]
|
||||||
icon = "@apps/discord[scale=0.25]"
|
icon = "@apps/discord[scale=0.25]"
|
||||||
indicator.bar.color = "#ffffff"
|
indicators.bar.color = "#ffffff"
|
||||||
|
|
||||||
mode.audio_volume.regex = "Discord"
|
mode.audio_volume.regex = "Discord"
|
||||||
mode.audio_volume.style.active.label = "{percentage}%"
|
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]
|
[knobs.right-bottom]
|
||||||
icon = "@apps/spotify[scale=1.1]"
|
icon = "@apps/spotify[scale=1.1]"
|
||||||
indicator.bar.color = "#ffffff"
|
indicators.bar.color = "#ffffff50"
|
||||||
|
|
||||||
mode.audio_volume.regex = "Spotify"
|
mode.audio_volume.regex = "Spotify"
|
||||||
mode.audio_volume.style.active.label = "{percentage}%"
|
mode.audio_volume.style.active.label = "{percentage}%"
|
||||||
|
|
|
@ -7,11 +7,13 @@ use tokio::sync::broadcast;
|
||||||
|
|
||||||
use crate::model::knob_page::StyleByStateMap;
|
use crate::model::knob_page::StyleByStateMap;
|
||||||
use crate::model::position::KnobPath;
|
use crate::model::position::KnobPath;
|
||||||
use crate::modes::knob::KnobEvent;
|
use crate::modes::knob::{KnobEvent, RotationDirection};
|
||||||
use crate::runner::command::IoWorkerCommand;
|
use crate::runner::command::IoWorkerCommand;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
#[serde(default = "default_delta")]
|
||||||
|
pub delta: f32,
|
||||||
#[serde(with = "serde_regex")]
|
#[serde(with = "serde_regex")]
|
||||||
pub regex: Regex,
|
pub regex: Regex,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -28,6 +30,10 @@ pub struct Config {
|
||||||
pub style: StyleByStateMap<State>,
|
pub style: StyleByStateMap<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_delta() -> f32 {
|
||||||
|
0.05
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Eq, PartialEq, Deserialize)]
|
#[derive(Debug, Default, Eq, PartialEq, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum MutedTurnAction {
|
pub enum MutedTurnAction {
|
||||||
|
@ -54,11 +60,22 @@ pub enum State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle(path: KnobPath, config: Arc<Config>, mut events: broadcast::Receiver<(KnobPath, KnobEvent)>, commands: flume::Sender<IoWorkerCommand>) {
|
pub async fn handle(path: KnobPath, config: Arc<Config>, mut events: broadcast::Receiver<(KnobPath, KnobEvent)>, commands: flume::Sender<IoWorkerCommand>) {
|
||||||
|
let mut value: f32 = 0.0;
|
||||||
|
|
||||||
while let Ok((event_path, event)) = events.recv().await {
|
while let Ok((event_path, event)) = events.recv().await {
|
||||||
if event_path != path {
|
if event_path != path {
|
||||||
continue;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,4 +12,5 @@ pub enum IoWorkerCommand {
|
||||||
SetActivePages { key_page_id: String, knob_page_id: String },
|
SetActivePages { key_page_id: String, knob_page_id: String },
|
||||||
SetKeyStyle { path: KeyPath, value: Option<KeyStyle> },
|
SetKeyStyle { path: KeyPath, value: Option<KeyStyle> },
|
||||||
SetKnobStyle { path: KnobPath, value: Option<KnobStyle> },
|
SetKnobStyle { path: KnobPath, value: Option<KnobStyle> },
|
||||||
|
SetKnobValue { path: KnobPath, value: f32 },
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use bytes::{BufMut, Bytes, BytesMut};
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
use resvg::usvg::tiny_skia_path::PathBuilder;
|
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 tiny_skia::{Color, IntSize, LineCap, LineJoin, Paint, Pixmap, PremultipliedColorU8, Rect, Shader, Stroke, Transform};
|
||||||
|
|
||||||
use loupedeck_serial::util::Endianness;
|
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);
|
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()
|
convert_pixels_to_rgb565(pixmap.pixels(), context.buffer_endianness).freeze()
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::time::Instant;
|
||||||
use color_eyre::eyre::{ContextCompat, WrapErr};
|
use color_eyre::eyre::{ContextCompat, WrapErr};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use enum_ordinalize::Ordinalize;
|
use enum_ordinalize::Ordinalize;
|
||||||
use log::{info, trace};
|
use log::{error, info, trace};
|
||||||
use rgb::RGB8;
|
use rgb::RGB8;
|
||||||
use tiny_skia::IntSize;
|
use tiny_skia::IntSize;
|
||||||
use tokio::sync::broadcast;
|
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);
|
draw_knob_at_path_if_visible(context, state, path);
|
||||||
context.device.refresh_display(&context.device.characteristics().key_grid.display).unwrap();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue