From 14c6b937d15717e5a6b9a815e15b3413e767b8b9 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Mon, 11 Sep 2023 07:51:16 +0100 Subject: [PATCH] implements advanced settings popup gives access to driver buffer settings. may open by button or ctrl-a --- src/nvda_voicemeeter/builder.py | 20 ++--- src/nvda_voicemeeter/util.py | 36 ++++----- src/nvda_voicemeeter/window.py | 137 +++++++++++++++++++++----------- 3 files changed, 111 insertions(+), 82 deletions(-) diff --git a/src/nvda_voicemeeter/builder.py b/src/nvda_voicemeeter/builder.py index cf7549b..fcc0c13 100644 --- a/src/nvda_voicemeeter/builder.py +++ b/src/nvda_voicemeeter/builder.py @@ -228,24 +228,20 @@ class Builder: 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") + """tab0 row5 represents advanced settings""" return psg.Frame( - "ASIO BUFFER", + "ADVANCED SETTINGS", [ [ - psg.ButtonMenu( - "ASIO BUFFER", - size=(14, 2), - menu_def=["", samples], - key="ASIO BUFFER", + psg.Button( + "ADVANCED SETTINGS", + size=(20, 2), + key="ADVANCED SETTINGS", ) - ] + ], ], - key="ASIO BUFFER FRAME", + key="ADVANCED SETTINGS FRAME", ) def make_tab1_row(self, i) -> psg.Frame: diff --git a/src/nvda_voicemeeter/util.py b/src/nvda_voicemeeter/util.py index ee2e957..96e8485 100644 --- a/src/nvda_voicemeeter/util.py +++ b/src/nvda_voicemeeter/util.py @@ -47,28 +47,20 @@ def get_patch_insert_channels() -> list: _patch_insert_channels = get_patch_insert_channels() -def get_asio_samples_list() -> list: - return [ - "1024", - "768", - "704", - "640", - "576", - "512", - "480", - "448", - "441", - "416", - "384", - "352", - "320", - "288", - "256", - "224", - "192", - "160", - "128", - ] +def get_asio_samples_list(driver) -> list: + if driver == "MME": + samples = ["2048", "1536", "1024", "896", "768", "704", "640", "576", "512", "480", "441"] + else: + # fmt: off + samples = [ + "2048", "1536", "1024", "768", "704", "640", "576", "512", "480", "448", "441", "416", "384", + "352", "320", "288", "256", "224", "192", "160", "128" + ] + # fmt: on + if driver == "ASIO": + samples = [x for x in samples if x not in ("2048", "1536")] + samples.append("Default") + return samples def get_tabs_labels() -> list: diff --git a/src/nvda_voicemeeter/window.py b/src/nvda_voicemeeter/window.py index d677716..7c2b050 100644 --- a/src/nvda_voicemeeter/window.py +++ b/src/nvda_voicemeeter/window.py @@ -18,6 +18,7 @@ from .parser import Parser from .util import ( _patch_insert_channels, get_asio_checkbox_index, + get_asio_samples_list, get_bus_modes, get_channel_identifier_list, get_insert_checkbox_index, @@ -62,10 +63,7 @@ class NVDAVMWindow(psg.Window): self[f"HARDWARE OUT||A2"].Widget.config(**buttonmenu_opts) if self.kind.name != "basic": [self[f"PATCH COMPOSITE||PC{i + 1}"].Widget.config(**buttonmenu_opts) for i in range(self.kind.phys_out)] - self["ASIO BUFFER"].Widget.config(**buttonmenu_opts) - if self.kind.name != "basic": - self["ASIO BUFFER FRAME"].update(visible=False) - self["ASIO BUFFER FRAME"].hide_row() + self.register_events() def __enter__(self): @@ -128,6 +126,7 @@ class NVDAVMWindow(psg.Window): self["tabs"].bind("", "||FOCUS IN") self.bind("", "CTRL-TAB") self.bind("", "CTRL-SHIFT-TAB") + self.bind("", "CTRL-A") # Hardware In for i in range(self.vm.kind.phys_in): @@ -167,6 +166,10 @@ class NVDAVMWindow(psg.Window): else: [self[f"INSERT CHECKBOX||IN{i + 1} {j}"].bind("", "||FOCUS IN") for j in range(8)] + # Advanced Settings + if self.kind.name != "basic": + self["ADVANCED SETTINGS"].bind("", "||KEY ENTER") + # Strip Params for i in range(self.kind.num_strip): for j in range(self.kind.phys_out): @@ -193,12 +196,6 @@ class NVDAVMWindow(psg.Window): self[f"BUS {i}||{param}"].bind("", "||FOCUS IN") self[f"BUS {i}||{param}"].bind("", "||KEY ENTER") - # ASIO Buffer - if self.kind.name != "basic": - self["ASIO BUFFER"].bind("", "||FOCUS IN") - self["ASIO BUFFER"].bind("", "||KEY SPACE", propagate=False) - self["ASIO BUFFER"].bind("", "||KEY ENTER", propagate=False) - def popup_save_as(self, message, title=None, initial_folder=None): layout = [ [psg.Text(message)], @@ -219,18 +216,15 @@ class NVDAVMWindow(psg.Window): self.logger.debug(f"values::{values}") if event in (psg.WIN_CLOSED, "Cancel"): break - elif event.endswith("||FOCUS IN"): - if values["Browse"]: - filepath = values["Browse"] - break - label = event.split("||")[0] - self.TKroot.after( - 200 if label == "Edit" else 1, - self.nvda.speak, - label, - ) - elif event.endswith("||KEY ENTER"): - window.find_element_with_focus().click() + match parsed_cmd := self.parser.match.parseString(event): + case [[button], ["FOCUS", "IN"]]: + if values["Browse"]: + filepath = values["Browse"] + break + self.nvda.speak(button) + case [[button], ["KEY", "ENTER"]]: + window.find_element_with_focus().click() + self.logger.debug(f"parsed::{parsed_cmd}") window.close() if filepath: return Path(filepath) @@ -269,24 +263,79 @@ class NVDAVMWindow(psg.Window): self.logger.debug(f"values::{values}") if event in (psg.WIN_CLOSED, "Cancel"): break - elif event.endswith("||KEY ENTER"): - window.find_element_with_focus().click() - elif event == "Index": - val = values["Index"] - self.nvda.speak(f"Index {val}") - elif event.endswith("||FOCUS IN"): - if event.startswith("Index"): + match parsed_cmd := self.parser.match.parseString(event): + case ["Index"]: val = values["Index"] self.nvda.speak(f"Index {val}") - else: - self.nvda.speak(event.split("||")[0]) - elif event == "Ok": - data = values - break - + case [[button], ["FOCUS", "IN"]]: + if button == "Index": + val = values["Index"] + self.nvda.speak(f"Index {val}") + else: + self.nvda.speak(button) + case [[button], ["KEY", "ENTER"]]: + window.find_element_with_focus().click() + case ["Ok"]: + data = values + break + self.logger.debug(f"parsed::{parsed_cmd}") window.close() return data + def popup_advanced_settings(self, title): + def _make_buffering_frame() -> psg.Frame: + buffer = [ + [ + psg.ButtonMenu( + driver, + size=(14, 2), + menu_def=["", get_asio_samples_list(driver)], + key=f"BUFFER {driver}", + ) + for driver in ("MME", "WDM", "KS", "ASIO") + ], + ] + return psg.Frame("BUFFERING", buffer) + + buffer_frame = _make_buffering_frame() + layout = [[buffer_frame], [psg.Button("Exit")]] + + window = psg.Window(title, layout, finalize=True) + buttonmenu_opts = {"takefocus": 1, "highlightthickness": 1} + for driver in ("MME", "WDM", "KS", "ASIO"): + window[f"BUFFER {driver}"].Widget.config(**buttonmenu_opts) + window[f"BUFFER {driver}"].bind("", "||FOCUS IN") + window[f"BUFFER {driver}"].bind("", "||KEY SPACE", propagate=False) + window[f"BUFFER {driver}"].bind("", "||KEY ENTER", propagate=False) + window["Exit"].bind("", "||FOCUS IN") + window["Exit"].bind("", "||KEY ENTER") + while True: + event, values = window.read() + self.logger.debug(f"event::{event}") + self.logger.debug(f"values::{values}") + if event in (psg.WIN_CLOSED, "Exit"): + break + match parsed_cmd := self.parser.match.parseString(event): + case ["BUFFER MME" | "BUFFER WDM" | "BUFFER KS" | "BUFFER ASIO"]: + if values[event] == "Default": + val = 0 + else: + val = int(values[event]) + driver = event.split()[1] + self.vm.set(f"option.buffer.{driver.lower()}", val) + self.TKroot.after(200, self.nvda.speak, f"{driver} BUFFER {val if val else 'default'}") + case [["BUFFER", driver], ["FOCUS", "IN"]]: + val = int(self.vm.get(f"option.buffer.{driver.lower()}")) + self.nvda.speak(f"{driver} BUFFER {val if val else 'default'}") + case [["BUFFER", driver], ["KEY", "SPACE" | "ENTER"]]: + open_context_menu_for_buttonmenu(window, f"BUFFER {driver}") + case [[button], ["FOCUS", "IN"]]: + self.nvda.speak(button) + case [[button], ["KEY", "ENTER"]]: + window.find_element_with_focus().click() + self.logger.debug(f"parsed::{parsed_cmd}") + window.close() + def run(self): """ Parses the event string and matches it to events @@ -495,19 +544,11 @@ class NVDAVMWindow(psg.Window): num = int(in_num[-1]) self.nvda.speak(f"Patch INSERT IN#{num} {channel} {'on' if val else 'off'}") - # ASIO Buffer - case ["ASIO BUFFER"]: - if values[event] == "Default": - val = 0 - else: - val = values[event] - self.vm.option.buffer("asio", val) - self.TKroot.after(200, self.nvda.speak, f"ASIO BUFFER {val if val else 'default'}") - case [["ASIO", "BUFFER"], ["FOCUS", "IN"]]: - val = int(self.vm.get("option.buffer.asio")) - self.nvda.speak(f"ASIO BUFFER {val if val else 'default'}") - case [["ASIO", "BUFFER"], ["KEY", "SPACE" | "ENTER"]]: - open_context_menu_for_buttonmenu(self, "ASIO BUFFER") + # Advanced Settings + case ["ADVANCED SETTINGS"] | ["CTRL-A"]: + self.popup_advanced_settings(title="Advanced Settings") + case [["ADVANCED", "SETTINGS"], ["KEY", "ENTER"]]: + self.find_element_with_focus().click() # Strip Params case [["STRIP", index], [param]]: