diff --git a/pyproject.toml b/pyproject.toml index 98de78b..1eff3c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "voicemeeter-compact" -version = "1.7.0" +version = "1.7.1" description = "A Compact Voicemeeter Remote App" authors = ["onyx-and-iris "] license = "MIT" diff --git a/vmcompact/app.py b/vmcompact/app.py index 3ff45bb..78dd0f8 100644 --- a/vmcompact/app.py +++ b/vmcompact/app.py @@ -1,9 +1,11 @@ import tkinter as tk +from functools import cached_property from pathlib import Path from tkinter import ttk from typing import NamedTuple from .builders import MainFrameBuilder +from .configurations import loader from .data import _base_values, _configuration, _kinds_all from .errors import VMCompactError from .menu import Menus @@ -41,6 +43,7 @@ class App(tk.Tk): self.iconbitmap(str(icon_path)) self.minsize(275, False) self.subject = Subject() + self._configs = None self["menu"] = Menus(self, vmr) self.styletable = ttk.Style() if _configuration.config: @@ -130,6 +133,11 @@ class App(tk.Tk): self.drag_id = "" _base_values.dragging = False + @cached_property + def userconfigs(self): + self._configs = loader(self.kind.name) + return self._configs + _apps = {kind.name: App.make(kind) for kind in _kinds_all} diff --git a/vmcompact/configurations.py b/vmcompact/configurations.py index da91b47..60c4de6 100644 --- a/vmcompact/configurations.py +++ b/vmcompact/configurations.py @@ -26,7 +26,7 @@ for configpath in configpaths: try: with open(filepath, "rb") as f: configs[filename] = tomllib.load(f) - logger.info(f"{filename} loaded into memory") + logger.info(f"configuration: {filename} loaded into memory") except tomllib.TOMLDecodeError: logger.error(f"Invalid TOML config: configs/{filename.stem}") @@ -66,3 +66,19 @@ else: def get_configuration(key): if key in configuration: return configuration[key] + + +def loader(kind_id): + configs = {} + userconfigpath = Path.home() / ".config" / "vm-compact" / "configs" / kind_id + if userconfigpath.exists(): + filepaths = list(userconfigpath.glob("*.toml")) + for filepath in filepaths: + identifier = filepath.with_suffix("").stem + try: + with open(filepath, "rb") as f: + configs[identifier] = tomllib.load(f) + logger.info(f"loader: {identifier} loaded into memory") + except tomllib.TOMLDecodeError: + logger.error(f"Invalid TOML config: configs/{filename.stem}") + return configs diff --git a/vmcompact/menu.py b/vmcompact/menu.py index 819dc02..1524f64 100644 --- a/vmcompact/menu.py +++ b/vmcompact/menu.py @@ -93,6 +93,14 @@ class Menus(tk.Menu): for profile in self.target.configs.keys() if profile not in self.config_defaults ] + elif self.parent.userconfigs: + [ + self.menu_configs_load.add_command( + label=name, command=partial(self.load_custom_profile, data) + ) + for name, data in self.parent.userconfigs.items() + if name not in self.config_defaults + ] else: self.menu_configs.entryconfig(0, state="disabled") self.menu_configs.add_command( @@ -213,6 +221,10 @@ class Menus(tk.Menu): self._unlock.set(not self._lock.get()) setattr(self.target.command, cmd, val) + def load_custom_profile(self, profile): + self.logger.info(f"loading user profile {profile}") + self.target.apply(profile) + def load_profile(self, profile): self.logger.info(f"loading user profile {profile}") self.target.apply_config(profile) @@ -289,6 +301,11 @@ class Menus(tk.Menu): for key in self.target.configs.keys() if key not in self.config_defaults ] + [ + self.menu_configs_load.delete(key) + for key in self.parent.userconfigs.keys() + if key not in self.config_defaults + ] [ self.menu_vban.entryconfig(j, state="disabled") @@ -307,6 +324,14 @@ class Menus(tk.Menu): for profile in self.target.configs.keys() if profile not in self.config_defaults ] + elif self.parent.userconfigs: + [ + self.menu_configs_load.add_command( + label=name, command=partial(self.load_custom_profile, data) + ) + for name, data in self.parent.userconfigs.items() + if name not in self.config_defaults + ] else: self.menu_configs.entryconfig(0, state="disabled") @@ -346,6 +371,11 @@ class Menus(tk.Menu): self.menu_layout.entryconfig( 0, state=f"{'normal' if kind.name == 'potato' else 'disabled'}" ) + # ensure the configs are reloaded into memory + if "config" in self.parent.target.__dict__: + del self.parent.target.__dict__["config"] + if "userconfigs" in self.parent.__dict__: + del self.parent.__dict__["userconfigs"] self.menu_setup() def vban_disconnect(self, i): @@ -366,6 +396,11 @@ class Menus(tk.Menu): self.menu_layout.entryconfig( 0, state=f"{'normal' if kind.name == 'potato' else 'disabled'}" ) + # ensure the configs are reloaded into memory + if "config" in self.parent.target.__dict__: + del self.parent.target.__dict__["config"] + if "userconfigs" in self.parent.__dict__: + del self.parent.__dict__["userconfigs"] self.menu_setup() self.after(15000, self.enable_vban_menus)