-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBufferFQueryQueueChannel.sc
114 lines (101 loc) · 4.13 KB
/
BufferFQueryQueueChannel.sc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Adapted method .readAndQuery from ddw quarks from James Harkins
// https://sc-users.bham.ac.narkive.com/yBE3WGch/buffer-readandquery
// Update towards OSCFunc
BufferFQueryQueueChannel {
// called by Buffer-readAndQuery to do the work
// if a file is being read and we're waiting for the b_info message from the server,
// the new file request goes into a queue to execute when the first is finished
classvar queue,
<isRunning = false, // true if file(s) are being read
<>timeToFail = 3.0;
*init { // also reset
queue = Array.new; // array elements will be args to Meta_Buffer-read2
isRunning = false;
}
*clear { this.init }
*add { arg ... args; // all args from read2
queue.isNil.if({ this.init });
queue = queue.add(args);
isRunning.not.if({ this.doQueue }); // isRunning==true means another file is in process
// so don't interrupt
}
*doQueue { // reads file and gets info on the first queue item
var server, path, startFrame, numFrames, channel, completionFunc, buffer, timeout, resp,
updater;
// get arguments
#server, path, startFrame, numFrames, channel, completionFunc, buffer, timeout = queue.at(0);
server.serverRunning.not.if({
"Server must be booted before buffers may be allocated.\nFailed: %"
.format(queue[0]).warn;
queue.removeAt(0); // drop first item from queue
(queue.size > 0).if({
this.doQueue // still an item left? go back for that one
// no need to clear this responder b/c it will be overwritten
}, {
isRunning = false; // so I can start again with the next .add call
});
^this // if server not booted, the next code block should be skipped
});
isRunning = true;
// place OSCResponder -- note that flow of control happens here
// resp = OSCpathResponder(server.addr, ['/b_info', buffer.bufnum], { arg t, r, m;
// resp = OSCpathResponder(server.addr, ['/b_info', buffer.bufnum], { arg t, r, m;
resp = OSCFunc({ |m, t| // |msg, time, addr, recvPort|
buffer.numFrames = m.at(2);
buffer.numChannels = m.at(3);
buffer.sampleRate = m.at(4);
" done".postln;
// must try here -- if completionFunc fails the queue gets stuck
try {
completionFunc.value(buffer);
} { |error|
error.reportError;
"Error occurred during buffer load completionFunc. Continuing with next file."
.warn;
};
queue.removeAt(0); // drop first item from queue
(queue.size > 0).if({
if(server.serverRunning) {
this.doQueue // still an item left? go back for that one
// no need to clear this responder b/c it will be overwritten
} {
updater = Updater(server, { |what|
if(what == \serverRunning and: { server.serverRunning }) {
updater.remove;
this.doQueue;
};
});
};
}, {
isRunning = false; // so I can start again with the next .add call
});
// }).add.removeWhenDone;
}, '/b_info', server.addr, argTemplate: [buffer.bufnum]).oneShot;
Post << "Loading " << path /*<< "[" << (startFrame ? 0) << ", " << (numFrames ? "")
<< "]..."*/;
// start the ball
// buffer.allocRead(path, startFrame, numFrames, ["/b_query", buffer.bufnum]);
buffer.allocReadChannel(path, startFrame, numFrames, channel, ["/b_query", buffer.bufnum]);
/*if (buffer.numChannels == 2, {
2.collect { |i| buffer.allocReadChannel(path, startFrame, numFrames, [i], ["/b_query", buffer.bufnum]) };
}, {
2.collect { |i| buffer.allocReadChannel(path, startFrame, numFrames, [0], ["/b_query", buffer.bufnum]) };
});*/
// check for failure -- if failure, continue with next file
SystemClock.schedAbs(Main.elapsedTime + (timeout ?? { timeToFail }), {
// this is a valid test b/c readAndQuery doesn't have a sampleRate arg
buffer.sampleRate.isNil.if({
format("Buffer-readAndQuery for % failed. Continuing with next.", path).warn;
resp.remove; // otherwise old responders remain and break later file loads
queue.removeAt(0);
(queue.size > 0).if({
this.doQueue // still an item left? go back for that one
// no need to clear this responder b/c it will be overwritten
}, {
isRunning = false; // so I can start again with the next .add call
});
});
nil
})
}
}