|
@@ -1,4 +1,4 @@
|
|
|
-// Module 5: OSC Communication Setup - MODIFIED FOR IDRAW OSC
|
|
|
|
|
|
|
+// Module 5: OSC Communication Setup - FIXED FOR MEMORY MANAGEMENT
|
|
|
// Save as "5_osc_communication.scd"
|
|
// Save as "5_osc_communication.scd"
|
|
|
|
|
|
|
|
(
|
|
(
|
|
@@ -10,6 +10,10 @@ OSCdef.freeAll;
|
|
|
~currentColor = (r: 0.0, g: 0.0, b: 1.0); // Default blue
|
|
~currentColor = (r: 0.0, g: 0.0, b: 1.0); // Default blue
|
|
|
~currentPadValues = (x: 0.0, y: 0.0, pressure: 1.0); //Default pad values
|
|
~currentPadValues = (x: 0.0, y: 0.0, pressure: 1.0); //Default pad values
|
|
|
|
|
|
|
|
|
|
+// Track active synths to prevent memory leaks
|
|
|
|
|
+~activeSynths = IdentityDictionary.new;
|
|
|
|
|
+~synthCounter = 0;
|
|
|
|
|
+
|
|
|
~synthParams = (
|
|
~synthParams = (
|
|
|
out: 0,
|
|
out: 0,
|
|
|
freq: 440,
|
|
freq: 440,
|
|
@@ -28,7 +32,86 @@ OSCdef.freeAll;
|
|
|
blueAmt: 0.5
|
|
blueAmt: 0.5
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
-// Define OSC responder for iDraw touch data
|
|
|
|
|
|
|
+// Function to clean up old synths
|
|
|
|
|
+~cleanupSynths = {
|
|
|
|
|
+ ~activeSynths.keysValuesDo({ |key, synth|
|
|
|
|
|
+ if(synth.isPlaying.not, {
|
|
|
|
|
+ ~activeSynths.removeAt(key);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // If too many synths are active, force cleanup of oldest ones
|
|
|
|
|
+ if(~activeSynths.size > 10, {
|
|
|
|
|
+ var oldestKeys = ~activeSynths.keys.asArray.sort.copyRange(0, ~activeSynths.size - 6);
|
|
|
|
|
+ oldestKeys.do({ |key|
|
|
|
|
|
+ if(~activeSynths[key].notNil, {
|
|
|
|
|
+ ~activeSynths[key].set(\gate, 0);
|
|
|
|
|
+ ~activeSynths.removeAt(key);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// Function to create a new synth safely
|
|
|
|
|
+~createSafeSynth = { |synthType = \rgbSynth, args|
|
|
|
|
|
+ var synth, synthId;
|
|
|
|
|
+
|
|
|
|
|
+ // Clean up old synths first
|
|
|
|
|
+ ~cleanupSynths.value;
|
|
|
|
|
+
|
|
|
|
|
+ // Create new synth
|
|
|
|
|
+ synthId = ~synthCounter;
|
|
|
|
|
+ ~synthCounter = ~synthCounter + 1;
|
|
|
|
|
+
|
|
|
|
|
+ // Add default parameters if not provided
|
|
|
|
|
+ args = args ++ [
|
|
|
|
|
+ \ampAttack, ~synthParams.ampAttack,
|
|
|
|
|
+ \ampRelease, ~synthParams.ampRelease,
|
|
|
|
|
+ \filterAttack, ~synthParams.filterAttack,
|
|
|
|
|
+ \filterRelease, ~synthParams.filterRelease,
|
|
|
|
|
+ \pitchAttack, ~synthParams.pitchAttack,
|
|
|
|
|
+ \pitchRelease, ~synthParams.pitchRelease,
|
|
|
|
|
+ \redAmt, ~synthParams.redAmt,
|
|
|
|
|
+ \greenAmt, ~synthParams.greenAmt,
|
|
|
|
|
+ \blueAmt, ~synthParams.blueAmt
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ synth = Synth(synthType, args);
|
|
|
|
|
+ ~activeSynths[synthId] = synth;
|
|
|
|
|
+
|
|
|
|
|
+ // Schedule automatic cleanup
|
|
|
|
|
+ SystemClock.sched(~synthParams.ampAttack + ~synthParams.ampRelease + 1, {
|
|
|
|
|
+ if(~activeSynths[synthId].notNil, {
|
|
|
|
|
+ ~activeSynths[synthId].set(\gate, 0);
|
|
|
|
|
+ ~activeSynths.removeAt(synthId);
|
|
|
|
|
+ });
|
|
|
|
|
+ nil; // Don't reschedule
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ synth;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// Define OSC responder for creating sounds (only for envelope-controlling pens)
|
|
|
|
|
+~triggerSound = {
|
|
|
|
|
+ var x = ~currentPadValues.x;
|
|
|
|
|
+ var y = ~currentPadValues.y;
|
|
|
|
|
+ var pressure = ~currentPadValues.pressure;
|
|
|
|
|
+ var freq = x.linexp(-0.5, 0.5, 100, 2000);
|
|
|
|
|
+ var amp = pressure.linlin(1, 8, 0.1, 0.8);
|
|
|
|
|
+
|
|
|
|
|
+ // Only create sounds for envelope-controlling pen types
|
|
|
|
|
+ if([\pen, \monoline, \marker].includes(~currentPenType.asSymbol), {
|
|
|
|
|
+ ~createSafeSynth.value(\rgbSynth, [
|
|
|
|
|
+ \out, ~sourceBus ? 0,
|
|
|
|
|
+ \freq, freq,
|
|
|
|
|
+ \amp, amp
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ ["Sound triggered:", ~currentPenType, freq, amp].postln;
|
|
|
|
|
+ });
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// Function to update effect parameters safely
|
|
|
~changeEffectParams = {
|
|
~changeEffectParams = {
|
|
|
var x = ~currentPadValues.x;
|
|
var x = ~currentPadValues.x;
|
|
|
var y = ~currentPadValues.y;
|
|
var y = ~currentPadValues.y;
|
|
@@ -38,9 +121,9 @@ OSCdef.freeAll;
|
|
|
["Touch data:", x, y, pressure, ~currentPenType, ~currentColor].postln;
|
|
["Touch data:", x, y, pressure, ~currentPenType, ~currentColor].postln;
|
|
|
|
|
|
|
|
// Handle touch based on current pen type
|
|
// Handle touch based on current pen type
|
|
|
- switch(~currentPenType,
|
|
|
|
|
|
|
+ switch(~currentPenType.asSymbol,
|
|
|
// Pen - Controls amplitude envelope
|
|
// Pen - Controls amplitude envelope
|
|
|
- "/pen", {
|
|
|
|
|
|
|
+ \pen, {
|
|
|
var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
|
var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
|
|
|
|
|
@@ -51,7 +134,7 @@ OSCdef.freeAll;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Monoline - Controls filter envelope
|
|
// Monoline - Controls filter envelope
|
|
|
- "/monoline", {
|
|
|
|
|
|
|
+ \monoline, {
|
|
|
var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
|
var filterRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
var filterRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
|
|
|
|
|
@@ -62,7 +145,7 @@ OSCdef.freeAll;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Marker - Controls pitch envelope
|
|
// Marker - Controls pitch envelope
|
|
|
- "/marker", {
|
|
|
|
|
|
|
+ \marker, {
|
|
|
var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
|
var pitchRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
var pitchRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
|
|
|
|
|
@@ -73,65 +156,78 @@ OSCdef.freeAll;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Pencil - Effect preset 1
|
|
// Pencil - Effect preset 1
|
|
|
- "/pencil", {
|
|
|
|
|
- // Apply Preset 1 effects
|
|
|
|
|
- ~filterSynth.set(
|
|
|
|
|
- \cutoff, x.linexp(-0.5, 0.5, 20, 18000),
|
|
|
|
|
- \res, y.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- ~lfoSynth.set(
|
|
|
|
|
- \freq, x.linlin(-0.5, 0.5, 0, 15),
|
|
|
|
|
- \intensity, pressure.linlin(1, 8, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- ~reverbSynth.set(
|
|
|
|
|
- \roomsize, y.linlin(-0.5, 0.5, 0.1, 0.9)
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ \pencil, {
|
|
|
|
|
+ // Apply Preset 1 effects - with safety checks
|
|
|
|
|
+ if(~filterSynth.notNil and: { ~filterSynth.isPlaying }, {
|
|
|
|
|
+ ~filterSynth.set(
|
|
|
|
|
+ \cutoff, x.linexp(-0.5, 0.5, 20, 18000),
|
|
|
|
|
+ \res, y.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if(~lfoSynth.notNil and: { ~lfoSynth.isPlaying }, {
|
|
|
|
|
+ ~lfoSynth.set(
|
|
|
|
|
+ \freq, x.linlin(-0.5, 0.5, 0, 15),
|
|
|
|
|
+ \intensity, pressure.linlin(1, 8, 0, 1)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if(~reverbSynth.notNil and: { ~reverbSynth.isPlaying }, {
|
|
|
|
|
+ ~reverbSynth.set(
|
|
|
|
|
+ \room, y.linlin(-0.5, 0.5, 0.1, 0.9)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
["Pencil preset:", "Cutoff", x.linexp(-0.5, 0.5, 20, 18000), "LFO", x.linlin(-0.5, 0.5, 0, 15)].postln;
|
|
["Pencil preset:", "Cutoff", x.linexp(-0.5, 0.5, 20, 18000), "LFO", x.linlin(-0.5, 0.5, 0, 15)].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Crayon - Effect preset 2
|
|
// Crayon - Effect preset 2
|
|
|
- "/crayon", {
|
|
|
|
|
- // Apply Preset 2 effects
|
|
|
|
|
- ~lfoSynth.set(
|
|
|
|
|
- \freq, x.linlin(-0.5, 0.5, 15, 1),
|
|
|
|
|
- \intensity, x.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- ~delaySynth.set(
|
|
|
|
|
- \delaytime, x.linlin(-0.5, 0.5, 0.01, 1.0)
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- ~filterSynth.set(
|
|
|
|
|
- \cutoff, y.linexp(-0.5, 0.5, 20, 18000),
|
|
|
|
|
- \res, pressure.linlin(1, 5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- ~reverbSynth.set(
|
|
|
|
|
- \mix, y.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ \crayon, {
|
|
|
|
|
+ // Apply Preset 2 effects - with safety checks
|
|
|
|
|
+ if(~lfoSynth.notNil and: { ~lfoSynth.isPlaying }, {
|
|
|
|
|
+ ~lfoSynth.set(
|
|
|
|
|
+ \freq, x.linlin(-0.5, 0.5, 15, 1),
|
|
|
|
|
+ \intensity, x.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if(~delaySynth.notNil and: { ~delaySynth.isPlaying }, {
|
|
|
|
|
+ ~delaySynth.set(
|
|
|
|
|
+ \delaytime, x.linlin(-0.5, 0.5, 0.01, 1.0)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if(~filterSynth.notNil and: { ~filterSynth.isPlaying }, {
|
|
|
|
|
+ ~filterSynth.set(
|
|
|
|
|
+ \cutoff, y.linexp(-0.5, 0.5, 20, 18000),
|
|
|
|
|
+ \res, pressure.linlin(1, 5, 0, 1)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if(~reverbSynth.notNil and: { ~reverbSynth.isPlaying }, {
|
|
|
|
|
+ ~reverbSynth.set(
|
|
|
|
|
+ \mix, y.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
+ );
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
["Crayon preset:", "LFO", x.linlin(-0.5, 0.5, 15, 1), "Filter", y.linexp(-0.5, 0.5, 20, 18000)].postln;
|
|
["Crayon preset:", "LFO", x.linlin(-0.5, 0.5, 15, 1), "Filter", y.linexp(-0.5, 0.5, 20, 18000)].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Fountain pen - Effect preset 3 (placeholder)
|
|
// Fountain pen - Effect preset 3 (placeholder)
|
|
|
- "/fountainPen", {
|
|
|
|
|
|
|
+ \fountainPen, {
|
|
|
// Apply Preset 3 effects (TBD in documentation)
|
|
// Apply Preset 3 effects (TBD in documentation)
|
|
|
["Fountain pen preset (TBD)"].postln;
|
|
["Fountain pen preset (TBD)"].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Water color - Effect preset 4 (placeholder)
|
|
// Water color - Effect preset 4 (placeholder)
|
|
|
- "/waterColor", {
|
|
|
|
|
|
|
+ \waterColor, {
|
|
|
// Apply Preset 4 effects (TBD in documentation)
|
|
// Apply Preset 4 effects (TBD in documentation)
|
|
|
["Water color preset (TBD)"].postln;
|
|
["Water color preset (TBD)"].postln;
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-// ----- OSC Pad Vaues -----
|
|
|
|
|
|
|
+// ----- OSC Pad Values -----
|
|
|
// OSC responder for x coordinate
|
|
// OSC responder for x coordinate
|
|
|
OSCdef(\xOSC, { |msg, time, addr, port|
|
|
OSCdef(\xOSC, { |msg, time, addr, port|
|
|
|
var x = msg[1].asFloat;
|
|
var x = msg[1].asFloat;
|
|
@@ -159,19 +255,19 @@ OSCdef(\pressureOSC, { |msg, time, addr, port|
|
|
|
// Update current pad value and change effects
|
|
// Update current pad value and change effects
|
|
|
~currentPadValues.pressure = pressure;
|
|
~currentPadValues.pressure = pressure;
|
|
|
~changeEffectParams.value;
|
|
~changeEffectParams.value;
|
|
|
|
|
+
|
|
|
|
|
+ // Trigger sound for envelope-controlling pens
|
|
|
|
|
+ ~triggerSound.value;
|
|
|
|
|
|
|
|
}, '/pressure');
|
|
}, '/pressure');
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
// ----- OSC Pen Types -----
|
|
// ----- OSC Pen Types -----
|
|
|
// OSC responder for pen
|
|
// OSC responder for pen
|
|
|
OSCdef(\penOSC, { |msg, time, addr, port|
|
|
OSCdef(\penOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
|
|
+ ~currentPenType = \pen;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -182,7 +278,7 @@ OSCdef(\monolineOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
|
|
+ ~currentPenType = \monoline;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -193,7 +289,7 @@ OSCdef(\markerOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
|
|
+ ~currentPenType = \marker;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -204,8 +300,8 @@ OSCdef(\pencilOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
- ~initializePreset1.value;
|
|
|
|
|
|
|
+ ~currentPenType = \pencil;
|
|
|
|
|
+ if(~initializePreset1.notNil, { ~initializePreset1.value; });
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -216,8 +312,8 @@ OSCdef(\crayonOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
- ~initializePreset2.value;
|
|
|
|
|
|
|
+ ~currentPenType = \crayon;
|
|
|
|
|
+ if(~initializePreset2.notNil, { ~initializePreset2.value; });
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -228,8 +324,8 @@ OSCdef(\fountainPenOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
- ~initializePreset3.value;
|
|
|
|
|
|
|
+ ~currentPenType = \fountainPen;
|
|
|
|
|
+ if(~initializePreset3.notNil, { ~initializePreset3.value; });
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -240,16 +336,13 @@ OSCdef(\waterColorOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = msg[0].asString;
|
|
|
|
|
- ~initializePreset4.value;
|
|
|
|
|
|
|
+ ~currentPenType = \waterColor;
|
|
|
|
|
+ if(~initializePreset4.notNil, { ~initializePreset4.value; });
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}, '/waterColor');
|
|
}, '/waterColor');
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
// ----- OSC RGB Colors -----
|
|
// ----- OSC RGB Colors -----
|
|
|
// OSC responder for red changes
|
|
// OSC responder for red changes
|
|
|
OSCdef(\redOSC, { |msg, time, addr, port|
|
|
OSCdef(\redOSC, { |msg, time, addr, port|
|
|
@@ -284,13 +377,19 @@ OSCdef(\blueOSC, { |msg, time, addr, port|
|
|
|
["Color changed:", ~currentColor].postln;
|
|
["Color changed:", ~currentColor].postln;
|
|
|
}, '/b');
|
|
}, '/b');
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+// Cleanup function
|
|
|
|
|
+~cleanupOSCSystem = {
|
|
|
|
|
+ ~activeSynths.keysValuesDo({ |key, synth|
|
|
|
|
|
+ synth.set(\gate, 0);
|
|
|
|
|
+ });
|
|
|
|
|
+ ~activeSynths.clear;
|
|
|
|
|
+ "OSC system cleaned up".postln;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
// Start the OSC server on port 57120 (default SuperCollider port)
|
|
// Start the OSC server on port 57120 (default SuperCollider port)
|
|
|
thisProcess.openUDPPort(57120);
|
|
thisProcess.openUDPPort(57120);
|
|
|
"OSC server ready on port 57120".postln;
|
|
"OSC server ready on port 57120".postln;
|
|
|
-"Registered OSC commands: /touch, /pen, /color".postln;
|
|
|
|
|
|
|
+"Registered OSC commands for pad values, pen types, and colors".postln;
|
|
|
"Ready to receive data from iDraw OSC app".postln;
|
|
"Ready to receive data from iDraw OSC app".postln;
|
|
|
|
|
+"To cleanup system, run: ~cleanupOSCSystem.value".postln;
|
|
|
)
|
|
)
|