Can one user library use another?

I am developing a library “muse” that uses the “oscP5” library. If I put my jar file in ~/Documents/Processing/libraries/muse/library/muse.jar, I am able to see the library in Processing. However, the dependent library, oscP5 (also located in the Processing libraries folder) is not found. If I include the contents of the oscP5 jar file inside my muse.jar file, everything works.

Is this expected? Is it possible for a user-contributed library to access another user-contributed library without including a copy of it in the jar file?

1 Like

I am not an expert, but what is your desired behavior – do you want:

  1. install muse and it just works, regardless of whether dependency oscp5 is installed by user or not
  2. install muse and, if required, auto-install oscp5 in user contributions manager
  3. install muse and, if oscp5 is not installed by user in contributions manager, muse is broken and gives errors.

I’m not sure whether 2 is supported by the way PDE installers work. 3 seems like a bad idea – counter to the Processing ethos of making things work for beginners. That would mean 1 is the easiest way to go – the downside being that your library could be using a different version of oscp5 internally than the user has installed – but the upside being that if the user updates their oscp5, it will never suddenly break muse, as muse uses an internal copy that is frozen.

I do not know if you can have the same library multiple times under the Processing Library folder. I will need to confirm this. My suspicion arises from my experience dealing with other libraries that seem to be doing this. The PDE might be loading all the jars and it will show conflict/ambiguous messages.

I will do some testing tomorrow and I let you know. I will agree with @jeremydouglass, you want to make sure your library works out-of-the-box to ensure the best user experience. I imagine that if you were using something like maven, you will declare this as a dependency. This is not actually supported in Processing as far as I understand.

As a temporal solution, I could imagine using a wrapper + fully qualified class names. It is not pretty but could do the job. This is not needed if what I said above is not true, and you don’t get those ambiguous messages.

=======EDIT
Relevant:

Kf


kf_keyword: Processing java library, jar files, building libraries

2 Likes

So Processing handles the third case and move the responsibility to the user to make sure the library is installed. In your case for your Library, you can access another library using the standard way. For example, if you were to use a component of the Minim library: import ddf.minim.ugens.Waveform; When a user uses your library, Processing also adds the Library folder into the classpath of your user’s sketch so it will access any other library installed via the Contribution Manager. In your case, it would be OscP5. If the user does not have this library installed, it will show the error:
The package “ddf” does not exist. You might be missing a library. This error is very informative and I would think option 3 would be the way to go instead of managing third parties dependencies yourself.

Kf

2 Likes

Thanks for your reply.

Yes, 1 does seem the “safest” solution, but, as you point out, if the dependent library is updated, then all the scattered (and hidden) copies of it need to be located and updated as well. I would be happy with 2 (and even 3, if the error message were clear enough), but these don’t seem to work (or wouldn’t work) in Processing: Even if the dependent library is installed, Processing does not find it if the library is only referenced from within my library (and not from the Sketch file).

For example, if I have my library without oscP5 inside it, but have installed oscP5 in the libraries folder, then my sketch, which only references the muse library, fails to load with a class not found error…

Caused by: java.lang.NoClassDefFoundError: oscP5/OscEventListener

If I add a spurious (unused) import of the library in my sketch (import oscP5.*;), the error goes away. I don’t understand the magic Processing does to convert a Sketch into a Java program, but it appears to include referenced libraries in the CLASSPATH, even if they are not explicitly used by the Sketch.

In any case, I’ll stick with option 1 for now.

Thanks again.

1 Like

Just looked at your “relevant” links. The video one, indeed, pinpoints the problem I have–and the “solution” I discovered: Include a spurious link to the dependent library in the Sketch. Judging from the serial one, I might be able to monkey with the Processing class path behind the scenes (in my library) and make it work. Will try that.

Thanks for weighing in.

I had a similar problem with G4P when trying to include PeasyCam.

To set the scene I use Eclipse and the Processing Library Template to build my libraries. Now I had 3 choices

  1. Include the PeasyCam jar in the distribution by putting it in the project lib folder
  2. Add the PeasyCam source code to the library project
  3. Link the PeasyCam jar to the library project in the build properties file.

The problem with (1) is that if you include the PeasyCam jar code in the lib folder it is available to the library but not to the sketch code. Including the PeasyCam library in the normal way then causes conflicts in the library jar.

The problem with (2) is that the PeasyCam code has to be updated manually and would need to be in a different package to the standard include.

Option (3) overcomes the difficulties of the previous options because the G4P library does not include the PeasyCam jar and does not have the PeasyCam source code embedded in its own code base. Using this option means that the Eclipse project must link to the jar in the build properties file. The following is an extract from the file for G4P

# Add all jar files that are required for compiling your project to the local 
# and project classpath. Use a comma as delimiter. These jar files must be 
# inside your classpath.local.location folder.

classpath.local.include=core.jar,jogl-all.jar,peasycam.jar

The PeasyCam library need only be included via the Processing IDE when G4P needs to make use of it.

Currently I am working on the next release of Shapes3D and in that version it is possible to use processing.video.Movie objects as textures. In other words Shapes3D uses Processing’s video library, so a similar situation. While doing this I discovered that option (3) only works if the Shapes3D API has no reference to the Movie class. In other words the Movie class is only used internally. So I could not use this

	public Shape3D movie(PApplet pApplet, Movie movie, int parts){
                // implementation
		return this;
	}

but since Movie inherits from PImage I could do this

	public Shape3D movie(PApplet pApplet, PImage movie, int parts){
                // implementation
		return this;
	}

and then test the parameter movie to see if if was a Movie object in the implementation.

In G4P API there is only one method that mentions PeasyCam -

	public PeasyCam getPeasyCam() {
		return pcam;
	}

Hope this helps.

1 Like

Thanks for this example. I’m using IntelliJ and think I can make similar adaptations.

@quark’s point #1 above is documented here.

Bottom line, if you want packages from the other JARs to be loaded by Processing, then you need to put those .class files into the main .jar file for the library ( sonia/library/sonia.jar in this case).



@quark Could you explain your issue here:

I didn’t understand your issue. You are using PImage instead to refer to your Movie object but then you are checking in your function that is indeed a Movie object? I am quoting: “and then test the parameter movie to see if if was a Movie object in the implementation”. I think I missed something here and personally I would prefer to use a Movie instead of PImage.

Kf

1 Like

So expanding on the actual method implementation used in Shapes3D we have something like

public Shape3D movie(PApplet pApplet, PImage movie, int parts){ 
    if(movie instanceof Movie){
        // we have a movie so deal with it
    else {
        // we have an image not a movie
    }
}

The advantage here is that the sketch only has to include the video library IF the sketch calls this method. If I used Movie instead of PImage for the parameter type then I would have to use option (1) or (2) described above to get the Shapes3D library to work, even it the sketch didn’t use the method.

2 Likes