diff --git a/pyproject.toml b/pyproject.toml index 0d27851..5ade5be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "voicemeeter-compact" -version = "1.0.4" +version = "1.0.5" description = "A Compact Voicemeeter Remote App" authors = ["onyx-and-iris "] license = "MIT" diff --git a/vmcompact/app.py b/vmcompact/app.py index b7072fd..b939793 100644 --- a/vmcompact/app.py +++ b/vmcompact/app.py @@ -22,7 +22,7 @@ class App(tk.Tk): """ APP_cls = type( - f"Voicemeeter{kind.name}.Compact", + f"Voicemeeter{kind}.Compact", (cls,), { "kind": kind, @@ -38,8 +38,7 @@ class App(tk.Tk): if icon_path.is_file(): self.iconbitmap(str(icon_path)) self.minsize(275, False) - self.subject_pdirty = Subject() - self.subject_ldirty = Subject() + self.subject = Subject() self.strip_levels = None self.bus_levels = None self["menu"] = Menus(self, vmr) @@ -92,26 +91,14 @@ class App(tk.Tk): if self.kind.name == "potato": self.builder.create_banner() - def on_update(self, subject, data): + def on_update(self, subject): """called whenever notified of update""" if not _base_values.in_scale_button_1: if subject == "pdirty": - self.after(1, self.notify_pdirty) + self.subject.notify("pdirty") elif subject == "ldirty" and not _base_values.dragging: - ( - self.strip_levels, - self.strip_comp, - self.bus_levels, - self.bus_comp, - ) = data - self.after(1, self.notify_ldirty) - - def notify_pdirty(self): - self.subject_pdirty.notify() - - def notify_ldirty(self): - self.subject_ldirty.notify() + self.subject.notify("ldirty") def _destroy_top_level_frames(self): """ @@ -122,8 +109,7 @@ class App(tk.Tk): Destroy all top level frames. """ self.target.subject.remove(self) - self.subject_pdirty.clear() - self.subject_ldirty.clear() + self.subject.clear() [ frame.destroy() for frame in self.winfo_children() diff --git a/vmcompact/builders.py b/vmcompact/builders.py index ad32952..0738cdb 100644 --- a/vmcompact/builders.py +++ b/vmcompact/builders.py @@ -37,8 +37,9 @@ class MainFrameBuilder(AbstractBuilder): ) self.app.resizable(False, False) if _configuration.themes_enabled: - print("Applying Sunvalley Theme") - sv_ttk.set_theme(_configuration.theme_mode) + if sv_ttk.get_theme() not in ("light", "dark"): + sv_ttk.set_theme(_configuration.theme_mode) + print(f"Sunvalley {sv_ttk.get_theme().capitalize()} Theme applied") def create_channelframe(self, type_): if type_ == "strip": @@ -301,7 +302,7 @@ class ChannelConfigFrameBuilder(AbstractBuilder): def teardown(self): """Deregister as observable, then destroy frame""" - self.configframe.parent.subject_pdirty.remove(self.configframe) + self.configframe.parent.subject.remove(self.configframe) self.configframe.destroy() def grid_configure(self): diff --git a/vmcompact/channels.py b/vmcompact/channels.py index b672575..7e45cc0 100644 --- a/vmcompact/channels.py +++ b/vmcompact/channels.py @@ -118,10 +118,10 @@ class ChannelLabelFrame(ttk.LabelFrame): retval = f"{retval[:8]}.." if not retval: self.parent.columnconfigure(self.index, minsize=0) - self.parent.parent.subject_ldirty.remove(self) + self.parent.parent.subject.remove(self) self.grid_remove() else: - self.parent.parent.subject_ldirty.add(self) + self.parent.parent.subject.add(self) self.grid() self.configure(text=retval) @@ -167,10 +167,10 @@ class Strip(ChannelLabelFrame): Checks offset against expected level array size to avoid a race condition """ - if self.level_offset + 1 < len(self.parent.parent.strip_levels): + if self.level_offset + 1 < len(self.parent.target.strip_levels): if ( any( - self.parent.parent.strip_comp[ + self.parent.target._strip_comp[ self.level_offset : self.level_offset + 1 ] ) @@ -178,7 +178,7 @@ class Strip(ChannelLabelFrame): ): val = self.convert_level( max( - self.parent.parent.strip_levels[ + self.parent.target.strip_levels[ self.level_offset : self.level_offset + 1 ] ) @@ -187,10 +187,10 @@ class Strip(ChannelLabelFrame): (0 if self.mute.get() else 100 + val - 18 + self.gain.get()) ) - def on_update(self): + def on_update(self, subject): """update levels""" - - self.after(_base_values.ldelay, self.upd_levels) + if subject == "ldirty": + self.after(_base_values.ldelay, self.upd_levels) class Bus(ChannelLabelFrame): @@ -208,10 +208,10 @@ class Bus(ChannelLabelFrame): return getattr(_target, self.identifier)[self.index] def upd_levels(self): - if self.level_offset + 1 < len(self.parent.parent.bus_levels): + if self.level_offset + 1 < len(self.parent.target.bus_levels): if ( any( - self.parent.parent.bus_comp[ + self.parent.target._bus_comp[ self.level_offset : self.level_offset + 1 ] ) @@ -219,17 +219,17 @@ class Bus(ChannelLabelFrame): ): val = self.convert_level( max( - self.parent.parent.bus_levels[ + self.parent.target.bus_levels[ self.level_offset : self.level_offset + 1 ] ) ) self.level.set((0 if self.mute.get() else 100 + val - 18)) - def on_update(self): + def on_update(self, subject): """update levels""" - - self.after(_base_values.ldelay, self.upd_levels) + if subject == "ldirty": + self.after(_base_values.ldelay, self.upd_levels) class ChannelFrame(ttk.Frame): @@ -241,7 +241,7 @@ class ChannelFrame(ttk.Frame): self.phys_out, self.virt_out = parent.kind.outs # registers channelframe as pdirty observer - self.parent.subject_pdirty.add(self) + self.parent.subject.add(self) @property def target(self): @@ -273,16 +273,16 @@ class ChannelFrame(ttk.Frame): def upd_labelframe(self, labelframe): labelframe.sync() - def on_update(self): + def on_update(self, subject): """update parameters""" - - for labelframe in self.labelframes: - self.after(1, self.upd_labelframe, labelframe) + if subject == "pdirty": + for labelframe in self.labelframes: + self.after(1, self.upd_labelframe, labelframe) def teardown(self): # deregisters channelframe as pdirty observer - self.parent.subject_pdirty.remove(self) + self.parent.subject.remove(self) self.destroy() setattr(self.parent, f"{self.identifier}_frame", None) diff --git a/vmcompact/config.py b/vmcompact/config.py index 0deec17..9d0d4fd 100644 --- a/vmcompact/config.py +++ b/vmcompact/config.py @@ -16,7 +16,7 @@ class Config(ttk.Frame): self.phys_in, self.virt_in = parent.kind.ins self.phys_out, self.virt_out = parent.kind.outs - self.parent.subject_pdirty.add(self) + self.parent.subject.add(self) @property def identifier(self): @@ -68,10 +68,10 @@ class Config(ttk.Frame): f"{param}.TButton", background=f'{"green" if val else "white"}' ) - def on_update(self): + def on_update(self, subject): """update parameters""" - - self.after(_base_values.pdelay, self.sync) + if subject == "pdirty": + self.after(_base_values.pdelay, self.sync) class StripConfig(Config): diff --git a/vmcompact/gainlayer.py b/vmcompact/gainlayer.py index 6e29e39..cd61797 100644 --- a/vmcompact/gainlayer.py +++ b/vmcompact/gainlayer.py @@ -120,10 +120,10 @@ class GainLayer(ttk.LabelFrame): retval = f"{retval[:8]}.." if not retval: self.parent.columnconfigure(self.index, minsize=0) - self.parent.parent.subject_ldirty.remove(self) + self.parent.parent.subject.remove(self) self.grid_remove() else: - self.parent.parent.subject_ldirty.add(self) + self.parent.parent.subject.add(self) self.grid() self.configure(text=retval) @@ -138,10 +138,10 @@ class GainLayer(ttk.LabelFrame): Checks offset against expected level array size to avoid a race condition """ - if self.level_offset + 1 < len(self.parent.parent.strip_levels): + if self.level_offset + 1 < len(self.parent.target.strip_levels): if ( any( - self.parent.parent.strip_comp[ + self.parent.target._strip_comp[ self.level_offset : self.level_offset + 1 ] ) @@ -149,7 +149,7 @@ class GainLayer(ttk.LabelFrame): ): val = self.convert_level( max( - self.parent.parent.strip_levels[ + self.parent.target.strip_levels[ self.level_offset : self.level_offset + 1 ] ) @@ -163,10 +163,10 @@ class GainLayer(ttk.LabelFrame): ) ) - def on_update(self): + def on_update(self, subject): """update levels""" - - self.after(_base_values.ldelay, self.upd_levels) + if subject == "ldirty": + self.after(_base_values.ldelay, self.upd_levels) def grid_configure(self): [ @@ -222,7 +222,7 @@ class SubMixFrame(ttk.Frame): self.grid(row=2, column=0, sticky=(tk.W)) # registers submixframe as pdirty observer - self.parent.subject_pdirty.add(self) + self.parent.subject.add(self) self.grid_configure() """ @@ -263,11 +263,12 @@ class SubMixFrame(ttk.Frame): def upd_labelframe(self, labelframe): labelframe.sync() - def on_update(self): - for labelframe in self.labelframes: - self.after(1, self.upd_labelframe, labelframe) + def on_update(self, subject): + if subject == "pdirty": + for labelframe in self.labelframes: + self.after(1, self.upd_labelframe, labelframe) def teardown(self): # deregisters submixframe as pdirty observer - self.parent.subject_pdirty.remove(self) + self.parent.subject.remove(self) self.destroy() diff --git a/vmcompact/navigation.py b/vmcompact/navigation.py index e3a655a..55bbc59 100644 --- a/vmcompact/navigation.py +++ b/vmcompact/navigation.py @@ -10,7 +10,7 @@ class Navigation(ttk.Frame): def __init__(self, parent): super().__init__(parent) self.parent = parent - self.grid(row=0, column=3, padx=(0, 5), pady=(5, 5), sticky=(tk.W, tk.E)) + self.grid(row=0, column=3, padx=(0, 2), pady=(5, 5), sticky=(tk.W, tk.E)) self.styletable = self.parent.styletable self.builder = builders.NavigationFrameBuilder(self) diff --git a/vmcompact/subject.py b/vmcompact/subject.py index 8183f53..2aadf6f 100644 --- a/vmcompact/subject.py +++ b/vmcompact/subject.py @@ -1,35 +1,36 @@ class Subject: + """Adds support for observers""" + def __init__(self): """list of current observers""" - self._observables = [] + self._observers = list() def notify(self, modifier=None): """run callbacks on update""" - for observer in self._observables: - observer.on_update() + [o.on_update(modifier) for o in self._observers] def add(self, observer): """adds an observer to observables""" - if observer not in self._observables: - self._observables.append(observer) + if observer not in self._observers: + self._observers.append(observer) def remove(self, observer): """removes an observer from observables""" try: - self._observables.remove(observer) + self._observers.remove(observer) except ValueError: pass def get(self) -> list: """returns the current observables""" - return self._observables + return self._observers def clear(self): """clears the observables list""" - self._observables.clear() + self._observers.clear()