#!/usr/bin/env python
"""
Example of a UDP txosc sender with Twisted.
This example is in the public domain.
"""
import argparse
import csv
import signal
import time
import ntplib
from twisted.internet import reactor
from txosc import osc
from txosc import async
class UDPSenderApplication(object):
"""
Example that sends UDP messages.
"""
def __init__(self, port, host, address, rows, shift, token):
self.port = port
self.host = host
self.client = async.DatagramClientProtocol()
self._client_port = reactor.listenUDP(0, self.client)
self.rows = rows
self.address = address
self.shift = shift
self.token = token
reactor.callLater(0, self.send_messages)
def _send(self, element):
# This method is defined only to simplify the example
self.client.send(element, (self.host, self.port))
print("Sent %s to %s:%d" % (element, self.host, self.port))
def send_messages(self):
t0 = time.time()
#tc = 0
for row in self.rows:
if not self.token.running:
break
if self.shift:
row[0] = ntplib.system_to_ntp_time(t0 + float(row[1])/1000.0)
row_conv = [ osc.TimeTagArgument(float(row[0]))] + [osc.IntArgument(int(a)) for a in row[1:]]
#time.sleep((row_conv[1].value-tc)/1000.0)
sleep_time = t0+float(row[1])/1000.0-time.time()
if sleep_time > 0:
time.sleep(sleep_time)
#time.sleep(0.1)
tc = row_conv[1].value
self._send(osc.Message(self.address,*row_conv))
print("Goodbye.")
reactor.callLater(0.1, reactor.stop)
class Token(object):
def __init__(self):
self.running = True
if __name__ == "__main__":
token = Token()
parser = argparse.ArgumentParser(description='Simulate an (osc) pianoroll client.')
parser.add_argument('datafile', metavar='DATAFILE', help='The file containing the pianoroll data (CSV).')
parser.add_argument('-e', '--event', dest='event', metavar='EVENT', required=True, help='the event code.')
parser.add_argument('-s', '--shift', dest='shift', action='store_true', required=False, help='Shift the data.', default=False)
args = parser.parse_args()
def customHandler(signum, _):
print("Got signal: %s" % signum)
token.running = False
if reactor.running:
reactor.callFromThread(reactor.stop) # to stop twisted code when in the reactor loop
signal.signal(signal.SIGINT, customHandler)
with open(args.datafile, 'rU') as datafile:
reader = csv.reader(datafile, delimiter=' ')
app = UDPSenderApplication(9090, "127.0.0.1", "/pianoroll/%s/" % args.event, list(reader), args.shift, token)
reactor.run()