Search code examples
max-msp-jitterableton-live

How can I include a mxj Java jar/class folder in a freezed m4l-Device?


I have a maxforlive device using java/mxj.

I used all of these options to include my java files during development:

  • Including my (maven) target/classes directory through max.java.config.txt.
  • Adding a directory through Options > File Preferences
  • Adding a jar to the automatically generated (OSX) ~/Documents/Max 7/Max for Live Devices/MyProject Project/ directory

All of these paths work fine i.e. the files are picked up and my mxj object works.

However, when i freeze the device for publication, java files are not included from any of those paths.

I tried to make sense of https://docs.cycling74.com/max7/tutorials/jitterchapter99_appendixd although I'm not building a standalone, but a freezed maxforlive device, so I included max.jar and mxj.mxo in the Project folder which did not work either.

When I copy my target/classes or target/classes/myproject folder into the generated Project folder (/code, /code/classes, /classes), max moves all the class files out into /code, creating a lot of work for me while not even picking the classes up for dev.

I saw devices on maxforlive.com with properly included java files, so I know it can be done. How can I achieve this?


Solution

  • Ok, so here it is: Including just a single class with no other class dependencies except MaxObject works fine. There's also no need to add .java files like I said in my previous comment.

    All you need to do is:

    • have the working mxj object in your patcher (doesn't matter where you saved it)
    • click the button on the bottom that says "Show containing project" on hover
    • add your classfile
    • freeze

    When you have more classes, it gets complicated.

    1) If you have your typical java hierarchy with folders and subfolders, that won't work. As you have to add each file separately, the hierarchy will be destroyed. Use a jar and add it to the containing project.

    2) Here it comes, believe it or not: All the classes you are going to use will have to be loaded on first instantiation. I call it static class allocation ;)

    A way to achieve that:

    • create a new instance of every class in the constructor of the class that extends MaxObject or any other constructors it calls. That includes classes with only static methods.

    • if you happen to use interfaces and create implementations of those dynamically (new Runnable() {...}), don't. Dynamic implementations are new classes.

    Fun fact: you can override methods of classes, too. So go

        class Runner {
          public void run() { throw new Exception("not implemented"); }
        }
    

    then you can dynamically create a

        new Runner() {
          public void run() {
            MaxObject.post("Even Mr. Gosling says interfaces were a mistake!");
          }
        }
    

    Don't believe it? I don't blame ya. Look at https://github.com/mihop/mxj-wsserver and http://www.maxforlive.com/library/device/3809 to be converted.