More framework implementation
This commit is contained in:
parent
beb24e985e
commit
ec70ed2c51
1
Linux/Cargo.lock
generated
1
Linux/Cargo.lock
generated
@ -10,6 +10,7 @@ dependencies = [
|
||||
"log",
|
||||
"min-rs",
|
||||
"platform-dirs",
|
||||
"regex",
|
||||
"relm4",
|
||||
"relm4-icons",
|
||||
"rust-i18n",
|
||||
|
@ -8,6 +8,7 @@ build = "build.rs"
|
||||
env_logger = "0.11.3"
|
||||
log = "0.4.21"
|
||||
platform-dirs = "0.3.0"
|
||||
regex = "1.10.5"
|
||||
relm4 = "0.8.1"
|
||||
relm4-icons = "0.8.3"
|
||||
rust-i18n = "3.0.1"
|
||||
|
7
Linux/locales/actions/pipewire.yaml
Normal file
7
Linux/locales/actions/pipewire.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
_version: 2
|
||||
|
||||
actions:
|
||||
pipewire:
|
||||
set_volume:
|
||||
name:
|
||||
en: Set volume
|
6
Linux/locales/devices/emulator.yaml
Normal file
6
Linux/locales/devices/emulator.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
_version: 2
|
||||
|
||||
devices:
|
||||
emulator:
|
||||
name:
|
||||
en: Emulator
|
6
Linux/locales/devices/serial_min.yaml
Normal file
6
Linux/locales/devices/serial_min.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
_version: 2
|
||||
|
||||
devices:
|
||||
serial_min:
|
||||
name:
|
||||
en: Serial device using MIN protocol
|
@ -1,8 +1,32 @@
|
||||
pub mod registry;
|
||||
pub mod pipewire;
|
||||
|
||||
use crate::registry::MkRegistry;
|
||||
use crate::registry::RegistryItem;
|
||||
use crate::util::unique_id::UniqueId;
|
||||
|
||||
pub fn register()
|
||||
|
||||
pub struct MkAction
|
||||
{
|
||||
pipewire::register();
|
||||
pub unique_id: UniqueId
|
||||
}
|
||||
|
||||
|
||||
impl RegistryItem for MkAction
|
||||
{
|
||||
fn unique_id(&self) -> UniqueId
|
||||
{
|
||||
self.unique_id.clone()
|
||||
}
|
||||
|
||||
fn name(&self) -> String
|
||||
{
|
||||
t!(format!("actions.{}.name", self.unique_id.as_str()).as_str()).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn register(registry: &mut MkRegistry<MkAction>)
|
||||
{
|
||||
pipewire::register(registry);
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
use super::registry::{MkAction, register_action};
|
||||
|
||||
use crate::registry::MkRegistry;
|
||||
use crate::util::unique_id::UniqueId;
|
||||
use super::MkAction;
|
||||
|
||||
pub mod set_volume;
|
||||
|
||||
|
||||
pub fn register()
|
||||
pub fn register(registry: &mut MkRegistry<MkAction>)
|
||||
{
|
||||
register_action(MkAction::new("Set volume"));
|
||||
registry.register(MkAction
|
||||
{
|
||||
unique_id: UniqueId::new("pipewire.set_volume")
|
||||
});
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
use log::info;
|
||||
|
||||
|
||||
pub struct MkAction
|
||||
{
|
||||
// TODO prepare for i18n by making this a translation key?
|
||||
name: &'static str
|
||||
}
|
||||
|
||||
|
||||
impl MkAction
|
||||
{
|
||||
pub fn new(name: &'static str) -> Self
|
||||
{
|
||||
Self
|
||||
{
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn register_action(action: MkAction)
|
||||
{
|
||||
info!("Registered action: {}", action.name);
|
||||
}
|
@ -2,10 +2,11 @@ use std::path::{Path, PathBuf};
|
||||
use std::io::{Error, Read, Write};
|
||||
use platform_dirs::AppDirs;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config
|
||||
{
|
||||
root: PathBuf
|
||||
root: PathBuf,
|
||||
pub device_id: Option<String>
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +18,8 @@ impl Config
|
||||
|
||||
Self
|
||||
{
|
||||
root: appdirs.data_dir
|
||||
root: appdirs.data_dir,
|
||||
device_id: None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
//use emulatorwindow::EmulatorWindow;
|
||||
//use relm4::prelude::*;
|
||||
//use relm4::gtk::prelude::GtkApplicationExt;
|
||||
|
||||
|
||||
use super::registry::{MkDevice, register_device};
|
||||
use crate::registry::MkRegistry;
|
||||
use crate::util::unique_id::UniqueId;
|
||||
use super::MkDevice;
|
||||
|
||||
|
||||
pub mod emulatorwindow;
|
||||
|
||||
|
||||
pub fn register()
|
||||
|
||||
|
||||
pub fn register(registry: &mut MkRegistry<MkDevice>)
|
||||
{
|
||||
register_device(MkDevice::new("Emulator"));
|
||||
registry.register(MkDevice {
|
||||
unique_id: UniqueId::new("emulator")
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,10 +1,35 @@
|
||||
pub mod registry;
|
||||
pub mod emulator;
|
||||
pub mod serial_min;
|
||||
|
||||
|
||||
pub fn register()
|
||||
use crate::registry::MkRegistry;
|
||||
use crate::registry::RegistryItem;
|
||||
use crate::util::unique_id::UniqueId;
|
||||
|
||||
|
||||
pub struct MkDevice
|
||||
{
|
||||
emulator::register();
|
||||
serial_min::register();
|
||||
pub unique_id: UniqueId
|
||||
}
|
||||
|
||||
|
||||
impl RegistryItem for MkDevice
|
||||
{
|
||||
fn unique_id(&self) -> UniqueId
|
||||
{
|
||||
self.unique_id.clone()
|
||||
}
|
||||
|
||||
fn name(&self) -> String
|
||||
{
|
||||
t!(format!("devices.{}.name", self.unique_id.as_str()).as_str()).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn register(registry: &mut MkRegistry<MkDevice>)
|
||||
{
|
||||
emulator::register(registry);
|
||||
serial_min::register(registry);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
use log::info;
|
||||
|
||||
|
||||
pub struct MkDevice
|
||||
{
|
||||
// TODO prepare for i18n by making this a translation key?
|
||||
name: &'static str
|
||||
}
|
||||
|
||||
|
||||
impl MkDevice
|
||||
{
|
||||
pub fn new(name: &'static str) -> Self
|
||||
{
|
||||
Self
|
||||
{
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn register_device(action: MkDevice)
|
||||
{
|
||||
info!("Registered device: {}", action.name);
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
use super::registry::{MkDevice, register_device};
|
||||
use crate::registry::MkRegistry;
|
||||
use crate::util::unique_id::UniqueId;
|
||||
use super::MkDevice;
|
||||
|
||||
|
||||
pub fn register()
|
||||
pub fn register(registry: &mut MkRegistry<MkDevice>)
|
||||
{
|
||||
register_device(MkDevice::new("Serial device using MIN protocol"));
|
||||
registry.register(MkDevice {
|
||||
unique_id: UniqueId::new("serial_min")
|
||||
});
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
use env_logger::Env;
|
||||
use mainwindow::MainWindowViewModel;
|
||||
use orchestrator::Orchestrator;
|
||||
use relm4::prelude::*;
|
||||
|
||||
#[macro_use]
|
||||
@ -7,10 +10,13 @@ extern crate rust_i18n;
|
||||
i18n!("locales");
|
||||
|
||||
|
||||
pub mod util;
|
||||
pub mod registry;
|
||||
pub mod devices;
|
||||
pub mod actions;
|
||||
|
||||
pub mod config;
|
||||
pub mod orchestrator;
|
||||
pub mod mainwindow;
|
||||
|
||||
fn main()
|
||||
@ -19,20 +25,13 @@ fn main()
|
||||
// .format_timestamp(None)
|
||||
.init();
|
||||
|
||||
devices::register();
|
||||
actions::register();
|
||||
|
||||
relm4_icons::initialize_icons();
|
||||
|
||||
load_config();
|
||||
let orchestrator = Rc::new(Orchestrator::new());
|
||||
|
||||
let app = RelmApp::new("com.github.mvrens.massiveknob");
|
||||
app.run::<mainwindow::MainWindow>(());
|
||||
}
|
||||
|
||||
|
||||
fn load_config()
|
||||
app.run::<mainwindow::MainWindow>(MainWindowViewModel
|
||||
{
|
||||
//let config = config::Config::new();
|
||||
//config.get_reader(name)
|
||||
orchestrator: Rc::clone(&orchestrator)
|
||||
});
|
||||
}
|
@ -1,11 +1,31 @@
|
||||
use std::rc::Rc;
|
||||
use gtk::prelude::*;
|
||||
use relm4::prelude::*;
|
||||
|
||||
use crate::orchestrator::Orchestrator;
|
||||
|
||||
pub struct MainWindow
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
pub struct MainWindowViewModel
|
||||
{
|
||||
pub orchestrator: Rc<Orchestrator>
|
||||
}
|
||||
|
||||
|
||||
impl std::fmt::Debug for MainWindowViewModel
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
||||
{
|
||||
f.debug_struct("MainWindowViewModel")
|
||||
// Skip orchestrator
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MainWindowMsg
|
||||
{
|
||||
@ -19,7 +39,7 @@ pub struct MainWindowWidgets
|
||||
|
||||
impl SimpleComponent for MainWindow
|
||||
{
|
||||
type Init = ();
|
||||
type Init = MainWindowViewModel;
|
||||
type Input = MainWindowMsg;
|
||||
type Output = ();
|
||||
type Root = gtk::Window;
|
||||
|
53
Linux/src/orchestrator/mod.rs
Normal file
53
Linux/src/orchestrator/mod.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use crate::actions;
|
||||
use crate::actions::MkAction;
|
||||
use crate::config::Config;
|
||||
use crate::devices;
|
||||
use crate::devices::MkDevice;
|
||||
use crate::registry::MkRegistry;
|
||||
use crate::util::unique_id::UniqueId;
|
||||
|
||||
|
||||
pub struct Orchestrator
|
||||
{
|
||||
config: Config,
|
||||
|
||||
device_registry: MkRegistry<MkDevice>,
|
||||
action_registry: MkRegistry<MkAction>
|
||||
}
|
||||
|
||||
|
||||
impl Orchestrator
|
||||
{
|
||||
pub fn new() -> Self
|
||||
{
|
||||
let config = Config::new();
|
||||
//config.get_reader(name)
|
||||
|
||||
let mut device_registry = MkRegistry::new();
|
||||
let mut action_registry = MkRegistry::new();
|
||||
|
||||
devices::register(&mut device_registry);
|
||||
actions::register(&mut action_registry);
|
||||
|
||||
Self
|
||||
{
|
||||
config,
|
||||
device_registry,
|
||||
action_registry
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn current_device(&self) -> Option<&MkDevice>
|
||||
{
|
||||
let Some(device_id) = &self.config.device_id else { return None };
|
||||
self.device_registry.by_id(UniqueId::new(device_id.as_str()))
|
||||
}
|
||||
|
||||
|
||||
pub fn set_current_device_id(&self, id: &str)
|
||||
{
|
||||
// TODO if changed, unload old device, activate new
|
||||
todo!("Store in config");
|
||||
}
|
||||
}
|
50
Linux/src/registry/mod.rs
Normal file
50
Linux/src/registry/mod.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use std::collections::HashMap;
|
||||
use log::info;
|
||||
|
||||
use crate::util::unique_id::UniqueId;
|
||||
|
||||
|
||||
pub trait RegistryItem
|
||||
{
|
||||
/// The unique ID of the item. This should remain stable across releases for
|
||||
/// the purpose of storing it in the user's configuration.
|
||||
fn unique_id(&self) -> UniqueId;
|
||||
|
||||
/// The name of the item for display purposes.
|
||||
fn name(&self) -> String;
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub struct MkRegistry<T> where T: RegistryItem
|
||||
{
|
||||
items: HashMap<String, T>
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'a, T> MkRegistry<T> where T: RegistryItem
|
||||
{
|
||||
pub fn new() -> Self
|
||||
{
|
||||
Self
|
||||
{
|
||||
items: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn register(&mut self, device: T)
|
||||
{
|
||||
let device_id = device.unique_id();
|
||||
|
||||
info!("Registered device: [{}] {}", device_id.as_str(), device.name());
|
||||
self.items.insert(String::from(device_id.as_str()), device);
|
||||
}
|
||||
|
||||
|
||||
pub fn by_id(&self, id: UniqueId) -> Option<&T>
|
||||
{
|
||||
self.items.get(id.as_str())
|
||||
}
|
||||
}
|
1
Linux/src/util/mod.rs
Normal file
1
Linux/src/util/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod unique_id;
|
38
Linux/src/util/unique_id.rs
Normal file
38
Linux/src/util/unique_id.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use regex::Regex;
|
||||
|
||||
|
||||
pub struct UniqueId
|
||||
{
|
||||
inner: String,
|
||||
}
|
||||
|
||||
|
||||
impl UniqueId
|
||||
{
|
||||
pub fn new(id: &str) -> Self
|
||||
{
|
||||
assert!(is_valid_unique_id(id), "Id '{id}' has invalid characters");
|
||||
UniqueId { inner: id.to_string() }
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str
|
||||
{
|
||||
self.inner.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn is_valid_unique_id(id: &str) -> bool
|
||||
{
|
||||
let re = Regex::new(r"^[a-zA-Z0-9\.\-_]+$").unwrap();
|
||||
re.is_match(id)
|
||||
}
|
||||
|
||||
|
||||
impl Clone for UniqueId
|
||||
{
|
||||
fn clone(&self) -> Self
|
||||
{
|
||||
Self { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user