midiOSCesp/esp/uosc/threadedclient.py

87 lines
2.2 KiB
Python
Executable File

# -*- coding: utf-8 -*-
"""OSC client running in a separate thread.
Communicates with the main thread via a queue. Provides the same API as the
non-threaded client, with a few threading-related extensions:
from uosc.threadedclient import ThreadedClient
# start=True starts the thread immediately
osc = ThreadedClient('192.168.0.42', 9001, start=True)
# if the OSC message can not placed in the queue within timeout
# raises a queue.Full error
osc.send('/pi', 3.14159, timeout=1.0)
# Stops and joins the thread and closes the client socket
osc.close()
"""
import logging
import threading
try:
import queue
except ImportError:
import Queue as queue
from uosc.client import Client
log = logging.getLogger(__name__)
class ThreadedClient(threading.Thread):
def __init__(self, host, port=None, start=False, timeout=3.0):
super(ThreadedClient, self).__init__()
self.host = host
self.port = port
self.timeout = timeout
self._q = queue.Queue()
if start:
self.start()
def run(self, *args, **kw):
self.client = Client((self.host, self.port))
while True:
msg = self._q.get()
if msg is None:
break
addr, msg = msg
log.debug("Sending OSC msg %s, %r", addr, msg)
self.client.send(addr, *msg)
self.client.close()
def send(self, addr, *args, **kw):
self._q.put((addr, args), timeout=kw.get('timeout', self.timeout))
def close(self, **kw):
timeout = kw.get('timeout', self.timeout)
log.debug("Emptying send queue...")
while True:
try:
self._q.get_nowait()
except queue.Empty:
break
if self.is_alive():
log.debug("Signalling OSC client thread to exit...")
self._q.put(None, timeout=timeout)
log.debug("Joining OSC client thread...")
self.join(timeout)
if self.is_alive():
log.warning("OSC client thread still alive after join().")
def __enter__(self):
return self
def __exit__(self, *args):
self.close()