Skip to content

Commit

Permalink
Merge pull request #19 from confusinguser/noise-map-module
Browse files Browse the repository at this point in the history
Implement noise map module
  • Loading branch information
confusinguser authored Feb 19, 2024
2 parents 3c1cc8f + d7e7992 commit ef35c36
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 13 deletions.
97 changes: 88 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ souvlaki = { version = "0.7.0", default-features = false, features = ["use_zbus"
tokio-util = { version = "0.7.10", features = ["rt"] }
clap = { version = "^4.4", features = ["derive", "cargo"] }
hsv = "0.1.1"
noise = "0.8.2"
4 changes: 2 additions & 2 deletions src/core/keyboard_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ impl KeyboardController {
if cancellation_token.is_cancelled() {
break;
}
// Get all messages that are currently in the receiver (max 100)
// Get all messages that are currently in the receiver (max 200)
let mut time_of_urgent_flag = None;
loop {
let all_messages_len = all_messages.len();
if all_messages_len >= 200 {
println!("Over 100 messages were received in the same cycle");
println!("Over 200 messages were received in the same cycle");
break;
}
let sleep_until = if let Some(urgent_flag) = time_of_urgent_flag {
Expand Down
12 changes: 10 additions & 2 deletions src/core/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

use crate::modules::media_playing::MediaModule;
use crate::modules::noise::{NoiseModule, NoiseModuleOptions};
use crate::modules::starfield::{StarfieldModule, StarfieldModuleOptions};
use crate::modules::workspaces::WorkspacesModule;

Expand All @@ -28,6 +29,7 @@ pub(crate) enum ModuleType {
Workspaces,
Media,
Starfield(StarfieldModuleOptions),
Noise(NoiseModuleOptions),
}

impl ModuleType {
Expand All @@ -48,29 +50,35 @@ impl ModuleType {
ModuleType::Starfield(opts) => {
StarfieldModule::run(task_tracker, cancellation_token, sender, module_leds, *opts)
}
ModuleType::Noise(opts) => {
NoiseModule::run(task_tracker, cancellation_token, sender, module_leds, *opts)
}
}
}

pub(crate) fn name(&self) -> &'static str {
match self {
ModuleType::Workspaces => "Sway Workspaces",
ModuleType::Media => "Media Player Monitor",
ModuleType::Starfield(_) => "Starfield Ambient Module",
ModuleType::Starfield(_) => "Starfield Ambient",
ModuleType::Noise(_) => "Noise",
}
}
pub(crate) fn desc(&self) -> &'static str {
match self {
ModuleType::Workspaces => "",
ModuleType::Media => "Shows media playhead and platform on keyboard",
ModuleType::Starfield(_) => "",
ModuleType::Noise(_) => "Noise thing",
}
}

pub(crate) fn all_module_types() -> [ModuleType; 3] {
pub(crate) fn all_module_types() -> [ModuleType; 4] {
[
ModuleType::Workspaces,
ModuleType::Media,
ModuleType::Starfield(StarfieldModuleOptions::default()),
ModuleType::Noise(NoiseModuleOptions::default()),
]
}
}
1 change: 1 addition & 0 deletions src/modules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub(crate) mod media_playing;
pub(crate) mod noise;
pub(crate) mod starfield;
pub(crate) mod workspaces;
112 changes: 112 additions & 0 deletions src/modules/noise.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
use std::time::{Duration, Instant};

use hsv::hsv_to_rgb;
use noise::NoiseFn;
use rand::random;
use rgb::{RGB, RGB8};
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc::Sender;
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

use crate::core::keyboard_controller::{KeyboardController, KeyboardControllerMessage};
use crate::core::utils;

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub(crate) struct NoiseModuleOptions {
pub(crate) color1: RGB8,
pub(crate) color2: RGB8,
/// Per second
pub(crate) speed: f32,
/// Divides coordinates by value
#[serde(default)]
pub(crate) zoom_in: f32,
}

impl Default for NoiseModuleOptions {
fn default() -> Self {
Self {
color1: RGB::from(hsv_to_rgb(44., 0.99, 0.02)),
color2: RGB::from(hsv_to_rgb(44., 0.99, 0.15)),
speed: 0.01,
zoom_in: 3.,
}
}
}

pub(crate) struct NoiseModule {}

impl NoiseModule {
pub fn run(
task_tracker: &TaskTracker,
cancellation_token: CancellationToken,
mut sender: Sender<KeyboardControllerMessage>,
module_leds: Vec<Option<u32>>,
_options: NoiseModuleOptions,
) {
task_tracker.spawn(async move {
let options = NoiseModuleOptions::default();
let mut depth = 0.;
let mut last_update = Instant::now();
let noise = noise::SuperSimplex::new(0);
let offset: (f64, f64) = (random(), random());

loop {
if cancellation_token.is_cancelled() {
break;
}

let now = Instant::now();
// If we have two nones back to back, we consider that a line break
let mut back_to_back_nones = 0;
let mut current_row = 0;
let mut first_in_this_row = 0;
for (i, led) in module_leds.iter().enumerate() {
let Some(led) = led else {
back_to_back_nones += 1;
if back_to_back_nones == 2 {
current_row += 1;
first_in_this_row = i + 1;
back_to_back_nones = 0;
}
continue;
};

let x = i - first_in_this_row;
KeyboardController::update_led(
&mut sender,
*led,
led_value(
&noise,
options.color1,
options.color2,
depth as f64,
x as f64 / options.zoom_in as f64 + offset.0,
current_row as f64 / options.zoom_in as f64 + offset.1,
),
)
.await
.unwrap();

depth += (now - last_update).as_secs_f32() * options.speed;
back_to_back_nones = 0;
}

last_update = Instant::now();
tokio::time::sleep(Duration::from_millis(20)).await;
}
});
}
}

fn led_value<T: NoiseFn<f64, 3>>(
noise: &T,
background: RGB8,
target: RGB8,
depth: f64,
x: f64,
y: f64,
) -> rgb::RGB<u8> {
let interpolation = noise.get([x, y, depth]);
utils::interpolate(background, target, interpolation as f32)
}

0 comments on commit ef35c36

Please sign in to comment.