// Module 5: OSC Communication Setup - MODIFIED FOR IDRAW OSC
// Save as "5_osc_communication.scd"

(
// Clear any existing OSC definitions
OSCdef.freeAll;

// Create network connextion for Processing forwarding
~targetIP = NetAddr.new("127.0.0.1", 57122);

// Variables to track current pen type and color
~currentPenType = "\pen";
~currentColor = (r: 0.0, g: 0.0, b: 1.0); // Default blue
~currentPadValues = (x: 0.0, y: 0.0, pressure: 1.0, a: 1.0); //Default pad values


// Define OSC responder for iDraw touch data
~changeEffectParams = {
    var x = ~currentPadValues.x;
    var y = ~currentPadValues.y;
    var pressure = ~currentPadValues.pressure;
	var a = ~currentPadValues.a;

    // Log the received data
    //["Touch data:", x, y, pressure, ~currentPenType, ~currentColor].postln;

    // Handle touch based on current pen type
    switch(~currentPenType,
        // Pen - Controls amplitude envelope
		"/pen", {
            var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
            var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);

			~setSynthsParam.(\ampAttack, ampAttack);
			~setSynthsParam.(\ampRelease, ampRelease);

            //["Amplitude envelope:", ampAttack, ampRelease].postln;
        },

        // Monoline - Controls filter envelope
		"/monoline", {
            var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
            var filterDecay = x.linexp(-0.5, 0.5, 0.001, 10);
			var envDepth = a.linlin(0, 1, 50, 0.001);

			~filterEnv.set(\attack, filterAttack);
			~filterEnv.set(\decay, filterDecay);
			~filter.set(\envDepth, envDepth);


            //["Filter envelope:", filterAttack, filterDecay, envDepth].postln;
        },

        // Marker - Controls pitch envelope
		"/marker", {
            var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
            var pitchDecay = x.linexp(-0.5, 0.5, 0.001, 10);
			var pitchRatio = a.linexp(0, 1, 10, 1);

			~setSynthsParam.(\pitchAttack, pitchAttack);
			~setSynthsParam.(\pitchDecay, pitchDecay);
			~setSynthsParam.(\pitchRatio, pitchRatio);

            //["Pitch envelope:", pitchAttack, pitchDecay, pitchRatio].postln;
        },

        // Pencil - Effect preset 1
		"/pencil", {
            // Apply Preset 1 effects
            ~filter.set(
                \cutoff, x.linexp(-0.5, 0.5, 100, 18000),
                \resonance, y.linlin(-0.5, 0.5, 0, 1),
				\lfoDepth, pressure.linlin(1, 8, 0, 4)
            );

            ~lfo.set(
                \freq, x.linlin(-0.5, 0.5, 0, 15),
				\waveform, 2
            );

			~ctl.set(8, y.linlin(-0.5, 0.5, 0, 1));
			~ctl.set(9, 0.5);

            //["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", {
            // Apply Preset 2 effects
            ~lfo.set(
                \freq, x.linlin(-0.5, 0.5, 15, 1),
				\waveform, 3
            );

            ~filter.set(
                \cutoff, y.linexp(-0.5, 0.5, 20, 18000),
                \resonance, pressure.linlin(1, 5, 0, 1),
				\lfoDepth, x.linlin(-0.5, 0.5, 0, 3)
            );


			~ctl.set(9, y.linlin(-0.5, 0.5, 0, 0.5)); // Reverb dry/wet
			~ctl.set(7, x.linlin(-0.5, 0.5, 0.001, 1.0)); // Delay amount
			~ctl.set(9, 0.8);


            //["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)
		"/fountainPen", {
            // Apply Preset 3 effects
			~lfo.set(
                \freq, x.linlin(-0.5, 0.5, 1, 15),
				\waveform, 0
            );

			~filter.set(
				\lfoDepth, 0
            );

			~setSynthsParam.(\lfoDepth, pressure.linlin(1, 5, 0, 0.5));

			//["fountainPen preset:", "LFO Depth", pressure.linlin(1, 5, 0, 0.5), "LFO Freq", x.linlin(-0.5, 0.5, 1, 15)].postln;

        },

        // Water color - Effect preset 4 (placeholder)
		"/waterColor", {
            // Apply Preset 4 effects (TBD in documentation)

			if (a >= 0 && a < 0.20) {
					~ctl.set(0, x.linlin(-0.5, 0.5, -60, 20));
					~ctl.set(1, y.linlin(-0.5, 0.5, -60, 20));
					["Set:", y.linlin(-0.5, 0.5, -60, 20)].postln;
			};

			if (a >= 0.20 && a < 0.40) {
					~ctl.set(2, x.linlin(-0.5, 0.5, 1, 15));
					~ctl.set(3, y.linlin(-0.5, 0.5, 0, 1));
			};

			if (a >= 0.40 && a < 0.60) {
					~ctl.set(4, x.linlin(-0.5, 0.5, 0, 1));
					~ctl.set(5, y.linlin(-0.5, 0.5, 0, 1));
			};

			if (a >= 0.60 && a < 0.80) {
					~ctl.set(6, x.linlin(-0.5, 0.5, 0, 1));
					~ctl.set(7, y.linlin(-0.5, 0.5, 0, 1));
			};

			if (a >= 0.80) {
					~ctl.set(8, x.linlin(-0.5, 0.5, 0, 1));
					~ctl.set(9, y.linlin(-0.5, 0.5, 0, 1));
			};

        }
    );
};


// ----- OSC Pad Vaues -----
// OSC responder for x coordinate
OSCdef(\xOSC, { |msg, time, addr, port|
    var x = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

    // Update current pad value and change effects
    ~currentPadValues.x = x;
	~changeEffectParams.value;

}, '/aspectX');

// OSC responder for y coordinate
OSCdef(\yOSC, { |msg, time, addr, port|
    var y = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

    // Update current pad value and change effects
    ~currentPadValues.y = y;
	~changeEffectParams.value;

}, '/aspectY');

// OSC responder for pressure coordinate
OSCdef(\pressureOSC, { |msg, time, addr, port|
    var pressure = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

    // Update current pad value and change effects
    ~currentPadValues.pressure = pressure;
	~changeEffectParams.value;

}, '/pressure');




// ----- OSC Pen Types -----
// OSC responder for pen
OSCdef(\penOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/pen');

// OSC responder for monoline
OSCdef(\monolineOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/monoline');

// OSC responder for marker
OSCdef(\markerOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/marker');

// OSC responder for pencil
OSCdef(\pencilOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/pencil');

// OSC responder for crayon
OSCdef(\crayonOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/crayon');

// OSC responder for fountainPen
OSCdef(\fountainPenOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/fountainPen');

// OSC responder for waterColor
OSCdef(\waterColorOSC, { |msg, time, addr, port|
    var penType = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

	if (penType == 1.0) {
		~currentPenType = msg[0].asString;
		["Current pen type:", ~currentPenType].postln;
	}

}, '/waterColor');




// ----- OSC Drawing Width -----
OSCdef(\opacityOSC, { |msg, time, addr, port|
    var a = msg[1].asFloat;
	~currentPadValues.a = a;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

}, '/a');


// ----- OSC RGB Colors -----
// OSC responder for red changes
OSCdef(\redOSC, { |msg, time, addr, port|
    var component = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

    // Update current color
    ~currentColor.r = component;
	~setSynthsParam.(\redAmt, component);

    //["Color changed:", ~currentColor].postln;
}, '/r');

// OSC responder for green changes
OSCdef(\greenOSC, { |msg, time, addr, port|
    var component = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

    // Update current color
    ~currentColor.g = component;
	~setSynthsParam.(\greenAmt, component);

    //["Color changed:", ~currentColor].postln;
}, '/g');

// OSC responder for blue changes
OSCdef(\blueOSC, { |msg, time, addr, port|
    var component = msg[1].asFloat;

	// Forward for Processing
	~targetIP.sendMsg(msg[0].asString, msg[1].asFloat);

    // Update current color
    ~currentColor.b = component;
	~setSynthsParam.(\blueAmt, component);

    //["Color changed:", ~currentColor].postln;
}, '/b');






// Start the OSC server on port 57120 (default SuperCollider port)
thisProcess.openUDPPort(57120);
"OSC server ready on port 57120".postln;
"Ready to receive data from iDraw OSC app".postln;
)