From 14a43770cd37b119cde565df1100e03f9a635a50 Mon Sep 17 00:00:00 2001 From: onyx-and-iris <75868496+onyx-and-iris@users.noreply.github.com> Date: Wed, 13 Apr 2022 06:50:49 +0100 Subject: [PATCH] ldirty, pdelay, ldelay added. changes to how levels are fetched ldirty added, true iff level value has changed. fetching level arrays moved to highest level of the app. pdelay and ldelay added to _base_vals dataclass. --- vmcompact/app.py | 35 +++++++++++++++++++++- vmcompact/channels.py | 67 ++++++++++++++++++++++++++++++++---------- vmcompact/config.py | 2 +- vmcompact/data.py | 4 +++ vmcompact/gainlayer.py | 58 ++++++++++++++++++++++++++++-------- 5 files changed, 136 insertions(+), 30 deletions(-) diff --git a/vmcompact/app.py b/vmcompact/app.py index 049b690..da6829f 100644 --- a/vmcompact/app.py +++ b/vmcompact/app.py @@ -61,6 +61,11 @@ class App(tk.Tk): # start pdirty watcher self.upd_pdirty() + self.strip_levels = None + self.bus_levels = None + self._strip_levels = None + self._bus_levels = None + self.watch_levels() self.resizable(False, False) if _base_vals.themes_enabled: @@ -85,6 +90,14 @@ class App(tk.Tk): def pdirty(self, val): self._pdirty = val + @property + def ldirty(self): + return self._ldirty + + @ldirty.setter + def ldirty(self, val): + self._ldirty = val + @property def configuration(self): return configuration["app"] @@ -155,7 +168,27 @@ class App(tk.Tk): def upd_pdirty_step(self): self.pdirty = self.target.pdirty - self.after(1, self.upd_pdirty_step) + self.after(_base_vals.pdelay, self.upd_pdirty_step) + + def watch_levels(self): + self.after(1, self.watch_levels_step) + + def watch_levels_step(self): + """ + Continuously fetch level arrays, only update + if ldirty + """ + self._strip_levels = self.target.strip_levels + self._bus_levels = self.target.bus_levels + + self.ldirty = not ( + self.strip_levels == self._strip_levels + and self.bus_levels == self._bus_levels + ) + if self.ldirty: + self.strip_levels = self._strip_levels + self.bus_levels = self._bus_levels + self.after(_base_vals.ldelay, self.watch_levels_step) def dragging(self, event, *args): if event.widget is self: diff --git a/vmcompact/channels.py b/vmcompact/channels.py index 21cbe44..9692671 100644 --- a/vmcompact/channels.py +++ b/vmcompact/channels.py @@ -1,6 +1,7 @@ import tkinter as tk from tkinter import ttk from functools import partial +from math import log from .data import _base_vals from .config import StripConfig, BusConfig @@ -76,6 +77,11 @@ class Channel(ttk.LabelFrame): self.setter("gain", self.gain.get()) self._parent._parent.nav_frame.info_text.set(round(self.gain.get(), 1)) + def convert_level(self, val): + if _base_vals.vban_connected: + return round(-val * 0.01, 1) + return round(20 * log(val, 10), 1) if val > 0 else -200.0 + def _make_widgets(self): """Creates a progressbar, scale, mute button and config button for a single channel""" # Progress bar @@ -131,7 +137,7 @@ class Channel(ttk.LabelFrame): """keeps params synced but ensures sliders are responsive""" if self._parent._parent.pdirty and not _base_vals.in_scale_button_1: self.sync() - self.after(1, self.watch_pdirty_step) + self.after(_base_vals.pdelay, self.watch_pdirty_step) def sync(self): """sync params with voicemeeter""" @@ -201,14 +207,39 @@ class Strip(Channel): def watch_levels_step(self): if not _base_vals.dragging: - vals = self.target.levels.prefader - val = vals[0] if vals[0] > vals[1] else vals[0] - self.level.set(val) - self.level.set( - (0 if self.mute.get() else 100 + (val - 18) + self.gain.get()) - ) + if self._parent._parent.ldirty: + if self.index <= self._parent.phys_in: + vals = ( + self.convert_level( + self._parent._parent.strip_levels[self.index * 2] + ), + self.convert_level( + self._parent._parent.strip_levels[self.index * 2 + 1] + ), + ) + else: + vals = ( + self.convert_level( + self._parent._parent.strip_levels[ + self._parent.phys_in * 2 + + (self.index - self._parent.phys_in) * 8 + ] + ), + self.convert_level( + self._parent._parent.strip_levels[ + self._parent.phys_in * 2 + + (self.index - self._parent.phys_in) * 8 + + 1 + ] + ), + ) + peak = vals[0] if vals[0] > vals[1] else vals[0] + self.level.set( + (0 if self.mute.get() else 100 + (peak - 18) + self.gain.get()) + ) self.after( - 25 if not _base_vals.in_scale_button_1 else 100, self.watch_levels_step + _base_vals.ldelay if not _base_vals.in_scale_button_1 else 100, + self.watch_levels_step, ) @@ -251,14 +282,18 @@ class Bus(Channel): def watch_levels_step(self): if not _base_vals.dragging: - vals = self.target.levels.all - val = vals[0] if vals[0] > vals[1] else vals[0] - self.level.set(val) - self.level.set( - (0 if self.mute.get() else 100 + (val - 18) + self.gain.get()) - ) + if self._parent._parent.ldirty: + vals = ( + self.convert_level(self._parent._parent.bus_levels[self.index * 8]), + self.convert_level( + self._parent._parent.bus_levels[self.index * 8 + 1] + ), + ) + peak = vals[0] if vals[0] > vals[1] else vals[0] + self.level.set((0 if self.mute.get() else 100 + (peak - 18))) self.after( - 25 if not _base_vals.in_scale_button_1 else 100, self.watch_levels_step + _base_vals.ldelay if not _base_vals.in_scale_button_1 else 100, + self.watch_levels_step, ) @@ -364,7 +399,7 @@ class ChannelFrame(ttk.Frame): def watch_pdirty_step(self): if self._parent.pdirty: self.watch_labels() - self.after(1, self.watch_pdirty_step) + self.after(_base_vals.pdelay, self.watch_pdirty_step) def watch_labels(self): for i, labelframe in enumerate(self.labelframes): diff --git a/vmcompact/config.py b/vmcompact/config.py index 4a0cea0..0b3d4c1 100644 --- a/vmcompact/config.py +++ b/vmcompact/config.py @@ -67,7 +67,7 @@ class Config(ttk.Frame): """keeps params synced but ensures sliders are responsive""" if self._parent.pdirty and not _base_vals.in_scale_button_1: self.sync() - self.after(1, self.watch_pdirty_step) + self.after(_base_vals.pdelay, self.watch_pdirty_step) class StripConfig(Config): diff --git a/vmcompact/data.py b/vmcompact/data.py index 200ef78..a5c3c95 100644 --- a/vmcompact/data.py +++ b/vmcompact/data.py @@ -21,6 +21,10 @@ class BaseValues: using_theme: bool = False # bus assigned as current submix submixes: int = 0 + # pdirty delay + pdelay: int = 50 + # ldirty delay + ldelay: int = 50 _base_vals = BaseValues() diff --git a/vmcompact/gainlayer.py b/vmcompact/gainlayer.py index 88422e0..c6d0f44 100644 --- a/vmcompact/gainlayer.py +++ b/vmcompact/gainlayer.py @@ -1,6 +1,7 @@ import tkinter as tk from tkinter import ttk, messagebox as msg from functools import partial +from math import log from .data import _base_vals @@ -74,6 +75,11 @@ class GainLayer(ttk.LabelFrame): background=f'{"green" if self.on.get() else "white"}', ) + def convert_level(self, val): + if _base_vals.vban_connected: + return round(-val * 0.01, 1) + return round(20 * log(val, 10), 1) if val > 0 else -200.0 + def _make_widgets(self): """Creates a progressbar, scale, on button and config button for a single channel""" # Progress bar @@ -135,7 +141,7 @@ class GainLayer(ttk.LabelFrame): """keeps params synced but ensures sliders are responsive""" if self._parent._parent.pdirty and not _base_vals.in_scale_button_1: self.sync() - self.after(1, self.watch_pdirty_step) + self.after(_base_vals.pdelay, self.watch_pdirty_step) def sync(self): """sync params with voicemeeter""" @@ -156,18 +162,45 @@ class GainLayer(ttk.LabelFrame): def watch_levels_step(self): if not _base_vals.dragging: - vals = self._parent.target.strip[self.index].levels.prefader - val = vals[0] if vals[0] > vals[1] else vals[0] - self.level.set(val) - self.level.set( - ( - 0 - if self._parent._parent.channel_frame.strips[self.index].mute.get() - else 100 + (val - 18) + self.gain.get() + if self._parent._parent.ldirty: + if self.index <= self._parent.phys_in: + vals = ( + self.convert_level( + self._parent._parent.strip_levels[self.index * 2] + ), + self.convert_level( + self._parent._parent.strip_levels[self.index * 2 + 1] + ), + ) + else: + vals = ( + self.convert_level( + self._parent._parent.strip_levels[ + self._parent.phys_in * 2 + + (self.index - self._parent.phys_in) * 8 + ] + ), + self.convert_level( + self._parent._parent.strip_levels[ + self._parent.phys_in * 2 + + (self.index - self._parent.phys_in) * 8 + + 1 + ] + ), + ) + peak = vals[0] if vals[0] > vals[1] else vals[0] + self.level.set( + ( + 0 + if self._parent._parent.channel_frame.strips[ + self.index + ].mute.get() + else 100 + (peak - 18) + self.gain.get() + ) ) - ) self.after( - 25 if not _base_vals.in_scale_button_1 else 100, self.watch_levels_step + _base_vals.ldelay if not _base_vals.in_scale_button_1 else 100, + self.watch_levels_step, ) @@ -175,6 +208,7 @@ class SubMixFrame(ttk.Frame): def __init__(self, parent): super().__init__(parent) self._parent = parent + self.phys_in, self.virt_in = parent.kind.ins self.phys_out, self.virt_out = parent.kind.outs 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) @@ -232,7 +266,7 @@ class SubMixFrame(ttk.Frame): def watch_pdirty_step(self): if self._parent.pdirty: self.watch_labels() - self.after(1, self.watch_pdirty_step) + self.after(_base_vals.pdelay, self.watch_pdirty_step) def watch_labels(self): for i, gainlayer in enumerate(self.gainlayers):