mirror of
https://github.com/onyx-and-iris/nvda-voicemeeter.git
synced 2024-11-22 18:00:50 +00:00
onyx-and-iris
e2edd29b87
strip, bus params implemented (mute, mono, eq etc) bus mode buttons now rotate through all bus modes
344 lines
12 KiB
Python
344 lines
12 KiB
Python
import PySimpleGUI as psg
|
|
|
|
from .util import (
|
|
get_asio_checkbox_index,
|
|
get_asio_samples_list,
|
|
get_input_device_list,
|
|
get_insert_checkbox_index,
|
|
get_output_device_list,
|
|
get_patch_composite_list,
|
|
get_tabs_labels,
|
|
)
|
|
|
|
|
|
class Builder:
|
|
"""Responsible for building the Window layout"""
|
|
|
|
def __init__(self, window):
|
|
self.window = window
|
|
self.vm = self.window.vm
|
|
self.kind = self.vm.kind
|
|
|
|
def run(self) -> list:
|
|
menu = [[self.make_menu()]]
|
|
|
|
layout0 = []
|
|
if self.kind.name == "basic":
|
|
steps = (
|
|
self.make_tab0_row0,
|
|
self.make_tab0_row1,
|
|
)
|
|
else:
|
|
steps = (
|
|
self.make_tab0_row0,
|
|
self.make_tab0_row1,
|
|
self.make_tab0_row2,
|
|
self.make_tab0_row3,
|
|
self.make_tab0_row4,
|
|
self.make_tab0_row5,
|
|
)
|
|
for step in steps:
|
|
layout0.append([step()])
|
|
|
|
layout1 = []
|
|
steps = (self.make_tab1_rows,)
|
|
for step in steps:
|
|
layout1.append([step()])
|
|
|
|
layout2 = []
|
|
steps = (self.make_tab2_rows,)
|
|
for step in steps:
|
|
layout2.append([step()])
|
|
|
|
layout3 = []
|
|
steps = (self.make_tab3_rows,)
|
|
for step in steps:
|
|
layout3.append([step()])
|
|
|
|
layouts = [layout0, layout1, layout2, layout3]
|
|
|
|
tabs = [psg.Tab(identifier, layouts[i], key=identifier) for i, identifier in enumerate(get_tabs_labels())]
|
|
tab_group = psg.TabGroup([tabs], change_submits=True, key="tabs")
|
|
|
|
return [[menu], [tab_group]]
|
|
|
|
def make_menu(self) -> psg.Menu:
|
|
menu_def = [
|
|
[
|
|
"&Voicemeeter",
|
|
[
|
|
"Restart Audio Engine::MENU",
|
|
"Save Settings::MENU",
|
|
"Load Settings::MENU",
|
|
"Load Settings on Startup ::MENU",
|
|
],
|
|
],
|
|
]
|
|
return psg.Menu(menu_def, key="menus")
|
|
|
|
def make_tab0_row0(self) -> psg.Frame:
|
|
"""tab0 row0 represents hardware ins"""
|
|
|
|
def add_physical_device_opts(layout):
|
|
devices = get_input_device_list(self.vm)
|
|
devices.append("- remove device selection -")
|
|
layout.append(
|
|
[
|
|
psg.ButtonMenu(
|
|
f"IN {i + 1}",
|
|
size=(6, 3),
|
|
menu_def=["", devices],
|
|
key=f"HARDWARE IN||{i + 1}",
|
|
)
|
|
for i in range(self.kind.phys_in)
|
|
]
|
|
)
|
|
|
|
hardware_in = list()
|
|
[step(hardware_in) for step in (add_physical_device_opts,)]
|
|
return psg.Frame("Hardware In", hardware_in)
|
|
|
|
def make_tab0_row1(self) -> psg.Frame:
|
|
"""tab0 row1 represents hardware outs"""
|
|
|
|
def add_physical_device_opts(layout):
|
|
devices = get_output_device_list(self.vm)
|
|
devices.append("- remove device selection -")
|
|
if self.kind.name == "basic":
|
|
num_outs = self.kind.phys_out + self.kind.virt_out
|
|
else:
|
|
num_outs = self.kind.phys_out
|
|
layout.append(
|
|
[
|
|
psg.ButtonMenu(
|
|
f"A{i + 1}",
|
|
size=(6, 3),
|
|
menu_def=["", devices],
|
|
key=f"HARDWARE OUT||A{i + 1}",
|
|
)
|
|
for i in range(num_outs)
|
|
]
|
|
)
|
|
|
|
hardware_out = list()
|
|
[step(hardware_out) for step in (add_physical_device_opts,)]
|
|
return psg.Frame("Hardware Out", hardware_out)
|
|
|
|
def make_tab0_row2(self) -> psg.Frame:
|
|
"""tab0 row2 represents patch asio inputs to strips"""
|
|
|
|
def add_asio_checkboxes(layout, i):
|
|
nums = list(range(99))
|
|
layout.append(
|
|
[
|
|
psg.Spin(
|
|
nums,
|
|
initial_value=self.window.cache["asio"][f"ASIO CHECKBOX||{get_asio_checkbox_index(0, i)}"],
|
|
size=2,
|
|
enable_events=True,
|
|
key=f"ASIO CHECKBOX||IN{i} 0",
|
|
)
|
|
],
|
|
)
|
|
layout.append(
|
|
[
|
|
psg.Spin(
|
|
nums,
|
|
initial_value=self.window.cache["asio"][f"ASIO CHECKBOX||{get_asio_checkbox_index(1, i)}"],
|
|
size=2,
|
|
enable_events=True,
|
|
key=f"ASIO CHECKBOX||IN{i} 1",
|
|
)
|
|
],
|
|
)
|
|
|
|
inner = list()
|
|
asio_checkboxlists = ([] for _ in range(self.kind.phys_out))
|
|
for i, checkbox_list in enumerate(asio_checkboxlists):
|
|
[step(checkbox_list, i + 1) for step in (add_asio_checkboxes,)]
|
|
inner.append(psg.Frame(f"In#{i + 1}", checkbox_list))
|
|
|
|
asio_checkboxes = [inner]
|
|
return psg.Frame("PATCH ASIO Inputs to Strips", asio_checkboxes)
|
|
|
|
def make_tab0_row3(self) -> psg.Frame:
|
|
"""tab0 row3 represents patch composite"""
|
|
|
|
def add_physical_device_opts(layout):
|
|
outputs = get_patch_composite_list(self.vm.kind)
|
|
layout.append(
|
|
[
|
|
psg.ButtonMenu(
|
|
f"PC{i + 1}",
|
|
size=(6, 2),
|
|
menu_def=["", outputs],
|
|
key=f"PATCH COMPOSITE||PC{i + 1}",
|
|
)
|
|
for i in range(self.kind.phys_out)
|
|
]
|
|
)
|
|
|
|
hardware_out = list()
|
|
[step(hardware_out) for step in (add_physical_device_opts,)]
|
|
return psg.Frame("PATCH COMPOSITE", hardware_out)
|
|
|
|
def make_tab0_row4(self) -> psg.Frame:
|
|
"""tab0 row4 represents patch insert"""
|
|
|
|
def add_insert_checkboxes(layout, i):
|
|
if i <= self.kind.phys_in:
|
|
[
|
|
layout.append(
|
|
[
|
|
psg.Checkbox(
|
|
text=channel,
|
|
default=self.vm.patch.insert[get_insert_checkbox_index(self.kind, j, i)].on,
|
|
enable_events=True,
|
|
key=f"INSERT CHECKBOX||IN{i} {j}",
|
|
)
|
|
],
|
|
)
|
|
for j, channel in enumerate(("LEFT", "RIGHT"))
|
|
]
|
|
else:
|
|
layout.append(
|
|
[
|
|
psg.Checkbox(
|
|
text=channel,
|
|
default=self.vm.patch.insert[get_insert_checkbox_index(self.kind, j, i)].on,
|
|
enable_events=True,
|
|
key=f"INSERT CHECKBOX||IN{i} {j}",
|
|
)
|
|
for j, channel in enumerate(("LEFT", "RIGHT", "C", "LFE", "SL", "SR", "BL", "BR"))
|
|
],
|
|
)
|
|
|
|
asio_checkboxes = list()
|
|
inner = list()
|
|
checkbox_lists = ([] for _ in range(self.kind.num_strip))
|
|
for i, checkbox_list in enumerate(checkbox_lists):
|
|
if i < self.kind.phys_in:
|
|
[step(checkbox_list, i + 1) for step in (add_insert_checkboxes,)]
|
|
inner.append(psg.Frame(f"In#{i + 1}", checkbox_list))
|
|
else:
|
|
[step(checkbox_list, i + 1) for step in (add_insert_checkboxes,)]
|
|
asio_checkboxes.append([psg.Frame(f"In#{i + 1}", checkbox_list)])
|
|
asio_checkboxes.insert(0, inner)
|
|
|
|
return psg.Frame("PATCH INSERT", asio_checkboxes)
|
|
|
|
def make_tab0_row5(self) -> psg.Frame:
|
|
"""tab0 row5 represents asio buffer"""
|
|
|
|
samples = get_asio_samples_list()
|
|
samples.append("Default")
|
|
|
|
return psg.Frame(
|
|
"ASIO BUFFER",
|
|
[
|
|
[
|
|
psg.ButtonMenu(
|
|
"ASIO BUFFER",
|
|
size=(14, 2),
|
|
menu_def=["", samples],
|
|
key="ASIO BUFFER",
|
|
)
|
|
]
|
|
],
|
|
key="ASIO BUFFER FRAME",
|
|
)
|
|
|
|
def make_tab1_row(self, i) -> psg.Frame:
|
|
"""tab1 row represents a strip's outputs (A1-A5, B1-B3)"""
|
|
|
|
def add_strip_outputs(layout):
|
|
layout.append(
|
|
[
|
|
psg.Button(
|
|
f"A{j + 1}" if j < self.kind.phys_out else f"B{j - self.kind.phys_out + 1}",
|
|
size=(4, 2),
|
|
key=f"STRIP {i}||A{j + 1}"
|
|
if j < self.kind.phys_out
|
|
else f"STRIP {i}||B{j - self.kind.phys_out + 1}",
|
|
)
|
|
for j in range(self.kind.phys_out + self.kind.virt_out)
|
|
],
|
|
)
|
|
layout.append(
|
|
[
|
|
psg.Button("Mono", size=(6, 2), key=f"STRIP {i}||MONO"),
|
|
psg.Button("Solo", size=(6, 2), key=f"STRIP {i}||SOLO"),
|
|
psg.Button("Mute", size=(6, 2), key=f"STRIP {i}||MUTE"),
|
|
],
|
|
)
|
|
|
|
outputs = list()
|
|
[step(outputs) for step in (add_strip_outputs,)]
|
|
return psg.Frame(self.window.cache["labels"][f"STRIP {i}||LABEL"], outputs, key=f"STRIP {i}||LABEL")
|
|
|
|
def make_tab1_rows(self) -> psg.Frame:
|
|
layout = [[self.make_tab1_row(i)] for i in range(self.kind.phys_in)]
|
|
return psg.Frame(None, layout, border_width=0)
|
|
|
|
def make_tab2_row(self, i) -> psg.Frame:
|
|
"""tab2 row represents a strip's outputs (A1-A5, B1-B3)"""
|
|
|
|
def add_strip_outputs(layout):
|
|
layout.append(
|
|
[
|
|
psg.Button(
|
|
f"A{j + 1}" if j < self.kind.phys_out else f"B{j - self.kind.phys_out + 1}",
|
|
size=(4, 2),
|
|
key=f"STRIP {i}||A{j + 1}"
|
|
if j < self.kind.phys_out
|
|
else f"STRIP {i}||B{j - self.kind.phys_out + 1}",
|
|
)
|
|
for j in range(self.kind.phys_out + self.kind.virt_out)
|
|
]
|
|
)
|
|
if i == self.kind.phys_in + self.kind.virt_in - 2:
|
|
layout.append(
|
|
[
|
|
psg.Button("K", size=(6, 2), key=f"STRIP {i}||MONO"),
|
|
psg.Button("Solo", size=(6, 2), key=f"STRIP {i}||SOLO"),
|
|
psg.Button("Mute", size=(6, 2), key=f"STRIP {i}||MUTE"),
|
|
],
|
|
)
|
|
else:
|
|
layout.append(
|
|
[
|
|
psg.Button("MC", size=(6, 2), key=f"STRIP {i}||MONO"),
|
|
psg.Button("Solo", size=(6, 2), key=f"STRIP {i}||SOLO"),
|
|
psg.Button("Mute", size=(6, 2), key=f"STRIP {i}||MUTE"),
|
|
],
|
|
)
|
|
|
|
outputs = list()
|
|
[step(outputs) for step in (add_strip_outputs,)]
|
|
return psg.Frame(self.window.cache["labels"][f"STRIP {i}||LABEL"], outputs, key=f"STRIP {i}||LABEL")
|
|
|
|
def make_tab2_rows(self) -> psg.Frame:
|
|
layout = [[self.make_tab2_row(i)] for i in range(self.kind.phys_in, self.kind.phys_in + self.kind.virt_in)]
|
|
return psg.Frame(None, layout, border_width=0)
|
|
|
|
def make_tab3_row(self, i) -> psg.Frame:
|
|
"""tab3 row represents bus composite toggle"""
|
|
|
|
def add_strip_outputs(layout):
|
|
layout.append(
|
|
[
|
|
psg.Button("Mono", size=(6, 2), key=f"BUS {i}||MONO"),
|
|
psg.Button("EQ", size=(6, 2), key=f"BUS {i}||EQ"),
|
|
psg.Button("Mute", size=(6, 2), key=f"BUS {i}||MUTE"),
|
|
psg.Button(f"BUSMODE", size=(12, 2), key=f"BUS {i}||MODE"),
|
|
]
|
|
)
|
|
|
|
outputs = list()
|
|
[step(outputs) for step in (add_strip_outputs,)]
|
|
return psg.Frame(self.window.cache["labels"][f"BUS {i}||LABEL"], outputs, key=f"BUS {i}||LABEL")
|
|
|
|
def make_tab3_rows(self) -> psg.Frame:
|
|
layout = [[self.make_tab3_row(i)] for i in range(self.kind.num_bus)]
|
|
return psg.Frame(None, layout, border_width=0)
|