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 --- 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 ++ 20 files changed, 479 insertions(+), 189 deletions(-) create mode 100644 src/java/com/cycling74/net/package.html create mode 100644 src/java/com/e1/pdj/test/NetTest.java (limited to 'src') 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); } -- cgit v1.2.1