1 //watches a server address for node-related messages
5 var <server, <responders;
9 ^super.new.ninit(server)
12 ninit { arg argServer;
17 server.addr.asArray.do({ arg addrItem; //support for multiple addresses
18 this.cmds.do({ arg cmd;
20 method = cmd.copyToEnd(1).asSymbol;
21 responders = responders.add(
22 OSCFunc({ arg msg; this.respond(method, msg) }, cmd, addrItem)
34 respond { arg method, msg;
35 this.performList(method, msg.drop(1))
40 responders.do({ arg item; item.enable });
46 responders.do({ arg item; item.free });
56 BasicNodeWatcher : AbstractNodeWatcher {
59 nodeIsPlaying { arg nodeID;
60 ^nodes.includes(nodeID);
62 nodeIsPlaying_ { arg nodeID;
63 //sometimes it is needed to set this before the server reply
68 nodes = IdentitySet.new;
71 cmds { ^#["/n_go", "/n_end"] }
84 ///////////////////////////////////
85 //watches registered nodes and sets their isPlaying/isRunning flag.
86 //a node needs to be registered to be addressed, other nodes are ignored.
88 NodeWatcher : BasicNodeWatcher {
93 all = IdentityDictionary.new;
97 *cmdPeriod { all.do { arg item; item.clear } }
99 *newFrom { arg server;
101 res = all.at(server.name);
103 res = this.new(server);
105 all.put(server.name, res)
110 *register { arg node, assumePlaying=false;
112 watcher = this.newFrom(node.server);
113 watcher.register(node, assumePlaying);
116 *unregister { arg node;
118 watcher = this.newFrom(node.server);
119 watcher.unregister(node);
122 cmds { ^#["/n_go", "/n_end", "/n_off", "/n_on"] }
123 respond { arg method, msg;
125 node = nodes.at(msg.at(1));
127 group = nodes.at(msg.at(2));
128 this.performList(method, node, group)
133 // we must copy 'nodes'
134 // b/c a /n_end dependant might add or remove nodes
135 // from the collection
136 // NEVER iterate over a collection that might change
137 nodes.copy.do({ arg node;
138 node.isPlaying = false;
139 node.isRunning = false;
140 node.changed(\n_end);
142 nodes = IdentityDictionary.new
145 register { arg node, assumePlaying=false;
146 if(server.serverRunning.not) { nodes.removeAll; ^this };
148 if(assumePlaying and: { nodes.at(node.nodeID).isNil }) { node.isPlaying = true };
149 nodes.put(node.nodeID, node);
153 unregister { arg node;
154 nodes.removeAt(node.nodeID);
158 //////////////private implementation//////////////
161 node.isPlaying = true;
162 node.isRunning = true;
163 node.changed(\n_go); // notify all the node's dependents of the change
167 this.unregister(node);
168 node.isPlaying = false;
169 node.isRunning = false;
170 node.changed(\n_end);
174 node.isRunning = false;
175 node.changed(\n_off);
179 node.isRunning = true;
186 DebugNodeWatcher : BasicNodeWatcher {
188 cmds { ^#["/n_go", "/n_end", "/n_off", "/n_on"] }
190 //////////////private implementation//////////////
192 doPost { arg action, nodeID, groupID, prevID, nextID;
193 Post << ("[ server: " + server.name + "]" +
194 action + nodeID + "in group" + groupID + "between nodes" + prevID + "and" + nextID
198 n_go { arg nodeID, groupID, prevID, nextID;
199 this.doPost("started", nodeID, groupID, prevID, nextID);
203 n_end { arg nodeID, groupID, prevID, nextID;
204 nodes.remove(nodeID);
205 this.doPost("ended", nodeID, groupID, prevID, nextID);
208 n_off { arg nodeID, groupID, prevID, nextID;
209 this.doPost("turned off", nodeID, groupID, prevID, nextID);
212 n_on { arg nodeID, groupID, prevID, nextID;
213 this.doPost("turned on", nodeID, prevID, nextID);