Announce: embedded web server for MaxMSP (beta)

Jan 16, 2008 at 6:37pm

Announce: embedded web server for MaxMSP (beta)

An installation piece I’m working on requires an embedded web server,
so I thought I’d go ahead and wrap up Jetty inside MXJ and release
the thing as a package under the LGPL, just in case anyone else finds
it useful to run a web server over bits of MaxMSP’s search path. You
can find it here:

http://www.loadbang.net/space/Software/net.loadbang.web

Instructions, javadocs, examples and sources included. I’m planning
to announce it to the general MaxMSP list soon, but thought I’d let
people on the developer list give it a bit of a bashing first. I’ve
run it on OS X and Windows and it seems pretty happy.

– N.

Nick Rothwell / Cassiel.com Limited
http://www.cassiel.com
http://www.myspace.com/cassieldotcom
http://www.last.fm/music/cassiel
http://www.reverbnation.com/cassiel
http://www.linkedin.com/in/cassiel
http://www.loadbang.net

#35404
Jan 17, 2008 at 4:50am

Nice! Thanks Nick, this is great. I had been meaning to try this for a while but never got around to it.

One thing I’ve wanted to do was to control Max patches from the web. I think using the URL query string would be a good way to do this, but your object doesn’t expose that to the patch. So I made a few adjustments…

* In net.loadbang.web.mxj.WebServer
I increased the number of outlets.
declareIO(1, 4);

* In net.loadbang.web.WebServer I added the following code to the top of ReporterHandler.handle() (sorry for the forum messing up my code formatting):

Enumeration params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = (String) params.nextElement();
String[] vals = request.getParameterValues(param);
if (vals == null) {
itsOutputter.output(3, param);
}
else {
StringBuffer s = new StringBuffer(param);
for (int i = 0; i < vals.length; i++) {
s.append(” “).append(vals[i]);
}
itsOutputter.output(3, s.toString());
}
}
// or something like this:
// itsOutputter.output(3, request.getQueryString());
// but I don’t feel like doing query string parsing in Max

Then, as a really simple example, you could serve up the following HTML:

To control this patch:

#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 376 147 32 196617 print;
#P user textedit 122 212 270 233 32896 3 9;
#P newex 122 186 62 196617 prepend set;
#P user textedit 306 213 454 234 32896 3 9;
#P newex 306 187 62 196617 prepend set;
#P newex 266 138 90 196617 route text1 text2;
#P window setfont Monaco 9.;
#P user umenu 23 42 100 262183 1 64 57 1;
#X add stop;
#X add start;
#P window linecount 2;
#P newex 113 79 214 262153 mxj net.loadbang.web.mxj.WebServer @port 8080 @placeholder web-root;
#P connect 1 1 0 0;
#P connect 2 0 5 0;
#P connect 5 0 6 0;
#P connect 2 1 3 0;
#P connect 3 0 4 0;
#P connect 0 3 7 0;
#P connect 0 3 2 0;
#P window clipboard copycount 8;

If that seems useful to you, might be worth including in your external. It wouldn’t take much effort to do something more interactive like using AJAX to update the Max patch on-the-fly (I think there was something like that in the aka.iphone experiements).

It would also be cool to enable JSP support. This could be used to allow the Max patch to communicate back to the browser. I’m not exactly sure how you do that with an embedded Jetty server. I might look into that some other time (unless you already know how?)

BTW, I was not able to use your build.xml file:
$ ant
Buildfile: build.xml
/Users/adam/workspace/net.loadbang.web/MXJ-basis/ant-defs.xml could not be found

BUILD FAILED
java.io.FileNotFoundException: /Users/adam/workspace/net.loadbang.web/MXJ-basis/ant-defs.xml (No such file or directory)

Cheers,
Adam

#120626
Jan 17, 2008 at 5:37am

This code is probably better:

Enumeration params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = (String) params.nextElement();
String[] vals = request.getParameterValues(param);
if (vals == null) {
itsOutputter.output(3, param);
}
else {
for (int i = 0; i < vals.length; i++) {
itsOutputter.output(3, param + ” ” + vals[i]);
}
}
}

Adam

#120627
Jan 17, 2008 at 7:14am

I got JSPs to work. Just needed to add the jars from Jetty’s lib/jsp directory (I used jsp-2.1), and then add the following handler in the handlers.setHandlers() call:

new WebAppContext(directory.toURL().toString(), “/”)

This seems to break the DefaultHandler’s behavior for favicon though (who cares?)

I also have some other changes that let me send messages like “set attrName attrValue” to the WebServer object in Max, and then I can access the value in the JSP with the ${attrName} syntax. So 2-way communication between the web browser and the Max patch is easily possible. Let me know if you would like to see the code.

-Adam

#120628
Jan 17, 2008 at 9:38am

> I got JSPs to work.

Wow. Quick work…!

I had been playing around with the servlet support, and had thought
about having the MXJ object call out into Max, but hadn’t thought
about JSP support. Thanks for all the effort. If you’re happy with
it, I’ll integrate your enhancements into the main release (credited,
natch).

– N.

nick rothwell — composition, systems, performance — http://
http://www.cassiel.com

#120629
Jan 17, 2008 at 12:24pm

> BTW, I was not able to use your build.xml file:
> $ ant
> Buildfile: build.xml
> /Users/adam/workspace/net.loadbang.web/MXJ-basis/ant-defs.xml could
> not be found

Oh yeah, sorry about that: the various references between the Ant
files (and for that matter, the class paths) are dependent on the way
I’ve laid out my Eclipse projects, and it’ll take a bit of effort to
get that into a form which can be used by anyone else. Well done on
getting it all into the air regardless.

– N.

Nick Rothwell / Cassiel.com Limited
http://www.cassiel.com
http://www.myspace.com/cassieldotcom
http://www.last.fm/music/cassiel
http://www.reverbnation.com/cassiel
http://www.linkedin.com/in/cassiel
http://www.loadbang.net

#120630

You must be logged in to reply to this topic.