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
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(" SCWindow.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
)