// OSC - messages from sclang to the local server (scsynth):

see [Server-Command-Reference], [ClientVsServer], [NodeMessaging]  )

(
SynthDef("testosc", { arg gate=1, freq=400, amp=0.2;
	var sig, env;
	env = EnvGen.kr(Env([0,1,1,0],[0.01,1,0.01], \sine, 2), gate, doneAction: 2);
	sig = Saw.ar([freq, freq*1.01], amp * env);
	Out.ar(0, sig );
	}).load(s);
)	

// Object style (these objects create the equivalent OSC messages) :
y = Synth("testosc", [\freq, 200]);
y.set(\freq, 500, \amp, 0.1);
y.free;

// the same but with OSC messages:

// get the next free node number of the server
y = s.nextNodeID;		

// start a new synth on the server with /s_new :
s.sendMsg("/s_new", "testosc", y, 0, 0, \freq, 200);

// change arguments with /n_set :
s.sendMsg("/n_set", y, \freq, 500, \amp, 0.1);

// free a node with /n_free :
s.sendMsg("/n_free", y);

// OSC - messages from server (scsynth) to the local client (sclang):

(see SendTrig  OSCresponder  NodeWatcher etc.)

( 
SynthDef("dustin",{
	var trig;
	trig = Dust.ar(2);
	Out.ar(0, trig);
	// SendTrig sends a /tr message to all registered clients
	SendTrig.ar(trig, 42, trig);
}).send(s);

// clap your hands !
SynthDef("detector",{
	var in, amp;
	in = AudioIn.ar(1);
	amp = Amplitude.kr(in, 0.01, 0.1) > 0.05;
	SendTrig.kr(amp, 42, amp);
}).send(s);
)

y = Synth("dustin");
a = Synth("detector");

s.addr

(
o = OSCresponder(s.addr,'/tr',{ arg time,responder,msg;
	msg.postln;
}).add;
)

o.remove;
y.free;
a.free;

// using NetAddr :

(
// a remote client:
n = NetAddr("200.0.0.7", 57120); // change the IP address!!,   57120 is sclang default port

// an OSC responder to this remote client:
r = OSCresponder(n, '/good/news', 
		{ arg time, resp, msg; 
		("received from" + n.ip + ":\n\t" ).post;
		[time, msg].postln 
		}).add;
)

OSCresponder.remove

m = NetAddr("200.0.0.7", 57120); // change the IP address!!,   57120 is sclang default port

// test it
m.sendMsg("/good/news", "you", "not you");
m.sendMsg("/good/news", 1, 1.3, 77);

m.sendBundle(0.2, ["/good/news", 1, 1.3, 77]);

// disconnect and remove the OSC responder:
r.remove;
n.disconnect;

// OSC - messages from sclang to a remote server :

z = Server("elsewhere", NetAddr("200.0.0.2", 57110));  //"130.149.50.213"
z.makeWindow;

// 57110 is the default port number of scsynth, \udp is the default protocol (see ServerOptions)
// 57120 is the default port number of sclang (SuperCollider application)

// localhost server is: 	NetAddr("127.0.0.1", 57110)
// sclang is: 			NetAddr("127.0.0.1", 57120)

z.boot;  // works only local, i.e. the server (scsynth) can't be booted from a remote client (sclang)!!
z.quit

z.boot

(
SynthDef("faraway", { arg gate=1, freq=400, amp=0.2;
	var sig, env;
	env = EnvGen.kr(Env.cutoff, gate, doneAction: 2);
	sig = Saw.ar([freq, freq*1.01] * LFSaw.kr(2).range(2, 1), amp * env);
	Out.ar(0, sig );
	}).send(s);	// send this to the remote server
)	

y = Synth("faraway", [\freq, 200], z);	// start the synth on the remote server
y.set(\freq, 500, \amp, 0.1);
y.free;

s.sendMsg("/n_set", 1003, \freq, -1);

s.queryAllNodes

// b = Buffer.read(z, "path");
y = Synth("faraway", [\freq, 200], s);
x = Synth.basicNew("faraway", s, 6328 )
x.free

// OSC - receiving messages from other OSC clients in sclang:
// (Max, pd, Csound, Reaktor, flash, Java u.v.a.m)

(
SynthDef("testmax", { arg gate=1, freq=400, amp=0.2;
	var sig, env;
	env = EnvGen.kr(Env.cutoff, gate, doneAction: 2);
	sig = Saw.ar([freq, freq*1.01], amp * env);
	Out.ar(0, sig );
	}, [0, 3, 0.1]).load(s);
)	

(
y = Synth.newPaused("testmax");

o = OSCresponder(nil, '/max', { arg time, resp, msg; 
		msg.postln; 
		if(msg[1] == 'start') 
			{ y.run(true) }
			{ if (msg[1] == 'stop') 
				{ y.run(false) }
				{ y.set(msg[1], msg[2]) };
			};	
	}).add;

)

// +++ Max-Patch start max_sc.pat and test

// when finished, you need to remove the OSCresponder:
o.remove;

// OSC - receiving messages from other OSC clients in scsynth:

// send these messages from a Max patch (NodeID = 1000) :
s.sendMsg("/s_new", "testosc", 1000, 0, 0, \freq, 200);
s.sendMsg("/n_set", 1000, \freq, 500, \amp, 0.1);
s.sendMsg("/n_free", 1000);

// OSC - messages from sclang to other apps (MaxMSP etc.):

~max = NetAddr("127.0.0.1", 7000);

~max = NetAddr("127.0.0.1", 49180);

~max.sendMsg("/zeugs", "/a", 0.5);
~max.sendMsg("/zeugs", "/b", -13);

(
Task({
	127.do({ arg i;
		~max.sendMsg("/dings", i);
		0.05.wait;
		})
	}).start;
)			

~max.sendMsg("/blabla", "good news! ");
~max.sendMsg("/blabla", "it works!!!");

~max.sendMsg("/clap");

// --------

(

// clap your hands !
SynthDef("detector",{
	var in, amp;
	
	in = AudioIn.ar(1);
	amp = Amplitude.kr(in, 0.01, 0.1, add: -0.05);
	SendTrig.kr(amp, 42, amp);
}).play(s);

// forward the trigger to Max
o = OSCresponder(s.addr,'/tr',{ arg time,responder,msg;
	msg.postln;
	~max.sendMsg("/clap");
}).add;
)

o.remove;

// OSC - messages from the server to other apps (Max etc.):

// an OSC client must register itself on the server be sending it the message /notify 1 
// after that it gets all the messages (/tr etc.) from the server

( 
SynthDef("dustin",{
	var trig;
	trig = Dust.ar(2);
	Out.ar(0, trig);
	// SendTrig sends a /tr message to all registered clients
	SendTrig.ar(trig, 42, trig);
}).send(s);
)

// Synth("dustin")

s.dumpOSC(1); // show me all arriving messages 
s.dumpOSC(0);

// send these commands from the other application (i.e. Max, pd etc.)
// notify on scsynth:
["/notify 1"]

// start a synth from the other app:
["/s_new", "dustin", 1000, 0, 0]

// the other app will receiver /tr messages like this:
["/tr", nodeID, tiggerID, triggerValue]

// send manually a /tr message to the addr ~max:
~max.sendMsg("/tr", 1000, 42, 0.3);

// unregister the other app:
["/notify 0"]