picrate 0.8.0-java → 0.9.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,388 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ * RawDXF - Code to write DXF files with beginRaw/endRaw
5
+ * An extension for the Processing project - http://processing.org
6
+ * <p/>
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ * <p/>
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ * <p/>
17
+ * You should have received a copy of the GNU Lesser General
18
+ * Public License along with the Processing project; if not,
19
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
20
+ * Suite 330, Boston, MA 02111-1307 USA
21
+ */
22
+ package processing.dxf;
23
+
24
+ import java.io.File;
25
+ import java.io.FileWriter;
26
+ import java.io.IOException;
27
+ import java.io.PrintWriter;
28
+ import processing.core.PGraphics;
29
+
30
+ /**
31
+ * A simple library to write DXF files with Processing. Because this is used
32
+ * with beginRaw() and endRaw(), only individual triangles and (discontinuous)
33
+ * line segments will be written to the file.
34
+ * <p>
35
+ * Use something like a keyPressed() in PApplet to trigger it, to avoid writing
36
+ * a bazillion .dxf files.
37
+ * <p>
38
+ * Usually, the file will be saved to the sketch's folder. Use Sketch &rarr;
39
+ * Show Sketch Folder to see it from the PDE.
40
+ * <p>
41
+ * A simple example of how to use:
42
+ * <PRE>
43
+ * import processing.dxf.*;
44
+ *
45
+ * boolean record;
46
+ *
47
+ * void setup() {
48
+ * size(500, 500, P3D);
49
+ * }
50
+ *
51
+ * void keyPressed() {
52
+ * // use a key press so that it doesn't make a million files
53
+ * if (key == 'r') record = true;
54
+ * }
55
+ *
56
+ * void draw() {
57
+ * if (record) {
58
+ * beginRaw(DXF, "output.dxf");
59
+ * }
60
+ *
61
+ * // do all your drawing here
62
+ *
63
+ * if (record) {
64
+ * endRaw();
65
+ * record = false;
66
+ * }
67
+ * }
68
+ * </PRE> or to use it and be able to control the current layer:
69
+ * <PRE>
70
+ * import processing.dxf.*;
71
+ *
72
+ * boolean record;
73
+ * RawDXF dxf;
74
+ *
75
+ * void setup() {
76
+ * size(500, 500, P3D);
77
+ * }
78
+ *
79
+ * void keyPressed() {
80
+ * // use a key press so that it doesn't make a million files
81
+ * if (key == 'r') record = true;
82
+ * }
83
+ *
84
+ * void draw() {
85
+ * if (record) {
86
+ * dxf = (RawDXF) createGraphics(width, height, DXF, "output.dxf");
87
+ * beginRaw(dxf);
88
+ * }
89
+ *
90
+ * // do all your drawing here, and to set the layer, call:
91
+ * // if (record) {
92
+ * // dxf.setLayer(num);
93
+ * // }
94
+ * // where 'num' is an integer.
95
+ * // the default is zero, or you can set it to whatever.
96
+ *
97
+ * if (record) {
98
+ * endRaw();
99
+ * record = false;
100
+ * dxf = null;
101
+ * }
102
+ * }
103
+ * </PRE> Note that even though this class is a subclass of PGraphics, it only
104
+ * implements the parts of the API that are necessary for beginRaw/endRaw.
105
+ * <p>
106
+ * Based on the original DXF writer from Simon Greenwold, February 2004. Updated
107
+ * for Processing 0070 by Ben Fry in September 2004, and again for Processing
108
+ * beta in April 2005. Rewritten to support beginRaw/endRaw by Ben Fry in
109
+ * February 2006. Updated again for inclusion as a core library in March 2006.
110
+ * Constructor modifications in September 2008 as we approach 1.0.
111
+ */
112
+ public class RawDXF extends PGraphics {
113
+
114
+ File file;
115
+ PrintWriter writer;
116
+ int currentLayer;
117
+
118
+ public RawDXF() {
119
+ }
120
+
121
+ @Override
122
+ public void setPath(String path) {
123
+ this.path = path;
124
+ if (path != null) {
125
+ file = new File(path);
126
+ if (!file.isAbsolute()) {
127
+ file = null;
128
+ }
129
+ }
130
+ if (file == null) {
131
+ throw new RuntimeException("DXF export requires an absolute path "
132
+ + "for the location of the output file.");
133
+ }
134
+ }
135
+
136
+ // ..............................................................
137
+ protected void allocate() {
138
+ /*
139
+ for (int i = 0; i < MAX_TRI_LAYERS; i++) {
140
+ layerList[i] = NO_LAYER;
141
+ }
142
+ */
143
+ setLayer(0);
144
+ }
145
+
146
+ @Override
147
+ public void dispose() {
148
+ writeFooter();
149
+
150
+ writer.flush();
151
+ writer.close();
152
+ writer = null;
153
+ }
154
+
155
+ @Override
156
+ public boolean displayable() {
157
+ return false; // just in case someone wants to use this on its own
158
+ }
159
+
160
+ @Override
161
+ public boolean is2D() {
162
+ return false;
163
+ }
164
+
165
+ @Override
166
+ public boolean is3D() {
167
+ return true;
168
+ }
169
+
170
+ // ..............................................................
171
+ @Override
172
+ public void beginDraw() {
173
+ // have to create file object here, because the name isn't yet
174
+ // available in allocate()
175
+ if (writer == null) {
176
+ try {
177
+ writer = new PrintWriter(new FileWriter(file));
178
+ } catch (IOException e) {
179
+ throw new RuntimeException(e); // java 1.4+
180
+ }
181
+ writeHeader();
182
+ }
183
+ }
184
+
185
+ @Override
186
+ public void endDraw() {
187
+ writer.flush();
188
+ }
189
+
190
+ // ..............................................................
191
+ /**
192
+ * Set the current layer being used in the DXF file.The default is zero.
193
+ *
194
+ * @param layer
195
+ */
196
+ public void setLayer(int layer) {
197
+ currentLayer = layer;
198
+ }
199
+
200
+ // ..............................................................
201
+ private void writeHeader() {
202
+ writer.println("0");
203
+ writer.println("SECTION");
204
+ writer.println("2");
205
+ writer.println("ENTITIES");
206
+ }
207
+
208
+ private void writeFooter() {
209
+ writer.println("0");
210
+ writer.println("ENDSEC");
211
+ writer.println("0");
212
+ writer.println("EOF");
213
+ }
214
+
215
+ /**
216
+ * Write a command on one line (as a String), then start a new line and
217
+ * write out a formatted float.Available for anyone who wants to insert
218
+ * additional commands into the DXF stream.
219
+ *
220
+ * @param cmd
221
+ * @param val
222
+ */
223
+ public void write(String cmd, float val) {
224
+ writer.println(cmd);
225
+ // Don't number format, will cause trouble on systems that aren't en-US
226
+ // http://dev.processing.org/bugs/show_bug.cgi?id=495
227
+ writer.println(val);
228
+ }
229
+
230
+ /**
231
+ * Write a line to the dxf file.Available for anyone who wants to insert
232
+ * additional commands into the DXF stream.
233
+ *
234
+ * @param what
235
+ */
236
+ public void println(String what) {
237
+ writer.println(what);
238
+ }
239
+
240
+ protected void writeLine(int index1, int index2) {
241
+ writer.println("0");
242
+ writer.println("LINE");
243
+
244
+ // write out the layer
245
+ writer.println("8");
246
+ writer.println(String.valueOf(currentLayer));
247
+
248
+ write("10", vertices[index1][X]);
249
+ write("20", vertices[index1][Y]);
250
+ write("30", vertices[index1][Z]);
251
+
252
+ write("11", vertices[index2][X]);
253
+ write("21", vertices[index2][Y]);
254
+ write("31", vertices[index2][Z]);
255
+ }
256
+
257
+
258
+ /*
259
+ protected void writeLineStrip() {
260
+ writeLine();
261
+ // shift the last vertex to be the first vertex
262
+ System.arraycopy(vertices[1], 0, vertices[0], 0, vertices[1].length);
263
+ vertexCount = 1;
264
+ }
265
+ */
266
+ protected void writeTriangle() {
267
+ writer.println("0");
268
+ writer.println("3DFACE");
269
+
270
+ // write out the layer
271
+ writer.println("8");
272
+ /*
273
+ if (i < MAX_TRI_LAYERS) {
274
+ if (layerList[i] >= 0) {
275
+ currentLayer = layerList[i];
276
+ }
277
+ }
278
+ */
279
+ writer.println(String.valueOf(currentLayer));
280
+
281
+ write("10", vertices[0][X]);
282
+ write("20", vertices[0][Y]);
283
+ write("30", vertices[0][Z]);
284
+
285
+ write("11", vertices[1][X]);
286
+ write("21", vertices[1][Y]);
287
+ write("31", vertices[1][Z]);
288
+
289
+ write("12", vertices[2][X]);
290
+ write("22", vertices[2][Y]);
291
+ write("32", vertices[2][Z]);
292
+
293
+ // Without adding EPSILON, Rhino kinda freaks out.
294
+ // A face is actually a quad, not a triangle,
295
+ // so instead kinda fudging the final point here.
296
+ write("13", vertices[2][X] + EPSILON);
297
+ write("23", vertices[2][Y] + EPSILON);
298
+ write("33", vertices[2][Z] + EPSILON);
299
+
300
+ vertexCount = 0;
301
+ }
302
+
303
+ // ..............................................................
304
+ @Override
305
+ public void beginShape(int kind) {
306
+ shape = kind;
307
+
308
+ if ((shape != LINES)
309
+ && (shape != TRIANGLES)
310
+ && (shape != POLYGON)) {
311
+ String err
312
+ = "RawDXF can only be used with beginRaw(), "
313
+ + "because it only supports lines and triangles";
314
+ throw new RuntimeException(err);
315
+ }
316
+
317
+ if ((shape == POLYGON) && fill) {
318
+ throw new RuntimeException("DXF Export only supports non-filled shapes.");
319
+ }
320
+
321
+ vertexCount = 0;
322
+ }
323
+
324
+ @Override
325
+ public void vertex(float x, float y) {
326
+ vertex(x, y, 0);
327
+ }
328
+
329
+ @Override
330
+ public void vertex(float x, float y, float z) {
331
+ float vertex[] = vertices[vertexCount];
332
+
333
+ vertex[X] = x; // note: not mx, my, mz like PGraphics3
334
+ vertex[Y] = y;
335
+ vertex[Z] = z;
336
+
337
+ if (fill) {
338
+ vertex[R] = fillR;
339
+ vertex[G] = fillG;
340
+ vertex[B] = fillB;
341
+ vertex[A] = fillA;
342
+ }
343
+
344
+ if (stroke) {
345
+ vertex[SR] = strokeR;
346
+ vertex[SG] = strokeG;
347
+ vertex[SB] = strokeB;
348
+ vertex[SA] = strokeA;
349
+ vertex[SW] = strokeWeight;
350
+ }
351
+
352
+ if (textureImage != null) { // for the future?
353
+ vertex[U] = textureU;
354
+ vertex[V] = textureV;
355
+ }
356
+ vertexCount++;
357
+
358
+ if ((shape == LINES) && (vertexCount == 2)) {
359
+ writeLine(0, 1);
360
+ vertexCount = 0;
361
+
362
+ /*
363
+ } else if ((shape == LINE_STRIP) && (vertexCount == 2)) {
364
+ writeLineStrip();
365
+ */
366
+ } else if ((shape == TRIANGLES) && (vertexCount == 3)) {
367
+ writeTriangle();
368
+ }
369
+ }
370
+
371
+ @Override
372
+ public void endShape(int mode) {
373
+ if (shape == POLYGON) {
374
+ for (int i = 0; i < vertexCount - 1; i++) {
375
+ writeLine(i, i + 1);
376
+ }
377
+ if (mode == CLOSE) {
378
+ writeLine(vertexCount - 1, 0);
379
+ }
380
+ }
381
+ /*
382
+ if ((vertexCount != 0) &&
383
+ ((shape != LINE_STRIP) && (vertexCount != 1))) {
384
+ System.err.println("Extra vertex boogers found.");
385
+ }
386
+ */
387
+ }
388
+ }
@@ -0,0 +1,756 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ Client - basic network client implementation
5
+ Part of the Processing project - http://processing.org
6
+
7
+ Copyright (c) 2004-2007 Ben Fry and Casey Reas
8
+ The previous version of this code was developed by Hernando Barragan
9
+
10
+ This library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Lesser General Public
12
+ License as published by the Free Software Foundation; either
13
+ version 2.1 of the License, or (at your option) any later version.
14
+
15
+ This library is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Lesser General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Lesser General
21
+ Public License along with this library; if not, write to the
22
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
+ Boston, MA 02111-1307 USA
24
+ */
25
+ package processing.net;
26
+
27
+ import java.io.IOException;
28
+ import java.io.InputStream;
29
+ import java.io.OutputStream;
30
+ import java.lang.reflect.InvocationTargetException;
31
+ import java.lang.reflect.Method;
32
+ import java.net.Socket;
33
+ import java.net.SocketException;
34
+ import processing.core.PApplet;
35
+
36
+ /**
37
+ * ( begin auto-generated from Client.xml )
38
+ *
39
+ * A client connects to a server and sends data back and forth. If anything goes
40
+ * wrong with the connection, for example the host is not there or is listening
41
+ * on a different port, an exception is thrown.
42
+ *
43
+ * ( end auto-generated )
44
+ *
45
+ * @webref net
46
+ * @brief The client class is used to create client Objects which connect to a
47
+ * server to exchange data.
48
+ * @instanceName client any variable of type Client
49
+ * @usage Application
50
+ * @see_external LIB_net/clientEvent
51
+ */
52
+ public class Client implements Runnable {
53
+
54
+ protected static final int MAX_BUFFER_SIZE = 1 << 27; // 128 MB
55
+
56
+ PApplet parent;
57
+ Method clientEventMethod;
58
+ Method disconnectEventMethod;
59
+
60
+ volatile Thread thread;
61
+ Socket socket;
62
+ int port;
63
+ String host;
64
+
65
+ public InputStream input;
66
+ public OutputStream output;
67
+
68
+ final Object bufferLock = new Object[0];
69
+
70
+ byte buffer[] = new byte[32768];
71
+ int bufferIndex;
72
+ int bufferLast;
73
+
74
+ boolean disposeRegistered = false;
75
+
76
+ /**
77
+ * @param parent typically use "this"
78
+ * @param host address of the server
79
+ * @param port port to read/write from on the server
80
+ */
81
+ public Client(PApplet parent, String host, int port) {
82
+ this.parent = parent;
83
+ this.host = host;
84
+ this.port = port;
85
+
86
+ try {
87
+ socket = new Socket(this.host, this.port);
88
+ input = socket.getInputStream();
89
+ output = socket.getOutputStream();
90
+
91
+ thread = new Thread(this);
92
+ thread.start();
93
+
94
+ parent.registerMethod("dispose", this);
95
+ disposeRegistered = true;
96
+
97
+ // reflection to check whether host sketch has a call for
98
+ // public void clientEvent(processing.net.Client)
99
+ // which would be called each time an event comes in
100
+ try {
101
+ clientEventMethod
102
+ = parent.getClass().getMethod("clientEvent", Client.class);
103
+ } catch (NoSuchMethodException | SecurityException e) {
104
+ // no such method, or an error.. which is fine, just ignore
105
+ }
106
+ // do the same for disconnectEvent(Client c);
107
+ try {
108
+ disconnectEventMethod
109
+ = parent.getClass().getMethod("disconnectEvent", Client.class);
110
+ } catch (NoSuchMethodException | SecurityException e) {
111
+ // no such method, or an error.. which is fine, just ignore
112
+ }
113
+
114
+ } catch (IOException e) {
115
+ dispose();
116
+ }
117
+ }
118
+
119
+ /**
120
+ * @param socket any object of type
121
+ * @param parent
122
+ * @throws IOException
123
+ */
124
+ public Client(PApplet parent, Socket socket) throws IOException {
125
+ this.parent = parent;
126
+ this.socket = socket;
127
+
128
+ input = socket.getInputStream();
129
+ output = socket.getOutputStream();
130
+
131
+ thread = new Thread(this);
132
+ thread.start();
133
+
134
+ // reflection to check whether host sketch has a call for
135
+ // public void clientEvent(processing.net.Client)
136
+ // which would be called each time an event comes in
137
+ try {
138
+ clientEventMethod
139
+ = parent.getClass().getMethod("clientEvent", Client.class);
140
+ } catch (NoSuchMethodException | SecurityException e) {
141
+ // no such method, or an error.. which is fine, just ignore
142
+ }
143
+ // do the same for disconnectEvent(Client c);
144
+ try {
145
+ disconnectEventMethod
146
+ = parent.getClass().getMethod("disconnectEvent", Client.class);
147
+ } catch (NoSuchMethodException | SecurityException e) {
148
+ // no such method, or an error.. which is fine, just ignore
149
+ }
150
+ }
151
+
152
+ /**
153
+ * ( begin auto-generated from Client_stop.xml )
154
+ *
155
+ * Disconnects from the server. Use to shut the connection when you're
156
+ * finished with the Client.
157
+ *
158
+ * ( end auto-generated )
159
+ *
160
+ * @webref client:client
161
+ * @brief Disconnects from the server
162
+ * @usage application
163
+ */
164
+ public void stop() {
165
+ if (disconnectEventMethod != null && thread != null) {
166
+ try {
167
+ disconnectEventMethod.invoke(parent, this);
168
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
169
+ Throwable cause = e;
170
+ // unwrap the exception if it came from the user code
171
+ if (e instanceof InvocationTargetException && e.getCause() != null) {
172
+ cause = e.getCause();
173
+ }
174
+ disconnectEventMethod = null;
175
+ }
176
+ }
177
+ if (disposeRegistered) {
178
+ parent.unregisterMethod("dispose", this);
179
+ disposeRegistered = false;
180
+ }
181
+ dispose();
182
+ }
183
+
184
+ /**
185
+ * Disconnect from the server: internal use only.
186
+ * <P>
187
+ * This should only be called by the internal functions in PApplet, use
188
+ * stop() instead from within your own applets.
189
+ */
190
+ public void dispose() {
191
+ thread = null;
192
+ try {
193
+ if (input != null) {
194
+ input.close();
195
+ input = null;
196
+ }
197
+ } catch (IOException e) {
198
+ }
199
+
200
+ try {
201
+ if (output != null) {
202
+ output.close();
203
+ output = null;
204
+ }
205
+ } catch (IOException e) {
206
+ }
207
+
208
+ try {
209
+ if (socket != null) {
210
+ socket.close();
211
+ socket = null;
212
+ }
213
+ } catch (IOException e) {
214
+ }
215
+ }
216
+
217
+ @Override
218
+ public void run() {
219
+ byte[] readBuffer;
220
+ { // make the read buffer same size as socket receive buffer so that
221
+ // we don't waste cycles calling listeners when there is more data waiting
222
+ int readBufferSize = 1 << 16; // 64 KB (default socket receive buffer size)
223
+ try {
224
+ readBufferSize = socket.getReceiveBufferSize();
225
+ } catch (SocketException ignore) {
226
+ }
227
+ readBuffer = new byte[readBufferSize];
228
+ }
229
+ while (Thread.currentThread() == thread) {
230
+ try {
231
+ while (input != null) {
232
+ int readCount;
233
+
234
+ // try to read a byte using a blocking read.
235
+ // An exception will occur when the sketch is exits.
236
+ try {
237
+ readCount = input.read(readBuffer, 0, readBuffer.length);
238
+ } catch (SocketException e) {
239
+ System.err.println("Client SocketException: " + e.getMessage());
240
+ // the socket had a problem reading so don't try to read from it again.
241
+ stop();
242
+ return;
243
+ }
244
+
245
+ // read returns -1 if end-of-stream occurs (for example if the host disappears)
246
+ if (readCount == -1) {
247
+ System.err.println("Client got end-of-stream.");
248
+ stop();
249
+ return;
250
+ }
251
+
252
+ synchronized (bufferLock) {
253
+ int freeBack = buffer.length - bufferLast;
254
+ if (readCount > freeBack) {
255
+ // not enough space at the back
256
+ int bufferLength = bufferLast - bufferIndex;
257
+ byte[] targetBuffer = buffer;
258
+ if (bufferLength + readCount > buffer.length) {
259
+ // can't fit even after compacting, resize the buffer
260
+ // find the next power of two which can fit everything in
261
+ int newSize = Integer.highestOneBit(bufferLength + readCount - 1) << 1;
262
+ if (newSize > MAX_BUFFER_SIZE) {
263
+ // buffer is full because client is not reading (fast enough)
264
+ System.err.println("Client: can't receive more data, buffer is full. "
265
+ + "Make sure you read the data from the client.");
266
+ stop();
267
+ return;
268
+ }
269
+ targetBuffer = new byte[newSize];
270
+ }
271
+ // compact the buffer (either in-place or into the new bigger buffer)
272
+ System.arraycopy(buffer, bufferIndex, targetBuffer, 0, bufferLength);
273
+ bufferLast -= bufferIndex;
274
+ bufferIndex = 0;
275
+ buffer = targetBuffer;
276
+ }
277
+ // copy all newly read bytes into the buffer
278
+ System.arraycopy(readBuffer, 0, buffer, bufferLast, readCount);
279
+ bufferLast += readCount;
280
+ }
281
+
282
+ // now post an event
283
+ if (clientEventMethod != null) {
284
+ try {
285
+ clientEventMethod.invoke(parent, this);
286
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
287
+ System.err.println("error, disabling clientEvent() for " + host);
288
+ Throwable cause = e;
289
+ // unwrap the exception if it came from the user code
290
+ if (e instanceof InvocationTargetException && e.getCause() != null) {
291
+ cause = e.getCause();
292
+ }
293
+ clientEventMethod = null;
294
+ }
295
+ }
296
+ }
297
+ } catch (IOException e) {
298
+ //errorMessage("run", e);
299
+
300
+ }
301
+ }
302
+ }
303
+
304
+ /**
305
+ * ( begin auto-generated from Client_active.xml )
306
+ *
307
+ * Returns true if this client is still active and hasn't run into any
308
+ * trouble.( end auto-generated )
309
+ *
310
+ *
311
+ * @return
312
+ * @webref client:client
313
+ * @brief Returns true if this client is still active
314
+ * @usage application
315
+ */
316
+ public boolean active() {
317
+ return (thread != null);
318
+ }
319
+
320
+ /**
321
+ * ( begin auto-generated from Client_ip.xml )
322
+ *
323
+ * Returns the IP address of the computer to which the Client is attached.(
324
+ * end auto-generated )
325
+ *
326
+ *
327
+ * @return
328
+ * @webref client:client
329
+ * @usage application
330
+ * @brief Returns the IP address of the machine as a String
331
+ */
332
+ public String ip() {
333
+ if (socket != null) {
334
+ return socket.getInetAddress().getHostAddress();
335
+ }
336
+ return null;
337
+ }
338
+
339
+ /**
340
+ * ( begin auto-generated from Client_available.xml )
341
+ *
342
+ * Returns the number of bytes available.When any client has bytes available
343
+ * from the server, it returns the number of bytes. ( end auto-generated )
344
+ *
345
+ * @return
346
+ * @webref client:client
347
+ * @usage application
348
+ * @brief Returns the number of bytes in the buffer waiting to be read
349
+ */
350
+ public int available() {
351
+ synchronized (bufferLock) {
352
+ return (bufferLast - bufferIndex);
353
+ }
354
+ }
355
+
356
+ /**
357
+ * ( begin auto-generated from Client_clear.xml )
358
+ *
359
+ * Empty the buffer, removes all the data stored there.
360
+ *
361
+ * ( end auto-generated )
362
+ *
363
+ * @webref client:client
364
+ * @usage application
365
+ * @brief Clears the buffer
366
+ */
367
+ public void clear() {
368
+ synchronized (bufferLock) {
369
+ bufferLast = 0;
370
+ bufferIndex = 0;
371
+ }
372
+ }
373
+
374
+ /**
375
+ * ( begin auto-generated from Client_read.xml )
376
+ *
377
+ * Returns a number between 0 and 255 for the next byte that's waiting in
378
+ * the buffer.Returns -1 if there is no byte, although this should be
379
+ * avoided by first cheacking <b>available()</b> to see if any data is
380
+ * available. ( end auto-generated )
381
+ *
382
+ * @return
383
+ * @webref client:client
384
+ * @usage application
385
+ * @brief Returns a value from the buffer
386
+ */
387
+ public int read() {
388
+ synchronized (bufferLock) {
389
+ if (bufferIndex == bufferLast) {
390
+ return -1;
391
+ }
392
+
393
+ int outgoing = buffer[bufferIndex++] & 0xff;
394
+ if (bufferIndex == bufferLast) { // rewind
395
+ bufferIndex = 0;
396
+ bufferLast = 0;
397
+ }
398
+ return outgoing;
399
+ }
400
+ }
401
+
402
+ /**
403
+ * ( begin auto-generated from Client_readChar.xml )
404
+ *
405
+ * Returns the next byte in the buffer as a char.Returns -1 or 0xffff if
406
+ * nothing is there. ( end auto-generated )
407
+ *
408
+ * @return
409
+ * @webref client:client
410
+ * @usage application
411
+ * @brief Returns the next byte in the buffer as a char
412
+ */
413
+ public char readChar() {
414
+ synchronized (bufferLock) {
415
+ if (bufferIndex == bufferLast) {
416
+ return (char) (-1);
417
+ }
418
+ return (char) read();
419
+ }
420
+ }
421
+
422
+ /**
423
+ * ( begin auto-generated from Client_readBytes.xml )
424
+ *
425
+ * Reads a group of bytes from the buffer.The version with no parameters
426
+ * returns a byte array of all data in the buffer. This is not efficient,
427
+ * but is easy to use. The version with the <b>byteBuffer</b> parameter is
428
+ * more memory and time efficient. It grabs the data in the buffer and puts
429
+ * it into the byte array passed in and returns an int value for the number
430
+ * of bytes read. If more bytes are available than can fit into the
431
+ * <b>byteBuffer</b>, only those that fit are read.
432
+ *
433
+ * ( end auto-generated )
434
+ * <h3>Advanced</h3>
435
+ * Return a byte array of anything that's in the serial buffer. Not
436
+ * particularly memory/speed efficient, because it creates a byte array on
437
+ * each read, but it's easier to use than readBytes(byte b[]) (see below).
438
+ *
439
+ * @return
440
+ * @webref client:client
441
+ * @usage application
442
+ * @brief Reads everything in the buffer
443
+ */
444
+ public byte[] readBytes() {
445
+ synchronized (bufferLock) {
446
+ if (bufferIndex == bufferLast) {
447
+ return null;
448
+ }
449
+
450
+ int length = bufferLast - bufferIndex;
451
+ byte outgoing[] = new byte[length];
452
+ System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
453
+
454
+ bufferIndex = 0; // rewind
455
+ bufferLast = 0;
456
+ return outgoing;
457
+ }
458
+ }
459
+
460
+ /**
461
+ * <h3>Advanced</h3>
462
+ * Return a byte array of anything that's in the serial buffer up to the
463
+ * specified maximum number of bytes. Not particularly memory/speed
464
+ * efficient, because it creates a byte array on each read, but it's easier
465
+ * to use than readBytes(byte b[]) (see below).
466
+ *
467
+ * @param max the maximum number of bytes to read
468
+ * @return
469
+ */
470
+ public byte[] readBytes(int max) {
471
+ synchronized (bufferLock) {
472
+ if (bufferIndex == bufferLast) {
473
+ return null;
474
+ }
475
+
476
+ int length = bufferLast - bufferIndex;
477
+ if (length > max) {
478
+ length = max;
479
+ }
480
+ byte outgoing[] = new byte[length];
481
+ System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
482
+
483
+ bufferIndex += length;
484
+ if (bufferIndex == bufferLast) {
485
+ bufferIndex = 0; // rewind
486
+ bufferLast = 0;
487
+ }
488
+
489
+ return outgoing;
490
+ }
491
+ }
492
+
493
+ /**
494
+ * <h3>Advanced</h3>
495
+ * Grab whatever is in the serial buffer, and stuff it into a byte buffer
496
+ * passed in by the user. This is more memory/time efficient than
497
+ * readBytes() returning a byte[] array.
498
+ *
499
+ * Returns an int for how many bytes were read. If more bytes are available
500
+ * than can fit into the byte array, only those that will fit are read.
501
+ *
502
+ * @param bytebuffer passed in byte array to be altered
503
+ * @return
504
+ */
505
+ public int readBytes(byte bytebuffer[]) {
506
+ synchronized (bufferLock) {
507
+ if (bufferIndex == bufferLast) {
508
+ return 0;
509
+ }
510
+
511
+ int length = bufferLast - bufferIndex;
512
+ if (length > bytebuffer.length) {
513
+ length = bytebuffer.length;
514
+ }
515
+ System.arraycopy(buffer, bufferIndex, bytebuffer, 0, length);
516
+
517
+ bufferIndex += length;
518
+ if (bufferIndex == bufferLast) {
519
+ bufferIndex = 0; // rewind
520
+ bufferLast = 0;
521
+ }
522
+ return length;
523
+ }
524
+ }
525
+
526
+ /**
527
+ * ( begin auto-generated from Client_readBytesUntil.xml )
528
+ *
529
+ * Reads from the port into a buffer of bytes up to and including a
530
+ * particular character.If the character isn't in the buffer, 'null' is
531
+ * returned. The version with no <b>byteBuffer</b> parameter returns a byte
532
+ * array of all data up to and including the <b>interesting</b> byte. This
533
+ * is not efficient, but is easy to use. The version with the
534
+ * <b>byteBuffer</b> parameter is more memory and time efficient. It grabs
535
+ * the data in the buffer and puts it into the byte array passed in and
536
+ * returns an int value for the number of bytes read. If the byte buffer is
537
+ * not large enough, -1 is returned and an error is printed to the message
538
+ * area. If nothing is in the buffer, 0 is returned.
539
+ *
540
+ * ( end auto-generated )
541
+ *
542
+ * @return
543
+ * @webref client:client
544
+ * @usage application
545
+ * @brief Reads from the buffer of bytes up to and including a particular
546
+ * character
547
+ * @param interesting character designated to mark the end of the data
548
+ */
549
+ public byte[] readBytesUntil(int interesting) {
550
+ byte what = (byte) interesting;
551
+
552
+ synchronized (bufferLock) {
553
+ if (bufferIndex == bufferLast) {
554
+ return null;
555
+ }
556
+
557
+ int found = -1;
558
+ for (int k = bufferIndex; k < bufferLast; k++) {
559
+ if (buffer[k] == what) {
560
+ found = k;
561
+ break;
562
+ }
563
+ }
564
+ if (found == -1) {
565
+ return null;
566
+ }
567
+
568
+ int length = found - bufferIndex + 1;
569
+ byte outgoing[] = new byte[length];
570
+ System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
571
+
572
+ bufferIndex += length;
573
+ if (bufferIndex == bufferLast) {
574
+ bufferIndex = 0; // rewind
575
+ bufferLast = 0;
576
+ }
577
+ return outgoing;
578
+ }
579
+ }
580
+
581
+ /**
582
+ * <h3>Advanced</h3>
583
+ * Reads from the serial port into a buffer of bytes until a particular
584
+ * character. If the character isn't in the serial buffer, then 'null' is
585
+ * returned.
586
+ *
587
+ * If outgoing[] is not big enough, then -1 is returned, and an error
588
+ * message is printed on the console. If nothing is in the buffer, zero is
589
+ * returned. If 'interesting' byte is not in the buffer, then 0 is returned.
590
+ *
591
+ * @param interesting
592
+ * @param byteBuffer passed in byte array to be altered
593
+ * @return
594
+ */
595
+ public int readBytesUntil(int interesting, byte byteBuffer[]) {
596
+ byte what = (byte) interesting;
597
+
598
+ synchronized (bufferLock) {
599
+ if (bufferIndex == bufferLast) {
600
+ return 0;
601
+ }
602
+
603
+ int found = -1;
604
+ for (int k = bufferIndex; k < bufferLast; k++) {
605
+ if (buffer[k] == what) {
606
+ found = k;
607
+ break;
608
+ }
609
+ }
610
+ if (found == -1) {
611
+ return 0;
612
+ }
613
+
614
+ int length = found - bufferIndex + 1;
615
+ if (length > byteBuffer.length) {
616
+ System.err.println("readBytesUntil() byte buffer is"
617
+ + " too small for the " + length
618
+ + " bytes up to and including char " + interesting);
619
+ return -1;
620
+ }
621
+ //byte outgoing[] = new byte[length];
622
+ System.arraycopy(buffer, bufferIndex, byteBuffer, 0, length);
623
+
624
+ bufferIndex += length;
625
+ if (bufferIndex == bufferLast) {
626
+ bufferIndex = 0; // rewind
627
+ bufferLast = 0;
628
+ }
629
+ return length;
630
+ }
631
+ }
632
+
633
+ /**
634
+ * ( begin auto-generated from Client_readString.xml )
635
+ *
636
+ * Returns the all the data from the buffer as a String.This method assumes
637
+ * the incoming characters are ASCII. If you want to transfer Unicode data,
638
+ * first convert the String to a byte stream in the representation of your
639
+ * choice (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
640
+ *
641
+ * ( end auto-generated )
642
+ *
643
+ * @return
644
+ * @webref client:client
645
+ * @usage application
646
+ * @brief Returns the buffer as a String
647
+ */
648
+ public String readString() {
649
+ byte b[] = readBytes();
650
+ if (b == null) {
651
+ return null;
652
+ }
653
+ return new String(b);
654
+ }
655
+
656
+ /**
657
+ * ( begin auto-generated from Client_readStringUntil.xml )
658
+ *
659
+ * Combination of <b>readBytesUntil()</b> and <b>readString()</b>.Returns
660
+ * <b>null</b> if it doesn't find what you're looking for. ( end
661
+ * auto-generated )
662
+ * <h3>Advanced</h3>
663
+ *
664
+ * If you want to move Unicode data, you can first convert the String to a
665
+ * byte stream in the representation of your choice (i.e. UTF8 or two-byte
666
+ * Unicode data), and send it as a byte array.
667
+ *
668
+ * @return
669
+ * @webref client:client
670
+ * @usage application
671
+ * @brief Returns the buffer as a String up to and including a particular
672
+ * character
673
+ * @param interesting character designated to mark the end of the data
674
+ */
675
+ public String readStringUntil(int interesting) {
676
+ byte b[] = readBytesUntil(interesting);
677
+ if (b == null) {
678
+ return null;
679
+ }
680
+ return new String(b);
681
+ }
682
+
683
+ /**
684
+ * ( begin auto-generated from Client_write.xml )
685
+ *
686
+ * Writes data to a server specified when constructing the client.
687
+ *
688
+ * ( end auto-generated )
689
+ *
690
+ * @webref client:client
691
+ * @usage application
692
+ * @brief Writes bytes, chars, ints, bytes[], Strings
693
+ * @param data data to write
694
+ */
695
+ public void write(int data) { // will also cover char
696
+ try {
697
+ output.write(data & 0xff); // for good measure do the &
698
+ output.flush(); // hmm, not sure if a good idea
699
+
700
+ } catch (IOException e) { // null pointer or serial port dead
701
+ //errorMessage("write", e);
702
+ //e.printStackTrace();
703
+ //dispose();
704
+ //disconnect(e);
705
+ stop();
706
+ }
707
+ }
708
+
709
+ public void write(byte data[]) {
710
+ try {
711
+ output.write(data);
712
+ output.flush(); // hmm, not sure if a good idea
713
+
714
+ } catch (IOException e) { // null pointer or serial port dead
715
+ stop();
716
+ }
717
+ }
718
+
719
+ /**
720
+ * <h3>Advanced</h3>
721
+ * Write a String to the output. Note that this doesn't account for Unicode
722
+ * (two bytes per char), nor will it send UTF8 characters.. It assumes that
723
+ * you mean to send a byte buffer (most often the case for networking and
724
+ * serial i/o) and will only use the bottom 8 bits of each char in the
725
+ * string. (Meaning that internally it uses String.getBytes)
726
+ *
727
+ * If you want to move Unicode data, you can first convert the String to a
728
+ * byte stream in the representation of your choice (i.e. UTF8 or two-byte
729
+ * Unicode data), and send it as a byte array.
730
+ *
731
+ * @param data
732
+ */
733
+ public void write(String data) {
734
+ write(data.getBytes());
735
+ }
736
+
737
+ /**
738
+ * Handle disconnect due to an Exception being thrown.
739
+ */
740
+ /*
741
+ protected void disconnect(Exception e) {
742
+ dispose();
743
+ if (e != null) {
744
+ e.printStackTrace();
745
+ }
746
+ }
747
+ */
748
+ /**
749
+ * General error reporting, all corralled here just in case I think of
750
+ * something slightly more intelligent to do.
751
+ */
752
+ //public void errorMessage(String where, Exception e) {
753
+ //parent.die("Error inside Client." + where + "()", e);
754
+ //e.printStackTrace(System.err);
755
+ //}
756
+ }