re-run through ruff formatter

This commit is contained in:
Onyx and Iris 2025-01-15 20:56:37 +00:00
parent 752d1d7dd9
commit e4fc68c1ad
12 changed files with 387 additions and 382 deletions

View File

@ -4,12 +4,12 @@ import vmcompact
def main(): def main():
KIND_ID = "banana" KIND_ID = 'banana'
with voicemeeterlib.api(KIND_ID) as vmr: with voicemeeterlib.api(KIND_ID) as vmr:
app = vmcompact.connect(KIND_ID, vmr) app = vmcompact.connect(KIND_ID, vmr)
app.mainloop() app.mainloop()
if __name__ == "__main__": if __name__ == '__main__':
main() main()

View File

@ -1,3 +1,3 @@
from .app import connect from .app import connect
__ALL__ = ["connect"] __ALL__ = ['connect']

View File

@ -29,10 +29,10 @@ class App(tk.Tk):
""" """
APP_cls = type( APP_cls = type(
f"Voicemeeter{kind}.Compact", f'Voicemeeter{kind}.Compact',
(cls,), (cls,),
{ {
"kind": kind, 'kind': kind,
}, },
) )
return APP_cls return APP_cls
@ -41,30 +41,34 @@ class App(tk.Tk):
super().__init__() super().__init__()
self.logger = logger.getChild(self.__class__.__name__) self.logger = logger.getChild(self.__class__.__name__)
self._vmr = vmr self._vmr = vmr
self._vmr.event.add(["pdirty", "ldirty"]) self._vmr.event.add(['pdirty', 'ldirty'])
self.subject = Subject() self.subject = Subject()
self.start_updates() self.start_updates()
self._vmr.init_thread() self._vmr.init_thread()
icon_path = Path(__file__).parent.resolve() / "img" / "cat.ico" for pn in (
if icon_path.is_file(): Path(__file__).parent.resolve() / 'img' / 'cat.ico',
self.iconbitmap(str(icon_path)) Path.cwd() / '_internal' / 'img' / 'cat.ico',
):
if pn.is_file():
self.iconbitmap(str(pn))
break
self.minsize(275, False) self.minsize(275, False)
self._configs = None self._configs = None
self.protocol("WM_DELETE_WINDOW", self.on_close_window) self.protocol('WM_DELETE_WINDOW', self.on_close_window)
self.menu = self["menu"] = Menus(self, vmr) self.menu = self['menu'] = Menus(self, vmr)
self.styletable = ttk.Style() self.styletable = ttk.Style()
if _configuration.config: if _configuration.config:
vmr.apply_config(_configuration.config) vmr.apply_config(_configuration.config)
self.build_app() self.build_app()
self.drag_id = "" self.drag_id = ''
self.bind("<Configure>", self.dragging) self.bind('<Configure>', self.dragging)
self.after(1, self.healthcheck_step) self.after(1, self.healthcheck_step)
def __str__(self): def __str__(self):
return f"{type(self).__name__}App" return f'{type(self).__name__}App'
@property @property
def target(self): def target(self):
@ -80,8 +84,8 @@ class App(tk.Tk):
frame frame
for frame in self.winfo_children() for frame in self.winfo_children()
if isinstance(frame, ttk.Frame) if isinstance(frame, ttk.Frame)
and "!stripconfig" in str(frame) and '!stripconfig' in str(frame)
or "!busconfig" in str(frame) or '!busconfig' in str(frame)
) )
def build_app(self, kind=None, vban=None): def build_app(self, kind=None, vban=None):
@ -97,22 +101,22 @@ class App(tk.Tk):
self.submix_frame = None self.submix_frame = None
self.builder = MainFrameBuilder(self) self.builder = MainFrameBuilder(self)
self.builder.setup() self.builder.setup()
self.builder.create_channelframe("strip") self.builder.create_channelframe('strip')
self.builder.create_separator() self.builder.create_separator()
self.builder.create_navframe() self.builder.create_navframe()
if _configuration.extended: if _configuration.extended:
self.nav_frame.extend.set(True) self.nav_frame.extend.set(True)
self.nav_frame.extend_frame() self.nav_frame.extend_frame()
if self.kind.name == "potato": if self.kind.name == 'potato':
self.builder.create_banner() self.builder.create_banner()
def on_pdirty(self): def on_pdirty(self):
if _base_values.run_update: if _base_values.run_update:
self.after(1, self.subject.notify, "pdirty") self.after(1, self.subject.notify, 'pdirty')
def on_ldirty(self): def on_ldirty(self):
if not _base_values.dragging: if not _base_values.dragging:
self.after(1, self.subject.notify, "ldirty") self.after(1, self.subject.notify, 'ldirty')
def _destroy_top_level_frames(self): def _destroy_top_level_frames(self):
""" """
@ -132,14 +136,14 @@ class App(tk.Tk):
def dragging(self, event, *args): def dragging(self, event, *args):
if event.widget is self: if event.widget is self:
if self.drag_id == "": if self.drag_id == '':
_base_values.dragging = True _base_values.dragging = True
else: else:
self.after_cancel(self.drag_id) self.after_cancel(self.drag_id)
self.drag_id = self.after(100, self.stop_drag) self.drag_id = self.after(100, self.stop_drag)
def stop_drag(self): def stop_drag(self):
self.drag_id = "" self.drag_id = ''
_base_values.dragging = False _base_values.dragging = False
@cached_property @cached_property
@ -149,11 +153,11 @@ class App(tk.Tk):
def start_updates(self): def start_updates(self):
def init(): def init():
self.logger.debug("updates started") self.logger.debug('updates started')
_base_values.run_update = True _base_values.run_update = True
if self._vmr.gui.launched_by_api: if self._vmr.gui.launched_by_api:
self.subject.notify("pdirty") self.subject.notify('pdirty')
self.after(12000, init) self.after(12000, init)
else: else:
init() init()
@ -163,10 +167,10 @@ class App(tk.Tk):
try: try:
self._vmr.version self._vmr.version
except voicemeeterlib.error.CAPIError: except voicemeeterlib.error.CAPIError:
resp = messagebox.askyesno(message="Restart Voicemeeter GUI?") resp = messagebox.askyesno(message='Restart Voicemeeter GUI?')
if resp: if resp:
self.logger.debug( self.logger.debug(
"healthcheck failed, rebuilding the app after GUI restart." 'healthcheck failed, rebuilding the app after GUI restart.'
) )
self._vmr.end_thread() self._vmr.end_thread()
self._vmr.run_voicemeeter(self._vmr.kind.name) self._vmr.run_voicemeeter(self._vmr.kind.name)
@ -175,13 +179,13 @@ class App(tk.Tk):
self.after(8000, self.start_updates) self.after(8000, self.start_updates)
self._destroy_top_level_frames() self._destroy_top_level_frames()
self.build_app(self._vmr.kind) self.build_app(self._vmr.kind)
vban_config = get_configuration("vban") vban_config = get_configuration('vban')
for i, _ in enumerate(vban_config): for i, _ in enumerate(vban_config):
target = getattr(self.menu, f"menu_vban_{i+1}") target = getattr(self.menu, f'menu_vban_{i + 1}')
target.entryconfig(0, state="normal") target.entryconfig(0, state='normal')
target.entryconfig(1, state="disabled") target.entryconfig(1, state='disabled')
[ [
self.menu.menu_vban.entryconfig(j, state="normal") self.menu.menu_vban.entryconfig(j, state='normal')
for j, _ in enumerate(self.menu.menu_vban.winfo_children()) for j, _ in enumerate(self.menu.menu_vban.winfo_children())
] ]
else: else:
@ -203,5 +207,5 @@ def connect(kind_id: str, vmr) -> App:
try: try:
VMMIN_cls = _apps[kind_id] VMMIN_cls = _apps[kind_id]
except KeyError: except KeyError:
raise VMCompactError(f"Invalid kind: {kind_id}") raise VMCompactError(f'Invalid kind: {kind_id}')
return VMMIN_cls(vmr) return VMMIN_cls(vmr)

View File

@ -17,7 +17,7 @@ class Banner(ttk.Frame):
self.label = ttk.Label( self.label = ttk.Label(
self, self,
text=f"SUBMIX: {self.submix.get().upper()}", text=f'SUBMIX: {self.submix.get().upper()}',
) )
self.label.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E)) self.label.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E))
@ -28,8 +28,8 @@ class Banner(ttk.Frame):
return self.parent.target return self.parent.target
def on_update(self, subject): def on_update(self, subject):
if subject == "submix": if subject == 'submix':
if not _base_values.dragging: if not _base_values.dragging:
self.logger.debug("checking submix for banner") self.logger.debug('checking submix for banner')
self.submix.set(self.target.bus[_configuration.submixes].label) self.submix.set(self.target.bus[_configuration.submixes].label)
self.label["text"] = f"SUBMIX: {self.submix.get().upper()}" self.label['text'] = f'SUBMIX: {self.submix.get().upper()}'

View File

@ -41,31 +41,31 @@ class MainFrameBuilder(AbstractBuilder):
) )
self.app.resizable(False, False) self.app.resizable(False, False)
if _configuration.themes_enabled: if _configuration.themes_enabled:
if sv_ttk.get_theme() not in ("light", "dark"): if sv_ttk.get_theme() not in ('light', 'dark'):
sv_ttk.set_theme(_configuration.theme_mode) sv_ttk.set_theme(_configuration.theme_mode)
self.logger.info( self.logger.info(
f"Sunvalley {sv_ttk.get_theme().capitalize()} Theme applied" 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':
self.app.strip_frame = _make_channelframe(self.app, type_) self.app.strip_frame = _make_channelframe(self.app, type_)
else: else:
self.app.bus_frame = _make_channelframe(self.app, type_) self.app.bus_frame = _make_channelframe(self.app, type_)
self.logger.info(f"Finished building channelframe type {type_}") self.logger.info(f'Finished building channelframe type {type_}')
def create_separator(self): def create_separator(self):
self.app.sep = ttk.Separator(self.app, orient="vertical") self.app.sep = ttk.Separator(self.app, orient='vertical')
self.app.sep.grid(row=0, column=1, sticky=(tk.N, tk.S)) self.app.sep.grid(row=0, column=1, sticky=(tk.N, tk.S))
self.app.columnconfigure(1, minsize=15) self.app.columnconfigure(1, minsize=15)
self.logger.info(f"Finished building separator") self.logger.info('Finished building separator')
def create_navframe(self): def create_navframe(self):
self.app.nav_frame = Navigation(self.app) self.app.nav_frame = Navigation(self.app)
self.logger.info(f"Finished building navframe") self.logger.info('Finished building navframe')
def create_configframe(self, type_, index, id): def create_configframe(self, type_, index, id):
if type_ == "strip": if type_ == 'strip':
self.app.config_frame = StripConfig(self.app, index, id) self.app.config_frame = StripConfig(self.app, index, id)
if self.app.strip_frame: if self.app.strip_frame:
[ [
@ -95,20 +95,20 @@ class MainFrameBuilder(AbstractBuilder):
if self.app.strip_frame: if self.app.strip_frame:
[ [
frame.styletable.configure( frame.styletable.configure(
f"{frame.identifier}Conf{frame.index}.TButton", f'{frame.identifier}Conf{frame.index}.TButton',
background=f"{'white' if not frame.conf.get() else 'yellow'}", background=f'{"white" if not frame.conf.get() else "yellow"}',
) )
for _, frame in enumerate(self.app.strip_frame.labelframes) for _, frame in enumerate(self.app.strip_frame.labelframes)
] ]
if self.app.bus_frame: if self.app.bus_frame:
[ [
frame.styletable.configure( frame.styletable.configure(
f"{frame.identifier}Conf{frame.index}.TButton", f'{frame.identifier}Conf{frame.index}.TButton',
background=f"{'white' if not frame.conf.get() else 'yellow'}", background=f'{"white" if not frame.conf.get() else "yellow"}',
) )
for _, frame in enumerate(self.app.bus_frame.labelframes) for _, frame in enumerate(self.app.bus_frame.labelframes)
] ]
self.logger.info(f"Finished building configframe for {type_}[{index}]") self.logger.info(f'Finished building configframe for {type_}[{index}]')
self.app.after(5, self.reset_config_frames) self.app.after(5, self.reset_config_frames)
def reset_config_frames(self): def reset_config_frames(self):
@ -121,7 +121,7 @@ class MainFrameBuilder(AbstractBuilder):
def create_banner(self): def create_banner(self):
self.app.banner = Banner(self.app) self.app.banner = Banner(self.app)
self.app.banner.grid(row=4, column=0, columnspan=3) self.app.banner.grid(row=4, column=0, columnspan=3)
self.logger.info(f"Finished building banner") self.logger.info('Finished building banner')
def teardown(self): def teardown(self):
pass pass
@ -140,31 +140,31 @@ class NavigationFrameBuilder(AbstractBuilder):
self.navframe.info = tk.BooleanVar() self.navframe.info = tk.BooleanVar()
self.navframe.channel_text = tk.StringVar( self.navframe.channel_text = tk.StringVar(
value=f"{self.navframe.parent.strip_frame.identifier.upper()}" value=f'{self.navframe.parent.strip_frame.identifier.upper()}'
) )
self.navframe.extend_text = tk.StringVar( self.navframe.extend_text = tk.StringVar(
value=f"{'REDUCE' if self.navframe.extend.get() else 'EXTEND'}" value=f'{"REDUCE" if self.navframe.extend.get() else "EXTEND"}'
) )
self.navframe.info_text = tk.StringVar() self.navframe.info_text = tk.StringVar()
def create_submix_button(self): def create_submix_button(self):
self.navframe.submix_button = ttk.Checkbutton( self.navframe.submix_button = ttk.Checkbutton(
self.navframe, self.navframe,
text="SUBMIX", text='SUBMIX',
command=self.navframe.show_submix, command=self.navframe.show_submix,
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'Submix.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Submix.TButton"}',
variable=self.navframe.submix, variable=self.navframe.submix,
) )
self.navframe.submix_button.grid(column=0, row=0) self.navframe.submix_button.grid(column=0, row=0)
if self.navframe.parent.kind.name != "potato": if self.navframe.parent.kind.name != 'potato':
self.navframe.submix_button["state"] = "disabled" self.navframe.submix_button['state'] = 'disabled'
def create_channel_button(self): def create_channel_button(self):
self.navframe.channel_button = ttk.Checkbutton( self.navframe.channel_button = ttk.Checkbutton(
self.navframe, self.navframe,
textvariable=self.navframe.channel_text, textvariable=self.navframe.channel_text,
command=self.navframe.switch_channel, command=self.navframe.switch_channel,
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'Channel.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Channel.TButton"}',
variable=self.navframe.channel, variable=self.navframe.channel,
) )
self.navframe.channel_button.grid(column=0, row=1, rowspan=1) self.navframe.channel_button.grid(column=0, row=1, rowspan=1)
@ -174,7 +174,7 @@ class NavigationFrameBuilder(AbstractBuilder):
self.navframe, self.navframe,
textvariable=self.navframe.extend_text, textvariable=self.navframe.extend_text,
command=self.navframe.extend_frame, command=self.navframe.extend_frame,
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'Extend.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Extend.TButton"}',
variable=self.navframe.extend, variable=self.navframe.extend,
) )
self.navframe.extend_button.grid(column=0, row=2) self.navframe.extend_button.grid(column=0, row=2)
@ -183,7 +183,7 @@ class NavigationFrameBuilder(AbstractBuilder):
self.navframe.info_button = ttk.Checkbutton( self.navframe.info_button = ttk.Checkbutton(
self.navframe, self.navframe,
textvariable=self.navframe.info_text, textvariable=self.navframe.info_text,
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'Rec.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else "Rec.TButton"}',
variable=self.navframe.info, variable=self.navframe.info,
) )
self.navframe.info_button.grid(column=0, row=3) self.navframe.info_button.grid(column=0, row=3)
@ -228,8 +228,8 @@ class ChannelLabelFrameBuilder(AbstractBuilder):
self.labelframe.pb = ttk.Progressbar( self.labelframe.pb = ttk.Progressbar(
self.labelframe, self.labelframe,
maximum=72, maximum=72,
orient="vertical", orient='vertical',
mode="determinate", mode='determinate',
variable=self.labelframe.level, variable=self.labelframe.level,
) )
self.labelframe.pb.grid(column=0, row=0) self.labelframe.pb.grid(column=0, row=0)
@ -240,17 +240,17 @@ class ChannelLabelFrameBuilder(AbstractBuilder):
self.labelframe, self.labelframe,
from_=12.0, from_=12.0,
to=-60.0, to=-60.0,
orient="vertical", orient='vertical',
variable=self.labelframe.gain, variable=self.labelframe.gain,
command=self.labelframe.scale_callback, command=self.labelframe.scale_callback,
length=_configuration.channel_height, length=_configuration.channel_height,
) )
self.scale.grid(column=1, row=0) self.scale.grid(column=1, row=0)
self.scale.bind("<Double-Button-1>", self.labelframe.reset_gain) self.scale.bind('<Double-Button-1>', self.labelframe.reset_gain)
self.scale.bind("<Button-1>", self.labelframe.scale_press) self.scale.bind('<Button-1>', self.labelframe.scale_press)
self.scale.bind("<ButtonRelease-1>", self.labelframe.scale_release) self.scale.bind('<ButtonRelease-1>', self.labelframe.scale_release)
self.scale.bind( self.scale.bind(
"<MouseWheel>", '<MouseWheel>',
partial( partial(
self.labelframe.pause_updates, self.labelframe.pause_updates,
self.labelframe._on_mousewheel, self.labelframe._on_mousewheel,
@ -268,9 +268,9 @@ class ChannelLabelFrameBuilder(AbstractBuilder):
"""Adds a mute button widget to a single label frame""" """Adds a mute button widget to a single label frame"""
self.button_mute = ttk.Checkbutton( self.button_mute = ttk.Checkbutton(
self.labelframe, self.labelframe,
text="MUTE", text='MUTE',
command=partial(self.labelframe.pause_updates, self.labelframe.toggle_mute), command=partial(self.labelframe.pause_updates, self.labelframe.toggle_mute),
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{self.identifier}Mute{self.index}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{self.identifier}Mute{self.index}.TButton"}',
variable=self.labelframe.mute, variable=self.labelframe.mute,
) )
self.button_mute.grid(column=0, row=2, columnspan=2) self.button_mute.grid(column=0, row=2, columnspan=2)
@ -278,9 +278,9 @@ class ChannelLabelFrameBuilder(AbstractBuilder):
def add_conf_button(self): def add_conf_button(self):
self.button_conf = ttk.Checkbutton( self.button_conf = ttk.Checkbutton(
self.labelframe, self.labelframe,
text="CONFIG", text='CONFIG',
command=self.labelframe.open_config, command=self.labelframe.open_config,
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{self.identifier}Conf{self.index}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{self.identifier}Conf{self.index}.TButton"}',
variable=self.labelframe.conf, variable=self.labelframe.conf,
) )
self.button_conf.grid(column=0, row=3, columnspan=2) self.button_conf.grid(column=0, row=3, columnspan=2)
@ -288,9 +288,9 @@ class ChannelLabelFrameBuilder(AbstractBuilder):
def add_on_button(self): def add_on_button(self):
self.button_on = ttk.Checkbutton( self.button_on = ttk.Checkbutton(
self.labelframe, self.labelframe,
text="ON", text='ON',
command=partial(self.labelframe.pause_updates, self.labelframe.set_on), command=partial(self.labelframe.pause_updates, self.labelframe.set_on),
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{self.identifier}On{self.index}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{self.identifier}On{self.index}.TButton"}',
variable=self.labelframe.on, variable=self.labelframe.on,
) )
self.button_on.grid(column=0, row=2, columnspan=2) self.button_on.grid(column=0, row=2, columnspan=2)
@ -339,40 +339,40 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder):
"""Responsible for building channel configframe widgets""" """Responsible for building channel configframe widgets"""
def setup(self): def setup(self):
if self.configframe.parent.kind.name == "basic": if self.configframe.parent.kind.name == 'basic':
self.configframe.slider_params = ("audibility",) self.configframe.slider_params = ('audibility',)
self.configframe.slider_vars = (tk.DoubleVar(),) self.configframe.slider_vars = (tk.DoubleVar(),)
else: else:
self.configframe.slider_params = ("comp.knob", "gate.knob", "limit") self.configframe.slider_params = ('comp.knob', 'gate.knob', 'limit')
self.configframe.slider_vars = [ self.configframe.slider_vars = [
tk.DoubleVar() for _ in self.configframe.slider_params tk.DoubleVar() for _ in self.configframe.slider_params
] ]
self.configframe.phys_out_params = [ self.configframe.phys_out_params = [
f"A{i+1}" for i in range(self.configframe.phys_out) f'A{i + 1}' for i in range(self.configframe.phys_out)
] ]
self.configframe.phys_out_params_vars = [ self.configframe.phys_out_params_vars = [
tk.BooleanVar() for _ in self.configframe.phys_out_params tk.BooleanVar() for _ in self.configframe.phys_out_params
] ]
self.configframe.virt_out_params = [ self.configframe.virt_out_params = [
f"B{i+1}" for i in range(self.configframe.virt_out) f'B{i + 1}' for i in range(self.configframe.virt_out)
] ]
self.configframe.virt_out_params_vars = [ self.configframe.virt_out_params_vars = [
tk.BooleanVar() for _ in self.configframe.virt_out_params tk.BooleanVar() for _ in self.configframe.virt_out_params
] ]
self.configframe.params = ("mono", "solo") self.configframe.params = ('mono', 'solo')
self.configframe.param_vars = list( self.configframe.param_vars = list(
tk.BooleanVar() for _ in self.configframe.params tk.BooleanVar() for _ in self.configframe.params
) )
if self.configframe.parent.kind.name in ("banana", "potato"): if self.configframe.parent.kind.name in ('banana', 'potato'):
if self.configframe.index == self.configframe.phys_in: if self.configframe.index == self.configframe.phys_in:
self.configframe.params = list( self.configframe.params = list(
map(lambda x: x.replace("mono", "mc"), self.configframe.params) map(lambda x: x.replace('mono', 'mc'), self.configframe.params)
) )
if self.configframe.parent.kind.name == "banana": if self.configframe.parent.kind.name == 'banana':
pass pass
# karaoke modes not in RT Packet yet. May implement in future # karaoke modes not in RT Packet yet. May implement in future
""" """
@ -388,101 +388,101 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder):
== self.configframe.phys_in + self.configframe.virt_in - 1 == self.configframe.phys_in + self.configframe.virt_in - 1
): ):
self.configframe.params = list( self.configframe.params = list(
map(lambda x: x.replace("mono", "mc"), self.configframe.params) map(lambda x: x.replace('mono', 'mc'), self.configframe.params)
) )
def create_comp_slider(self): def create_comp_slider(self):
comp_label = ttk.Label(self.configframe, text="Comp") comp_label = ttk.Label(self.configframe, text='Comp')
comp_scale = ttk.Scale( comp_scale = ttk.Scale(
self.configframe, self.configframe,
from_=0.0, from_=0.0,
to=10.0, to=10.0,
orient="horizontal", orient='horizontal',
length=_configuration.channel_width, length=_configuration.channel_width,
variable=self.configframe.slider_vars[ variable=self.configframe.slider_vars[
self.configframe.slider_params.index("comp.knob") self.configframe.slider_params.index('comp.knob')
], ],
command=partial(self.configframe.scale_callback, "comp.knob"), command=partial(self.configframe.scale_callback, 'comp.knob'),
) )
comp_scale.bind( comp_scale.bind(
"<Double-Button-1>", partial(self.configframe.reset_scale, "comp.knob", 0) '<Double-Button-1>', partial(self.configframe.reset_scale, 'comp.knob', 0)
) )
comp_scale.bind("<Button-1>", self.configframe.scale_press) comp_scale.bind('<Button-1>', self.configframe.scale_press)
comp_scale.bind("<ButtonRelease-1>", self.configframe.scale_release) comp_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
comp_scale.bind("<Enter>", partial(self.configframe.scale_enter, "comp.knob")) comp_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'comp.knob'))
comp_scale.bind("<Leave>", self.configframe.scale_leave) comp_scale.bind('<Leave>', self.configframe.scale_leave)
comp_label.grid(column=0, row=0) comp_label.grid(column=0, row=0)
comp_scale.grid(column=1, row=0) comp_scale.grid(column=1, row=0)
def create_gate_slider(self): def create_gate_slider(self):
gate_label = ttk.Label(self.configframe, text="Gate") gate_label = ttk.Label(self.configframe, text='Gate')
gate_scale = ttk.Scale( gate_scale = ttk.Scale(
self.configframe, self.configframe,
from_=0.0, from_=0.0,
to=10.0, to=10.0,
orient="horizontal", orient='horizontal',
length=_configuration.channel_width, length=_configuration.channel_width,
variable=self.configframe.slider_vars[ variable=self.configframe.slider_vars[
self.configframe.slider_params.index("gate.knob") self.configframe.slider_params.index('gate.knob')
], ],
command=partial(self.configframe.scale_callback, "gate.knob"), command=partial(self.configframe.scale_callback, 'gate.knob'),
) )
gate_scale.bind( gate_scale.bind(
"<Double-Button-1>", partial(self.configframe.reset_scale, "gate.knob", 0) '<Double-Button-1>', partial(self.configframe.reset_scale, 'gate.knob', 0)
) )
gate_scale.bind("<Button-1>", self.configframe.scale_press) gate_scale.bind('<Button-1>', self.configframe.scale_press)
gate_scale.bind("<ButtonRelease-1>", self.configframe.scale_release) gate_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
gate_scale.bind("<Enter>", partial(self.configframe.scale_enter, "gate.knob")) gate_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'gate.knob'))
gate_scale.bind("<Leave>", self.configframe.scale_leave) gate_scale.bind('<Leave>', self.configframe.scale_leave)
gate_label.grid(column=2, row=0) gate_label.grid(column=2, row=0)
gate_scale.grid(column=3, row=0) gate_scale.grid(column=3, row=0)
def create_limit_slider(self): def create_limit_slider(self):
limit_label = ttk.Label(self.configframe, text="Limit") limit_label = ttk.Label(self.configframe, text='Limit')
limit_scale = ttk.Scale( limit_scale = ttk.Scale(
self.configframe, self.configframe,
from_=-40, from_=-40,
to=12, to=12,
orient="horizontal", orient='horizontal',
length=_configuration.channel_width, length=_configuration.channel_width,
variable=self.configframe.slider_vars[ variable=self.configframe.slider_vars[
self.configframe.slider_params.index("limit") self.configframe.slider_params.index('limit')
], ],
command=partial(self.configframe.scale_callback, "limit"), command=partial(self.configframe.scale_callback, 'limit'),
) )
limit_scale.bind( limit_scale.bind(
"<Double-Button-1>", partial(self.configframe.reset_scale, "limit", 12) '<Double-Button-1>', partial(self.configframe.reset_scale, 'limit', 12)
) )
limit_scale.bind("<Button-1>", self.configframe.scale_press) limit_scale.bind('<Button-1>', self.configframe.scale_press)
limit_scale.bind("<ButtonRelease-1>", self.configframe.scale_release) limit_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
limit_scale.bind("<Enter>", partial(self.configframe.scale_enter, "limit")) limit_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'limit'))
limit_scale.bind("<Leave>", self.configframe.scale_leave) limit_scale.bind('<Leave>', self.configframe.scale_leave)
limit_label.grid(column=4, row=0) limit_label.grid(column=4, row=0)
limit_scale.grid(column=5, row=0) limit_scale.grid(column=5, row=0)
def create_audibility_slider(self): def create_audibility_slider(self):
aud_label = ttk.Label(self.configframe, text="Audibility") aud_label = ttk.Label(self.configframe, text='Audibility')
aud_scale = ttk.Scale( aud_scale = ttk.Scale(
self.configframe, self.configframe,
from_=0.0, from_=0.0,
to=10.0, to=10.0,
orient="horizontal", orient='horizontal',
length=_configuration.channel_width, length=_configuration.channel_width,
variable=self.configframe.slider_vars[ variable=self.configframe.slider_vars[
self.configframe.slider_params.index("audibility") self.configframe.slider_params.index('audibility')
], ],
command=partial(self.configframe.scale_callback, "audibility"), command=partial(self.configframe.scale_callback, 'audibility'),
) )
aud_scale.bind( aud_scale.bind(
"<Double-Button-1>", partial(self.configframe.reset_scale, "audibility", 0) '<Double-Button-1>', partial(self.configframe.reset_scale, 'audibility', 0)
) )
aud_scale.bind("<Button-1>", self.configframe.scale_press) aud_scale.bind('<Button-1>', self.configframe.scale_press)
aud_scale.bind("<ButtonRelease-1>", self.configframe.scale_release) aud_scale.bind('<ButtonRelease-1>', self.configframe.scale_release)
aud_scale.bind("<Enter>", partial(self.configframe.scale_enter, "audibility")) aud_scale.bind('<Enter>', partial(self.configframe.scale_enter, 'audibility'))
aud_scale.bind("<Leave>", self.configframe.scale_leave) aud_scale.bind('<Leave>', self.configframe.scale_leave)
aud_label.grid(column=0, row=0) aud_label.grid(column=0, row=0)
aud_scale.grid(column=1, row=0) aud_scale.grid(column=1, row=0)
@ -495,7 +495,7 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder):
command=partial( command=partial(
self.configframe.pause_updates, self.configframe.toggle_a, param self.configframe.pause_updates, self.configframe.toggle_a, param
), ),
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{param}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
variable=self.configframe.phys_out_params_vars[ variable=self.configframe.phys_out_params_vars[
self.configframe.phys_out_params.index(param) self.configframe.phys_out_params.index(param)
], ],
@ -518,7 +518,7 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder):
command=partial( command=partial(
self.configframe.pause_updates, self.configframe.toggle_b, param self.configframe.pause_updates, self.configframe.toggle_b, param
), ),
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{param}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
variable=self.configframe.virt_out_params_vars[ variable=self.configframe.virt_out_params_vars[
self.configframe.virt_out_params.index(param) self.configframe.virt_out_params.index(param)
], ],
@ -541,7 +541,7 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder):
command=partial( command=partial(
self.configframe.pause_updates, self.configframe.toggle_p, param self.configframe.pause_updates, self.configframe.toggle_p, param
), ),
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{param}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
variable=self.configframe.param_vars[i], variable=self.configframe.param_vars[i],
) )
for i, param in enumerate(self.configframe.params) for i, param in enumerate(self.configframe.params)
@ -576,7 +576,7 @@ class BusConfigFrameBuilder(ChannelConfigFrameBuilder):
} }
self.configframe.bus_modes = list(self.configframe.bus_mode_map.keys()) self.configframe.bus_modes = list(self.configframe.bus_mode_map.keys())
# fmt: on # fmt: on
self.configframe.params = ("mono", "eq.on", "eq.ab") self.configframe.params = ('mono', 'eq.on', 'eq.ab')
self.configframe.param_vars = [tk.BooleanVar() for _ in self.configframe.params] self.configframe.param_vars = [tk.BooleanVar() for _ in self.configframe.params]
self.configframe.bus_mode_label_text = tk.StringVar( self.configframe.bus_mode_label_text = tk.StringVar(
value=self.configframe.bus_mode_map[self.configframe.current_bus_mode()] value=self.configframe.bus_mode_map[self.configframe.current_bus_mode()]
@ -590,13 +590,13 @@ class BusConfigFrameBuilder(ChannelConfigFrameBuilder):
column=0, row=0, columnspan=2, sticky=(tk.W) column=0, row=0, columnspan=2, sticky=(tk.W)
) )
self.configframe.busmode_button.bind( self.configframe.busmode_button.bind(
"<Button-1>", '<Button-1>',
partial( partial(
self.configframe.pause_updates, self.configframe.rotate_bus_modes_right self.configframe.pause_updates, self.configframe.rotate_bus_modes_right
), ),
) )
self.configframe.busmode_button.bind( self.configframe.busmode_button.bind(
"<Button-3>", '<Button-3>',
partial( partial(
self.configframe.pause_updates, self.configframe.rotate_bus_modes_left self.configframe.pause_updates, self.configframe.rotate_bus_modes_left
), ),
@ -610,7 +610,7 @@ class BusConfigFrameBuilder(ChannelConfigFrameBuilder):
command=partial( command=partial(
self.configframe.pause_updates, self.configframe.toggle_p, param self.configframe.pause_updates, self.configframe.toggle_p, param
), ),
style=f"{'Toggle.TButton' if _configuration.themes_enabled else f'{param}.TButton'}", style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}',
variable=self.configframe.param_vars[i], variable=self.configframe.param_vars[i],
) )
for i, param in enumerate(self.configframe.params) for i, param in enumerate(self.configframe.params)

View File

@ -46,7 +46,7 @@ class ChannelLabelFrame(ttk.LabelFrame):
try: try:
return getattr(self.target, param) return getattr(self.target, param)
except AttributeError as e: except AttributeError as e:
self.logger(f"{type(e).__name__}: {e}") self.logger(f'{type(e).__name__}: {e}')
def setter(self, param, value): def setter(self, param, value):
if param in dir(self.target): # avoid calling getattr (with hasattr) if param in dir(self.target): # avoid calling getattr (with hasattr)
@ -56,19 +56,19 @@ class ChannelLabelFrame(ttk.LabelFrame):
"""callback function for scale widget""" """callback function for scale widget"""
val = round(self.gain.get(), 1) val = round(self.gain.get(), 1)
self.setter("gain", val) self.setter('gain', val)
self.gainlabel.set(val) self.gainlabel.set(val)
def toggle_mute(self, *args): def toggle_mute(self, *args):
self.target.mute = self.mute.get() self.target.mute = self.mute.get()
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{self.identifier}Mute{self.index}.TButton", f'{self.identifier}Mute{self.index}.TButton',
background=f'{"red" if self.mute.get() else "white"}', background=f'{"red" if self.mute.get() else "white"}',
) )
def reset_gain(self, *args): def reset_gain(self, *args):
self.setter("gain", 0) self.setter('gain', 0)
self.gain.set(0) self.gain.set(0)
self.gainlabel.set(self.gain.get()) self.gainlabel.set(self.gain.get())
@ -76,16 +76,16 @@ class ChannelLabelFrame(ttk.LabelFrame):
self.after(1, self.remove_events) self.after(1, self.remove_events)
def remove_events(self): def remove_events(self):
self.parent.target.event.remove("pdirty") self.parent.target.event.remove('pdirty')
self.parent.target.event.remove("ldirty") self.parent.target.event.remove('ldirty')
def scale_release(self, *args): def scale_release(self, *args):
_base_values.run_update = False _base_values.run_update = False
self.after(1, self.add_events) self.after(1, self.add_events)
def add_events(self): def add_events(self):
self.parent.target.event.add("pdirty") self.parent.target.event.add('pdirty')
self.parent.target.event.add("ldirty") self.parent.target.event.add('ldirty')
self.after(500, self.resume_updates) self.after(500, self.resume_updates)
def pause_updates(self, func, *args): def pause_updates(self, func, *args):
@ -115,7 +115,7 @@ class ChannelLabelFrame(ttk.LabelFrame):
self.gain.set(12) self.gain.set(12)
elif self.gain.get() < -60: elif self.gain.get() < -60:
self.gain.set(-60) self.gain.set(-60)
self.setter("gain", self.gain.get()) self.setter('gain', self.gain.get())
self.gainlabel.set(round(self.gain.get(), 1)) self.gainlabel.set(round(self.gain.get(), 1))
def open_config(self): def open_config(self):
@ -125,36 +125,36 @@ class ChannelLabelFrame(ttk.LabelFrame):
self.parent.parent.config_frame.teardown() self.parent.parent.config_frame.teardown()
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{self.identifier}Conf{self.index}.TButton", f'{self.identifier}Conf{self.index}.TButton',
background=f'{"yellow" if self.conf.get() else "white"}', background=f'{"yellow" if self.conf.get() else "white"}',
) )
def on_update(self, subject): def on_update(self, subject):
if subject == "ldirty": if subject == 'ldirty':
self.upd_levels() self.upd_levels()
elif subject == "pdirty": elif subject == 'pdirty':
self.sync_params() self.sync_params()
elif subject == "labelframe": elif subject == 'labelframe':
self.after(5, self.sync_labels) self.after(5, self.sync_labels)
def sync_params(self): def sync_params(self):
"""sync parameter states, update button colours""" """sync parameter states, update button colours"""
self.gain.set(self.getter("gain")) self.gain.set(self.getter('gain'))
self.gainlabel.set(round(self.gain.get(), 1)) self.gainlabel.set(round(self.gain.get(), 1))
self.mute.set(self.getter("mute")) self.mute.set(self.getter('mute'))
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{self.identifier}Mute{self.index}.TButton", f'{self.identifier}Mute{self.index}.TButton',
background=f'{"red" if self.mute.get() else "white"}', background=f'{"red" if self.mute.get() else "white"}',
) )
def sync_labels(self): def sync_labels(self):
"""sync labelframes according to label text""" """sync labelframes according to label text"""
retval = self.getter("label") retval = self.getter('label')
if self.parent.label_cache[self.id][self.index] != retval: if self.parent.label_cache[self.id][self.index] != retval:
self.parent.label_cache[self.id][self.index] = retval self.parent.label_cache[self.id][self.index] = retval
if len(retval) > 10: if len(retval) > 10:
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.remove(self) self.parent.parent.subject.remove(self)
@ -236,8 +236,8 @@ class ChannelFrame(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.label_cache = { self.label_cache = {
"strip": [""] * (self.phys_in + self.virt_in), 'strip': [''] * (self.phys_in + self.virt_in),
"bus": [""] * (self.phys_out + self.virt_out), 'bus': [''] * (self.phys_out + self.virt_out),
} }
self.parent.subject.add(self) self.parent.subject.add(self)
self.update_labels() self.update_labels()
@ -264,10 +264,10 @@ class ChannelFrame(ttk.Frame):
def update_labels(self): def update_labels(self):
for labelframe in self.labelframes: for labelframe in self.labelframes:
labelframe.on_update("labelframe") labelframe.on_update('labelframe')
def on_update(self, subject): def on_update(self, subject):
if subject == "pdirty": if subject == 'pdirty':
self.update_labels() self.update_labels()
def grid_configure(self): def grid_configure(self):
@ -281,7 +281,7 @@ class ChannelFrame(ttk.Frame):
[self.parent.subject.remove(frame) for frame in self.labelframes] [self.parent.subject.remove(frame) for frame in self.labelframes]
self.parent.subject.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)
def _make_channelframe(parent, identifier): def _make_channelframe(parent, identifier):
@ -298,7 +298,7 @@ def _make_channelframe(parent, identifier):
""" """
for i, labelframe in enumerate( for i, labelframe in enumerate(
getattr(self, "strips" if identifier == "strip" else "buses") getattr(self, 'strips' if identifier == 'strip' else 'buses')
): ):
labelframe.grid(row=0, column=i) labelframe.grid(row=0, column=i)
label = labelframe.target.label label = labelframe.target.label
@ -329,20 +329,20 @@ def _make_channelframe(parent, identifier):
self.grid_configure() self.grid_configure()
init_labels(self) init_labels(self)
if identifier == "strip": if identifier == 'strip':
CHANNELFRAME_cls = type( CHANNELFRAME_cls = type(
f"ChannelFrame{identifier.capitalize()}", f'ChannelFrame{identifier.capitalize()}',
(ChannelFrame,), (ChannelFrame,),
{ {
"__init__": init_strip, '__init__': init_strip,
}, },
) )
else: else:
CHANNELFRAME_cls = type( CHANNELFRAME_cls = type(
f"ChannelFrame{identifier.capitalize()}", f'ChannelFrame{identifier.capitalize()}',
(ChannelFrame,), (ChannelFrame,),
{ {
"__init__": init_bus, '__init__': init_bus,
}, },
) )
return CHANNELFRAME_cls(parent) return CHANNELFRAME_cls(parent)

View File

@ -31,7 +31,7 @@ class Config(ttk.Frame):
return self.parent.target return self.parent.target
def getter(self, param): def getter(self, param):
param = param.split(".") param = param.split('.')
try: try:
if len(param) == 2: if len(param) == 2:
target = getattr(self.target, param[0]) target = getattr(self.target, param[0])
@ -39,10 +39,10 @@ class Config(ttk.Frame):
else: else:
return getattr(self.target, param[0]) return getattr(self.target, param[0])
except AttributeError as e: except AttributeError as e:
self.logger.error(f"{type(e).__name__}: {e}") self.logger.error(f'{type(e).__name__}: {e}')
def setter(self, param, value): def setter(self, param, value):
param = param.split(".") param = param.split('.')
try: try:
if len(param) == 2: if len(param) == 2:
target = getattr(self.target, param[0]) target = getattr(self.target, param[0])
@ -50,22 +50,22 @@ class Config(ttk.Frame):
else: else:
setattr(self.target, param[0], value) setattr(self.target, param[0], value)
except AttributeError as e: except AttributeError as e:
self.logger(f"{type(e).__name__}: {e}") self.logger(f'{type(e).__name__}: {e}')
def scale_press(self, *args): def scale_press(self, *args):
self.after(1, self.remove_events) self.after(1, self.remove_events)
def remove_events(self): def remove_events(self):
self.parent.target.event.remove("pdirty") self.parent.target.event.remove('pdirty')
self.parent.target.event.remove("ldirty") self.parent.target.event.remove('ldirty')
def scale_release(self, *args): def scale_release(self, *args):
_base_values.run_update = False _base_values.run_update = False
self.after(1, self.add_events) self.after(1, self.add_events)
def add_events(self): def add_events(self):
self.parent.target.event.add("pdirty") self.parent.target.event.add('pdirty')
self.parent.target.event.add("ldirty") self.parent.target.event.add('ldirty')
self.after(350, self.resume_updates) self.after(350, self.resume_updates)
def pause_updates(self, func, *args): def pause_updates(self, func, *args):
@ -84,7 +84,7 @@ class Config(ttk.Frame):
self.parent.nav_frame.info_text.set(round(val, 1)) self.parent.nav_frame.info_text.set(round(val, 1))
def scale_leave(self, *args): def scale_leave(self, *args):
self.parent.nav_frame.info_text.set("") self.parent.nav_frame.info_text.set('')
def scale_callback(self, param, *args): def scale_callback(self, param, *args):
"""callback function for scale widget""" """callback function for scale widget"""
@ -102,12 +102,12 @@ class Config(ttk.Frame):
self.setter(param, val) self.setter(param, val)
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", background=f'{"green" if val else "white"}' f'{param}.TButton', background=f'{"green" if val else "white"}'
) )
def on_update(self, subject): def on_update(self, subject):
"""update parameters""" """update parameters"""
if subject == "pdirty": if subject == 'pdirty':
self.sync() self.sync()
@ -134,7 +134,7 @@ class StripConfig(Config):
def make_row_0(self): def make_row_0(self):
if self.index < self.phys_in: if self.index < self.phys_in:
if self.parent.kind.name == "basic": if self.parent.kind.name == 'basic':
self.builder.create_audibility_slider() self.builder.create_audibility_slider()
else: else:
self.builder.create_comp_slider() self.builder.create_comp_slider()
@ -153,7 +153,7 @@ class StripConfig(Config):
self.setter(param, val) self.setter(param, val)
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", background=f'{"green" if val else "white"}' f'{param}.TButton', background=f'{"green" if val else "white"}'
) )
def toggle_b(self, param): def toggle_b(self, param):
@ -161,7 +161,7 @@ class StripConfig(Config):
self.setter(param, val) self.setter(param, val)
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", background=f'{"green" if val else "white"}' f'{param}.TButton', background=f'{"green" if val else "white"}'
) )
def teardown(self): def teardown(self):
@ -190,21 +190,21 @@ class StripConfig(Config):
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
[ [
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", f'{param}.TButton',
background=f'{"green" if self.phys_out_params_vars[i].get() else "white"}', background=f'{"green" if self.phys_out_params_vars[i].get() else "white"}',
) )
for i, param in enumerate(self.phys_out_params) for i, param in enumerate(self.phys_out_params)
] ]
[ [
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", f'{param}.TButton',
background=f'{"green" if self.virt_out_params_vars[i].get() else "white"}', background=f'{"green" if self.virt_out_params_vars[i].get() else "white"}',
) )
for i, param in enumerate(self.virt_out_params) for i, param in enumerate(self.virt_out_params)
] ]
[ [
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", f'{param}.TButton',
background=f'{"green" if self.param_vars[i].get() else "white"}', background=f'{"green" if self.param_vars[i].get() else "white"}',
) )
for i, param in enumerate(self.params) for i, param in enumerate(self.params)
@ -255,14 +255,14 @@ class BusConfig(Config):
self.bus_mode_label_text.set(self.bus_mode_map[self.bus_modes[next]]) self.bus_mode_label_text.set(self.bus_mode_map[self.bus_modes[next]])
else: else:
self.target.mode.normal = True self.target.mode.normal = True
self.bus_mode_label_text.set("Normal") self.bus_mode_label_text.set('Normal')
def rotate_bus_modes_left(self, *args): def rotate_bus_modes_left(self, *args):
current_mode = self.current_bus_mode() current_mode = self.current_bus_mode()
prev = self.bus_modes.index(current_mode) - 1 prev = self.bus_modes.index(current_mode) - 1
if prev < 0: if prev < 0:
self.target.mode.rearonly = True self.target.mode.rearonly = True
self.bus_mode_label_text.set("Rear Only") self.bus_mode_label_text.set('Rear Only')
else: else:
setattr( setattr(
self.target.mode, self.target.mode,
@ -283,7 +283,7 @@ class BusConfig(Config):
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
[ [
self.styletable.configure( self.styletable.configure(
f"{param}.TButton", f'{param}.TButton',
background=f'{"green" if self.param_vars[i].get() else "white"}', background=f'{"green" if self.param_vars[i].get() else "white"}',
) )
for i, param in enumerate(self.params) for i, param in enumerate(self.params)

View File

@ -13,9 +13,9 @@ configuration = {}
def get_configpath(): def get_configpath():
configpaths = [ configpaths = [
Path.cwd() / "configs", Path.cwd() / 'configs',
Path.home() / ".config" / "vm-compact" / "configs", Path.home() / '.config' / 'vm-compact' / 'configs',
Path.home() / "Documents" / "Voicemeeter" / "configs", Path.home() / 'Documents' / 'Voicemeeter' / 'configs',
] ]
for configpath in configpaths: for configpath in configpaths:
if configpath.exists(): if configpath.exists():
@ -23,55 +23,55 @@ def get_configpath():
if configpath := get_configpath(): if configpath := get_configpath():
filepaths = list(configpath.glob("*.toml")) filepaths = list(configpath.glob('*.toml'))
if any(f.stem in ("app", "vban") for f in filepaths): if any(f.stem in ('app', 'vban') for f in filepaths):
configs = {} configs = {}
for filepath in filepaths: for filepath in filepaths:
filename = filepath.with_suffix("").stem filename = filepath.with_suffix('').stem
if filename in ("app", "vban"): if filename in ('app', 'vban'):
try: try:
with open(filepath, "rb") as f: with open(filepath, 'rb') as f:
configs[filename] = tomllib.load(f) configs[filename] = tomllib.load(f)
logger.info(f"configuration: {filename} loaded into memory") logger.info(f'configuration: {filename} loaded into memory')
except tomllib.TOMLDecodeError: except tomllib.TOMLDecodeError:
logger.error(f"Invalid TOML config: configs/{filename.stem}") logger.error(f'Invalid TOML config: configs/{filename.stem}')
configuration |= configs configuration |= configs
_defaults = { _defaults = {
"configs": { 'configs': {
"config": None, 'config': None,
}, },
"theme": { 'theme': {
"enabled": True, 'enabled': True,
"mode": "light", 'mode': 'light',
}, },
"extends": { 'extends': {
"extended": True, 'extended': True,
"extends_horizontal": True, 'extends_horizontal': True,
}, },
"channel": { 'channel': {
"width": 80, 'width': 80,
"height": 130, 'height': 130,
"xpadding": 3, 'xpadding': 3,
}, },
"mwscroll_step": { 'mwscroll_step': {
"size": 3, 'size': 3,
}, },
"submixes": { 'submixes': {
"default": 0, 'default': 0,
}, },
"navigation": {"show": True}, 'navigation': {'show': True},
} }
if "app" in configuration: if 'app' in configuration:
for key in _defaults: for key in _defaults:
if key in configuration["app"]: if key in configuration['app']:
configuration["app"][key] = _defaults[key] | configuration["app"][key] configuration['app'][key] = _defaults[key] | configuration['app'][key]
else: else:
configuration["app"][key] = _defaults[key] configuration['app'][key] = _defaults[key]
else: else:
configuration["app"] = _defaults configuration['app'] = _defaults
def get_configuration(key): def get_configuration(key):
@ -80,19 +80,19 @@ def get_configuration(key):
def loader(kind_id, target): def loader(kind_id, target):
configs = {"reset": target.configs["reset"]} configs = {'reset': target.configs['reset']}
if configpath := get_configpath(): if configpath := get_configpath():
userconfigpath = configpath / kind_id userconfigpath = configpath / kind_id
if userconfigpath.exists(): if userconfigpath.exists():
filepaths = list(userconfigpath.glob("*.toml")) filepaths = list(userconfigpath.glob('*.toml'))
for filepath in filepaths: for filepath in filepaths:
identifier = filepath.with_suffix("").stem identifier = filepath.with_suffix('').stem
try: try:
with open(filepath, "rb") as f: with open(filepath, 'rb') as f:
configs[identifier] = tomllib.load(f) configs[identifier] = tomllib.load(f)
logger.info(f"loader: {identifier} loaded into memory") logger.info(f'loader: {identifier} loaded into memory')
except tomllib.TOMLDecodeError: except tomllib.TOMLDecodeError:
logger.error(f"Invalid TOML config: configs/{filename.stem}") logger.error(f'Invalid TOML config: configs/{filename.stem}')
target.configs = configs target.configs = configs
return target.configs return target.configs

View File

@ -4,7 +4,7 @@ from voicemeeterlib import kinds
from .configurations import get_configuration from .configurations import get_configuration
configuration = get_configuration("app") configuration = get_configuration('app')
class SingletonMeta(type): class SingletonMeta(type):
@ -20,32 +20,32 @@ class SingletonMeta(type):
@dataclass @dataclass
class Configurations(metaclass=SingletonMeta): class Configurations(metaclass=SingletonMeta):
# is the gui extended # is the gui extended
extended: bool = configuration["extends"]["extended"] extended: bool = configuration['extends']['extended']
# direction the gui extends # direction the gui extends
extends_horizontal: bool = configuration["extends"]["extends_horizontal"] extends_horizontal: bool = configuration['extends']['extends_horizontal']
# are themes enabled # are themes enabled
themes_enabled: bool = configuration["theme"]["enabled"] themes_enabled: bool = configuration['theme']['enabled']
# light or dark # light or dark
theme_mode: str = configuration["theme"]["mode"] theme_mode: str = configuration['theme']['mode']
# size of mousewheel scroll step # size of mousewheel scroll step
mwscroll_step: int = configuration["mwscroll_step"]["size"] mwscroll_step: int = configuration['mwscroll_step']['size']
# bus assigned as current submix # bus assigned as current submix
submixes: int = configuration["submixes"]["default"] submixes: int = configuration['submixes']['default']
# width of a single channel labelframe # width of a single channel labelframe
channel_width: int = configuration["channel"]["width"] channel_width: int = configuration['channel']['width']
# height of a single channel labelframe # height of a single channel labelframe
channel_height: int = configuration["channel"]["height"] channel_height: int = configuration['channel']['height']
# xpadding for a single channel labelframe # xpadding for a single channel labelframe
channel_xpadding: int = configuration["channel"]["xpadding"] channel_xpadding: int = configuration['channel']['xpadding']
# do we grid the navigation frame? # do we grid the navigation frame?
navigation_show: bool = configuration["navigation"]["show"] navigation_show: bool = configuration['navigation']['show']
@property @property
def config(self): def config(self):
if "configs" in configuration: if 'configs' in configuration:
return configuration["configs"]["config"] return configuration['configs']['config']
@dataclass @dataclass

View File

@ -19,7 +19,7 @@ class GainLayer(ttk.LabelFrame):
else: else:
self.level_offset = parent.phys_in * 2 + (index - parent.phys_in) * 8 self.level_offset = parent.phys_in * 2 + (index - parent.phys_in) * 8
self.builder = builders.ChannelLabelFrameBuilder(self, index, id="gainlayer") self.builder = builders.ChannelLabelFrameBuilder(self, index, id='gainlayer')
self.builder.setup() self.builder.setup()
self.builder.add_progressbar() self.builder.add_progressbar()
self.builder.add_scale() self.builder.add_scale()
@ -38,20 +38,20 @@ class GainLayer(ttk.LabelFrame):
@property @property
def identifier(self): def identifier(self):
return "gainlayer" return 'gainlayer'
def getter(self, param): def getter(self, param):
try: try:
return getattr(self.target, param) return getattr(self.target, param)
except AttributeError as e: except AttributeError as e:
self.logger(f"{type(e).__name__}: {e}") self.logger(f'{type(e).__name__}: {e}')
def setter(self, param, value): def setter(self, param, value):
if param in dir(self.target): # avoid calling getattr (with hasattr) if param in dir(self.target): # avoid calling getattr (with hasattr)
setattr(self.target, param, value) setattr(self.target, param, value)
def reset_gain(self, *args): def reset_gain(self, *args):
self.setter("gain", 0) self.setter('gain', 0)
self.gain.set(0) self.gain.set(0)
self.gainlabel.set(self.gain.get()) self.gainlabel.set(self.gain.get())
@ -59,23 +59,23 @@ class GainLayer(ttk.LabelFrame):
"""callback function for scale widget""" """callback function for scale widget"""
val = round(self.gain.get(), 1) val = round(self.gain.get(), 1)
self.setter("gain", val) self.setter('gain', val)
self.gainlabel.set(val) self.gainlabel.set(val)
def scale_press(self, *args): def scale_press(self, *args):
self.after(1, self.remove_events) self.after(1, self.remove_events)
def remove_events(self): def remove_events(self):
self.parent.target.event.remove("pdirty") self.parent.target.event.remove('pdirty')
self.parent.target.event.remove("ldirty") self.parent.target.event.remove('ldirty')
def scale_release(self, *args): def scale_release(self, *args):
_base_values.run_update = False _base_values.run_update = False
self.after(1, self.add_events) self.after(1, self.add_events)
def add_events(self): def add_events(self):
self.parent.target.event.add("pdirty") self.parent.target.event.add('pdirty')
self.parent.target.event.add("ldirty") self.parent.target.event.add('ldirty')
self.after(500, self.resume_updates) self.after(500, self.resume_updates)
def pause_updates(self, func, *args): def pause_updates(self, func, *args):
@ -103,7 +103,7 @@ class GainLayer(ttk.LabelFrame):
self.gain.set(12) self.gain.set(12)
elif self.gain.get() < -60: elif self.gain.get() < -60:
self.gain.set(-60) self.gain.set(-60)
self.setter("gain", self.gain.get()) self.setter('gain', self.gain.get())
self.after(1, self.resume_updates) self.after(1, self.resume_updates)
def set_on(self): def set_on(self):
@ -116,20 +116,20 @@ class GainLayer(ttk.LabelFrame):
) )
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{self.identifier}On{self.index}.TButton", f'{self.identifier}On{self.index}.TButton',
background=f'{"green" if self.on.get() else "white"}', background=f'{"green" if self.on.get() else "white"}',
) )
def on_update(self, subject): def on_update(self, subject):
if subject == "ldirty": if subject == 'ldirty':
self.upd_levels() self.upd_levels()
elif subject == "pdirty": elif subject == 'pdirty':
self.sync_params() self.sync_params()
elif subject == "labelframe": elif subject == 'labelframe':
self.after(5, self.sync_labels) self.after(5, self.sync_labels)
def sync_params(self): def sync_params(self):
self.gain.set(self.getter("gain")) self.gain.set(self.getter('gain'))
self.gainlabel.set(round(self.gain.get(), 1)) self.gainlabel.set(round(self.gain.get(), 1))
self.on.set( self.on.set(
getattr( getattr(
@ -139,7 +139,7 @@ class GainLayer(ttk.LabelFrame):
) )
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"{self.identifier}On{self.index}.TButton", f'{self.identifier}On{self.index}.TButton',
background=f'{"green" if self.on.get() else "white"}', background=f'{"green" if self.on.get() else "white"}',
) )
@ -147,7 +147,7 @@ class GainLayer(ttk.LabelFrame):
"""sync params with voicemeeter""" """sync params with voicemeeter"""
retval = self.parent.target.strip[self.index].label retval = self.parent.target.strip[self.index].label
if len(retval) > 10: if len(retval) > 10:
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.remove(self) self.parent.parent.subject.remove(self)
@ -201,8 +201,8 @@ class SubMixFrame(ttk.Frame):
self.parent = parent self.parent = parent
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.buses = tuple(f"A{i+1}" for i in range(self.phys_out)) + tuple( self.buses = tuple(f'A{i + 1}' for i in range(self.phys_out)) + tuple(
f"B{i+1}" for i in range(self.virt_out) f'B{i + 1}' for i in range(self.virt_out)
) )
self.gainlayers = [ self.gainlayers = [
@ -221,7 +221,7 @@ class SubMixFrame(ttk.Frame):
else: else:
if parent.bus_frame and parent.bus_frame.grid_info(): if parent.bus_frame and parent.bus_frame.grid_info():
self.grid( self.grid(
row=parent.bus_frame.grid_info()["row"], column=0, sticky=(tk.W) row=parent.bus_frame.grid_info()['row'], column=0, sticky=(tk.W)
) )
parent.bus_frame.grid_remove() parent.bus_frame.grid_remove()
else: else:
@ -256,9 +256,9 @@ class SubMixFrame(ttk.Frame):
) )
def on_update(self, subject): def on_update(self, subject):
if subject == "pdirty": if subject == 'pdirty':
for labelframe in self.labelframes: for labelframe in self.labelframes:
labelframe.on_update("labelframe") labelframe.on_update('labelframe')
def grid_configure(self): def grid_configure(self):
[ [

View File

@ -4,11 +4,10 @@ import webbrowser
from functools import partial from functools import partial
from tkinter import messagebox from tkinter import messagebox
import sv_ttk
import vban_cmd import vban_cmd
from vban_cmd.error import VBANCMDConnectionError from vban_cmd.error import VBANCMDConnectionError
import sv_ttk
from .data import _base_values, _configuration, get_configuration, kind_get from .data import _base_values, _configuration, get_configuration, kind_get
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -20,8 +19,8 @@ class Menus(tk.Menu):
self.parent = parent self.parent = parent
self.vmr = vmr self.vmr = vmr
self.logger = logger.getChild(self.__class__.__name__) self.logger = logger.getChild(self.__class__.__name__)
self.vban_config = get_configuration("vban") self.vban_config = get_configuration('vban')
self.app_config = get_configuration("app") self.app_config = get_configuration('app')
self._is_topmost = tk.BooleanVar() self._is_topmost = tk.BooleanVar()
self._lock = tk.BooleanVar() self._lock = tk.BooleanVar()
self._unlock = tk.BooleanVar() self._unlock = tk.BooleanVar()
@ -31,9 +30,9 @@ class Menus(tk.Menu):
# voicemeeter menu # voicemeeter menu
self.menu_voicemeeter = tk.Menu(self, tearoff=0) self.menu_voicemeeter = tk.Menu(self, tearoff=0)
self.add_cascade(menu=self.menu_voicemeeter, label="Voicemeeter") self.add_cascade(menu=self.menu_voicemeeter, label='Voicemeeter')
self.menu_voicemeeter.add_checkbutton( self.menu_voicemeeter.add_checkbutton(
label="Always On Top", label='Always On Top',
onvalue=1, onvalue=1,
offvalue=0, offvalue=0,
variable=self._is_topmost, variable=self._is_topmost,
@ -41,51 +40,51 @@ class Menus(tk.Menu):
) )
self.menu_voicemeeter.add_separator() self.menu_voicemeeter.add_separator()
self.menu_voicemeeter.add_command( self.menu_voicemeeter.add_command(
label="Show", label='Show',
underline=0, underline=0,
command=partial(self.action_invoke_voicemeeter, "show"), command=partial(self.action_invoke_voicemeeter, 'show'),
) )
self.menu_voicemeeter.add_command( self.menu_voicemeeter.add_command(
label="Hide", label='Hide',
underline=0, underline=0,
command=partial(self.action_invoke_voicemeeter, "hide"), command=partial(self.action_invoke_voicemeeter, 'hide'),
) )
self.menu_voicemeeter.add_command( self.menu_voicemeeter.add_command(
label="Restart", label='Restart',
underline=0, underline=0,
command=partial(self.action_invoke_voicemeeter, "restart"), command=partial(self.action_invoke_voicemeeter, 'restart'),
) )
self.menu_voicemeeter.add_command( self.menu_voicemeeter.add_command(
label="Shutdown", label='Shutdown',
underline=0, underline=0,
command=partial(self.action_invoke_voicemeeter, "shutdown"), command=partial(self.action_invoke_voicemeeter, 'shutdown'),
) )
self.menu_voicemeeter.add_separator() self.menu_voicemeeter.add_separator()
self.menu_lock = tk.Menu(self.menu_voicemeeter, tearoff=0) self.menu_lock = tk.Menu(self.menu_voicemeeter, tearoff=0)
self.menu_voicemeeter.add_cascade( self.menu_voicemeeter.add_cascade(
menu=self.menu_lock, label="GUI Lock", underline=0 menu=self.menu_lock, label='GUI Lock', underline=0
) )
self.menu_lock.add_checkbutton( self.menu_lock.add_checkbutton(
label="Lock", label='Lock',
onvalue=1, onvalue=1,
offvalue=0, offvalue=0,
variable=self._lock, variable=self._lock,
command=partial(self.action_set_voicemeeter, "lock"), command=partial(self.action_set_voicemeeter, 'lock'),
) )
self.menu_lock.add_checkbutton( self.menu_lock.add_checkbutton(
label="Unlock", label='Unlock',
onvalue=1, onvalue=1,
offvalue=0, offvalue=0,
variable=self._unlock, variable=self._unlock,
command=partial(self.action_set_voicemeeter, "lock", False), command=partial(self.action_set_voicemeeter, 'lock', False),
) )
# configs menu # configs menu
self.menu_configs = tk.Menu(self, tearoff=0) self.menu_configs = tk.Menu(self, tearoff=0)
self.add_cascade(menu=self.menu_configs, label="Configs") self.add_cascade(menu=self.menu_configs, label='Configs')
self.menu_configs_load = tk.Menu(self.menu_configs, tearoff=0) self.menu_configs_load = tk.Menu(self.menu_configs, tearoff=0)
self.menu_configs.add_cascade(menu=self.menu_configs_load, label="Load config") self.menu_configs.add_cascade(menu=self.menu_configs_load, label='Load config')
self.config_defaults = {"reset"} self.config_defaults = {'reset'}
if len(self.parent.userconfigs) > len(self.config_defaults) and all( if len(self.parent.userconfigs) > len(self.config_defaults) and all(
key in self.parent.userconfigs for key in self.config_defaults key in self.parent.userconfigs for key in self.config_defaults
): ):
@ -97,22 +96,24 @@ class Menus(tk.Menu):
if profile not in self.config_defaults if profile not in self.config_defaults
] ]
else: else:
self.menu_configs.entryconfig(0, state="disabled") self.menu_configs.entryconfig(0, state='disabled')
self.menu_configs.add_command( self.menu_configs.add_command(
label="Reset to defaults", command=self.load_defaults label='Reset to defaults', command=self.load_defaults
) )
# layout menu # layout menu
self.menu_layout = tk.Menu(self, tearoff=0) self.menu_layout = tk.Menu(self, tearoff=0)
self.add_cascade(menu=self.menu_layout, label="Layout") self.add_cascade(menu=self.menu_layout, label='Layout')
# layout/submixes # layout/submixes
# here we build menu regardless of kind but disable if not potato # here we build menu regardless of kind but disable if not potato
buses = tuple(f"A{i+1}" for i in range(5)) + tuple(f"B{i+1}" for i in range(3)) buses = tuple(f'A{i + 1}' for i in range(5)) + tuple(
f'B{i + 1}' for i in range(3)
)
self.menu_submixes = tk.Menu(self.menu_layout, tearoff=0) self.menu_submixes = tk.Menu(self.menu_layout, tearoff=0)
self.menu_layout.add_cascade(menu=self.menu_submixes, label="Submixes") self.menu_layout.add_cascade(menu=self.menu_submixes, label='Submixes')
[ [
self.menu_submixes.add_checkbutton( self.menu_submixes.add_checkbutton(
label=f"Bus {buses[i]}", label=f'Bus {buses[i]}',
underline=0, underline=0,
onvalue=1, onvalue=1,
offvalue=0, offvalue=0,
@ -122,94 +123,94 @@ class Menus(tk.Menu):
for i in range(8) for i in range(8)
] ]
self._selected_bus[_configuration.submixes].set(True) self._selected_bus[_configuration.submixes].set(True)
if self.parent.kind.name != "potato": if self.parent.kind.name != 'potato':
self.menu_layout.entryconfig(0, state="disabled") self.menu_layout.entryconfig(0, state='disabled')
# layout/extends # layout/extends
self.menu_extends = tk.Menu(self.menu_layout, tearoff=0) self.menu_extends = tk.Menu(self.menu_layout, tearoff=0)
self.menu_layout.add_cascade( self.menu_layout.add_cascade(
menu=self.menu_extends, label="Extends", underline=0 menu=self.menu_extends, label='Extends', underline=0
) )
self.menu_extends.add_command( self.menu_extends.add_command(
label="horizontal", label='horizontal',
underline=0, underline=0,
command=partial(self.switch_orientation, extends_horizontal=True), command=partial(self.switch_orientation, extends_horizontal=True),
) )
self.menu_extends.add_command( self.menu_extends.add_command(
label="vertical", label='vertical',
underline=0, underline=0,
command=partial(self.switch_orientation, extends_horizontal=False), command=partial(self.switch_orientation, extends_horizontal=False),
) )
self.menu_extends.entryconfig( self.menu_extends.entryconfig(
0 if _configuration.extends_horizontal else 1, state="disabled" 0 if _configuration.extends_horizontal else 1, state='disabled'
) )
# layout/themes # layout/themes
self.menu_themes = tk.Menu(self.menu_layout, tearoff=0) self.menu_themes = tk.Menu(self.menu_layout, tearoff=0)
self.menu_layout.add_cascade(menu=self.menu_themes, label="Themes") self.menu_layout.add_cascade(menu=self.menu_themes, label='Themes')
self.menu_themes.add_command( self.menu_themes.add_command(
label="light", command=partial(self.load_theme, "light") label='light', command=partial(self.load_theme, 'light')
) )
self.menu_themes.add_command( self.menu_themes.add_command(
label="dark", command=partial(self.load_theme, "dark") label='dark', command=partial(self.load_theme, 'dark')
) )
self.menu_themes.entryconfig( self.menu_themes.entryconfig(
0 if self.app_config["theme"]["mode"] == "light" else 1, 0 if self.app_config['theme']['mode'] == 'light' else 1,
state="disabled", state='disabled',
) )
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.menu_layout.entryconfig(2, state="disabled") self.menu_layout.entryconfig(2, state='disabled')
# layout/navigation # layout/navigation
self.menu_navigation = tk.Menu(self.menu_layout, tearoff=0) self.menu_navigation = tk.Menu(self.menu_layout, tearoff=0)
self.menu_layout.add_cascade(menu=self.menu_navigation, label="Navigation") self.menu_layout.add_cascade(menu=self.menu_navigation, label='Navigation')
self.menu_navigation.add_checkbutton( self.menu_navigation.add_checkbutton(
label="show", label='show',
onvalue=1, onvalue=1,
offvalue=0, offvalue=0,
variable=self._navigation_show, variable=self._navigation_show,
command=partial(self.toggle_navigation, "show"), command=partial(self.toggle_navigation, 'show'),
) )
self.menu_navigation.add_checkbutton( self.menu_navigation.add_checkbutton(
label="hide", label='hide',
onvalue=1, onvalue=1,
offvalue=0, offvalue=0,
variable=self._navigation_hide, variable=self._navigation_hide,
command=partial(self.toggle_navigation, "hide"), command=partial(self.toggle_navigation, 'hide'),
) )
# vban connect menu # vban connect menu
self.menu_vban = tk.Menu(self, tearoff=0) self.menu_vban = tk.Menu(self, tearoff=0)
self.add_cascade(menu=self.menu_vban, label="VBAN") self.add_cascade(menu=self.menu_vban, label='VBAN')
if self.vban_config: if self.vban_config:
for i, _ in enumerate(self.vban_config): for i, _ in enumerate(self.vban_config):
setattr(self, f"menu_vban_{i+1}", tk.Menu(self.menu_vban, tearoff=0)) setattr(self, f'menu_vban_{i + 1}', tk.Menu(self.menu_vban, tearoff=0))
target_menu = getattr(self, f"menu_vban_{i+1}") target_menu = getattr(self, f'menu_vban_{i + 1}')
self.menu_vban.add_cascade( self.menu_vban.add_cascade(
menu=target_menu, menu=target_menu,
label=f"{self.vban_config[f'connection-{i+1}']['streamname']}", label=f'{self.vban_config[f"connection-{i + 1}"]["streamname"]}',
underline=0, underline=0,
) )
target_menu.add_command( target_menu.add_command(
label="Connect", command=partial(self.vban_connect, i) label='Connect', command=partial(self.vban_connect, i)
) )
target_menu.add_command( target_menu.add_command(
label="Disconnect", command=partial(self.vban_disconnect, i) label='Disconnect', command=partial(self.vban_disconnect, i)
) )
target_menu.entryconfig(1, state="disabled") target_menu.entryconfig(1, state='disabled')
else: else:
self.entryconfig(4, state="disabled") self.entryconfig(4, state='disabled')
# Help menu # Help menu
self.menu_help = tk.Menu(self, tearoff=0) self.menu_help = tk.Menu(self, tearoff=0)
self.add_cascade(menu=self.menu_help, label="Help") self.add_cascade(menu=self.menu_help, label='Help')
self.menu_help.add_command( self.menu_help.add_command(
label="Voicemeeter Site", label='Voicemeeter Site',
command=self.documentation, command=self.documentation,
) )
self.menu_help.add_command( self.menu_help.add_command(
label="Source Code", label='Source Code',
command=self.github, command=self.github,
) )
self.menu_help.add_command( self.menu_help.add_command(
label="App Creator", label='App Creator',
command=self.onyxandiris, command=self.onyxandiris,
) )
@ -220,56 +221,56 @@ class Menus(tk.Menu):
def enable_vban_menus(self): def enable_vban_menus(self):
[ [
self.menu_vban.entryconfig(j, state="normal") self.menu_vban.entryconfig(j, state='normal')
for j, _ in enumerate(self.menu_vban.winfo_children()) for j, _ in enumerate(self.menu_vban.winfo_children())
] ]
def action_invoke_voicemeeter(self, cmd): def action_invoke_voicemeeter(self, cmd):
if fn := getattr(self.target.command, cmd): if fn := getattr(self.target.command, cmd):
fn() fn()
if cmd == "shutdown": if cmd == 'shutdown':
self.parent.on_close_window() self.parent.on_close_window()
def action_set_voicemeeter(self, cmd, val=True): def action_set_voicemeeter(self, cmd, val=True):
if cmd == "lock": if cmd == 'lock':
self._lock.set(val) self._lock.set(val)
self._unlock.set(not self._lock.get()) self._unlock.set(not self._lock.get())
setattr(self.target.command, cmd, val) setattr(self.target.command, cmd, val)
def load_custom_profile(self, profile): def load_custom_profile(self, profile):
self.logger.info(f"loading user profile {profile}") self.logger.info(f'loading user profile {profile}')
self.target.apply(profile) self.target.apply(profile)
if not _base_values.run_update: if not _base_values.run_update:
self.parent.subject.notify("pdirty") self.parent.subject.notify('pdirty')
def load_profile(self, profile): def load_profile(self, profile):
self.logger.info(f"loading user profile {profile}") self.logger.info(f'loading user profile {profile}')
self.target.apply_config(profile) self.target.apply_config(profile)
if not _base_values.run_update: if not _base_values.run_update:
self.parent.subject.notify("pdirty") self.parent.subject.notify('pdirty')
def load_defaults(self): def load_defaults(self):
msg = ( msg = (
"Are you sure you want to Reset values to defaults?", 'Are you sure you want to Reset values to defaults?',
"Physical strips B1, Virtual strips A1", 'Physical strips B1, Virtual strips A1',
"Mono, Solo, Mute, EQ all OFF", 'Mono, Solo, Mute, EQ all OFF',
"Gain sliders for Strip/Bus at 0.0", 'Gain sliders for Strip/Bus at 0.0',
) )
resp = messagebox.askyesno(message="\n".join(msg)) resp = messagebox.askyesno(message='\n'.join(msg))
if resp: if resp:
self.load_profile("reset") self.load_profile('reset')
def always_on_top(self): def always_on_top(self):
self.parent.attributes("-topmost", self._is_topmost.get()) self.parent.attributes('-topmost', self._is_topmost.get())
def switch_orientation(self, extends_horizontal: bool = True, *args): def switch_orientation(self, extends_horizontal: bool = True, *args):
_configuration.extends_horizontal = extends_horizontal _configuration.extends_horizontal = extends_horizontal
if extends_horizontal: if extends_horizontal:
self.menu_extends.entryconfig(0, state="disabled") self.menu_extends.entryconfig(0, state='disabled')
self.menu_extends.entryconfig(1, state="normal") self.menu_extends.entryconfig(1, state='normal')
else: else:
self.menu_extends.entryconfig(1, state="disabled") self.menu_extends.entryconfig(1, state='disabled')
self.menu_extends.entryconfig(0, state="normal") self.menu_extends.entryconfig(0, state='normal')
def set_submix(self, i): def set_submix(self, i):
if _configuration.submixes != i: if _configuration.submixes != i:
@ -279,38 +280,38 @@ class Menus(tk.Menu):
self.parent.nav_frame.show_submix() self.parent.nav_frame.show_submix()
for j, var in enumerate(self._selected_bus): for j, var in enumerate(self._selected_bus):
var.set(i == j) var.set(i == j)
self.parent.subject.notify("submix") self.parent.subject.notify('submix')
def load_theme(self, theme): def load_theme(self, theme):
sv_ttk.set_theme(theme) sv_ttk.set_theme(theme)
_configuration.theme_mode = theme _configuration.theme_mode = theme
self.menu_themes.entryconfig( self.menu_themes.entryconfig(
0, 0,
state=f"{'disabled' if theme == 'light' else 'normal'}", state=f'{"disabled" if theme == "light" else "normal"}',
) )
self.menu_themes.entryconfig( self.menu_themes.entryconfig(
1, 1,
state=f"{'disabled' if theme == 'dark' else 'normal'}", state=f'{"disabled" if theme == "dark" else "normal"}',
) )
[ [
menu.config(bg=f"{'black' if theme == 'dark' else 'white'}") menu.config(bg=f'{"black" if theme == "dark" else "white"}')
for menu in self.winfo_children() for menu in self.winfo_children()
if isinstance(menu, tk.Menu) if isinstance(menu, tk.Menu)
] ]
self.menu_lock.config(bg=f"{'black' if theme == 'dark' else 'white'}") self.menu_lock.config(bg=f'{"black" if theme == "dark" else "white"}')
self.menu_configs_load.config(bg=f"{'black' if theme == 'dark' else 'white'}") self.menu_configs_load.config(bg=f'{"black" if theme == "dark" else "white"}')
[ [
menu.config(bg=f"{'black' if theme == 'dark' else 'white'}") menu.config(bg=f'{"black" if theme == "dark" else "white"}')
for menu in self.menu_vban.winfo_children() for menu in self.menu_vban.winfo_children()
if isinstance(menu, tk.Menu) if isinstance(menu, tk.Menu)
] ]
[ [
menu.config(bg=f"{'black' if theme == 'dark' else 'white'}") menu.config(bg=f'{"black" if theme == "dark" else "white"}')
for menu in self.menu_layout.winfo_children() for menu in self.menu_layout.winfo_children()
if isinstance(menu, tk.Menu) if isinstance(menu, tk.Menu)
] ]
self.logger.info( self.logger.info(
f"Finished loading theme Sunvalley {sv_ttk.get_theme().capitalize()} theme" f'Finished loading theme Sunvalley {sv_ttk.get_theme().capitalize()} theme'
) )
def menu_teardown(self, i): def menu_teardown(self, i):
@ -321,10 +322,10 @@ class Menus(tk.Menu):
try: try:
self.menu_configs_load.delete(profile) self.menu_configs_load.delete(profile)
except tk._tkinter.tclError as e: except tk._tkinter.tclError as e:
self.logger.warning(f"{type(e).__name__}: {e}") self.logger.warning(f'{type(e).__name__}: {e}')
[ [
self.menu_vban.entryconfig(j, state="disabled") self.menu_vban.entryconfig(j, state='disabled')
for j, _ in enumerate(self.menu_vban.winfo_children()) for j, _ in enumerate(self.menu_vban.winfo_children())
if j != i if j != i
] ]
@ -336,44 +337,44 @@ class Menus(tk.Menu):
self.menu_configs_load.add_command( self.menu_configs_load.add_command(
label=profile, command=partial(self.load_profile, profile) label=profile, command=partial(self.load_profile, profile)
) )
self.menu_configs.entryconfig(0, state="normal") self.menu_configs.entryconfig(0, state='normal')
else: else:
self.menu_configs.entryconfig(0, state="disabled") self.menu_configs.entryconfig(0, state='disabled')
def toggle_navigation(self, cmd=None): def toggle_navigation(self, cmd=None):
if cmd == "show": if cmd == 'show':
self.logger.debug("show navframe") self.logger.debug('show navframe')
self.parent.nav_frame.grid() self.parent.nav_frame.grid()
self._navigation_show.set(True) self._navigation_show.set(True)
self._navigation_hide.set(not self._navigation_show.get()) self._navigation_hide.set(not self._navigation_show.get())
else: else:
self.logger.debug("hide navframe") self.logger.debug('hide navframe')
self.parent.nav_frame.grid_remove() self.parent.nav_frame.grid_remove()
self._navigation_hide.set(True) self._navigation_hide.set(True)
self._navigation_show.set(not self._navigation_hide.get()) self._navigation_show.set(not self._navigation_hide.get())
def vban_connect(self, i): def vban_connect(self, i):
opts = {} opts = {}
opts |= self.vban_config[f"connection-{i+1}"] opts |= self.vban_config[f'connection-{i + 1}']
kind_id = opts.pop("kind") kind_id = opts.pop('kind')
self.vban = vban_cmd.api(kind_id, **opts) self.vban = vban_cmd.api(kind_id, **opts)
# login to vban interface # login to vban interface
try: try:
self.logger.info(f"Attempting vban connection to {opts.get('ip')}") self.logger.info(f'Attempting vban connection to {opts.get("ip")}')
self.vban.login() self.vban.login()
except VBANCMDConnectionError as e: except VBANCMDConnectionError as e:
self.vban.logout() self.vban.logout()
msg = ( msg = (
f"Timeout attempting to establish connection to {opts.get('ip')}", f'Timeout attempting to establish connection to {opts.get("ip")}',
f"Please check your connection settings", 'Please check your connection settings',
) )
messagebox.showerror("Connection Error", "\n".join(msg)) messagebox.showerror('Connection Error', '\n'.join(msg))
msg = (str(e), f"resuming local connection") msg = (str(e), 'resuming local connection')
self.logger.error(", ".join(msg)) self.logger.error(', '.join(msg))
self.after(1, self.enable_vban_menus) self.after(1, self.enable_vban_menus)
return return
self.menu_teardown(i) self.menu_teardown(i)
self.vban.event.add(["pdirty", "ldirty"]) self.vban.event.add(['pdirty', 'ldirty'])
# destroy the current App frames # destroy the current App frames
self.parent._destroy_top_level_frames() self.parent._destroy_top_level_frames()
_base_values.vban_connected = True _base_values.vban_connected = True
@ -382,17 +383,17 @@ class Menus(tk.Menu):
# build new app frames according to a kind # build new app frames according to a kind
kind = kind_get(kind_id) kind = kind_get(kind_id)
self.parent.build_app(kind, self.vban) self.parent.build_app(kind, self.vban)
target_menu = getattr(self, f"menu_vban_{i+1}") target_menu = getattr(self, f'menu_vban_{i + 1}')
target_menu.entryconfig(0, state="disabled") target_menu.entryconfig(0, state='disabled')
target_menu.entryconfig(1, state="normal") target_menu.entryconfig(1, state='normal')
self.menu_layout.entryconfig( self.menu_layout.entryconfig(
0, state=f"{'normal' if kind.name == 'potato' else 'disabled'}" 0, state=f'{"normal" if kind.name == "potato" else "disabled"}'
) )
# ensure the configs are reloaded into memory # ensure the configs are reloaded into memory
if "config" in self.parent.target.__dict__: if 'config' in self.parent.target.__dict__:
del self.parent.target.__dict__["config"] del self.parent.target.__dict__['config']
if "userconfigs" in self.parent.__dict__: if 'userconfigs' in self.parent.__dict__:
del self.parent.__dict__["userconfigs"] del self.parent.__dict__['userconfigs']
self.menu_setup() self.menu_setup()
def vban_disconnect(self, i): def vban_disconnect(self, i):
@ -407,26 +408,26 @@ class Menus(tk.Menu):
# build new app frames according to a kind # build new app frames according to a kind
kind = kind_get(self.vmr.type) kind = kind_get(self.vmr.type)
self.parent.build_app(kind) self.parent.build_app(kind)
target_menu = getattr(self, f"menu_vban_{i+1}") target_menu = getattr(self, f'menu_vban_{i + 1}')
target_menu.entryconfig(0, state="normal") target_menu.entryconfig(0, state='normal')
target_menu.entryconfig(1, state="disabled") target_menu.entryconfig(1, state='disabled')
self.menu_layout.entryconfig( self.menu_layout.entryconfig(
0, state=f"{'normal' if kind.name == 'potato' else 'disabled'}" 0, state=f'{"normal" if kind.name == "potato" else "disabled"}'
) )
# ensure the configs are reloaded into memory # ensure the configs are reloaded into memory
if "config" in self.parent.target.__dict__: if 'config' in self.parent.target.__dict__:
del self.parent.target.__dict__["config"] del self.parent.target.__dict__['config']
if "userconfigs" in self.parent.__dict__: if 'userconfigs' in self.parent.__dict__:
del self.parent.__dict__["userconfigs"] del self.parent.__dict__['userconfigs']
self.menu_setup() self.menu_setup()
self.after(15000, self.enable_vban_menus) self.after(15000, self.enable_vban_menus)
def documentation(self): def documentation(self):
webbrowser.open_new(r"https://voicemeeter.com/") webbrowser.open_new(r'https://voicemeeter.com/')
def github(self): def github(self):
webbrowser.open_new(r"https://github.com/onyx-and-iris/voicemeeter-compact") webbrowser.open_new(r'https://github.com/onyx-and-iris/voicemeeter-compact')
def onyxandiris(self): def onyxandiris(self):
webbrowser.open_new(r"https://onyxandiris.online") webbrowser.open_new(r'https://onyxandiris.online')

View File

@ -33,7 +33,7 @@ class Navigation(ttk.Frame):
if self.submix.get(): if self.submix.get():
self.parent.submix_frame = SubMixFrame(self.parent) self.parent.submix_frame = SubMixFrame(self.parent)
self.logger.info( self.logger.info(
f"Finished building submixframe for submix {_configuration.submixes}" f'Finished building submixframe for submix {_configuration.submixes}'
) )
else: else:
if _configuration.extends_horizontal: if _configuration.extends_horizontal:
@ -49,51 +49,51 @@ class Navigation(ttk.Frame):
else: else:
self.parent.rowconfigure(2, weight=0, minsize=0) self.parent.rowconfigure(2, weight=0, minsize=0)
self.logger.info( self.logger.info(
f"Finished tearing down submixframe for submix {_configuration.submixes}" f'Finished tearing down submixframe for submix {_configuration.submixes}'
) )
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"Submix.TButton", 'Submix.TButton',
background=f'{"purple" if self.submix.get() else "white"}', background=f'{"purple" if self.submix.get() else "white"}',
) )
def switch_channel(self): def switch_channel(self):
if self.channel_text.get() == "STRIP": if self.channel_text.get() == 'STRIP':
self.mainframebuilder.create_channelframe("bus") self.mainframebuilder.create_channelframe('bus')
self.parent.strip_frame.teardown() self.parent.strip_frame.teardown()
else: else:
self.mainframebuilder.create_channelframe("strip") self.mainframebuilder.create_channelframe('strip')
self.parent.bus_frame.teardown() self.parent.bus_frame.teardown()
self.extend_button["state"] = ( self.extend_button['state'] = (
"disabled" if self.channel_text.get() == "STRIP" else "normal" 'disabled' if self.channel_text.get() == 'STRIP' else 'normal'
) )
[frame.teardown() for frame in self.parent.configframes] [frame.teardown() for frame in self.parent.configframes]
self.channel_text.set("BUS" if self.channel_text.get() == "STRIP" else "STRIP") self.channel_text.set('BUS' if self.channel_text.get() == 'STRIP' else 'STRIP')
def extend_frame(self): def extend_frame(self):
_configuration.extended = self.extend.get() _configuration.extended = self.extend.get()
if self.extend.get(): if self.extend.get():
self.channel_button["state"] = "disabled" self.channel_button['state'] = 'disabled'
self.mainframebuilder.create_channelframe("bus") self.mainframebuilder.create_channelframe('bus')
else: else:
[ [
frame.teardown() frame.teardown()
for frame in self.parent.configframes for frame in self.parent.configframes
if "!busconfig" in str(frame) if '!busconfig' in str(frame)
] ]
self.parent.bus_frame.teardown() self.parent.bus_frame.teardown()
self.parent.bus_frame = None self.parent.bus_frame = None
self.channel_button["state"] = "normal" self.channel_button['state'] = 'normal'
if self.parent.submix_frame: if self.parent.submix_frame:
self.parent.submix_frame.teardown() self.parent.submix_frame.teardown()
self.submix.set(False) self.submix.set(False)
if not _configuration.themes_enabled: if not _configuration.themes_enabled:
self.styletable.configure( self.styletable.configure(
f"Submix.TButton", 'Submix.TButton',
background=f'{"purple" if self.submix.get() else "white"}', background=f'{"purple" if self.submix.get() else "white"}',
) )
self.extend_text.set("REDUCE" if self.extend.get() else "EXTEND") self.extend_text.set('REDUCE' if self.extend.get() else 'EXTEND')