mirror of
https://github.com/onyx-and-iris/voicemeeter-compact.git
synced 2024-11-24 22:00:53 +00:00
fix app title.
merge subject classes. modify obsevers callback ensure sunvalley theme loaded only once. minor version bump
This commit is contained in:
parent
60e55fd7f9
commit
fd30a5ef0d
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "voicemeeter-compact"
|
name = "voicemeeter-compact"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
description = "A Compact Voicemeeter Remote App"
|
description = "A Compact Voicemeeter Remote App"
|
||||||
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
@ -22,7 +22,7 @@ class App(tk.Tk):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
APP_cls = type(
|
APP_cls = type(
|
||||||
f"Voicemeeter{kind.name}.Compact",
|
f"Voicemeeter{kind}.Compact",
|
||||||
(cls,),
|
(cls,),
|
||||||
{
|
{
|
||||||
"kind": kind,
|
"kind": kind,
|
||||||
@ -38,8 +38,7 @@ class App(tk.Tk):
|
|||||||
if icon_path.is_file():
|
if icon_path.is_file():
|
||||||
self.iconbitmap(str(icon_path))
|
self.iconbitmap(str(icon_path))
|
||||||
self.minsize(275, False)
|
self.minsize(275, False)
|
||||||
self.subject_pdirty = Subject()
|
self.subject = Subject()
|
||||||
self.subject_ldirty = Subject()
|
|
||||||
self.strip_levels = None
|
self.strip_levels = None
|
||||||
self.bus_levels = None
|
self.bus_levels = None
|
||||||
self["menu"] = Menus(self, vmr)
|
self["menu"] = Menus(self, vmr)
|
||||||
@ -92,26 +91,14 @@ class App(tk.Tk):
|
|||||||
if self.kind.name == "potato":
|
if self.kind.name == "potato":
|
||||||
self.builder.create_banner()
|
self.builder.create_banner()
|
||||||
|
|
||||||
def on_update(self, subject, data):
|
def on_update(self, subject):
|
||||||
"""called whenever notified of update"""
|
"""called whenever notified of update"""
|
||||||
|
|
||||||
if not _base_values.in_scale_button_1:
|
if not _base_values.in_scale_button_1:
|
||||||
if subject == "pdirty":
|
if subject == "pdirty":
|
||||||
self.after(1, self.notify_pdirty)
|
self.subject.notify("pdirty")
|
||||||
elif subject == "ldirty" and not _base_values.dragging:
|
elif subject == "ldirty" and not _base_values.dragging:
|
||||||
(
|
self.subject.notify("ldirty")
|
||||||
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()
|
|
||||||
|
|
||||||
def _destroy_top_level_frames(self):
|
def _destroy_top_level_frames(self):
|
||||||
"""
|
"""
|
||||||
@ -122,8 +109,7 @@ class App(tk.Tk):
|
|||||||
Destroy all top level frames.
|
Destroy all top level frames.
|
||||||
"""
|
"""
|
||||||
self.target.subject.remove(self)
|
self.target.subject.remove(self)
|
||||||
self.subject_pdirty.clear()
|
self.subject.clear()
|
||||||
self.subject_ldirty.clear()
|
|
||||||
[
|
[
|
||||||
frame.destroy()
|
frame.destroy()
|
||||||
for frame in self.winfo_children()
|
for frame in self.winfo_children()
|
||||||
|
@ -37,8 +37,9 @@ class MainFrameBuilder(AbstractBuilder):
|
|||||||
)
|
)
|
||||||
self.app.resizable(False, False)
|
self.app.resizable(False, False)
|
||||||
if _configuration.themes_enabled:
|
if _configuration.themes_enabled:
|
||||||
print("Applying Sunvalley Theme")
|
if sv_ttk.get_theme() not in ("light", "dark"):
|
||||||
sv_ttk.set_theme(_configuration.theme_mode)
|
sv_ttk.set_theme(_configuration.theme_mode)
|
||||||
|
print(f"Sunvalley {sv_ttk.get_theme().capitalize()} Theme applied")
|
||||||
|
|
||||||
def create_channelframe(self, type_):
|
def create_channelframe(self, type_):
|
||||||
if type_ == "strip":
|
if type_ == "strip":
|
||||||
@ -301,7 +302,7 @@ class ChannelConfigFrameBuilder(AbstractBuilder):
|
|||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
"""Deregister as observable, then destroy frame"""
|
"""Deregister as observable, then destroy frame"""
|
||||||
self.configframe.parent.subject_pdirty.remove(self.configframe)
|
self.configframe.parent.subject.remove(self.configframe)
|
||||||
self.configframe.destroy()
|
self.configframe.destroy()
|
||||||
|
|
||||||
def grid_configure(self):
|
def grid_configure(self):
|
||||||
|
@ -118,10 +118,10 @@ class ChannelLabelFrame(ttk.LabelFrame):
|
|||||||
retval = f"{retval[:8]}.."
|
retval = f"{retval[:8]}.."
|
||||||
if not retval:
|
if not retval:
|
||||||
self.parent.columnconfigure(self.index, minsize=0)
|
self.parent.columnconfigure(self.index, minsize=0)
|
||||||
self.parent.parent.subject_ldirty.remove(self)
|
self.parent.parent.subject.remove(self)
|
||||||
self.grid_remove()
|
self.grid_remove()
|
||||||
else:
|
else:
|
||||||
self.parent.parent.subject_ldirty.add(self)
|
self.parent.parent.subject.add(self)
|
||||||
self.grid()
|
self.grid()
|
||||||
self.configure(text=retval)
|
self.configure(text=retval)
|
||||||
|
|
||||||
@ -167,10 +167,10 @@ class Strip(ChannelLabelFrame):
|
|||||||
|
|
||||||
Checks offset against expected level array size to avoid a race condition
|
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 (
|
if (
|
||||||
any(
|
any(
|
||||||
self.parent.parent.strip_comp[
|
self.parent.target._strip_comp[
|
||||||
self.level_offset : self.level_offset + 1
|
self.level_offset : self.level_offset + 1
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -178,7 +178,7 @@ class Strip(ChannelLabelFrame):
|
|||||||
):
|
):
|
||||||
val = self.convert_level(
|
val = self.convert_level(
|
||||||
max(
|
max(
|
||||||
self.parent.parent.strip_levels[
|
self.parent.target.strip_levels[
|
||||||
self.level_offset : self.level_offset + 1
|
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())
|
(0 if self.mute.get() else 100 + val - 18 + self.gain.get())
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self, subject):
|
||||||
"""update levels"""
|
"""update levels"""
|
||||||
|
if subject == "ldirty":
|
||||||
self.after(_base_values.ldelay, self.upd_levels)
|
self.after(_base_values.ldelay, self.upd_levels)
|
||||||
|
|
||||||
|
|
||||||
class Bus(ChannelLabelFrame):
|
class Bus(ChannelLabelFrame):
|
||||||
@ -208,10 +208,10 @@ class Bus(ChannelLabelFrame):
|
|||||||
return getattr(_target, self.identifier)[self.index]
|
return getattr(_target, self.identifier)[self.index]
|
||||||
|
|
||||||
def upd_levels(self):
|
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 (
|
if (
|
||||||
any(
|
any(
|
||||||
self.parent.parent.bus_comp[
|
self.parent.target._bus_comp[
|
||||||
self.level_offset : self.level_offset + 1
|
self.level_offset : self.level_offset + 1
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -219,17 +219,17 @@ class Bus(ChannelLabelFrame):
|
|||||||
):
|
):
|
||||||
val = self.convert_level(
|
val = self.convert_level(
|
||||||
max(
|
max(
|
||||||
self.parent.parent.bus_levels[
|
self.parent.target.bus_levels[
|
||||||
self.level_offset : self.level_offset + 1
|
self.level_offset : self.level_offset + 1
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.level.set((0 if self.mute.get() else 100 + val - 18))
|
self.level.set((0 if self.mute.get() else 100 + val - 18))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self, subject):
|
||||||
"""update levels"""
|
"""update levels"""
|
||||||
|
if subject == "ldirty":
|
||||||
self.after(_base_values.ldelay, self.upd_levels)
|
self.after(_base_values.ldelay, self.upd_levels)
|
||||||
|
|
||||||
|
|
||||||
class ChannelFrame(ttk.Frame):
|
class ChannelFrame(ttk.Frame):
|
||||||
@ -241,7 +241,7 @@ class ChannelFrame(ttk.Frame):
|
|||||||
self.phys_out, self.virt_out = parent.kind.outs
|
self.phys_out, self.virt_out = parent.kind.outs
|
||||||
|
|
||||||
# registers channelframe as pdirty observer
|
# registers channelframe as pdirty observer
|
||||||
self.parent.subject_pdirty.add(self)
|
self.parent.subject.add(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target(self):
|
def target(self):
|
||||||
@ -273,16 +273,16 @@ class ChannelFrame(ttk.Frame):
|
|||||||
def upd_labelframe(self, labelframe):
|
def upd_labelframe(self, labelframe):
|
||||||
labelframe.sync()
|
labelframe.sync()
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self, subject):
|
||||||
"""update parameters"""
|
"""update parameters"""
|
||||||
|
if subject == "pdirty":
|
||||||
for labelframe in self.labelframes:
|
for labelframe in self.labelframes:
|
||||||
self.after(1, self.upd_labelframe, labelframe)
|
self.after(1, self.upd_labelframe, labelframe)
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
# deregisters channelframe as pdirty observer
|
# deregisters channelframe as pdirty observer
|
||||||
|
|
||||||
self.parent.subject_pdirty.remove(self)
|
self.parent.subject.remove(self)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
setattr(self.parent, f"{self.identifier}_frame", None)
|
setattr(self.parent, f"{self.identifier}_frame", None)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class Config(ttk.Frame):
|
|||||||
self.phys_in, self.virt_in = parent.kind.ins
|
self.phys_in, self.virt_in = parent.kind.ins
|
||||||
self.phys_out, self.virt_out = parent.kind.outs
|
self.phys_out, self.virt_out = parent.kind.outs
|
||||||
|
|
||||||
self.parent.subject_pdirty.add(self)
|
self.parent.subject.add(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def identifier(self):
|
def identifier(self):
|
||||||
@ -68,10 +68,10 @@ class Config(ttk.Frame):
|
|||||||
f"{param}.TButton", background=f'{"green" if val else "white"}'
|
f"{param}.TButton", background=f'{"green" if val else "white"}'
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self, subject):
|
||||||
"""update parameters"""
|
"""update parameters"""
|
||||||
|
if subject == "pdirty":
|
||||||
self.after(_base_values.pdelay, self.sync)
|
self.after(_base_values.pdelay, self.sync)
|
||||||
|
|
||||||
|
|
||||||
class StripConfig(Config):
|
class StripConfig(Config):
|
||||||
|
@ -120,10 +120,10 @@ class GainLayer(ttk.LabelFrame):
|
|||||||
retval = f"{retval[:8]}.."
|
retval = f"{retval[:8]}.."
|
||||||
if not retval:
|
if not retval:
|
||||||
self.parent.columnconfigure(self.index, minsize=0)
|
self.parent.columnconfigure(self.index, minsize=0)
|
||||||
self.parent.parent.subject_ldirty.remove(self)
|
self.parent.parent.subject.remove(self)
|
||||||
self.grid_remove()
|
self.grid_remove()
|
||||||
else:
|
else:
|
||||||
self.parent.parent.subject_ldirty.add(self)
|
self.parent.parent.subject.add(self)
|
||||||
self.grid()
|
self.grid()
|
||||||
self.configure(text=retval)
|
self.configure(text=retval)
|
||||||
|
|
||||||
@ -138,10 +138,10 @@ class GainLayer(ttk.LabelFrame):
|
|||||||
|
|
||||||
Checks offset against expected level array size to avoid a race condition
|
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 (
|
if (
|
||||||
any(
|
any(
|
||||||
self.parent.parent.strip_comp[
|
self.parent.target._strip_comp[
|
||||||
self.level_offset : self.level_offset + 1
|
self.level_offset : self.level_offset + 1
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -149,7 +149,7 @@ class GainLayer(ttk.LabelFrame):
|
|||||||
):
|
):
|
||||||
val = self.convert_level(
|
val = self.convert_level(
|
||||||
max(
|
max(
|
||||||
self.parent.parent.strip_levels[
|
self.parent.target.strip_levels[
|
||||||
self.level_offset : self.level_offset + 1
|
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"""
|
"""update levels"""
|
||||||
|
if subject == "ldirty":
|
||||||
self.after(_base_values.ldelay, self.upd_levels)
|
self.after(_base_values.ldelay, self.upd_levels)
|
||||||
|
|
||||||
def grid_configure(self):
|
def grid_configure(self):
|
||||||
[
|
[
|
||||||
@ -222,7 +222,7 @@ class SubMixFrame(ttk.Frame):
|
|||||||
self.grid(row=2, column=0, sticky=(tk.W))
|
self.grid(row=2, column=0, sticky=(tk.W))
|
||||||
|
|
||||||
# registers submixframe as pdirty observer
|
# registers submixframe as pdirty observer
|
||||||
self.parent.subject_pdirty.add(self)
|
self.parent.subject.add(self)
|
||||||
|
|
||||||
self.grid_configure()
|
self.grid_configure()
|
||||||
"""
|
"""
|
||||||
@ -263,11 +263,12 @@ class SubMixFrame(ttk.Frame):
|
|||||||
def upd_labelframe(self, labelframe):
|
def upd_labelframe(self, labelframe):
|
||||||
labelframe.sync()
|
labelframe.sync()
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self, subject):
|
||||||
for labelframe in self.labelframes:
|
if subject == "pdirty":
|
||||||
self.after(1, self.upd_labelframe, labelframe)
|
for labelframe in self.labelframes:
|
||||||
|
self.after(1, self.upd_labelframe, labelframe)
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
# deregisters submixframe as pdirty observer
|
# deregisters submixframe as pdirty observer
|
||||||
self.parent.subject_pdirty.remove(self)
|
self.parent.subject.remove(self)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
@ -10,7 +10,7 @@ class Navigation(ttk.Frame):
|
|||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.parent = 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.styletable = self.parent.styletable
|
||||||
|
|
||||||
self.builder = builders.NavigationFrameBuilder(self)
|
self.builder = builders.NavigationFrameBuilder(self)
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
class Subject:
|
class Subject:
|
||||||
|
"""Adds support for observers"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""list of current observers"""
|
"""list of current observers"""
|
||||||
|
|
||||||
self._observables = []
|
self._observers = list()
|
||||||
|
|
||||||
def notify(self, modifier=None):
|
def notify(self, modifier=None):
|
||||||
"""run callbacks on update"""
|
"""run callbacks on update"""
|
||||||
|
|
||||||
for observer in self._observables:
|
[o.on_update(modifier) for o in self._observers]
|
||||||
observer.on_update()
|
|
||||||
|
|
||||||
def add(self, observer):
|
def add(self, observer):
|
||||||
"""adds an observer to observables"""
|
"""adds an observer to observables"""
|
||||||
|
|
||||||
if observer not in self._observables:
|
if observer not in self._observers:
|
||||||
self._observables.append(observer)
|
self._observers.append(observer)
|
||||||
|
|
||||||
def remove(self, observer):
|
def remove(self, observer):
|
||||||
"""removes an observer from observables"""
|
"""removes an observer from observables"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._observables.remove(observer)
|
self._observers.remove(observer)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get(self) -> list:
|
def get(self) -> list:
|
||||||
"""returns the current observables"""
|
"""returns the current observables"""
|
||||||
|
|
||||||
return self._observables
|
return self._observers
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""clears the observables list"""
|
"""clears the observables list"""
|
||||||
|
|
||||||
self._observables.clear()
|
self._observers.clear()
|
||||||
|
Loading…
Reference in New Issue
Block a user