utils/pianoroll-client.py
author ymh <ymh.work@gmail.com>
Fri, 16 Jan 2015 03:16:19 +0100
changeset 93 79ae42ad97d4
parent 85 eff9460bd4f2
permissions -rw-r--r--
optimize and refactor pianoroll component
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
#!/usr/bin/env python
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
"""
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
Example of a UDP txosc sender with Twisted.
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
This example is in the public domain.
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
"""
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
73
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
     8
import argparse
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
import csv
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    10
import signal
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
import time
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
85
eff9460bd4f2 add new visualization + small corrections
ymh <ymh.work@gmail.com>
parents: 73
diff changeset
    13
import ntplib
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
from twisted.internet import reactor
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
from txosc import osc
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
from txosc import async
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
class UDPSenderApplication(object):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
    """
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    Example that sends UDP messages.
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
    """
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    23
    def __init__(self, port, host, address, rows, shift, token):
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
        self.port = port
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
        self.host = host
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        self.client = async.DatagramClientProtocol()
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
        self._client_port = reactor.listenUDP(0, self.client)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
        self.rows = rows
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        self.address = address
85
eff9460bd4f2 add new visualization + small corrections
ymh <ymh.work@gmail.com>
parents: 73
diff changeset
    30
        self.shift = shift
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    31
        self.token = token
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
        reactor.callLater(0, self.send_messages)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
    def _send(self, element):
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        # This method is defined only to simplify the example
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        self.client.send(element, (self.host, self.port))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
        print("Sent %s to %s:%d" % (element, self.host, self.port))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    def send_messages(self):
85
eff9460bd4f2 add new visualization + small corrections
ymh <ymh.work@gmail.com>
parents: 73
diff changeset
    40
        t0 = time.time()
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    41
        #tc = 0
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        for row in self.rows:
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    43
            if not self.token.running:
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    44
                break
85
eff9460bd4f2 add new visualization + small corrections
ymh <ymh.work@gmail.com>
parents: 73
diff changeset
    45
            if self.shift:
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    46
                row[0] = ntplib.system_to_ntp_time(t0 + float(row[1])/1000.0)
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
            row_conv = [ osc.TimeTagArgument(float(row[0]))] + [osc.IntArgument(int(a)) for a in row[1:]]
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    48
            #time.sleep((row_conv[1].value-tc)/1000.0)
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    49
            sleep_time = t0+float(row[1])/1000.0-time.time()
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    50
            if sleep_time > 0:
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    51
                time.sleep(sleep_time)
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    52
            #time.sleep(0.1)
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    53
            tc = row_conv[1].value
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
            self._send(osc.Message(self.address,*row_conv))
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        print("Goodbye.")
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        reactor.callLater(0.1, reactor.stop)
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    58
class Token(object):
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    59
    def __init__(self):
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    60
        self.running = True
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    61
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
if __name__ == "__main__":
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    64
    token = Token()
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    65
73
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    66
    parser = argparse.ArgumentParser(description='Simulate an (osc) pianoroll client.')
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    67
    parser.add_argument('datafile', metavar='DATAFILE', help='The file containing the pianoroll data (CSV).')
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    68
    parser.add_argument('-e', '--event', dest='event', metavar='EVENT', required=True, help='the event code.')
85
eff9460bd4f2 add new visualization + small corrections
ymh <ymh.work@gmail.com>
parents: 73
diff changeset
    69
    parser.add_argument('-s', '--shift', dest='shift', action='store_true', required=False, help='Shift the data.', default=False)
73
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    70
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    71
    args = parser.parse_args()
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    72
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    73
    def customHandler(signum, _):
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    74
        print("Got signal: %s" % signum)
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    75
        token.running = False
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    76
        if reactor.running:
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    77
            reactor.callFromThread(reactor.stop) # to stop twisted code when in the reactor loop
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    78
    signal.signal(signal.SIGINT, customHandler)
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    79
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    80
73
2a6590aeac15 Add argument for events on pianoroll client
ymh <ymh.work@gmail.com>
parents: 68
diff changeset
    81
    with open(args.datafile, 'rU') as datafile:
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
        reader = csv.reader(datafile, delimiter=' ')
93
79ae42ad97d4 optimize and refactor pianoroll component
ymh <ymh.work@gmail.com>
parents: 85
diff changeset
    83
        app = UDPSenderApplication(9090, "127.0.0.1", "/pianoroll/%s/" % args.event, list(reader), args.shift, token)
0
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
e1d4d7a8255a First shareable version
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
    reactor.run()