From 5d63b1b2a6968f9c0146e1946b72ca6073370fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Sun, 19 Jul 2009 15:56:13 +0000 Subject: updated to 0.8.5 svn path=/trunk/externals/loaders/pdj/; revision=11874 --- .settings/org.eclipse.cdt.core.prefs | 3 +- Mac OS X-build.properties | 6 +- README | 31 +++-- Windows XP-build.properties | 7 +- build.properties | 2 +- build.xml | 154 ++++++++++++++++--------- lib/ant/cpptasks.jar | Bin 345211 -> 345202 bytes res/docs/pdj.odt | Bin 38324 -> 22922 bytes res/docs/pdj.pdf | Bin 98167 -> 115535 bytes src/MaxObject.c | 9 +- src/init.c | 128 ++++++++++++++++++++ src/java/com/cycling74/max/Callback.java | 22 +++- src/java/com/cycling74/max/MaxObject.java | 2 +- src/java/com/cycling74/max/MaxSystem.java | 6 +- src/java/com/cycling74/max/package.html | 2 +- src/java/com/cycling74/msp/MSPPerformable.java | 4 +- src/java/com/cycling74/net/TcpReceiver.java | 97 +++++++++++----- src/java/com/cycling74/net/TcpSender.java | 92 ++++++--------- src/java/com/cycling74/net/UdpReceiver.java | 64 ++++++---- src/java/com/cycling74/net/UdpSender.java | 45 ++++++-- src/java/com/cycling74/net/package.html | 5 + src/java/com/e1/pdj/PDJSystem.java | 58 +++------- src/java/com/e1/pdj/test/CallbackTest.java | 12 +- src/java/com/e1/pdj/test/NetTest.java | 55 +++++++++ src/java/pdj_test_class.java | 5 + src/pdj-osx.c | 47 ++++++-- src/pdj.c | 2 +- src/pdj.h | 6 + src/type_handler.c | 7 ++ www/index.html | 11 +- 30 files changed, 621 insertions(+), 261 deletions(-) create mode 100644 src/java/com/cycling74/net/package.html create mode 100644 src/java/com/e1/pdj/test/NetTest.java diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs index d57d8bd..89a7b4b 100644 --- a/.settings/org.eclipse.cdt.core.prefs +++ b/.settings/org.eclipse.cdt.core.prefs @@ -1,3 +1,4 @@ -#Mon Jul 03 15:02:11 EDT 2006 +#Mon May 26 11:38:29 EDT 2008 eclipse.preferences.version=1 +indexer/indexerId=org.eclipse.cdt.core.fastIndexer indexerId=org.eclipse.cdt.core.fastIndexer diff --git a/Mac OS X-build.properties b/Mac OS X-build.properties index f58ccf2..91a256d 100644 --- a/Mac OS X-build.properties +++ b/Mac OS X-build.properties @@ -3,8 +3,8 @@ # put the root of your pd path installation pd.home=/Applications/pd.app/Contents/Resources -# now building fat binaries -pdj.archBuild=d_fat +# the archive will always be named pd_darwin +pdj.archBuild=pd_darwin # common OS X properties isOSX=true @@ -14,3 +14,5 @@ platform=osx jdk.libs=/System/Library/Frameworks/JavaVM.framework/Libraries jdk.home=/Library/Java/Home pdj.outfile=${dist.dir}/pdj.${pdj.archBuild} + + diff --git a/README b/README index 53fbd90..905666f 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ pdj - java plugin interface to pure-data ########################################################################### -RELEASE 0.8.4 / March 2008 +RELEASE 0.8.5 / May 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 @@ -27,7 +27,7 @@ IMPLEMENTED: LIMITATION: - * Signal inlets cannot be hot inlets for receiving atom message. + * Signal inlets cannot be hot inlets for receiving atom messages. This means that if you create a signal inlet and send an atom to this inlet, pdj won't be able to process it; float or symbol. This looks like a work as designed in pd. @@ -40,14 +40,14 @@ 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. + * you must use pdj pd scheduler if you need to use AWT with OS X. See below. REQUIEREMENTS: - * pure-data 0.41.x + * pure-data 0.40.x powerpc/intel/ub * java JDK version 1.4.x or better; use 1.5 if you can ! - * works on linux, windows and OS X (10.3.9) + * works on linux, windows and OS X (10.3 or better) REQUIEREMENTS FOR BUILDING: @@ -66,6 +66,7 @@ INSTALLATION: the same directory * double check dist/pdj.properties to be sure that the JAVA environment parameters are right + * Use the corresponding build for MacOS 10.3 or 10.4 and greater USAGE: @@ -75,8 +76,10 @@ USAGE: USING AWT WITH OS X: + === THIS ONLY WORKS ON pd 41.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 : + This is because the event GUI mechanism has these limitation : --> A CFRunLoopRun must be park in the main thread before the main loop is started @@ -93,11 +96,14 @@ USING AWT WITH OS X: 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 + environment 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. + Rename the file pdj.pd_darwin to pdj.d_fat since pure-data only search for + .d_fat extensions. + + Be careful 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 @@ -106,6 +112,15 @@ USING AWT WITH OS X: CHANGELOG: + --- VERSION 0.8.5 --- + * added com.cycling74.net package + * support for the pd-extended auto-build, slowly pdj will be part of pd-extended + * can now be build with mingw on windows + * FIXED: sending un-initialized array crash pure-data + * FIXED: MaxObject reflection with java 1.5 caused an RMI/IIOP error + * FIXED: Callback reflection with java 1.5 caused IllegalArgumentException + * FIXED: OS X 10.3 support + --- VERSION 0.8.4 --- * amd64 for Linux (thanks to Sergio Torres-Perez) * getInlets() starts at 0 not 1 (thanks to MiS) diff --git a/Windows XP-build.properties b/Windows XP-build.properties index 868579e..4c305df 100644 --- a/Windows XP-build.properties +++ b/Windows XP-build.properties @@ -6,9 +6,14 @@ jdk.home=C:/Java/jdk1.6.0_02 # put the path of where pd is installed pd.home=C:/Projets/pd +# the compiler type. If you are using gcc, you will need a pd build that was +# done with gcc since it will have to look for a file name pd.a in the /obj +# directory +#compiler=gcc +compiler=msvc + # common windows properties isWin32=true -compiler=msvc linker.type=shared platform=win32 jdk.libs=${jdk.home}/jre/lib/i386 diff --git a/build.properties b/build.properties index 656f89a..c082c72 100644 --- a/build.properties +++ b/build.properties @@ -2,7 +2,7 @@ # PDJ packaging version # ========================================================================= -pdj.version=0.8.4 +pdj.version=0.8.5 # Various path definition # ========================================================================= diff --git a/build.xml b/build.xml index 69bc840..730e7ad 100644 --- a/build.xml +++ b/build.xml @@ -31,6 +31,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -49,6 +76,10 @@ + + + + @@ -61,7 +92,11 @@ - + + + + + @@ -76,15 +111,17 @@ + - - - - - + + + + + + @@ -93,19 +130,20 @@ - + + - - + + - - - - + + + + @@ -117,10 +155,13 @@ + + + @@ -136,38 +177,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -180,7 +189,7 @@ - + @@ -207,6 +216,7 @@ + @@ -221,20 +231,56 @@ - - - - + + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/ant/cpptasks.jar b/lib/ant/cpptasks.jar index becac8e..c906a29 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 index c9df624..d4e9b17 100644 Binary files a/res/docs/pdj.odt and b/res/docs/pdj.odt differ diff --git a/res/docs/pdj.pdf b/res/docs/pdj.pdf index 49894ac..385c131 100644 Binary files a/res/docs/pdj.pdf and b/res/docs/pdj.pdf differ diff --git a/src/MaxObject.c b/src/MaxObject.c index cffbd76..67a0aa9 100644 --- a/src/MaxObject.c +++ b/src/MaxObject.c @@ -25,6 +25,11 @@ JNIEXPORT jlong JNICALL Java_com_cycling74_max_MaxObject_newInlet inlet_new(&pdj->x_obj, &pdj->x_obj.ob_pd, &s_signal, 0); return 0; } + + if ( inlet_proxy == 0 ) { + bug("the inlet_proxy IS NOT initialized. danke!"); + return 0; + } proxy = (t_inlet_proxy *) pd_new(inlet_proxy); proxy->idx = pdj->nb_inlet++; @@ -77,7 +82,9 @@ JNIEXPORT void JNICALL Java_com_cycling74_max_MaxObject_doOutletAnything t_atom args[MAX_ATOMS_STACK]; int argc; - jatoms2atoms(env, value, &argc, args); + if ( jatoms2atoms(env, value, &argc, args) != 0 ) + return; + if ( str == NULL ) { if ( args[0].a_type == A_FLOAT ) { outlet_anything(x, &s_list, argc, args); diff --git a/src/init.c b/src/init.c index b147db4..df5851c 100644 --- a/src/init.c +++ b/src/init.c @@ -2,10 +2,12 @@ * initialization */ + #include #include #include #include "pdj.h" +#include "native_classes.h" #define MAX_PROPERTIES 40 char *properties[MAX_PROPERTIES+1][2]; @@ -209,8 +211,134 @@ static int initIDCaching(JNIEnv *env) { static int linkClasses(JNIEnv *env) { + // link native method to java classes + JNINativeMethod link; + jclass maxsystem = (*env)->FindClass(env, "com/cycling74/max/MaxSystem"); + jclass mspbuffer = (*env)->FindClass(env, "com/cycling74/msp/MSPBuffer"); jclass pdjSystem = (*env)->FindClass(env, "com/e1/pdj/PDJSystem"); jmethodID id; + + link.name = "newInlet"; + link.signature = "(I)J"; + link.fnPtr = Java_com_cycling74_max_MaxObject_newInlet; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "newOutlet"; + link.signature = "(I)J"; + link.fnPtr = Java_com_cycling74_max_MaxObject_newOutlet; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "doOutletBang"; + link.signature = "(J)V"; + link.fnPtr = Java_com_cycling74_max_MaxObject_doOutletBang; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "doOutletFloat"; + link.signature = "(JF)V"; + link.fnPtr = Java_com_cycling74_max_MaxObject_doOutletFloat; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "doOutletSymbol"; + link.signature = "(JLjava/lang/String;)V"; + link.fnPtr = Java_com_cycling74_max_MaxObject_doOutletSymbol; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "doOutletAnything"; + link.signature = "(JLjava/lang/String;[Lcom/cycling74/max/Atom;)V"; + link.fnPtr = Java_com_cycling74_max_MaxObject_doOutletAnything; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "getPatchPath"; + link.signature = "()Ljava/lang/String;"; + link.fnPtr = Java_com_cycling74_max_MaxObject_getPatchPath; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "pushPdjPointer"; + link.signature = "(J)V"; + link.fnPtr = Java_com_cycling74_max_MaxObject_pushPdjPointer; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "popPdjPointer"; + link.signature = "()J"; + link.fnPtr = Java_com_cycling74_max_MaxObject_popPdjPointer; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxObject, &link, 1); + + link.name = "getTime"; + link.signature = "()D"; + link.fnPtr = Java_com_cycling74_max_MaxClock_getTime; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxClock, &link, 1); + + link.name = "delay"; + link.signature = "(D)V"; + link.fnPtr = Java_com_cycling74_max_MaxClock_delay; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxClock, &link, 1); + + link.name = "release"; + link.signature = "()V"; + link.fnPtr = Java_com_cycling74_max_MaxClock_release; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxClock, &link, 1); + + link.name = "unset"; + link.signature = "()V"; + link.fnPtr = Java_com_cycling74_max_MaxClock_unset; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxClock, &link, 1); + + link.name = "create_clock"; + link.signature = "()V"; + link.fnPtr = Java_com_cycling74_max_MaxClock_create_1clock; + (*env)->RegisterNatives(env, pdjCaching.cls_MaxClock, &link, 1); + + + link.name = "post"; + link.signature = "(Ljava/lang/String;)V"; + link.fnPtr = Java_com_cycling74_max_MaxSystem_post; + (*env)->RegisterNatives(env, maxsystem, &link, 1); + + link.name = "error"; + link.signature = "(Ljava/lang/String;)V"; + link.fnPtr = Java_com_cycling74_max_MaxSystem_error; + (*env)->RegisterNatives(env, maxsystem, &link, 1); + + link.name = "ouch"; + link.signature = "(Ljava/lang/String;)V"; + link.fnPtr = Java_com_cycling74_max_MaxSystem_ouch; + (*env)->RegisterNatives(env, maxsystem, &link, 1); + + link.name = "sendMessageToBoundObject"; + link.signature = "(Ljava/lang/String;Ljava/lang/String;[Lcom/cycling74/max/Atom;)Z"; + link.fnPtr = Java_com_cycling74_max_MaxSystem_sendMessageToBoundObject; + (*env)->RegisterNatives(env, maxsystem, &link, 1); + + link.name = "locateFile"; + link.signature = "(Ljava/lang/String;)Ljava/lang/String;"; + link.fnPtr = Java_com_cycling74_max_MaxSystem_locateFile; + (*env)->RegisterNatives(env, maxsystem, &link, 1); + + link.name = "locateFile"; + link.signature = "(Ljava/lang/String;)Ljava/lang/String;"; + link.fnPtr = Java_com_cycling74_max_MaxSystem_locateFile; + (*env)->RegisterNatives(env, maxsystem, &link, 1); + + link.name = "setSize"; + link.signature = "(Ljava/lang/String;IJ)V"; + link.fnPtr = Java_com_cycling74_msp_MSPBuffer_setSize; + (*env)->RegisterNatives(env, mspbuffer, &link, 1); + + link.name = "getSize"; + link.signature = "(Ljava/lang/String;)J"; + link.fnPtr = Java_com_cycling74_msp_MSPBuffer_getSize; + (*env)->RegisterNatives(env, mspbuffer, &link, 1); + + link.name = "getArray"; + link.signature = "(Ljava/lang/String;JJ)[F"; + link.fnPtr = Java_com_cycling74_msp_MSPBuffer_getArray; + (*env)->RegisterNatives(env, mspbuffer, &link, 1); + + link.name = "setArray"; + link.signature = "(Ljava/lang/String;J[F)V"; + link.fnPtr = Java_com_cycling74_msp_MSPBuffer_setArray; + (*env)->RegisterNatives(env, mspbuffer, &link, 1); + if ( pdjSystem == NULL ) { SHOWEXC; return 1; diff --git a/src/java/com/cycling74/max/Callback.java b/src/java/com/cycling74/max/Callback.java index 1eed30f..14d4848 100644 --- a/src/java/com/cycling74/max/Callback.java +++ b/src/java/com/cycling74/max/Callback.java @@ -130,6 +130,7 @@ public class Callback implements Executable { try { method.invoke(obj, args); } catch (IllegalArgumentException e) { + e.printStackTrace(); MaxSystem.error("pdj: IllegalArgumentException:" + e); } catch (IllegalAccessException e) { MaxSystem.error("pdj: IllegalAccessException:" + e); @@ -144,7 +145,7 @@ public class Callback implements Executable { * @return the array of arguments */ public Object[] getArgs() { - return args; + return (Object[]) args[0]; } /** @@ -176,7 +177,7 @@ public class Callback implements Executable { * @param i int value */ public void setArgs(int i) { - args = new Object[] { new Integer(i) }; + setSubArgs(new Object[] { new Integer(i) }); } /** @@ -184,7 +185,7 @@ public class Callback implements Executable { * @param f float argument */ public void setArgs(float f) { - args = new Object[] { new Float(f) }; + setSubArgs(new Object[] { new Float(f) }); } /** @@ -192,7 +193,7 @@ public class Callback implements Executable { * @param value int value */ public void setArgs(String value) { - args = new Object[] { value }; + setSubArgs(new Object[] { value }); } /** @@ -200,7 +201,7 @@ public class Callback implements Executable { * @param flag boolean value */ public void setArgs(boolean flag) { - args = new Object[] { flag ? Boolean.TRUE : Boolean.FALSE }; + setSubArgs(new Object[] { flag ? Boolean.TRUE : Boolean.FALSE }); } /** @@ -208,6 +209,15 @@ public class Callback implements Executable { * @param args the array object to pass to the method */ public void setArgs(Object args[]) { - this.args = (Object[]) args.clone(); + setSubArgs((Object[]) args.clone()); + } + + /** + * Fix for <1.5 method.invoke. + * @param args + */ + private void setSubArgs(Object args[]) { + this.args = new Object[1]; + this.args[0] = args; } } diff --git a/src/java/com/cycling74/max/MaxObject.java b/src/java/com/cycling74/max/MaxObject.java index 15f2a16..5b93bc3 100644 --- a/src/java/com/cycling74/max/MaxObject.java +++ b/src/java/com/cycling74/max/MaxObject.java @@ -863,7 +863,7 @@ public class MaxObject { } catch (NoSuchMethodException e) { try { Constructor c = clz.getConstructor(argType); - obj = (MaxObject) c.newInstance(new Object[0]); + obj = (MaxObject) c.newInstance((Object[]) new Object[0]); } catch ( Exception e1 ) { popPdjPointer(); throw e1; diff --git a/src/java/com/cycling74/max/MaxSystem.java b/src/java/com/cycling74/max/MaxSystem.java index dd8fe48..cdecb0b 100644 --- a/src/java/com/cycling74/max/MaxSystem.java +++ b/src/java/com/cycling74/max/MaxSystem.java @@ -146,8 +146,8 @@ public class MaxSystem { int ret[] = new int[3]; ret[0] = 0; - ret[1] = 99; - ret[2] = 0; + ret[1] = 8; + ret[2] = 5; return ret; } @@ -171,7 +171,7 @@ public class MaxSystem { } // constants - public static String MXJ_VERSION = "pdj 0.8.4"; + public static String MXJ_VERSION = "pdj 0.8.5"; public static final int PATH_STYLE_COLON = 2; public static final int PATH_STYLE_MAX = 0; diff --git a/src/java/com/cycling74/max/package.html b/src/java/com/cycling74/max/package.html index dcd23c3..1df006d 100644 --- a/src/java/com/cycling74/max/package.html +++ b/src/java/com/cycling74/max/package.html @@ -1,5 +1,5 @@ -

Basic package for PDJ

+

Basic package for PDJ.

\ No newline at end of file diff --git a/src/java/com/cycling74/msp/MSPPerformable.java b/src/java/com/cycling74/msp/MSPPerformable.java index 6f27241..75b3e13 100644 --- a/src/java/com/cycling74/msp/MSPPerformable.java +++ b/src/java/com/cycling74/msp/MSPPerformable.java @@ -6,12 +6,12 @@ package com.cycling74.msp; */ public interface MSPPerformable { /** - * @see MSPPerformer.dspsetup(MSPSignal in[], MSPSignal out[]) + * Interface for MSPPerformer.dspsetup(MSPSignal in[], MSPSignal out[]) */ public void dspsetup(MSPSignal in[], MSPSignal out[]); /** - * @see MSPPerformer.perform(MSPSignal in[], MSPSignal out[]); + * Interface for MSPPerformer.perform(MSPSignal in[], MSPSignal out[]); */ public void perform(MSPSignal in[], MSPSignal out[]); } diff --git a/src/java/com/cycling74/net/TcpReceiver.java b/src/java/com/cycling74/net/TcpReceiver.java index f449517..3de2343 100644 --- a/src/java/com/cycling74/net/TcpReceiver.java +++ b/src/java/com/cycling74/net/TcpReceiver.java @@ -1,33 +1,54 @@ package com.cycling74.net; -import java.lang.reflect.Method; -import java.net.DatagramPacket; -import java.net.DatagramSocket; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; import com.cycling74.max.Atom; +import com.cycling74.max.Callback; 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 +/** + * Class wrapper to receive atoms via TCP/IP using the class + * TcpSender. + * + * This class is a work in progress and have been lightly tested. */ public class TcpReceiver implements Runnable { - DatagramSocket receiver; - DatagramPacket packet; - - Method callback = null; - Object instance; + ServerSocket receiver; + + Callback callback = null; String debugString = null; - int port; + int port = -1; boolean runnable = true; + public TcpReceiver() { + + } + + public TcpReceiver(int port) { + this.port = port; + } + + public TcpReceiver(int port, Object caller, String method) { + this.port = port; + this.callback = new Callback(caller, method, new Object[] { new Atom[0] }); + } + + public void close() { if ( receiver == null ) return; runnable = false; - receiver.close(); + try { + receiver.close(); + } catch (IOException e) { + e.printStackTrace(); + } } public int getPort() { @@ -35,9 +56,17 @@ public class TcpReceiver implements Runnable { } public void setActive(boolean active) { - if ( active == false ) { - runnable = true; - new Thread(this).start(); + if ( port == -1 ) + throw new MaxRuntimeException("No TCP port specified"); + + if ( active == true ) { + try { + receiver = new ServerSocket(port); + } catch (IOException e) { + throw new MaxRuntimeException(e); + } + runnable = true; + new Thread(this, "TcpSender[" + port + "]").start(); } else { close(); } @@ -46,8 +75,7 @@ public class TcpReceiver implements Runnable { public void setCallback(Object caller, String methodName) { try { - callback = caller.getClass().getDeclaredMethod(methodName, new Class[] { Atom.class }); - instance = caller; + this.callback = new Callback(caller, methodName, new Object[] { new Atom[0] }); } catch (Exception e) { throw new MaxRuntimeException(e); } @@ -62,22 +90,29 @@ public class TcpReceiver implements Runnable { this.debugString = debugString; } + private void parseMessage(BufferedReader reader) throws IOException { + while(runnable) { + String msg = reader.readLine(); + if ( debugString != null ) + MaxSystem.post(debugString + " " + msg); + + if ( callback != null ) { + callback.setArgs(Atom.parse(msg)); + try { + callback.execute(); + } catch( Exception e ) { + e.printStackTrace(); + } + } + } + } + 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(); - } + Socket socket = receiver.accept(); + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + parseMessage(reader); } } catch (Exception e) { if ( runnable != false) { diff --git a/src/java/com/cycling74/net/TcpSender.java b/src/java/com/cycling74/net/TcpSender.java index 2ba0f67..a092bfb 100644 --- a/src/java/com/cycling74/net/TcpSender.java +++ b/src/java/com/cycling74/net/TcpSender.java @@ -1,20 +1,21 @@ package com.cycling74.net; import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetSocketAddress; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; 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 +/** + * Class wrapper to send atoms via TCP/IP. The host on the other side + * must use TcpReceive to read the sended atoms. + * + * This class is a work in progress and have been lightly tested. */ public class TcpSender { - DatagramSocket sender; - DatagramPacket packet; + InetAddress inetAddress; String address = null; int port = -1; @@ -22,58 +23,47 @@ public class TcpSender { } public TcpSender(String address, int port) { - this.address= address; + setAddress(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); - } + send(Atom.toOneString(args)); } 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); - } + send(Integer.toString(i)); } 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); - } + send(Float.toString(f)); } + public void send(String msg) { + if ( address == null ) + throw new MaxRuntimeException("TcpSender has no active hosts"); + if ( port == -1 ) + throw new MaxRuntimeException("TcpSender has no active port"); + + try { + Socket sender = new Socket(inetAddress, port); + sender.getOutputStream().write(msg.getBytes()); + sender.close(); + } catch (IOException e) { + throw new MaxRuntimeException(e); + } + } + public String getAddress() { return address; } public void setAddress(String address) { - if ( sender != null ) { - sender = null; - sender.close(); - } + try { + inetAddress = InetAddress.getByName(address); + } catch (UnknownHostException e) { + throw new MaxRuntimeException(e); + } this.address = address; } @@ -82,22 +72,6 @@ public class TcpSender { } 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 index fd47e25..f7423fd 100644 --- a/src/java/com/cycling74/net/UdpReceiver.java +++ b/src/java/com/cycling74/net/UdpReceiver.java @@ -5,24 +5,32 @@ import java.net.DatagramSocket; import com.cycling74.max.Atom; import com.cycling74.max.MaxRuntimeException; -import com.cycling74.max.MaxSystem; +//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 +/** + * Class wrapper to receive atoms via UDP/IP using the class + * UdpSender. + * + * This class is a work in progress and have been lightly tested. */ public class UdpReceiver implements Runnable { DatagramSocket receiver; DatagramPacket packet; - Callback callback; - + Callback callback = null; String debugString = null; - int port; boolean runnable = true; + int port = -1; - public void close() { + public UdpReceiver() { + } + + public UdpReceiver(int port) { + this.port = port; + } + + public void close() { if ( receiver == null ) return; runnable = false; @@ -34,17 +42,23 @@ public class UdpReceiver implements Runnable { } public void setActive(boolean active) { - if ( active == false ) { - runnable = true; - new Thread(this).start(); + if ( active == true ) { + if ( port == -1 ) + throw new MaxRuntimeException("No UDP port specified"); + try { + receiver = new DatagramSocket(port); + } catch ( Exception e ) { + throw new MaxRuntimeException(e); + } + runnable = true; + new Thread(this, "UdpReceiver[" + port + "]").start(); } else { close(); } - } public void setCallback(Object caller, String methodName) { - callback = new Callback(caller, methodName); + callback = new Callback(caller, methodName, new Object[] { new Atom[0] }); } public void setPort(int port) { @@ -57,22 +71,22 @@ public class UdpReceiver implements Runnable { } public void run() { - DatagramPacket packet = new DatagramPacket(new byte[4096], 4096); - Object callerArgs[] = new Object[1]; - try { while(runnable) { + DatagramPacket packet = new DatagramPacket(new byte[4096], 4096); 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(); - } */ + //if ( debugString != null ) + // MaxSystem.post(debugString + " " + msg); + + if ( callback != null ) { + callback.setArgs(Atom.parse(msg)); + try { + callback.execute(); + } catch( Exception e ) { + e.printStackTrace(); + } + } } } catch (Exception e) { if ( runnable != false) { diff --git a/src/java/com/cycling74/net/UdpSender.java b/src/java/com/cycling74/net/UdpSender.java index 6ef7e34..e4c2d53 100644 --- a/src/java/com/cycling74/net/UdpSender.java +++ b/src/java/com/cycling74/net/UdpSender.java @@ -8,9 +8,11 @@ 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 +/** + * Class wrapper to send atoms via UDP/IP. The host on the other side + * must use UdpReceive to read the sended atoms. + * + * This class is a work in progress and have been lightly tested. */ public class UdpSender { InetAddress inetAddress; @@ -23,6 +25,11 @@ public class UdpSender { public UdpSender() { } + /** + * Create a UpdSender. + * @param address the hostname/ip address of the host to reach + * @param port the UDP port to use + */ public UdpSender(String address, int port) { this.address = address; this.port = port; @@ -41,22 +48,45 @@ public class UdpSender { send(Float.toString(f).getBytes()); } + public void send(String msg, Atom args[]) { + send((msg + " " + Atom.toOneString(args)).getBytes()); + } + + /** + * Returns the hostname/ip address to reach. + * @return hostname/ip address to reach + */ public String getAddress() { return address; } + /** + * Sets hostname/ip address to reach. + * @param address hostname/ip address to reach + */ + public void setAddress(String address) { this.address = address; - initsocket(); + if ( port != -1 ) + initsocket(); } + /** + * Returns the UDP port to use. + * @return the UDP port to use + */ public int getPort() { return port; } + /** + * Sets the UDP port to use. + * @param port the UDP port to use + */ public void setPort(int port) { this.port = port; - initsocket(); + if ( address != null ) + initsocket(); } synchronized void initsocket() { @@ -71,14 +101,13 @@ public class UdpSender { void send(byte buff[]) { if ( sender == null ) - throw new MaxRuntimeException("UdpSender is not initialized"); - + throw new MaxRuntimeException("UdpSender: UPD port or address is missing"); + 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/cycling74/net/package.html b/src/java/com/cycling74/net/package.html new file mode 100644 index 0000000..830ac7c --- /dev/null +++ b/src/java/com/cycling74/net/package.html @@ -0,0 +1,5 @@ + + +

Network utilities for sending atoms.

+ + \ No newline at end of file diff --git a/src/java/com/e1/pdj/PDJSystem.java b/src/java/com/e1/pdj/PDJSystem.java index 1fd50d2..ac3fd47 100644 --- a/src/java/com/e1/pdj/PDJSystem.java +++ b/src/java/com/e1/pdj/PDJSystem.java @@ -2,12 +2,10 @@ package com.e1.pdj; import com.cycling74.max.MaxSystem; -import java.awt.Component; -import java.awt.Frame; import java.awt.Toolkit; import java.io.*; - import java.awt.GraphicsEnvironment; + /** * Startup class for pdj. */ @@ -24,7 +22,7 @@ public class PDJSystem { public static void _init_system() { if ( loaded == 1 ) return; - linknative(); + javainit(); initIO(); } @@ -42,49 +40,29 @@ public class PDJSystem { GenericCompiler.rtJar = systemCpJar + ps + "jre" + ps + "lib" + ps + "rt.jar" + File.pathSeparator; } - /** - * Link the Java native classes - */ - static void linknative() { - String pdjHome = System.getProperty("pdj.home"); + static void javainit() { // 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 ) { - // maps PD object as a JVM native library - Runtime.getRuntime().load(pdjHome + "/pdj.pd_linux"); - loaded = 1; - resolvRtJar(); - return; - } - - if ( osname.indexOf("Windows") != -1 ) { - // maps PD object as a JVM native library - Runtime.getRuntime().load(pdjHome + "/pdj.dll"); - loaded = 1; - resolvRtJar(); - return; - } - if ( osname.indexOf("OS X") != -1 ) { - // maps PD object as a JVM native library - Runtime.getRuntime().load(pdjHome + "/pdj.d_fat"); - loaded = 1; - - if ( System.getenv("PDJ_USE_AWT") != null ) { - GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); - Toolkit.getDefaultToolkit(); - } - GenericCompiler.rtJar = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar:"; - - return; - } - - System.err.println("pdj: operating system type not found, the native link has not been made"); + try { + if (System.getenv("PDJ_USE_AWT") != null) { + GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + Toolkit.getDefaultToolkit(); + } + } catch (Error e) { + // on java 1.4, this will throw an error, we simply ignore AWT with 1.4 + } + GenericCompiler.rtJar = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar:"; + loaded = 1; + return; + } + + loaded = 1; + resolvRtJar(); } static boolean redirectIO() { diff --git a/src/java/com/e1/pdj/test/CallbackTest.java b/src/java/com/e1/pdj/test/CallbackTest.java index 4105479..526a5f4 100644 --- a/src/java/com/e1/pdj/test/CallbackTest.java +++ b/src/java/com/e1/pdj/test/CallbackTest.java @@ -1,10 +1,20 @@ package com.e1.pdj.test; +import com.cycling74.max.*; import junit.framework.TestCase; public class CallbackTest extends TestCase { - public void testSomething() { + + + public void testArgs() { + Callback callback = new Callback(this, "callme", new Object[] { new Integer[0] }); + Integer[] args = new Integer[] { new Integer(1), new Integer(2) }; + callback.setArgs((Object[]) args); + callback.execute(); + } + + public void callme(Integer args[]) { } } diff --git a/src/java/com/e1/pdj/test/NetTest.java b/src/java/com/e1/pdj/test/NetTest.java new file mode 100644 index 0000000..01b103a --- /dev/null +++ b/src/java/com/e1/pdj/test/NetTest.java @@ -0,0 +1,55 @@ +package com.e1.pdj.test; + +import com.cycling74.max.*; +import com.cycling74.net.*; +import junit.framework.TestCase; + +public class NetTest extends TestCase { + Atom value[]; + + public void testUDP() { + UdpReceiver receive = new UdpReceiver(7500); + receive.setCallback(this, "callback_test"); + receive.setActive(true); + + value = null; + + UdpSender send = new UdpSender("localhost", 7500); + send.send(7500); + + try { + Thread.sleep(1000); + } catch ( InterruptedException e ) { + } + + receive.close(); + + assertNotNull(value); + assertEquals(Integer.parseInt(value[0].toString()), 7500); + } + + public void callback_test(Atom args[]) { + value = args; + } + + public void testTCP() { + TcpReceiver receive = new TcpReceiver(7500); + receive.setCallback(this, "callback_test"); + receive.setActive(true); + + value = null; + + TcpSender send = new TcpSender("localhost", 7500); + send.send(7500); + + try { + Thread.sleep(1000); + } catch ( InterruptedException e ) { + } + + receive.close(); + + assertNotNull(value); + assertEquals(Integer.parseInt(value[0].toString()), 7500); + } +} diff --git a/src/java/pdj_test_class.java b/src/java/pdj_test_class.java index 61cf804..949e2e9 100644 --- a/src/java/pdj_test_class.java +++ b/src/java/pdj_test_class.java @@ -51,6 +51,11 @@ public class pdj_test_class extends MaxObject implements Executable { protected void inlet(float f) { post("le float " + f + "inlet " + getInlet()); + + Atom args[] = new Atom[2]; + args[0] = Atom.newAtom(1); + + outlet(0, args); } void wer(Atom[] atom) { diff --git a/src/pdj-osx.c b/src/pdj-osx.c index 7c5b281..c0564d6 100644 --- a/src/pdj-osx.c +++ b/src/pdj-osx.c @@ -13,7 +13,7 @@ * === 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 : + * because the event GUI mechanism has these limitation : * * --> A CFRunLoopRun must be park in the main thread. * --> Java must be run in a secondary thread. @@ -27,12 +27,12 @@ * 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 + * Once the patch is applied and compiled, you must configure your pure-data environment * 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 + * Be careful 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 * @@ -41,18 +41,33 @@ */ int rc_pd = 0xFF; -CFRunLoopRef cfrunloop; -/* setting the environment varible APP_NAME_ to the applications name */ +/* setting the environment variable APP_NAME_ to the applications name */ /* sets it for the application menu */ -void setAppName(const char * name) { +static void setAppName(const char * name) { char a[32]; pid_t id = getpid(); sprintf(a,"APP_NAME_%ld",(long)id); setenv(a, name, 1); } +static void *getProcAddress(const char *name) { + NSSymbol symbol; + char *symbolName; + + // Prepend a '_' for the Unix C symbol mangling convention + symbolName = malloc (strlen (name) + 2); + strcpy(symbolName + 1, name); + symbolName[0] = '_'; + symbol = NULL; + + if (NSIsSymbolNameDefined(symbolName)) + symbol = NSLookupAndBindSymbol(symbolName); + free (symbolName); + + return symbol ? NSAddressOfSymbol(symbol) : NULL; +} /** * The main pd thread, will become a secondary thread to AWT. @@ -66,12 +81,22 @@ void *pdj_pdloop(void *notused) { // we create the JVM now init_jvm(); + pdj_setup(); /* open audio and MIDI */ sys_reopen_midi(); sys_reopen_audio(); - rc_pd = m_mainloop(); + // m_mainloop is only in 41.x, we will try to be gentle if we do not + // find the function m_mainloop + int (*mainloop)() = getProcAddress("m_mainloop"); + + if ( mainloop == NULL ) { + fprintf(stderr, "unable to find m_mainloop function in current pure-data\n"); + exit(-1); + } + + rc_pd = mainloop(); exit(rc_pd); } @@ -158,10 +183,12 @@ int getuglylibpath(char *path) { imagename = (char *) _dyld_get_image_name(i); } - if ( imagename != NULL ) { + if ( imagename != NULL ) { + // remove the pdj.d_fat/pdj.pd_darwin text strncpy(path, imagename, MAXPDSTRING); - // remove the pdj.pd_fat text - path[strlen(imagename) - 10] = 0; + int i = strlen(imagename)-1; + for(; i != 0 && path[i] != '/'; i--); + path[i] = 0; return 0; } diff --git a/src/pdj.c b/src/pdj.c index d76c4f9..d721f36 100644 --- a/src/pdj.c +++ b/src/pdj.c @@ -362,7 +362,7 @@ static void pdj_loadbang(t_pdj *pdj) { } -void pdj_setup(void) { +DLLEXPORT void pdj_setup(void) { char stack_pos; pdj_class = class_new(gensym("pdj"), diff --git a/src/pdj.h b/src/pdj.h index f8755e8..7906d47 100644 --- a/src/pdj.h +++ b/src/pdj.h @@ -35,6 +35,12 @@ #define JPOINTER_CAST (unsigned int) #endif +#ifdef WIN32GCC + #define DLLEXPORT __declspec(dllexport) +#else + #define DLLEXPORT +#endif + // the JVM takes 50M; I don't care taking 4K... #define BUFFER_SIZE 4096 diff --git a/src/type_handler.c b/src/type_handler.c index 0c7bc67..4c0bc37 100644 --- a/src/type_handler.c +++ b/src/type_handler.c @@ -44,6 +44,13 @@ int jatoms2atoms(JNIEnv *env, jobjectArray jatoms, int *nb_atoms, t_atom *atoms) for(i=0;i<*nb_atoms;i++) { obj = (*env)->GetObjectArrayElement(env, jatoms, i); + if ( obj == NULL ) { + jclass exception = (*env)->FindClass(env, "java/lang/NullPointerException"); + ASSERT(exception); + (*env)->ThrowNew(env, exception, NULL); + (*env)->DeleteLocalRef(env, exception); + return 1; + } rc |= jatom2atom(env, obj, atoms+i); } diff --git a/www/index.html b/www/index.html index 23abd9a..d3fe970 100644 --- a/www/index.html +++ b/www/index.html @@ -34,16 +34,17 @@ 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.40.x or better
  • +0.41.x
  • java jdk 1.4.x or better; use java 1.5 !!!
  • apache ant 1.5.x or better for building
  • works on Linux / Windows / OS X
  • Download:

    -

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

    Download latest release here: pdj-0.8.5.tar.gz +/ pdj-0.8.5-win32.zip +/ pdj-0.8.5-osx.tar.gz - for 10.4/10.5 +/ pdj-0.8.5-osx103.tar.gz - for 10.3 +(May 2008)

    Documentation: pdj.pdf

    -- cgit v1.2.1