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 just sets
12 * up the framework to run the patterns. Should not need modification
13 * for general animation work.
16 GrizzlyOutput[] buildGrizzlies() throws SocketException, UnknownHostException {
17 return new GrizzlyOutput[] {
18 new GrizzlyOutput(lx, "192.168.88.100", 6, 5, 6, 7, 7, 8, 1, 2, 4, 3, 11, 10, 9, 9, 12, 13),
19 new GrizzlyOutput(lx, "192.168.88.101", 25, 23, 24, 43, 45, 44, 1, 1, 1, 1, 1, 41, 42, 21, 20, 22),
20 new GrizzlyOutput(lx, "192.168.88.104", 26, 28, 27, 19, 18, 17, 1, 1, 18, 19, 15, 16, 14, 29, 30, 31),
21 new GrizzlyOutput(lx, "192.168.88.105", 1, 1, 1, 39, 38, 40, 34, 35, 33, 32, 37, 37, 1, 1, 1, 1),
25 class GrizzlyOutput extends LXDatagramOutput {
27 public final String ipAddress;
29 private int frameNumber = 0;
31 GrizzlyOutput(LX lx, String ipAddress, int ... cubeIndices) throws UnknownHostException, SocketException {
33 this.ipAddress = ipAddress;
35 for (int rawCubeIndex : cubeIndices) {
36 if (rawCubeIndex > 0) {
37 Cube cube = model.getCubeByRawIndex(rawCubeIndex);
38 addDatagram(new GrizzlyDatagram(this, channelNum, cube).setAddress(ipAddress));
42 this.enabled.setValue(false);
45 protected void beforeSend(int[] colors) {
49 public int getFrameNumber() {
50 return this.frameNumber;
54 static class GrizzlyDatagram extends LXDatagram {
56 private static byte[] oscString(String s) {
58 int padding = (4 - ((len + 1) % 4)) % 4;
59 byte[] bytes = new byte[len + 1 + padding];
60 System.arraycopy(s.getBytes(), 0, bytes, 0, len);
61 for (int i = len; i < bytes.length; ++i) {
67 private static int oscIntCopy(int i, byte[] buffer, int pos) {
68 buffer[pos] = (byte) ((i >> 24) & 0xff);
69 buffer[pos + 1] = (byte) ((i >> 16) & 0xff);
70 buffer[pos + 2] = (byte) ((i >> 8) & 0xff);
71 buffer[pos + 3] = (byte) (i & 0xff);
75 private final static int[] STRIP_ORDERING = new int[] { 9, 8, 11, 5, 4, 7, 6, 10, 14, 2, 1, 0, 3, 13, 12, 15 };
77 private static int[] cubePointIndices(Cube cube) {
78 int[] pointIndices = new int[Cube.POINTS_PER_CUBE - 2];
80 for (int stripIndex : STRIP_ORDERING) {
81 Strip strip = cube.strips.get(stripIndex);
82 int stripLen = ((stripIndex == 9) || (stripIndex == 15)) ? 15 : 16;
83 for (int i = stripLen-1; i >= 0; --i) {
84 pointIndices[pi++] = strip.points.get(i).index;
90 private final static byte[] OSC_ADDRESS = oscString("/shady/pointbuffer");
91 private final static byte[] OSC_TYPETAG = oscString(",iiiiibi");
93 private final static int HEADER_LENGTH = OSC_ADDRESS.length + OSC_TYPETAG.length + 24;
94 private final static int FOOTER_LENGTH = 4;
96 private final static int OSC_PORT = 779;
98 private GrizzlyOutput output;
100 private int[] pointIndices;
102 private final int frameNumberPos;
104 private final int dataPos;
106 public GrizzlyDatagram(GrizzlyOutput output, int channelNum, Cube cube) {
107 this(output, channelNum, cubePointIndices(cube));
110 public GrizzlyDatagram(GrizzlyOutput output, int channelNum, int[] pointIndices) {
111 super(HEADER_LENGTH + 4*pointIndices.length + FOOTER_LENGTH);
114 this.output = output;
115 this.pointIndices = pointIndices;
116 int dataLength = 4*pointIndices.length;
121 System.arraycopy(OSC_ADDRESS, 0, this.buffer, pos, OSC_ADDRESS.length);
122 pos += OSC_ADDRESS.length;
125 System.arraycopy(OSC_TYPETAG, 0, this.buffer, pos, OSC_TYPETAG.length);
126 pos += OSC_TYPETAG.length;
127 this.frameNumberPos = pos;
128 pos += oscIntCopy(0, this.buffer, pos); // placeholder for frame number
129 pos += oscIntCopy(0xDEADBEEF, this.buffer, pos);
130 pos += oscIntCopy(channelNum, this.buffer, pos);
131 pos += oscIntCopy(0xFEEDBEEF, this.buffer, pos);
132 pos += oscIntCopy(dataLength, this.buffer, pos);
133 pos += oscIntCopy(dataLength, this.buffer, pos);
137 oscIntCopy(0xBEFFFFEB, this.buffer, this.buffer.length - 4);
140 void onSend(int[] colors) {
141 oscIntCopy(this.output.getFrameNumber(), this.buffer, frameNumberPos);
142 int dataIndex = this.dataPos;
143 for (int index : this.pointIndices) {
144 color c = (index >= 0) ? colors[index] : 0;
145 this.buffer[dataIndex] = (byte) 0; // unused, alpha
146 this.buffer[dataIndex + 1] = (byte) ((c >> 16) & 0xff); // r
147 this.buffer[dataIndex + 2] = (byte) ((c >> 8) & 0xff); // g
148 this.buffer[dataIndex + 3] = (byte) (c & 0xff); // b