Skip to content

Instantly share code, notes, and snippets.

@iani
Last active December 31, 2015 16:19
Show Gist options
  • Select an option

  • Save iani/8013195 to your computer and use it in GitHub Desktop.

Select an option

Save iani/8013195 to your computer and use it in GitHub Desktop.
SuperCollider class: Watches the wav files in a chosen directory. If any files are added, they are read into buffers. If any files are removed, their buffers are freed. When any buffer is read or freed, a changed notification is issued. One can make any object do any action when receiving that notification by using the addNotifier method (see ex…
// IZ Dec 17, 2013 (11:31 PM)
/*
(Save this file as WatchSamplesInDir.sc and put it inside SuperCollider Extensions folder.
Then recompile. )
Watches the wav files in a chosen directory.
If any files are added, they are read into buffers.
If any files are removed, their buffers are freed.
When any buffer is read or freed, a changed notification is issued.
Here is how to add an action to do when receiving the notification:
//:
\anyObject.addNotifier(WatchSamplesInDir, \buffers, {
// As an example,
// play the first sample, when new samples are loaded:
{ WatchSamplesInDir.buffers.first.play; }.defer(1);
})
//:
*/
WatchSamplesInDir {
classvar default;
classvar <loadedPaths;
classvar <buffers;
classvar <>soundFileExtension = "aiff";
var <>path2watch;
var <loop;
var <>pollingRate = 5;
*start { this.default.start; }
*stop { this.default.stop; }
*default {
if (default.isNil) { default = this.new };
^default;
}
*initClass {
StartUp.add({ ServerBoot.add({ this.serverBooted }, Server.default) });
}
*new { | path2watch |
if (loadedPaths.isNil) {
loadedPaths = Set();
};
^super.new.init(path2watch);
}
*serverBooted {
var buf, bufnum, numFrames;
if (buffers.size > 0) {
buf = buffers.first;
bufnum = buf.bufnum;
numFrames = buf.numFrames;
buf.updateInfo({ | b |
{
postf("Server booted?????. Checking actual buffer here: \n %\n", b);
if (b.numFrames != numFrames) {
buffers = nil;
loadedPaths = Set();
"server booted, buffers emptied, checking to reload if running.".postln;
}{
"Buffer ok. Continuing without reload.".postln;
};
}.defer(0.5);
});
};
}
init { | argPath2Watch |
path2watch = argPath2Watch;
}
start {
if (path2watch.notNil) { ^this.startLoop };
path2watch = this.loadDefaultPath2Watch;
if (path2watch.notNil) { ^this.startLoop };
Dialog.openPanel({ | path |
path2watch = PathName(path).pathOnly +/+ "*." ++ soundFileExtension;
path2watch.writeArchive(this.defaultPathSavePath);
this.startLoop;
})
}
startLoop {
if (loop.notNil) { loop.stop };
loop = {
loop {
this.poll;
pollingRate.wait;
}
}.fork;
}
poll {
var paths2add, paths2remove, pathsNowInFolder, buffer;
pathsNowInFolder = Set() addAll: path2watch.pathMatch;
// paths now in folder which are not currently loaded:
paths2add = pathsNowInFolder difference: loadedPaths;
// paths currently loaded which are not any more in folder:
paths2remove = loadedPaths difference: pathsNowInFolder;
loadedPaths = pathsNowInFolder;
// first load new buffers
paths2add do: { | p |
postf("adding: %\n", p);
buffers = buffers add: Buffer.read(Server.default, p);
};
// then free the buffers
paths2remove do: { | p |
buffer = buffers detect: { | b | b.path == p };
if (buffer.notNil) {
postf("removing: %\n", p);
buffer.free;
buffers remove: buffer;
};
};
// if any buffers were loaded or removed, notify:
if (0 < (paths2add.size + paths2remove.size)) {
this.class.changed(\buffers, this);
}
}
loadDefaultPath2Watch {
var path;
path = this.defaultPathSavePath;
if (File.exists(path)) {
^path.load;
}{
^nil;
}
}
defaultPathSavePath {
^Platform.userAppSupportDir ++ "/WatchSamplesInDirPath.scd";
}
stop {
loop.stop;
loop = nil;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment