From 1d9a856359cb4dbfeb3a45d7be35afed6c58d030 Mon Sep 17 00:00:00 2001 From: Mel Date: Mon, 9 Feb 2026 18:22:53 +0100 Subject: [PATCH] removed VTS hotkey feature and added a 60Hz poller for sliders and knobs to set volumes more real time --- src/midimixer/midimixer.py | 99 +++++++++++++++----------------------- 1 file changed, 40 insertions(+), 59 deletions(-) diff --git a/src/midimixer/midimixer.py b/src/midimixer/midimixer.py index b6e7abc..8596cc3 100755 --- a/src/midimixer/midimixer.py +++ b/src/midimixer/midimixer.py @@ -3,6 +3,7 @@ import json import mido import subprocess +import time nanoKontrol2_mapping: dict[int, str] = { 0: "Slider_1", @@ -66,7 +67,7 @@ audiomixer_mapping = { "Slider_2": "mic2.input", "Solo_2": "mic2.input", "Mute_2": "mic2.input", - # "Record_2": "mic2.input", + "Record_2": "mic2.input", "Slider_3": "system.input", "Solo_3": "system.input", "Mute_3": "system.input", @@ -79,14 +80,14 @@ audiomixer_mapping = { "Solo_5": "music.input", "Mute_5": "music.input", "Record_5": "obs_music.input", - "Slider_6": "obs.input", - "Solo_6": "obs.input", - "Mute_6": "obs.input", - # "Record_6": "obs.input", - "Slider_7": "music.input", - "Solo_7": "music.input", - "Mute_7": "music.input", - # "Record_7": "music.input", + "Slider_6": "obs_monitor.input", + "Solo_6": "obs_monitor.input", + "Mute_6": "", + "Record_6": "obs_monitor.input", + "Slider_7": "", + "Solo_7": "", + "Mute_7": "", + "Record_7": "", "Slider_8": "browser.input", "Solo_8": "browser.input", "Mute_8": "browser.input", @@ -104,12 +105,12 @@ audiomixer_mapping = { "Play": "XF86AudioPlay", "Stop": "XF86AudioStop", "Record": "alsa_output.pci-0000_7d_00.6.analog-stereo", - "Marker_set": "vts ctrl+v+2", - "Marker_prev": "vts ctrl+v+3", - "Marker_next": "vts ctrl+v+4", - "Track_prev": "vts ctrl+v+5", - "Track_next": "vts ctrl+v+6", - "Cycle": "vts ctrl+v+0", + "Marker_set": "", + "Marker_prev": "", + "Marker_next": "", + "Track_prev": "", + "Track_next": "", + "Cycle": "", } @@ -178,13 +179,14 @@ def find_id(device: str) -> str: return device_id -def set_mute(toggle: bool, device: str) -> None: +def set_mute(mute: bool, device: str) -> None: device_id = find_id(device) - if toggle: - subprocess.Popen(["/usr/bin/wpctl", "set-mute", device_id, "1"]) - else: - subprocess.Popen(["/usr/bin/wpctl", "set-mute", device_id, "0"]) + if device_id: + if mute: + subprocess.Popen(["/usr/bin/wpctl", "set-mute", device_id, "1"]) + else: + subprocess.Popen(["/usr/bin/wpctl", "set-mute", device_id, "0"]) def set_volume(volume: int, device: str) -> None: @@ -203,26 +205,9 @@ def press_hotkey(hotkey: str) -> None: def reset() -> None: for channel in audiomixer_mapping: if channel.startswith("Mute_") or channel == "Record": - set_mute(False, audiomixer_mapping[channel]) + set_mute(mute=False, device=audiomixer_mapping[channel]) elif channel.startswith("Record_"): - set_mute(True, audiomixer_mapping[channel]) - - -def vts_hotkey(hotkey: str) -> None: - vts = subprocess.run( - ["/usr/bin/xdotool", "search", "--name", "Vtube Studio"], - capture_output=True, - text=True, - ).stdout.strip("\n") - subprocess.Popen( - [ - "/usr/bin/xdotool", - "key", - "--window", - vts, - f"{hotkey}", - ] - ) + set_mute(mute=True, device=audiomixer_mapping[channel]) def main(): @@ -233,6 +218,9 @@ def main(): # Unmute all channels for me and mute all OBS channels when program starts (usually at boot) reset() + last_time = time.monotonic() + frequency = 1 / 60 + with mido.open_input(midi_device[0]) as mixer: for update in mixer: midi_input = nanoKontrol2_mapping[update.control] @@ -240,16 +228,19 @@ def main(): # Mute speakers if midi_input == "Record": if update.value == 127: - set_mute(toggle=True, device=audiomixer_mapping["Knob_2"]) + set_mute(mute=True, device=audiomixer_mapping["Knob_2"]) else: - set_mute(toggle=False, device=audiomixer_mapping["Knob_2"]) + set_mute(mute=False, device=audiomixer_mapping["Knob_2"]) # Set volume per channel if midi_input in sliders: - set_volume( - volume=update.value, - device=audiomixer_mapping[nanoKontrol2_mapping[update.control]], - ) + now = time.monotonic() + if now - last_time >= frequency: + last_time = now + set_volume( + volume=update.value, + device=audiomixer_mapping[nanoKontrol2_mapping[update.control]], + ) # Muting channels for user if ( @@ -257,13 +248,13 @@ def main(): and midi_input.startswith("Mute_") and update.value == 127 ): - set_mute(toggle=True, device=audiomixer_mapping[midi_input]) + set_mute(mute=True, device=audiomixer_mapping[midi_input]) elif ( midi_input in buttons and midi_input.startswith("Mute_") and update.value == 0 ): - set_mute(toggle=False, device=audiomixer_mapping[midi_input]) + set_mute(mute=False, device=audiomixer_mapping[midi_input]) # Enabling channels for OBS if ( @@ -271,13 +262,13 @@ def main(): and midi_input.startswith("Record_") and update.value == 0 ): - set_mute(toggle=True, device=audiomixer_mapping[midi_input]) + set_mute(mute=True, device=audiomixer_mapping[midi_input]) elif ( midi_input in buttons and midi_input.startswith("Record_") and update.value == 127 ): - set_mute(toggle=False, device=audiomixer_mapping[midi_input]) + set_mute(mute=False, device=audiomixer_mapping[midi_input]) # Media controls if midi_input in ["Prev", "Next"] and update.value == 127: @@ -287,16 +278,6 @@ def main(): ): press_hotkey(hotkey=audiomixer_mapping[midi_input]) - try: - if ( - midi_input - in ["Marker_prev", "Marker_next", "Track_prev", "Track_next"] - and update.value == 127 - ) or midi_input in ["Cycle", "Marker_set"]: - if audiomixer_mapping[midi_input].startswith("vts"): - vts_hotkey(hotkey=audiomixer_mapping[midi_input].split(" ")[1]) - except KeyError: - pass # TODO define mixers in config files # TODO user config for audio streams