summaryrefslogtreecommitdiffstats
path: root/src/clients/supercollider/Om.sc
diff options
context:
space:
mode:
Diffstat (limited to 'src/clients/supercollider/Om.sc')
-rw-r--r--src/clients/supercollider/Om.sc746
1 files changed, 0 insertions, 746 deletions
diff --git a/src/clients/supercollider/Om.sc b/src/clients/supercollider/Om.sc
deleted file mode 100644
index cb366d58..00000000
--- a/src/clients/supercollider/Om.sc
+++ /dev/null
@@ -1,746 +0,0 @@
-// TODO:
-// * Keep track of established connections.
-Om : Model {
- classvar <>program = "om", <>patchLoader = "om_patch_loader";
- classvar <>oscURL, <nodeTypeMap, <>uiClass;
- var <addr;
- var <>loadIntoJack = true;
- var allocator, requestResponders, requestHandlers, notificationResponders;
- var creatingNode, newNodeEnd;
- var <registered = false, <booting = false;
- var <root;
- var <plugins, pluginParentEvent;
- var onNewPatch;
- *initClass {
- Class.initClassTree(Event);
- Class.initClassTree(NetAddr);
- Event.parentEvents.default[\omcmd] = \noteOn;
- Event.parentEvents.default[\omEventFunctions] = (
- noteOn: #{ arg midinote=60, amp=0.1;
- [midinote, asInteger((amp * 127).clip(0, 127)) ] },
- noteOff: #{ arg midinote=60; [ midinote ] },
- setPortValue: #{|portValue=0| [portValue] }
- );
- Event.parentEvents.default.eventTypes[\om]=#{|server|
- var freqs, lag, dur, sustain, strum, target, bndl, omcmd;
- freqs = ~freq = ~freq.value + ~detune;
- if (freqs.isKindOf(Symbol).not) {
- ~amp = ~amp.value;
- strum = ~strum;
- lag = ~lag + server.latency;
- sustain = ~sustain = ~sustain.value;
- omcmd = ~omcmd;
- target = ~target;
- ~midinote = ~midinote.value;
- ~portValue = ~portValue.value;
- bndl = ~omEventFunctions[omcmd].valueEnvir.asCollection;
- bndl = bndl.flop;
- bndl.do {|msgArgs, i|
- var latency;
- latency = i * strum + lag;
- if(latency == 0.0) {
- target.performList(omcmd, msgArgs)
- } {
- thisThread.clock.sched(latency, {
- target.performList(omcmd, msgArgs);
- })
- };
- if(omcmd === \noteOn) {
- thisThread.clock.sched(sustain + latency, {
- target.noteOff(msgArgs[0])
- })
- }
- }
- }
- };
- oscURL="osc.udp://"++NetAddr.localAddr.ip++$:++NetAddr.localAddr.port;
- nodeTypeMap = IdentityDictionary[
- \Internal -> OmInternalNode,
- \LADSPA -> OmLADSPANode,
- \DSSI -> OmDSSINode
- ];
- uiClass = OmEmacsUI
- }
- *new { | netaddr |
- ^super.new.init(netaddr)
- }
- gui { ^uiClass.new(this) }
- init { |netaddr|
- addr = netaddr ? NetAddr("127.0.0.1", 16180);
- onNewPatch = IdentityDictionary.new;
- allocator = StackNumberAllocator(0,1024);
- requestHandlers = IdentityDictionary.new;
- requestResponders = [
- "response/ok" -> {|id|
- requestHandlers.removeAt(id).value; allocator.free(id) },
- "response/error" -> {|id,text|
- requestHandlers.removeAt(id);
- allocator.free(id);
- ("Om"+text).error }
- ].collect({|a|
- var func = a.value;
- OSCresponder(addr, "/om/"++a.key, {|time,resp,msg|
- func.value(*msg[1..])
- })
- });
- notificationResponders = [
- "new_patch" -> {|path,poly|
- var func = onNewPatch.removeAt(path);
- if (func.notNil) {
- func.value(this.getPatch(path,false).prSetPoly(poly))
- }
- },
- "metadata/update" -> {|path,key,value|
- this.getObject(path).metadata.prSetMetadata(key, value) },
- "new_node" -> {|path,poly,type,lib,label|
- var patchPath, nodeName, patch, node;
- var lastSlash = path.asString.inject(nil,{|last,char,i|
- if(char==$/,i,last)
- });
- if (lastSlash.notNil) {
- patchPath = path.asString.copyFromStart(lastSlash-1);
- nodeName = path.asString.copyToEnd(lastSlash+1);
- patch = this.getPatch(patchPath);
- if (patch.notNil) {
- if (patch.hasNode(nodeName).not) {
- node = nodeTypeMap[type].new
- (nodeName, patch, poly, label, lib);
- creatingNode = node;
- patch.nodes[nodeName.asSymbol] = node;
- patch.changed(\newNode, node);
- } {
- if (patch.getNode(nodeName).class != nodeTypeMap[type]) {
- ("Om sent an existng node with differing type"+path).warn
- }
- }
- } {
- ("Om tried to create node in non-existing patch"+patchPath).warn
- }
- } {
- ("Invalid path in node creation"+path).warn
- }
- },
- "new_node_end" -> {
- newNodeEnd.value(creatingNode);
- newNodeEnd = nil;
- creatingNode = nil },
- "new_port" -> {|path,type,dir,hint,def,min,max|
- var basePath, portName, parent, port;
- var lastSlash = path.asString.inject(nil,{|last,char,i|
- if(char==$/,i,last)
- });
- if (lastSlash.notNil) {
- basePath = path.asString.copyFromStart(lastSlash-1);
- portName = path.asString.copyToEnd(lastSlash+1);
- parent = this.getNode(basePath) ? this.getPatch(basePath);
- if (parent.notNil) {
- if (parent.hasPort(portName).not) {
- port = OmPort.new(portName, parent, type, dir, hint, def, min, max);
- parent.ports[portName.asSymbol] = port;
- parent.changed(\newPort, port)
- } {
- if (parent.getPort(portName).porttype != type) {
- ("Om tried to create an already existing port with differing type"
- +path).warn
- }
- }
- } {
- ("Om tried to create port on non-existing object"+basePath).warn
- }
- } {
- ("Invalid path in port creation"+path).warn
- }
- },
- "control_change" -> {|path,value|
- this.getPort(path).prSetValue(value) },
- "patch_enabled" -> {|path| this.getPatch(path).prSetEnabled(true) },
- "patch_disabled" -> {|path| this.getPatch(path).prSetEnabled(false) },
- "plugin" -> {|lib,label,name,type|
- plugins.add(Event.new(4,nil,pluginParentEvent).putAll(
- (type:type, lib:lib, label:label, name:name))) },
- "node_removal" -> {|path|
- var node = this.getNode(path);
- if (node.notNil) {
- node.parent.nodes.removeAt(node.name.asSymbol).free
- } {
- ("Om attempting to remove non-existing node"+path).warn
- }
- },
- "port_removal" -> {|path|
- var port = this.getPort(path);
- if (port.notNil) {
- port.parent.ports.removeAt(port.name.asSymbol).free
- } {
- ("Om attempting to remove non-existing port"+path).warn
- }
- },
- "patch_destruction" -> {|path|
- var patch = this.getPatch(path);
- if (patch.notNil) {
- patch.parent.patches.removeAt(patch.name.asSymbol).free
- } {
- ("Om attempting to remove non-existing patch"+path).warn
- }
- },
- "program_add" -> {|path,bank,program,name|
- var node = this.getNode(path);
- if (node.respondsTo(\prProgramAdd)) {
- node.prProgramAdd(bank,program,name)
- } {
- ("Om tried to add program info to"+node).warn
- }
- }
- ].collect({|a|
- var func = a.value;
- OSCresponder(addr, "/om/"++a.key, {|time,resp,msg|
- func.value(*msg[1..])
- })
- });
- pluginParentEvent = Event.new(2,nil,nil).putAll((
- engine:this,
- new:{|self,path,poly=1,handler|self.engine.createNode(path?("/"++self.name),self.type,self.lib,self.label,poly,created:handler)}
- ));
- }
- *waitForBoot {|func| ^this.new.waitForBoot(func) }
- waitForBoot {|func|
- var r, id = 727;
- requestHandlers[id] = {
- r.stop;
- booting=false;
- this.changed(\running, true);
- func.value(this)
- };
- if (booting.not) {this.boot};
- r = Routine.run {
- 50.do {
- 0.1.wait;
- addr.sendMsg("/om/ping", id)
- };
- requestHandlers.removeAt(id);
- "Om engine boot failed".error;
- }
- }
- getPatch {|path, mustExist=true|
- var elements, currentPatch;
- if (path.class == Array) { elements = path
- } { elements = path.asString.split($/) };
- elements.do{|elem|
- if (elem=="") {
- currentPatch = root
- } {
- currentPatch = currentPatch.getPatch(elem,mustExist);
- if (currentPatch.isNil) { ^nil }
- }
- };
- ^currentPatch;
- }
- getNode {|path|
- var basePath, nodeName, patch;
- if (path.class == Array) { basePath = path
- } { basePath = path.asString.split($/) };
- nodeName = basePath.pop;
- patch = this.getPatch(basePath,true);
- if (patch.notNil) {
- ^patch.getNode(nodeName)
- };
- ^nil
- }
- getPort {|path|
- var basePath, portName, node, patch;
- basePath = path.asString.split($/);
- portName = basePath.pop;
- node = this.getNode(basePath.copy);
- if (node.notNil) { ^node.getPort(portName) };
- patch = this.getPatch(basePath,true);
- if (patch.notNil) { ^patch.getPort(portName) };
- ^nil
- }
- getObject {|path|
- var patch,node,port;
- patch = this.getPatch(path,true);
- if (patch.notNil) { ^patch };
- node = this.getNode(path);
- if (node.notNil) { ^node };
- port = this.getPort(path,true);
- if (port.notNil) { ^port };
- ^nil
- }
- at {|path|^this.getObject(path.asString)}
- *boot {|func|
- ^Om.new.waitForBoot {|e|
- e.activate {
- e.register {
- e.loadPlugins {
- e.requestPlugins {
- e.requestAllObjects {
- func.value(e)
- }
- }
- }
- }
- }
- }
- }
- boot {
- requestResponders.do({|resp| resp.add});
- booting = true;
- if (addr.addr == 2130706433) {
- if (loadIntoJack) {
- ("jack_load"+"-i"+addr.port+"Om"+"om").unixCmd
- } {
- (program+"-p"+addr.port).unixCmd
- }
- } {
- "You have to manually boot Om now".postln
- }
- }
- loadPatch {|patchPath| (patchLoader + patchPath).unixCmd }
- activate { | handler |
- this.sendReq("engine/activate", {
- root = OmPatch("",nil,this);
- this.changed(\newPatch, root);
- handler.value
- })
- }
- register { | handler |
- this.sendReq("engine/register_client", {
- registered=true;
- notificationResponders.do({|resp| resp.add});
- this.changed(\registered, registered);
- handler.value(this)
- })
- }
- unregister { | handler |
- this.sendReq("engine/unregister_client", {
- registered=false;
- notificationResponders.do({|resp| resp.remove});
- this.changed(\registered, registered);
- handler.value(this)
- })
- }
- registered_ {|flag|
- if (flag and: registered.not) {
- this.register
- } {
- if (flag.not and: registered) {
- this.unregister
- }
- }
- }
- loadPlugins { | handler | this.sendReq("engine/load_plugins", handler) }
- requestPlugins {|handler|
- var startTime = Main.elapsedTime;
- plugins = Set.new;
- this.sendReq("request/plugins", {
- ("Received info about"+plugins.size+"plugins in"+(Main.elapsedTime-startTime)+"seconds").postln;
- this.changed(\plugins, plugins);
- handler.value(this);
- })
- }
- requestAllObjects { |handler|
- this.sendReq("request/all_objects", handler)
- }
- createPatch { | path, poly=1, handler |
- onNewPatch[path.asSymbol] = handler;
- this.sendReq("synth/create_patch", nil, path.asString, poly.asInteger)
- }
- createNode { | path, type='LADSPA', lib, label, poly=1, created, handler |
- newNodeEnd = created;
- this.sendReq("synth/create_node",handler,path,type,lib,label,poly)
- }
- createAudioInput { | path, handler |
- this.createNode(path,"Internal","","audio_input",0,handler)
- }
- createAudioOutput {|path,handler|
- this.createNode(path,"Internal","","audio_output",0,handler)
- }
- createMIDIInput {|path,handler|
- this.createNode(path,"Internal","","midi_input",1,handler)
- }
- createMIDIOutput {|path,handler|
- this.createNode(path,"Internal","","midi_output",1,handler)
- }
- createNoteIn {|path| this.createNode(path,"Internal","","note_in") }
- connect {|fromPath,toPath,handler|
- this.sendReq("synth/connect",handler,fromPath.asString,toPath.asString)
- }
- disconnect { | fromPath, toPath, handler |
- this.sendReq("synth/disconnect",handler,fromPath.asString,toPath.asString)
- }
- disconnectAll { | path, handler |
- this.sendReq("synth/disconnect_all",handler,path);
- }
- sendReq { | path, handler...args |
- var id = allocator.alloc;
- requestHandlers[id] = handler;
- addr.sendMsg("/om/"++path, id, *args)
- }
- quit {
- if (loadIntoJack) {
- ("jack_unload"+"Om").unixCmd;
- booting=false;
- requestResponders.do(_.remove);
- notificationResponders.do(_.remove);
- this.changed(\running, false);
- } {
- this.sendReq("engine/quit", {
- booting=false;
- requestResponders.do(_.remove);
- notificationResponders.do(_.remove);
- this.changed(\running, false);
- })
- }
- }
- ping {| n=1, func |
- var id, result, start;
- id = allocator.alloc;
- result = 0;
- requestHandlers[id] = {
- var end;
- end = Main.elapsedTime;
- result=max((end-start).postln,result);
- n=n-1;
- if (n > 0) {
- start = Main.elapsedTime;
- addr.sendMsg("/om/ping", id)
- } {
- allocator.free(id);
- func.value(result)
- }
- };
- start = Main.elapsedTime;
- addr.sendMsg("/om/ping", id)
- }
- setPortValue {|path, val| this.getPort(path.asString).value=val }
- jackConnect {|path, jackPort|
- this.getPort(path).jackConnect(jackPort)
- }
- noteOn {|path, note, vel|
- var patch,node;
- patch = this.getPatch(path,true);
- if (patch.notNil) { patch.noteOn(note,vel) };
- node = this.getNode(path);
- if (node.notNil) { node.noteOn(note,vel) };
- }
- noteOff {|path, note|
- var patch,node;
- patch = this.getPatch(path,true);
- if (patch.notNil) { patch.noteOff(note) };
- node = this.getNode(path);
- if (node.notNil) { node.noteOff(note) };
- }
- matchPlugins{ | label, lib, name, type |
- ^plugins.select{ |p|
- label.matchItem(p.label) and: {
- lib.matchItem(p.lib) and: {
- name.matchItem(p.name) and: {
- type.matchItem(p.type)
- }
- }
- }
- }
- }
- dssiMsg {|path,reqType="program" ...args|
- addr.sendMsg("/dssi"++path++$/++reqType,*args)
- }
-}
-
-OmMetadata {
- var object, dict;
- *new {|obj|^super.new.metadataInit(obj)}
- metadataInit {|obj|
- dict=Dictionary.new;
- object=obj
- }
- put {|key,val|
- object.engine.sendReq("metadata/set", nil,
- object.path, key.asString, val.asString)
- }
- at {|key|^dict.at(key.asSymbol)}
- prSetMetadata {|key,val|
- dict.put(key,val);
- object.changed(\metadata, key, val)
- }
-}
-
-OmObject : Model {
- var <name, <parent, <metadata;
- *new {|name, parent|
- ^super.new.initOmObject(name,parent);
- }
- initOmObject {|argName, argParent|
- name = argName;
- parent = argParent;
- metadata=OmMetadata(this)
- }
- path { ^parent.notNil.if({ parent.path ++ $/ ++ name }, name).asString }
- depth { ^parent.notNil.if({ parent.depth + 1 }, 0) }
- engine { ^parent.engine }
-}
-
-OmPort : OmObject {
- var <porttype, <direction, <spec, <value, <connections;
- *new {|name,parent,type,dir,hint,def,min,max|
- ^super.new(name,parent).initPort(type,dir,hint,def,min,max)
- }
- initPort {|type,dir,hint,def,min,max|
- porttype = type;
- direction = dir;
- spec = ControlSpec(min, max,
- if (hint == 'LOGARITHMIC', 'exp', 'lin'),
- if (hint == 'INTEGER', 1, 0),
- def);
- connections = IdentityDictionary.new;
- }
- jackConnect {|jackPort|
- if (porttype.asSymbol != \AUDIO
- || direction.asSymbol!=\OUTPUT) {
- Error("Not a audio output port").throw
- };
- ("jack_connect" + "Om:"++(this.path) + jackPort).unixCmd
- }
- value_ {|val|
- if (porttype == \CONTROL and: {direction == \INPUT}) {
- this.engine.sendReq("synth/set_port_value", nil, this.path, val)
- } {
- Error("Not a input control port"+this.path).throw
- }
- }
- connectTo {|destPort|
- if (this.direction!=destPort.direction) {
- this.engine.connect(this,destPort)
- } {
- Error("Unable to connect ports with same direction").throw
- }
- }
-
- // Setters for OSC responders
- prSetValue {|argValue|
- if (value != argValue) {
- value = argValue;
- this.changed(\value, value)
- }
- }
-}
-
-OmNode : OmObject { // Abstract class
- var <ports, <polyphonic;
- *new {|name,parent,poly|
- ^super.new(name,parent).initNode(poly)
- }
- initNode {|argPoly|
- polyphonic = argPoly;
- ports = IdentityDictionary.new;
- }
- hasPort {|name| ^ports[name.asSymbol].notNil }
- getPort {|name| ^ports[name.asSymbol] }
- portArray {|type=\AUDIO,dir=\OUTPUT|
- var result = Array.new(8);
- ports.do {|port|
- if (port.porttype==type and: {port.direction==dir}) {
- result=result.add(port)
- }
- };
- ^result
- }
- audioOut {
- ^this.portArray(\AUDIO, \OUTPUT)
- }
- audioIn {
- ^this.portArray(\AUDIO, \INPUT)
- }
-}
-
-OmInternalNode : OmNode {
- var <pluginlabel;
- *new {|name,parent,poly,label|
- ^super.new(name,parent,poly).initInternalNode(label)
- }
- initInternalNode {|label|
- pluginlabel = label
- }
- noteOn { |note,vel|
- if (pluginlabel == \note_in or:
- {pluginlabel == \trigger_in and: {this.value == note}}) {
- this.engine.sendReq("synth/note_on", nil, this.path, note, vel)
- } {
- Error("Not a trigger_in or note_in node").throw
- }
- }
- noteOff {|note|
- if (pluginlabel == \note_in or:
- {pluginlabel == \trigger_in and: {this.value == note}}) {
- this.engine.sendReq("synth/note_off", nil, this.path, note)
- } {
- Error("Not a trigger_in or note_in node").throw
- }
- }
-}
-
-OmLADSPANode : OmNode {
- var <pluginlabel, <libname;
- *new {|name, parent, poly, label, lib|
- ^super.new(name,parent,poly).initLADSPANode(label,lib)
- }
- initLADSPANode {|label,lib|
- pluginlabel = label;
- libname = lib
- }
-}
-
-OmDSSINode : OmLADSPANode {
- var programs;
- *new {|name,parent,poly,label,lib|
- ^super.new(name,parent,poly,label,lib).initDSSI
- }
- initDSSI {
- programs = Set.new;
- }
- program {|bank, prog|
- this.engine.dssiMsg(this.path,"program",bank.asInteger,prog.asInteger)
- }
- prProgramAdd {|bank,program,name|
- var info = (bank:bank, program:program, name:name);
- if (programs.includes(info).not) {
- programs.add(info);
- this.changed(\programAdded, info)
- }
- }
-}
-
-OmPatch : OmNode {
- var <nodes, <patches, <poly, <enabled;
- var om;
- *new {|name,parent,engine|
- ^super.new(name,parent).initPatch(engine);
- }
- initPatch {|argEngine|
- nodes = IdentityDictionary.new;
- patches = IdentityDictionary.new;
- om = argEngine
- }
- hasNode {|name|
- ^nodes[name.asSymbol].notNil
- }
- getNode {|name|
- ^nodes[name.asSymbol]
- }
- hasPatch {|name|
- ^patches[name.asSymbol].notNil
- }
- getPatch {|name,mustExist=false|
- if (this.hasPatch(name).not) {
- if (mustExist) { ^nil };
- patches[name.asSymbol] = OmPatch(name,this);
- };
- ^patches[name.asSymbol]
- }
- engine {
- if (om.notNil) { ^om } { ^parent.engine };
- }
- connect {|fromPort, toPort|
- this.engine.connect(this.path++$/++fromPort, this.path++$/++toPort)
- }
- dumpX {
- (String.fill(this.depth,$ )++"*"+this.path).postln;
- nodes.do{|node|
- (String.fill(node.depth,$ )++"**"+node.path).postln;
- node.ports.do{|port|
- (String.fill(port.depth,$ )++"***"+port.path).postln };
- };
- ports.do{|port| (String.fill(port.depth,$ )++"***"+port.path).postln };
- patches.do(_.dump)
- }
- noteOn {|note,vel|
- var targetNode;
- this.nodes.do{|node|
- if (node.class == OmInternalNode) {
- node.pluginlabel.switch(
- \trigger_in, {
- if (node.ports['Note Number'].value == note) {
- targetNode = node;
- }
- },
- \note_in, {
- targetNode = node;
- }
- )
- }
- };
- if (targetNode.notNil) {
- targetNode.noteOn(note, vel)
- } {
- Error("Unable to find trigger_in for note "++note).throw
- }
- }
- noteOff {|note|
- var targetNode;
- this.nodes.do{|node|
- if (node.class == OmInternalNode) {
- node.pluginlabel.switch(
- \trigger_in, {
- if (node.ports['Note Number'].value == note) {
- targetNode = node;
- }
- },
- \note_in, {
- targetNode = node;
- }
- )
- }
- };
- if (targetNode.notNil) {
- targetNode.noteOff(note)
- } {
- Error("Unable to find node for note_off "++note).throw
- }
- }
- newPatch {|name, poly=1, handler|
- this.engine.createPatch(this.path++$/++name, poly, handler)
- }
- newNode {|name, poly=1, type, lib, label, fullname, handler|
- var candidates = this.engine.matchPlugins(label,lib,fullname,type);
- if (candidates.size == 1) {
- candidates.pop.new(this.path++"/"++name, poly, handler)
- } {
- if (candidates.size==0) {
- Error("Plugin not found").throw
- } {
- Error("Plugin info not unique").throw
- }
- }
- }
-
- // Setters for OSC responders
- prSetPoly {|argPoly| poly = argPoly }
- prSetEnabled {|flag|
- if (flag != enabled) {
- enabled = flag;
- this.changed(\enabled, flag)
- }
- }
-}
-
-
-OmEmacsUI {
- var engine, window, bootBtn;
- *new {|engine| ^super.newCopyArgs(engine).init }
- init {
- window = EmacsBuffer("*Om -"+engine.addr.ip++$:++engine.addr.port);
- bootBtn = EmacsButton(window, ["Boot","Quit"], {|value|
- if (value==1) {
- engine.boot
- } {
- engine.quit
- }
- }).value=engine.registered.binaryValue;
- engine.addDependant(this);
- window.front;
- }
- update {|who, what ... args|
- Emacs.message(who.asString+what+args);
- if (what == \newPatch or: {what == \newNode or: {what == \newPort}}) {
- args[0].addDependant(this)
- };
- }
-}