Client represents a remote sclang application
Client and LocalClient together represent a sender / reciever pair for sclang side osc messages.
Using SynthDef like global function definitions, ClientFunc, an sclang application
can evaluate code on a remote sclang app.
Class Methods
*new(name, netAddr)
returns a new instance and stores it in a global dictionary
the port is set to defaultPort, which is hardcoded presently.
if no address is passed in, localhost is used.
Instance Methods
send(key, args ...)
evaluates a client function that is stored at that key
password_ (symbol)
set the password for interpreter access
cmdName_
set the cmdName under which the client sends (default: '/client')
this cmdName must be the same like the LocalClient reciever cmdName
interpret(string)
if the remote client has the same password, it interprets the string
LocalClient represents a listener to a remote sclang application
superclass: Client
Note that passing a nil address to LocalClient will make it respond to any remote client
and try to match any message that is sent from a client object.
If it is expected to listen to a specific remote client, the address of that client should be used.
Instance Methods
start
start listening to the world
stop
stop listening to the world
reply( key, args...)
reply to a sender with a message
remove
remove from client list
isListening
returns whether it is listening to the world
password_ (symbol)
set the password for interpreter access from outside
cmdName_
set the cmdName under which the client recieves (default: '/client')
this cmdName must be the same like the Client sender cmdName
allowInterpret
open the interpreter to the world (potential hacking danger)
disallow
close the interpreter access
ClientFunc similar to SynthDef - represents a client side stored function
*new(name, func)
global function that is accessed by LocalClient when a message is recieved.
the key sent is a key of the ClientFunc that is evaluated.
the other args are passed to the function: time, responder, args...
Note:
for accessing a gui element or a document from an OSCResponder such as the one
in LocalClient, one has to defer the action:
ClientFunc(\ok, { defer({ ... }) });
// example
// instantiate a remote-local pair (in this case both are local of course)
a = LocalClient.default; // this one listens to any remote client and evaluates the functions.
b = Client.new; // this one sends the messages
// eqivalent to the above defaults:
a = LocalClient(\default, nil); //addr is nil : listen to all
b = Client(\default, NetAddr("127.0.0.1", 57120));
// store some client functions to be accessible from outside (analogous to SynthDef)
ClientFunc(\ok, { arg ... args; args.postln });
ClientFunc(\yes, { arg ... args; \ok2.postln });
// start the local client
a.start;
// send messages
b.send(\ok, "rrere", 39);
b.send(\ok, "rrxxxre");
b.send(\ok, 2, 3, 4, 5, 6);
b.send(\yes, "rrere", 39);
b.send(\yes);
opening remote interpreter access is risky, because
anyone can access the interpreter (also unix commands)
if you do not set the password, this is not possible.
// open interpreter
a.password = \xyz;
b.password = \xyz;
a.allowInterpret;
// remote interpret
b.interpret(" Array.fill(8, { [1,0].choose }).postln ");
b.interpret(" String.fill(80, { [$u, $n].choose }).postln");
// remote GUI
b.interpret(" GUI.window.new(\"aLl uR mAchIneZ are bEloNg to us!\").front;{ SinOsc.ar(500, 0, LFPulse.kr(4)) }.play;");
// close interpret
a.disallow
//test: this should not interpret
b.interpret(" String.fill(8, { [$u, $n].choose }).postln");
a.stop; //stop local responder
writing a chat
(
// hit tab for sending
var n, d, e, b;
n = "John";
d = Document("chat").background_(Color.rand).bounds_(Rect(30, 10, 400, 200));
e = Document("chat-write").background_(Color.rand).bounds_(Rect(30, 210, 400, 50));
a = LocalClient.default.start;
b = Client.new;
ClientFunc(\chat, { arg str; { d.string = d.string ++ str ++ "\n" }.defer });
e.keyDownAction_({ arg doc, char;
var string;
if(char === Char.tab)
{
string = n + ":" + e.currentLine;
b.send(\chat, string.copy);
AppClock.sched(0.1, { e.string = "" }); // time is the original crime. remove the tab.
}
});
e.onClose_({ AppClock.sched(0.1, { a.remove; d.close; nil }) }); // sched, otherwise sc crashes
)