Skip to content

Commit 3f29cb4

Browse files
committed
getting sketch process to run concurrently with main process
1 parent d19cacf commit 3f29cb4

File tree

5 files changed

+493
-33
lines changed

5 files changed

+493
-33
lines changed

release/PythonMode.zip

7.57 KB
Binary file not shown.

src/info/sansgills/mode/python/Communicator.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import java.io.BufferedReader;
55
import java.io.InputStream;
66
import java.io.InputStreamReader;
7-
import java.io.OutputStream;
7+
import java.io.PrintWriter;
88

99
import processing.app.exec.StreamRedirectThread;
1010
import processing.core.PApplet;
@@ -15,14 +15,15 @@
1515
* Handles sending messages to and recieving messages from
1616
*
1717
*/
18+
1819
public class Communicator {
1920
private PythonEditor editor;
2021
private Process sketchProcess;
2122

2223
private StreamRedirectThread outThread;
2324
private MessageReceiverThread errThread;
2425

25-
private OutputStream toSketch;
26+
private PrintWriter toSketch;
2627

2728
public Communicator (Process sketchProcess, PythonEditor editor){
2829
this.sketchProcess = sketchProcess;
@@ -31,7 +32,7 @@ public Communicator (Process sketchProcess, PythonEditor editor){
3132
outThread = new StreamRedirectThread("JVM Stdout Reader", sketchProcess.getInputStream(), System.out);
3233
errThread = new MessageReceiverThread(sketchProcess.getErrorStream(), editor);
3334

34-
toSketch = sketchProcess.getOutputStream();
35+
toSketch = new PrintWriter(sketchProcess.getOutputStream());
3536

3637
outThread.start();
3738
errThread.start();
@@ -41,8 +42,34 @@ public void close(){
4142
errThread.running = false;
4243
errThread = null;
4344
outThread = null;
45+
toSketch.close();
46+
toSketch = null;
47+
}
48+
49+
50+
// communication methods
51+
52+
/*
53+
* Tell sketch to close
54+
*/
55+
public void sendClose(){
56+
toSketch.println("__STOP__"); //hard-coded, what the hell
57+
toSketch.flush();
4458
}
4559

60+
/*
61+
* Send a new sketch
62+
*/
63+
public void sendSketch(String[] args){
64+
StringBuilder out = new StringBuilder("__SKETCH__");
65+
for(String a : args){
66+
out.append(" "+a);
67+
}
68+
69+
70+
toSketch.println(out.toString());
71+
72+
}
4673

4774
//private class to handle doing things when the sketch process sends us a message via system.err
4875
private class MessageReceiverThread extends Thread{

src/info/sansgills/mode/python/PythonRunner.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
import java.awt.Point;
44
import java.io.File;
5-
import java.io.InputStream;
65
import java.util.ArrayList;
76

87
import processing.app.Base;
98
import processing.app.Preferences;
10-
import processing.app.exec.StreamRedirectThread;
119
import processing.core.PApplet;
1210

1311
/**
@@ -45,6 +43,7 @@ public void launch(boolean present) {
4543
* Construct the command-line command to start the sketch with
4644
*
4745
* TODO add proper machine detection & whatnot from Java Mode
46+
*
4847
*/
4948
private String[] buildArgs(boolean present){
5049
ArrayList<String> args = new ArrayList<String>();
@@ -63,15 +62,7 @@ private String[] buildArgs(boolean present){
6362
appendSketchArgs(args, present);
6463

6564
String[] out = args.toArray(new String[0]);
66-
67-
/*{//debugging
68-
String cmd = "";
69-
for (String c : out) {
70-
cmd += c + " ";
71-
}
72-
System.out.println("command: " + cmd);
73-
}*/
74-
65+
7566
return out;
7667
}
7768

@@ -152,7 +143,9 @@ private void appendSketchArgs(ArrayList<String> args, boolean present){
152143
args.add(PApplet.ARGS_STOP_COLOR + "=" + Preferences.get("run.present.stop.color"));
153144
args.add(PApplet.ARGS_BGCOLOR + "=" + Preferences.get("run.present.bgcolor"));
154145
}
155-
146+
147+
148+
args.add(PApplet.ARGS_EXTERNAL);
156149
args.add(build.getClassName()); // sketch name
157150
}
158151

@@ -178,10 +171,6 @@ public void run(){
178171
* Kill the code.
179172
*/
180173
public void close() {
181-
communicator.close();
182-
if(sketchProcess != null){
183-
sketchProcess.destroy();
184-
sketchProcess = null;
185-
}
174+
communicator.sendClose();
186175
}
187176
}

src/info/sansgills/mode/python/wrapper/ProcessingJythonWrapper.java

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
package info.sansgills.mode.python.wrapper;
22

3+
import info.sansgills.mode.python.PythonEditor;
4+
35
import java.awt.GraphicsDevice;
6+
import java.awt.Point;
7+
import java.io.BufferedReader;
8+
import java.io.InputStream;
9+
import java.io.InputStreamReader;
410
import java.util.Arrays;
511
import java.util.Scanner;
612

713
import org.python.core.*;
814
import org.python.util.InteractiveConsole;
915

16+
import processing.core.PApplet;
17+
1018
/**
1119
*
1220
* Class to handle running jython sketches. Packaged separately from the main mode for easy export.
@@ -39,22 +47,38 @@ public class ProcessingJythonWrapper {
3947
"mouseReleased", "mouseClicked", "mouseWheel", "mouseMoved",
4048
"mouseDragged", "keyPressed", "keyReleased", "keyTyped" };
4149

50+
static MessageReceiverThread receiver;
51+
4252
static InteractiveConsole interp; // python interpreter to feed things to
4353
static PySystemState sys; // for modifying python classpath, as yet
4454
static PythonPApplet constructedApplet; // Applet we pull from the interpreter
4555

4656
static final String objname = "__applet__";
4757

58+
static boolean parallel;
59+
4860
/**
4961
*
50-
* First argument is the path to the script; the rest are things to pass to PApplet.
62+
* First argument is the path to the script; the rest are things to pass to
63+
* PApplet.
5164
*
5265
*/
5366
public static void main(String[] args) {
54-
String scriptPath = args[0];
55-
String[] params = Arrays.copyOfRange(args, 1, args.length);
56-
prepare();
57-
run(scriptPath, params);
67+
if (args[0].indexOf("__PARALLEL__") != -1) {
68+
parallel = true;
69+
receiver = new MessageReceiverThread(System.in);
70+
receiver.start();
71+
// running from PDE
72+
} else {
73+
parallel = false;
74+
String scriptPath = args[0];
75+
String[] params = Arrays.copyOfRange(args, 1, args.length);
76+
receiver = new MessageReceiverThread(System.in);
77+
receiver.start();
78+
79+
prepare();
80+
run(scriptPath, params);
81+
}
5882
}
5983

6084
public static void prepare() {
@@ -68,7 +92,21 @@ public static void prepare() {
6892
PySystemState.add_package("processing.opengl");
6993
}
7094

71-
95+
/*
96+
* Called by PythonPApplet when it's exiting
97+
* Get rid of all references to our applet
98+
*
99+
* ...this tangle of callbacks probably makes me a bad person
100+
*/
101+
static void sketchExiting(){
102+
if (parallel) {
103+
scrub();
104+
constructedApplet = null;
105+
sys = null;
106+
} else {
107+
System.exit(0);
108+
}
109+
}
72110

73111
/*
74112
* Run.
@@ -95,27 +133,57 @@ public static void run(String scriptPath, String[] params){
95133
for (String name : sketchFunctions){
96134
PyFunction function = (PyFunction) interp.get(name);
97135
if(function != null){
98-
System.out.println("found "+name);
99136
constructedApplet.inject(name, function);
100137
}
101138
}
102139

103140
//run the sketch!
104-
PythonPApplet.runSketch(params, constructedApplet);
141+
PythonPApplet.runSketchOpen(params, constructedApplet);
105142

106143
} catch (Exception e){
107144
System.err.println("Error running sketch: " + e.getMessage()); //TODO
108145
e.printStackTrace();
109-
System.exit(1);
146+
if(constructedApplet != null){
147+
constructedApplet.exit();
148+
}
110149
}
111150
}
112151

113152
public static void scrub(){
114153
interp.exec(scrub);
115154
}
116155

117-
public static void runSketch(String[] params, PythonPApplet constructedApplet){
118-
GraphicsDevice displayDevice;
156+
157+
158+
/*
159+
* Class to handle receiving messages from the PDE
160+
* not to be confused with Communicator.MessageReceiverThread; same idea, different location
161+
*/
162+
private static class MessageReceiverThread extends Thread{
163+
BufferedReader messageReader;
164+
public boolean running;
119165

166+
public MessageReceiverThread(InputStream messageStream){
167+
this.messageReader = new BufferedReader(new InputStreamReader(messageStream));
168+
this.running = true;
169+
}
170+
171+
public void run() {
172+
try {
173+
String currentLine;
174+
175+
// continually read messages
176+
while ((currentLine = messageReader.readLine()) != null && running) {
177+
try {
178+
if (currentLine.indexOf("__STOP__") != -1) {
179+
// PDE is telling us to kill the applet
180+
if (constructedApplet != null) {
181+
constructedApplet.exit();
182+
}
183+
}
184+
} catch (Exception e) {}
185+
}
186+
} catch (Exception e) {}
187+
}
120188
}
121189
}

0 commit comments

Comments
 (0)