Patch BUS to A1 ASIO Outputs implemented

Patch ASIO Inputs to Strips moved to Advanced Settings
This commit is contained in:
onyx-and-iris 2023-10-26 20:12:49 +01:00
parent 6e146bac50
commit a80e4e2d83
5 changed files with 142 additions and 98 deletions

View File

@ -26,7 +26,6 @@ class Builder:
steps = ( steps = (
self.make_tab0_row0, self.make_tab0_row0,
self.make_tab0_row1, self.make_tab0_row1,
self.make_tab0_row2,
self.make_tab0_row3, self.make_tab0_row3,
self.make_tab0_row4, self.make_tab0_row4,
self.make_tab0_row5, self.make_tab0_row5,
@ -152,47 +151,6 @@ class Builder:
[step(hardware_out) for step in (add_physical_device_opts,)] [step(hardware_out) for step in (add_physical_device_opts,)]
return psg.Frame("Hardware Out", hardware_out) 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||{util.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||{util.get_asio_checkbox_index(1, i)}"
],
size=2,
enable_events=True,
key=f"ASIO CHECKBOX||IN{i} 1",
)
],
)
inner = []
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: def make_tab0_row3(self) -> psg.Frame:
"""tab0 row3 represents patch composite""" """tab0 row3 represents patch composite"""

View File

@ -79,10 +79,17 @@ def _make_label_cache(vm) -> dict:
def _make_patch_asio_cache(vm) -> dict: def _make_patch_asio_cache(vm) -> dict:
params = {}
if vm.kind.name != "basic": if vm.kind.name != "basic":
return {**{f"ASIO CHECKBOX||{i}": vm.patch.asio[i].get() for i in range(vm.kind.phys_out * 2)}} params |= {**{f"ASIO INPUT SPINBOX||{i}": vm.patch.asio[i].get() for i in range(vm.kind.phys_out * 2)}}
for i in range(vm.kind.phys_out - 1):
target = getattr(vm.patch, f"A{i + 2}")
params |= {**{f"ASIO OUTPUT A{i + 2} SPINBOX||{j}": target[j].get() for j in range(vm.kind.num_bus)}}
return params
def _make_patch_insert_cache(vm) -> dict: def _make_patch_insert_cache(vm) -> dict:
params = {}
if vm.kind.name != "basic": if vm.kind.name != "basic":
return {**{f"INSERT CHECKBOX||{i}": vm.patch.insert[i].on for i in range(vm.kind.num_strip_levels)}} params |= {**{f"INSERT CHECKBOX||{i}": vm.patch.insert[i].on for i in range(vm.kind.num_strip_levels)}}
return params

View File

@ -48,6 +48,30 @@ class Popup:
if filepath: if filepath:
return Path(filepath) return Path(filepath)
def on_pdirty(self):
if self.popup.Title == "Advanced Settings":
if self.kind.name != "basic":
for key, value in self.window.cache["asio"].items():
if "INPUT" in key:
identifier, i = key.split("||")
partial = util.get_channel_identifier_list(self.window.vm)[int(i)]
self.popup[f"{identifier}||{partial}"].update(value=value)
elif "OUTPUT" in key:
self.popup[key].update(value=value)
if self.popup.Title == "Advanced Compressor":
for param in ("RATIO", "THRESHOLD", "ATTACK", "RELEASE", "KNEE"):
self.popup[f"COMPRESSOR||SLIDER {param}"].update(
value=getattr(self.window.vm.strip[self.index].comp, param.lower())
)
self.popup["COMPRESSOR||SLIDER INPUT GAIN"].update(value=self.window.vm.strip[self.index].comp.gainin)
self.popup["COMPRESSOR||SLIDER OUTPUT GAIN"].update(value=self.window.vm.strip[self.index].comp.gainout)
elif self.popup.Title == "Advanced Gate":
for param in ("THRESHOLD", "DAMPING", "BPSIDECHAIN", "ATTACK", "HOLD", "RELEASE"):
self.popup[f"GATE||SLIDER {param}"].update(
value=getattr(self.window.vm.strip[self.index].gate, param.lower())
)
def rename(self, message, index, title=None, tab=None): def rename(self, message, index, title=None, tab=None):
if "Strip" in tab: if "Strip" in tab:
if index < self.kind.phys_in: if index < self.kind.phys_in:
@ -94,6 +118,50 @@ class Popup:
return data return data
def advanced_settings(self, title): def advanced_settings(self, title):
def add_patch_asio_input_to_strips(layout, i):
nums = list(range(99))
layout.append(
[
psg.Spin(
nums,
initial_value=self.window.cache["asio"][
f"ASIO INPUT SPINBOX||{util.get_asio_input_spinbox_index(0, i)}"
],
size=2,
enable_events=True,
key=f"ASIO INPUT SPINBOX||IN{i} 0",
)
],
)
layout.append(
[
psg.Spin(
nums,
initial_value=self.window.cache["asio"][
f"ASIO INPUT SPINBOX||{util.get_asio_input_spinbox_index(1, i)}"
],
size=2,
enable_events=True,
key=f"ASIO INPUT SPINBOX||IN{i} 1",
)
],
)
def add_patch_bus_to_asio_outputs(layout, i):
nums = list(range(99))
layout.append(
[
psg.Spin(
nums,
initial_value=self.window.cache["asio"][f"ASIO OUTPUT A{i} SPINBOX||{j}"],
size=2,
enable_events=True,
key=f"ASIO OUTPUT A{i} SPINBOX||{j}",
)
for j in range(self.kind.num_bus)
],
)
def _make_buffering_frame() -> psg.Frame: def _make_buffering_frame() -> psg.Frame:
buffer = [ buffer = [
[ [
@ -109,27 +177,79 @@ class Popup:
return psg.Frame("BUFFERING", buffer) return psg.Frame("BUFFERING", buffer)
layout = [] layout = []
if self.kind.name != "basic":
inner = []
patch_input_to_strips = ([] for _ in range(self.kind.phys_in))
for i, checkbox_list in enumerate(patch_input_to_strips):
[step(checkbox_list, i + 1) for step in (add_patch_asio_input_to_strips,)]
inner.append(psg.Frame(f"In#{i + 1}", checkbox_list))
layout.append([psg.Frame("PATCH ASIO Inputs to Strips", [inner])])
inner_2 = []
patch_output_to_bus = ([] for _ in range(self.kind.phys_out - 1))
for i, checkbox_list in enumerate(patch_output_to_bus):
[step(checkbox_list, i + 2) for step in (add_patch_bus_to_asio_outputs,)]
inner_2.append([psg.Frame(f"OutA{i + 2}", checkbox_list)])
layout.append([psg.Frame("PATCH BUS to A1 ASIO Outputs", [*inner_2])])
steps = (_make_buffering_frame,) steps = (_make_buffering_frame,)
for step in steps: for step in steps:
layout.append([step()]) layout.append([step()])
layout.append([psg.Button("Exit", size=(8, 2))]) layout.append([psg.Button("Exit", size=(8, 2))])
popup = psg.Window(title, layout, finalize=True) self.popup = psg.Window(title, layout, finalize=True)
if self.kind.name != "basic":
for i in range(self.kind.phys_out):
self.popup[f"ASIO INPUT SPINBOX||IN{i + 1} 0"].Widget.config(state="readonly")
self.popup[f"ASIO INPUT SPINBOX||IN{i + 1} 1"].Widget.config(state="readonly")
for i in range(self.kind.phys_out - 1):
for j in range(self.kind.num_bus):
self.popup[f"ASIO OUTPUT A{i + 2} SPINBOX||{j}"].Widget.config(state="readonly")
if self.kind.name != "basic":
for i in range(self.kind.phys_out):
self.popup[f"ASIO INPUT SPINBOX||IN{i + 1} 0"].bind("<FocusIn>", "||FOCUS IN")
self.popup[f"ASIO INPUT SPINBOX||IN{i + 1} 1"].bind("<FocusIn>", "||FOCUS IN")
for i in range(self.kind.phys_out - 1):
for j in range(self.kind.num_bus):
self.popup[f"ASIO OUTPUT A{i + 2} SPINBOX||{j}"].bind("<FocusIn>", "||FOCUS IN")
buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1} buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1}
for driver in ("MME", "WDM", "KS", "ASIO"): for driver in ("MME", "WDM", "KS", "ASIO"):
popup[f"BUFFER {driver}"].Widget.config(**buttonmenu_opts) self.popup[f"BUFFER {driver}"].Widget.config(**buttonmenu_opts)
popup[f"BUFFER {driver}"].bind("<FocusIn>", "||FOCUS IN") self.popup[f"BUFFER {driver}"].bind("<FocusIn>", "||FOCUS IN")
popup[f"BUFFER {driver}"].bind("<space>", "||KEY SPACE", propagate=False) self.popup[f"BUFFER {driver}"].bind("<space>", "||KEY SPACE", propagate=False)
popup[f"BUFFER {driver}"].bind("<Return>", "||KEY ENTER", propagate=False) self.popup[f"BUFFER {driver}"].bind("<Return>", "||KEY ENTER", propagate=False)
popup["Exit"].bind("<FocusIn>", "||FOCUS IN") self.popup["Exit"].bind("<FocusIn>", "||FOCUS IN")
popup["Exit"].bind("<Return>", "||KEY ENTER") self.popup["Exit"].bind("<Return>", "||KEY ENTER")
self.window.vm.observer.add(self.on_pdirty)
while True: while True:
event, values = popup.read() event, values = self.popup.read()
self.logger.debug(f"event::{event}") self.logger.debug(f"event::{event}")
self.logger.debug(f"values::{values}") self.logger.debug(f"values::{values}")
if event in (psg.WIN_CLOSED, "Exit"): if event in (psg.WIN_CLOSED, "Exit"):
break break
match parsed_cmd := self.window.parser.match.parseString(event): match parsed_cmd := self.window.parser.match.parseString(event):
case [["ASIO", "INPUT", "SPINBOX"], [in_num, channel]]:
index = util.get_asio_input_spinbox_index(int(channel), int(in_num[-1]))
val = values[f"ASIO INPUT SPINBOX||{in_num} {channel}"]
self.window.vm.patch.asio[index].set(val)
channel = ("left", "right")[int(channel)]
self.window.nvda.speak(str(val))
case [["ASIO", "INPUT", "SPINBOX"], [in_num, channel], ["FOCUS", "IN"]]:
if self.popup.find_element_with_focus() is not None:
val = values[f"ASIO INPUT SPINBOX||{in_num} {channel}"]
channel = ("left", "right")[int(channel)]
num = int(in_num[-1])
self.window.nvda.speak(f"Patch ASIO inputs to strips IN#{num} {channel} {val}")
case [["ASIO", "OUTPUT", param, "SPINBOX"], [index]]:
target = getattr(self.window.vm.patch, param)[int(index)]
target.set(values[event])
self.window.nvda.speak(str(values[event]))
case [["ASIO", "OUTPUT", param, "SPINBOX"], [index], ["FOCUS", "IN"]]:
if self.popup.find_element_with_focus() is not None:
val = values[f"ASIO OUTPUT {param} SPINBOX||{index}"]
self.window.nvda.speak(
f"Patch BUS to A1 ASIO Outputs OUT {param} channel {int(index) + 1} {val}"
)
case ["BUFFER MME" | "BUFFER WDM" | "BUFFER KS" | "BUFFER ASIO"]: case ["BUFFER MME" | "BUFFER WDM" | "BUFFER KS" | "BUFFER ASIO"]:
if values[event] == "Default": if values[event] == "Default":
if "MME" in event: if "MME" in event:
@ -149,27 +269,14 @@ class Popup:
val = int(self.window.vm.get(f"option.buffer.{driver.lower()}")) val = int(self.window.vm.get(f"option.buffer.{driver.lower()}"))
self.window.nvda.speak(f"{driver} BUFFER {val if val else 'default'}") self.window.nvda.speak(f"{driver} BUFFER {val if val else 'default'}")
case [["BUFFER", driver], ["KEY", "SPACE" | "ENTER"]]: case [["BUFFER", driver], ["KEY", "SPACE" | "ENTER"]]:
util.open_context_menu_for_buttonmenu(popup, f"BUFFER {driver}") util.open_context_menu_for_buttonmenu(self.popup, f"BUFFER {driver}")
case [[button], ["FOCUS", "IN"]]: case [[button], ["FOCUS", "IN"]]:
self.window.nvda.speak(button) self.window.nvda.speak(button)
case [_, ["KEY", "ENTER"]]: case [_, ["KEY", "ENTER"]]:
popup.find_element_with_focus().click() self.popup.find_element_with_focus().click()
self.logger.debug(f"parsed::{parsed_cmd}") self.logger.debug(f"parsed::{parsed_cmd}")
popup.close() self.window.vm.observer.remove(self.on_pdirty)
self.popup.close()
def on_pdirty(self):
if self.popup.Title == "Advanced Compressor":
for param in ("RATIO", "THRESHOLD", "ATTACK", "RELEASE", "KNEE"):
self.popup[f"COMPRESSOR||SLIDER {param}"].update(
value=getattr(self.window.vm.strip[self.index].comp, param.lower())
)
self.popup["COMPRESSOR||SLIDER INPUT GAIN"].update(value=self.window.vm.strip[self.index].comp.gainin)
self.popup["COMPRESSOR||SLIDER OUTPUT GAIN"].update(value=self.window.vm.strip[self.index].comp.gainout)
elif self.popup.Title == "Advanced Gate":
for param in ("THRESHOLD", "DAMPING", "BPSIDECHAIN", "ATTACK", "HOLD", "RELEASE"):
self.popup[f"GATE||SLIDER {param}"].update(
value=getattr(self.window.vm.strip[self.index].gate, param.lower())
)
def compressor(self, index, title=None): def compressor(self, index, title=None):
self.index = index self.index = index

View File

@ -1,7 +1,7 @@
from typing import Iterable from typing import Iterable
def get_asio_checkbox_index(channel, num) -> int: def get_asio_input_spinbox_index(channel, num) -> int:
if channel == 0: if channel == 0:
return 2 * num - 2 return 2 * num - 2
return 2 * num - 1 return 2 * num - 1

View File

@ -58,10 +58,6 @@ class NVDAVMWindow(psg.Window):
for i in range(self.kind.num_bus): for i in range(self.kind.num_bus):
self[f"BUS {i}||SLIDER GAIN"].Widget.config(**slider_opts) self[f"BUS {i}||SLIDER GAIN"].Widget.config(**slider_opts)
self[f"BUS {i}||MODE"].Widget.config(**buttonmenu_opts) self[f"BUS {i}||MODE"].Widget.config(**buttonmenu_opts)
if self.kind.name != "basic":
for i in range(self.kind.phys_out):
self[f"ASIO CHECKBOX||IN{i + 1} 0"].Widget.config(state="readonly")
self[f"ASIO CHECKBOX||IN{i + 1} 1"].Widget.config(state="readonly")
self.register_events() self.register_events()
self["tabgroup"].set_focus() self["tabgroup"].set_focus()
@ -124,10 +120,6 @@ class NVDAVMWindow(psg.Window):
for i in range(self.kind.num_bus): for i in range(self.kind.num_bus):
self[f"BUS {i}||SLIDER GAIN"].update(value=self.vm.bus[i].gain) self[f"BUS {i}||SLIDER GAIN"].update(value=self.vm.bus[i].gain)
if self.kind.name != "basic": if self.kind.name != "basic":
for key, value in self.cache["asio"].items():
identifier, i = key.split("||")
partial = util.get_channel_identifier_list(self.vm)[int(i)]
self[f"{identifier}||{partial}"].update(value=value)
for key, value in self.cache["insert"].items(): for key, value in self.cache["insert"].items():
identifier, i = key.split("||") identifier, i = key.split("||")
partial = util.get_channel_identifier_list(self.vm)[int(i)] partial = util.get_channel_identifier_list(self.vm)[int(i)]
@ -195,12 +187,6 @@ class NVDAVMWindow(psg.Window):
self["HARDWARE OUT||A2"].bind("<space>", "||KEY SPACE", propagate=False) self["HARDWARE OUT||A2"].bind("<space>", "||KEY SPACE", propagate=False)
self["HARDWARE OUT||A2"].bind("<Return>", "||KEY ENTER", propagate=False) self["HARDWARE OUT||A2"].bind("<Return>", "||KEY ENTER", propagate=False)
# Patch ASIO
if self.kind.name != "basic":
for i in range(self.kind.phys_out):
self[f"ASIO CHECKBOX||IN{i + 1} 0"].bind("<FocusIn>", "||FOCUS IN")
self[f"ASIO CHECKBOX||IN{i + 1} 1"].bind("<FocusIn>", "||FOCUS IN")
# Patch Composite # Patch Composite
if self.kind.name != "basic": if self.kind.name != "basic":
for i in range(self.kind.composite): for i in range(self.kind.composite):
@ -591,20 +577,6 @@ class NVDAVMWindow(psg.Window):
case [["HARDWARE", "OUT"], [key], ["KEY", "SPACE" | "ENTER"]]: case [["HARDWARE", "OUT"], [key], ["KEY", "SPACE" | "ENTER"]]:
util.open_context_menu_for_buttonmenu(self, f"HARDWARE OUT||{key}") util.open_context_menu_for_buttonmenu(self, f"HARDWARE OUT||{key}")
# Patch ASIO
case [["ASIO", "CHECKBOX"], [in_num, channel]]:
index = util.get_asio_checkbox_index(int(channel), int(in_num[-1]))
val = values[f"ASIO CHECKBOX||{in_num} {channel}"]
self.vm.patch.asio[index].set(val)
channel = ("left", "right")[int(channel)]
self.nvda.speak(str(val))
case [["ASIO", "CHECKBOX"], [in_num, channel], ["FOCUS", "IN"]]:
if self.find_element_with_focus() is not None:
val = values[f"ASIO CHECKBOX||{in_num} {channel}"]
channel = ("left", "right")[int(channel)]
num = int(in_num[-1])
self.nvda.speak(f"Patch ASIO inputs to strips IN#{num} {channel} {val}")
# Patch COMPOSITE # Patch COMPOSITE
case [["PATCH", "COMPOSITE"], [key]]: case [["PATCH", "COMPOSITE"], [key]]:
val = values[f"PATCH COMPOSITE||{key}"] val = values[f"PATCH COMPOSITE||{key}"]