From 0f770551cebca90c92b7a39b0e0135a445af51f9 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 22 Mar 2008 02:28:22 +0000 Subject: merging in pdj-0.8.4.tar.gz from http://www.le-son666.com/software/pdj/ svn path=/trunk/externals/loaders/pdj/; revision=9624 --- LICENSE | 2 +- Linux-build.properties | 12 +- Mac OS X-build.properties | 2 +- README | 80 ++++++---- Windows XP-build.properties | 1 + build.properties | 2 +- build.xml | 152 +++++++++---------- lib/ant/cpptasks.jar | Bin 345204 -> 345211 bytes res/docs/pdj.odt | Bin 0 -> 38324 bytes res/docs/pdj.pdf | Bin 0 -> 98167 bytes res/pdj.properties | 2 +- src/MaxClock.c | 2 +- src/MaxObject.c | 13 +- src/MaxSystem.c | 2 +- src/init.c | 16 +- src/java/com/cycling74/max/MaxObject.java | 4 +- .../com/cycling74/max/MaxRuntimeException.java | 8 +- src/java/com/cycling74/max/MaxSystem.java | 2 +- src/java/com/cycling74/msp/AudioFileBuffer.java | 2 +- src/java/com/cycling74/net/TcpReceiver.java | 89 +++++++++++ src/java/com/cycling74/net/TcpSender.java | 103 +++++++++++++ src/java/com/cycling74/net/UdpReceiver.java | 84 +++++++++++ src/java/com/cycling74/net/UdpSender.java | 84 +++++++++++ src/java/com/e1/pdj/JikesCompiler.java | 1 - src/java/com/e1/pdj/PDJSystem.java | 20 +-- src/java/pdj_test_class.java | 3 +- src/pd_patch/osx_extsched_fix.patch | 29 ++++ src/pdj-linux.c | 27 +++- src/pdj-osx.c | 165 ++++++++++++++++++++- src/pdj.h | 9 +- src/pdj~.c | 8 +- src/type_handler.c | 4 +- www/index.html | 13 +- 33 files changed, 767 insertions(+), 174 deletions(-) create mode 100644 res/docs/pdj.odt create mode 100644 res/docs/pdj.pdf create mode 100644 src/java/com/cycling74/net/TcpReceiver.java create mode 100644 src/java/com/cycling74/net/TcpSender.java create mode 100644 src/java/com/cycling74/net/UdpReceiver.java create mode 100644 src/java/com/cycling74/net/UdpSender.java create mode 100644 src/pd_patch/osx_extsched_fix.patch diff --git a/LICENSE b/LICENSE index fd043d8..ea0404c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2007, Pascal Gauthier +Copyright (c) 2004-2008, Pascal Gauthier All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Linux-build.properties b/Linux-build.properties index 12b5a90..e91b75d 100644 --- a/Linux-build.properties +++ b/Linux-build.properties @@ -1,15 +1,19 @@ -# property file for Linux +# property file for Linux, now with default ubuntu packages # put the path of where the jdk (java sdk) is installed -jdk.home=/usr/local/java +jdk.home=/usr/lib/jvm/java-6-sun # put the path of where pd is installed -pd.home=/home/asb2m10/pd-0.39-0 +pd.home=/usr # common linux properties isLinux=true compiler=gcc linker.type=shared platform=linux + +# 64-bits system ? uncomment this +#jdk.libs=${jdk.home}/jre/lib/amd64 + jdk.libs=${jdk.home}/jre/lib/i386 -pdj.outfile=${dist.dir}/pdj \ No newline at end of file +pdj.outfile=${dist.dir}/pdj diff --git a/Mac OS X-build.properties b/Mac OS X-build.properties index 95e4761..f58ccf2 100644 --- a/Mac OS X-build.properties +++ b/Mac OS X-build.properties @@ -3,7 +3,7 @@ # put the root of your pd path installation pd.home=/Applications/pd.app/Contents/Resources -# set this to 'pd_darwin' if you are building for PowerPC +# now building fat binaries pdj.archBuild=d_fat # common OS X properties diff --git a/README b/README index 5737e2a..53fbd90 100644 --- a/README +++ b/README @@ -2,8 +2,7 @@ pdj - java plugin interface to pure-data ########################################################################### -RELEASE 0.8.3 / September 2007 - +RELEASE 0.8.4 / March 2008 PDJ enables you to write java code to interact with pure-data objects. The API is totally based on Cycling74 Max/MSP 'mxj' object implementation. This @@ -22,15 +21,10 @@ IMPLEMENTED: * Atom 98% * MaxSystem 90% * MaxQelem 90% - * MSPObject 85% (missing signal in/outlet detection) + * MSPObject 90% (missing signal in/outlet detection) * MSPPerformable 100% * MaxPatcher 5% -TODO: - - * MSPObject connection status - * MaxBox/MaxPatcher object; inspiration from dyn~ (kudo Mr. Grill!) - LIMITATION: * Signal inlets cannot be hot inlets for receiving atom message. @@ -38,13 +32,6 @@ LIMITATION: to this inlet, pdj won't be able to process it; float or symbol. This looks like a work as designed in pd. -BUGS: - - * OS X: cannot use AWT classes with OS X because of a weird bug - that locks the thread when the GUI libraries are loaded. - -> http://lists.apple.com/archives/java-dev/2004/Mar/msg00910.html - this solution has been tested but the loadLibrary still hang. - WORKAROUNDS: * on most cases you don't have to put the JVM libs dir to the @@ -53,34 +40,32 @@ WORKAROUNDS: * on some machines, the System.out redirection can crash PD. If it is the case, you can disable it in the pdj.properties file; check the property: pdj.redirect-pdio. + * You must use pdj pd scheduler if you need to use AWT with OS X. + See below. REQUIEREMENTS: - * pure-data 0.38.x or better + * pure-data 0.41.x * java JDK version 1.4.x or better; use 1.5 if you can ! - * works on linux, windows + * works on linux, windows and OS X (10.3.9) REQUIEREMENTS FOR BUILDING: * apache ant 1.6.x or better + * comes with it's own version of cpptask that has been patched for + linking with GCC/OS X with the -arch argument. * c compiler INSTALLATION: * if you are using the source distribution, build it before -> download java sdk from java.sun.com (unless you are using OS X) - -> download apache ant for ant.apache.org -> edit file -build.properties -> in the root directory of pdj, run 'ant package' - * add the pdj external (pdj.pd_linux/pd.dll/pd.pd_dawrin) directory - to your pd path (very important on OS X) * the other files of the original binary directory must be in the same directory * double check dist/pdj.properties to be sure that the JAVA environment parameters are right - * === OS X WARNING ==== - I am working on a universal binary of pdj. This is planned on version - 0.8.4. If you really need a OS X build, email me. USAGE: @@ -88,18 +73,57 @@ USAGE: * create a pdj object with the name of the java class; if you have not compiled it before, pdj will do it for you +USING AWT WITH OS X: + + Unlike Linux or Windows, you cannot just simply fire-up a AWT form on OS X. + This is because the event GUI mecanism has these limitation : + + --> A CFRunLoopRun must be park in the main thread before the main loop is + started + --> Java must be run in a secondary thread. + + Since this prerequisite need a pure-data patch, we will write our own pd + scheduler. This scheduler will simple fire-up another thread that will + run the real pd scheduler (m_mainloop) and park the main thread with a + CFRunLoopRun. + + To be able to use the pdj scheduler, you need to apply a patch to pd. (Yes + there is a bug with the -schedlib option). The patch is available in the + directory src/pd_patch/osx_extsched_fix.patch. This patch has been made on + a miller's 41.2 pd version. + + Once the patch is applied and compiled, you must configure your pure-data + environement to add the option : -schedlib [fullpath of the pdj external + without the extension]. Use the menu Pd -> Preference -> Startup to do this. + Don't forget to click on [Save All Settings]. + + Be carfull when you configure this switch since it can crash PD on startup. + If you do have the problem; you will have to delete all pd-preferences by + deleting file: ~/Library/Preferences/org.puredata.pd.plist + + If the scheduler is loaded, you should have this pd message : + 'pdj: using pdj scheduler for Java AWT' + CHANGELOG: + + --- VERSION 0.8.4 --- + * amd64 for Linux (thanks to Sergio Torres-Perez) + * getInlets() starts at 0 not 1 (thanks to MiS) + * OS X gets pdj path by it's library path + * OS X powerpc/intel distribution + * added a user guide + * FIXED: AWT usage on OS X + --- VERSION 0.8.3 --- * Atom.getInt() on a float now works. * corrected some classpath definition issues with windows * bypass the java compilation with pdj.compiler=null * remove dependencies task for cpptasks.jar (now part of distribution) * FIXED: comment on property pdj.vm_args failed to initialize VM - * BUG: cannot link with OS X and cpptasks. Planned on 0.8.4 --- VERSION 0.8.2 --- * if javac is set, using the javac compiler from the JAVA_HOME first - * optimizations (main thread JVM and symbol method resolution) + * optimization (main thread JVM and symbol method resolution) * FIXED: using pdj.classpath with directories * FIXED: search path on file in the current directory * FIXED: leak with open_path and casting warnings @@ -144,7 +168,7 @@ CHANGELOG: --- VERSION 0.5 --- * method inlet resolution (bang->float->list->anything) now works - * windows support (premilinary support) + * windows support (preliminary support) * auto-compiling class of every .java in /class (max -1; pdj +1) --- VERSION 0.4 --- @@ -166,9 +190,11 @@ CHANGELOG: THANKS: + * Sergio Torres-Perez * Thomas Grill + * Michal Seta * patrick a 11h11 * pd-mtl crew ! -(c) Pascal Gauthier 2004-2007, under BSD like license +(c) Pascal Gauthier 2004-2008, under BSD like license asb2m10@users.sourceforge.net diff --git a/Windows XP-build.properties b/Windows XP-build.properties index 0d777bf..868579e 100644 --- a/Windows XP-build.properties +++ b/Windows XP-build.properties @@ -5,6 +5,7 @@ jdk.home=C:/Java/jdk1.6.0_02 # put the path of where pd is installed pd.home=C:/Projets/pd + # common windows properties isWin32=true compiler=msvc diff --git a/build.properties b/build.properties index e28db31..656f89a 100644 --- a/build.properties +++ b/build.properties @@ -2,7 +2,7 @@ # PDJ packaging version # ========================================================================= -pdj.version=0.8.3 +pdj.version=0.8.4 # Various path definition # ========================================================================= diff --git a/build.xml b/build.xml index a1414c7..69bc840 100644 --- a/build.xml +++ b/build.xml @@ -1,28 +1,27 @@ - + + - - + - + com.cycling74.max.MaxObject, + com.cycling74.max.MaxClock, + com.cycling74.max.MaxSystem, + com.cycling74.msp.MSPBuffer, + com.cycling74.msp.MSPObject"/> + - + @@ -35,110 +34,106 @@ - - + + - - + + - + - + - - + + + outfile="${pdj.outfile}" name="${compiler}"> - + - + - - - - - - - - + + + + + + + + - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - + + + - - @@ -146,7 +141,7 @@ - + @@ -155,50 +150,45 @@ - - - + - + - + - + - - - + - + - + + - The MXJ Java API for pure-data + The MXJ Java API for pure-data

This API is based on MXJ for Max/MSP.

]]>
- Max/MSP by Cycling74. Please see original MXJ implementation.]]> @@ -208,12 +198,11 @@ - - + @@ -230,11 +219,12 @@ - + - + + diff --git a/lib/ant/cpptasks.jar b/lib/ant/cpptasks.jar index 1b6e6ad..becac8e 100644 Binary files a/lib/ant/cpptasks.jar and b/lib/ant/cpptasks.jar differ diff --git a/res/docs/pdj.odt b/res/docs/pdj.odt new file mode 100644 index 0000000..c9df624 Binary files /dev/null and b/res/docs/pdj.odt differ diff --git a/res/docs/pdj.pdf b/res/docs/pdj.pdf new file mode 100644 index 0000000..49894ac Binary files /dev/null and b/res/docs/pdj.pdf differ diff --git a/res/pdj.properties b/res/pdj.properties index 1f00908..9637e9b 100644 --- a/res/pdj.properties +++ b/res/pdj.properties @@ -13,7 +13,7 @@ # add your jars or directories of jars seperated with a ':' for unix and # ';' for windows # -pdj.system-classpath=/home/asb2m10/workspace/mxdublin/work/mxdublin.jar +pdj.system-classpath=/home/asb2m10/Documents/workspace/mxdublin/work/mxdublin.jar # by default from where the pdj.pd_linux is located, every .jar in # ${pdj.home}/lib will be added to the pdj classpath diff --git a/src/MaxClock.c b/src/MaxClock.c index e7e5886..c5694fd 100644 --- a/src/MaxClock.c +++ b/src/MaxClock.c @@ -11,7 +11,7 @@ typedef struct _clockCtnr { static t_clockCtnr *getClock(JNIEnv *env, jobject obj) { - return (t_clockCtnr *) (*env)->GetLongField(env, obj, pdjCaching.FIDMaxClock_clock_ptr); + return (t_clockCtnr *) JPOINTER_CAST (*env)->GetLongField(env, obj, pdjCaching.FIDMaxClock_clock_ptr); } diff --git a/src/MaxObject.c b/src/MaxObject.c index 3c77f49..cffbd76 100644 --- a/src/MaxObject.c +++ b/src/MaxObject.c @@ -4,7 +4,7 @@ static t_pdj *getMaxObject(JNIEnv *env, jobject obj) { - t_pdj *ret = (t_pdj *) (*env)->GetLongField(env, obj, + t_pdj *ret = (t_pdj *) JPOINTER_CAST (*env)->GetLongField(env, obj, pdjCaching.FIDMaxObject_pdobj_ptr); if ( ret == NULL ) @@ -27,8 +27,7 @@ JNIEXPORT jlong JNICALL Java_com_cycling74_max_MaxObject_newInlet } proxy = (t_inlet_proxy *) pd_new(inlet_proxy); - pdj->nb_inlet++; - proxy->idx = pdj->nb_inlet; + proxy->idx = pdj->nb_inlet++; proxy->peer = pdj; return (jlong) inlet_new(&pdj->x_obj, &proxy->x_obj.ob_pd, 0, 0); @@ -53,28 +52,28 @@ JNIEXPORT jlong JNICALL Java_com_cycling74_max_MaxObject_newOutlet JNIEXPORT void JNICALL Java_com_cycling74_max_MaxObject_doOutletBang (JNIEnv *env, jobject obj, jlong outlet) { - t_outlet *x = (t_outlet *) ((unsigned int) outlet); + t_outlet *x = (t_outlet *) (JPOINTER_CAST outlet); outlet_bang(x); } JNIEXPORT void JNICALL Java_com_cycling74_max_MaxObject_doOutletFloat (JNIEnv *env, jobject obj, jlong outlet , jfloat value) { - t_outlet *x = (t_outlet *) ((unsigned int) outlet); + t_outlet *x = (t_outlet *) (JPOINTER_CAST outlet); outlet_float(x, value); } JNIEXPORT void JNICALL Java_com_cycling74_max_MaxObject_doOutletSymbol (JNIEnv *env, jobject obj, jlong outlet, jstring value) { - t_outlet *x = (t_outlet *) ((unsigned int) outlet); + t_outlet *x = (t_outlet *) (JPOINTER_CAST outlet); outlet_symbol(x, jstring2symbol(env, value)); } JNIEXPORT void JNICALL Java_com_cycling74_max_MaxObject_doOutletAnything (JNIEnv *env, jobject obj, jlong outlet, jstring str, jobjectArray value) { - t_outlet *x = (t_outlet *) ((unsigned int) outlet); + t_outlet *x = (t_outlet *) (JPOINTER_CAST outlet); t_atom args[MAX_ATOMS_STACK]; int argc; diff --git a/src/MaxSystem.c b/src/MaxSystem.c index c506fa2..ea48ab2 100644 --- a/src/MaxSystem.c +++ b/src/MaxSystem.c @@ -158,7 +158,7 @@ JNIEXPORT jboolean JNICALL Java_com_cycling74_max_MaxSystem_sendMessageToBoundOb JNIEXPORT jstring JNICALL Java_com_cycling74_max_MaxSystem_locateFile (JNIEnv *env, jclass cls, jstring filename) { - const jbyte *file = (*env)->GetStringUTFChars(env, filename, NULL); + const char *file = (*env)->GetStringUTFChars(env, filename, NULL); char fullpath[MAXPDSTRING], *pfullpath; FILE *fd; diff --git a/src/init.c b/src/init.c index 4666367..b147db4 100644 --- a/src/init.c +++ b/src/init.c @@ -1,5 +1,5 @@ /** - * This code is very ugly and needs rewrite. PERIOD. + * initialization */ #include @@ -97,7 +97,7 @@ static void load_properties() { } -static void copyToJavaSystemProperties(JNIEnv *env) { +void copyToJavaSystemProperties(JNIEnv *env) { jclass system = (*env)->FindClass(env, "java/lang/System"); jmethodID id = (*env)->GetStaticMethodID(env, system, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); int i; @@ -232,8 +232,8 @@ static int linkClasses(JNIEnv *env) { } -void buildVMOptions(jint *nb, JavaVMOption *options) { - static char cp[BUFFER_SIZE], pdj_cp[BUFFER_SIZE]; +static void buildVMOptions(jint *nb, JavaVMOption *options) { + static char cp[BUFFER_SIZE]; char installPath[BUFFER_SIZE]; char *prop; char *token, *work; @@ -316,7 +316,7 @@ JNIEnv *init_jvm(void) { vm_args.options = opt; vm_args.version = JNI_VERSION_1_4; vm_args.ignoreUnrecognized = JNI_FALSE; - + vm_type = pdj_getProperty("pdj.vm_type"); if ( vm_type == NULL ) { error("pdj: unknown vm_type, using client"); @@ -332,12 +332,12 @@ JNIEnv *init_jvm(void) { error("pdj: unable to create JVM: JNI_CreateJavaVM = %d", rc); return NULL; } - - copyToJavaSystemProperties(jni_env); - if ( initIDCaching(jni_env) != 0) { + + if ( initIDCaching(jni_env) != 0 ) { return NULL; } + copyToJavaSystemProperties(jni_env); if ( linkClasses(jni_env) != 0 ) { return NULL; } diff --git a/src/java/com/cycling74/max/MaxObject.java b/src/java/com/cycling74/max/MaxObject.java index 3d07d49..15f2a16 100644 --- a/src/java/com/cycling74/max/MaxObject.java +++ b/src/java/com/cycling74/max/MaxObject.java @@ -806,7 +806,7 @@ public class MaxObject { } /** - * Tries to instanciate a MaxObject. + * Tries to instantiate a MaxObject. * @param name fq java name * @param _pdobj_ptr C pointer to pd object * @param args objects arguments @@ -844,7 +844,7 @@ public class MaxObject { pushPdjPointer(_pdobj_ptr); - // instanciate the object + // instantiate the object if ( args.length > 0 ) { try { Object argValue[] = new Object[1]; diff --git a/src/java/com/cycling74/max/MaxRuntimeException.java b/src/java/com/cycling74/max/MaxRuntimeException.java index 9909a5c..8043aa9 100644 --- a/src/java/com/cycling74/max/MaxRuntimeException.java +++ b/src/java/com/cycling74/max/MaxRuntimeException.java @@ -5,11 +5,15 @@ package com.cycling74.max; */ public class MaxRuntimeException extends RuntimeException { + public MaxRuntimeException() { + } + public MaxRuntimeException(String msg) { super(msg); } - public MaxRuntimeException() { - } + public MaxRuntimeException(Exception e) { + super(e); + } } diff --git a/src/java/com/cycling74/max/MaxSystem.java b/src/java/com/cycling74/max/MaxSystem.java index 3a29540..dd8fe48 100644 --- a/src/java/com/cycling74/max/MaxSystem.java +++ b/src/java/com/cycling74/max/MaxSystem.java @@ -171,7 +171,7 @@ public class MaxSystem { } // constants - public static String MXJ_VERSION = "pdj 0.8.3"; + public static String MXJ_VERSION = "pdj 0.8.4"; public static final int PATH_STYLE_COLON = 2; public static final int PATH_STYLE_MAX = 0; diff --git a/src/java/com/cycling74/msp/AudioFileBuffer.java b/src/java/com/cycling74/msp/AudioFileBuffer.java index b2e76f3..eebffa1 100644 --- a/src/java/com/cycling74/msp/AudioFileBuffer.java +++ b/src/java/com/cycling74/msp/AudioFileBuffer.java @@ -12,7 +12,7 @@ import javax.sound.sampled.UnsupportedAudioFileException; import com.cycling74.max.MessageReceiver; /** - * Work in progress, target: 0.8.4 + * Work in progress, target: 0.8.5 */ class AudioFileBuffer { diff --git a/src/java/com/cycling74/net/TcpReceiver.java b/src/java/com/cycling74/net/TcpReceiver.java new file mode 100644 index 0000000..f449517 --- /dev/null +++ b/src/java/com/cycling74/net/TcpReceiver.java @@ -0,0 +1,89 @@ +package com.cycling74.net; + +import java.lang.reflect.Method; +import java.net.DatagramPacket; +import java.net.DatagramSocket; + +import com.cycling74.max.Atom; +import com.cycling74.max.MaxRuntimeException; +import com.cycling74.max.MaxSystem; + +/** + * This portion of code is scheduled for pdj-0.8.5 + * IT IS NOT FUNCTIONAL + */ +public class TcpReceiver implements Runnable { + DatagramSocket receiver; + DatagramPacket packet; + + Method callback = null; + Object instance; + + String debugString = null; + int port; + boolean runnable = true; + + public void close() { + if ( receiver == null ) + return; + runnable = false; + receiver.close(); + } + + public int getPort() { + return port; + } + + public void setActive(boolean active) { + if ( active == false ) { + runnable = true; + new Thread(this).start(); + } else { + close(); + } + + } + + public void setCallback(Object caller, String methodName) { + try { + callback = caller.getClass().getDeclaredMethod(methodName, new Class[] { Atom.class }); + instance = caller; + } catch (Exception e) { + throw new MaxRuntimeException(e); + } + } + + public void setPort(int port) { + setActive(false); + this.port = port; + } + + public void setDebugString(String debugString) { + this.debugString = debugString; + } + + public void run() { + DatagramPacket packet = new DatagramPacket(new byte[4096], 4096); + Object callerArgs[] = new Object[1]; + + try { + while(runnable) { + receiver.receive(packet); + String msg = new String(packet.getData(), 0, packet.getLength()); + if ( debugString != null ) + MaxSystem.post(debugString + " " + msg); + callerArgs[0] = Atom.parse(msg); + try { + callback.invoke(instance, callerArgs); + } catch( Exception e ) { + e.printStackTrace(); + } + } + } catch (Exception e) { + if ( runnable != false) { + runnable = false; + throw new MaxRuntimeException(e); + } + } + } +} diff --git a/src/java/com/cycling74/net/TcpSender.java b/src/java/com/cycling74/net/TcpSender.java new file mode 100644 index 0000000..2ba0f67 --- /dev/null +++ b/src/java/com/cycling74/net/TcpSender.java @@ -0,0 +1,103 @@ +package com.cycling74.net; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; + +import com.cycling74.max.Atom; +import com.cycling74.max.MaxRuntimeException; + +/** + * This portion of code is scheduled for pdj-0.8.5 + * IT IS NOT FUNCTIONAL + */ +public class TcpSender { + DatagramSocket sender; + DatagramPacket packet; + String address = null; + int port = -1; + + public TcpSender() { + } + + public TcpSender(String address, int port) { + this.address= address; + this.port = port; + } + + public void send(Atom args[]) { + if ( sender == null ) + initsocket(); + + byte buff[] = Atom.toOneString(args).getBytes(); + packet.setData(buff, 0, buff.length); + try { + sender.send(packet); + } catch (IOException e) { + throw new MaxRuntimeException(e); + } + } + + public void send(int i) { + if ( sender == null ) + initsocket(); + + byte buff[] = Integer.toString(i).getBytes(); + packet.setData(buff, 0, buff.length); + try { + sender.send(packet); + } catch (IOException e) { + throw new MaxRuntimeException(e); + } + } + + public void send(float f) { + if ( sender == null ) + initsocket(); + + byte buff[] = Float.toString(f).getBytes(); + packet.setData(buff, 0, buff.length); + try { + sender.send(packet); + } catch (IOException e) { + throw new MaxRuntimeException(e); + } + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + if ( sender != null ) { + sender = null; + sender.close(); + } + this.address = address; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + if ( sender != null ) { + sender = null; + sender.close(); + } + this.port = port; + } + + private synchronized void initsocket() { + if ( sender != null ) + return; + try { + sender = new DatagramSocket(); + sender.connect(new InetSocketAddress(address, port)); + packet = new DatagramPacket(new byte[0], 0); + } catch (Exception e) { + throw new MaxRuntimeException(e); + } + } +} diff --git a/src/java/com/cycling74/net/UdpReceiver.java b/src/java/com/cycling74/net/UdpReceiver.java new file mode 100644 index 0000000..fd47e25 --- /dev/null +++ b/src/java/com/cycling74/net/UdpReceiver.java @@ -0,0 +1,84 @@ +package com.cycling74.net; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; + +import com.cycling74.max.Atom; +import com.cycling74.max.MaxRuntimeException; +import com.cycling74.max.MaxSystem; +import com.cycling74.max.Callback; + +/** + * This portion of code is scheduled for pdj-0.8.5 + * IT IS NOT FUNCTIONAL + */ +public class UdpReceiver implements Runnable { + DatagramSocket receiver; + DatagramPacket packet; + + Callback callback; + + String debugString = null; + int port; + boolean runnable = true; + + public void close() { + if ( receiver == null ) + return; + runnable = false; + receiver.close(); + } + + public int getPort() { + return port; + } + + public void setActive(boolean active) { + if ( active == false ) { + runnable = true; + new Thread(this).start(); + } else { + close(); + } + + } + + public void setCallback(Object caller, String methodName) { + callback = new Callback(caller, methodName); + } + + public void setPort(int port) { + setActive(false); + this.port = port; + } + + public void setDebugString(String debugString) { + this.debugString = debugString; + } + + public void run() { + DatagramPacket packet = new DatagramPacket(new byte[4096], 4096); + Object callerArgs[] = new Object[1]; + + try { + while(runnable) { + receiver.receive(packet); + String msg = new String(packet.getData(), 0, packet.getLength()); + if ( debugString != null ) + MaxSystem.post(debugString + " " + msg); + callerArgs[0] = Atom.parse(msg); + + /* try { + callback.invoke(instance, callerArgs); + } catch( Exception e ) { + e.printStackTrace(); + } */ + } + } catch (Exception e) { + if ( runnable != false) { + runnable = false; + throw new MaxRuntimeException(e); + } + } + } +} diff --git a/src/java/com/cycling74/net/UdpSender.java b/src/java/com/cycling74/net/UdpSender.java new file mode 100644 index 0000000..6ef7e34 --- /dev/null +++ b/src/java/com/cycling74/net/UdpSender.java @@ -0,0 +1,84 @@ +package com.cycling74.net; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; + +import com.cycling74.max.Atom; +import com.cycling74.max.MaxRuntimeException; + +/** + * This portion of code is scheduled for pdj-0.8.5 + * IT IS NOT FUNCTIONAL + */ +public class UdpSender { + InetAddress inetAddress; + DatagramSocket sender; + boolean init; + + String address = null; + int port = -1; + + public UdpSender() { + } + + public UdpSender(String address, int port) { + this.address = address; + this.port = port; + initsocket(); + } + + public void send(Atom args[]) { + send(Atom.toOneString(args).getBytes()); + } + + public void send(int i) { + send(Integer.toString(i).getBytes()); + } + + public void send(float f) { + send(Float.toString(f).getBytes()); + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + initsocket(); + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + initsocket(); + } + + synchronized void initsocket() { + try { + sender = null; + inetAddress = InetAddress.getByName(address); + sender = new DatagramSocket(); + } catch (Exception e) { + throw new MaxRuntimeException(e); + } + } + + void send(byte buff[]) { + if ( sender == null ) + throw new MaxRuntimeException("UdpSender is not initialized"); + + try { + DatagramPacket packet = new DatagramPacket(buff, buff.length, inetAddress, port); + sender.send(packet); + } catch (IOException e) { + throw new MaxRuntimeException(e); + } + + } +} diff --git a/src/java/com/e1/pdj/JikesCompiler.java b/src/java/com/e1/pdj/JikesCompiler.java index f9337b2..041a4f7 100644 --- a/src/java/com/e1/pdj/JikesCompiler.java +++ b/src/java/com/e1/pdj/JikesCompiler.java @@ -1,6 +1,5 @@ package com.e1.pdj; -import java.io.*; import com.cycling74.max.MaxSystem; public class JikesCompiler extends GenericCompiler { diff --git a/src/java/com/e1/pdj/PDJSystem.java b/src/java/com/e1/pdj/PDJSystem.java index 3d30a53..1fd50d2 100644 --- a/src/java/com/e1/pdj/PDJSystem.java +++ b/src/java/com/e1/pdj/PDJSystem.java @@ -7,6 +7,7 @@ import java.awt.Frame; import java.awt.Toolkit; import java.io.*; +import java.awt.GraphicsEnvironment; /** * Startup class for pdj. */ @@ -50,7 +51,7 @@ public class PDJSystem { // this is a hack to be sure that statics of MaxSystem are loaded // before everything Class cls = MaxSystem.class; - + String osname = System.getProperty("os.name"); if ( osname.indexOf("Linux") != -1 ) { @@ -71,20 +72,13 @@ public class PDJSystem { if ( osname.indexOf("OS X") != -1 ) { // maps PD object as a JVM native library - try { - Runtime.getRuntime().load(pdjHome + "/pdj.pd_darwin"); - } catch (UnsatisfiedLinkError e ) { - Runtime.getRuntime().load(pdjHome + "/pdj.pd_imac"); - } + Runtime.getRuntime().load(pdjHome + "/pdj.d_fat"); loaded = 1; - - // this will initialize the AWT component in another thread - new Thread(new Runnable() { - public void run() { - Class clz = Component.class; - } - }).start(); + if ( System.getenv("PDJ_USE_AWT") != null ) { + GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + Toolkit.getDefaultToolkit(); + } GenericCompiler.rtJar = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar:"; return; diff --git a/src/java/pdj_test_class.java b/src/java/pdj_test_class.java index ff6f756..61cf804 100644 --- a/src/java/pdj_test_class.java +++ b/src/java/pdj_test_class.java @@ -9,6 +9,7 @@ public class pdj_test_class extends MaxObject implements Executable { clock = new MaxClock(this); declareAttribute("patate"); + declareIO(2,2); } public pdj_test_class(Atom args[]) { @@ -49,7 +50,7 @@ public class pdj_test_class extends MaxObject implements Executable { } protected void inlet(float f) { - post("le float " + f); + post("le float " + f + "inlet " + getInlet()); } void wer(Atom[] atom) { diff --git a/src/pd_patch/osx_extsched_fix.patch b/src/pd_patch/osx_extsched_fix.patch new file mode 100644 index 0000000..29195e4 --- /dev/null +++ b/src/pd_patch/osx_extsched_fix.patch @@ -0,0 +1,29 @@ +--- s_loader.orig 2008-03-12 11:19:15.000000000 -0400 ++++ s_loader.c 2008-03-12 11:18:09.000000000 -0400 +@@ -247,7 +247,7 @@ + typedef int (*t_externalschedlibmain)(const char *); + t_externalschedlibmain externalmainfunc; + char filename[MAXPDSTRING]; +- snprintf(filename, sizeof(filename), "%s.%s", externalschedlibname, ++ snprintf(filename, sizeof(filename), "%s%s", externalschedlibname, + sys_dllextent); + sys_bashfilename(filename, filename); + #ifdef MSW +@@ -255,7 +255,7 @@ + HINSTANCE ntdll = LoadLibrary(filename); + if (!ntdll) + { +- post("%s: couldn't load external scheduler lib ", filename); ++ fprintf(stderr, "%s: couldn't load external scheduler lib ", filename); + return (0); + } + externalmainfunc = +@@ -266,7 +266,7 @@ + void *dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (!dlobj) + { +- post("%s: %s", filename, dlerror()); ++ fprintf(stderr, "%s: %s\n", filename, dlerror()); + return (0); + } + externalmainfunc = (t_externalschedlibmain)dlsym(dlobj, diff --git a/src/pdj-linux.c b/src/pdj-linux.c index 63bb015..5af919f 100644 --- a/src/pdj-linux.c +++ b/src/pdj-linux.c @@ -4,6 +4,19 @@ #include #include "pdj.h" +// test if this system is amd64 +#ifdef __LP64__ + #define ARCH "amd64" + #define MAPPOS 73 +#else + #define ARCH "i386" + #define MAPPOS 49 +#endif + +/* + * This is why it is called getuglylibpath... getting the info from /proc... + * if you have a better idea; well I would like to be informed + */ int getuglylibpath(char *path) { char buffer[BUFFER_SIZE]; FILE *f; @@ -20,7 +33,7 @@ int getuglylibpath(char *path) { fgets(buffer, BUFFER_SIZE-1, f); if ( strstr(buffer, "pdj.pd_linux") != NULL ) { buffer[strlen(buffer) - 14] = 0; - strcpy(path, buffer+49); + strcpy(path, buffer + MAPPOS); fclose(f); return 0; } @@ -43,7 +56,7 @@ JNI_CreateJavaVM_func *linkjvm(char *vm_type) { if ( javahome == NULL ) { javahome = getenv("JAVA_HOME"); } else { - sprintf(work, "%s/jre/lib/i386/%s/libjvm.so", javahome, vm_type); + sprintf(work, "%s/jre/lib/" ARCH "/%s/libjvm.so", javahome, vm_type); libVM = dlopen(work, RTLD_LAZY); if ( libVM == NULL ) { @@ -60,20 +73,20 @@ JNI_CreateJavaVM_func *linkjvm(char *vm_type) { /* using LD_LIBRARY_PATH + putenv doesn't work, load std jvm libs * with absolute path. order is important. */ - sprintf(work, "%s/jre/lib/i386/%s/libjvm.so", javahome, vm_type); + sprintf(work, "%s/jre/lib/" ARCH "/%s/libjvm.so", javahome, vm_type); dlopen(work, RTLD_LAZY); - sprintf(work, "%s/jre/lib/i386/libverify.so", javahome); + sprintf(work, "%s/jre/lib/" ARCH "/libverify.so", javahome); dlopen(work, RTLD_LAZY); - sprintf(work, "%s/jre/lib/i386/libjava.so", javahome); + sprintf(work, "%s/jre/lib/" ARCH "/libjava.so", javahome); dlopen(work, RTLD_LAZY); - sprintf(work, "%s/jre/lib/i386/libmlib_image.so", javahome); + sprintf(work, "%s/jre/lib/" ARCH "/libmlib_image.so", javahome); dlopen(work, RTLD_LAZY); /* ELF should support dynamic LD_LIBRARY_PATH :( :( :( */ - sprintf(work, "%s/jre/lib/i386/libjava.so", javahome); + sprintf(work, "%s/jre/lib/" ARCH "/libjava.so", javahome); libVM = dlopen(work, RTLD_LAZY); } diff --git a/src/pdj-osx.c b/src/pdj-osx.c index bd2be18..7c5b281 100644 --- a/src/pdj-osx.c +++ b/src/pdj-osx.c @@ -2,12 +2,170 @@ #include #include #include +#include +#include +#include +#include #include "pdj.h" +/** + * === USING AWT WITH OS X + * + * Unlike Linux or Windows, you cannot just simply fire-up a AWT form on OS X. This is + * because the event GUI mecanism has these limitation : + * + * --> A CFRunLoopRun must be park in the main thread. + * --> Java must be run in a secondary thread. + * + * Since this prerequisite need a pure-data patch, we will write our own pd scheduler. + * This scheduler will simple fire-up another thread that will run the real pd + * scheduler (m_mainloop) and park the main thread with a CFRunLoopRun. + * + * To be able to use the pdj scheduler, you need to apply a patch to pd. (Yes there + * is a bug with the -schedlib option). The patch is available in the directory + * src/pd_patch/osx_extsched_fix.patch. This patch has been made on a miller's 41.2 + * pd version. + * + * Once the patch is applied and compiled, you must configure your pure-data environement + * to add the option : -schedlib [fullpath of the pdj external without the extension]. Use + * the menu Pd -> Preference -> Startup to do this. Don't forget to click on [Save All + * Settings]. + * + * Be carfull when you configure this switch since it can crash PD on startup. If you do + * have the problem; you will have to delete all pd-preference by deleting file: + * ~/Library/Preferences/org.puredata.pd.plist + * + * If the scheduler is loaded, you should have this pd message : + * 'pdj: using pdj scheduler for Java AWT.' + */ + +int rc_pd = 0xFF; +CFRunLoopRef cfrunloop; + + +/* setting the environment varible APP_NAME_ to the applications name */ +/* sets it for the application menu */ +void setAppName(const char * name) { + char a[32]; + pid_t id = getpid(); + sprintf(a,"APP_NAME_%ld",(long)id); + setenv(a, name, 1); +} + + +/** + * The main pd thread, will become a secondary thread to AWT. + */ +void *pdj_pdloop(void *notused) { + post("pdj: using pdj scheduler for Java AWT."); + rc_pd = 0; + + // this will tell the java init code to initialize AWT before anything + setenv("PDJ_USE_AWT", "true", 1); + + // we create the JVM now + init_jvm(); + + /* open audio and MIDI */ + sys_reopen_midi(); + sys_reopen_audio(); + + rc_pd = m_mainloop(); + + exit(rc_pd); +} + + +/* call back for dummy source used to make sure the CFRunLoop doesn't exit right away */ +/* This callback is called when the source has fired. */ +void sourceCallBack ( void *info ) { +} + + +/** + * This function is called when pdj is considered a scheduler on pd + */ +int pd_extern_sched(void *notused) { + CFRunLoopSourceContext sourceContext; + + /* Start the thread that runs the pure-data main thread and the VM. */ + pthread_t vmthread; + + setAppName("pdj"); + + /* create a new pthread copying the stack size of the primordial pthread */ + struct rlimit limit; + size_t stack_size = 0; + int rc = getrlimit(RLIMIT_STACK, &limit); + if (rc == 0) { + if (limit.rlim_cur != 0LL) { + stack_size = (size_t)limit.rlim_cur; + } + } + + pthread_attr_t thread_attr; + pthread_attr_init(&thread_attr); + pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + if (stack_size > 0) { + pthread_attr_setstacksize(&thread_attr, stack_size); + } + + /* Start the thread that we will start the pd main thread */ + pthread_create(&vmthread, &thread_attr, pdj_pdloop, NULL); + pthread_attr_destroy(&thread_attr); + + /* Create a a sourceContext to be used by our source that makes */ + /* sure the CFRunLoop doesn't exit right away */ + sourceContext.version = 0; + sourceContext.info = NULL; + sourceContext.retain = NULL; + sourceContext.release = NULL; + sourceContext.copyDescription = NULL; + sourceContext.equal = NULL; + sourceContext.hash = NULL; + sourceContext.schedule = NULL; + sourceContext.cancel = NULL; + sourceContext.perform = &sourceCallBack; + + /* Create the Source from the sourceContext */ + CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate(NULL, 0, &sourceContext); + + /* Use the constant kCFRunLoopCommonModes to add the source to the set of objects */ + /* monitored by all the common modes */ + CFRunLoopAddSource (CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); + + /* Park this thread in the runloop for Java */ + CFRunLoopRun(); + + return rc_pd; +} + + int getuglylibpath(char *path) { char fullpath[MAXPDSTRING], *pfullpath; + int cnt = _dyld_image_count(); + char *imagename = NULL; FILE *fd; + int i; + + // we get the bundle header, that contains the dyld header too... + struct mach_header* header = (struct mach_header*) &_mh_bundle_header; + + for(i=1;iExceptionDescribe(env);bug("ouch, assertion failed %s:%d\n", __FILE__, __LINE__);}} + #define JASSERT(v) { if ( v == NULL ) {(*env)->ExceptionDescribe(env);bug("ouch, jni assertion failed %s:%d\n", __FILE__, __LINE__);}} #undef DEBUG #define DEBUG(X) {X}; #else #define ASSERT(v) + #undef DEBUG #define DEBUG(X) #define JASSERT(v) #endif @@ -28,6 +29,12 @@ #define PATH_SEP ":" #endif +#ifdef __LP64__ + #define JPOINTER_CAST (unsigned long) +#else + #define JPOINTER_CAST (unsigned int) +#endif + // the JVM takes 50M; I don't care taking 4K... #define BUFFER_SIZE 4096 diff --git a/src/pdj~.c b/src/pdj~.c index d2f2a36..8ecdb5d 100644 --- a/src/pdj~.c +++ b/src/pdj~.c @@ -20,12 +20,13 @@ t_int *pdj_tilde_perform(t_int *w) { /* call the performer */ (*env)->CallVoidMethod(env, pdjt->pdj.obj, pdjt->performer, pdjt->_used_inputs, pdjt->_used_outputs); - + + /* set work to output outlets */ + work = i + 3; + /* if an exception occured, stop the dsp processing for this object */ if ( (*env)->ExceptionOccurred(env) ) { int tmp; - - work = i + 3; /* insert silence */ for (tmp=0;tmpouts_count;tmp++) { @@ -41,7 +42,6 @@ t_int *pdj_tilde_perform(t_int *w) { } /* copy buffer out */ - work = i + 3; for (i=0;iouts_count;i++) { t_sample *out = (t_sample *)(w[work+i]); (*env)->GetFloatArrayRegion(env, pdjt->outs[i], 0, sz, out); diff --git a/src/type_handler.c b/src/type_handler.c index 7089a31..0c7bc67 100644 --- a/src/type_handler.c +++ b/src/type_handler.c @@ -4,7 +4,7 @@ int jatom2atom(JNIEnv *env, jobject jatom, t_atom *atom) { int type = (*env)->GetIntField(env, jatom, pdjCaching.FIDAtom_type); - const jbyte *symbolValue; + const char *symbolValue; jstring value; switch(type) { @@ -121,7 +121,7 @@ jobjectArray atoms2jatoms(JNIEnv *env, int argc, t_atom *argv) { t_symbol *jstring2symbol(JNIEnv *env, jstring strvalue) { - const jbyte *tmp = (*env)->GetStringUTFChars(env, strvalue, NULL); + const char *tmp = (*env)->GetStringUTFChars(env, strvalue, NULL); t_symbol *value; JASSERT(tmp); diff --git a/www/index.html b/www/index.html index 219bed2..23abd9a 100644 --- a/www/index.html +++ b/www/index.html @@ -34,16 +34,19 @@ into the pdj object argument. If pdj finds out that the .java is younger than the .class, pdj will compile it for you.

Requirements:

  • pure-data -0.38.x or better
  • +0.40.x or better
  • java jdk 1.4.x or better; use java 1.5 !!!
  • apache ant 1.5.x or better for building
  • -
  • works on linux, os x (tested on 10.4) and windows
  • +
  • works on Linux / Windows / OS X
  • Download:

    -

    Download latest release here: pdj-0.8.3.tar.gz -/ pdj-0.8.3-win32.zip -(September 9 2006) +

    Download latest release here: pdj-0.8.4.tar.gz +/ pdj-0.8.4-win32.zip +/ pdj-0.8.4-osx.zip +(March 2008)

    +

    Documentation: pdj.pdf

    + Contact: asb2m10 .at. users.sourceforge.net -- cgit v1.2.1