From a95c6e7183174c2877dda5ebc765a9aa7d61fec4 Mon Sep 17 00:00:00 2001 From: Brosef Date: Wed, 3 Jun 2026 13:26:46 +0100 Subject: [PATCH] Implemented v1 --- README.md | 8 +++++ main.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 3 files changed, 98 insertions(+) create mode 100644 main.py create mode 100644 requirements.txt diff --git a/README.md b/README.md index 9c9476e..ba1ffa9 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # Simple OSC Router A simple router for allowing multiple applications to talk to VRChat simultaneously. + +## How do I use it? +By default, this software broadcasts anthing from ports 9100 to 9199 (depending on the `--count` / `-c` option) to port 9000 (VRChat's OSC server). +And broadcasts anything from port 9001 (VRChat's OSC client) to ports 9200 to 9299 (still depending on `-c`). + +The only command line argument is `--count` / `-c`, which specifies how many routes will be created. This defaults to `5`. + +For most cases you can simply run `main.py`, if you want more configuration (such as changing port numbers, binds etc.) see `python3 main.py --help` or `py main.py --help` on Windows. \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..8cd273b --- /dev/null +++ b/main.py @@ -0,0 +1,89 @@ +""" +A simple router for allowing multiple applications to talk to VRChat simultaneously. +""" + +from threading import Thread +import argparse +import logging + +from pythonosc import udp_client, osc_server +from pythonosc.dispatcher import Dispatcher + +logging.basicConfig(level=logging.DEBUG) +logger = logging.getLogger('main') + +parser = argparse.ArgumentParser(description='Simple OSC router/') +parser.add_argument('--count', '-c', type=int, help='How many routers to create', default=5) + +parser.add_argument('--routerIP', type=str, default='127.0.0.1', + help='') +parser.add_argument('--routerTXStartPort', '-ssp', type=int, + help='The starting port for the router servers.', default=9100) +parser.add_argument('--routerRXStartPort', '-csp', type=int, + help='The starting port for the router clients.', default=9200) + +parser.add_argument('--masterIP', type=str, default='127.0.0.1', + help='') +parser.add_argument('--masterTXPort', type=int, + help='', default=9000) +parser.add_argument('--masterRXPort', type=int, + help='', default=9001) + +args = parser.parse_args() + + + +routerDispatcher = Dispatcher() +masterDispatcher = Dispatcher() + +masterServer = osc_server.ThreadingOSCUDPServer((args.masterIP, args.masterRXPort), + masterDispatcher, timeout=2.5) +masterClient = udp_client.SimpleUDPClient(args.masterIP, args.masterTXPort, timeout=2.5) + +routerServers = [] +routerClients = [] + +def broadcastToMaster(address, value): + """ + Broadcasts anything sent from a router to the master. + """ + + logger.debug('Broadcasting "%s"="%s" to master...', address, value) + masterClient.send_message(address, value) + +def broadcastToRouters(address, value): + """ + Broadcasts anything sent from the master to the routers. + """ + + logger.debug('Broadcasting "%s"="%s" to %s routers...', address, value, len(routerClients)) + for c in routerClients: + c.send_message(address, value) + + +routerDispatcher.map('*', broadcastToMaster) +masterDispatcher.map('*', broadcastToRouters) + +for i in range(args.count): + logger.debug('Starting router #%s...', i+1) + serverPort = args.routerRXStartPort + i + clientPort = args.routerTXStartPort + i + server = osc_server.ThreadingOSCUDPServer((args.routerIP, serverPort), routerDispatcher, + timeout=2.5) + client = udp_client.SimpleUDPClient(args.routerIP, clientPort, timeout=2.5) + routerClients.append(client) + routerServers.append(server) + + Thread(target=server.serve_forever).start() + +logger.info('Ready. Press CTRL+C to quit.') + +try: + masterServer.serve_forever() +except KeyboardInterrupt: + pass + +masterServer.server_close() + +for s in routerServers: + s.server_close() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4e1b50f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +python-osc \ No newline at end of file