1
0
mirror of synced 2024-11-24 19:53:09 +01:00

More framework implementation

This commit is contained in:
Mark van Renswoude 2024-06-22 10:28:40 +02:00
parent beb24e985e
commit ec70ed2c51
19 changed files with 280 additions and 90 deletions

1
Linux/Cargo.lock generated
View File

@ -10,6 +10,7 @@ dependencies = [
"log",
"min-rs",
"platform-dirs",
"regex",
"relm4",
"relm4-icons",
"rust-i18n",

View File

@ -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"

View File

@ -0,0 +1,7 @@
_version: 2
actions:
pipewire:
set_volume:
name:
en: Set volume

View File

@ -0,0 +1,6 @@
_version: 2
devices:
emulator:
name:
en: Emulator

View File

@ -0,0 +1,6 @@
_version: 2
devices:
serial_min:
name:
en: Serial device using MIN protocol

View File

@ -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);
}

View File

@ -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")
});
}

View File

@ -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);
}

View File

@ -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
}
}

View File

@ -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")
});
}
/*

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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")
});
}

View File

@ -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()
{
//let config = config::Config::new();
//config.get_reader(name)
app.run::<mainwindow::MainWindow>(MainWindowViewModel
{
orchestrator: Rc::clone(&orchestrator)
});
}

View File

@ -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;

View 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
View 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
View File

@ -0,0 +1 @@
pub mod unique_id;

View 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() }
}
}