1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#!/usr/bin/env python3
import argparse
import random
import time
import fileinput
from pythonosc import udp_client
from math import ceil
from math import floor
from generate_utils import getLayerParam
from generate_utils import getSelectParam
from generate_utils import getEnableParam
from generate_utils import getBoardIndex
from generate_utils import NUM_LAYERS
from generate_utils import BOARD_ROWS
from generate_utils import BOARD_COLS
def usage():
print("python3 -m pip install python-osc")
print("python3 ./osc_ctrl.py")
parser = argparse.ArgumentParser()
parser.add_argument("-i", default="127.0.0.1", help="OSC server IP")
parser.add_argument("-p", type=int, default=9000, help="OSC server port")
args = parser.parse_args()
client = udp_client.SimpleUDPClient(args.i, args.p)
def encodeMessage(msg):
result = []
for char in msg:
char_int = ord(char)
if char_int >= ord('A') and char_int <= ord('Z'):
result.append(ord(char) - ord('A'))
elif char >= 'a' and char <= 'z':
result.append((ord(char) - ord('a')) + 26)
elif char >= '0' and char <= '9':
result.append((ord(char) - ord('0')) + 52)
elif char == '.':
result.append(62)
elif char == ',':
result.append(63)
elif char == ' ':
result.append(64)
# Pad message with spaces so that it overwrites any leftover text.
result += [65] * (BOARD_ROWS * BOARD_COLS - len(result))
return result
# `which_cell` is an integer in the range [0,8).
def sendMessageCell(msg_cell, which_cell):
s0 = ((floor(which_cell / 4) % 2) == 1)
s1 = ((floor(which_cell / 2) % 2) == 1)
s2 = ((floor(which_cell / 1) % 2) == 1)
print("Cell s0/s1/s2: {}/{}/{}".format(s0,s1,s2))
# Seek each layer to the current cell.
for i in range(0, len(msg_cell)):
print("Board index: {}".format(getBoardIndex(i, s0, s1, s2)))
addr="/avatar/parameters/" + getLayerParam(i)
client.send_message(addr, msg_cell[i])
addr="/avatar/parameters/" + getSelectParam(i, 0)
client.send_message(addr, (floor(which_cell / 4) % 2) == 1)
addr="/avatar/parameters/" + getSelectParam(i, 1)
client.send_message(addr, (floor(which_cell / 2) % 2) == 1)
addr="/avatar/parameters/" + getSelectParam(i, 2)
client.send_message(addr, (which_cell % 2) == 1)
# Wait for convergence.
time.sleep(0.3)
# Enable each layer.
# TODO(yum_food) for some reason, if we don't active every layer, the
# desired subset won't reliably fire. Why?
for i in range(0, NUM_LAYERS):
addr="/avatar/parameters/" + getEnableParam(i)
client.send_message(addr, True)
# Wait for convergence.
time.sleep(0.3)
# Disable each layer.
for i in range(0, NUM_LAYERS):
addr="/avatar/parameters/" + getEnableParam(i)
client.send_message(addr, False)
# Wait for convergence.
time.sleep(0.3)
def sendMessage(msg):
# The board is broken down into contiguous collections of characters called
# cells. Each cell contains `NUM_LAYERS` characters. We can update one cell
# every ~1.0 seconds; going faster causes the board to display garbage to
# remote players.
msg = encodeMessage(msg)
n_cells = ceil(len(msg) / NUM_LAYERS)
for cell in range(0, n_cells):
cell_begin = cell * NUM_LAYERS
cell_end = (cell + 1) * NUM_LAYERS
cell_msg = msg[cell_begin:cell_end]
print("Send cell {}".format(cell))
sendMessageCell(cell_msg, cell)
for line in fileinput.input():
sendMessage(line)
sendMessage("")
|