diff --git a/poetry.lock b/poetry.lock index 91371dd..5d7f6e0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.3.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. [[package]] name = "altgraph" @@ -223,7 +223,7 @@ files = [ [[package]] name = "vban-cmd" -version = "2.5.2" +version = "2.10.1" description = "Python interface for the VBAN RT Packet Service (Sendtext)" optional = false python-versions = ">=3.10" @@ -240,7 +240,7 @@ url = "../vban-cmd-python" [[package]] name = "voicemeeter-api" -version = "2.7.1" +version = "2.7.2" description = "A Python wrapper for the Voiceemeter API" optional = false python-versions = ">=3.10" @@ -258,4 +258,4 @@ url = "../voicemeeter-api-python" [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.14" -content-hash = "d457ab1aaa0beaad130dc9a2a04e5e1f8c1b29ed1d0e7d43183e2648fd9ed47c" +content-hash = "171da15ce55f47b4e651aade40ab21afd5ef589ff7ff26e51caf6840d25b98a1" diff --git a/pyproject.toml b/pyproject.toml index 2113759..aa382ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,8 +7,8 @@ license = { text = "MIT" } readme = "README.md" requires-python = ">=3.10,<3.14" dependencies = [ - "voicemeeter-api (>=2.6.1,<3.0.0)", - "vban-cmd (>=2.5.0,<3.0.0)", + "voicemeeter-api (>=2.7.2,<3.0.0)", + "vban-cmd (>=2.10.1,<3.0.0)", "sv-ttk (>=2.6.0,<3.0.0)", "tomli (>=2.0.1,<3.0) ; python_version < '3.11'", ] diff --git a/vmcompact/builders.py b/vmcompact/builders.py index 19db6f5..f168763 100644 --- a/vmcompact/builders.py +++ b/vmcompact/builders.py @@ -227,7 +227,7 @@ class ChannelLabelFrameBuilder(AbstractBuilder): """Adds a progress bar widget to a single label frame""" self.labelframe.pb = ttk.Progressbar( self.labelframe, - maximum=72, + maximum=72, # Range: 0 = -60dB, 72 = +12dB (72dB total range) orient='vertical', mode='determinate', variable=self.labelframe.level, @@ -362,15 +362,15 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder): tk.BooleanVar() for _ in self.configframe.virt_out_params ] - self.configframe.params = ('mono', 'solo') - self.configframe.param_vars = list( - tk.BooleanVar() for _ in self.configframe.params + self.configframe.bool_params = ('mono', 'solo') + self.configframe.bool_param_vars = list( + tk.BooleanVar() for _ in self.configframe.bool_params ) if self.configframe.parent.kind.name in ('banana', 'potato'): if self.configframe.index == self.configframe.phys_in: self.configframe.params = list( - map(lambda x: x.replace('mono', 'mc'), self.configframe.params) + map(lambda x: x.replace('mono', 'mc'), self.configframe.bool_params) ) if self.configframe.parent.kind.name == 'banana': pass @@ -388,7 +388,10 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder): == self.configframe.phys_in + self.configframe.virt_in - 1 ): self.configframe.params = list( - map(lambda x: x.replace('mono', 'mc'), self.configframe.params) + map( + lambda x: x.replace('mono', 'mc'), + self.configframe.bool_params, + ) ) def create_comp_slider(self): @@ -542,9 +545,9 @@ class StripConfigFrameBuilder(ChannelConfigFrameBuilder): self.configframe.pause_updates, self.configframe.toggle_p, param ), style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}', - variable=self.configframe.param_vars[i], + variable=self.configframe.bool_param_vars[i], ) - for i, param in enumerate(self.configframe.params) + for i, param in enumerate(self.configframe.bool_params) ] [ button.grid( @@ -574,10 +577,22 @@ class BusConfigFrameBuilder(ChannelConfigFrameBuilder): "lfeonly": "LFE Only", "rearonly": "Rear Only", } + self.configframe.bus_mode_map_reverse = {v: k for k, v in self.configframe.bus_mode_map.items()} self.configframe.bus_modes = list(self.configframe.bus_mode_map.keys()) # fmt: on - self.configframe.params = ('mono', 'eq.on', 'eq.ab') - self.configframe.param_vars = [tk.BooleanVar() for _ in self.configframe.params] + self.configframe.int_params = ('mono',) + self.configframe.int_param_vars = [ + tk.IntVar(value=getattr(self.configframe.target, param)) + for param in self.configframe.int_params + ] + self.configframe.mono_modes = ['mono: off', 'mono: on', 'stereo reverse'] + self.configframe.bus_mono_label_text = tk.StringVar( + value=self.configframe.mono_modes[self.configframe.target.mono] + ) + self.configframe.bool_params = ('eq.on', 'eq.ab') + self.configframe.bool_param_vars = [ + tk.BooleanVar() for _ in self.configframe.bool_params + ] self.configframe.bus_mode_label_text = tk.StringVar( value=self.configframe.bus_mode_map[self.configframe.current_bus_mode()] ) @@ -602,6 +617,20 @@ class BusConfigFrameBuilder(ChannelConfigFrameBuilder): ), ) + def create_bus_mono_button(self): + self.configframe.mono_button = ttk.Button( + self.configframe, textvariable=self.configframe.bus_mono_label_text + ) + self.configframe.mono_button.bind( + '', + partial(self.configframe.pause_updates, self.configframe.rotate_mono_right), + ) + self.configframe.mono_button.bind( + '', + partial(self.configframe.pause_updates, self.configframe.rotate_mono_left), + ) + self.configframe.mono_button.grid(column=0, row=1, sticky=(tk.W)) + def create_param_buttons(self): param_buttons = [ ttk.Checkbutton( @@ -611,13 +640,13 @@ class BusConfigFrameBuilder(ChannelConfigFrameBuilder): self.configframe.pause_updates, self.configframe.toggle_p, param ), style=f'{"Toggle.TButton" if _configuration.themes_enabled else f"{param}.TButton"}', - variable=self.configframe.param_vars[i], + variable=self.configframe.bool_param_vars[i], ) - for i, param in enumerate(self.configframe.params) + for i, param in enumerate(self.configframe.bool_params) ] [ button.grid( - column=i, + column=i + 1, row=1, ) for i, button in enumerate(param_buttons) diff --git a/vmcompact/channels.py b/vmcompact/channels.py index 03bc641..c064c9a 100644 --- a/vmcompact/channels.py +++ b/vmcompact/channels.py @@ -197,14 +197,22 @@ class Strip(ChannelLabelFrame): def upd_levels(self): """ - Updates level values. + Updates level values using direct dB values. """ if self.index < self.parent.parent.kind.num_strip: if self.target.levels.is_updated: val = max(self.target.levels.prefader) - self.level.set( - (0 if self.mute.get() else 72 + val - 12 + self.gain.get()) - ) + if val < -72: + if self.level.get() != 0: + self.level.set(0) + return + # Convert dB to progressbar: -60dB=0, 0dB=60, +12dB=72 + if self.mute.get(): + level_display = 0 + else: + level_db = val + self.gain.get() + level_display = max(0, min(72, level_db + 60)) + self.level.set(level_display) class Bus(ChannelLabelFrame): @@ -223,9 +231,18 @@ class Bus(ChannelLabelFrame): def upd_levels(self): if self.index < self.parent.parent.kind.num_bus: - if self.target.levels.is_updated or self.level.get() != -118: + if self.target.levels.is_updated: val = max(self.target.levels.all) - self.level.set((0 if self.mute.get() else 72 + val - 12)) + if val < -72: + if self.level.get() != 0: + self.level.set(0) + return + # Convert dB to progressbar: -60dB=0, 0dB=60, +12dB=72 + if self.mute.get(): + level_display = 0 + else: + level_display = max(0, min(72, val + 60)) + self.level.set(level_display) class ChannelFrame(ttk.Frame): diff --git a/vmcompact/config.py b/vmcompact/config.py index d9fe5f5..2f9839b 100644 --- a/vmcompact/config.py +++ b/vmcompact/config.py @@ -98,7 +98,7 @@ class Config(ttk.Frame): self.slider_vars[self.slider_params.index(param)].set(val) def toggle_p(self, param): - val = self.param_vars[self.params.index(param)].get() + val = self.bool_param_vars[self.bool_params.index(param)].get() self.setter(param, val) if not _configuration.themes_enabled: self.styletable.configure( @@ -177,15 +177,14 @@ class StripConfig(Config): for i, param in enumerate(self.virt_out_params) ] [ - self.param_vars[i].set(self.getter(param)) - for i, param in enumerate(self.params) + self.bool_param_vars[i].set(self.getter(param)) + for i, param in enumerate(self.bool_params) + ] + [ + self.slider_vars[i].set(self.getter(param)) + for i, param in enumerate(self.slider_params) + if self.index < self.phys_in ] - if not _base_values.vban_connected: # slider vars not defined in RT Packet - [ - self.slider_vars[i].set(self.getter(param)) - for i, param in enumerate(self.slider_params) - if self.index < self.phys_in - ] if not _configuration.themes_enabled: [ @@ -207,7 +206,7 @@ class StripConfig(Config): f'{param}.TButton', background=f'{"green" if self.param_vars[i].get() else "white"}', ) - for i, param in enumerate(self.params) + for i, param in enumerate(self.bool_params) ] @@ -238,53 +237,56 @@ class BusConfig(Config): self.builder.create_bus_mode_button() def make_row_1(self): + self.builder.create_bus_mono_button() self.builder.create_param_buttons() def current_bus_mode(self): return self.target.mode.get() def rotate_bus_modes_right(self, *args): - current_mode = self.current_bus_mode() - next = self.bus_modes.index(current_mode) + 1 - if next < len(self.bus_modes): - setattr( - self.target.mode, - self.bus_modes[next], - True, - ) - self.bus_mode_label_text.set(self.bus_mode_map[self.bus_modes[next]]) - else: - self.target.mode.normal = True - self.bus_mode_label_text.set('Normal') + current_mode = self.bus_mode_map_reverse[self.bus_mode_label_text.get()] + current_index = self.bus_modes.index(current_mode) + next_index = (current_index + 1) % len(self.bus_modes) + next_mode = self.bus_modes[next_index] + + setattr(self.target.mode, next_mode, True) + self.bus_mode_label_text.set(self.bus_mode_map[next_mode]) def rotate_bus_modes_left(self, *args): - current_mode = self.current_bus_mode() - prev = self.bus_modes.index(current_mode) - 1 - if prev < 0: - self.target.mode.rearonly = True - self.bus_mode_label_text.set('Rear Only') - else: - setattr( - self.target.mode, - self.bus_modes[prev], - True, - ) - self.bus_mode_label_text.set(self.bus_mode_map[self.bus_modes[prev]]) + current_mode = self.bus_mode_map_reverse[self.bus_mode_label_text.get()] + current_index = self.bus_modes.index(current_mode) + prev_index = (current_index - 1) % len(self.bus_modes) + prev_mode = self.bus_modes[prev_index] + + setattr(self.target.mode, prev_mode, True) + self.bus_mode_label_text.set(self.bus_mode_map[prev_mode]) + + def rotate_mono_right(self, *args): + current_val = self.mono_modes.index(self.bus_mono_label_text.get()) + next_val = (current_val + 1) % 3 + self.bus_mono_label_text.set(self.mono_modes[next_val]) + self.setter('mono', next_val) + + def rotate_mono_left(self, *args): + current_val = self.mono_modes.index(self.bus_mono_label_text.get()) + next_val = (current_val - 1) % 3 + self.bus_mono_label_text.set(self.mono_modes[next_val]) + self.setter('mono', next_val) def teardown(self): self.builder.teardown() def sync(self): [ - self.param_vars[i].set(self.getter(param)) - for i, param in enumerate(self.params) + self.bool_param_vars[i].set(self.getter(param)) + for i, param in enumerate(self.bool_params) ] self.bus_mode_label_text.set(self.bus_mode_map[self.current_bus_mode()]) if not _configuration.themes_enabled: [ self.styletable.configure( f'{param}.TButton', - background=f'{"green" if self.param_vars[i].get() else "white"}', + background=f'{"green" if self.bool_param_vars[i].get() else "white"}', ) - for i, param in enumerate(self.params) + for i, param in enumerate(self.bool_params) ] diff --git a/vmcompact/gainlayer.py b/vmcompact/gainlayer.py index ff9feba..7b551a3 100644 --- a/vmcompact/gainlayer.py +++ b/vmcompact/gainlayer.py @@ -161,17 +161,18 @@ class GainLayer(ttk.LabelFrame): """ Updates level values. """ - if self.parent.target.strip[self.index].levels.is_updated: val = max(self.parent.target.strip[self.index].levels.prefader) - self.level.set( - ( - 0 - if self.parent.parent.strip_frame.strips[self.index].mute.get() - or not self.on.get() - else 72 + val - 12 + self.gain.get() - ) - ) + # Convert dB to progressbar: -60dB=0, 0dB=60, +12dB=72 + if ( + self.parent.parent.strip_frame.strips[self.index].mute.get() + or not self.on.get() + ): + level_display = 0 + else: + level_db = val + self.gain.get() + level_display = max(0, min(72, level_db + 60)) + self.level.set(level_display) def grid_configure(self): self.grid(padx=_configuration.channel_xpadding, sticky=(tk.N, tk.S)) diff --git a/vmcompact/menu.py b/vmcompact/menu.py index 0c7edac..85833af 100644 --- a/vmcompact/menu.py +++ b/vmcompact/menu.py @@ -421,7 +421,7 @@ class Menus(tk.Menu): del self.parent.__dict__['userconfigs'] self.menu_setup() - self.after(500, self.enable_vban_menus) + self.after(50, self.enable_vban_menus) def documentation(self): webbrowser.open_new(r'https://voicemeeter.com/')