Initial Commit

This commit is contained in:
plane000
2018-04-20 10:15:15 +01:00
parent 49150ccfe4
commit 62101e8e61
2870 changed files with 520122 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/processing-core"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>processing-dxf</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,12 @@
#Sat Nov 12 10:56:00 CST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<project name="Processing DXF Library" default="build">
<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="library/dxf.jar" />
</target>
<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../../../core/library/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
<mkdir dir="bin" />
<javac source="1.8"
target="1.8"
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../../../core/library/core.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
../../mode/jdtCompilerAdapter.jar" />
</javac>
</target>
<target name="build" depends="compile" description="Build DXF library">
<jar basedir="bin" destfile="library/dxf.jar" />
</target>
</project>

View File

@@ -0,0 +1,48 @@
/**
* Simple DXF Export
* by Simon Greenwold.
*
* Press the 'R' key to export a DXF file.
*/
import processing.dxf.*;
boolean record = false;
void setup() {
size(400, 400, P3D);
noStroke();
sphereDetail(12);
}
void draw() {
if (record == true) {
beginRaw(DXF, "output.dxf"); // Start recording to the file
}
lights();
background(0);
translate(width / 3, height / 3, -200);
rotateZ(map(mouseY, 0, height, 0, PI));
rotateY(map(mouseX, 0, width, 0, HALF_PI));
for (int y = -2; y < 2; y++) {
for (int x = -2; x < 2; x++) {
for (int z = -2; z < 2; z++) {
pushMatrix();
translate(120*x, 120*y, -120*z);
sphere(30);
popMatrix();
}
}
}
if (record == true) {
endRaw();
record = false; // Stop recording to the file
}
}
void keyPressed() {
if (key == 'R' || key == 'r') { // Press R to save the file
record = true;
}
}

View File

@@ -0,0 +1,2 @@
name = DXF Export
version = 1

View File

@@ -0,0 +1,403 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* RawDXF - Code to write DXF files with beginRaw/endRaw
* An extension for the Processing project - http://processing.org
* <p/>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p/>
* You should have received a copy of the GNU Lesser General
* Public License along with the Processing project; if not,
* write to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
package processing.dxf;
import java.io.*;
import processing.core.*;
/**
* A simple library to write DXF files with Processing.
* Because this is used with beginRaw() and endRaw(), only individual
* triangles and (discontinuous) line segments will be written to the file.
* <p>
* Use something like a keyPressed() in PApplet to trigger it,
* to avoid writing a bazillion .dxf files.
* <p>
* Usually, the file will be saved to the sketch's folder.
* Use Sketch &rarr; Show Sketch Folder to see it from the PDE.
* <p>
* A simple example of how to use:
* <PRE>
* import processing.dxf.*;
*
* boolean record;
*
* void setup() {
* size(500, 500, P3D);
* }
*
* void keyPressed() {
* // use a key press so that it doesn't make a million files
* if (key == 'r') record = true;
* }
*
* void draw() {
* if (record) {
* beginRaw(DXF, "output.dxf");
* }
*
* // do all your drawing here
*
* if (record) {
* endRaw();
* record = false;
* }
* }
* </PRE>
* or to use it and be able to control the current layer:
* <PRE>
* import processing.dxf.*;
*
* boolean record;
* RawDXF dxf;
*
* void setup() {
* size(500, 500, P3D);
* }
*
* void keyPressed() {
* // use a key press so that it doesn't make a million files
* if (key == 'r') record = true;
* }
*
* void draw() {
* if (record) {
* dxf = (RawDXF) createGraphics(width, height, DXF, "output.dxf");
* beginRaw(dxf);
* }
*
* // do all your drawing here, and to set the layer, call:
* // if (record) {
* // dxf.setLayer(num);
* // }
* // where 'num' is an integer.
* // the default is zero, or you can set it to whatever.
*
* if (record) {
* endRaw();
* record = false;
* dxf = null;
* }
* }
* </PRE>
* Note that even though this class is a subclass of PGraphics, it only
* implements the parts of the API that are necessary for beginRaw/endRaw.
* <p>
* Based on the original DXF writer from Simon Greenwold, February 2004.
* Updated for Processing 0070 by Ben Fry in September 2004,
* and again for Processing beta in April 2005.
* Rewritten to support beginRaw/endRaw by Ben Fry in February 2006.
* Updated again for inclusion as a core library in March 2006.
* Constructor modifications in September 2008 as we approach 1.0.
*/
public class RawDXF extends PGraphics {
File file;
PrintWriter writer;
int currentLayer;
public RawDXF() { }
public void setPath(String path) {
this.path = path;
if (path != null) {
file = new File(path);
if (!file.isAbsolute()) file = null;
}
if (file == null) {
throw new RuntimeException("DXF export requires an absolute path " +
"for the location of the output file.");
}
}
// ..............................................................
protected void allocate() {
/*
for (int i = 0; i < MAX_TRI_LAYERS; i++) {
layerList[i] = NO_LAYER;
}
*/
setLayer(0);
}
public void dispose() {
writeFooter();
writer.flush();
writer.close();
writer = null;
}
public boolean displayable() {
return false; // just in case someone wants to use this on its own
}
public boolean is2D() {
return false;
}
public boolean is3D() {
return true;
}
// ..............................................................
public void beginDraw() {
// have to create file object here, because the name isn't yet
// available in allocate()
if (writer == null) {
try {
writer = new PrintWriter(new FileWriter(file));
} catch (IOException e) {
throw new RuntimeException(e); // java 1.4+
}
writeHeader();
}
}
public void endDraw() {
writer.flush();
}
// ..............................................................
/**
* Set the current layer being used in the DXF file.
* The default is zero.
*/
public void setLayer(int layer) {
currentLayer = layer;
}
// ..............................................................
private void writeHeader() {
writer.println("0");
writer.println("SECTION");
writer.println("2");
writer.println("ENTITIES");
}
private void writeFooter() {
writer.println("0");
writer.println("ENDSEC");
writer.println("0");
writer.println("EOF");
}
/**
* Write a command on one line (as a String), then start a new line
* and write out a formatted float. Available for anyone who wants to
* insert additional commands into the DXF stream.
*/
public void write(String cmd, float val) {
writer.println(cmd);
// Don't number format, will cause trouble on systems that aren't en-US
// http://dev.processing.org/bugs/show_bug.cgi?id=495
writer.println(val);
}
/**
* Write a line to the dxf file. Available for anyone who wants to
* insert additional commands into the DXF stream.
*/
public void println(String what) {
writer.println(what);
}
protected void writeLine(int index1, int index2) {
writer.println("0");
writer.println("LINE");
// write out the layer
writer.println("8");
writer.println(String.valueOf(currentLayer));
write("10", vertices[index1][X]);
write("20", vertices[index1][Y]);
write("30", vertices[index1][Z]);
write("11", vertices[index2][X]);
write("21", vertices[index2][Y]);
write("31", vertices[index2][Z]);
}
/*
protected void writeLineStrip() {
writeLine();
// shift the last vertex to be the first vertex
System.arraycopy(vertices[1], 0, vertices[0], 0, vertices[1].length);
vertexCount = 1;
}
*/
protected void writeTriangle() {
writer.println("0");
writer.println("3DFACE");
// write out the layer
writer.println("8");
/*
if (i < MAX_TRI_LAYERS) {
if (layerList[i] >= 0) {
currentLayer = layerList[i];
}
}
*/
writer.println(String.valueOf(currentLayer));
write("10", vertices[0][X]);
write("20", vertices[0][Y]);
write("30", vertices[0][Z]);
write("11", vertices[1][X]);
write("21", vertices[1][Y]);
write("31", vertices[1][Z]);
write("12", vertices[2][X]);
write("22", vertices[2][Y]);
write("32", vertices[2][Z]);
// Without adding EPSILON, Rhino kinda freaks out.
// A face is actually a quad, not a triangle,
// so instead kinda fudging the final point here.
write("13", vertices[2][X] + EPSILON);
write("23", vertices[2][Y] + EPSILON);
write("33", vertices[2][Z] + EPSILON);
vertexCount = 0;
}
// ..............................................................
public void beginShape(int kind) {
shape = kind;
if ((shape != LINES) &&
(shape != TRIANGLES) &&
(shape != POLYGON)) {
String err =
"RawDXF can only be used with beginRaw(), " +
"because it only supports lines and triangles";
throw new RuntimeException(err);
}
if ((shape == POLYGON) && fill) {
throw new RuntimeException("DXF Export only supports non-filled shapes.");
}
vertexCount = 0;
}
public void vertex(float x, float y) {
vertex(x, y, 0);
}
public void vertex(float x, float y, float z) {
float vertex[] = vertices[vertexCount];
vertex[X] = x; // note: not mx, my, mz like PGraphics3
vertex[Y] = y;
vertex[Z] = z;
if (fill) {
vertex[R] = fillR;
vertex[G] = fillG;
vertex[B] = fillB;
vertex[A] = fillA;
}
if (stroke) {
vertex[SR] = strokeR;
vertex[SG] = strokeG;
vertex[SB] = strokeB;
vertex[SA] = strokeA;
vertex[SW] = strokeWeight;
}
if (textureImage != null) { // for the future?
vertex[U] = textureU;
vertex[V] = textureV;
}
vertexCount++;
if ((shape == LINES) && (vertexCount == 2)) {
writeLine(0, 1);
vertexCount = 0;
/*
} else if ((shape == LINE_STRIP) && (vertexCount == 2)) {
writeLineStrip();
*/
} else if ((shape == TRIANGLES) && (vertexCount == 3)) {
writeTriangle();
}
}
public void endShape(int mode) {
if (shape == POLYGON) {
for (int i = 0; i < vertexCount - 1; i++) {
writeLine(i, i+1);
}
if (mode == CLOSE) {
writeLine(vertexCount - 1, 0);
}
}
/*
if ((vertexCount != 0) &&
((shape != LINE_STRIP) && (vertexCount != 1))) {
System.err.println("Extra vertex boogers found.");
}
*/
}
}

View File

@@ -0,0 +1,74 @@
<?xml version="1.0"?>
<project name="Processing Hardware I/O Library" default="build">
<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="library/io.jar" />
</target>
<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../../../core/library/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
<mkdir dir="bin" />
<javac source="1.8"
target="1.8"
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../../../core/library/core.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
../../mode/jdtCompilerAdapter.jar" />
</javac>
</target>
<target name="build" depends="compile" description="Build I/O library">
<jar basedir="bin" destfile="library/io.jar" />
</target>
<target name="dist" depends="build" description="Package standalone library">
<!-- set revision number as library version -->
<loadfile srcfile="../../../todo.txt" property="revision">
<filterchain>
<headfilter lines="1"/>
<tokenfilter>
<stringtokenizer suppressdelims="true"/>
<!-- grab the thing from the first line that's 4 digits -->
<containsregex pattern="(\d\d\d\d)" />
</tokenfilter>
</filterchain>
</loadfile>
<replaceregexp file="library.properties" match="version = .*" replace="version = ${revision}" flags="g" />
<replaceregexp file="library.properties" match="prettyVersion = .*" replace="prettyVersion = ${revision}" flags="g" />
<get src="http://download.processing.org/reference.zip"
dest="reference.zip"
usetimestamp="true" />
<mkdir dir="reference" />
<unzip dest="."
src="reference.zip"
overwrite="true">
<patternset>
<include name="reference/css/**" />
<include name="reference/img/**" />
<include name="reference/javascript/**" />
<include name="reference/libraries/io/**" />
</patternset>
</unzip>
<delete file="reference.zip" />
<echo file="reference/index.html" message="&lt;html&gt;&lt;head&gt;&lt;meta http-equiv='refresh' content='0; url=libraries/io/index.html'&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;" />
<zip destfile="../io.zip">
<zipfileset dir="." prefix="io">
<exclude name="bin/**"/>
</zipfileset>
</zip>
<copy file="library.properties"
toFile="../io.txt"/>
</target>
</project>

View File

@@ -0,0 +1,43 @@
import processing.io.*;
I2C i2c;
// HMC6352 is a digital compass module using I2C
// datasheet: https://www.sparkfun.com/datasheets/Components/HMC6352.pdf
// see setup.png in the sketch folder for wiring details
void setup() {
//printArray(I2C.list());
i2c = new I2C(I2C.list()[0]);
setHeadingMode();
}
void draw() {
background(255);
float deg = getHeading();
println(deg + " degrees");
line(width/2, height/2, width/2+sin(radians(deg))*width/2, height/2-cos(radians(deg))*height/2);
}
void setHeadingMode() {
i2c.beginTransmission(0x21);
// command byte for writing to EEPROM
i2c.write(0x77);
// address of the output data control byte
i2c.write(0x4e);
// give us the plain heading
i2c.write(0x00);
i2c.endTransmission();
}
float getHeading() {
i2c.beginTransmission(0x21);
// command byte for reading the data
i2c.write(0x41);
byte[] in = i2c.read(2);
i2c.endTransmission();
// put bytes together to tenth of degrees
// & 0xff makes sure the byte is not interpreted as a negative value
int deg = (in[0] & 0xff) << 8 | (in[1] & 0xff);
// return degrees
return deg / 10.0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

View File

@@ -0,0 +1,27 @@
import processing.io.*;
I2C i2c;
// MCP4725 is a Digital-to-Analog converter using I2C
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf
void setup() {
//printArray(I2C.list());
i2c = new I2C(I2C.list()[0]);
}
void draw() {
background(map(mouseX, 0, width, 0, 255));
setAnalog(map(mouseX, 0, width, 0.0, 1.0));
}
// outputs voltages from 0V to the supply voltage
// (works with 3.3V and 5V)
void setAnalog(float fac) {
fac = constrain(fac, 0.0, 1.0);
// convert to 12 bit value
int val = int(4095 * fac);
i2c.beginTransmission(0x60);
i2c.write(val >> 8);
i2c.write(val & 255);
i2c.endTransmission();
}

View File

@@ -0,0 +1,12 @@
import processing.io.*;
MCP4725 dac;
void setup() {
//printArray(I2C.list());
dac = new MCP4725(I2C.list()[0], 0x60);
}
void draw() {
background(map(mouseX, 0, width, 0, 255));
dac.setAnalog(map(mouseX, 0, width, 0.0, 1.0));
}

View File

@@ -0,0 +1,27 @@
import processing.io.I2C;
// MCP4725 is a Digital-to-Analog converter using I2C
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf
class MCP4725 extends I2C {
int address;
// there can be more than one device connected to the bus
// as long as they have different addresses
MCP4725(String dev, int address) {
super(dev);
this.address = address;
}
// outputs voltages from 0V to the supply voltage
// (works with 3.3V and 5V)
void setAnalog(float fac) {
fac = constrain(fac, 0.0, 1.0);
// convert to 12 bit value
int val = int(4095 * fac);
beginTransmission(address);
write(val >> 8);
write(val & 255);
endTransmission();
}
}

View File

@@ -0,0 +1,22 @@
import processing.io.*;
// 0.96" 128x64 OLED display ("SKU 346540")
SSD1306 oled;
void setup() {
size(128, 64);
// the display can be set to one of these two addresses: 0x3c (default) or 0x3d
// (they might be listed as 0x7a and 0x7b on the circuit board)
// you might need to use a different interface on other SBCs
oled = new SSD1306("i2c-1", 0x3c);
}
void draw() {
background(0);
stroke(255);
line(0, 0, 127, 63);
line(0, 63, 127, 0);
oled.sendImage(get());
}

View File

@@ -0,0 +1,118 @@
import processing.io.I2C;
// SSD1306 is a small, inexpensive 128x64 pixels monochrome OLED display
// available online as "0.96" 128x64 OLED display", SKU 346540
// or from Adafruit
// datasheet: https://www.adafruit.com/datasheets/SSD1306.pdf
class SSD1306 extends I2C {
int address;
// there can be more than one device connected to the bus
// as long as they have different addresses
SSD1306(String dev, int address) {
super(dev);
this.address = address;
init();
}
protected void init() {
writeCommand(0xae); // turn display off
writeCommand(0xa8, 0x3f); // set multiplex ratio to the highest setting
writeCommand(0x8d, 0x14); // enable charge pump
writeCommand(0x20, 0x00); // set memory addressing mode to horizontal
writeCommand(0xd5, 0x80); // set display clock divide ratio & oscillator frequency to default
writeCommand(0xd3, 0x00); // no display offset
writeCommand(0x40 | 0x00); // set default display start line
// use the following two lines to flip the display
writeCommand(0xa0 | 0x01); // set segment re-map
writeCommand(0xc8); // set COM output scan direction
writeCommand(0xda, 0x12); // set COM pins hardware configuration
writeCommand(0xd9, 0xf1); // set pre-charge period to 241x DCLK
writeCommand(0xdB, 0x40); // set VCOMH deselect level
writeCommand(0xa4); // display RAM content (not all-on)
writeCommand(0xa6); // set normal (not-inverted) display
// set this since we don't have access to the OLED's reset pins (?)
writeCommand(0x21, 0, 127); // set column address
writeCommand(0x22, 0, 7); // set page address
writeCommand(0x81, 0xcf); // set contrast
writeCommand(0x2e); // deactivate scroll
writeCommand(0xaf); // turn display on
}
void invert(boolean inverted) {
if (inverted) {
writeCommand(0xa7);
} else {
writeCommand(0xa6);
}
}
void sendImage(PImage img) {
sendImage(img, 0, 0);
}
void sendImage(PImage img, int startX, int startY) {
byte[] frame = new byte[1024];
img.loadPixels();
for (int y=startY; y < height && y-startY < 64; y++) {
for (int x=startX; x < width && x-startX < 128; x++) {
if (128 <= brightness(img.pixels[y*img.width+x])) {
// this isn't the normal (scanline) mapping, but 8 pixels below each other at a time
// white pixels have their bit turned on
frame[x + (y/8)*128] |= (1 << (y % 8));
}
}
}
sendFramebuffer(frame);
}
void sendFramebuffer(byte[] buf) {
if (buf.length != 1024) {
System.err.println("The framebuffer should be 1024 bytes long, with one bit per pixel");
throw new IllegalArgumentException("Unexpected buffer size");
}
writeCommand(0x00 | 0x0); // set start address
writeCommand(0x10 | 0x0); // set higher column start address
writeCommand(0x40 | 0x0); // set start line
// send the frame buffer as 16 byte long packets
for (int i=0; i < buf.length/16; i++) {
super.beginTransmission(address);
super.write(0x40); // indicates data write
for (int j=0; j < 16; j++) {
super.write(buf[i*16+j]);
}
super.endTransmission();
}
}
protected void writeCommand(int arg1) {
super.beginTransmission(address);
super.write(0x00); // indicates command write
super.write(arg1);
super.endTransmission();
}
protected void writeCommand(int arg1, int arg2) {
super.beginTransmission(address);
super.write(0x00);
super.write(arg1);
super.write(arg2);
super.endTransmission();
}
protected void writeCommand(int arg1, int arg2, int arg3) {
super.beginTransmission(address);
super.write(0x00);
super.write(arg1);
super.write(arg2);
super.write(arg3);
super.endTransmission();
}
}

View File

@@ -0,0 +1,25 @@
import processing.io.*;
color bgcolor = 0;
// GPIO numbers refer to different phyiscal pins on various boards
// On the Raspberry Pi GPIO 4 is physical pin 7 on the header
// see setup.png in the sketch folder for wiring details
void setup() {
GPIO.pinMode(4, GPIO.INPUT);
GPIO.attachInterrupt(4, this, "pinEvent", GPIO.RISING);
}
void draw() {
background(bgcolor);
}
// this function will be called whenever GPIO 4 is brought from LOW to HIGH
void pinEvent(int pin) {
println("Received interrupt");
if (bgcolor == 0) {
bgcolor = color(255);
} else {
bgcolor = color(0);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

View File

@@ -0,0 +1,39 @@
import processing.io.*;
LED leds[];
// the Raspberry Pi has two build-in LEDs we can control
// led0 (green) and led1 (red)
void setup() {
String available[] = LED.list();
print("Available: ");
println(available);
// create an object for each LED and store it in an array
leds = new LED[available.length];
for (int i=0; i < available.length; i++) {
leds[i] = new LED(available[i]);
}
frameRate(1);
}
void draw() {
// make the LEDs count in binary
for (int i=0; i < leds.length; i++) {
if ((frameCount & (1 << i)) != 0) {
leds[i].brightness(1.0);
} else {
leds[i].brightness(0.0);
}
}
println(frameCount);
}
void keyPressed() {
// cleanup
for (int i=0; i < leds.length; i++) {
leds[i].close();
}
exit();
}

View File

@@ -0,0 +1,22 @@
import processing.io.*;
SPI spi;
// MCP3001 is a Analog-to-Digital converter using SPI
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf
// see setup.png in the sketch folder for wiring details
void setup() {
//printArray(SPI.list());
spi = new SPI(SPI.list()[0]);
spi.settings(500000, SPI.MSBFIRST, SPI.MODE0);
}
void draw() {
// dummy write, actual values don't matter
byte[] out = { 0, 0 };
byte[] in = spi.transfer(out);
// some input bit shifting according to the datasheet p. 16
int val = ((in[0] & 0x1f) << 5) | ((in[1] & 0xf8) >> 3);
// val is between 0 and 1023
background(map(val, 0, 1023, 0, 255));
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,22 @@
import processing.io.SPI;
// MCP3001 is a Analog-to-Digital converter using SPI
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf
class MCP3001 extends SPI {
MCP3001(String dev) {
super(dev);
settings(500000, SPI.MSBFIRST, SPI.MODE0);
}
float getAnalog() {
// dummy write, actual values don't matter
byte[] out = { 0, 0 };
byte[] in = transfer(out);
// some input bit shifting according to the datasheet p. 16
int val = ((in[0] & 0x1f) << 5) | ((in[1] & 0xf8) >> 3);
// val is between 0 and 1023
return val/1023.0;
}
}

View File

@@ -0,0 +1,13 @@
import processing.io.*;
MCP3001 adc;
// see setup.png in the sketch folder for wiring details
void setup() {
//printArray(SPI.list());
adc = new MCP3001(SPI.list()[0]);
}
void draw() {
background(adc.getAnalog() * 255);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,27 @@
import processing.io.SPI;
// MCP3008 is a Analog-to-Digital converter using SPI
// other than the MCP3001, this has 8 input channels
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf
class MCP3008 extends SPI {
MCP3008(String dev) {
super(dev);
settings(500000, SPI.MSBFIRST, SPI.MODE0);
}
float getAnalog(int channel) {
if (channel < 0 || 7 < channel) {
System.err.println("The channel needs to be from 0 to 7");
throw new IllegalArgumentException("Unexpected channel");
}
byte[] out = { 0, 0, 0 };
// encode the channel number in the first byte
out[0] = (byte)(0x18 | channel);
byte[] in = transfer(out);
int val = ((in[1] & 0x03) << 8) | (in[2] & 0xff);
// val is between 0 and 1023
return val/1023.0;
}
}

View File

@@ -0,0 +1,15 @@
import processing.io.*;
MCP3008 adc;
// see setup.png in the sketch folder for wiring details
void setup() {
//printArray(SPI.list());
adc = new MCP3008(SPI.list()[0]);
}
void draw() {
background(adc.getAnalog(0) * 255);
fill(adc.getAnalog(1) * 255);
ellipse(width/2, height/2, width * 0.75, width * 0.75);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -0,0 +1,34 @@
import processing.io.*;
// see setup.png in the sketch folder for wiring details
// for more reliable operation it is recommended to power
// the servo from an external power source, see setup_better.png
SoftwareServo servo1;
SoftwareServo servo2;
void setup() {
size(400, 300);
servo1 = new SoftwareServo(this);
servo1.attach(17);
servo2 = new SoftwareServo(this);
servo2.attach(4);
}
void draw() {
background(0);
stroke(255);
strokeWeight(3);
// we don't go right to the edge to prevent
// making the servo unhappy
float angle = 90 + sin(frameCount / 100.0)*85;
servo1.write(angle);
float y = map(angle, 0, 180, 0, height);
line(0, y, width/2, y);
angle = 90 + cos(frameCount / 100.0)*85;
servo2.write(90 + cos(frameCount / 100.0)*85);
y = map(angle, 0, 180, 0, height);
line(width/2, y, width, y);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -0,0 +1,20 @@
import processing.io.*;
// GPIO numbers refer to different phyiscal pins on various boards
// On the Raspberry Pi GPIO 4 is physical pin 7 on the header
// see setup.png in the sketch folder for wiring details
void setup() {
GPIO.pinMode(4, GPIO.INPUT);
}
void draw() {
// sense the input pin
if (GPIO.digitalRead(4) == GPIO.HIGH) {
fill(255);
} else {
fill(204);
}
stroke(255);
ellipse(width/2, height/2, width*0.75, height*0.75);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

View File

@@ -0,0 +1,25 @@
import processing.io.*;
boolean ledOn = false;
// GPIO numbers refer to different phyiscal pins on various boards
// On the Raspberry Pi GPIO 4 is physical pin 7 on the header
// see setup.png in the sketch folder for wiring details
void setup() {
GPIO.pinMode(4, GPIO.OUTPUT);
frameRate(0.5);
}
void draw() {
// make the LED blink
ledOn = !ledOn;
if (ledOn) {
GPIO.digitalWrite(4, GPIO.LOW);
fill(204);
} else {
GPIO.digitalWrite(4, GPIO.HIGH);
fill(255);
}
stroke(255);
ellipse(width/2, height/2, width*0.75, height*0.75);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

View File

@@ -0,0 +1,56 @@
import processing.io.*;
// using a capacitor that gets charged and discharged, while
// measuring the time it takes, is an inexpensive way to
// read the value of an (analog) resistive sensor, such as
// a photocell
// kudos to ladyada for the original tutorial
// see setup.png in the sketch folder for wiring details
int max = 0;
int min = 9999;
void setup() {
}
void draw() {
int val = sensorRead(4);
println(val);
// track largest and smallest reading, to get a sense
// how we compare
if (max < val) {
max = val;
}
if (val < min) {
min = val;
}
// convert current reading into a number between 0.0 and 1.0
float frac = map(val, min, max, 0.0, 1.0);
background(255 * frac);
}
int sensorRead(int pin) {
// discharge the capacitor
GPIO.pinMode(pin, GPIO.OUTPUT);
GPIO.digitalWrite(pin, GPIO.LOW);
delay(100);
// now the capacitor should be empty
// measure the time takes to fill it
// up to ~ 1.4V again
GPIO.pinMode(pin, GPIO.INPUT);
int start = millis();
while (GPIO.digitalRead(pin) == GPIO.LOW) {
// wait
}
// return the time elapsed
// this will vary based on the value of the
// resistive sensor (lower resistance will
// make the capacitor charge faster)
return millis() - start;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -0,0 +1,9 @@
name = Hardware I/O
authors = The Processing Foundation
url = http://processing.org/reference/libraries/io/index.html
categories = Hardware
sentence = Access peripherals on the Raspberry Pi and other Linux-based computers.
paragraph = For other platforms, this is solely provided in order to build and export sketches that require processing.io.
version = 1
prettyVersion = 1
minRevision = 247

View File

@@ -0,0 +1 @@
name = Hardware I/O for Raspberry Pi and other Linux-based computers

View File

@@ -0,0 +1,20 @@
TARGET := libprocessing-io.so
OBJS := impl.o
CC := gcc
# prefix with -m32 to compile for linux32
CFLAGS := -std=gnu99 -fPIC -g -ffast-math
CFLAGS += -I$(shell dirname $(shell realpath $(shell which javac)))/../include
CFLAGS += -I$(shell dirname $(shell realpath $(shell which javac)))/../include/linux
LDFLAGS := -shared
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
iface.h:
javah -classpath .. -o iface.h processing.io.NativeInterface
clean:
rm -f $(TARGET) $(OBJS)
.PHONY: iface.h clean

View File

@@ -0,0 +1,109 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class processing_io_NativeInterface */
#ifndef _Included_processing_io_NativeInterface
#define _Included_processing_io_NativeInterface
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: processing_io_NativeInterface
* Method: openDevice
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_openDevice
(JNIEnv *, jclass, jstring);
/*
* Class: processing_io_NativeInterface
* Method: getError
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_processing_io_NativeInterface_getError
(JNIEnv *, jclass, jint);
/*
* Class: processing_io_NativeInterface
* Method: closeDevice
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_closeDevice
(JNIEnv *, jclass, jint);
/*
* Class: processing_io_NativeInterface
* Method: readFile
* Signature: (Ljava/lang/String;[B)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_readFile
(JNIEnv *, jclass, jstring, jbyteArray);
/*
* Class: processing_io_NativeInterface
* Method: writeFile
* Signature: (Ljava/lang/String;[B)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_writeFile
(JNIEnv *, jclass, jstring, jbyteArray);
/*
* Class: processing_io_NativeInterface
* Method: pollDevice
* Signature: (Ljava/lang/String;I)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_pollDevice
(JNIEnv *, jclass, jstring, jint);
/*
* Class: processing_io_NativeInterface
* Method: transferI2c
* Signature: (II[B[B)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_transferI2c
(JNIEnv *, jclass, jint, jint, jbyteArray, jbyteArray);
/*
* Class: processing_io_NativeInterface
* Method: servoStartThread
* Signature: (III)J
*/
JNIEXPORT jlong JNICALL Java_processing_io_NativeInterface_servoStartThread
(JNIEnv *, jclass, jint, jint, jint);
/*
* Class: processing_io_NativeInterface
* Method: servoUpdateThread
* Signature: (JII)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_servoUpdateThread
(JNIEnv *, jclass, jlong, jint, jint);
/*
* Class: processing_io_NativeInterface
* Method: servoStopThread
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_servoStopThread
(JNIEnv *, jclass, jlong);
/*
* Class: processing_io_NativeInterface
* Method: setSpiSettings
* Signature: (IIII)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_setSpiSettings
(JNIEnv *, jclass, jint, jint, jint, jint);
/*
* Class: processing_io_NativeInterface
* Method: transferSpi
* Signature: (I[B[B)I
*/
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_transferSpi
(JNIEnv *, jclass, jint, jbyteArray, jbyteArray);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,344 @@
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#include <errno.h>
#include <fcntl.h>
#include <jni.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/spi/spidev.h>
#include <poll.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <time.h>
#include <unistd.h>
#include "iface.h"
static const int servo_pulse_oversleep = 35; // amount of uS to account for when sleeping
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_openDevice
(JNIEnv *env, jclass cls, jstring _fn)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_RDWR);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
} else {
return file;
}
}
JNIEXPORT jstring JNICALL Java_processing_io_NativeInterface_getError
(JNIEnv *env, jclass cls, jint _errno)
{
char *msg = strerror(abs(_errno));
if (msg) {
return (*env)->NewStringUTF(env, msg);
} else {
return NULL;
}
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_closeDevice
(JNIEnv *env, jclass cls, jint handle)
{
if (close(handle) < 0) {
return -errno;
} else {
return 0;
}
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_readFile
(JNIEnv *env, jclass cls, jstring _fn, jbyteArray _in)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_RDONLY);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
}
jbyte *in = (*env)->GetByteArrayElements(env, _in, NULL);
int len = read(file, in, (*env)->GetArrayLength(env, _in));
if (len < 0) {
len = -errno;
}
(*env)->ReleaseByteArrayElements(env, _in, in, 0);
close(file);
return len;
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_writeFile
(JNIEnv *env, jclass cls, jstring _fn, jbyteArray _out)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_WRONLY);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
}
jbyte *out = (*env)->GetByteArrayElements(env, _out, JNI_FALSE);
int len = write(file, out, (*env)->GetArrayLength(env, _out));
if (len < 0) {
len = -errno;
}
(*env)->ReleaseByteArrayElements(env, _out, out, JNI_ABORT);
close(file);
return len;
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_pollDevice
(JNIEnv *env, jclass cls, jstring _fn, jint timeout)
{
const char *fn = (*env)->GetStringUTFChars(env, _fn, JNI_FALSE);
int file = open(fn, O_RDONLY|O_NONBLOCK);
(*env)->ReleaseStringUTFChars(env, _fn, fn);
if (file < 0) {
return -errno;
}
// dummy read
char tmp;
while (0 < read(file, &tmp, 1));
struct pollfd fds[1];
memset(fds, 0, sizeof(fds));
fds[0].fd = file;
fds[0].events = POLLPRI|POLLERR;
// and wait
int ret = poll(fds, 1, timeout);
close(file);
if (ret < 0) {
return -errno;
} else if (ret == 0) {
// timeout
return 0;
} else if (fds[0].revents & POLLPRI) {
// interrupt
return 1;
} else {
// POLLERR?
return -ENOMSG;
}
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_transferI2c
(JNIEnv *env, jclass cls, jint handle, jint slave, jbyteArray _out, jbyteArray _in)
{
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg msgs[2];
jbyte *out, *in;
packets.msgs = msgs;
msgs[0].addr = slave;
msgs[0].flags = 0;
msgs[0].len = (*env)->GetArrayLength(env, _out);
out = (*env)->GetByteArrayElements(env, _out, NULL);
msgs[0].buf = out;
if (_in != NULL) {
in = (*env)->GetByteArrayElements(env, _in, NULL);
msgs[1].addr = slave;
msgs[1].flags = I2C_M_RD; // I2C_M_RECV_LEN is not supported
msgs[1].len = (*env)->GetArrayLength(env, _in);
msgs[1].buf = in;
packets.nmsgs = 2;
} else {
packets.nmsgs = 1;
}
int ret = ioctl(handle, I2C_RDWR, &packets);
if (ret < 0) {
ret = -errno;
}
(*env)->ReleaseByteArrayElements(env, _out, out, JNI_ABORT);
if (_in != NULL) {
(*env)->ReleaseByteArrayElements(env, _in, in, 0);
}
return ret;
}
typedef struct {
int fd;
pthread_t thread;
int pulse;
int period;
} SERVO_STATE_T;
static void* servoThread(void *ptr) {
SERVO_STATE_T *state = (SERVO_STATE_T*)ptr;
struct timespec on, off;
on.tv_sec = 0;
off.tv_sec = 0;
do {
write(state->fd, "1", 1);
on.tv_nsec = state->pulse * 1000;
nanosleep(&on, NULL);
write(state->fd, "0", 1);
off.tv_nsec = (state->period - state->pulse) * 1000;
nanosleep(&off, NULL);
} while (1);
}
JNIEXPORT jlong JNICALL Java_processing_io_NativeInterface_servoStartThread
(JNIEnv *env, jclass cls, jint gpio, jint pulse, jint period)
{
char path[26 + 19 + 1];
int fd;
pthread_t thread;
// setup struct holding our state
SERVO_STATE_T *state = malloc(sizeof(SERVO_STATE_T));
if (!state) {
return -ENOMEM;
}
memset(state, 0, sizeof(*state));
state->pulse = (pulse - servo_pulse_oversleep > 0) ? pulse - servo_pulse_oversleep : 0;
// we're obviously also oversleeping in the general period case
// but other than the pulse, this doesn't seem to be crucial with servos
state->period = period;
// open gpio
sprintf(path, "/sys/class/gpio/gpio%d/value", gpio);
state->fd = open(path, O_WRONLY);
if (state->fd < 0) {
free(state);
return -errno;
}
// start thread
int ret = pthread_create(&state->thread, NULL, servoThread, state);
if (ret != 0) {
free(state);
return -ret;
}
// set scheduling policy and priority
struct sched_param param;
param.sched_priority = 75;
ret = pthread_setschedparam(state->thread, SCHED_FIFO, &param);
if (ret != 0) {
fprintf(stderr, "Error setting thread policy: %s\n", strerror(ret));
}
return (intptr_t)state;
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_servoUpdateThread
(JNIEnv *env, jclass cls, jlong handle, jint pulse, jint period)
{
SERVO_STATE_T *state = (SERVO_STATE_T*)(intptr_t)handle;
state->pulse = (pulse - servo_pulse_oversleep > 0) ? pulse - servo_pulse_oversleep : 0;
state->period = period;
return 0;
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_servoStopThread
(JNIEnv *env, jclass cls, jlong handle)
{
SERVO_STATE_T *state = (SERVO_STATE_T*)(intptr_t)handle;
// signal thread to stop
pthread_cancel(state->thread);
pthread_join(state->thread, NULL);
close(state->fd);
free(state);
return 0;
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_setSpiSettings
(JNIEnv *env, jclass cls, jint handle, jint _maxSpeed, jint dataOrder, jint mode)
{
uint8_t tmp;
uint32_t maxSpeed;
tmp = (uint8_t)mode;
int ret = ioctl(handle, SPI_IOC_WR_MODE, &tmp);
if (ret < 0) {
return ret;
}
tmp = (uint8_t)dataOrder;
ret = ioctl(handle, SPI_IOC_WR_LSB_FIRST, &tmp);
if (ret < 0) {
return ret;
}
maxSpeed = (uint32_t)_maxSpeed;
ret = ioctl(handle, SPI_IOC_WR_MAX_SPEED_HZ, &maxSpeed);
if (ret < 0) {
return ret;
}
return 0;
}
JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_transferSpi
(JNIEnv *env, jclass cls, jint handle, jbyteArray _out, jbyteArray _in)
{
jbyte* out = (*env)->GetByteArrayElements(env, _out, NULL);
jbyte* in = (*env)->GetByteArrayElements(env, _in, NULL);
struct spi_ioc_transfer xfer = {
.tx_buf = (unsigned long)out,
.rx_buf = (unsigned long)in,
.len = MIN((*env)->GetArrayLength(env, _out), (*env)->GetArrayLength(env, _in)),
};
int ret = ioctl(handle, SPI_IOC_MESSAGE(1), &xfer);
(*env)->ReleaseByteArrayElements(env, _out, out, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, _in, in, 0);
return ret;
}

View File

@@ -0,0 +1,514 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
import processing.core.*;
import processing.io.NativeInterface;
import java.lang.reflect.Method;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
/**
* @webref
*/
public class GPIO {
// those constants are generally the same as in Arduino.h
public static final int INPUT = 0;
public static final int OUTPUT = 1;
public static final int INPUT_PULLUP = 2;
public static final int INPUT_PULLDOWN = 3;
public static final int LOW = 0;
public static final int HIGH = 1;
public static final int NONE = 0;
/**
* trigger when level changes
*/
public static final int CHANGE = 1;
/**
* trigger when level changes from high to low
*/
public static final int FALLING = 2;
/**
* trigger when level changes from low to high
*/
public static final int RISING = 3;
protected static Map<Integer, Thread> irqThreads = new HashMap<Integer, Thread>();
protected static boolean serveInterrupts = true;
protected static BitSet values = new BitSet();
static {
NativeInterface.loadLibrary();
}
public static void analogWrite(int pin, int value) {
// currently this can't be done in a non-platform-specific way
// the best way forward would be implementing a generic, "soft"
// PWM in the kernel that uses high resolution timers, similiar
// to the patch Bill Gatliff posted, which unfortunately didn't
// get picked up, see
// https://dev.openwrt.org/browser/trunk/target/linux/generic/files/drivers/pwm/gpio-pwm.c?rev=35328
// additionally, there currently doesn't seem to be a way to link
// a PWM channel back to the GPIO pin it is associated with
// alternatively, this could be implemented in user-space to some
// degree
// see http://stackoverflow.com/a/13371570/3030124
// see http://raspberrypi.stackexchange.com/a/304
throw new RuntimeException("Not yet implemented");
}
/**
* Calls a function when the value of an input pin changes
* @param pin GPIO pin
* @param parent typically use "this"
* @param method name of sketch method to call
* @param mode when to call: GPIO.CHANGE, GPIO.FALLING or GPIO.RISING
* @see noInterrupts
* @see interrupts
* @see releaseInterrupt
* @webref
*/
public static void attachInterrupt(int pin, PApplet parent, String method, int mode) {
if (irqThreads.containsKey(pin)) {
throw new RuntimeException("You must call releaseInterrupt before attaching another interrupt on the same pin");
}
enableInterrupt(pin, mode);
final int irqPin = pin;
final PApplet irqObject = parent;
final Method irqMethod;
try {
irqMethod = parent.getClass().getMethod(method, int.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Method " + method + " does not exist");
}
// it might be worth checking how Java threads compare to pthreads in terms
// of latency
Thread t = new Thread(new Runnable() {
public void run() {
boolean gotInterrupt = false;
try {
do {
try {
if (waitForInterrupt(irqPin, 100)) {
gotInterrupt = true;
}
if (gotInterrupt && serveInterrupts) {
irqMethod.invoke(irqObject, irqPin);
gotInterrupt = false;
}
// if we received an interrupt while interrupts were disabled
// we still deliver it the next time interrupts get enabled
// not sure if everyone agrees with this logic though
} catch (RuntimeException e) {
// make sure we're not busy spinning on error
Thread.sleep(100);
}
} while (!Thread.currentThread().isInterrupted());
} catch (Exception e) {
// terminate the thread on any unexpected exception that might occur
System.err.println("Terminating interrupt handling for pin " + irqPin + " after catching: " + e.getMessage());
}
}
}, "GPIO" + pin + " IRQ");
t.setPriority(Thread.MAX_PRIORITY);
t.start();
irqThreads.put(pin, t);
}
/**
* Checks if the GPIO pin number can be valid
*
* Board-specific classes, such as RPI, assign -1 to pins that carry power,
* ground and the like.
* @param pin GPIO pin
*/
protected static void checkValidPin(int pin) {
if (pin < 0) {
throw new RuntimeException("Operation not supported on this pin");
}
}
/**
* Returns the value of an input pin
* @param pin GPIO pin
* @return GPIO.HIGH (1) or GPIO.LOW (0)
* @see pinMode
* @see digitalWrite
* @webref
*/
public static int digitalRead(int pin) {
checkValidPin(pin);
if (NativeInterface.isSimulated()) {
return LOW;
}
String fn = String.format("/sys/class/gpio/gpio%d/value", pin);
byte in[] = new byte[2];
int ret = NativeInterface.readFile(fn, in);
if (ret < 0) {
throw new RuntimeException(NativeInterface.getError(ret));
} else if (1 <= ret && in[0] == '0') {
return LOW;
} else if (1 <= ret && in[0] == '1') {
return HIGH;
} else {
System.err.print("Read " + ret + " bytes");
if (0 < ret) {
System.err.format(", first byte is 0x%02x" + in[0]);
}
System.err.println();
throw new RuntimeException("Unexpected value");
}
}
/**
* Sets an output pin to be either high or low
* @param pin GPIO pin
* @param value GPIO.HIGH (1) or GPIO.LOW (0)
* @see pinMode
* @see digitalRead
* @webref
*/
public static void digitalWrite(int pin, int value) {
checkValidPin(pin);
String out;
if (value == LOW) {
// values are also stored in a bitmap to make it possible to set a
// default level per pin before enabling the output
values.clear(pin);
out = "0";
} else if (value == HIGH) {
values.set(pin);
out = "1";
} else {
System.err.println("Only GPIO.LOW and GPIO.HIGH, 0 and 1, or true and false, can be used.");
throw new IllegalArgumentException("Illegal value");
}
if (NativeInterface.isSimulated()) {
return;
}
String fn = String.format("/sys/class/gpio/gpio%d/value", pin);
int ret = NativeInterface.writeFile(fn, out);
if (ret < 0) {
if (ret != -2) { // ENOENT, pin might not yet be exported
throw new RuntimeException(NativeInterface.getError(ret));
}
}
}
/**
* @param value true or false
*/
public static void digitalWrite(int pin, boolean value) {
if (value) {
digitalWrite(pin, HIGH);
} else {
digitalWrite(pin, LOW);
}
}
/**
* Disables an interrupt for an input pin
* @param pin GPIO pin
* @see enableInterrupt
* @see waitForInterrupt
*/
protected static void disableInterrupt(int pin) {
enableInterrupt(pin, NONE);
}
/**
* Enables an interrupt for an input pin
* @param pin GPIO pin
* @param mode what to wait for: GPIO.CHANGE, GPIO.FALLING or GPIO.RISING
* @see waitForInterrupt
* @see disableInterrupt
*/
protected static void enableInterrupt(int pin, int mode) {
checkValidPin(pin);
String out;
if (mode == NONE) {
out = "none";
} else if (mode == CHANGE) {
out = "both";
} else if (mode == FALLING) {
out = "falling";
} else if (mode == RISING) {
out = "rising";
} else {
throw new IllegalArgumentException("Unknown mode");
}
if (NativeInterface.isSimulated()) {
return;
}
String fn = String.format("/sys/class/gpio/gpio%d/edge", pin);
int ret = NativeInterface.writeFile(fn, out);
if (ret < 0) {
if (ret == -2) { // ENOENT
System.err.println("Make sure your called pinMode on the input pin");
}
throw new RuntimeException(NativeInterface.getError(ret));
}
}
/**
* Allows interrupts to happen
* @see attachInterrupt
* @see noInterrupts
* @see releaseInterrupt
* @webref
*/
public static void interrupts() {
serveInterrupts = true;
}
/**
* Prevents interrupts from happpening
* @see attachInterrupt
* @see interrupts
* @see releaseInterrupt
* @webref
*/
public static void noInterrupts() {
serveInterrupts = false;
}
/**
* Configures a pin to act either as input or output
* @param pin GPIO pin
* @param mode GPIO.INPUT or GPIO.OUTPUT
* @see digitalRead
* @see digitalWrite
* @see releasePin
* @webref
*/
public static void pinMode(int pin, int mode) {
checkValidPin(pin);
if (NativeInterface.isSimulated()) {
return;
}
// export pin through sysfs
String fn = "/sys/class/gpio/export";
int ret = NativeInterface.writeFile(fn, Integer.toString(pin));
if (ret < 0) {
if (ret == -2) { // ENOENT
System.err.println("Make sure your kernel is compiled with GPIO_SYSFS enabled");
}
if (ret == -22) { // EINVAL
System.err.println("GPIO pin " + pin + " does not seem to be available on your platform");
}
if (ret != -16) { // EBUSY, returned when the pin is already exported
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
}
// delay to give udev a chance to change the file permissions behind our back
// there should really be a cleaner way for this
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// set direction and default level for outputs
fn = String.format("/sys/class/gpio/gpio%d/direction", pin);
String out;
if (mode == INPUT) {
out = "in";
} else if (mode == OUTPUT) {
if (values.get(pin)) {
out = "high";
} else {
out = "low";
}
} else if (mode == INPUT_PULLUP || mode == INPUT_PULLDOWN) {
// currently this can't be done in a non-platform-specific way, see
// http://lists.infradead.org/pipermail/linux-rpi-kernel/2015-August/002146.html
throw new RuntimeException("Not yet implemented");
} else {
throw new IllegalArgumentException("Unknown mode");
}
ret = NativeInterface.writeFile(fn, out);
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
}
/**
* Stops listening for interrupts on an input pin
* @param pin GPIO pin
* @see attachInterrupt
* @see noInterrupts
* @see interrupts
* @webref
*/
public static void releaseInterrupt(int pin) {
Thread t = irqThreads.get(pin);
if (t == null) {
return;
}
t.interrupt();
try {
t.join();
} catch (InterruptedException e) {
System.err.println("Error joining thread in releaseInterrupt: " + e.getMessage());
}
t = null;
irqThreads.remove(pin);
disableInterrupt(pin);
}
/**
* Gives ownership of a pin back to the operating system
* @param pin GPIO pin
* @see pinMode
* @webref
*/
public static void releasePin(int pin) {
checkValidPin(pin);
if (NativeInterface.isSimulated()) {
return;
}
String fn = "/sys/class/gpio/unexport";
int ret = NativeInterface.writeFile(fn, Integer.toString(pin));
if (ret < 0) {
if (ret == -2) { // ENOENT
System.err.println("Make sure your kernel is compiled with GPIO_SYSFS enabled");
}
// EINVAL is returned when trying to unexport pins that weren't exported to begin with, ignore this case
if (ret != -22) {
throw new RuntimeException(NativeInterface.getError(ret));
}
}
}
/**
* Waits for the value of an input pin to change
* @param pin GPIO pin
* @param mode what to wait for: GPIO.CHANGE, GPIO.FALLING or GPIO.RISING
* @webref
*/
public static void waitFor(int pin, int mode) {
waitFor(pin, mode, -1);
}
/**
* Waits for the value of an input pin to change
*
* This function will throw a RuntimeException in case of a timeout.
* @param timeout don't wait more than timeout milliseconds
* @webref
*/
public static void waitFor(int pin, int mode, int timeout) {
enableInterrupt(pin, mode);
if (waitForInterrupt(pin, timeout) == false) {
throw new RuntimeException("Timeout occurred");
}
}
public static boolean waitForInterrupt(int pin, int mode, int timeout) {
throw new RuntimeException("The waitForInterrupt function has been renamed to waitFor. Please update your sketch accordingly.");
}
/**
* Waits for the value of an input pin to change
*
* Make sure to setup the interrupt with enableInterrupt() before calling
* this function. A timeout value of -1 waits indefinitely.
* @param pin GPIO pin
* @param timeout don't wait more than timeout milliseconds
* @return true if the interrupt occured, false if the timeout occured
* @see enableInterrupt
* @see disableInterrupt
*/
protected static boolean waitForInterrupt(int pin, int timeout) {
checkValidPin(pin);
if (NativeInterface.isSimulated()) {
// pretend the interrupt happens after 200ms
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
return true;
}
String fn = String.format("/sys/class/gpio/gpio%d/value", pin);
int ret = NativeInterface.pollDevice(fn, timeout);
if (ret < 0) {
if (ret == -2) { // ENOENT
System.err.println("Make sure your called pinMode on the input pin");
}
throw new RuntimeException(NativeInterface.getError(ret));
} else if (ret == 0) {
// timeout
return false;
} else {
// interrupt
return true;
}
}
}

View File

@@ -0,0 +1,262 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
import processing.io.NativeInterface;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @webref
*/
public class I2C {
protected String dev;
protected int handle;
protected int slave;
protected byte[] out;
protected boolean transmitting;
/**
* Opens an I2C interface as master
* @param dev interface name
* @see list
* @webref
*/
public I2C(String dev) {
NativeInterface.loadLibrary();
this.dev = dev;
if (NativeInterface.isSimulated()) {
return;
}
handle = NativeInterface.openDevice("/dev/" + dev);
if (handle < 0) {
throw new RuntimeException(NativeInterface.getError(handle));
}
}
/**
* Begins a transmission to an attached device
* @see write
* @see read
* @see endTransmission
* @webref
*/
public void beginTransmission(int slave) {
// addresses 120 (0x78) to 127 are additionally reserved
if (0x78 <= slave) {
System.err.println("beginTransmission expects a 7 bit address, try shifting one bit to the right");
throw new IllegalArgumentException("Illegal address");
}
this.slave = slave;
transmitting = true;
out = null;
}
/**
* Closes the I2C device
* @webref
*/
public void close() {
if (NativeInterface.isSimulated()) {
return;
}
NativeInterface.closeDevice(handle);
handle = 0;
}
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
/**
* Ends the current transmissions
* @see beginTransmission
* @see write
* @webref
*/
public void endTransmission() {
if (!transmitting) {
// silently ignore this case
return;
}
if (NativeInterface.isSimulated()) {
return;
}
// implement these flags if needed: https://github.com/raspberrypi/linux/blob/rpi-patches/Documentation/i2c/i2c-protocol
int ret = NativeInterface.transferI2c(handle, slave, out, null);
transmitting = false;
out = null;
if (ret < 0) {
if (ret == -5) { // EIO
System.err.println("The device did not respond. Check the cabling and whether you are using the correct address.");
}
throw new RuntimeException(NativeInterface.getError(ret));
}
}
/**
* Lists all available I2C interfaces
* @return String array
* @webref
*/
public static String[] list() {
if (NativeInterface.isSimulated()) {
// as on the Raspberry Pi
return new String[]{ "i2c-1" };
}
ArrayList<String> devs = new ArrayList<String>();
File dir = new File("/dev");
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.getName().startsWith("i2c-")) {
devs.add(file.getName());
}
}
}
// listFiles() does not guarantee ordering
String[] tmp = devs.toArray(new String[devs.size()]);
Arrays.sort(tmp);
return tmp;
}
/**
* Reads bytes from the attached device
* @param len number of bytes to read
* @return bytes read from device
* @see beginTransmission
* @see write
* @see endTransmission
* @webref
*/
public byte[] read(int len) {
if (!transmitting) {
throw new RuntimeException("beginTransmisson has not been called");
}
byte[] in = new byte[len];
if (NativeInterface.isSimulated()) {
return in;
}
int ret = NativeInterface.transferI2c(handle, slave, out, in);
transmitting = false;
out = null;
if (ret < 0) {
if (ret == -5) { // EIO
System.err.println("The device did not respond. Check the cabling and whether you are using the correct address.");
}
throw new RuntimeException(NativeInterface.getError(ret));
}
return in;
}
/**
* Adds bytes to be written to the device
* @param out bytes to be written
* @see beginTransmission
* @see read
* @see endTransmission
* @webref
*/
public void write(byte[] out) {
if (!transmitting) {
throw new RuntimeException("beginTransmisson has not been called");
}
if (this.out == null) {
this.out = out;
} else {
byte[] tmp = new byte[this.out.length + out.length];
System.arraycopy(this.out, 0, tmp, 0, this.out.length);
System.arraycopy(out, 0, tmp, this.out.length, out.length);
this.out = tmp;
}
}
/**
* Adds bytes to be written to the attached device
* @param out string to be written
* @see beginTransmission
* @see read
* @see endTransmission
*/
public void write(String out) {
write(out.getBytes());
}
/**
* Adds a byte to be written to the attached device
* @param out single byte to be written, e.g. numeric literal (0 to 255, or -128 to 127)
* @see beginTransmission
* @see read
* @see endTransmission
*/
public void write(int out) {
if (out < -128 || 255 < out) {
System.err.println("The write function can only operate on a single byte at a time. Call it with a value from 0 to 255, or -128 to 127.");
throw new RuntimeException("Argument does not fit into a single byte");
}
byte[] tmp = new byte[1];
tmp[0] = (byte)out;
write(tmp);
}
/**
* Adds a byte to be written to the attached device
* @param out single byte to be written
* @see beginTransmission
* @see read
* @see endTransmission
*/
public void write(byte out) {
// cast to (unsigned) int
write(out & 0xff);
}
}

View File

@@ -0,0 +1,177 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
import processing.io.NativeInterface;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @webref
*/
public class LED {
protected String dev;
protected int maxBrightness;
protected int prevBrightness;
protected String prevTrigger;
/**
* Opens a LED device
* @param dev device name
* @see list
* @webref
*/
public LED(String dev) {
NativeInterface.loadLibrary();
this.dev = dev;
if (NativeInterface.isSimulated()) {
return;
}
// read maximum brightness
try {
Path path = Paths.get("/sys/class/leds/" + dev + "/max_brightness");
String tmp = new String(Files.readAllBytes(path));
maxBrightness = Integer.parseInt(tmp.trim());
} catch (Exception e) {
System.err.println(e.getMessage());
throw new RuntimeException("Unable to read maximum brightness");
}
// read current trigger setting to be able to restore it later
try {
Path path = Paths.get("/sys/class/leds/" + dev + "/trigger");
String tmp = new String(Files.readAllBytes(path));
int start = tmp.indexOf('[');
int end = tmp.indexOf(']', start);
if (start != -1 && end != -1) {
prevTrigger = tmp.substring(start+1, end);
}
} catch (Exception e) {
System.err.println(e.getMessage());
throw new RuntimeException("Unable to read trigger setting");
}
// read current brightness to be able to restore it later
try {
Path path = Paths.get("/sys/class/leds/" + dev + "/brightness");
String tmp = new String(Files.readAllBytes(path));
prevBrightness = Integer.parseInt(tmp.trim());
} catch (Exception e) {
System.err.println(e.getMessage());
throw new RuntimeException("Unable to read current brightness");
}
// disable trigger
String fn = "/sys/class/leds/" + dev + "/trigger";
int ret = NativeInterface.writeFile(fn, "none");
if (ret < 0) {
if (ret == -13) { // EACCES
System.err.println("You might need to install a custom udev rule to allow regular users to modify /sys/class/leds/*.");
}
throw new RuntimeException(NativeInterface.getError(ret));
}
}
/**
* Sets the brightness
* @param bright 0.0 (off) to 1.0 (maximum)
* @webref
*/
public void brightness(float bright) {
if (bright < 0.0 || 1.0 < bright) {
System.err.println("Brightness must be between 0.0 and 1.0.");
throw new IllegalArgumentException("Illegal argument");
}
if (NativeInterface.isSimulated()) {
return;
}
String fn = "/sys/class/leds/" + dev + "/brightness";
int ret = NativeInterface.writeFile(fn, Integer.toString((int)(bright * maxBrightness)));
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
}
/**
* Restores the previous state
* @webref
*/
public void close() {
if (NativeInterface.isSimulated()) {
return;
}
// restore previous settings
String fn = "/sys/class/leds/" + dev + "/brightness";
int ret = NativeInterface.writeFile(fn, Integer.toString(prevBrightness));
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
fn = "/sys/class/leds/" + dev + "/trigger";
ret = NativeInterface.writeFile(fn, prevTrigger);
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
}
/**
* Lists all available LED devices
* @return String array
* @webref
*/
public static String[] list() {
if (NativeInterface.isSimulated()) {
// as on the Raspberry Pi
return new String[]{ "led0", "led1" };
}
ArrayList<String> devs = new ArrayList<String>();
File dir = new File("/sys/class/leds");
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
devs.add(file.getName());
}
}
// listFiles() does not guarantee ordering
String[] tmp = devs.toArray(new String[devs.size()]);
Arrays.sort(tmp);
return tmp;
}
}

View File

@@ -0,0 +1,75 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
public class NativeInterface {
protected static boolean loaded = false;
protected static boolean alwaysSimulate = false;
public static void loadLibrary() {
if (!loaded) {
if (isSimulated()) {
System.err.println("The Processing I/O library is not supported on this platform. Instead of values from actual hardware ports, your sketch will only receive stand-in values that allow you to test the remainder of its functionality.");
} else {
System.loadLibrary("processing-io");
}
loaded = true;
}
}
public static void alwaysSimulate() {
alwaysSimulate = true;
}
public static boolean isSimulated() {
return alwaysSimulate ||
!"Linux".equals(System.getProperty("os.name"));
}
public static native int openDevice(String fn);
public static native String getError(int errno);
public static native int closeDevice(int handle);
// the following two functions were done in native code to get access to the
// specifc error number (errno) that might occur
public static native int readFile(String fn, byte[] in);
public static native int writeFile(String fn, byte[] out);
public static int writeFile(String fn, String out) {
return writeFile(fn, out.getBytes());
}
/* GPIO */
public static native int pollDevice(String fn, int timeout);
/* I2C */
public static native int transferI2c(int handle, int slave, byte[] out, byte[] in);
/* SoftwareServo */
public static native long servoStartThread(int gpio, int pulse, int period);
public static native int servoUpdateThread(long handle, int pulse, int period);
public static native int servoStopThread(long handle);
/* SPI */
public static native int setSpiSettings(int handle, int maxSpeed, int dataOrder, int mode);
public static native int transferSpi(int handle, byte[] out, byte[] in);
}

View File

@@ -0,0 +1,215 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
import processing.io.NativeInterface;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @webref
*/
public class PWM {
int channel;
String chip;
/**
* Opens a PWM channel
* @param channel PWM channel
* @see list
* @webref
*/
public PWM(String channel) {
NativeInterface.loadLibrary();
int pos = channel.indexOf("/pwm");
if (pos == -1) {
throw new IllegalArgumentException("Unsupported channel");
}
chip = channel.substring(0, pos);
this.channel = Integer.parseInt(channel.substring(pos+4));
if (NativeInterface.isSimulated()) {
return;
}
// export channel through sysfs
String fn = "/sys/class/pwm/" + chip + "/export";
int ret = NativeInterface.writeFile(fn, Integer.toString(this.channel));
if (ret < 0) {
if (ret == -2) { // ENOENT
System.err.println("Make sure your kernel is compiled with PWM_SYSFS enabled and you have the necessary PWM driver for your platform");
}
// XXX: check
if (ret == -22) { // EINVAL
System.err.println("PWM channel " + channel + " does not seem to be available on your platform");
}
// XXX: check
if (ret != -16) { // EBUSY, returned when the pin is already exported
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
}
// delay to give udev a chance to change the file permissions behind our back
// there should really be a cleaner way for this
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* Disables the PWM output
* @webref
*/
public void clear() {
if (NativeInterface.isSimulated()) {
return;
}
String fn = String.format("/sys/class/pwm/%s/pwm%d/enable", chip, channel);
int ret = NativeInterface.writeFile(fn, "0");
if (ret < 0) {
throw new RuntimeException(NativeInterface.getError(ret));
}
}
/**
* Gives ownership of a channel back to the operating system
* @webref
*/
public void close() {
if (NativeInterface.isSimulated()) {
return;
}
// XXX: implicit clear()?
// XXX: also check GPIO
String fn = "/sys/class/pwm/" + chip + "/unexport";
int ret = NativeInterface.writeFile(fn, Integer.toString(channel));
if (ret < 0) {
if (ret == -2) { // ENOENT
System.err.println("Make sure your kernel is compiled with PWM_SYSFS enabled and you have the necessary PWM driver for your platform");
}
// XXX: check
// EINVAL is also returned when trying to unexport pins that weren't exported to begin with
throw new RuntimeException(NativeInterface.getError(ret));
}
}
/**
* Lists all available PWM channels
* @return String array
* @webref
*/
public static String[] list() {
if (NativeInterface.isSimulated()) {
return new String[]{ "pwmchip0/pwm0", "pwmchip0/pwm1" };
}
ArrayList<String> devs = new ArrayList<String>();
File dir = new File("/sys/class/pwm");
File[] chips = dir.listFiles();
if (chips != null) {
for (File chip : chips) {
// get the number of supported channels
try {
Path path = Paths.get("/sys/class/pwm/" + chip.getName() + "/npwm");
String tmp = new String(Files.readAllBytes(path));
int npwm = Integer.parseInt(tmp.trim());
for (int i=0; i < npwm; i++) {
devs.add(chip.getName() + "/pwm" + i);
}
} catch (Exception e) {
}
}
}
// listFiles() does not guarantee ordering
String[] tmp = devs.toArray(new String[devs.size()]);
Arrays.sort(tmp);
return tmp;
}
/**
* Enables the PWM output
* @param period cycle period in Hz
* @param duty duty cycle, 0.0 (always off) to 1.0 (always on)
* @webref
*/
public void set(int period, float duty) {
if (NativeInterface.isSimulated()) {
return;
}
// set period
String fn = fn = String.format("/sys/class/pwm/%s/pwm%d/period", chip, channel);
// convert to nanoseconds
int ret = NativeInterface.writeFile(fn, String.format("%d", (int)(1000000000 / period)));
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
// set duty cycle
fn = fn = String.format("/sys/class/pwm/%s/pwm%d/duty_cycle", chip, channel);
if (duty < 0.0 || 1.0 < duty) {
System.err.println("Duty cycle must be between 0.0 and 1.0.");
throw new IllegalArgumentException("Illegal argument");
}
// convert to nanoseconds
ret = NativeInterface.writeFile(fn, String.format("%d", (int)((1000000000 * duty) / period)));
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
// enable output
fn = String.format("/sys/class/pwm/%s/pwm%d/enable", chip, channel);
ret = NativeInterface.writeFile(fn, "1");
if (ret < 0) {
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
}
}
/**
* Enables the PWM output with a preset period of 1 kHz
* @param duty duty cycle, 0.0 (always off) to 1.0 (always on)
* @webref
*/
public void set(float duty) {
set(1000, duty);
}
}

View File

@@ -0,0 +1,226 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider as part of GSoC 2015
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
import processing.io.NativeInterface;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @webref
*/
public class SPI {
/**
* CPOL=0, CPHA=0, most common
*/
public static final int MODE0 = 0;
/**
* CPOL=0, CPHA=1
*/
public static final int MODE1 = 1;
/**
* CPOL=1, CPHA=0
*/
public static final int MODE2 = 2;
/**
* CPOL=1, CPHA=1
*/
public static final int MODE3 = 3;
/**
* most significant bit first, most common
*/
public static final int MSBFIRST = 0;
/**
* least significant bit first
*/
public static final int LSBFIRST = 1;
protected int dataOrder = 0;
protected String dev;
protected int handle;
protected int maxSpeed = 500000;
protected int mode = 0;
protected static Map<String, String> settings = new HashMap<String, String>();
/**
* Opens an SPI interface as master
* @param dev device name
* @see list
* @webref
*/
public SPI(String dev) {
NativeInterface.loadLibrary();
this.dev = dev;
if (NativeInterface.isSimulated()) {
return;
}
handle = NativeInterface.openDevice("/dev/" + dev);
if (handle < 0) {
throw new RuntimeException(NativeInterface.getError(handle));
}
}
/**
* Closes the SPI interface
* @webref
*/
public void close() {
if (NativeInterface.isSimulated()) {
return;
}
NativeInterface.closeDevice(handle);
handle = 0;
}
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
/**
* Lists all available SPI interfaces
* @return String array
* @webref
*/
public static String[] list() {
if (NativeInterface.isSimulated()) {
// as on the Raspberry Pi
return new String[]{ "spidev0.0", "spidev0.1" };
}
ArrayList<String> devs = new ArrayList<String>();
File dir = new File("/dev");
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.getName().startsWith("spidev")) {
devs.add(file.getName());
}
}
}
// listFiles() does not guarantee ordering
String[] tmp = devs.toArray(new String[devs.size()]);
Arrays.sort(tmp);
return tmp;
}
/**
* Configures the SPI interface
* @param maxSpeed maximum transmission rate in Hz, 500000 (500 kHz) is a resonable default
* @param dataOrder whether data is send with the first- or least-significant bit first (SPI.MSBFIRST or SPI.LSBFIRST, the former is more common)
* @param mode <a href="https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Clock_polarity_and_phase">SPI.MODE0 to SPI.MODE3</a>
* @webref
*/
public void settings(int maxSpeed, int dataOrder, int mode) {
this.maxSpeed = maxSpeed;
this.dataOrder = dataOrder;
this.mode = mode;
}
/**
* Transfers data over the SPI bus
* @param out bytes to send
* @return bytes read in (array is the same length as out)
* @webref
*/
public byte[] transfer(byte[] out) {
if (NativeInterface.isSimulated()) {
return new byte[out.length];
}
// track the current setting per device across multiple instances
String curSettings = maxSpeed + "-" + dataOrder + "-" + mode;
if (!curSettings.equals(settings.get(dev))) {
int ret = NativeInterface.setSpiSettings(handle, maxSpeed, dataOrder, mode);
if (ret < 0) {
System.err.println(NativeInterface.getError(handle));
throw new RuntimeException("Error updating device configuration");
}
settings.put(dev, curSettings);
}
byte[] in = new byte[out.length];
int transferred = NativeInterface.transferSpi(handle, out, in);
if (transferred < 0) {
throw new RuntimeException(NativeInterface.getError(transferred));
} else if (transferred < out.length) {
throw new RuntimeException("Fewer bytes transferred than requested: " + transferred);
}
return in;
}
/**
* Transfers data over the SPI bus
* @param out string to send
* @return bytes read in (array is the same length as out)
*/
public byte[] transfer(String out) {
return transfer(out.getBytes());
}
/**
* Transfers data over the SPI bus
* @param out single byte to send, e.g. numeric literal (0 to 255, or -128 to 127)
* @return bytes read in (array is the same length as out)
*/
public byte[] transfer(int out) {
if (out < -128 || 255 < out) {
System.err.println("The transfer function can only operate on a single byte at a time. Call it with a value from 0 to 255, or -128 to 127.");
throw new RuntimeException("Argument does not fit into a single byte");
}
byte[] tmp = new byte[1];
tmp[0] = (byte)out;
return transfer(tmp);
}
/**
* Transfers data over the SPI bus
* @param out single byte to send
* @return bytes read in (array is the same length as out)
*/
public byte[] transfer(byte out) {
// cast to (unsigned) int
return transfer(out & 0xff);
}
}

View File

@@ -0,0 +1,162 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Copyright (c) The Processing Foundation 2015
Hardware I/O library developed by Gottfried Haider
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.io;
import processing.core.*;
/**
* @webref
*/
public class SoftwareServo {
public static final int DEFAULT_MIN_PULSE = 544;
public static final int DEFAULT_MAX_PULSE = 2400;
protected int pin = -1; // gpio number (-1 .. not attached)
protected long handle = -1; // native thread id (<0 .. not started)
protected int period = 20000; // 20 ms (50 Hz)
protected int minPulse = 0; // minimum pulse width in microseconds
protected int maxPulse = 0; // maximum pulse width in microseconds
protected int pulse = 0; // current pulse in microseconds
/**
* Opens a servo motor
* @param parent typically use "this"
* @webref
*/
public SoftwareServo(PApplet parent) {
NativeInterface.loadLibrary();
}
/**
* Closes a servo motor
* @webref
*/
public void close() {
detach();
}
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
/**
* Attaches a servo motor to a GPIO pin
* @param pin GPIO pin
* @webref
*/
public void attach(int pin) {
detach();
this.pin = pin;
this.minPulse = DEFAULT_MIN_PULSE;
this.maxPulse = DEFAULT_MAX_PULSE;
}
/**
* Attaches a servo motor to a GPIO pin using custom pulse widths
* @param minPulse minimum pulse width in microseconds (default: 544, same as on Arduino)
* @param maxPulse maximum pulse width in microseconds (default: 2400, same as on Arduino)
* @webref
*/
public void attach(int pin, int minPulse, int maxPulse) {
detach();
this.pin = pin;
this.minPulse = minPulse;
this.maxPulse = maxPulse;
}
/**
* Moves a servo motor to a given orientation
* @param angle angle in degrees (controls speed and direction on continuous-rotation servos)
* @webref
*/
public void write(float angle) {
if (attached() == false) {
System.err.println("You need to call attach(pin) before write(angle).");
throw new RuntimeException("Servo is not attached");
}
if (angle < 0 || 180 < angle) {
System.err.println("Only degree values between 0 and 180 can be used.");
throw new IllegalArgumentException("Illegal value");
}
pulse = (int)(minPulse + (angle/180.0) * (maxPulse-minPulse));
if (handle < 0) {
// start a new thread
GPIO.pinMode(pin, GPIO.OUTPUT);
if (NativeInterface.isSimulated()) {
return;
}
handle = NativeInterface.servoStartThread(pin, pulse, period);
if (handle < 0) {
throw new RuntimeException(NativeInterface.getError((int)handle));
}
} else {
// thread already running
int ret = NativeInterface.servoUpdateThread(handle, pulse, period);
if (ret < 0) {
throw new RuntimeException(NativeInterface.getError(ret));
}
}
}
/**
* Returns whether a servo motor is attached to a pin
* @return true if attached, false is not
* @webref
*/
public boolean attached() {
return (pin != -1);
}
/**
* Detatches a servo motor from a GPIO pin
* @webref
*/
public void detach() {
if (0 <= handle) {
// stop thread
int ret = NativeInterface.servoStopThread(handle);
GPIO.pinMode(pin, GPIO.INPUT);
handle = -1;
pin = -1;
if (ret < 0) {
throw new RuntimeException(NativeInterface.getError(ret));
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry combineaccessrules="false" kind="src" path="/processing-core"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>processing-net</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,295 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=18
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=18
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=36
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=false
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=1
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=1
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=2
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=2
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

View File

@@ -0,0 +1,3 @@
eclipse.preferences.version=1
formatter_profile=_processing
formatter_settings_version=12

View File

@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<project name="Processing Net Library" default="build">
<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="library/net.jar" />
</target>
<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../../../core/library/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
<mkdir dir="bin" />
<javac source="1.8"
target="1.8"
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../../../core/library/core.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
../../mode/jdtCompilerAdapter.jar" />
</javac>
</target>
<target name="build" depends="compile" description="Build net library">
<jar basedir="bin" destfile="library/net.jar" />
</target>
</project>

View File

@@ -0,0 +1,52 @@
/**
* Chat Server
* by Tom Igoe.
*
* Press the mouse to stop the server.
*/
import processing.net.*;
int port = 10002;
boolean myServerRunning = true;
int bgColor = 0;
int direction = 1;
int textLine = 60;
Server myServer;
void setup()
{
size(400, 400);
textFont(createFont("SanSerif", 16));
myServer = new Server(this, port); // Starts a myServer on port 10002
background(0);
}
void mousePressed()
{
// If the mouse clicked the myServer stops
myServer.stop();
myServerRunning = false;
}
void draw()
{
if (myServerRunning == true)
{
text("server", 15, 45);
Client thisClient = myServer.available();
if (thisClient != null) {
if (thisClient.available() > 0) {
text("mesage from: " + thisClient.ip() + " : " + thisClient.readString(), 15, textLine);
textLine = textLine + 35;
}
}
}
else
{
text("server", 15, 45);
text("stopped", 15, 65);
}
}

View File

@@ -0,0 +1,34 @@
/**
* HTTP Client.
*
* Starts a network client that connects to a server on port 80,
* sends an HTTP 1.0 GET request, and prints the results.
*
* Note that this code is not necessary for simple HTTP GET request:
* Simply calling loadStrings("http://www.processing.org") would do
* the same thing as (and more efficiently than) this example.
* This example is for people who might want to do something more
* complicated later.
*/
import processing.net.*;
Client c;
String data;
void setup() {
size(200, 200);
background(50);
fill(200);
c = new Client(this, "www.ucla.edu", 80); // Connect to server on port 80
c.write("GET / HTTP/1.0\r\n"); // Use the HTTP "GET" command to ask for a Web page
c.write("\r\n");
}
void draw() {
if (c.available() > 0) { // If there's incoming data from the client...
data = c.readString(); // ...then grab it and print it
println(data);
}
}

View File

@@ -0,0 +1,46 @@
/**
* Shared Drawing Canvas (Client)
* by Alexander R. Galloway.
*
* The Processing Client class is instantiated by specifying a remote
* address and port number to which the socket connection should be made.
* Once the connection is made, the client may read (or write) data to the server.
* Before running this program, start the Shared Drawing Canvas (Server) program.
*/
import processing.net.*;
Client c;
String input;
int data[];
void setup()
{
size(450, 255);
background(204);
stroke(0);
frameRate(5); // Slow it down a little
// Connect to the server's IP address and port
c = new Client(this, "127.0.0.1", 12345); // Replace with your server's IP and port
}
void draw()
{
if (mousePressed == true) {
// Draw our line
stroke(255);
line(pmouseX, pmouseY, mouseX, mouseY);
// Send mouse coords to other person
c.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
}
// Receive data from server
if (c.available() > 0) {
input = c.readString();
input = input.substring(0, input.indexOf("\n")); // Only up to the newline
data = int(split(input, ' ')); // Split values into an array
// Draw line using received coords
stroke(0);
line(data[0], data[1], data[2], data[3]);
}
}

View File

@@ -0,0 +1,50 @@
/**
* Shared Drawing Canvas (Server)
* by Alexander R. Galloway.
*
* A server that shares a drawing canvas between two computers.
* In order to open a socket connection, a server must select a
* port on which to listen for incoming clients and through which
* to communicate. Once the socket is established, a client may
* connect to the server and send or receive commands and data.
* Get this program running and then start the Shared Drawing
* Canvas (Client) program so see how they interact.
*/
import processing.net.*;
Server s;
Client c;
String input;
int data[];
void setup()
{
size(450, 255);
background(204);
stroke(0);
frameRate(5); // Slow it down a little
s = new Server(this, 12345); // Start a simple server on a port
}
void draw()
{
if (mousePressed == true) {
// Draw our line
stroke(255);
line(pmouseX, pmouseY, mouseX, mouseY);
// Send mouse coords to other person
s.write(pmouseX + " " + pmouseY + " " + mouseX + " " + mouseY + "\n");
}
// Receive data from client
c = s.available();
if (c != null) {
input = c.readString();
input = input.substring(0, input.indexOf("\n")); // Only up to the newline
data = int(split(input, ' ')); // Split values into an array
// Draw line using received coords
stroke(0);
line(data[0], data[1], data[2], data[3]);
}
}

View File

@@ -0,0 +1,2 @@
name = Network
version = 1

View File

@@ -0,0 +1,690 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Client - basic network client implementation
Part of the Processing project - http://processing.org
Copyright (c) 2004-2007 Ben Fry and Casey Reas
The previous version of this code was developed by Hernando Barragan
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.net;
import processing.core.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
/**
* ( begin auto-generated from Client.xml )
*
* A client connects to a server and sends data back and forth. If anything
* goes wrong with the connection, for example the host is not there or is
* listening on a different port, an exception is thrown.
*
* ( end auto-generated )
* @webref net
* @brief The client class is used to create client Objects which connect to a server to exchange data.
* @instanceName client any variable of type Client
* @usage Application
* @see_external LIB_net/clientEvent
*/
public class Client implements Runnable {
PApplet parent;
Method clientEventMethod;
Method disconnectEventMethod;
Thread thread;
Socket socket;
int port;
String host;
public InputStream input;
public OutputStream output;
byte buffer[] = new byte[32768];
int bufferIndex;
int bufferLast;
boolean disposeRegistered = false;
/**
* @param parent typically use "this"
* @param host address of the server
* @param port port to read/write from on the server
*/
public Client(PApplet parent, String host, int port) {
this.parent = parent;
this.host = host;
this.port = port;
try {
socket = new Socket(this.host, this.port);
input = socket.getInputStream();
output = socket.getOutputStream();
thread = new Thread(this);
thread.start();
parent.registerMethod("dispose", this);
disposeRegistered = true;
// reflection to check whether host sketch has a call for
// public void clientEvent(processing.net.Client)
// which would be called each time an event comes in
try {
clientEventMethod =
parent.getClass().getMethod("clientEvent",
new Class[] { Client.class });
} catch (Exception e) {
// no such method, or an error.. which is fine, just ignore
}
// do the same for disconnectEvent(Client c);
try {
disconnectEventMethod =
parent.getClass().getMethod("disconnectEvent",
new Class[] { Client.class });
} catch (Exception e) {
// no such method, or an error.. which is fine, just ignore
}
} catch (ConnectException ce) {
ce.printStackTrace();
dispose();
} catch (IOException e) {
e.printStackTrace();
dispose();
}
}
/**
* @param socket any object of type Socket
* @throws IOException
*/
public Client(PApplet parent, Socket socket) throws IOException {
this.parent = parent;
this.socket = socket;
input = socket.getInputStream();
output = socket.getOutputStream();
thread = new Thread(this);
thread.start();
// reflection to check whether host sketch has a call for
// public void disconnectEvent(processing.net.Client)
try {
disconnectEventMethod =
parent.getClass().getMethod("disconnectEvent",
new Class[] { Client.class });
} catch (Exception e) {
// no such method, or an error.. which is fine, just ignore
}
}
/**
* ( begin auto-generated from Client_stop.xml )
*
* Disconnects from the server. Use to shut the connection when you're
* finished with the Client.
*
* ( end auto-generated )
* @webref client:client
* @brief Disconnects from the server
* @usage application
*/
public void stop() {
if (disconnectEventMethod != null && thread != null){
try {
disconnectEventMethod.invoke(parent, new Object[] { this });
} catch (Exception e) {
e.printStackTrace();
disconnectEventMethod = null;
}
}
if (disposeRegistered) {
parent.unregisterMethod("dispose", this);
disposeRegistered = false;
}
dispose();
}
/**
* Disconnect from the server: internal use only.
* <P>
* This should only be called by the internal functions in PApplet,
* use stop() instead from within your own applets.
*/
public void dispose() {
thread = null;
try {
if (input != null) {
input.close();
input = null;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (output != null) {
output.close();
output = null;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
socket = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (Thread.currentThread() == thread) {
try {
while (input != null) {
int value;
// try to read a byte using a blocking read.
// An exception will occur when the sketch is exits.
try {
value = input.read();
} catch (SocketException e) {
System.err.println("Client SocketException: " + e.getMessage());
// the socket had a problem reading so don't try to read from it again.
stop();
return;
}
// read returns -1 if end-of-stream occurs (for example if the host disappears)
if (value == -1) {
System.err.println("Client got end-of-stream.");
stop();
return;
}
synchronized (buffer) {
// todo: at some point buffer should stop increasing in size,
// otherwise it could use up all the memory.
if (bufferLast == buffer.length) {
byte temp[] = new byte[bufferLast << 1];
System.arraycopy(buffer, 0, temp, 0, bufferLast);
buffer = temp;
}
buffer[bufferLast++] = (byte)value;
}
// now post an event
if (clientEventMethod != null) {
try {
clientEventMethod.invoke(parent, new Object[] { this });
} catch (Exception e) {
System.err.println("error, disabling clientEvent() for " + host);
e.printStackTrace();
clientEventMethod = null;
}
}
}
} catch (IOException e) {
//errorMessage("run", e);
e.printStackTrace();
}
}
}
/**
* ( begin auto-generated from Client_active.xml )
*
* Returns true if this client is still active and hasn't run
* into any trouble.
*
* ( end auto-generated )
* @webref client:client
* @brief Returns true if this client is still active
* @usage application
*/
public boolean active() {
return (thread != null);
}
/**
* ( begin auto-generated from Client_ip.xml )
*
* Returns the IP address of the computer to which the Client is attached.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Returns the IP address of the machine as a String
*/
public String ip() {
if (socket != null){
return socket.getInetAddress().getHostAddress();
}
return null;
}
/**
* ( begin auto-generated from Client_available.xml )
*
* Returns the number of bytes available. When any client has bytes
* available from the server, it returns the number of bytes.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Returns the number of bytes in the buffer waiting to be read
*/
public int available() {
return (bufferLast - bufferIndex);
}
/**
* ( begin auto-generated from Client_clear.xml )
*
* Empty the buffer, removes all the data stored there.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Clears the buffer
*/
public void clear() {
bufferLast = 0;
bufferIndex = 0;
}
/**
* ( begin auto-generated from Client_read.xml )
*
* Returns a number between 0 and 255 for the next byte that's waiting in
* the buffer. Returns -1 if there is no byte, although this should be
* avoided by first cheacking <b>available()</b> to see if any data is available.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Returns a value from the buffer
*/
public int read() {
if (bufferIndex == bufferLast) return -1;
synchronized (buffer) {
int outgoing = buffer[bufferIndex++] & 0xff;
if (bufferIndex == bufferLast) { // rewind
bufferIndex = 0;
bufferLast = 0;
}
return outgoing;
}
}
/**
* ( begin auto-generated from Client_readChar.xml )
*
* Returns the next byte in the buffer as a char. Returns -1 or 0xffff if
* nothing is there.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Returns the next byte in the buffer as a char
*/
public char readChar() {
if (bufferIndex == bufferLast) return (char)(-1);
return (char) read();
}
/**
* ( begin auto-generated from Client_readBytes.xml )
*
* Reads a group of bytes from the buffer. The version with no parameters
* returns a byte array of all data in the buffer. This is not efficient,
* but is easy to use. The version with the <b>byteBuffer</b> parameter is
* more memory and time efficient. It grabs the data in the buffer and puts
* it into the byte array passed in and returns an int value for the number
* of bytes read. If more bytes are available than can fit into the
* <b>byteBuffer</b>, only those that fit are read.
*
* ( end auto-generated )
* <h3>Advanced</h3>
* Return a byte array of anything that's in the serial buffer.
* Not particularly memory/speed efficient, because it creates
* a byte array on each read, but it's easier to use than
* readBytes(byte b[]) (see below).
*
* @webref client:client
* @usage application
* @brief Reads everything in the buffer
*/
public byte[] readBytes() {
if (bufferIndex == bufferLast) return null;
synchronized (buffer) {
int length = bufferLast - bufferIndex;
byte outgoing[] = new byte[length];
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
bufferIndex = 0; // rewind
bufferLast = 0;
return outgoing;
}
}
/**
* <h3>Advanced</h3>
* Return a byte array of anything that's in the serial buffer
* up to the specified maximum number of bytes.
* Not particularly memory/speed efficient, because it creates
* a byte array on each read, but it's easier to use than
* readBytes(byte b[]) (see below).
*
* @param max the maximum number of bytes to read
*/
public byte[] readBytes(int max) {
if (bufferIndex == bufferLast) return null;
synchronized (buffer) {
int length = bufferLast - bufferIndex;
if (length > max) length = max;
byte outgoing[] = new byte[length];
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
bufferIndex += length;
if (bufferIndex == bufferLast) {
bufferIndex = 0; // rewind
bufferLast = 0;
}
return outgoing;
}
}
/**
* <h3>Advanced</h3>
* Grab whatever is in the serial buffer, and stuff it into a
* byte buffer passed in by the user. This is more memory/time
* efficient than readBytes() returning a byte[] array.
*
* Returns an int for how many bytes were read. If more bytes
* are available than can fit into the byte array, only those
* that will fit are read.
*
* @param bytebuffer passed in byte array to be altered
*/
public int readBytes(byte bytebuffer[]) {
if (bufferIndex == bufferLast) return 0;
synchronized (buffer) {
int length = bufferLast - bufferIndex;
if (length > bytebuffer.length) length = bytebuffer.length;
System.arraycopy(buffer, bufferIndex, bytebuffer, 0, length);
bufferIndex += length;
if (bufferIndex == bufferLast) {
bufferIndex = 0; // rewind
bufferLast = 0;
}
return length;
}
}
/**
* ( begin auto-generated from Client_readBytesUntil.xml )
*
* Reads from the port into a buffer of bytes up to and including a
* particular character. If the character isn't in the buffer, 'null' is
* returned. The version with no <b>byteBuffer</b> parameter returns a byte
* array of all data up to and including the <b>interesting</b> byte. This
* is not efficient, but is easy to use. The version with the
* <b>byteBuffer</b> parameter is more memory and time efficient. It grabs
* the data in the buffer and puts it into the byte array passed in and
* returns an int value for the number of bytes read. If the byte buffer is
* not large enough, -1 is returned and an error is printed to the message
* area. If nothing is in the buffer, 0 is returned.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Reads from the buffer of bytes up to and including a particular character
* @param interesting character designated to mark the end of the data
*/
public byte[] readBytesUntil(int interesting) {
if (bufferIndex == bufferLast) return null;
byte what = (byte)interesting;
synchronized (buffer) {
int found = -1;
for (int k = bufferIndex; k < bufferLast; k++) {
if (buffer[k] == what) {
found = k;
break;
}
}
if (found == -1) return null;
int length = found - bufferIndex + 1;
byte outgoing[] = new byte[length];
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
bufferIndex += length;
if (bufferIndex == bufferLast) {
bufferIndex = 0; // rewind
bufferLast = 0;
}
return outgoing;
}
}
/**
* <h3>Advanced</h3>
* Reads from the serial port into a buffer of bytes until a
* particular character. If the character isn't in the serial
* buffer, then 'null' is returned.
*
* If outgoing[] is not big enough, then -1 is returned,
* and an error message is printed on the console.
* If nothing is in the buffer, zero is returned.
* If 'interesting' byte is not in the buffer, then 0 is returned.
*
* @param byteBuffer passed in byte array to be altered
*/
public int readBytesUntil(int interesting, byte byteBuffer[]) {
if (bufferIndex == bufferLast) return 0;
byte what = (byte)interesting;
synchronized (buffer) {
int found = -1;
for (int k = bufferIndex; k < bufferLast; k++) {
if (buffer[k] == what) {
found = k;
break;
}
}
if (found == -1) return 0;
int length = found - bufferIndex + 1;
if (length > byteBuffer.length) {
System.err.println("readBytesUntil() byte buffer is" +
" too small for the " + length +
" bytes up to and including char " + interesting);
return -1;
}
//byte outgoing[] = new byte[length];
System.arraycopy(buffer, bufferIndex, byteBuffer, 0, length);
bufferIndex += length;
if (bufferIndex == bufferLast) {
bufferIndex = 0; // rewind
bufferLast = 0;
}
return length;
}
}
/**
* ( begin auto-generated from Client_readString.xml )
*
* Returns the all the data from the buffer as a String. This method
* assumes the incoming characters are ASCII. If you want to transfer
* Unicode data, first convert the String to a byte stream in the
* representation of your choice (i.e. UTF8 or two-byte Unicode data), and
* send it as a byte array.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Returns the buffer as a String
*/
public String readString() {
if (bufferIndex == bufferLast) return null;
return new String(readBytes());
}
/**
* ( begin auto-generated from Client_readStringUntil.xml )
*
* Combination of <b>readBytesUntil()</b> and <b>readString()</b>. Returns
* <b>null</b> if it doesn't find what you're looking for.
*
* ( end auto-generated )
* <h3>Advanced</h3>
* <p/>
* If you want to move Unicode data, you can first convert the
* String to a byte stream in the representation of your choice
* (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
*
* @webref client:client
* @usage application
* @brief Returns the buffer as a String up to and including a particular character
* @param interesting character designated to mark the end of the data
*/
public String readStringUntil(int interesting) {
byte b[] = readBytesUntil(interesting);
if (b == null) return null;
return new String(b);
}
/**
* ( begin auto-generated from Client_write.xml )
*
* Writes data to a server specified when constructing the client.
*
* ( end auto-generated )
* @webref client:client
* @usage application
* @brief Writes bytes, chars, ints, bytes[], Strings
* @param data data to write
*/
public void write(int data) { // will also cover char
try {
output.write(data & 0xff); // for good measure do the &
output.flush(); // hmm, not sure if a good idea
} catch (Exception e) { // null pointer or serial port dead
//errorMessage("write", e);
//e.printStackTrace();
//dispose();
//disconnect(e);
e.printStackTrace();
stop();
}
}
public void write(byte data[]) {
try {
output.write(data);
output.flush(); // hmm, not sure if a good idea
} catch (Exception e) { // null pointer or serial port dead
//errorMessage("write", e);
//e.printStackTrace();
//disconnect(e);
e.printStackTrace();
stop();
}
}
/**
* <h3>Advanced</h3>
* Write a String to the output. Note that this doesn't account
* for Unicode (two bytes per char), nor will it send UTF8
* characters.. It assumes that you mean to send a byte buffer
* (most often the case for networking and serial i/o) and
* will only use the bottom 8 bits of each char in the string.
* (Meaning that internally it uses String.getBytes)
*
* If you want to move Unicode data, you can first convert the
* String to a byte stream in the representation of your choice
* (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
*/
public void write(String data) {
write(data.getBytes());
}
/**
* Handle disconnect due to an Exception being thrown.
*/
/*
protected void disconnect(Exception e) {
dispose();
if (e != null) {
e.printStackTrace();
}
}
*/
/**
* General error reporting, all corralled here just in case
* I think of something slightly more intelligent to do.
*/
//public void errorMessage(String where, Exception e) {
//parent.die("Error inside Client." + where + "()", e);
//e.printStackTrace(System.err);
//}
}

View File

@@ -0,0 +1,372 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Server - basic network server implementation
Part of the Processing project - http://processing.org
Copyright (c) 2004-2007 Ben Fry and Casey Reas
The previous version of this code was developed by Hernando Barragan
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.net;
import processing.core.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
/**
* ( begin auto-generated from Server.xml )
*
* A server sends and receives data to and from its associated clients
* (other programs connected to it). When a server is started, it begins
* listening for connections on the port specified by the <b>port</b>
* parameter. Computers have many ports for transferring data and some are
* commonly used so be sure to not select one of these. For example, web
* servers usually use port 80 and POP mail uses port 110.
*
* ( end auto-generated )
* @webref net
* @usage application
* @brief The server class is used to create server objects which send and receives data to and from its associated clients (other programs connected to it).
* @instanceName server any variable of type Server
*/
public class Server implements Runnable {
PApplet parent;
Method serverEventMethod;
Thread thread;
ServerSocket server;
int port;
/** Number of clients currently connected. */
public int clientCount;
/** Array of client objects, useful length is determined by clientCount. */
public Client[] clients;
/**
* @param parent typically use "this"
* @param port port used to transfer data
*/
public Server(PApplet parent, int port) {
this(parent, port, null);
}
/**
* @param parent typically use "this"
* @param port port used to transfer data
* @param host when multiple NICs are in use, the ip (or name) to bind from
*/
public Server(PApplet parent, int port, String host) {
this.parent = parent;
this.port = port;
try {
if (host == null) {
server = new ServerSocket(this.port);
} else {
server = new ServerSocket(this.port, 10, InetAddress.getByName(host));
}
//clients = new Vector();
clients = new Client[10];
thread = new Thread(this);
thread.start();
parent.registerMethod("dispose", this);
// reflection to check whether host applet has a call for
// public void serverEvent(Server s, Client c);
// which is called when a new guy connects
try {
serverEventMethod =
parent.getClass().getMethod("serverEvent",
new Class[] { Server.class,
Client.class });
} catch (Exception e) {
// no such method, or an error.. which is fine, just ignore
}
} catch (IOException e) {
//e.printStackTrace();
thread = null;
throw new RuntimeException(e);
//errorMessage("<init>", e);
}
}
/**
* ( begin auto-generated from Server_disconnect.xml )
*
* Disconnect a particular client.
*
* ( end auto-generated )
* @brief Disconnect a particular client.
* @webref server:server
* @param client the client to disconnect
*/
public void disconnect(Client client) {
client.stop();
int index = clientIndex(client);
if (index != -1) {
removeIndex(index);
}
}
protected void removeIndex(int index) {
clientCount--;
// shift down the remaining clients
for (int i = index; i < clientCount; i++) {
clients[i] = clients[i+1];
}
// mark last empty var for garbage collection
clients[clientCount] = null;
}
protected void disconnectAll() {
synchronized (clients) {
for (int i = 0; i < clientCount; i++) {
try {
clients[i].stop();
} catch (Exception e) {
// ignore
}
clients[i] = null;
}
clientCount = 0;
}
}
protected void addClient(Client client) {
if (clientCount == clients.length) {
clients = (Client[]) PApplet.expand(clients);
}
clients[clientCount++] = client;
}
protected int clientIndex(Client client) {
for (int i = 0; i < clientCount; i++) {
if (clients[i] == client) {
return i;
}
}
return -1;
}
/**
* ( begin auto-generated from Server_active.xml )
*
* Returns true if this server is still active and hasn't run
* into any trouble.
*
* ( end auto-generated )
* @webref server:server
* @brief Return true if this server is still active.
*/
public boolean active() {
return thread != null;
}
static public String ip() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
return null;
}
}
// the last index used for available. can't just cycle through
// the clients in order from 0 each time, because if client 0 won't
// shut up, then the rest of the clients will never be heard from.
int lastAvailable = -1;
/**
* ( begin auto-generated from Server_available.xml )
*
* Returns the next client in line with a new message.
*
* ( end auto-generated )
* @brief Returns the next client in line with a new message.
* @webref server
* @usage application
*/
public Client available() {
synchronized (clients) {
int index = lastAvailable + 1;
if (index >= clientCount) index = 0;
for (int i = 0; i < clientCount; i++) {
int which = (index + i) % clientCount;
Client client = clients[which];
//Check for valid client
if (!client.active()){
removeIndex(which); //Remove dead client
i--; //Don't skip the next client
//If the client has data make sure lastAvailable
//doesn't end up skipping the next client
which--;
//fall through to allow data from dead clients
//to be retreived.
}
if (client.available() > 0) {
lastAvailable = which;
return client;
}
}
}
return null;
}
/**
* ( begin auto-generated from Server_stop.xml )
*
* Disconnects all clients and stops the server.
*
* ( end auto-generated )
* <h3>Advanced</h3>
* Use this to shut down the server if you finish using it while your applet
* is still running. Otherwise, it will be automatically be shut down by the
* host PApplet using dispose(), which is identical.
* @brief Disconnects all clients and stops the server.
* @webref server
* @usage application
*/
public void stop() {
dispose();
}
/**
* Disconnect all clients and stop the server: internal use only.
*/
public void dispose() {
thread = null;
if (clients != null) {
disconnectAll();
clientCount = 0;
clients = null;
}
try {
if (server != null) {
server.close();
server = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while (Thread.currentThread() == thread) {
try {
Socket socket = server.accept();
Client client = new Client(parent, socket);
synchronized (clients) {
addClient(client);
if (serverEventMethod != null) {
try {
serverEventMethod.invoke(parent, new Object[] { this, client });
} catch (Exception e) {
System.err.println("Disabling serverEvent() for port " + port);
e.printStackTrace();
serverEventMethod = null;
}
}
}
} catch (SocketException e) {
//thrown when server.close() is called and server is waiting on accept
System.err.println("Server SocketException: " + e.getMessage());
thread = null;
} catch (IOException e) {
//errorMessage("run", e);
e.printStackTrace();
thread = null;
}
try {
Thread.sleep(8);
} catch (InterruptedException ex) { }
}
}
/**
* ( begin auto-generated from Server_write.xml )
*
* Writes a value to all the connected clients. It sends bytes out from the
* Server object.
*
* ( end auto-generated )
* @webref server
* @brief Writes data to all connected clients
* @param data data to write
*/
public void write(int data) { // will also cover char
int index = 0;
while (index < clientCount) {
if (clients[index].active()) {
clients[index].write(data);
index++;
} else {
removeIndex(index);
}
}
}
public void write(byte data[]) {
int index = 0;
while (index < clientCount) {
if (clients[index].active()) {
clients[index].write(data);
index++;
} else {
removeIndex(index);
}
}
}
public void write(String data) {
int index = 0;
while (index < clientCount) {
if (clients[index].active()) {
clients[index].write(data);
index++;
} else {
removeIndex(index);
}
}
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/processing-core"/>
<classpathentry kind="lib" path="library/itext.jar" sourcepath="itext-src.zip"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>processing-pdf</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,292 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=18
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=18
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=36
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=false
org.eclipse.jdt.core.formatter.comment.format_source_code=true
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.jdt.core.formatter.comment.line_length=80
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=1
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=1
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=2
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=80
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=space
org.eclipse.jdt.core.formatter.tabulation.size=2
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

View File

@@ -0,0 +1,4 @@
eclipse.preferences.version=1
formatter_profile=_processing
formatter_settings_version=12
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>

View File

@@ -0,0 +1,11 @@
This library uses iText 2.1.7, which is the last LGPL/MPL version of the iText project.
We've used iText for several years. The license for iText has changed for subsequent versions and is no longer compatible with Processing, so we're stuck at 2.x.
At the iText site, there's also some [vague wording](http://lowagie.com/itext2) about legal liability for commercial projects using the 2.x series. It's not clear where this leaves us.
Bruno Lowagie did an enormous amount of (free) work with the iText project, and we certainly don't fault him for the new commercial license.
We're using iText in a very limited way--drawing to it like it's a Java Graphics2D object. There might be other options for us in this space, but it's not much of a priority.
Ben Fry, 12 October 2013

View File

@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<project name="Processing PDF Library" default="build">
<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="library/pdf.jar" />
</target>
<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../../../core/library/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
<mkdir dir="bin" />
<javac source="1.8"
target="1.8"
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../../../core/library/core.jar; library/itext.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
../../mode/jdtCompilerAdapter.jar" />
</javac>
</target>
<target name="build" depends="compile" description="Build PDF library">
<jar basedir="bin" destfile="library/pdf.jar" />
</target>
</project>

View File

@@ -0,0 +1,194 @@
/**
* PDF Complex
* by Marius Watz (workshop.evolutionzone.com).
*
* Example using PDF to output complex 3D geometry for print.
* Press "s" to save a PDF.
*/
import processing.opengl.*;
import processing.pdf.*;
// Trig lookup tables borrowed from Toxi. Cryptic but effective
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION=1.0;
int SINCOS_LENGTH= int((360.0/SINCOS_PRECISION));
// System data
boolean dosave=false;
int num;
float pt[];
int style[];
void setup() {
size(600, 600, OPENGL);
frameRate(24);
background(255);
// Fill the tables
sinLUT=new float[SINCOS_LENGTH];
cosLUT=new float[SINCOS_LENGTH];
for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i]= (float)Math.sin(i*DEG_TO_RAD*SINCOS_PRECISION);
cosLUT[i]= (float)Math.cos(i*DEG_TO_RAD*SINCOS_PRECISION);
}
num = 150;
pt = new float[6*num]; // rotx, roty, deg, rad, w, speed
style = new int[2*num]; // color, render style
// Set up arc shapes
int index=0;
float prob;
for (int i=0; i<num; i++) {
pt[index++] = random(PI*2); // Random X axis rotation
pt[index++] = random(PI*2); // Random Y axis rotation
pt[index++] = random(60,80); // Short to quarter-circle arcs
if(random(100)>90) pt[index]=(int)random(8,27)*10;
pt[index++] = int(random(2,50)*5); // Radius. Space them out nicely
pt[index++] = random(4,32); // Width of band
if(random(100)>90) pt[index]=random(40,60); // Width of band
pt[index++] = radians(random(5,30))/5; // Speed of rotation
// get colors
prob = random(100);
if(prob<30) style[i*2]=colorBlended(random(1), 255,0,100, 255,0,0, 210);
else if(prob<70) style[i*2]=colorBlended(random(1), 0,153,255, 170,225,255, 210);
else if(prob<90) style[i*2]=colorBlended(random(1), 200,255,0, 150,255,0, 210);
else style[i*2]=color(255,255,255, 220);
if(prob<50) style[i*2]=colorBlended(random(1), 200,255,0, 50,120,0, 210);
else if(prob<90) style[i*2]=colorBlended(random(1), 255,100,0, 255,255,0, 210);
else style[i*2]=color(255,255,255, 220);
style[i*2+1]=(int)(random(100))%3;
}
}
void draw() {
if(dosave) {
// set up PGraphicsPDF for use with beginRaw()
PGraphicsPDF pdf = (PGraphicsPDF)beginRaw(PDF, "pdf_complex_out.pdf");
// set default Illustrator stroke styles and paint background rect.
pdf.strokeJoin(MITER);
pdf.strokeCap(SQUARE);
pdf.fill(0);
pdf.noStroke();
pdf.rect(0,0, width,height);
}
background(0);
int index=0;
translate(width/2,height/2,0);
rotateX(PI/6);
rotateY(PI/6);
for (int i=0; i<num; i++) {
pushMatrix();
rotateX(pt[index++]);
rotateY(pt[index++]);
if(style[i*2+1]==0) {
stroke(style[i*2]);
noFill();
strokeWeight(1);
arcLine(0,0, pt[index++],pt[index++],pt[index++]);
}
else if(style[i*2+1]==1) {
fill(style[i*2]);
noStroke();
arcLineBars(0,0, pt[index++],pt[index++],pt[index++]);
}
else {
fill(style[i*2]);
noStroke();
arc(0,0, pt[index++],pt[index++],pt[index++]);
}
// increase rotation
pt[index-5]+=pt[index]/10;
pt[index-4]+=pt[index++]/20;
popMatrix();
}
if(dosave) {
endRaw();
dosave=false;
}
}
// Get blend of two colors
public int colorBlended(float fract,
float r, float g, float b,
float r2, float g2, float b2, float a) {
r2 = (r2 - r);
g2 = (g2 - g);
b2 = (b2 - b);
return color(r + r2 * fract, g + g2 * fract, b + b2 * fract, a);
}
// Draw arc line
public void arcLine(float x,float y,float deg,float rad,float w) {
int a=(int)(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
int numlines=(int)(w/2);
for (int j=0; j<numlines; j++) {
beginShape();
for (int i=0; i<a; i++) {
vertex(cosLUT[i]*rad+x,sinLUT[i]*rad+y);
}
endShape();
rad += 2;
}
}
// Draw arc line with bars
public void arcLineBars(float x,float y,float deg,float rad,float w) {
int a = int((min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1)));
a /= 4;
beginShape(QUADS);
for (int i=0; i<a; i+=4) {
vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
vertex(cosLUT[i+2]*(rad+w)+x,sinLUT[i+2]*(rad+w)+y);
vertex(cosLUT[i+2]*(rad)+x,sinLUT[i+2]*(rad)+y);
}
endShape();
}
// Draw solid arc
public void arc(float x,float y,float deg,float rad,float w) {
int a = int(min (deg/SINCOS_PRECISION,SINCOS_LENGTH-1));
beginShape(QUAD_STRIP);
for (int i = 0; i < a; i++) {
vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
}
endShape();
}
void keyPressed() {
if (key == 's') {
dosave=true;
}
}
void mouseReleased() {
background(255);
}

View File

@@ -0,0 +1,31 @@
/**
* Large Page.
*
* Saves one frame as a PDF with a size larger
* than the screen. When PDF is used as the renderer
* (the third parameter of size) the display window
* does not open. The file is saved to the sketch folder.
* You can open it by "Sketch->Show Sketch Folder."
*/
import processing.pdf.*;
void setup()
{
size(2000, 2000, PDF, "Line.pdf");
}
void draw()
{
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(200, 0, width/2, height);
exit(); // Quit the program
}

View File

@@ -0,0 +1,38 @@
/**
* Many PDFs.
*
* Saves one PDF file each each frame while the mouse is pressed.
* When the mouse is released, the PDF creation stops.
*/
import processing.pdf.*;
boolean savePDF = false;
void setup() {
size(600, 600);
frameRate(24);
}
void draw() {
if(savePDF == true) {
beginRecord(PDF, "lines" + frameCount + ".pdf");
}
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
if(savePDF == true) {
endRecord();
}
}
void mousePressed() {
savePDF = true;
}
void mouseReleased() {
savePDF = false;
}

View File

@@ -0,0 +1,30 @@
/**
* Many Pages.
*
* Saves a new page into a PDF file each loop through draw().
* Pressing the mouse finishes writing the file and exits the program.
*/
import processing.pdf.*;
PGraphicsPDF pdf;
void setup() {
size(600, 600);
frameRate(4);
pdf = (PGraphicsPDF)beginRecord(PDF, "Lines.pdf");
}
void draw() {
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
pdf.nextPage();
}
void mousePressed() {
endRecord();
exit();
}

View File

@@ -0,0 +1,37 @@
/**
* Mouse Press.
*
* Saves one PDF of the contents of the display window
* each time the mouse is pressed.
*/
import processing.pdf.*;
boolean saveOneFrame = false;
void setup() {
size(600, 600);
frameRate(24);
}
void draw() {
if(saveOneFrame == true) {
beginRecord(PDF, "Line.pdf");
}
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
if(saveOneFrame == true) {
endRecord();
saveOneFrame = false;
}
}
void mousePressed() {
saveOneFrame = true;
}

View File

@@ -0,0 +1,33 @@
/**
* Multiple Frames.
*
* Saves one PDF document of many frames drawn to the screen.
* Starts the file when the mouse is pressed and end the file
* when the mouse is released.
*/
import processing.pdf.*;
void setup() {
size(600, 600);
frameRate(24);
background(255);
}
void draw() {
stroke(0, 20);
strokeWeight(20.0);
line(mouseX, 0, width-mouseY, height);
}
void mousePressed() {
beginRecord(PDF, "Lines.pdf");
background(255);
}
void mouseReleased() {
endRecord();
background(255);
}

View File

@@ -0,0 +1,23 @@
/**
* One Frame.
*
* Saves one PDF with the contents of the display window.
* Because this example uses beginRecord, the image is shown
* on the display window and is saved to the file.
*/
import processing.pdf.*;
size(600, 600);
beginRecord(PDF, "line.pdf");
background(255);
stroke(0, 20);
strokeWeight(20.0);
line(200, 0, 400, height);
endRecord();

View File

@@ -0,0 +1,45 @@
/**
* RandomBook
*
* Creates a 768 page book of random lines.
*/
import processing.pdf.*;
PGraphicsPDF pdf;
void setup() {
size(594, 842);
// randomSeed(0); // Uncomment to make the same book each time
pdf = (PGraphicsPDF)beginRecord(PDF, "RandomBook.pdf");
beginRecord(pdf);
}
void draw() {
background(255);
for (int i=0; i<100; i++) {
float r = random(1.0);
if(r < 0.2) {
stroke(255);
} else {
stroke(0);
}
float sw = pow(random(1.0), 12);
strokeWeight(sw * 260);
float x1 = random(-200, -100);
float x2 = random(width+100, width+200);
float y1 = random(-100, height+100);
float y2 = random(-100, height+100);
line(x1, y1, x2, y2);
}
if(frameCount == 768) {
endRecord();
exit(); // Quit
} else {
pdf.nextPage(); // Tell it to go to the next page
}
}

View File

@@ -0,0 +1,2 @@
name = PDF Export
version = 1

View File

@@ -0,0 +1,686 @@
/*
Part of the Processing project - http://processing.org
Copyright (c) 2005-11 Ben Fry and Casey Reas
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
package processing.pdf;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.*;
import java.util.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
import processing.awt.PGraphicsJava2D;
import processing.core.*;
/**
* Thin wrapper for the iText PDF library that handles writing PDF files.
* The majority of the work in this library is done by
* <a href="http://www.lowagie.com/iText/">iText</a>.
* <br /> <br />
* This is currently using iText 2.1.7.
* <br /> <br />
* The issue is that versions from the 5.x series were slow to handle lots of
* fonts with the DefaultFontMapper. 2.x seemed a little slower than 1.x,
* but 5.x took up to 10 times the time to load, meaning a lag of several
* seconds when starting sketches on a machine that had a good handful of
* fonts installed. (Like, say, anyone in our target audience. Or me.)
*/
public class PGraphicsPDF extends PGraphicsJava2D {
/** File being written, if it's a file. */
protected File file;
/** OutputStream being written to, if using an OutputStream. */
protected OutputStream output;
protected Document document;
protected PdfWriter writer;
protected PdfContentByte content;
/** Shared across instances because it's incredibly time-consuming to create. */
static protected DefaultFontMapper mapper;
static protected String[] fontList;
/*
public PGraphicsPDF() {
// PDF always likes native fonts. Always.
hint(ENABLE_NATIVE_FONTS);
}
*/
public void setPath(String path) {
this.path = path;
if (path != null) {
file = new File(path);
if (!file.isAbsolute()) {
file = null;
}
}
if (file == null) {
throw new RuntimeException("PGraphicsPDF requires an absolute path " +
"for the location of the output file.");
}
}
/**
* Set the library to write to an output stream instead of a file.
*/
public void setOutput(OutputStream output) {
this.output = output;
}
// /**
// * all the init stuff happens in here, in case someone calls size()
// * along the way and wants to hork things up.
// */
// protected void allocate() {
// // can't do anything here, because this will be called by the
// // superclass PGraphics, and the file/path object won't be set yet
// // (since super() called right at the beginning of the constructor)
// }
@Override
public PSurface createSurface() {
return surface = new PSurfaceNone(this);
}
@Override
protected void defaultSettings() { // ignore
super.defaultSettings();
textMode = SHAPE;
}
public void beginDraw() {
// long t0 = System.currentTimeMillis();
if (document == null) {
document = new Document(new Rectangle(width, height));
boolean missingPath = false;
try {
if (file != null) {
//BufferedOutputStream output = new BufferedOutputStream(stream, 16384);
output = new BufferedOutputStream(new FileOutputStream(file), 16384);
} else if (output == null) {
missingPath = true;
throw new RuntimeException("PGraphicsPDF requires a path " +
"for the location of the output file.");
}
writer = PdfWriter.getInstance(document, output);
document.open();
content = writer.getDirectContent();
// template = content.createTemplate(width, height);
} catch (RuntimeException re) {
if (missingPath) {
throw re; // don't re-package our own error
} else {
throw new RuntimeException("Problem saving the PDF file.", re);
}
} catch (FileNotFoundException fnfe) {
throw new RuntimeException("Can't save the PDF file to " + path, fnfe);
} catch (DocumentException de) {
throw new RuntimeException("Error inside the PDF library.", de);
}
g2 = content.createGraphicsShapes(width, height);
}
// super in Java2D now creates an image buffer, don't do that
//super.beginDraw();
checkSettings();
resetMatrix(); // reset model matrix
vertexCount = 0;
// Also need to push the matrix since the matrix doesn't reset on each run
// http://dev.processing.org/bugs/show_bug.cgi?id=1227
pushMatrix();
}
static protected DefaultFontMapper getMapper() {
if (mapper == null) {
// long t = System.currentTimeMillis();
mapper = new DefaultFontMapper();
if (PApplet.platform == PConstants.MACOSX) {
try {
String homeLibraryFonts =
System.getProperty("user.home") + "/Library/Fonts";
mapper.insertDirectory(homeLibraryFonts);
} catch (Exception e) {
// might be a security issue with getProperty() and user.home
// if this sketch is running from the web
}
// add the system font paths
mapper.insertDirectory("/System/Library/Fonts");
mapper.insertDirectory("/Library/Fonts");
} else if (PApplet.platform == PConstants.WINDOWS) {
// how to get the windows fonts directory?
// could be c:\winnt\fonts or c:\windows\fonts or not even c:
// maybe do a Runtime.exec() on echo %WINDIR% ?
// Runtime.exec solution might be a mess on systems where the
// the backslash/colon characters not really used (i.e. JP)
// find the windows fonts folder
File roots[] = File.listRoots();
for (int i = 0; i < roots.length; i++) {
if (roots[i].toString().startsWith("A:")) {
// Seems to be a problem with some machines that the A:
// drive is returned as an actual root, even if not available.
// This won't fix the issue if the same thing happens with
// other removable drive devices, but should fix the
// initial/problem as cited by the bug report:
// http://dev.processing.org/bugs/show_bug.cgi?id=478
// If not, will need to use the other fileExists() code below.
continue;
}
File folder = new File(roots[i], "WINDOWS/Fonts");
if (folder.exists()) {
mapper.insertDirectory(folder.getAbsolutePath());
break;
}
folder = new File(roots[i], "WINNT/Fonts");
if (folder.exists()) {
mapper.insertDirectory(folder.getAbsolutePath());
break;
}
}
} else if (PApplet.platform == PConstants.LINUX) {
checkDir("/usr/share/fonts/", mapper);
checkDir("/usr/local/share/fonts/", mapper);
checkDir(System.getProperty("user.home") + "/.fonts", mapper);
}
// System.out.println("mapping " + (System.currentTimeMillis() - t));
}
return mapper;
}
static protected void checkDir(String path, DefaultFontMapper mapper) {
File folder = new File(path);
if (folder.exists()) {
mapper.insertDirectory(path);
traverseDir(folder, mapper);
}
}
/**
* Recursive walk to get all subdirectories for font fun.
* Patch submitted by Matthias Breuer.
* (<a href="http://dev.processing.org/bugs/show_bug.cgi?id=1566">Bug 1566</a>)
*/
static protected void traverseDir(File folder, DefaultFontMapper mapper) {
File[] files = folder.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
mapper.insertDirectory(files[i].getPath());
traverseDir(new File(files[i].getPath()), mapper);
}
}
}
// endDraw() needs to be overridden so that the endDraw() from
// PGraphicsJava2D is not inherited (it calls loadPixels).
// http://dev.processing.org/bugs/show_bug.cgi?id=1169
public void endDraw() {
// Also need to pop the matrix since the matrix doesn't reset on each run
// http://dev.processing.org/bugs/show_bug.cgi?id=1227
popMatrix();
}
/**
* Gives the same basic functionality of File.exists but can be
* used to look for removable media without showing a system
* dialog if the media is not present. Workaround pulled from the
* <A HREF="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4089199">
* bug report</A> on bugs.sun.com. This bug was fixed in Java 6, and we
* can remove the workaround when we start requiring Java 6.
*/
protected static boolean fileExists(File file) {
try {
Process process =
Runtime.getRuntime().exec(new String[] {
"cmd.exe", "/c", "dir", file.getAbsolutePath()
});
// We need to consume all available output or the process will block.
boolean haveExitCode = false;
int exitCode = -1;
InputStream out = process.getInputStream();
InputStream err = process.getErrorStream();
while (!haveExitCode) {
while (out.read() >= 0) {
}
while (err.read() >= 0) {
}
try {
exitCode = process.exitValue();
haveExitCode = true;
} catch (IllegalThreadStateException e) {
// Not yet complete.
Thread.sleep(100);
}
}
//int exitCode = process.waitFor();
return exitCode == 0;
} catch (IOException e) {
System.out.println("Unable to check for file: " + file + " : " + e);
return false;
} catch (InterruptedException e) {
System.out.println("Unable to check for file. Interrupted: " +
file + " : " + e);
return false;
}
}
/**
* Call to explicitly go to the next page from within a single draw().
*/
public void nextPage() {
PStyle savedStyle = getStyle();
endDraw();
g2.dispose();
try {
// writer.setPageEmpty(false); // maybe useful later
document.newPage(); // is this bad if no addl pages are made?
} catch (Exception e) {
e.printStackTrace();
}
g2 = createGraphics();
beginDraw();
style(savedStyle);
}
protected Graphics2D createGraphics() {
if (textMode == SHAPE) {
return content.createGraphicsShapes(width, height);
} else if (textMode == MODEL) {
return content.createGraphics(width, height, getMapper());
}
// Should not be reachable...
throw new RuntimeException("Invalid textMode() selected for PDF.");
}
public void dispose() {
if (document != null) {
g2.dispose();
document.close(); // can't be done in finalize, not always called
document = null;
}
//new Exception().printStackTrace(System.out);
}
/**
* Don't open a window for this renderer, it won't be used.
*/
public boolean displayable() {
return false;
}
/*
protected void finalize() throws Throwable {
System.out.println("calling finalize");
//document.close(); // do this in dispose instead?
}
*/
//////////////////////////////////////////////////////////////
/*
public void endRecord() {
super.endRecord();
dispose();
}
public void endRaw() {
System.out.println("ending raw");
super.endRaw();
System.out.println("disposing");
dispose();
System.out.println("done");
}
*/
//////////////////////////////////////////////////////////////
/*
protected void rectImpl(float x1, float y1, float x2, float y2) {
//rect.setFrame(x1, y1, x2-x1, y2-y1);
//draw_shape(rect);
System.out.println("rect implements");
g2.fillRect((int)x1, (int)y1, (int) (x2-x1), (int) (y2-y1));
}
*
/*
public void clear() {
g2.setColor(Color.red);
g2.fillRect(0, 0, width, height);
}
*/
//////////////////////////////////////////////////////////////
protected void imageImpl(PImage image,
float x1, float y1, float x2, float y2,
int u1, int v1, int u2, int v2) {
pushMatrix();
translate(x1, y1);
int imageWidth = image.width;
int imageHeight = image.height;
scale((x2 - x1) / imageWidth,
(y2 - y1) / imageHeight);
if (u2-u1 == imageWidth && v2-v1 == imageHeight) {
g2.drawImage(image.getImage(), 0, 0, null);
} else {
PImage tmp = image.get(u1, v1, u2-u1, v2-v1);
g2.drawImage((Image) tmp.getNative(), 0, 0, null);
}
popMatrix();
}
//////////////////////////////////////////////////////////////
public void textFont(PFont which) {
super.textFont(which);
checkFont();
// Make sure a native version of the font is available.
// if (textFont.getFont() == null) {
// throw new RuntimeException("Use createFont() instead of loadFont() " +
// "when drawing text using the PDF library.");
// }
// Make sure that this is a font that the PDF library can deal with.
// if ((textMode != SHAPE) && !checkFont(which.getName())) {
// System.err.println("Use PGraphicsPDF.listFonts() to get a list of available fonts.");
// throw new RuntimeException("The font “" + which.getName() + "” cannot be used with PDF Export.");
// }
}
/**
* Change the textMode() to either SHAPE or MODEL.
* <br/>
* This resets all renderer settings, and therefore must
* be called <EM>before</EM> any other commands that set the fill()
* or the textFont() or anything. Unlike other renderers,
* use textMode() directly after the size() command.
*/
public void textMode(int mode) {
if (textMode != mode) {
if (mode == SHAPE) {
textMode = SHAPE;
g2.dispose();
// g2 = content.createGraphicsShapes(width, height);
g2 = createGraphics();
} else if (mode == MODEL) {
textMode = MODEL;
g2.dispose();
// g2 = content.createGraphics(width, height, mapper);
g2 = createGraphics();
// g2 = template.createGraphics(width, height, mapper);
} else if (mode == SCREEN) {
throw new RuntimeException("textMode(SCREEN) not supported with PDF");
} else {
throw new RuntimeException("That textMode() does not exist");
}
}
}
protected void textLineImpl(char buffer[], int start, int stop,
float x, float y) {
checkFont();
super.textLineImpl(buffer, start, stop, x, y);
}
//////////////////////////////////////////////////////////////
public void loadPixels() {
nope("loadPixels");
}
public void updatePixels() {
nope("updatePixels");
}
public void updatePixels(int x, int y, int c, int d) {
nope("updatePixels");
}
//
public int get(int x, int y) {
nope("get");
return 0; // not reached
}
public PImage get(int x, int y, int c, int d) {
nope("get");
return null; // not reached
}
public PImage get() {
nope("get");
return null; // not reached
}
public void set(int x, int y, int argb) {
nope("set");
}
public void set(int x, int y, PImage image) {
nope("set");
}
//
public void mask(int alpha[]) {
nope("mask");
}
public void mask(PImage alpha) {
nope("mask");
}
//
public void filter(int kind) {
nope("filter");
}
public void filter(int kind, float param) {
nope("filter");
}
//
public void copy(int sx1, int sy1, int sx2, int sy2,
int dx1, int dy1, int dx2, int dy2) {
nope("copy");
}
public void copy(PImage src,
int sx1, int sy1, int sx2, int sy2,
int dx1, int dy1, int dx2, int dy2) {
nope("copy");
}
//
public void blend(int sx, int sy, int dx, int dy, int mode) {
nope("blend");
}
public void blend(PImage src,
int sx, int sy, int dx, int dy, int mode) {
nope("blend");
}
public void blend(int sx1, int sy1, int sx2, int sy2,
int dx1, int dy1, int dx2, int dy2, int mode) {
nope("blend");
}
public void blend(PImage src,
int sx1, int sy1, int sx2, int sy2,
int dx1, int dy1, int dx2, int dy2, int mode) {
nope("blend");
}
//
public boolean save(String filename) {
nope("save");
return false;
}
//////////////////////////////////////////////////////////////
/**
* Add a directory that should be searched for font data.
* <br/>
* On Mac OS X, the following directories are added by default:
* <UL>
* <LI>/System/Library/Fonts
* <LI>/Library/Fonts
* <LI>~/Library/Fonts
* </UL>
* On Windows, all drive letters are searched for WINDOWS\Fonts
* or WINNT\Fonts, any that exists is added.
* <br/><br/>
* On Linux or any other platform, you'll need to add the
* directories by hand. (If there are actual standards here that we
* can use as a starting point, please file a bug to make a note of it)
*/
public void addFonts(String directory) {
mapper.insertDirectory(directory);
}
/**
* Check whether the specified font can be used with the PDF library.
* @param name name of the font
* @return true if it's ok
*/
protected void checkFont() {
Font awtFont = (Font) textFont.getNative();
if (awtFont == null) { // always need a native font or reference to it
throw new RuntimeException("Use createFont() instead of loadFont() " +
"when drawing text using the PDF library.");
} else if (textMode != SHAPE) {
if (textFont.isStream()) {
throw new RuntimeException("Use textMode(SHAPE) with PDF when loading " +
".ttf and .otf files with createFont().");
} else if (mapper.getAliases().get(textFont.getName()) == null) {
//System.out.println("alias for " + name + " = " + mapper.getAliases().get(name));
// System.err.println("Use PGraphicsPDF.listFonts() to get a list of " +
// "fonts that can be used with PDF.");
// throw new RuntimeException("The font “" + textFont.getName() + "” " +
// "cannot be used with PDF Export.");
if (textFont.getName().equals("Lucida Sans")) {
throw new RuntimeException("Use textMode(SHAPE) with the default " +
"font when exporting to PDF.");
} else {
throw new RuntimeException("Use textMode(SHAPE) with " +
"" + textFont.getName() + "" +
"when exporting to PDF.");
}
}
}
}
/**
* List the fonts known to the PDF renderer. This is like PFont.list(),
* however not all those fonts are available by default.
*/
static public String[] listFonts() {
if (fontList == null) {
HashMap<?, ?> map = getMapper().getAliases();
// Set entries = map.entrySet();
// fontList = new String[entries.size()];
fontList = new String[map.size()];
int count = 0;
for (Object key : map.keySet()) {
// for (Object entry : map.entrySet()) {
// fontList[count++] = (String) ((Map.Entry) entry).getKey();
fontList[count++] = (String) key;
}
// Iterator it = entries.iterator();
// int count = 0;
// while (it.hasNext()) {
// Map.Entry entry = (Map.Entry) it.next();
// //System.out.println(entry.getKey() + "-->" + entry.getValue());
// fontList[count++] = (String) entry.getKey();
// }
fontList = PApplet.sort(fontList);
}
return fontList;
}
//////////////////////////////////////////////////////////////
protected void nope(String function) {
throw new RuntimeException("No " + function + "() for " + getClass().getSimpleName());
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="library/jssc.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/processing-core"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>processing-serial</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,12 @@
#Sat Nov 12 10:56:44 CST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -0,0 +1,32 @@
<?xml version="1.0"?>
<project name="Processing Serial Library" default="build">
<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="library/serial.jar" />
</target>
<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../../../core/library/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../../../core/library/core.jar" />
<mkdir dir="bin" />
<javac source="1.8"
target="1.8"
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../../../core/library/core.jar; library/jssc.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
<compilerclasspath path="../../mode/org.eclipse.jdt.core.jar;
../../mode/jdtCompilerAdapter.jar" />
</javac>
</target>
<target name="build" depends="compile" description="Build serial library">
<jar basedir="bin" destfile="library/serial.jar" />
</target>
</project>

View File

@@ -0,0 +1,150 @@
/**
* Serial Call-Response
* by Tom Igoe.
*
* Sends a byte out the serial port, and reads 3 bytes in.
* Sets foregound color, xpos, and ypos of a circle onstage
* using the values returned from the serial port.
* Thanks to Daniel Shiffman and Greg Shakar for the improvements.
*
* Note: This sketch assumes that the device on the other end of the serial
* port is going to send a single byte of value 65 (ASCII A) on startup.
* The sketch waits for that byte, then sends an ASCII A whenever
* it wants more data.
*/
import processing.serial.*;
int bgcolor; // Background color
int fgcolor; // Fill color
Serial myPort; // The serial port
int[] serialInArray = new int[3]; // Where we'll put what we receive
int serialCount = 0; // A count of how many bytes we receive
int xpos, ypos; // Starting position of the ball
boolean firstContact = false; // Whether we've heard from the microcontroller
void setup() {
size(256, 256); // Stage size
noStroke(); // No border on the next thing drawn
// Set the starting position of the ball (middle of the stage)
xpos = width/2;
ypos = height/2;
// Print a list of the serial ports, for debugging purposes:
printArray(Serial.list());
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(bgcolor);
fill(fgcolor);
// Draw the shape
ellipse(xpos, ypos, 20, 20);
}
void serialEvent(Serial myPort) {
// read a byte from the serial port:
int inByte = myPort.read();
// if this is the first byte received, and it's an A,
// clear the serial buffer and note that you've
// had first contact from the microcontroller.
// Otherwise, add the incoming byte to the array:
if (firstContact == false) {
if (inByte == 'A') {
myPort.clear(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller
myPort.write('A'); // ask for more
}
}
else {
// Add the latest byte from the serial port to array:
serialInArray[serialCount] = inByte;
serialCount++;
// If we have 3 bytes:
if (serialCount > 2 ) {
xpos = serialInArray[0];
ypos = serialInArray[1];
fgcolor = serialInArray[2];
// print the values (for debugging purposes only):
println(xpos + "\t" + ypos + "\t" + fgcolor);
// Send a capital A to request new sensor readings:
myPort.write('A');
// Reset serialCount:
serialCount = 0;
}
}
}
/*
// Serial Call and Response
// by Tom Igoe
// Language: Wiring/Arduino
// This program sends an ASCII A (byte of value 65) on startup
// and repeats that until it gets some data in.
// Then it waits for a byte in the serial port, and
// sends three sensor values whenever it gets a byte in.
// Thanks to Greg Shakar for the improvements
// Created 26 Sept. 2005
// Updated 18 April 2008
int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0; // incoming serial byte
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
pinMode(2, INPUT); // digital sensor is on digital pin 2
establishContact(); // send a byte to establish contact until Processing responds
}
void loop()
{
// if we get a valid byte, read analog ins:
if (Serial.available() > 0) {
// get incoming byte:
inByte = Serial.read();
// read first analog input, divide by 4 to make the range 0-255:
firstSensor = analogRead(0)/4;
// delay 10ms to let the ADC recover:
delay(10);
// read second analog input, divide by 4 to make the range 0-255:
secondSensor = analogRead(1)/4;
// read switch, multiply by 155 and add 100
// so that you're sending 100 or 255:
thirdSensor = 100 + (155 * digitalRead(2));
// send sensor values:
Serial.write(firstSensor);
Serial.write(secondSensor);
Serial.write(thirdSensor);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.write('A'); // send a capital A
delay(300);
}
}
*/

View File

@@ -0,0 +1,50 @@
/**
* Serial Duplex
* by Tom Igoe.
*
* Sends a byte out the serial port when you type a key
* listens for bytes received, and displays their value.
* This is just a quick application for testing serial data
* in both directions.
*/
import processing.serial.*;
Serial myPort; // The serial port
int whichKey = -1; // Variable to hold keystoke values
int inByte = -1; // Incoming serial data
void setup() {
size(400, 300);
// create a font with the third font available to the system:
PFont myFont = createFont(PFont.list()[2], 14);
textFont(myFont);
// List all the available serial ports:
printArray(Serial.list());
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// In Windows, this usually opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(0);
text("Last Received: " + inByte, 10, 130);
text("Last Sent: " + whichKey, 10, 100);
}
void serialEvent(Serial myPort) {
inByte = myPort.read();
}
void keyPressed() {
// Send the keystroke out:
myPort.write(key);
whichKey = key;
}

View File

@@ -0,0 +1,86 @@
/**
* Many Serial Ports
*
* Read data from the multiple Serial Ports
*/
import processing.serial.*;
Serial[] myPorts = new Serial[2]; // Create a list of objects from Serial class
int[] dataIn = new int[2]; // a list to hold data from the serial ports
void setup() {
size(400, 300);
// print a list of the serial ports:
printArray(Serial.list());
// On my machine, the first and third ports in the list
// were the serial ports that my microcontrollers were
// attached to.
// Open whatever ports ares the ones you're using.
// get the ports' names:
String portOne = Serial.list()[0];
String portTwo = Serial.list()[2];
// open the ports:
myPorts[0] = new Serial(this, portOne, 9600);
myPorts[1] = new Serial(this, portTwo, 9600);
}
void draw() {
// clear the screen:
background(0);
// use the latest byte from port 0 for the first circle
fill(dataIn[0]);
ellipse(width/3, height/2, 40, 40);
// use the latest byte from port 1 for the second circle
fill(dataIn[1]);
ellipse(2*width/3, height/2, 40, 40);
}
/**
* When SerialEvent is generated, it'll also give you
* the port that generated it. Check that against a list
* of the ports you know you opened to find out where
* the data came from
*/
void serialEvent(Serial thisPort) {
// variable to hold the number of the port:
int portNumber = -1;
// iterate over the list of ports opened, and match the
// one that generated this event:
for (int p = 0; p < myPorts.length; p++) {
if (thisPort == myPorts[p]) {
portNumber = p;
}
}
// read a byte from the port:
int inByte = thisPort.read();
// put it in the list that holds the latest data from each port:
dataIn[portNumber] = inByte;
// tell us who sent what:
println("Got " + inByte + " from serial port " + portNumber);
}
/*
The following Wiring/Arduino code runs on both microcontrollers that
were used to send data to this sketch:
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
}
void loop() {
// read analog input, divide by 4 to make the range 0-255:
int analogValue = analogRead(0)/4;
Serial.write(analogValue);
// pause for 10 milliseconds:
delay(10);
}
*/

View File

@@ -0,0 +1,64 @@
/**
* Simple Read
*
* Read data from the serial port and change the color of a rectangle
* when a switch connected to a Wiring or Arduino board is pressed and released.
* This example works with the Wiring / Arduino program that follows below.
*/
import processing.serial.*;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
void setup()
{
size(200, 200);
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0) { // If data is available,
val = myPort.read(); // read it and store it in val
}
background(255); // Set background to white
if (val == 0) { // If the serial value is 0,
fill(0); // set fill to black
}
else { // If the serial value is not 0,
fill(204); // set fill to light gray
}
rect(50, 50, 100, 100);
}
/*
// Wiring / Arduino Code
// Code for sensing a switch status and writing the value to the serial port.
int switchPin = 4; // Switch connected to pin 4
void setup() {
pinMode(switchPin, INPUT); // Set pin 0 as an input
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
if (digitalRead(switchPin) == HIGH) { // If switch is ON,
Serial.write(1); // send 1 to Processing
} else { // If the switch is not ON,
Serial.write(0); // send 0 to Processing
}
delay(100); // Wait 100 milliseconds
}
*/

View File

@@ -0,0 +1,67 @@
/**
* Simple Write.
*
* Check if the mouse is over a rectangle and writes the status to the serial port.
* This example works with the Wiring / Arduino program that follows below.
*/
import processing.serial.*;
Serial myPort; // Create object from Serial class
int val; // Data received from the serial port
void setup()
{
size(200, 200);
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(255);
if (mouseOverRect() == true) { // If mouse is over square,
fill(204); // change color and
myPort.write('H'); // send an H to indicate mouse is over square
}
else { // If mouse is not over square,
fill(0); // change color and
myPort.write('L'); // send an L otherwise
}
rect(50, 50, 100, 100); // Draw a square
}
boolean mouseOverRect() { // Test if mouse is over square
return ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150));
}
/*
// Wiring/Arduino code:
// Read data from the serial and turn ON or OFF a light depending on the value
char val; // Data received from the serial port
int ledPin = 4; // Set the pin to digital I/O 4
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
while (Serial.available()) { // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if (val == 'H') { // If H was received
digitalWrite(ledPin, HIGH); // turn the LED on
} else {
digitalWrite(ledPin, LOW); // Otherwise turn it OFF
}
delay(100); // Wait 100 milliseconds for next reading
}
*/

View File

@@ -0,0 +1,3 @@
name = Serial
version = 1

View File

@@ -0,0 +1,4 @@
This is using a modified version of Java Simple Serial Connector by Alexey Sokolov. See https://github.com/gohai/java-simple-serial-connector for details on the modifications.
To compile the C++ portion of the library on OS X:
g++ -shared [or: -dynamiclib?] -arch i386 -arch x86_64 -I/System/Library/Frameworks/IOKit.framework/Versions/A/Headers -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin -framework IOKit -framework CoreFoundation -o libjSSC-2.6.jnilib jssc.cpp

Some files were not shown because too many files have changed in this diff Show More