2 * DOUBLE BLACK DIAMOND DOUBLE BLACK DIAMOND
5 * ///\\\ ///\\\ ///\\\ ///\\\
6 * \\\/// \\\/// \\\/// \\\///
9 * EXPERTS ONLY!! EXPERTS ONLY!!
11 * If you are an artist, you may ignore this file! It contains
12 * the code to drive grizzly board outputs.
15 GrizzlyOutput[] buildGrizzlies() throws SocketException, UnknownHostException {
16 return new GrizzlyOutput[] {
17 new GrizzlyOutput(lx, "192.168.88.100", 6, 5, 6, 7, 7, 8, 1, 2, 4, 3, 11, 10, 9, 9, 12, 13),
18 new GrizzlyOutput(lx, "192.168.88.101", 25, 23, 24, 43, 45, 44, 1, 1, 1, 1, 1, 41, 42, 21, 20, 22),
19 new GrizzlyOutput(lx, "192.168.88.104", 26, 28, 27, 19, 18, 17, 1, 1, 18, 19, 15, 16, 14, 29, 30, 31),
20 new GrizzlyOutput(lx, "192.168.88.105", 1, 1, 1, 39, 38, 40, 34, 35, 33, 32, 37, 37, 1, 1, 1, 1),
25 * Grizzly Output, sends packets to one grizzly board with a fixed IP and a number
28 class GrizzlyOutput extends LXDatagramOutput {
30 public final String ipAddress;
32 private int frameNumber = 0;
34 public GrizzlyOutput(LX lx, String ipAddress, int ... cubeIndices) throws UnknownHostException, SocketException {
36 this.ipAddress = ipAddress;
38 for (int rawCubeIndex : cubeIndices) {
39 if (rawCubeIndex > 0) {
40 Cube cube = model.getCubeByRawIndex(rawCubeIndex);
41 addDatagram(new GrizzlyDatagram(this, channelNum, cube).setAddress(ipAddress));
45 this.enabled.setValue(false);
48 protected void beforeSend(int[] colors) {
52 public int getFrameNumber() {
53 return this.frameNumber;
58 * Datagram to a Grizzlyboard. A simple fixed OSC packet.
60 static class GrizzlyDatagram extends LXDatagram {
62 private static byte[] oscString(String s) {
64 int padding = (4 - ((len + 1) % 4)) % 4;
65 byte[] bytes = new byte[len + 1 + padding];
66 System.arraycopy(s.getBytes(), 0, bytes, 0, len);
67 for (int i = len; i < bytes.length; ++i) {
73 private static int oscIntCopy(int i, byte[] buffer, int pos) {
74 buffer[pos] = (byte) ((i >> 24) & 0xff);
75 buffer[pos + 1] = (byte) ((i >> 16) & 0xff);
76 buffer[pos + 2] = (byte) ((i >> 8) & 0xff);
77 buffer[pos + 3] = (byte) (i & 0xff);
81 private final static int[] STRIP_ORDERING = new int[] { 9, 8, 11, 5, 4, 7, 6, 10, 14, 2, 1, 0, 3, 13, 12, 15 };
83 private static int[] cubePointIndices(Cube cube) {
84 int[] pointIndices = new int[Cube.POINTS_PER_CUBE - 2];
86 for (int stripIndex : STRIP_ORDERING) {
87 Strip strip = cube.strips.get(stripIndex);
88 int stripLen = ((stripIndex == 9) || (stripIndex == 15)) ? 15 : 16;
89 for (int i = stripLen-1; i >= 0; --i) {
90 pointIndices[pi++] = strip.points.get(i).index;
96 private final static byte[] OSC_ADDRESS = oscString("/shady/pointbuffer");
97 private final static byte[] OSC_TYPETAG = oscString(",iiiiibi");
99 private final static int HEADER_LENGTH = OSC_ADDRESS.length + OSC_TYPETAG.length + 24;
100 private final static int FOOTER_LENGTH = 4;
102 private final static int OSC_PORT = 779;
104 private GrizzlyOutput output;
106 private int[] pointIndices;
108 private final int frameNumberPos;
110 private final int dataPos;
112 public GrizzlyDatagram(GrizzlyOutput output, int channelNum, Cube cube) {
113 this(output, channelNum, cubePointIndices(cube));
116 public GrizzlyDatagram(GrizzlyOutput output, int channelNum, int[] pointIndices) {
117 super(HEADER_LENGTH + 4*pointIndices.length + FOOTER_LENGTH);
120 this.output = output;
121 this.pointIndices = pointIndices;
122 int dataLength = 4*pointIndices.length;
127 System.arraycopy(OSC_ADDRESS, 0, this.buffer, pos, OSC_ADDRESS.length);
128 pos += OSC_ADDRESS.length;
131 System.arraycopy(OSC_TYPETAG, 0, this.buffer, pos, OSC_TYPETAG.length);
132 pos += OSC_TYPETAG.length;
133 this.frameNumberPos = pos;
134 pos += oscIntCopy(0, this.buffer, pos); // placeholder for frame number
135 pos += oscIntCopy(0xDEADBEEF, this.buffer, pos);
136 pos += oscIntCopy(channelNum, this.buffer, pos);
137 pos += oscIntCopy(0xFEEDBEEF, this.buffer, pos);
138 pos += oscIntCopy(dataLength, this.buffer, pos);
139 pos += oscIntCopy(dataLength, this.buffer, pos);
143 oscIntCopy(0xBEFFFFEB, this.buffer, this.buffer.length - 4);
146 void onSend(int[] colors) {
147 oscIntCopy(this.output.getFrameNumber(), this.buffer, frameNumberPos);
148 int dataIndex = this.dataPos;
149 for (int index : this.pointIndices) {
150 color c = (index >= 0) ? colors[index] : 0;
151 this.buffer[dataIndex] = (byte) 0; // unused, alpha
152 this.buffer[dataIndex + 1] = (byte) ((c >> 16) & 0xff); // r
153 this.buffer[dataIndex + 2] = (byte) ((c >> 8) & 0xff); // g
154 this.buffer[dataIndex + 3] = (byte) (c & 0xff); // b