How to create an OSC server without blocking GUI operations
emoto-yasushi opened this issue · 0 comments
emoto-yasushi commented
I created an OSC server with a GUI that sends OSC on the client and has "start" and "stop" buttons.
Messages are received without problems, but when I run serve_forever(), the GUI operation is blocked and I cannot press the stop() button.
OSC_Client.py
import argparse
import random
import time
from pythonosc import udp_client
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--ip", default="127.0.0.1",help="The ip of the OSC server")
parser.add_argument("--port", type=int, default=5005,help="The port the OSC server is listening on")
args = parser.parse_args()
client = udp_client.SimpleUDPClient(args.ip, args.port)
for x in range(10):
client.send_message("/volume", str(x))
time.sleep(1)
OSC_GUI_Server.py
import tkinter as tk
import threading
import time
import argparse
from pythonosc import dispatcher
from pythonosc import osc_server
class threading_and_sleepGUI():
def __init__(self):
self.stop_flag = False
self.thread = None
self.currentVolume = ""
self.server = None
self.osc_thread = None
def worker(self):
print(time.time())
print(self.currentVolume)
time.sleep(8)
def scheduler(self,interval, f, wait = True):
base_time = time.time()
next_time = 0
while not self.stop_flag:
t = threading.Thread(target = f)
t.start()
if wait:
t.join()
next_time = ((base_time - time.time()) % interval) or interval
time.sleep(next_time)
def start(self):
if not self.thread:
self.thread = threading.Thread(target=self.scheduler, args=(1, self.worker, False))
self.stop_flag=False
self.thread.start()
self.start_osc_server()
def stop(self):
if self.thread:
self.stop_flag=True
self.thread.join()
self.thread=None
self.server.stop()
def print_volume_handler(self,unused_addr, args):
self.currentVolume = args[0]
def start_osc_server(self):
parser = argparse.ArgumentParser()
parser.add_argument("--ip", default="", help="The ip to listen on")
parser.add_argument("--port",type=int, default=5005, help="The port to listen on")
args = parser.parse_args()
osc_dispatcher = dispatcher.Dispatcher()
osc_dispatcher.map("/volume", self.print_volume_handler)
self.server = osc_server.ThreadingOSCUDPServer((args.ip, args.port), osc_dispatcher)
print("Serving on {}".format(self.server.server_address))
self.server.serve_forever()
def GUI_start(self):
root=tk.Tk()
Button001=tk.Button(root,text="Start",command=self.start)
Button001.pack()
Button002=tk.Button(root,text="Stop",command=self.stop)
Button002.pack()
root.mainloop()
self.stop_flag=True
self.thread.join()
t = threading_and_sleepGUI()
t.GUI_start()
I have also tried Concurrent Mode using the following code But this time I could not receive any messages. How can I create a server without blocking the GUI?
OSC_GUI_Concurrent_Server.py
import tkinter as tk
import threading
import time
import argparse
import pythonosc
from pythonosc.osc_server import AsyncIOOSCUDPServer
from pythonosc.dispatcher import Dispatcher
import asyncio
class threading_and_sleepGUI():
def __init__(self):
self.stop_flag = False
self.thread = None
self.currentVolume = ""
self.transport = None
def worker(self):
print(time.time())
print(self.currentVolume)
time.sleep(8)
def scheduler(self,interval, f, wait = True):
base_time = time.time()
next_time = 0
while not self.stop_flag:
t = threading.Thread(target = f)
t.start()
if wait:
t.join()
next_time = ((base_time - time.time()) % interval) or interval
time.sleep(next_time)
def start(self):
if not self.thread:
self.thread = threading.Thread(target=self.scheduler, args=(1, self.worker, False))
self.stop_flag=False
self.thread.start()
asyncio.run(self.start_osc_server())
def stop(self):
if self.thread:
self.stop_flag=True
self.thread.join()
self.thread=None
self.transport.close()
def print_volume_handler(self,unused_addr, args):
self.currentVolume = args[0]
async def start_osc_server(self):
dispatcher = Dispatcher()
dispatcher.map("/volume", self.print_volume_handler)
ip = ""
port = 5005
server = AsyncIOOSCUDPServer((ip, port), dispatcher, asyncio.get_event_loop())
self.transport, protocol = await server.create_serve_endpoint() # Create datagram endpoint and start serving
def GUI_start(self):
root=tk.Tk()
Button001=tk.Button(root,text="Start",command=self.start)
Button001.pack()
Button002=tk.Button(root,text="Stop",command=self.stop)
Button002.pack()
root.mainloop()
self.stop_flag=True
self.thread.join()
t = threading_and_sleepGUI()
t.GUI_start()