Forums > Java

Using third party jars

April 19, 2010 | 12:54 pm

Hi

Trying to get to grips with mxj, I’ve not really used Java before and the first example I’m working on uses imported third party jars. Looking at tutorial 8 and the documentation that comes with the jars I believe I’m supposed to use ‘implements’? Like this:

public class WhichThread extends MaxObject implements Runnable
{
public void run() {
this.bang();
}

}

I need to implement something called ‘GloveConnectionListener’ and I understand that run() works with Runnable above but how do I find out the corresponding method for ‘GloveConnectionListener’?

Garrett


April 19, 2010 | 1:41 pm

Googling the ‘GloveConnectionListener’ tells me you are trying to use the java SDK that came with your AcceleGlove, right?

Looking at the AcceleGloveUserGuide.pdf, i think you need to create an instance of the Glove object.

Within a MaxObject that might look something like this:


public class MaxGlove extends MaxObject {
Glove glove = new Glove("portname");
}

I would suggest to study the MaxObject API a bit to understand how it works.


April 19, 2010 | 2:15 pm

Hi

Yes that’s correct, although I don’t think new Glove("portname") actually needs anything passed to it, the help says it does but none of the examples actually do. Anyway that doesn’t seem to produce any errors.

This is what I’ve got at the moment:

import com.cycling74.max.*;
import com.idrt.Glove;
import com.idrt.GloveConnectionEvent;
import com.idrt.GloveConnectionListener;
import com.idrt.Handshape;
import com.idrt.Glove.GloveIOException;
import com.idrt.Handshape.HandshapeException;

public class AcceleGloveCapture extends MaxObject implements GloveConnectionListener
{
public AcceleGloveCapture()
{
Handshape h;

try
{
//Create connection to the AcceleGlove
Glove g = new Glove();
g.addGloveConnectionListener(this);

for (;;)
{
// Print current accelerometer values
h = g.captureHandshape();
outlet(0, h.toString());
}
}

catch (GloveIOException e)
{
e.printStackTrace();
}

catch (HandshapeException e)
{
e.printStackTrace();
}
}

//Close the glove object when the glove is disconnected.
public void statusReceived(GloveConnectionEvent event)
{
Glove g = (Glove) event.getSource();
g.close();
outlet(1, "The Glove is disconnected");
System.exit(0);
}
}

It seems to compile fine in Eclipse but won’t load in max and gives the following error.

• error: java.lang.NoClassDefFoundError: com/idrt/GloveConnectionListener
• error: at java.lang.ClassLoader.defineClass1(Native Method)
• error: at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
• error: at com.cycling74.max.MXJClassLoaderImpl.doLoadClass(MXJClassLoaderImpl.java:119)
• error: at com.cycling74.max.MXJClassLoader.loadClazz(MXJClassLoader.java:78)
• error: Could not load class ‘AcceleGloveCapture’


April 19, 2010 | 3:54 pm

Well – the error seems pretty clear – it looks like max can’t find the .jar you are linking to, or at least the first thing it is telling you is that it can’t find a class definition for the first class you are importing (then it just bails). I seem to remember at least trying to do this ages ago, but I can’t remember whether I could get it to work or not, and I’m not on the relevant computer to check.

Anyway, looking at your code is not likely to get you anywhere – I think what you need to do is make sure you have the .jar in the right place in the searchpath and then look at why it’s not loading if that is already correct…

Sorry not to be more helpful, but maybe that’ll get you somewhere…

Alex


April 20, 2010 | 9:05 am

yes, first of all put the jar in the right place, or edit your max.java.config file to point at the folder containing your jar.

another thing, I would advice against using the for(;;) loop, it might cause max to hang. Maybe better to trigger the h = g.captureHandshape(); through a bang sent my max. In this case you need to define Glove g as a global variable.

btw. are you by any chance in the Netherlands? I’d be interested in trying out the glove.. :)


April 20, 2010 | 9:20 am

Oh yes – that for loop doesn’t look like a good idea. If you want to automate this better to use a clock to call a routine that gets the values – or as Florito suggests expect a bang from the user to do this. Many objects like hi give you the option of self clocking, which is my preferred approach, as if users want to poll at will they can, but it saves making a metro most of the time when you just want output at a regular interval….

Alex


April 20, 2010 | 11:00 am

>yes, first of all put the jar in the right place, or edit
>your max.java.config file to point at the folder containing
>your jar.

ah that’s where I’m going wrong, max is linking to the folder with the class only, I guess I can drop the jars in there to get it to work but is that considered a good space to put them or should I be adding another line to my max.java.config.txt?

[edit]ah in the lib folder in cycling 74/java works! yep max crashed but it showed up as a valid object first so I’m on track now. Thanks for your help all – I’ll most likely be back when I’m stuck again[/edit]

>btw. are you by any chance in the Netherlands? I’d be
>interested in trying out the glove.. :)

no sorry I’m in Wales, I would if I was :)
The gloves ok, it’s tricky to get any degree of control with it – lots of practice required.

Garrett


April 20, 2010 | 1:10 pm

Hi

ok so I’m getting very close (I think), the problems of finding the jar are now resolved, max is seeing the object correctly and I’m attempting to integrate a MaxClock as Alex suggested. This is what I have so far:

import com.cycling74.max.*;
import com.idrt.Glove;
import com.idrt.GloveConnectionEvent;
import com.idrt.GloveConnectionListener;
import com.idrt.Handshape;
import com.idrt.Glove.GloveIOException;
import com.idrt.Handshape.HandshapeException;

public class AcceleGloveCapture extends MaxObject implements GloveConnectionListener, Executable
{
private MaxClock clock;
private float interval=400.f;
Glove g;

//This executes as soon as the max object is created
public AcceleGloveCapture()
{
//Declare the interval variable
declareAttribute("interval");

//Create a clock object
clock = new MaxClock(this);
}

//A toggle switch executes this
public void inlet(int i)
{
//If on (1) is received
if (i==1)
{
//Start clock
clock.delay(0);
}
else
{
//Stop clock
clock.unset();

//close the glove, tell max it’s closed and exit
g.close();
outlet(1, "The Glove is disconnected");
System.exit(0);
}
}

//This loops (I think)
public void execute()
{
//Call bang()
bang();

//Set the interval (in case its changed)
clock.delay(interval);
}

//If the object gets deleted tidy up
protected void notifyDeleted()
{
//Unset the clock
clock.unset();
}

//This executes at timed intervals when the clock gets turned on
public void bang()
{
Handshape h;

try
{
//Create connection to the AcceleGlove
Glove g = new Glove();
g.addGloveConnectionListener(this);

// Print current accelerometer values
h = g.captureHandshape();
outlet(0, h.toString());

}
catch (GloveIOException e)
{
//Input/output exception, trace it
e.printStackTrace();
}
catch (HandshapeException e)
{
//Handshake exception, trace it
e.printStackTrace();
}
}

//Close the glove object when the glove is disconnected.
public void statusReceived(GloveConnectionEvent event)
{
//No source anymore so it does not exist
Glove g = (Glove) event.getSource();

//Close the glove, tell max it’s closed and exit
g.close();
outlet(1, "The Glove is disconnected");
System.exit(0);
}
}

The clock seems to work fine as I’m getting regular print outs in the max window as soon as I toggle the object on. I get an error about the RXTX jar, what looks like one line of input from the glove and then it bugs out:

WARNING: RXTX Version mismatch
Jar version = RXTX-2.2pre1
native lib Version = RXTX-2.2pre2
print: 49 88 0 97 129 0 103 125 0 103 116 0 112 122 0 168 107 38
• error: com.idrt.Glove$GloveIOException: Could not find an available glove.
• error: at com.idrt.Glove.(Glove.java:53)
• error: at AcceleGloveCapture.bang(AcceleGloveCapture.java:76)
• error: at AcceleGloveCapture.execute(AcceleGloveCapture.java:53)
• error: at com.cycling74.max.MaxClock.tick(MaxClock.java:149)
• error: com.idrt.Glove$GloveIOException: Could not find an available glove.

In my Java, is my connection to the glove in the right place? Surely within the bang it will keep trying to connect to the glove over and over? I’ve tried putting it where the clock is turned on so it only gets called once but that give me a error:

Unhandled exception type Glove.GloveIOException AcceleGloveCapture.java /acceleglove/src

Many thanks for all your help and suggestions so far.

Garrett


April 20, 2010 | 7:14 pm

OK – error messages are generally there for a reason – it seems to be telling you the following:

The jar does not match the native library (whatever that is – does the java stuff communicate with some kind of native driver?) – anyway – looks like the java jar you have is not as recent as the native library, so you should go download the latest version and make sure they match. (no idea what the risks are when they don’t match, but if it’s warning you take heed).

Then it can’t find your glove (no idea why) – the problem is not in your code. IIt looks to me like the error you are getting is not getting caught (even though you have a catch in your code for what looks like the same problem – (note at the bottom it says unhandled exception – suggesting you are not handling the error properly)…

A.


April 21, 2010 | 5:32 pm

Hi

>The jar does not match the native library
>(whatever that is – does the java stuff
>communicate with some kind of native driver?)

Yes there is a driver for the glove. These are not provided on the Acceleglove website so I’m in the process of contacting them. Thanks for your help on this, I’ll be back again I’m sure :)

Garrett


April 21, 2010 | 7:40 pm

Umm. That won’t help probably – read the error message again:

>Jar version = RXTX-2.2pre1
>native lib Version = RXTX-2.2pre2

Now – in any sensible numbering system that means your driver / lib is MORE up-to-date than your jar…

Anyway – a quick google of this error suggests that it’s actually probably third part serial communication thing that’s the issue, although whether this is the most important issue I’m not sure:

http://groups.google.com/group/makerbot/browse_thread/thread/7cf23fb1a360b1b3

Alex


April 22, 2010 | 2:56 am

Before you go any further, get those calls to System.exit() out of there. As soon as you get all of the code working, you are going to crash Max!


April 23, 2010 | 9:52 am

>Now – in any sensible numbering system that means your
>driver / lib is MORE up-to-date than your jar…

When you say my jar, do you mean the one I’m importing for the Acceleglove or what I’m making? I’ll try the update suggested on that forum tonight and see if it helps.

>get those calls to System.exit()

will do this later tonight as well.

Garrett


April 23, 2010 | 11:16 am

Actually looks like the RXTX jar (whatever that is) vs. the RXTX nativ lib

A.


April 28, 2010 | 8:20 pm

hi

I’ve got this working now, just tidying it up before I post it here. Tutorial 07 says notifyDeleted() gets called when the object gets deleted so I have the following:

//if the patch closes or the object is deleted
protected void notifyDeleted()
{
//close the glove
g.close();
outlet(1, "The glove is disconnected.");
}

which does seem to close the glove without problem but the message doesn’t get sent out outlet 1 – this is normal isn’t it? Is there a way I can get the message sent before the object is actually gone? I’m guessing not but more importantly is there a method which can detect when the patch is closed?

Thanks in advance
Garrett


April 28, 2010 | 8:56 pm

The object is being deleted, so it probably can’t send through an outlet.

If you just want to notify the user you could post directly to the max window.

Look for a closebang message, or try that (there is a closebang object)….

Alex


May 10, 2010 | 7:57 pm

>The object is being deleted, so it probably can’t send through an outlet.

Yes that’s what I figured but good to have confirmation that I was thinking the right way about this.

So as promised now I’ve got it working and tested it here’s an example of how to connect to and track the Acceleglove. I’ve tested it in max 4.6 and 5 and it works quite well. I dumped the internal clock and it simply waits for a bang from max now (as Florito and Alex suggested above) which is immensely faster. Here’s the Java and I’ve attached a zip with a demo maxpat and screenshot – in case anyone needs to convert back to Max 4.6 it should be quite simple as everything is in the top level patch.

Garrett

import com.cycling74.max.*;
import com.idrt.Glove;
import com.idrt.GloveConnectionEvent;
import com.idrt.GloveConnectionListener;
import com.idrt.Handshape;
import com.idrt.Glove.GloveIOException;
import com.idrt.Handshape.HandshapeException;

public class AcceleGloveManual extends MaxObject implements GloveConnectionListener
{
public Glove g;

//This executes as soon as the max object is created.
public AcceleGloveManual()
{
try
{
//Create connection to the AcceleGlove and start listening.
g = new Glove();
g.addGloveConnectionListener(this);

//Send a message to the max window that the glove is connected.
post("The Acceleglove is connected.");
}
catch (GloveIOException e)
{
//Input/output exception, trace it.
e.printStackTrace();
}
}

//This executes at timed intervals when the clock gets turned on.
public void bang()
{
Handshape h;

try
{
//Send current accelerometer values out outlet 0.
h = g.captureHandshape();
outlet(0, h.toString());

//Send 1 (on) out outlet 1.
outlet(1, 1);
}
catch (GloveIOException e)
{
//Input/output exception, trace it.
e.printStackTrace();

//Send 0 (off) out outlet 1.
outlet(1, 0);
}
catch (HandshapeException e)
{
//Handshake exception, trace it.
e.printStackTrace();

//Send 0 (off) out outlet 1.
outlet(1, 0);
}
}

//If the patch closes or the object is deleted
protected void notifyDeleted()
{
//Close the glove.
g.close();
}

//Close the glove object when the glove is disconnected.
public void statusReceived(GloveConnectionEvent event)
{
//No source anymore so it does not exist.
g = (Glove) event.getSource();

//Close the glove, tell max window it’s closed.
g.close();
post("The Acceleglove is disconnected.");
}
}


July 12, 2010 | 11:11 am

Hi

I’ve been testing a standalone I’ve made with this class and it seemed to work fine on my machine but as soon as I moved it to another has started to have some issues. The error message I get is below:

• error: java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown while loading gnu.io.RXTXCommDriver
• error: java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path
• error: at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1755)
• error: at java.lang.Runtime.loadLibrary0(Runtime.java:822)
• error: at java.lang.System.loadLibrary(System.java:993)
• error: at gnu.io.CommPortIdentifier.(CommPortIdentifier.java:123)

It looks as if maybe a path is missing somewhere and googling it I came up with this on the processing forum (http://processing.org/discourse/yabb2/YaBB.pl?num=1170029680) which suggests that it’s the librxtxSerial.jnilib.

Both librxtxSerial.jnilib and RXTXcomm.jar are correctly linked in Eclipse to my .java file and when I compile my standalone in max with the .class they are coping over correctly into Contents/support/lib/Acceleglove/.

Anyone able to shed some light on what might be happening here?

thanks in advance
Garrett


July 13, 2010 | 1:58 pm

Hello

Ok so I think I’ve found the problem but not the reason. librxtxSerial.jnilib seems to want to be in:

Library/Java/Extensions/

on the system. Is this normal? There is a copy that has been copied into the standalone in:

Contents/support/lib/Acceleglove/

but the standalone seems to ignore that. Is there any way to get the standalone to use that one or do I just have to live with dropping a copy into Extensions?

Thanks in advance
Garrett


Viewing 19 posts - 1 through 19 (of 19 total)