Compare commits

...

3 Commits

Author SHA1 Message Date
c2db0f2757 dependencies updated.
patch bump
2023-08-06 23:16:20 +01:00
bfb0482c32 on_close_window() callback added.
cleanly shuts down vban connection on windows close
if vban connected.
2023-08-06 23:15:54 +01:00
6222ab1e62 id renamed to identifier in _make_channelframe()
label_cache arrays now initialised with empty strings

update_levels() now called when initialising ChannelFrame
2023-08-06 23:15:08 +01:00
5 changed files with 60 additions and 46 deletions

20
poetry.lock generated
View File

@ -115,13 +115,13 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-
[[package]] [[package]]
name = "sv-ttk" name = "sv-ttk"
version = "2.5.3" version = "2.5.5"
description = "A gorgeous theme for Tkinter, based on Windows 11's UI" description = "A gorgeous theme for Tkinter, based on Windows 11's UI"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "sv_ttk-2.5.3-py3-none-any.whl", hash = "sha256:d13bf6a7b49316431eefcf83f30d0daf312c00553c4e0b6f91acffd7b2aaa1d3"}, {file = "sv_ttk-2.5.5-py3-none-any.whl", hash = "sha256:49d1cd03c032728c183d1fe2318f88cdb658ef3e87157e1ca3fcf6661054965b"},
{file = "sv_ttk-2.5.3.tar.gz", hash = "sha256:d9b9a5d14f4cbdd4e0bda2e1a84445b0aa852b99f74aafce9386459e385717b3"}, {file = "sv_ttk-2.5.5.tar.gz", hash = "sha256:9bbfe2aba6cc6f9fdf70d79331046543c9666fcccc78bad5ff648a9987e3cedb"},
] ]
[[package]] [[package]]
@ -137,13 +137,13 @@ files = [
[[package]] [[package]]
name = "vban-cmd" name = "vban-cmd"
version = "2.3.2" version = "2.4.4"
description = "Python interface for the VBAN RT Packet Service (Sendtext)" description = "Python interface for the VBAN RT Packet Service (Sendtext)"
optional = false optional = false
python-versions = ">=3.10,<4.0" python-versions = ">=3.10,<4.0"
files = [ files = [
{file = "vban_cmd-2.3.2-py3-none-any.whl", hash = "sha256:28168a7ec1c6966fd4bcbaed3144219f8cdc2490f15dd8ecba2aa19f2a3461f5"}, {file = "vban_cmd-2.4.4-py3-none-any.whl", hash = "sha256:f439219a2dc6a45123bb70fc94d2aabfc643f26dffc9206da2228e2520f83e01"},
{file = "vban_cmd-2.3.2.tar.gz", hash = "sha256:c33e338e3207f35a6b9f9026d29cf68af9e5f6d7c96aea4b581225f4befd844e"}, {file = "vban_cmd-2.4.4.tar.gz", hash = "sha256:31dbf6abb681d57772c9082722b024d0798eff99b4c622bfbb539179852a935d"},
] ]
[package.dependencies] [package.dependencies]
@ -151,13 +151,13 @@ tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""}
[[package]] [[package]]
name = "voicemeeter-api" name = "voicemeeter-api"
version = "2.3.2" version = "2.4.4"
description = "A Python wrapper for the Voiceemeter API" description = "A Python wrapper for the Voiceemeter API"
optional = false optional = false
python-versions = ">=3.10,<4.0" python-versions = ">=3.10,<4.0"
files = [ files = [
{file = "voicemeeter_api-2.3.2-py3-none-any.whl", hash = "sha256:081bd6b3e27d8757e4c5ed239b4c58f9bcb4f4d16ebc9c88229e9390dac184c8"}, {file = "voicemeeter_api-2.4.4-py3-none-any.whl", hash = "sha256:2e2f0b475de7cfc0d1c397838498162f0b405ab82a6f6ca0095434b43385b43e"},
{file = "voicemeeter_api-2.3.2.tar.gz", hash = "sha256:aa700600b5910e4bb55df20cdf028aae2a44cc14bfd80dd0fe060aa03bbf7e02"}, {file = "voicemeeter_api-2.4.4.tar.gz", hash = "sha256:a4f8ecaa7f5d6b9e9a8545dcf047754711af9a120628b3a98821466c7d65c1e7"},
] ]
[package.dependencies] [package.dependencies]
@ -166,4 +166,4 @@ tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""}
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.10" python-versions = "^3.10"
content-hash = "770291c3645dd9bfd28051c0deb13bf5ae17a510bfc2785b51be1bc5c7266b1a" content-hash = "cde74de8c9de0895555068efea354edf6b51f2332c253f02f6c8f26fe6b4e795"

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "voicemeeter-compact" name = "voicemeeter-compact"
version = "1.9.1" version = "1.9.2"
description = "A Compact Voicemeeter Remote App" description = "A Compact Voicemeeter Remote App"
authors = ["onyx-and-iris <code@onyxandiris.online>"] authors = ["onyx-and-iris <code@onyxandiris.online>"]
license = "MIT" license = "MIT"
@ -12,10 +12,10 @@ include = ["vmcompact/img/cat.ico"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.10" python = "^3.10"
sv-ttk = "^2.5.1" sv-ttk = "^2.5.5"
tomli = { version = "^2.0.1", python = "<3.11" } tomli = { version = "^2.0.1", python = "<3.11" }
voicemeeter-api = "^2.3.2" voicemeeter-api = "^2.4.4"
vban-cmd = "^2.3.2" vban-cmd = "^2.4.4"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
black = { version = "^22.6.0", allow-prereleases = true } black = { version = "^22.6.0", allow-prereleases = true }

View File

@ -50,6 +50,7 @@ class App(tk.Tk):
self.minsize(275, False) self.minsize(275, False)
self.subject = Subject() self.subject = Subject()
self._configs = None self._configs = None
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:
@ -182,6 +183,11 @@ class App(tk.Tk):
self.destroy() self.destroy()
self.after(250, self.healthcheck_step) self.after(250, self.healthcheck_step)
def on_close_window(self):
if _base_values.vban_connected:
self._vban.logout()
self.destroy()
_apps = {kind.name: App.make(kind) for kind in _kinds_all} _apps = {kind.name: App.make(kind) for kind in _kinds_all}

View File

@ -151,17 +151,18 @@ class ChannelLabelFrame(ttk.LabelFrame):
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")
self.parent.label_cache[self.id].insert(self.index, retval) if self.parent.label_cache[self.id][self.index] != retval:
if len(retval) > 10: self.parent.label_cache[self.id][self.index] = retval
retval = f"{retval[:8]}.." if len(retval) > 10:
if not retval: retval = f"{retval[:8]}.."
self.parent.columnconfigure(self.index, minsize=0) if not retval:
self.parent.parent.subject.remove(self) self.parent.columnconfigure(self.index, minsize=0)
self.grid_remove() self.parent.parent.subject.remove(self)
else: self.grid_remove()
self.parent.parent.subject.add(self) else:
self.grid() self.parent.parent.subject.add(self)
self.configure(text=retval) self.grid()
self.configure(text=retval)
def grid_configure(self): def grid_configure(self):
self.grid(padx=_configuration.channel_xpadding, sticky=(tk.N, tk.S)) self.grid(padx=_configuration.channel_xpadding, sticky=(tk.N, tk.S))
@ -228,15 +229,18 @@ class Bus(ChannelLabelFrame):
class ChannelFrame(ttk.Frame): class ChannelFrame(ttk.Frame):
label_cache = {"strip": list(), "bus": list()}
def init(self, parent, id): def init(self, parent, id):
super().__init__(parent) super().__init__(parent)
self.parent = parent self.parent = parent
self.id = id self.id = id
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 = {
"strip": [""] * (self.phys_in + self.virt_in),
"bus": [""] * (self.phys_out + self.virt_out),
}
self.parent.subject.add(self) self.parent.subject.add(self)
self.update_labels()
@property @property
def target(self): def target(self):
@ -258,13 +262,13 @@ class ChannelFrame(ttk.Frame):
if isinstance(frame, ttk.LabelFrame) if isinstance(frame, ttk.LabelFrame)
) )
def update_labels(self):
for labelframe in self.labelframes:
labelframe.on_update("labelframe")
def on_update(self, subject): def on_update(self, subject):
if subject == "pdirty": if subject == "pdirty":
target = getattr(self.target, self.id) self.update_labels()
num = getattr(self.parent.kind, f"num_{self.id}")
if self.label_cache[self.id] != [target[i].label for i in range(num)]:
for labelframe in self.labelframes:
labelframe.on_update("labelframe")
def grid_configure(self): def grid_configure(self):
[ [
@ -280,7 +284,7 @@ class ChannelFrame(ttk.Frame):
setattr(self.parent, f"{self.identifier}_frame", None) setattr(self.parent, f"{self.identifier}_frame", None)
def _make_channelframe(parent, id): def _make_channelframe(parent, identifier):
""" """
Creates a Channel Frame class of type strip or bus Creates a Channel Frame class of type strip or bus
""" """
@ -288,29 +292,33 @@ def _make_channelframe(parent, id):
phys_in, virt_in = parent.kind.ins phys_in, virt_in = parent.kind.ins
phys_out, virt_out = parent.kind.outs phys_out, virt_out = parent.kind.outs
def init_labels(self, id): def init_labels(self):
""" """
Grids each labelframe, grid_removes any without a label Grids each labelframe, grid_removes any without a label
""" """
for i, labelframe in enumerate( for i, labelframe in enumerate(
getattr(self, "strips" if id == "strip" else "buses") getattr(self, "strips" if identifier == "strip" else "buses")
): ):
labelframe.grid(row=0, column=i) labelframe.grid(row=0, column=i)
if not labelframe.target.label: label = labelframe.target.label
if not label:
self.columnconfigure(i, minsize=0) self.columnconfigure(i, minsize=0)
labelframe.grid_remove() labelframe.grid_remove()
self.label_cache[identifier][i] = label
def init_strip(self, *args, **kwargs): def init_strip(self, *args, **kwargs):
self.init(parent, id) self.init(parent, identifier)
self.strips = tuple(Strip(self, i, id) for i in range(phys_in + virt_in)) self.strips = tuple(
Strip(self, i, identifier) for i in range(phys_in + virt_in)
)
self.grid(row=0, column=0, sticky=(tk.W)) self.grid(row=0, column=0, sticky=(tk.W))
self.grid_configure() self.grid_configure()
init_labels(self, id) init_labels(self)
def init_bus(self, *args, **kwargs): def init_bus(self, *args, **kwargs):
self.init(parent, id) self.init(parent, identifier)
self.buses = tuple(Bus(self, i, id) for i in range(phys_out + virt_out)) self.buses = tuple(Bus(self, i, identifier) for i in range(phys_out + virt_out))
if _configuration.extended: if _configuration.extended:
if _configuration.extends_horizontal: if _configuration.extends_horizontal:
self.grid(row=0, column=2, sticky=(tk.W)) self.grid(row=0, column=2, sticky=(tk.W))
@ -319,11 +327,11 @@ def _make_channelframe(parent, id):
else: else:
self.grid(row=0, column=0) self.grid(row=0, column=0)
self.grid_configure() self.grid_configure()
init_labels(self, id) init_labels(self)
if id == "strip": if identifier == "strip":
CHANNELFRAME_cls = type( CHANNELFRAME_cls = type(
f"ChannelFrame{id.capitalize()}", f"ChannelFrame{identifier.capitalize()}",
(ChannelFrame,), (ChannelFrame,),
{ {
"__init__": init_strip, "__init__": init_strip,
@ -331,7 +339,7 @@ def _make_channelframe(parent, id):
) )
else: else:
CHANNELFRAME_cls = type( CHANNELFRAME_cls = type(
f"ChannelFrame{id.capitalize()}", f"ChannelFrame{identifier.capitalize()}",
(ChannelFrame,), (ChannelFrame,),
{ {
"__init__": init_bus, "__init__": init_bus,

View File

@ -227,7 +227,7 @@ class Menus(tk.Menu):
if fn := getattr(self.target.command, cmd): if fn := getattr(self.target.command, cmd):
fn() fn()
if cmd == "shutdown": if cmd == "shutdown":
self.parent.destroy() 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":