( //~~FUNCTION THAT GENERATES THE GUI ~generateGUI = { var win, clockStringFunc, metronomeStringFunc, metronomeColorFunc, masterView, faderView, tabs; var tabButtonReset, transportButton, mixerButton, startPos = 0; var partAbbr = ["guitar", "accompHigh", "accompLowLower", "accompLowUpper", "interlude"]; var trackNames = ["guitar", "high", "low 1", "low 2", "interlude"]; var partVols, partMutes, partPans; var masterMute, masterVol; partVols = [1, 1, 1, 1, 1]; partMutes = [1, 1, 1, 1, 1]; partPans = [0, 0, 0, 0, 0]; masterMute = 1; masterVol = 1; clockStringFunc = { arg measure, beat; var measureString, beatString, leadSpace; measureString = measure.asInteger.asString; beatString = beat.asInteger.asString; leadSpace = (3 - measureString.size).collect({" "}).join; leadSpace ++ measureString ++ "." ++ beatString }; // [-30, -105, -104].asAscii and [-30, -105, -113].asAscii are unicode inverse bullet and normal bullet, respectively metronomeStringFunc = { arg beat; if(beat == 1, {[-30, -105, -104].asAscii}, {[-30, -105, -113].asAscii}) }; metronomeColorFunc = { arg beat; if(beat == 1, {Color.red},{Color.black}) }; ~appStatusFunc = Task({ loop { {~appStatus.string = ~appStatusString ++ "*"}.defer; 0.5.wait; {~appStatus.string = ~appStatusString ++ "* *"}.defer; 0.5.wait; {~appStatus.string = ~appStatusString ++ "* * *"}.defer; 0.5.wait; {~appStatus.string = ~appStatusString ++ "* * * *"}.defer; 0.5.wait; {~appStatus.string = ~appStatusString ++ "* * * * *"}.defer; 0.5.wait; } }); win = Window("Counterfeiting in Colonial Connecticut", Rect(500, 500, 1100, 500), false).front; masterView = { var view, masterIndicators, master, generator, transport, ranSeed, startPosText, prevSectionButton, prevSubsectionButton, playStopButton, nextSubsectionButton, nextSectionButton, sectionDisplay, clock, metronome; OSCFunc({ arg msg, time; { var measure, beat; measure = msg[3]; beat = msg[4]; clock.string = clockStringFunc.value(measure, beat); metronome.stringColor = metronomeColorFunc.value(beat); metronome.string = metronomeStringFunc.value(beat); }.defer; },'/measureClock', s.addr); OSCFunc({ arg msg, time; {metronome.string = ""}.defer},'/measureClockReset', s.addr); ~updateSection = {arg shift, stop = true; if(((~currentSection + shift) >= 0) && ((~currentSection + shift) < ~patterns.size), { var section, subSection; if(~isPlaying, { if(stop, {~patterns[~currentSection].stop}); }); ~currentSection = (~currentSection + shift).trunc(shift.abs); section = ((~currentSection / 4) + 1).asInteger; subSection = ((~currentSection % 4) + 1).asInteger; sectionDisplay.string = "section: " ++ section.asString ++ "." ++ subSection.asString; if(~isPlaying, { ~play.set(\sel, ~currentSection % 2); ~patterns[~currentSection].play(quant: 0) }, { /* var measure, beat; measure = 1; beat = 1; clock.string = clockStringFunc.value(measure, beat); metronome.stringColor = metronomeColorFunc.value(beat); metronome.string = metronomeStringFunc.value(beat); */ }); }); }; view = View(win); generator = HLayout( Button(view).states_([["generate"]]).action_({ ~appStatusString = "generating data"; ~appStatusFunc.start; ~generateData.value(seed: ranSeed.string.asInteger); }), ranSeed = TextField(view).string_("20170121"), Button(view).states_([["reset seed"]]).action_({ ranSeed.string = "20170121"}), Button(view).states_([["random seed"]]).action_({ ranSeed.string = 50000000.rand.asString}), [~appStatus = StaticText(view).string_("status: ready"), stretch: 1], nil); transport = HLayout( prevSectionButton = Button(view).states_([["<<", Color.black]]).action_({| pState | ~updateSection.value(-4); }), prevSubsectionButton = Button(view).states_([["<", Color.black]]).action_({| pState | ~updateSection.value(-1); }), playStopButton = Button(view).states_([["play", Color.black], ["stop", Color.black, Color.grey]]).action_( /* {| pState | pauseButton.value = 0; if(pState.value == 0, {~play.set(\playRate, 0, \startTrig, 0); clock.string = clockStringFunc.value((startPos * ~totalDur * 5).asInteger)}, {~play.set(\startPos, startPos, \playRate, 1, \startTrig, 1)})} */ {| pState | if(pState.value == 0, { ~isPlaying = false; ~patterns[~currentSection].stop; },{ ~isPlaying = true; ~play.set(\sel, ~currentSection % 2); ~patterns[~currentSection].play(quant: 0) }) } ), nextSubsectionButton = Button(view).states_([[">", Color.black]]).action_({| pState | ~updateSection.value(1); }), nextSectionButton = Button(view).states_([[">>", Color.black]]).action_({| pState | ~updateSection.value(4); }), StaticText(view).string_("start time"), [Slider(view, Rect(0, 0, 30, 5)).action_( {|pos| var min, sec; startPosText.string = clockStringFunc.value((pos.value * ~totalDur * 5).asInteger); startPos = pos.value; }), stretch: 1], startPosText = StaticText(win).string_(" 1.1").font_(Font("Monaco", 15)), nil); view.layout_(HLayout( [VLayout(generator, nil, sectionDisplay = StaticText(win).string_("section: 1.1").font_(Font("Monaco", 70)), HLayout(clock = StaticText(win).string_(" 1.1").font_(Font("Monaco", 200)), StaticText(win).string_("|").font_(Font("Monaco", 200)), metronome = StaticText(win).string_([-30, -105, -104].asAscii).font_(Font("Monaco", 300)).stringColor_(Color.red)), nil, transport ), alignment: \top])) }; faderView = { var view, masterIndicators, trackIndicators, master, tracks; view = View(win); masterIndicators = {LevelIndicator()} ! 2; trackIndicators = {LevelIndicator()} ! 5; OSCFunc.new({arg msg; { {|i| masterIndicators[i].value = msg[3 + i].ampdb.linlin(-40, 0, 0, 1)} ! 2}.defer}, '/masterLevels', s.addr); OSCFunc.new({arg msg; { {|i| trackIndicators[i].value = msg[3 + i].ampdb.linlin(-40, 0, 0, 1)} ! 5}.defer}, '/trackLevels', s.addr); master = HLayout( VLayout( [HLayout( Slider(view).value_(0.8).action_( {|v| masterVol = v.value * 1.25; ~play.set(\masterVol, masterVol)}), masterIndicators[0], masterIndicators[1]), stretch: 2], Button(view).states_([["mute", Color.black], ["mute", Color.black, Color.grey]]).action_( {|v| masterMute = (1 - v.value).abs; ~play.set(\masterMute, masterMute)}), StaticText(view).string_(" master ").align_(\center) //StaticText(view).string_("("++groupNames[group]++")").align_(\center) ), nil); tracks = { |part| HLayout( VLayout( HLayout( Slider(view).value_(0.8).action_( {|v| partVols[part] = v.value * 1.25; ~play.set(partAbbr[part] ++ "Vol", partVols[part])}), trackIndicators[part]), Button(view).states_([["mute", Color.black], ["mute", Color.black, Color.grey]]).action_( {|v| partMutes[part] = (1 - v.value).abs; ~play.set(partAbbr[part] ++ "Mute", partMutes[part])}), StaticText(view).string_("pan").align_(\center), Knob(view).value_(0.5).action_( {|v| partPans[part] = v.value * 2 - 1; ~play.set(partAbbr[part] ++ "Pan", partPans[part])}), StaticText(view).string_(trackNames[part]).align_(\center) ), nil) } ! 5; view.layout_(HLayout(master, nil, *tracks))}; tabButtonReset = {transportButton.value = 1; mixerButton.value = 1; }; win.layout = VLayout( HLayout( transportButton = Button().states_([["transport", Color.white, Color.grey], ["transport", Color.black]]).action_( {tabButtonReset.value; transportButton.value = 0; tabs.index = 0 }).value_(0), mixerButton = Button().states_([["mixer", Color.white, Color.grey], ["mixer", Color.black]]).action_( {tabButtonReset.value; mixerButton.value = 0; tabs.index = 1 }).value_(1)), tabs = StackLayout(masterView.value, faderView.value)); }; )