FluidProxyUgen : UGen { var <>pluginname; *kr { |pluginname...args| ^this.new1('control', pluginname,*args) } init { |pluginname...args| this.pluginname = pluginname; inputs = args++Done.none++0; rate = inputs.rate; } name{ ^pluginname.asString; } } FluidManipulationClient { classvar clock; var ugen; var id; var defName, def; var onSynthFree, keepAlive; var aliveThread; var postit; *initClass { clock = TempoClock.new; clock.permanent = true; } *prServerString{ |s| var ascii = s.ascii; ^[ascii.size].addAll(ascii) } *newFromDesc { arg rate, numOutputs, inputs, specialIndex; ^FluidProxyUgen.newFromDesc(rate, numOutputs, inputs, specialIndex) } *new{ |server...args| server = server ? Server.default; if(server.serverRunning.not,{ (this.asString + "– server not running").error; ^nil }); ^super.newCopyArgs(server ?? {Server.default}).baseinit(*args) } makeDef { |defName...args| ^SynthDef(defName,{ var ugen = FluidProxyUgen.kr(this.class.name, *args); this.ugen = ugen; ugen }); } updateSynthControls {} baseinit { |...args| var makeFirstSynth,synthMsg; id = UniqueID.next; postit = {|x| x.postln;}; keepAlive = true; defName = (this.class.name.asString ++ id).asSymbol; def = this.makeDef(defName,*args); synth = Synth.basicNew(def.name, server); synthMsg = synth.newMsg(RootNode(server)); def.doSend(server,synthMsg); onSynthFree = { synth = nil; if(keepAlive){ synth = Synth(defName,target: RootNode(server)); synth.onFree{clock.sched(0,onSynthFree)}; this.updateSynthControls; } }; CmdPeriod.add({synth = nil}); synth.onFree{clock.sched(0,onSynthFree)}; this.updateSynthControls; } free{ keepAlive = false; if(server.serverRunning){server.sendMsg("/cmd","free"++this.class.name,id)}; synth.tryPerform(\free); ^nil } cols {|action| action ?? {action = postit}; this.prSendMsg(\cols,[],action,[numbers(FluidMessageResponse,_,1,_)]); } read{|filename, action| this.prSendMsg(\read,[filename.asString],action); } write{|filename, action| this.prSendMsg(\write,[filename.asString],action); } size {|action| action ?? {action = postit}; this.prSendMsg(\size,[],action,[numbers(FluidMessageResponse,_,1,_)]); } prSendMsg { |msg, args, action,parser| if(this.server.serverRunning.not,{(this.asString + "– server not running").error; ^nil}); forkIfNeeded{ synth ?? {onSynthFree.value; server.sync}; OSCFunc( { |msg| defer{ var result; result = FluidMessageResponse.collectArgs(parser,msg.drop(3)); if(action.notNil){action.value(result)}{action.value}; } },'/'++msg, server.addr, nil,[synth.nodeID]).oneShot; server.listSendMsg(['/u_cmd', synth.nodeID, ugen.synthIndex, msg].addAll(args)); } } } FluidDataClient : FluidManipulationClient { var