SwingOSC – Java-based GUI classes

last mod: 27-jan-08 sciss

SwingOSC

A SwingOSC object is the client-side representation of a java GUI server. A lot of the method names are closely modelled after the Server class (the client representation of scsynth), so it"s fairly easy to use.

SwingOSC is also the name of the java / OSC based GUI library. For an overview of GUI objects using SwingOSC, please read the help file SwingGUI.

The default server

There is always a default Server, which is stored in the class variable default. Any GUI components created without a target will be created on the default server. At startup, a server representation referring to the local machine is created and stored both in the class variables local and default. When you boot SwingOSC manually from a terminal (see below), please note that this default server assumes SwingOSC to listen at TCP port 57111 and to send an initial ping message to sclang (127.0.0.1:57120). If the initial ping is not send, you will have to call initTree manually.

Note that in this document we will assume that the global variable g is assigned to the default server, by executing the following line:

     g = SwingOSC.default;   // !
	  
	  

Booting and Quitting the Server from within SuperCollider

Method signatures:

        <aServer>.boot( <startAliveThread = true> )
        <aServer>.quit
        

Examples:

        g.boot;
        // ...
        g.quit;
    

Note: this assumes that the file "SwingOSC.jar" has been copied into the main SuperCollider folder. If you want to use a different install location, set the class variable program appropriately:

        SwingOSC.program = "<completePathToAndIncludingSwingOSC.jar>";
       

Here's for example, what my "~/scwork/startup.rtf" reads:

        SwingOptions.default.javaOptions = SwingOptions.default.javaOptions + "-Xdock:icon=/Users/rutz/Documents/workspace/SwingOSC/application.icns";
        SwingOSC.program                 = "/Users/rutz/Documents/workspace/SwingOSC/build/SwingOSC.jar";
        g                                = SwingOSC.default;

If you want to use a specific java program, you can set the class field java, e.g. to force SwingOSC to boot with a Java 1.4 version on Mac OS X:

        SwingOSC.java = "/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Commands/java";

You can register a custom function to be executed when the server has been booted. For example:

Method signature:

    <aServer>.doWhenBooted( <func>, <timeout = 20> )
        

Example:

(
    g.doWhenBooted({
        JSCWindow.viewPalette;
    });
    g.boot;
)

Differences to the audio Server: doWhenBooted's second argument here is timeout in seconds.

Alternatively you can combine the two methods above:

Method signature:

    <aServer>.waitForBoot( <func>, <timeout = 20> )
        

Example:

(
    g.waitForBoot({
        JSCWindow.viewPalette;
    });
    g.boot;
)

On Mac OS 10.3.9 (Panther), there is a known issue with unixCmds blocking each other, so to boot SwingOSC and scsynth successively, you may need to call g.unblockPipe after booting SwingOSC.

 

Booting the server from a terminal

You can boot a SwingOSC server from within sclang with the boot method (see above). However sometimes you may wish to boot it from a terminal or by double clicking an executable shell script in the Finder. Please refer to the Document "readme.html" in the main SwingOSC folder to learn about launching the server from a terminal. You usually launch the server by the following command:

	cd <mainSwingOSCFolder>
  	java -jar build/SwingOSC.jar -t 57111 -i -L
	

Make sure to use TCP port 57111 and restrict OSC communication to the local machine (-L option) when possible.

If you prefer to use UDP transport, use -u instead of -t.

To quit the server press Ctrl-C in the terminal.

 

Creating another server

You might want to create another server instance because


To create a new server:

	<aServer> = SwingOSC.new( <name>, <addr>, <options>, <clientID> );
	

The name must be a unique Symbol (no two servers with the same name may exist). The addr is a NetAddr object describing the server's socket (IP and port). The options argument is an instance of SwingOptions. If several clients are sharing the same server, use a different clientID Integer (default: 0) for each, so their objectID-allocators won't interfere.

Important: If you don't specify options, default options will be created. loopBack is turned on (true) if the supplied addr argument uses the loopback-IP "127.0.0.1", otherwise it is off. Inversely, if you don't specify an addr, an appropriate address will be created: if the option's loopBack flag is true, the address will be NetAddr"127.0.0.1", 57111 ). If loopBack is false, the local computer's IP address will be determined (only working on Unix systems). Therefore, to use a server without loopback as default:

	g = SwingOSC.new( \test, options: SwingOptions.new.loopBack_( false ));
	SwingOSC.default = g;
	g.boot;

Do not try to modify the loopBack settings an already existing server.

Here is another example:

(
    f = SwingOSC.new( \secondSwing, NetAddr( "localhost", 44444 ));
    f.options.protocol = \udp;  // if you don't want tcp
    f.waitForBoot({
        var win;
        
        win = JSCWindow( server: f );
        win.onClose = { f.quit; };
        JSCStaticText( win.view, Rect( 40, 40, 100, 30 )).font_( JFont( "Helvetica", 36 )).string_( "Kieka" );
        win.front;
    });
    // use this on MacOS 10.3.9 Panther if booting blocks:
    // g.unblockPipe;
)

 

Sending Messages to the Server and Receiving Replies

Method signatures:

    // send a single message
    <aServer>.sendMsg( <arg1>, [ <arg2>  ... ])
    // send a single message as array
    <aServer>.listSendMsg( <arrayOfArgs> )
    // send a bundle
    <aServer>.sendBundle( <time>, <arrayOfArgs1>, [ <arrayOfArgs2>  ... ])
    // send an array of messages as a bundle
    <aServer>.listSendBundle( <time>, <arrayOfArraysOfArgs> )
        

Examples:

     g.sendMsg( '/print', '[', '/local', \OS_Name, '[', '/method', 'java.lang.System', \getProperty, 'os.name', ']', ']');
     g.listSendMsg([ '/print', '[', '/local', \OS_Version, '[', '/method', 'java.lang.System', \getProperty, 'os.version', ']', ']' ]);

Note: bundle times should always be set to nil for now, since they are not used by SwingOSC. this behaviour may change in the future, so your code is safe if you use nil.

To receive replies, you can set up either a normal OSCresponderNode or an OSCpathResponder. If, for some reason, the address argument doesn't work, use nil instead. Example:

(
    OSCpathResponder( g.addr, [ '/info', \confirm ], { arg time, resp, msg;
        var choice, rgb;
    
        resp.remove;
        choice = msg[ 2 ];
        ("User's choice : " ++ [ "Ok", nil, "Cancel" ].at( choice )).postln;
        if( choice == 0, {
            OSCresponderNode( g.addr, '/set', { arg time, resp, msg;
                if( msg[ 1 ].asSymbol === \color, {
                    resp.remove;
                    msg.postln;
                    rgb = msg[ 3 ];
                    ("New colour : " ++ Color.new255( (rgb >> 16 & 0xFF), (rgb >> 8) & 0xFF, rgb & 0xFF )).postln;
                });
            }).add;
            g.sendBundle( nil,
                [ '/local', \color, '[', '/method', \colorChooser, \getColor, ']' ],
                [ '/get', \color, \RGB ]);
        });
    }).add;
    // note : showConfirmDialog is modal and will block OSC processing in SwingOSC
    // until the dialog is closed. this is just an example anyway
    g.sendBundle( nil,
        [ '/local', \colorChooser, '[', '/new', 'javax.swing.JColorChooser', ']' ],
        [ '/query', \confirm, '[', '/method', 'javax.swing.JOptionPane', \showConfirmDialog,
            '[', '/ref', \null, ']', '[', '/ref', \colorChooser, ']', "Select a colour", 2, ']' ]);
)

The above example can be simplified by using the sendMsgSync method. This must be called inside a Routine as for example created by fork:

Method signature:

        // send a single message and wait for a success or failure reply
        <aServer>.sendMsgSync( <msgArray>, <successMsgArray>, <failureMsgArray>, <timeout = 4>, <condition> )
        

Example:

(
fork {
    var choice, rgb, msg;

    g.sendMsg( '/local', \colorChooser, '[', '/new', 'javax.swing.JColorChooser', ']' );
    msg = g.sendMsgSync([ '/query', \confirm, '[', '/method', 'javax.swing.JOptionPane', \showConfirmDialog,
                            '[', '/ref', \null, ']', '[', '/ref', \colorChooser, ']', "Select a colour", 2, ']' ],
        [ '/info', \confirm ], timeout: 60 );
    if( msg.notNil, {
        choice = msg[ 2 ];
        ("User's choice : " ++ [ "Ok", nil, "Cancel" ].at( choice )).postln;
        if( choice == 0, {
            g.sendMsg( '/local', \color, '[', '/method', \colorChooser, \getColor, ']' );
            msg = g.sendMsgSync([ '/get', \color, \RGB ], [ '/set', \color, \RGB ]);
            if( msg.notNil, {
                rgb = msg[ 3 ];
                ("New colour : " ++ Color.new255( (rgb >> 16 & 0xFF), (rgb >> 8) & 0xFF, rgb & 0xFF )).postln;
            }, {
                "Timeout!".warn;
            });
        });
    }, {
        "This takes way too long, i'm giving up".postln;
    });
};
)

Note: a timeout of nil means no timeout (waits forever).

 

Adding custom Java classes to the class path

Method signatures:

        <aServer>.addClasses( <url1>, [ <url2> ... ])
        <aServer>.removeClasses( <url1>, [ <url2> ... ])
        <aServer>.updateClasses( <url1>, [ <url2> ... ])
        

Example: see "DynamicClasses.html" in examples for folder.

URLs can point to single class files, jar archives or folders containing class files. Make sure to use proper file://... URLs and not plain path names for files!

The updateClasses method can be used to dynamically develop java classes. It is a shorthand for removing and re-adding the URLs in order to use modified recompiled versions of java classes.

 

Class methods

Method signatures:

	SwingOSC.local;     // reference to default local server
	SwingOSC.default;   // reference to default local server; this will be used in GUI elements when no explicit server is specified
	SwingOSC.quitAll;   // quit all registered servers ; UNTESTED
	SwingOSC.killAll;   // query the system for any SwingOSC server apps and hard quit them ; UNTESTED