removed VTS hotkey feature and added a 60Hz poller for sliders and knobs to set volumes more real time

This commit is contained in:
Mel
2026-02-09 18:22:53 +01:00
parent 636ba5e8bc
commit 1d9a856359

View File

@@ -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