aboutsummaryrefslogtreecommitdiffstats
path: root/.config/SuperCollider/functions.scd
diff options
context:
space:
mode:
Diffstat (limited to '.config/SuperCollider/functions.scd')
-rw-r--r--.config/SuperCollider/functions.scd172
1 files changed, 172 insertions, 0 deletions
diff --git a/.config/SuperCollider/functions.scd b/.config/SuperCollider/functions.scd
new file mode 100644
index 0000000..3f27e31
--- /dev/null
+++ b/.config/SuperCollider/functions.scd
@@ -0,0 +1,172 @@
+postln('Loading custom functions.');
+
+/*
+ * JACK specific helper functions
+ * TODO: move to Quark
+ */
+// disconnect a port
+~jackDisconnectPort = {
+ arg source, sourceChannel, destination, destinationChannel;
+ ("jack_disconnect "++source++":"++sourceChannel++" "++destination++":"++destinationChannel).unixCmd({
+ arg exitCode;
+ if(exitCode != 0, {
+ postln("Disconnecting "++source++":"++sourceChannel++" from "++destination++":"++destinationChannel++" was unsuccessful!");
+ });
+ });
+};
+
+// connect a port
+~jackConnectPort = {
+ arg source, sourceChannel, destination, destinationChannel;
+ ("jack_connect "++source++":"++sourceChannel++" "++destination++":"++destinationChannel).unixCmd({
+ arg exitCode;
+ if(exitCode != 0, {
+ postln("Connecting "++source++":"++sourceChannel++" from "++destination++":"++destinationChannel++" was unsuccessful!");
+ });
+ });
+};
+
+// returns the amount of ports of a given client
+~jackClientPorts = {
+ arg clientName;
+ ("jack_lsp "++clientName++"| wc -l").unixCmdGetStdOut.asInt;
+};
+
+/*
+ * SuperCollider specific helper functions
+ *
+ */
+// adds one or more channels to Server.local.options.num{In,Out}putBusChannels
+// makes the tuple available in ~additionalChannels Dictionairy
+~addAdditionalChannels = {
+ arg type, name, channels;
+ if( (name.isKindOf(Symbol) && channels.isArray), {
+ switch (type,
+ \input, {
+ ~additionalChannels.at(\inputs).add(name -> channels);
+ postln("Added additional input channels for '"++name++"': "++channels.asString);
+ Server.local.options.numInputBusChannels = Server.local.options.numInputBusChannels + channels.size;
+ postln("Setting numInputBusChannels to "++Server.local.options.numInputBusChannels);
+ },
+ \output, {
+ ~additionalChannels.at(\outputs).add(name -> channels);
+ postln("Added additional output channels for '"++name++"': "++channels.asString);
+ Server.local.options.numOutputBusChannels = Server.local.options.numOutputBusChannels + channels.size;
+ postln("Setting numOutputBusChannels to "++Server.local.options.numOutputBusChannels);
+ },
+ { error("Expecting \input or \output as type, got "++type.asString);
+ });
+ },{
+ error('Expecting type Symbol for name and type Array for channels.');
+ });
+};
+
+/*
+ * SSR specific helper functions
+ * TODO: move to Quark
+ */
+
+// sets up the necessary OSC connection for an existing local or remote SSR
+// instance, subscribes to it and returns the NetAddr associated with it
+~ssrSetupOSC = {
+ arg host="localhost", port=50001;
+ var ssr;
+ // set ssr of the client instance
+ ssr = NetAddr(host, port);
+ // answer /poll messages with an /alive answer
+ OSCdef(
+ \pollreply,
+ {
+ arg msg, time, addr, recvPort;
+ ~ssr.sendMsg("/alive");
+ },
+ '/poll',
+ ssr
+ );
+ // subscribe to server with MessageLevel::SERVER
+ ssr.sendMsg("/subscribe", $T, 2);
+ ssr;
+};
+
+// clears the SSR scene, unsubscribes from the instance and removes alive
+// answers OSCdef
+~ssrDismantleOSC = {
+ arg ssr;
+ if (ssr.isKindOf(NetAddr), {
+ // remove all sources
+ ssr.sendMsg("/scene/clear");
+ // unsubscribe from server
+ ssr.sendMsg("/subscribe", $F);
+ // disable alive answers
+ OSCdef(\alive).disable;
+ });
+};
+
+// adds a source to an SSR instance
+~ssrAddSource = {
+ arg ssr, name, model = "point", port, x = 0.0, y = 0.0, orientation = 0.0,
+ gain = 0.0, movability = $F, orientationMovability = $F, mute = $F;
+ if (ssr.isKindOf(NetAddr), {
+ if (name.isString, {
+ if (model.isString, {
+ if (port.isString, {
+ ssr.sendMsg("/source/new", name, model, port, x, y, orientation,
+ gain, movability, orientationMovability, mute)
+ },{
+ error("The port argument is not of type String: "++port.class);
+ });
+ },{
+ error("The model argument is not of type String: "++model.class);
+ });
+ },{
+ error("The name argument is not of type String: "++name.class);
+ });
+ },{
+ error("The ssr argument is not of type NetAddr: "++ssr.class);
+ });
+};
+
+/*
+ * MIDI specific helper functions
+ * TODO: move to Quark
+ */
+
+// map inputs of a given MIDI device's control messages to the values on a
+// control Bus
+~midiControlToBus = {
+ arg key, msgNum, chan, uid, bus;
+ if(key.isKindOf(Symbol),{
+ if((msgNum.isArray),{
+ if (chan.isInteger, {
+ if (uid.isInteger, {
+ if (bus.isKindOf(Bus), {
+ MIDIdef.new(
+ key: key,
+ func: {
+ arg ...args;
+ bus.setAt(
+ msgNum.indexOf(args[1].asInteger),
+ args[0].asInteger.lincurve(0, 127, 0.0, 1.0, 4, nil)
+ );
+ },
+ msgNum: msgNum,
+ chan: chan,
+ msgType: \control,
+ srcID: uid
+ );
+ },{
+ error('Argument bus must be of type Bus: '++bus.class);
+ });
+ },{
+ error('Argument uid must be of type Integer: '++uid.class);
+ });
+ },{
+ error('Argument chan must be of type Integer: '++chan.class);
+ });
+ },{
+ error('Argument msgNum must be of type Array: '++msgNum.class);
+ });
+ },{
+ error('Argument key must be of type Symbol: '++key.class);
+ });
+};