122 lines
3.7 KiB
Rust
122 lines
3.7 KiB
Rust
use std::path::Path;
|
|
use std::sync::Arc;
|
|
use std::thread;
|
|
|
|
use color_eyre::eyre::{ContextCompat, WrapErr};
|
|
use color_eyre::Result;
|
|
use log::info;
|
|
use tokio::sync::broadcast;
|
|
|
|
use deckster_shared::handler_communication::{HandlerCommand, HandlerEvent};
|
|
use deckster_shared::path::{KeyPath, KnobPath};
|
|
use loupedeck_serial::commands::VibrationPattern;
|
|
use loupedeck_serial::device::LoupedeckDevice;
|
|
|
|
use crate::handler_host;
|
|
use crate::handler_host::KeyOrKnobConfig;
|
|
use crate::model::config::Config;
|
|
use crate::runner::io_worker::{do_io_work, IoWorkerContext};
|
|
use crate::runner::mqtt::start_mqtt_client;
|
|
|
|
mod graphics;
|
|
mod io_worker;
|
|
mod mqtt;
|
|
pub mod state;
|
|
|
|
pub async fn start(config_directory: &Path, config: Config) -> Result<()> {
|
|
let config = Arc::new(config);
|
|
info!("Discovering devices…");
|
|
|
|
let available_devices = LoupedeckDevice::discover()?;
|
|
let available_device = available_devices.first().wrap_err("No device connected.")?;
|
|
info!("Found {} device(s).", available_devices.len());
|
|
|
|
let (commands_sender, commands_receiver) = flume::bounded::<HandlerCommand>(5);
|
|
let events_sender = broadcast::Sender::<HandlerEvent>::new(5);
|
|
|
|
commands_sender
|
|
.send(HandlerCommand::SetActivePages {
|
|
knob_page_id: config.initial.knob_page.clone(),
|
|
key_page_id: config.initial.key_page.clone(),
|
|
})
|
|
.unwrap();
|
|
|
|
let key_configs = config
|
|
.key_pages_by_id
|
|
.iter()
|
|
.flat_map(|(page_id, p)| {
|
|
p.keys.iter().map(|(position, k)| {
|
|
(
|
|
KeyPath {
|
|
page_id: page_id.clone(),
|
|
position: *position,
|
|
},
|
|
KeyOrKnobConfig {
|
|
handler_name: k.handler.as_str().into(),
|
|
handler_config: Arc::clone(&k.config),
|
|
},
|
|
)
|
|
})
|
|
})
|
|
.collect();
|
|
|
|
let knob_configs = config
|
|
.knob_pages_by_id
|
|
.iter()
|
|
.flat_map(|(page_id, p)| {
|
|
p.knobs.iter().filter_map(|(position, k)| {
|
|
if k.handler.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
Some((
|
|
KnobPath {
|
|
page_id: page_id.clone(),
|
|
position,
|
|
},
|
|
KeyOrKnobConfig {
|
|
handler_name: k.handler.as_str().into(),
|
|
handler_config: Arc::clone(&k.config),
|
|
},
|
|
))
|
|
})
|
|
})
|
|
.collect();
|
|
|
|
info!("Initializing handler processes…");
|
|
|
|
handler_host::start(
|
|
&config_directory.join("handlers"),
|
|
key_configs,
|
|
knob_configs,
|
|
commands_sender.clone(),
|
|
events_sender.subscribe(),
|
|
)
|
|
.await?;
|
|
|
|
if let Some(mqtt_config) = &config.mqtt {
|
|
info!("Initializing MQTT client…");
|
|
start_mqtt_client(mqtt_config, commands_sender.clone(), events_sender.subscribe()).await;
|
|
}
|
|
|
|
info!("Connecting to the device…");
|
|
let device = available_device.connect().wrap_err("Connecting to the device failed.")?;
|
|
info!("Connected.");
|
|
|
|
device.set_brightness(0.5);
|
|
device.vibrate(VibrationPattern::RiseFall);
|
|
|
|
let io_worker_context = IoWorkerContext::create(config_directory, Arc::clone(&config), device, commands_sender.clone(), events_sender);
|
|
|
|
let io_worker_thread = thread::Builder::new()
|
|
.name("deckster IO worker".to_owned())
|
|
.spawn(move || {
|
|
do_io_work(io_worker_context, commands_receiver);
|
|
})
|
|
.wrap_err("Could not spawn the worker thread")?;
|
|
|
|
info!("Ready.");
|
|
io_worker_thread.join().unwrap();
|
|
|
|
Ok(())
|
|
}
|