2 var <>score, routine, isPlaying = false;
3 classvar <>program, <>options;
6 program = Platform.case(\windows, {".\\scsynth.exe"}, {"./scsynth"});
7 options = ServerOptions.new;
11 ^super.new.init(list);
14 *newFromFile { arg path;
16 list = thisProcess.interpreter.executeFile(path);
17 ^super.new.init(list);
21 score = [[0.0, ["/g_new", 1]]] ++ list;
26 score = score.add(bundle)
29 *playFromFile { arg path, server;
31 list = thisProcess.interpreter.executeFile(path);
32 ^this.new(list).play(server);
35 *play { arg list, server;
36 ^this.new(list).play(server);
39 score = score.sort({ arg a, b; b[0] >= a[0] });
41 play { arg server, clock, quant=0.0;
42 var size, osccmd, timekeep, inserver, rout;
44 inserver = server ? Server.default;
51 deltatime = osccmd[0];
52 msg = osccmd.copyToEnd(1);
53 (deltatime-timekeep).wait;
54 inserver.listSendBundle(inserver.latency, msg);
60 routine.play(clock, quant);
61 }, {"Score already playing".warn;}
65 endTime { ^score.last[0] }
66 startTime { ^score.first[0] }
68 section { arg start = 0, end, configevents;
70 if(end.isNil) { end = this.endTime };
71 sectionlist = Array.new;
73 if(item[0].inclusivelyBetween(start, end)) {
75 item[0] = item[0] - start;
76 sectionlist = sectionlist.add(item);
79 sectionlist = sectionlist.add([end - start, [0]]); // add dummy command (cmd_none)
80 if(configevents.notNil,
81 {if(configevents.isArray,
82 {if(configevents[0] == 0.0,
83 {sectionlist = sectionlist.addFirst(configevents)},
84 {"Configuration events should have a timestamp of 0.0".warn; ^nil})},
85 {"Configuration events need to be a bundle array: [time, [events]]".warn;
87 ^this.class.new(sectionlist);
90 writeOSCFile { arg path, from, to, clock;
91 if(to.notNil or: {from.notNil}) {
93 to = to ? this.endTime;
94 this.section(from, to).write(path, clock)
96 this.write(path, clock)
100 recordNRT { arg oscFilePath, outputFilePath, inputFilePath, sampleRate = 44100, headerFormat =
101 "AIFF", sampleFormat = "int16", options, completionString="", duration = nil, action = nil;
102 this.writeOSCFile(oscFilePath, 0, duration);
103 unixCmd(program + " -N" + oscFilePath.quote
104 + if(inputFilePath.notNil, { inputFilePath.quote }, { "_" })
105 + outputFilePath.quote
106 + sampleRate + headerFormat + sampleFormat +
107 (options ? Score.options).asOptionsString
108 + completionString, action);
111 *recordNRT { arg list, oscFilePath, outputFilePath, inputFilePath, sampleRate = 44100,
112 headerFormat = "AIFF", sampleFormat = "int16", options, completionString="", duration = nil, action = nil;
113 this.new(list).recordNRT(oscFilePath, outputFilePath, inputFilePath, sampleRate,
114 headerFormat, sampleFormat, options, completionString, duration, action);
119 isPlaying.if({routine.stop; isPlaying = false; routine = nil;}, {"Score not playing".warn;}
123 *writeFromFile { arg path, oscFilePath, clock;
125 list = thisProcess.interpreter.executeFile(path);
126 this.write(list, oscFilePath, clock);
129 *write { arg list, oscFilePath, clock;
130 var osccmd, f, tempoFactor;
131 f = File(oscFilePath, "w");
132 tempoFactor = (clock ? TempoClock.default).tempo.reciprocal;
135 var msg = list[i].copy;
136 msg[0] = msg[0]* tempoFactor;
137 osccmd = msg.asRawOSC;
138 f.write(osccmd.size).write(osccmd);
146 write { arg oscFilePath, clock;
147 this.class.write(score, oscFilePath, clock);
150 saveToFile { arg path;
152 f = File.new(path, "w");
153 f.putString("[ // SuperCollider Score output " ++ Date.getDate ++ "\n");
155 f.putString((me).asCompileString ++ ",\n");