scide: LookupDialog - redo lookup on classes after partial lookup
[supercollider.git] / SCClassLibrary / Common / Control / asScore / ScoreStreamPlayer.sc
blobffc62109c7f27f6ad69dc03969eea8befdf4e7ea
1 /*
2  ScoreStreamPlayer collects OSC commands from an EventStream into a Score. It is derived from server to provide allocation of nodeIDs, bufums, etc.
4   It implements the functionality of a TempoClock, to support tempo changes and time based patterns.
6  Patterns that play on multiple servers are not directly supported, but can be managed.
7  For example, assuming the server is explicitly identified in the pattern:
9  arrayOfScores = arrayOfServers.collect { | server |
10                 Pchain(
11                         Pbind(\freq,
12                                 Pfunc({| ev |
13                                         if (ev[\server] == server)
14                                                 { ev[\freq] }
15                                                 { \rest}
16                                 })
17                         ),
18                         pattern
19                 ).asScore
20  }
23 ScoreStreamPlayer : Server {
24         var <>beats, <>tempo;
25         var <>bundleList, <>maxTime;
27         *new { ^super.new("record").initScoreStreamPlayer }
29         initScoreStreamPlayer {
30                 this.latency_(0);
31                 Server.set.remove(this); // we do not want to be part of the server list
32                 ^this
33         }
35         beats2secs { | beats | ^beats }
36         secs2beats { | beats | ^beats }
38         add { | beats, args|
39                 bundleList = bundleList.add([beats min: maxTime] ++ args)
40         }
42         prepareEvent { | event |
43                 event = event.copy;
44                 event.use({
45                         ~schedBundle = { | lag, offset, server ...bundle |
46                                 this.add(offset * tempo + lag + beats, bundle)
47                         };
48                         ~schedBundleArray = { | lag, offset, server, bundle |
49                                 this.add(offset * tempo + lag + beats, bundle)
50                         };
51                 });
52                 ^event;
53         }
55         makeScore { | stream, duration = 1, event, timeOffset = 0|
56                 var ev, startTime, proto;
57                 proto = (
58                         server: this,
60                         schedBundle: { | lag, offset, server ...bundle |
61                                 this.add(offset * tempo + lag + beats, bundle)
62                         },
63                         schedBundleArray: { | lag, offset, server, bundle |
64                                 this.add(offset * tempo + lag + beats, bundle)
65                         }
66                 );
68                 event = event ? Event.default;
69                 event = event.copy.putAll(proto);
70                 beats = timeOffset;
71                 tempo = 1;
72                 bundleList = [];
73                 maxTime = timeOffset + duration;
74                 Routine {
75                         thisThread.clock = this;
76                         while ({
77                                 thisThread.beats = beats;
78                                 ev = stream.next(event.copy);
79                                 (maxTime >= beats) && ev.notNil
80                         },{
81                                 ev.putAll(proto);
82                                 ev.play;
83                                 beats = ev.delta * tempo + beats
84                         })
85                 }.next;
86                 bundleList = bundleList.sort({ | a, b | b[0] >= a[0] });
87                 if ((startTime = bundleList[0][0]) < 0 ) {
88                         timeOffset = timeOffset - startTime;
89                 };
90 //              bundleList.do { | b | b[0] = b[0] + timeOffset }
92                 ^Score(bundleList.add([duration+timeOffset, [\c_set, 0, 0]]) );
93         }