aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Runge <dave@sleepmap.de>2016-06-22 02:07:01 +0200
committerDavid Runge <dave@sleepmap.de>2016-06-22 02:07:01 +0200
commit0f883cd9df74327a904da5a98ca35d4e7b82a90d (patch)
tree97290bb08864cf084e68df193ddc07c43b291e4b
parent195adaa0860f0d2e32ff32ba72226a49e7cf0d59 (diff)
downloadbowelyzer-0f883cd9df74327a904da5a98ca35d4e7b82a90d.tar.gz
bowelyzer-0f883cd9df74327a904da5a98ca35d4e7b82a90d.tar.bz2
bowelyzer-0f883cd9df74327a904da5a98ca35d4e7b82a90d.tar.xz
bowelyzer-0f883cd9df74327a904da5a98ca35d4e7b82a90d.zip
Bowelyzer.sc: Adding functionality to listen for OSC messages sent by GUI elements. BowelyzerGUI.sc: Adding first version of class for GUI of bowelyzer.0.2
-rw-r--r--Bowelyzer.sc92
-rw-r--r--BowelyzerGUI.sc353
2 files changed, 444 insertions, 1 deletions
diff --git a/Bowelyzer.sc b/Bowelyzer.sc
index 3d01b1a..3071588 100644
--- a/Bowelyzer.sc
+++ b/Bowelyzer.sc
@@ -22,10 +22,100 @@ Bowelyzer{
server.waitForBoot({
hub = BowelyzerOSCHub.new(config.config);
analyzer = BowelyzerAnalyzer.new(config.config);
- //gui = BowelyzerGUI.new(config.config);
+ gui = BowelyzerGUI.new(config.config);
+ this.addGUIListeners;
},
5,
{"scsynth failed to start!".postln});
}
+ addGUIListeners{
+ OSCdef.newMatching(
+ key: \controls,
+ func: {|msg, time, addr, recvPort|
+ postln("Received: "++msg);
+ // if the control exists, change it
+ if(msg[1].notNil && msg[2].notNil && msg[3].notNil,{
+ if(config.config.at(\controls).includesKey(msg[1]),{
+ if(config.config.at(\controls).at(msg[1]).includesKey(msg[2]),{
+ config.config.at(\controls).at(msg[1]).put(msg[2], config.getControlValue(msg[2], msg[3]));
+ });
+ });
+ });
+ },
+ path: "/controls",
+ srcID: NetAddr.new("127.0.0.1", NetAddr.langPort)
+ );
+ OSCdef.newMatching(
+ key: \inputs,
+ func: {|msg, time, addr, recvPort|
+ postln("Received: "++msg);
+ if(msg[1].notNil && msg[2].notNil && msg[3].notNil,{
+ if(config.config.at(\inputs).includesKey(msg[1]) && config.config.at(\controls).includesKey(msg[1]),{
+ switch(msg[2],
+ \name,{
+ //if the name exists and the new name is not empty, change it
+ if(msg[3]!= "",{
+ //move the controls
+ config.config.at(\controls).put(msg[3].asSymbol, config.config.at(\controls).at(msg[1]));
+ config.config.at(\controls).removeAt(msg[1].asSymbol);
+ // rename the input
+ config.config.at(\inputs).put(msg[3].asSymbol, config.config.at(\inputs).at(msg[1]));
+ config.config.at(\inputs).removeAt(msg[1]);
+ // rename the GUI element in channelView
+ Routine{
+ gui.channels.keysValuesDo({|name, channelView|
+ postln(name++"->"++channelView.name);
+ if(channelView.name.asSymbol == msg[1].asSymbol, {
+ channelView.name = msg[3].asSymbol;
+ });
+ });
+ //TODO: rename the LevelListener
+ }.play(AppClock);
+ // free the synth on the server and start a new one according to the config
+ analyzer.freeAnalysisSynth(msg[1].asSymbol);
+ analyzer.addSynthWithName(msg[3]);
+ Routine{
+ 1.wait;
+ analyzer.startSynthWithNameAndControls(msg[3].asSymbol, config.config.at(\controls).at(msg[3]), config.config.at(\inputs).at(msg[3]));
+ }.play;
+ hub.freeSynthListener(msg[1]);
+ hub.addSynthListener(msg[3]);
+ hub.startSynthListener(msg[3]);
+ });
+ },
+ \input,{
+ // if the input name exists and the new is an Integer and greater/equal 0
+ if(((msg[3].isInteger) && (msg[3].asInteger >= 0)),{
+ // change the input in configuration
+ config.config.at(\inputs).put(msg[1], msg[3].asInteger);
+ analyzer.setSynthControl(msg[1].asSymbol, \inputChannel, msg[3].asInteger);
+ });
+ }
+ );
+ });
+ });
+ },
+ path: "/inputs",
+ srcID: NetAddr.new("127.0.0.1", NetAddr.langPort)
+ );
+ OSCdef.newMatching(
+ key: \toggle,
+ func: {|msg, time, addr, recvPort|
+ postln("Received: "++msg);
+ if(msg[1].notNil && msg[2].notNil && msg[3].notNil,{
+ if(config.config.at(\inputs).includesKey(msg[1]),{
+ switch(msg[3],
+ 0,{analyzer.startAnalysisSynth(msg[1])},
+ 1,{analyzer.stopAnalysisSynth(msg[1])}
+ );
+ });
+ });
+ },
+ path: "/toggle",
+ srcID: NetAddr.new("127.0.0.1", NetAddr.langPort)
+ );
+ }
+ //TODO: add SimpleController
+ //TODO: delegate changes to BowelyzerConfig.config and update analyzer and GUI with it
}
diff --git a/BowelyzerGUI.sc b/BowelyzerGUI.sc
new file mode 100644
index 0000000..f50ac63
--- /dev/null
+++ b/BowelyzerGUI.sc
@@ -0,0 +1,353 @@
+BowelyzerGUI{
+
+ var mainView,
+ channelContainerView,
+ <channels,
+ <indicators,
+ //TODO: move to BowelyzerConfig
+ fadeOutTime = 1.0,
+ fadeOutSteps = 20,
+ minWidth=1280,
+ minHeight=720;
+
+ *new{
+ arg config;
+ ^super.new.init(config)
+ }
+
+ init{
+ arg config;
+ postln("Launching GUI.");
+ channels = Set.new(config.at(\inputs).size);
+ indicators = Dictionary.new(config.at(\inputs).size);
+ this.setupMainView(config);
+ this.setupChannelViews(config);
+ //TODO: add Button for adding new channel
+ //TODO: add Button to save/load setup
+ }
+
+ //setup the main view, in which all other views reside
+ setupMainView{
+ arg config;
+ mainView = PageLayout.new("Bowelyzer");
+ mainView.asView.background = Color.fromHexString("#DBDBDB");
+ channelContainerView = View(mainView.asView, Rect(0, 0, mainView.bounds.width/config.at(\inputs).size, mainView.bounds.height));
+ channelContainerView.asView.background = Color.fromHexString("#FEFEFE");
+ channelContainerView.layout = HLayout();
+ channelContainerView.layout.spacing = 10;
+ channelContainerView.layout.margins = [4,0,4,0];
+ //TODO: add vertical scroll
+ }
+
+ //setup channel views
+ setupChannelViews{
+ arg config;
+ var channelView, headView, controlMeterContainerView, meterView, controlsView, controlsFromConfig, levelIndicator;
+ config.at(\inputs).keysValuesDo({|name, input|
+ channelView = View(mainView.asView, Rect(0, 0, mainView.bounds.width/config.at(\inputs).size, mainView.bounds.height));
+ channelView.asView.background = Color.fromHexString("#FEEFEF");
+ channelView.name = name;
+ channelView.layout = VLayout();
+ channelView.layout.spacing = 0;
+ channelView.layout.margins = [0,10,0,0];
+ // adding name textfield of input
+ headView = View(channelView.asView, Rect(0, 0, channelView.bounds.width/config.at(\inputs).size, 40));
+ headView.asView.background = Color.fromHexString("#DDEFDD");
+ headView.name = \inputs;
+ headView.layout = HLayout();
+ headView.layout.spacing = 0;
+ headView.layout.margins = [4,0,4,0];
+ headView.maxHeight_(30);
+ this.setupEZText(headView, "name", name.asString);
+ this.setupEZNumber(headView, "input", config.at(\inputs).at(name));
+
+ controlMeterContainerView = View(channelView.asView, Rect(0, 0, channelView.bounds.width/config.at(\inputs).size, channelView.bounds.height));
+ controlMeterContainerView.asView.background = Color.fromHexString("#DDDDEF");
+ controlMeterContainerView.name = \meterAndControls;
+ controlMeterContainerView.layout = HLayout();
+ channelView.layout.spacing = 0;
+ channelView.layout.margins = [4,0,4,0];
+ meterView = View(controlMeterContainerView.asView, Rect(0,0, channelView.bounds.width*0.1, channelView.bounds.height));
+ meterView.asView.background = Color.fromHexString("#EEEFEE");
+ meterView.name = \meterView;
+ meterView.layout = VLayout();
+ meterView.maxWidth = 60;
+ meterView.layout.spacing = 20;
+ meterView.layout.margins = [0,10,0,0];
+
+ //setup a toggle button for each channel
+ this.setupPauseButton(meterView);
+
+ // setup a small View as indicator for incoming/outgoing OSC messages for each input
+ this.setupOSCIndicator(meterView);
+ this.addOSCIndicatorFadeOutTask(name);
+ indicators.at(name).play(AppClock);
+
+
+ // setup LevelIndicator for each input
+ this.setupLevelIndicator(meterView);
+ this.setupLevelListener(name, NetAddr.new(config.at(\synthServerAddress), config.at(\synthServerPort)));
+
+ controlsView = View(controlMeterContainerView.asView, Rect(0,0, channelView.bounds.width*0.9, channelView.bounds.height));
+ controlsView.asView.background = Color.fromHexString("#EEEFEE");
+ controlsView.name = \controls;
+ controlsView.layout = VLayout();
+ controlsView.layout.spacing = 2;
+ controlsView.layout.margins = [0,0,0,0];
+
+ config.at(\controls).at(name).order.do({|control, i|
+ var unit;
+ var value = config.at(\controls).at(name).at(control), controlIs = BowelyzerConfig.controlContainedIn(control);
+ switch(
+ controlIs.asSymbol,
+ \knob, {this.setupEZKnob(controlsView, control, value, \controls, name)},
+ \slider, {this.setupEZSlider(controlsView, control, value)},
+ \ranger, {this.setupEZRanger(controlsView, control, value, \controls, name)}
+ );
+ });
+
+ channelContainerView.layout.add(channelView);
+ channels.add(channelView);
+ });
+ }
+
+ // setup a OSC indicator view (one on each channel)
+ setupOSCIndicator{
+ arg parent;
+ ^View(parent, Rect(0,0,40,40))
+ .name_(\OSCIndicator)
+ .background_(Color.fromHexString("#EEEFEE"))
+ //.background_(Color.fromHexString("#99EF99"))
+ .maxSize_(40@20)
+ .visible_(true)
+ ;
+ }
+
+ // setup tasks for changing the OSC indicator color (on receiving a message)
+ addOSCIndicatorFadeOutTask{
+ arg name;
+ indicators.put(
+ name.asSymbol,
+ Task({
+ channels.do({|channel|
+ if(channel.name.asSymbol == name,{
+ channel.children.do({|channelChild|
+ if(channelChild.name.asSymbol == \meterAndControls,{
+ channelChild.children.do({|meterAndControls|
+ if(meterAndControls.name.asSymbol == \meterView, {
+ meterAndControls.children.do({|meterView|
+ if(meterView.isKindOf(View) && meterView.name.asSymbol == \OSCIndicator, {
+ meterView.background_(Color.fromHexString("#99FF99"));
+ fadeOutSteps.do({|item,i|
+ meterView.background_(meterView.background.blend(Color.fromHexString("#EEEFEE"), (fadeOutTime/fadeOutSteps)));
+ (fadeOutTime/fadeOutSteps).wait;
+ });
+ meterView.background_(Color.fromHexString("#EEEFEE"));
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ })
+ );
+ }
+
+ freeOSCIndicatorFadeOutTask{
+
+ }
+
+ // setup a listener for a level indicator by name and source (of synth server)
+ setupLevelListener{
+ arg name, source;
+ postln("Setting up LevelListener for: "++name);
+ OSCdef.newMatching(
+ key: \levels++name,
+ func: {|msg, time, addr, recvPort|
+ var msgName = msg[0].asString.replace("/levels/", "").asSymbol;
+ {
+ channels.do({|channel|
+ if(channel.name.asSymbol == msgName,{
+ channel.children.do({|channelChild|
+ if(channelChild.name.asSymbol == \meterAndControls,{
+ channelChild.children.do({|meterAndControls|
+ if(meterAndControls.name.asSymbol == \meterView, {
+ meterAndControls.children.do({|meterView|
+ if(meterView.isKindOf(LevelIndicator), {
+ //postln("Setting up LevelIndicator for "++msgName);
+ meterView.value = msg[3].ampdb.linlin(-40, 0, 0, 1);
+ meterView.peakLevel = msg[4].ampdb.linlin(-40, 0, 0, 1);
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ }.defer;
+ },
+ path: "/levels/"++name,
+ srcID: source
+ );
+ }
+
+ startLevelListener{
+ arg name;
+ OSCdef(\levels++name).enable;
+ }
+
+ stopLevelListener{
+ arg name;
+ OSCdef(\levels++name).disable;
+ }
+
+ freeLevelListener{
+ arg name;
+ OSCdef(\levels++name).free;
+ }
+
+ setupLevelIndicator{
+ arg parent;
+ ^LevelIndicator(
+ parent
+ ).maxSize_(50@600)
+ .style_(\led)
+ .drawsPeak_(true);
+ }
+
+ setupPauseButton{
+ arg parent;
+ ^Button(parent, Rect(0,0,40,20))
+ .states_([
+ ["on", Color.black, Color.fromHexString("#99FF99")],
+ ["off", Color.black, Color.fromHexString("#FF9999")]
+ ])
+ .action_({
+ arg controlUnit;
+ var address = NetAddr.new("127.0.0.1", NetAddr.langPort),
+ type = "/toggle",
+ name = controlUnit.parent.parent.parent.name.asSymbol,
+ controlName = \active,
+ controlValue = controlUnit.value;
+ address.sendMsg(type, name, controlName, controlValue);
+ })
+ .maxSize_(40@20);
+ }
+
+
+ setupEZText{
+ arg parent, control, value;
+ ^EZText(
+ parent: parent,
+ bounds: 140@20,
+ label: control,
+ action: {
+ arg controlUnit;
+ var address = NetAddr.new("127.0.0.1", NetAddr.langPort),
+ type = "/"++controlUnit.view.parent.name.asString,
+ name = controlUnit.view.parent.parent.name.asSymbol,
+ controlName = controlUnit.labelView.string.asSymbol,
+ controlValue = controlUnit.value;
+ address.sendMsg(type, name, controlName, controlValue);
+ },
+ labelWidth: 40,
+ textWidth: 100,
+ initVal:value.asString,
+ layout: \horz,
+ margin: nil
+ )
+ .view.maxHeight_(20);
+ }
+
+ setupEZNumber{
+ arg parent, control, value;
+ ^EZNumber(
+ parent: parent,
+ bounds: 100@20,
+ label: control,
+ controlSpec: control.asSymbol,
+ action: {
+ arg controlUnit;
+ var address = NetAddr.new("127.0.0.1", NetAddr.langPort),
+ type = "/"++controlUnit.view.parent.name.asString,
+ name = controlUnit.view.parent.parent.name.asSymbol,
+ controlName = controlUnit.labelView.string.asSymbol,
+ controlValue = controlUnit.value;
+ address.sendMsg(type, name, controlName, controlValue);
+ },
+ initVal:value,
+ unitWidth:0,
+ layout: \horz,
+ margin: nil
+ )
+ .view.maxSize_(100@20);
+ }
+
+ setupEZSlider{
+ arg parent, control, value;
+ ^EZSlider(
+ parent: parent,
+ bounds: 230@40,
+ label: control,
+ controlSpec: control.asSymbol,
+ action: {
+ arg controlUnit;
+ var address = NetAddr.new("127.0.0.1", NetAddr.langPort),
+ type = "/"++controlUnit.view.parent.name.asString,
+ name = controlUnit.view.parent.parent.parent.name.asSymbol,
+ controlName = controlUnit.labelView.string.asSymbol,
+ controlValue = controlUnit.value;
+ address.sendMsg(type, name, controlName, controlValue);
+ },
+ numberWidth: 70,
+ layout: \line2,
+ margin: nil
+ );
+ }
+
+ setupEZRanger{
+ arg parent, control, value;
+ ^EZRanger(
+ parent: parent,
+ bounds: 300@16,
+ label: control,
+ controlSpec: control,
+ action: {
+ arg controlUnit;
+ var address = NetAddr.new("127.0.0.1", NetAddr.langPort),
+ type = "/"++controlUnit.view.parent.name.asString,
+ name = controlUnit.view.parent.parent.parent.name.asSymbol,
+ controlName = controlUnit.labelView.string.asSymbol,
+ controlValue = controlUnit.value;
+ address.sendMsg(type, name, controlName, controlValue);
+ },
+ labelWidth: 120,
+ unitWidth:30
+ );
+ }
+
+ setupEZKnob{
+ arg parent, control, value, type, name;
+ ^EZKnob(
+ parent: parent,
+ bounds: 300@16,
+ label: control,
+ controlSpec: \freq,
+ action: {
+ arg controlUnit;
+ var address = NetAddr.new("127.0.0.1", NetAddr.langPort),
+ type = "/"++controlUnit.view.parent.name.asString,
+ name = controlUnit.view.parent.parent.parent.name.asSymbol,
+ controlName = controlUnit.labelView.string.asSymbol,
+ controlValue = controlUnit.value;
+ address.sendMsg(type, name, controlName, controlValue);
+ },
+ labelWidth: 120,
+ unitWidth:30
+ );
+ }
+}
+