Add VRC OSC tooling
This commit is contained in:
124
VRWT_Tool/VRC_OSC/src/tools/discord_hold_mute_listener.py
Normal file
124
VRWT_Tool/VRC_OSC/src/tools/discord_hold_mute_listener.py
Normal file
@@ -0,0 +1,124 @@
|
||||
from pythonosc.dispatcher import Dispatcher
|
||||
from pythonosc.osc_server import BlockingOSCUDPServer
|
||||
from datetime import datetime
|
||||
import pyautogui
|
||||
import time
|
||||
import sys
|
||||
|
||||
HOST = "127.0.0.1"
|
||||
PORT = 9001
|
||||
PARAMETER = "/avatar/parameters/DiscordSend"
|
||||
|
||||
# Discordの初期状態を「ミュート中」と仮定
|
||||
discord_muted = True
|
||||
button_pressed = False
|
||||
last_action_time = 0.0
|
||||
DEBOUNCE_SECONDS = 0.3
|
||||
|
||||
def log(level, message):
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
print(f"[{level}] {now} {message}", flush=True)
|
||||
|
||||
def wait_exit():
|
||||
input("Press Enter to exit...")
|
||||
|
||||
def press_discord_mute_hotkey():
|
||||
pyautogui.hotkey("ctrl", "shift", "m")
|
||||
|
||||
def handle_discord_send(address, *args):
|
||||
global discord_muted
|
||||
global button_pressed
|
||||
global last_action_time
|
||||
|
||||
if not args:
|
||||
log("ERROR", "OSC args is empty")
|
||||
return
|
||||
|
||||
value = args[0]
|
||||
now_ts = time.time()
|
||||
|
||||
if isinstance(value, bool):
|
||||
is_pressed = value
|
||||
elif isinstance(value, int) or isinstance(value, float):
|
||||
is_pressed = value != 0
|
||||
else:
|
||||
log("ERROR", f"unsupported value type value={value}")
|
||||
return
|
||||
|
||||
if now_ts - last_action_time < DEBOUNCE_SECONDS:
|
||||
return
|
||||
|
||||
# 押した瞬間: ミュート解除
|
||||
if is_pressed and not button_pressed:
|
||||
button_pressed = True
|
||||
|
||||
if discord_muted:
|
||||
log("ACTION", "VRChat button pressed -> Discord unmute hotkey")
|
||||
press_discord_mute_hotkey()
|
||||
discord_muted = False
|
||||
last_action_time = now_ts
|
||||
else:
|
||||
log("INFO", "already unmuted")
|
||||
|
||||
return
|
||||
|
||||
# 離した瞬間: ミュート
|
||||
if not is_pressed and button_pressed:
|
||||
button_pressed = False
|
||||
|
||||
if not discord_muted:
|
||||
log("ACTION", "VRChat button released -> Discord mute hotkey")
|
||||
press_discord_mute_hotkey()
|
||||
discord_muted = True
|
||||
last_action_time = now_ts
|
||||
else:
|
||||
log("INFO", "already muted")
|
||||
|
||||
return
|
||||
|
||||
def main():
|
||||
log("CHECK", "STEP=1 OSC受信状態確認")
|
||||
log("INFO", f"host={HOST}")
|
||||
log("INFO", f"port={PORT}")
|
||||
log("INFO", f"parameter={PARAMETER}")
|
||||
|
||||
log("CHECK", "STEP=2 想定状態判定")
|
||||
log("INFO", "Windows PowerShellで実行していること")
|
||||
log("INFO", "VRChat OSC Enabledであること")
|
||||
log("INFO", "Discordのミュート切替キーが Ctrl+Shift+M であること")
|
||||
log("INFO", "Discordの現在状態はミュート中として扱います")
|
||||
|
||||
answer = input("[ACTION] 続行しますか? yes/no: ").strip().lower()
|
||||
|
||||
if answer != "yes":
|
||||
if answer == "no":
|
||||
log("FATAL", "ユーザー操作により停止 STEP=2")
|
||||
wait_exit()
|
||||
sys.exit(1)
|
||||
|
||||
log("ERROR", "不正入力です STEP=2")
|
||||
wait_exit()
|
||||
sys.exit(1)
|
||||
|
||||
log("ACTION", "STEP=3 OSC受信開始")
|
||||
log("INFO", "VRChatのメニューを押している間だけDiscordミュート解除します")
|
||||
log("INFO", "停止する場合は Ctrl+C")
|
||||
|
||||
dispatcher = Dispatcher()
|
||||
dispatcher.map(PARAMETER, handle_discord_send)
|
||||
|
||||
try:
|
||||
server = BlockingOSCUDPServer((HOST, PORT), dispatcher)
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
log("INFO", "Ctrl+C detected")
|
||||
except Exception as e:
|
||||
log("FATAL", f"OSC server error STEP=3 detail={e}")
|
||||
wait_exit()
|
||||
sys.exit(1)
|
||||
|
||||
log("CHECK", "STEP=4 結果確認")
|
||||
log("INFO", "終了しました")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
21
VRWT_Tool/VRC_OSC/src/tools/osc_debug_listener.py
Normal file
21
VRWT_Tool/VRC_OSC/src/tools/osc_debug_listener.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from pythonosc.dispatcher import Dispatcher
|
||||
from pythonosc.osc_server import BlockingOSCUDPServer
|
||||
from datetime import datetime
|
||||
|
||||
HOST = "127.0.0.1"
|
||||
PORT = 9001
|
||||
|
||||
def on_any(address, *args):
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
print(f"[INFO] {now} address={address} args={args}", flush=True)
|
||||
|
||||
dispatcher = Dispatcher()
|
||||
dispatcher.set_default_handler(on_any)
|
||||
|
||||
print("[CHECK] OSC受信開始")
|
||||
print(f"[INFO] host={HOST}")
|
||||
print(f"[INFO] port={PORT}")
|
||||
print("[ACTION] VRChatでメニューを押してください")
|
||||
|
||||
server = BlockingOSCUDPServer((HOST, PORT), dispatcher)
|
||||
server.serve_forever()
|
||||
54
VRWT_Tool/VRC_OSC/src/tools/osc_test_print_listener.py
Normal file
54
VRWT_Tool/VRC_OSC/src/tools/osc_test_print_listener.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from pythonosc.dispatcher import Dispatcher
|
||||
from pythonosc.osc_server import BlockingOSCUDPServer
|
||||
from datetime import datetime
|
||||
|
||||
HOST = "127.0.0.1"
|
||||
PORT = 9001
|
||||
|
||||
def log(msg):
|
||||
print(msg, flush=True)
|
||||
|
||||
def on_test(address, *args):
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
|
||||
log("")
|
||||
log(f"[INFO] time={now}")
|
||||
log(f"[ACTION] OSC parameter received")
|
||||
log(f"[INFO] address={address}")
|
||||
log(f"[INFO] args={args}")
|
||||
|
||||
dispatcher = Dispatcher()
|
||||
|
||||
dispatcher.map(
|
||||
"/avatar/parameters/TestPrint",
|
||||
on_test
|
||||
)
|
||||
|
||||
log("[CHECK] STEP=1 OSC待受開始")
|
||||
log(f"[INFO] host={HOST}")
|
||||
log(f"[INFO] port={PORT}")
|
||||
|
||||
try:
|
||||
server = BlockingOSCUDPServer(
|
||||
(HOST, PORT),
|
||||
dispatcher
|
||||
)
|
||||
|
||||
log("[INFO] OSC server started")
|
||||
log("[ACTION] VRChatでTestPrintを押してください")
|
||||
|
||||
server.serve_forever()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
log("")
|
||||
log("[INFO] Ctrl+C detected")
|
||||
log("[INFO] shutdown")
|
||||
|
||||
except Exception as e:
|
||||
log("")
|
||||
log("[FATAL] OSC server error")
|
||||
log(f"[ERROR] detail={e}")
|
||||
|
||||
print("")
|
||||
input("Press Enter to exit...")
|
||||
raise SystemExit(1)
|
||||
Reference in New Issue
Block a user