# SwingOSC -- v0.54 OSC Command Reference --

### Basic Concept and Notation

The concept of SwingOSC is mainly to map the API of the Java reflection mechanism to OpenSoundControl. Reflection means that although Java code is compiled (just in time), objects can inspect themselves, their methods and fields – just as in an interpreted language. This powerfull mechanism provides the basis for "scripting" java, that is, creating objects on the fly and calling arbitrary methods in an interpreted style.

Java distinguishes between fields and methods. To read a java object's field, the `"/field"` and `"/fieldr"` OSC commands are provided. To call a java object's method, the `"/method"` and `"/methodr"` OSC commands are provided. To instantiate an object, use the `"/new"` command.

A variable mechanism is provided by the `"/local"`, `"/global"` and `"/free"` OSC commands. Variables are referred to by an arbitrary identifier, similiar to node IDs in SuperCollider, however in SwingOSC an identifier can be a string as well. Unlike SuperCollider, variables (node IDs) are not linked in any kind of tree structure. Freeing a variable will not dispose or cleanup the object that it refers to; the client is responsible for calling appropriate methods before removing the variable.

Communication back to the client is accomplished by the `"/query"` command. However, java classes themselves can provide other mechanisms, as demonstrated for example in the `ActionResponder` class which uses a custom OSC message `"/action"`.

Message formatting is closely based upon the perspective and features of SuperCollider's OSC engine. The key concepts are:

- Flat namespace. SwingOSC doesn't use OSC "path" addresses such as `"/myWindow/contentPane/firstContainer/firstGadget/resize"`. Instead, each object is referred to by an identifier chosen by the client.
- Only basic tag types. SwingOSC like SuperCollider recognizes floats, integers and strings. A bundle's timetag is ignored at the moment.
- Functional style message nesting. SuperCollider does not supported array type tags. To allow functional style programming, the string arguments "[" and "]" carry the special meaning of introducing a sub-OSC-message. You can think of this sub-message as a `( ... )` LISP-expression which gets evaluated to a single return value (with possible side-effects!). Sub-messages are evaluated from left to right in depth-first-order. If a sub-message has a return value, this value is used instead of the message as the argument of the outer message. For example, processing the message
  `[ "/print", "[", "/local", "myPoint", "[", "/new", "java.awt.geom.Point2D$Double", "[", "/method", "java.lang.Math", "cos", 0.5, "]", "[", "/method", "java.lang.Math", "sin", 0.5, "]", "]", "]" ]`
  will first examine the `"/print"` command whose first argument is expected to be a variable name. Instead of writing the variable name as a string, we use a nested message that as a side effect calculates the cosine and sine of 0.5, creates a point object with these values and assigns that point object to a local variable `myPoint`. `"/local"` not only assigns a value to a variable but also returns the name of the variable, hence this name is the argument passed to `"/print"`. Complicated?
- Note that to use the reserved bracket strings as regular strings you need the special escape sequences `"[", "/ref", "brko", "]"` (open bracket) and `"[", "/ref", "brkc", "]"` (close bracket).
- For backwards compatibility it is still allowed to use real arrays in SuperCollider which get encoded to an OSC blop (binary large object). However this practise is deprecated and not recommended.

To ease the use of Swing GUI classes and the Beans terminology, the `"/set"` and `"/get"` commands are provided.

By convention, SuperCollider notation is used in this reference document. That is, an OSC message is written as an array in square brackets `[ ... ]` with the first element being the command name (or "OSC address") and the successive elements being the OSC message arguments. For brevity, method and variable names are sometimes written as symbols using a backslash (`\myVariable`), although they are converted into strings by SuperCollider when sending the message. Placeholders are written inside pointed brackets `< >` and prefixed by a javaish type name (`Object` meaning "any kind of type"). When arguments can occur once or more, the notation `[ ... ] * N` is used where the square brackets are not to be confused with a nested message!

### Creating a Global Assignment

Global assignments are assignments accessible by all clients. They share the same name space. Assigning an object to a global variable which already exists, will override that variable. This behaviour might change in the future, so be sure to free variables properly before reusing them. To distinguish variables from class names in a `"/method"` statement, please do not use period characters in the variable name and do not begin with an uppercase character.

Syntax:

    [ "/global"
    	[ String <objectID>,
    	 Object <value> ] * N
    ]

Returns: the object identifier of the last assignment.

Example: `[ "/global", "pi", 3.1415926 ]`

### Creating a Local Assignment

Local assignments are assignments accessible only by the client which created that assignment. The client is identified by its sending address. Assigning an object to a local variable will obscure a global variable of the same name. To distinguish variables from class names in a `"/method"` statement, please do not use period characters in the variable name and do not begin with an uppercase character.

Syntax:

    [ "/local"
    	[ String <objectID>,
    	  Object <value> ] * N
    ]

Returns: the object identifier of the last assignment.

Example: `[ "/local", "pi", 3.1415926 ]`

### Removing Assignments

Each `<objectID>` will be first looked up in the local dictionary, and, if not found, in the global dictionary.

Syntax:

    [ "/free"
    	[ String <objectID> ] * N
    ]

Returns: the value corresponding to the last freed object.

Example: `[ "/free", "pi" ]`

### Printing Variables

The values of variables are printed to the console of the SwingOSC server, using each object's `toString()` method.

Syntax:

    [ "/print"
    	[ String <objectID> ] * N
    ]

Returns: the value corresponding to the last printed object.

Example: `[ "/print", "pi" ]`

### Referring to an Assignment

This de-references an object and makes it available as an argument to a method call for example, by replacing the variable name with the variable value.

Syntax:

    [ "/ref"
    	String <objectID>
    ]

Returns: the value corresponding to the variable referred to by `<objectID>`.

Example: `[ "/global", "second_pi", "[", "/ref", "pi", "]" ]`

### Constructing an Array Argument

Syntax:

    [ "/array"
    	[ Object <anObject> ] * N
    ]

Returns: an `Object[]` array with elements provided by the arguments.

Example: `[ "/new", "javax.swing.JComboBox", [ "/array", "spring", "summer", "autumn", "icecream" ]];`

Typed arrays and arrays of primitives are not supported. Arrays always appear as `Object[]`. This means that a method whose signature is for example `public void theMethod( float[] someValues )` cannot be called. You may of course add a custom java class with a helper method `public void theMethod( Object[] someValues )` that converts the arguments to a float array and calls the original method.

### Creating an Object

Syntax:

    [ "/new"
    	String <className>,
    	[
    	  Object <constructorArgument>
    	] * N
    ]

Returns: the newly created java object.

Example:
`[ "/new", "javax.swing.JFrame", "MyTitle" ]`
`[ "/global", "myFrame", [ "/new", "javax.swing.JFrame", "MyTitle" ]]`

### Calling Methods on Object References

Syntax:

    [ "/method"
    	String <objectID>,
    	String <methodName>,
    	[
    	  Object <methodArgument>
    	] * N
    ]

Returns: the method return value or `null` if the method has no return value (is declared `void`).

Example:
`[ "/method", "myFrame", "add", [ "/ref", "myButton" ]]`
`[ "/method", "myFrame", "toFront" ]`

Note: when `<objectID>` is the name of a class, the static class method will be invoked on that class.

e.g. `[ "/query, "now", [ "/method", "java.lang.System", "currentTimeMillis" ]]`

### Calling Methods directly

Syntax:

    [ "/methodr"
    	Object <anObject>,
    	String <methodName>,
    	[
    	  Object <methodArgument>
    	] * N
    ]

Returns: the method return value or `null` if the method has no return value (is declared `void`).

Example: `[ "/methodr", [ "/new", "java.awt.FileDialog", [ "/ref", \myFrame ]], \show ]`.

### Setting Object Properties

This is a helper mechanism which can be fully emulated using the `/method` command. It is provided for improved readability and as a shortcut to `/method`, similar to the `<properties>` tag in java's `XMLEncoder`.

Syntax:

    [ "/set"
    	String <objectID>,
    	[
    	  String <propertyName>,
    	  Object <propertyValue>
    	] * N
    ]

Returns: the return value of the last setter method or `null` if that method has no return value.

Example:
`[ "/set", "myButton", "focusable", false, "background",
[ "/new", "java.awt.Color", 0xFF, 0x00, 0x7F ]]`

which is equal to

           [[ "/method", "myButton", "setFocusable", true" ],
            [ "/method", "myButton", "setBackground",
            [ "/new", "java.awt.Color", 0xFF, 0x00, 0x7F ]]]

### Getting Return Values

This method sends java objects back to the OSC client using `"/info"` reply messages. These objects must be basic single value objects such as a string, a number, a boolean.

Syntax:

    [ "/query"
    	[  String <identifier>,
    	   Object <anObject>
    	] * N
    ]

Returns: the return value of the last getter method or `null` if that method has no return value. Note that because of the "side-effect" nature of `"/query"`, it shouldn't really be used in message nesting.

Example: `[ "/query", "pi", [ "/ref", "pi" ], "second_pi", [ "/ref", "second_pi" ]]`

This example will reply to the OSC client with the message `[ "/info", "pi", 3.14..., "second_pi", 3.14... ]`

Example:
`[ "/query", "piInt", [ "/method", "pi", "intValue" ],
"butSel", [ "/method", "myButton", "isSelected" ]]`

This example will reply with the message `[ "/info", "piInt", 3, "butSel", true ]`. So generally, the `<identifier>` can be chosen arbitrarily by the client and is only used to let the client identity its query by looking at the even indices arguments of the `"/info"` message.

### Getting Object Properties

This method sends object properties back to the OSC client using `"/set"` reply messages.

As `"/set"` is a shortcut for `"/method"`, `"/get"` is a shortcut for `"/query"`. Property-getter methods are resolved by prepending `"get"` to the property name in the first place, and, if not found, retrying with the prefix `"is"`. Therefore a property `"selected"` is looked up as method `"getSelected()"` first, and, if not found, as `"isSelected()"` second. Getter methods requiring additional argument must be invoked using the `"/query"` command.

Syntax:

    [ "/get"
    	String <objectID>,
    	[
    	  String <propertyName>
    	] * N
    ]

Returns: the return value of the last getter method or `null` if that method has no return value. Note that because of the "side-effect" nature of `"/get"`, it shouldn't really be used in message nesting.

Example: `[ "/get", "myButton", "selected", "focusable", "text" ]`

This example will reply to the OSC client with the message
`[ "/set", "myButton", "selected", true, "focusable", false, "text", "OK" ]`

### Retrieving Fields on Object References

Syntax:

    [ "/field"
    	String <objectID>,
    	String <fieldName>
    ]

Returns: the value of the field of the object saved in the variable `<objectID>`.

Example:
`[ "/field", "myDimension", "width" ]`
`[ "/field", "java.awt.Color", "red" ]`

Note (second example): when `<objectID>` is the name of a class, the static class field will be retrieved.

### Retrieving Fields directly

Syntax:

    [ "/fieldr"
    	Object <anObject>,
    	String <fieldName>
    ]

Returns: the value of the field of the object `<anObject>`.

Example: `[ "/fieldr", [ "/new", "java.awt.Dimension", 320, 240 ], "width" ]`.

### Adding Classes

This allows you to dynamically expand the class path. You can add `.jar` files or folders or single class files to the class loader's list of places to look for classes when a `/new` command is executed. The places have to be specified as valid URLs. This way you do not need to add all places to java's class path when launching SwingOSC. It also allows you to add remote classes in a network.

Syntax:

    [ "/classes"
    	"add"
    	[ String <classPathURL> ] * N
    ]

Returns: nothing

Example:
`[ "/classes", "add", "file:///Users/rutz/Desktop/JCollider/build/JCollider.jar" ]`
`[ "/classes", "add", "http://java.sun.com/applets/other/Bubbles/Bubbles.jar" ]`
`[ "/classes", "add", "http://java.sun.com/applets/other/Bubbles/classes/Bubbles.class" ]`

To remove or re-load modified classes use these signatures:

    [ "/classes"
    	"remove" | "update"
    	[ String <classPathURL> ] * N
    ]

### Debugging

Syntax:

Turns on/off printing of incoming OSC messages to the console. The modes are 0 = no printing, 1 = text dump, 2 = hex dump, 3 = text + hex dump . the optional second mode toggles OSC dumping of outgoing messages.

Syntax:

    [ "/dumpOSC"
    	int <mode>,
    	[int <mode2>]
    ]

Returns: nothing

### Terminating SwingOSC

Quits the server program.

Syntax:

    [ "/quit" ]

Returns: nothing

### Constants

Apart from local and global variables, a few constants are supplied by SwingOSC which can be addressed in the same way (using `"/ref"`). These are:

- `\null` : the java `null` reference. Note that due to a bug you cannot use this in a constructor (`"/new"`) statement, for example (FIXED?) `[ "/new", "javax.swing.JPanel", [ "/ref", \null ]]` don't seem to work. As a workaround you can do this: `[ "/set", [ "/local", \myPanel, [ "/new", "javax.swing.JPanel" ]], \layout, [ "/ref", \null ]]`

### OSC Format

As of version 0.3, SwingOSC uses only core type tags when sending messages: `i` (integer), `f` (float), `s` (symbol), `b` (blob). However, when receiving, it should be able to decode 64-bit numbers as well as symbols and booleans. Time tags are ignored at the moment. This may change in the future, so it is advised to use the special time-tag `nil` (scheduled for immediate execution) when creating bundles.

### Type Conversions

Since some OSC clients (i.e. SuperCollider) only have the core set of OSC type tags, some types are converted on the fly.

- when a method or constructor argument requires a boolean but an integer is provided, a zero is interpreted as "false", everything else as "true"
- integers are automatically casted into longs, floats are casted into doubles

Also note that you can use the java wrapper classes for primitives. E.g.

    [ "/new", "java.lang.Boolean", "true" ]

...although that looks a bit tedious

### Threading

All commands are deferred to the Java AWT/Swing thread. Therefore, any GUI methods may safely be invoked. Note that messages are processed synchronously which means that time consuming method calls will block successive OSC commands until the method returns. In certain cases you may wish to use a special Java class that spawns a separate thread. The OSC receiver is running asynchronously, so messages arriving while a method is evaluated are safely cached, with memory only limited by the java VM stack size.

### TO-DO

- security issues, scope / class name space limiting
- un-blob nested messages before printing them in dumpOSC mode
- bundle time awareness ?
- a non-realtime OSC-file based mode as in scsynth? could be useful for scripting
- make the /import statement work

### Known Issues

- Typed arrays and arrays of primitives are not supported. See `"/array"` for details.
- (FIXED?) the \null placeholder doesn't seem to be working in some commands ?
- user can quit the server accidentally by hitting Cmd+Q when a window is open
- SuperCollider has some OSC bugs ; see examples/SuperColliderBUGS.rtf for details

### Index

commands recognized by the server:

- `/array` : Constructing an Array Argument
- `/classes` : Adding Classes
- `/dumpOSC` : Debugging
- `/field` : Retrieving Fields on Object References
- `/fieldr` : Retrieving Fields directly
- `/free` : Removing Assignments
- `/get` : Getting Object Properties
- `/global` : Creating a Global Assignment
- `/local` : Creating a Local Assignment
- `/method` : Calling Methods on Object References
- `/methodr` : Calling Methods directly
- `/new` : Creating an Object
- `/print` : Printing Variables
- `/query` : Getting Return Values
- `/quit` : Terminating SwingOSC
- `/ref` : Referring to an Assignment
- `/set` : Setting Object Properties

commands sent by the server in reply (DOCUMENTATION PENDING):

- /set : (reply for /get)
- /info : (reply for /query)

class specific reply commands (DOCUMENTATION PENDING):

- /action : (when using the ActionResponder class)
- /window : (when using the WindowResponder class)

last mod: 30-jul-07 sciss