HelpBrowser: path box becomes a more conventional search box
[supercollider.git] / SCClassLibrary / Common / Control / NodeWatcher.sc
blobb735368f0d2770ad80b24be6c4cd5aac7ad68c1b
1 //watches a server address for node-related messages
3 AbstractNodeWatcher {
5         var <server, <responders;
6         var <isWatching=false;
8         *new { arg server;
9                 ^super.new.ninit(server)
10         }
12         ninit { arg argServer;
13                 var cmds;
14                 server = argServer;
15                 this.clear;
16                 responders = [];
17                 server.addr.asArray.do({ arg addrItem; //support for multiple addresses
18                         this.cmds.do({ arg cmd;
19                                 var method;
20                                 method = cmd.copyToEnd(1).asSymbol;
21                                 responders = responders.add(
22                                         OSCFunc({ arg msg; this.respond(method, msg) }, cmd, addrItem).disable
23                                 )
24                         });
25                 });
26         }
28         clear {}
30         cmds { ^nil }
32         respond { arg method, msg;
33                 this.performList(method, msg.drop(1))
34         }
36         start {
37                 if(isWatching.not, {
38                         responders.do({ arg item; item.enable });
39                         isWatching = true;
40                 })
41         }
42         stop {
43                 if(isWatching, {
44                         responders.do({ arg item; item.free });
45                         isWatching = false;
46                         this.free;
47                 })
48         }
54 BasicNodeWatcher : AbstractNodeWatcher {
55         var <nodes;
57         nodeIsPlaying { arg nodeID;
58                 ^nodes.includes(nodeID);
59         }
60         nodeIsPlaying_ { arg nodeID;
61                 //sometimes it is needed to set this before the server reply
62                 ^nodes.add(nodeID);
63         }
65         clear {
66                 nodes = IdentitySet.new;
67         }
69         cmds {  ^#["/n_go", "/n_end"] }
71         n_end { arg nodeID;
72                 nodes.remove(nodeID);
73         }
74         n_go { arg nodeID;
75                 nodes.add(nodeID);
76         }
82 ///////////////////////////////////
83 //watches registered nodes and sets their isPlaying/isRunning flag.
84 //a node needs to be  registered to be addressed, other nodes are ignored.
86 NodeWatcher : BasicNodeWatcher {
88         classvar <>all;
90         *initClass {
91                 all = IdentityDictionary.new;
92                 CmdPeriod.add(this);
93         }
95         *cmdPeriod { all.do { arg item; item.clear } }
97         *newFrom { arg server;
98                 var res;
99                 res = all.at(server.name);
100                 if(res.isNil, {
101                         res = this.new(server);
102                         res.start;
103                         all.put(server.name, res)
104                 });
105                 ^res
106         }
108         *register { arg node, assumePlaying=false;
109                 var watcher;
110                 watcher = this.newFrom(node.server);
111                 watcher.register(node, assumePlaying);
112         }
114         *unregister { arg node;
115                 var watcher;
116                 watcher = this.newFrom(node.server);
117                 watcher.unregister(node);
118         }
120         cmds { ^#["/n_go", "/n_end", "/n_off", "/n_on"] }
121         respond { arg method, msg;
122                 var node, group;
123                 node = nodes.at(msg.at(1));
124                 if(node.notNil, {
125                                 group = nodes.at(msg.at(2));
126                                 this.performList(method, node, group)
127                 })
128         }
130         clear {
131                 nodes.do({ arg node;
132                         node.isPlaying = false;
133                         node.isRunning = false;
134                         node.changed(\n_end);
135                 });
136                 nodes = IdentityDictionary.new
137         }
139         register { arg node, assumePlaying=false;
140                 if(server.serverRunning.not) { nodes.removeAll; ^this };
141                 if(isWatching) {
142                         if(assumePlaying and: { nodes.at(node.nodeID).isNil }) { node.isPlaying = true };
143                         nodes.put(node.nodeID, node);
144                 };
145         }
147         unregister { arg node;
148                 nodes.removeAt(node.nodeID);
149         }
152         //////////////private implementation//////////////
154         n_go { arg node;
155                 node.isPlaying = true;
156                 node.isRunning = true;
157                 node.changed(\n_go);  // notify all the node's dependents of the change
158         }
160         n_end { arg node;
161                 this.unregister(node);
162                 node.isPlaying = false;
163                 node.isRunning = false;
164                 node.changed(\n_end);
165         }
167         n_off { arg node;
168                 node.isRunning = false;
169                 node.changed(\n_off);
170         }
172         n_on { arg node;
173                 node.isRunning = true;
174                 node.changed(\n_on);
175         }
180 DebugNodeWatcher : BasicNodeWatcher {
182         cmds { ^#["/n_go", "/n_end", "/n_off", "/n_on"] }
184         //////////////private implementation//////////////
186         doPost { arg action, nodeID, groupID, prevID, nextID;
187                 Post << ("[ server: " + server.name + "]" +
188                 action + nodeID + "in group" + groupID + "between nodes" + prevID + "and" + nextID
189                 ) << Char.nl
190         }
192         n_go { arg nodeID, groupID, prevID, nextID;
193                 this.doPost("started", nodeID, groupID, prevID, nextID);
194                 nodes.add(nodeID);
195         }
197         n_end { arg nodeID, groupID, prevID, nextID;
198                 nodes.remove(nodeID);
199                 this.doPost("ended", nodeID, groupID, prevID, nextID);
200         }
202         n_off { arg nodeID, groupID, prevID, nextID;
203                 this.doPost("turned off", nodeID, groupID, prevID, nextID);
204         }
206         n_on { arg nodeID, groupID, prevID, nextID;
207                 this.doPost("turned on", nodeID, prevID, nextID);
208         }