Skip to content

Commit

Permalink
Merge pull request #16 from confusinguser/keyboard-controller-overhaul
Browse files Browse the repository at this point in the history
Keyboard controller overhaul
  • Loading branch information
confusinguser authored Feb 11, 2024
2 parents c807f22 + 823559c commit 0829611
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 164 deletions.
33 changes: 28 additions & 5 deletions src/cli/main_command.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::bail;
use clap::{arg, command, value_parser, ArgMatches, Command};
use tokio::sync::{mpsc, Mutex};
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

use crate::core::config_manager::Configuration;
use crate::core::keyboard_controller::KeyboardController;
use crate::core::{config_creator, config_manager, utils};

Expand Down Expand Up @@ -59,9 +62,19 @@ pub(crate) async fn main_command(matches: ArgMatches) -> anyhow::Result<()> {
}

async fn create_config(args: &ArgMatches) -> anyhow::Result<()> {
let keyboard_controller = KeyboardController::connect(Configuration::default()).await?;
let keyboard_controller = KeyboardController::connect().await?;
let (mut sender, receiver) = mpsc::channel(100);
let cancellation_token = CancellationToken::new();
let keyboard_controller = Arc::new(Mutex::new(keyboard_controller));
KeyboardController::run(
keyboard_controller.clone(),
&TaskTracker::new(),
cancellation_token,
receiver,
);
let new_config = config_creator::start_config_creator(
&keyboard_controller,
keyboard_controller,
&mut sender,
args.get_one::<u32>("ledlimit").copied(),
)
.await?;
Expand All @@ -72,9 +85,19 @@ async fn create_config(args: &ArgMatches) -> anyhow::Result<()> {
async fn create_keymap(args: &ArgMatches) -> anyhow::Result<()> {
// TODO Confirm that the user wants to do this
let keymap_path = utils::get_keymap_path(args)?;
let keyboard_controller = KeyboardController::connect(Configuration::default()).await?;
let keyboard_controller = KeyboardController::connect().await?;
let (mut sender, receiver) = mpsc::channel(100);
let cancellation_token = CancellationToken::new();
let keyboard_controller = Arc::new(Mutex::new(keyboard_controller));
KeyboardController::run(
keyboard_controller.clone(),
&TaskTracker::new(),
cancellation_token,
receiver,
);
let new_keymap = config_creator::create_keymap(
&keyboard_controller,
keyboard_controller,
&mut sender,
args.get_one::<u32>("ledlimit").copied(),
)
.await?;
Expand Down
59 changes: 36 additions & 23 deletions src/cli/module_subcommand.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use std::io::{self, BufRead};
use std::sync::Arc;
use tokio::sync::Mutex;

use anyhow::bail;
use clap::ArgMatches;
use crossterm::event::{Event, KeyCode, KeyModifiers, MouseButton, MouseEventKind};
use openrgb::data::Color;
use tokio::sync::mpsc::{self, Sender};
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

use crate::core::config_manager::{self, Configuration};
use crate::core::keyboard_controller::KeyboardController;
use crate::core::keyboard_controller::{KeyboardController, KeyboardControllerMessage};
use crate::core::module::{Module, ModuleType};
use crate::core::utils::{
self, default_terminal_settings, highlight_all_modules, highlight_one_module,
Expand All @@ -17,13 +22,22 @@ pub async fn module(args: &ArgMatches) -> anyhow::Result<()> {
let config_path = utils::get_config_path(args)?;
let keymap_path = utils::get_keymap_path(args)?;
let mut config = config_manager::read_config_and_keymap(&config_path, &keymap_path)?;
let keyboard_controller = KeyboardController::connect(Configuration::default()).await?;
keyboard_controller.turn_all_off().await?;
let keyboard_controller = KeyboardController::connect().await?;
let (mut sender, receiver) = mpsc::channel(100);
let cancellation_token = CancellationToken::new();
let keyboard_controller = Arc::new(Mutex::new(keyboard_controller));
KeyboardController::run(
keyboard_controller.clone(),
&TaskTracker::new(),
cancellation_token,
receiver,
);
KeyboardController::turn_all_off(&mut sender).await?;

match args.subcommand_name() {
Some("add") => add(&keyboard_controller, &mut config).await?,
Some("remove") => remove(&keyboard_controller, &mut config).await?,
Some("info") => info(&keyboard_controller, &mut config).await?,
Some("add") => add(&mut sender, &mut config).await?,
Some("remove") => remove(&mut sender, &mut config).await?,
Some("info") => info(&mut sender, &mut config).await?,
Some("modify") => todo!(),
_ => todo!(),
}
Expand All @@ -34,19 +48,19 @@ pub async fn module(args: &ArgMatches) -> anyhow::Result<()> {
}

pub async fn add(
keyboard_controller: &KeyboardController,
sender: &mut Sender<KeyboardControllerMessage>,
config: &mut Configuration,
) -> anyhow::Result<()> {
println!("Choose a module to add:");
let module_type = choose_module_type_to_add()?;
println!("Click the buttons which are in this module IN ORDER from left to right. Press LMB when done. Press RMB to add a button to the module which is not tied to any LED");
add_module(keyboard_controller, config, module_type).await?;
add_module(sender, config, module_type).await?;

Ok(())
}

async fn add_module(
keyboard_controller: &KeyboardController,
sender: &mut Sender<KeyboardControllerMessage>,
config: &mut Configuration,
module_type: ModuleType,
) -> anyhow::Result<()> {
Expand All @@ -71,8 +85,7 @@ async fn add_module(
continue;
}
module_leds.push(Some(index_pressed));
keyboard_controller
.set_led_by_index(index_pressed, Color::new(255, 255, 255))
KeyboardController::update_led(sender, index_pressed, Color::new(255, 255, 255))
.await?;
} else {
println!("This button is not tied to an LED, it can't be used in module");
Expand All @@ -93,7 +106,7 @@ async fn add_module(
}
}
default_terminal_settings()?;
keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
Ok(())
}

Expand All @@ -118,7 +131,7 @@ fn choose_module_type_to_add() -> anyhow::Result<ModuleType> {
}

pub async fn remove(
keyboard_controller: &KeyboardController,
sender: &mut Sender<KeyboardControllerMessage>,
config: &mut Configuration,
) -> anyhow::Result<()> {
if config.modules.is_empty() {
Expand All @@ -127,7 +140,7 @@ pub async fn remove(
}

println!("Choose a module to remove by clicking on a button in it");
highlight_all_modules(keyboard_controller, config, 100., 100.).await?;
highlight_all_modules(sender, config, 100., 100.).await?;

utils::prepare_terminal_event_capture()?;
loop {
Expand Down Expand Up @@ -159,9 +172,9 @@ pub async fn remove(
}
}
if let Some(module_selected) = module_selected {
keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
highlight_one_module(
keyboard_controller,
sender,
config.modules.len(),
module_selected.0,
module_selected.1,
Expand All @@ -177,7 +190,7 @@ pub async fn remove(
if module_removal_confirmed {
config.modules.remove(module_selected.0);
}
keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
break;
} else {
println!("This button is not tied to a module");
Expand All @@ -204,11 +217,11 @@ Number of LEDs: {}",
}

async fn info(
keyboard_controller: &KeyboardController,
sender: &mut Sender<KeyboardControllerMessage>,
config: &mut Configuration,
) -> anyhow::Result<()> {
println!("Choose a module to get info on by clicking a button in it");
highlight_all_modules(keyboard_controller, config, 100., 100.).await?;
highlight_all_modules(sender, config, 100., 100.).await?;

utils::prepare_terminal_event_capture()?;
loop {
Expand Down Expand Up @@ -243,12 +256,12 @@ async fn info(
// TODO Make user select between each module that has this button, also for remove
// subcommand
print_module_info(module_selected);
keyboard_controller.turn_all_off().await?;
highlight_all_modules(keyboard_controller, config, 80., 10.).await?;
highlight_one_module_rainbow(keyboard_controller, module_selected).await?;
KeyboardController::turn_all_off(sender).await?;
highlight_all_modules(sender, config, 80., 10.).await?;
highlight_one_module_rainbow(sender, module_selected).await?;
utils::pause_until_click()?;

keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
break;
} else {
println!("This button is not tied to a module");
Expand Down
19 changes: 13 additions & 6 deletions src/cli/start_subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,32 @@ use std::sync::Arc;

use clap::ArgMatches;
use tokio::signal;
use tokio::sync::{mpsc, Mutex};
use tokio_util::sync::CancellationToken;
use tokio_util::task::TaskTracker;

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

pub(crate) async fn start(args: &ArgMatches) -> anyhow::Result<()> {
let config = config_manager::read_config_and_keymap_from_args(args)?;
let keyboard_controller = KeyboardController::connect(config).await?;
let (sender, receiver) = mpsc::channel::<KeyboardControllerMessage>(100);
let keyboard_controller = KeyboardController::connect().await?;

let cancellation_token = CancellationToken::new();
keyboard_controller.turn_all_off().await?;
let keyboard_controller = Arc::new(keyboard_controller);
let keyboard_controller = Arc::new(Mutex::new(keyboard_controller));
let task_tracker = TaskTracker::new();
for module in &keyboard_controller.config.modules {
KeyboardController::run(
keyboard_controller,
&task_tracker,
cancellation_token.clone(),
receiver,
);
for module in &config.modules {
module.module_type.run(
&task_tracker,
cancellation_token.clone(),
keyboard_controller.clone(),
sender.clone(),
module.module_leds.clone(),
);
}
Expand Down
47 changes: 25 additions & 22 deletions src/core/config_creator.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
use std::sync::Arc;
use tokio::sync::Mutex;

use crossterm::event::*;
use openrgb::data::Color;
use tokio::sync::mpsc::Sender;

use crate::cli::module_subcommand;
use crate::core::config_manager::Configuration;
use crate::core::keymap::Keymap;
use crate::core::utils::default_terminal_settings;

use super::keyboard_controller::KeyboardController;
use super::keyboard_controller::{KeyboardController, KeyboardControllerMessage};
use super::utils::prepare_terminal_event_capture;

pub(crate) async fn start_config_creator(
keyboard_controller: &KeyboardController,
keyboard_controller: Arc<Mutex<KeyboardController>>,
sender: &mut Sender<KeyboardControllerMessage>,
led_limit: Option<u32>,
) -> anyhow::Result<Configuration> {
let mut config = Configuration::default();
println!("Press every key as it lights up. If no key lights up, press LMB. If no reaction is given when key is pressed, press RMB");
build_key_led_map(keyboard_controller, &mut config.keymap, led_limit).await?;
build_key_led_map(keyboard_controller, sender, &mut config.keymap, led_limit).await?;
println!(
"Press the first key of every row. In order. When all of them have been pressed, press LMB"
);
build_first_in_row(keyboard_controller, &mut config.keymap).await?;
build_first_in_row(sender, &mut config.keymap).await?;
println!("Now, we're going to place the modules");
module_subcommand::add(keyboard_controller, &mut config).await?;
module_subcommand::add(sender, &mut config).await?;
Ok(config)
}

async fn build_first_in_row(
keyboard_controller: &KeyboardController,
sender: &mut Sender<KeyboardControllerMessage>,
keymap: &mut Keymap,
) -> anyhow::Result<()> {
prepare_terminal_event_capture()?;
keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
loop {
let event = crossterm::event::read().unwrap();
if let Event::Key(event) = event {
Expand All @@ -44,8 +49,7 @@ async fn build_first_in_row(
}
if let Some(&index_pressed) = keymap.key_led_map.get(&event.code) {
keymap.first_in_row.push(index_pressed);
keyboard_controller
.set_led_by_index(index_pressed, Color::new(255, 255, 255))
KeyboardController::update_led(sender, index_pressed, Color::new(255, 255, 255))
.await?;
} else {
default_terminal_settings()?;
Expand All @@ -57,7 +61,7 @@ async fn build_first_in_row(
if event.kind == MouseEventKind::Down(MouseButton::Left) {
default_terminal_settings()?;
println!("Great. There are {} rows", keymap.first_in_row.len());
keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
break;
}
}
Expand All @@ -67,25 +71,23 @@ async fn build_first_in_row(
}

async fn build_key_led_map(
keyboard_controller: &KeyboardController,
keyboard_controller: Arc<Mutex<KeyboardController>>,
sender: &mut Sender<KeyboardControllerMessage>,
keymap: &mut Keymap,
led_limit: Option<u32>,
) -> anyhow::Result<()> {
prepare_terminal_event_capture()?;
keyboard_controller.turn_all_off().await?;
KeyboardController::turn_all_off(sender).await?;
for index in 0..keyboard_controller
.num_leds()
.lock()
.await
.num_leds()
.min(led_limit.unwrap_or(u32::MAX))
{
if index != 0 {
keyboard_controller
.set_led_by_index(index - 1, Color::new(0, 0, 0))
.await?;
KeyboardController::update_led(sender, index - 1, Color::new(0, 0, 0)).await?;
}
keyboard_controller
.set_led_by_index(index, Color::new(255, 255, 255))
.await?;
KeyboardController::update_led(sender, index, Color::new(255, 255, 255)).await?;
loop {
let event = crossterm::event::read().unwrap();
match event {
Expand Down Expand Up @@ -121,15 +123,16 @@ async fn build_key_led_map(
}

pub(crate) async fn create_keymap(
keyboard_controller: &KeyboardController,
keyboard_controller: Arc<Mutex<KeyboardController>>,
sender: &mut Sender<KeyboardControllerMessage>,
led_limit: Option<u32>,
) -> anyhow::Result<Keymap> {
let mut keymap = Keymap::default();
println!("Press every key as it lights up. If no key lights up, press LMB. If no reaction is given when key is pressed, press RMB");
build_key_led_map(keyboard_controller, &mut keymap, led_limit).await?;
build_key_led_map(keyboard_controller, sender, &mut keymap, led_limit).await?;
println!(
"Press the first key of every row. In order. When all of them have been pressed, press LMB"
);
build_first_in_row(keyboard_controller, &mut keymap).await?;
build_first_in_row(sender, &mut keymap).await?;
Ok(keymap)
}
Loading

0 comments on commit 0829611

Please sign in to comment.