Permalink
Browse files

added timeline

  • Loading branch information...
1 parent c779ff2 commit 387e5c793285d5fc243ca1e25ec54c315bfd6767 @grirgz committed Oct 16, 2012
Showing with 1,921 additions and 167 deletions.
  1. +8 −0 bindings.sc
  2. +10 −0 crap30.sc
  3. +140 −0 crap31.sc
  4. +211 −0 crap32.sc
  5. +298 −0 crap33.sc
  6. +42 −4 eventscore.sc
  7. +1 −1 live27.sc
  8. +332 −0 live28.sc
  9. +2 −0 main.sc
  10. +113 −66 matrix.sc
  11. +117 −10 node_manager.sc
  12. +66 −75 player.sc
  13. +35 −10 side.sc
  14. +24 −1 synthlab.sc
  15. +522 −0 timeline.sc
View
8 bindings.sc
@@ -26,7 +26,14 @@
["show_panel.editplayer", \kb, 0, \f12],
["create_new_livenode", \kb, \alt, "c"],
],
+ timeline: [
+ ["play_timeline", \kb, 0, \f5],
+ ["stop_timeline", \kb, 0, \f6],
+ ["close_timeline", \kb, 0, \escape],
+ ],
side: [
+ ["open_timeline", \kb, \ctrlalt, "l"],
+
["decrease_select_offset", \midi, 0, \begin],
["increase_select_offset", \midi, 0, \end],
["increase_samplekit_part", \midi, 0, \right],
@@ -55,6 +62,7 @@
["edit_wrapper", \kb, \alt, "w"],
["copy_node", \kb, \ctrl, "c"],
+ ["cut_node", \kb, \ctrl, "x"],
["paste_node", \kb, \ctrl, "v"],
//["copy_group", \kb, \ctrl, \kbnumpad],
["remove_node", \kb, \ctrlshift, \f4],
View
10 crap30.sc
@@ -445,3 +445,13 @@ p = Pbind(
).play;
)
p.originalStream.get_receiver
+
+
+Mdef.node(\s1_part1_sect1_var1).song_path
+Mdef.node("s1_part1_sect1_var1").children
+~newln = Mdef.main.node_manager.duplicate_livenode(Mdef.node("monosampler_l1084").uname)
+
+Mdef.node(\s1_part1_sect1_var1).add_children(~newln)
+
+
+
View
140 crap31.sc
@@ -0,0 +1,140 @@
+
+(
+~pmonopar = { arg pat, par;
+
+ Pfset({
+ currentEnvironment[\monogroup] = Group.new;
+ },
+ Ppar([Pset(\group, Pkey(\monogroup), pat), Pbind(\type, \set, \id, Pkey(\monogroup)) <> par]),
+ {
+ currentEnvironment[\monogroup].free;
+ }
+ )
+
+};
+)
+
+(
+SynthDef(\acid, { arg out=0, amp=0.1, gate=1, pan=0, freq=200, ffreq=400, rq=0.1;
+ var ou;
+ ou = LFSaw.ar(freq);
+ ou = RLPF.ar(ou, ffreq, rq);
+ ou = ou * EnvGen.ar(Env.adsr(0.01,0.1,0.8,0.1),gate,doneAction:2);
+ ou = Pan2.ar(ou, pan, amp);
+ Out.ar(out, ou);
+}).add;
+)
+
+(
+~pmonopar.(
+ Pbind(
+ \instrument, \acid,
+ \freq, 300,
+ \legato, 0.8,
+ \dur, 2,
+ ),
+ Pbind(
+ \args, [\ffreq],
+ \ffreq, Pseq([100,1200],inf),
+ \dur, 0.5,
+ ),
+).play;
+
+)
+(
+~pmonopar.(
+ Pbind(
+ \instrument, \acid,
+ \freq, 300,
+ \legato, 0.1,
+ \dur, 4,
+ ),
+ Ppar([
+ Pbind(
+ \args, [\ffreq],
+ \ffreq, Pseq([100,1200],inf),
+ \dur, 0.5,
+ ),
+ Pbind(
+ \args, [\rq],
+ \rq, Pseq([0.1,1.7],inf),
+ \dur, 1.7,
+ )
+ ])
+).play;
+
+)
+
+~pmonopar = { arg pat, par;
+ var buskeydict = Dictionary.new;
+ var respat = List.new;
+ var ctlpatlist = List.new;
+ var pbindpat;
+ var makebusmap;
+
+ "pcontrol start".debug;
+ makebusmap = { arg key;
+ Pfunc { arg ev; [key, ev[key]].debug("pfunc"); ev[key].asMap }
+ };
+
+ if(pat.class == EventPatternProxy) {
+ pbindpat = pat.source;
+ } {
+ pbindpat = pat
+ };
+
+ pbindpat.patternpairs.pairsDo { arg key,val;
+ var buskey;
+ var env;
+ var cbus;
+ var ctlpat;
+ if(val.class == Ref) {
+ buskey = "bus_" ++ key;
+ respat.add(key);
+ respat.add(makebusmap.(buskey));
+ env = val.value;
+ buskeydict[buskey] = env.levels[0];
+ cbus.set(env.levels[0]);
+ ctlpat = Pbind(
+ \instrument, \ctlPoint,
+ \value, Pseq(env.levels[1..],inf),
+ \time, Pseq(env.times,inf) / Pfunc({thisThread.clock.tempo}),
+ \group, Pkey(\busgroup),
+ \outbus, Pfunc { arg ev; ev[buskey].index },
+ \curve, env.curves,
+ \dur, Pseq(env.times,inf)
+ );
+ ctlpatlist.add(ctlpat);
+ }
+ };
+
+ respat.debug("respat");
+
+ Pfset({
+ buskeydict.debug("penvcontrol init pfset");
+ buskeydict.keysValuesDo { arg key, val;
+ currentEnvironment[key] = Bus.control(s, 1);
+ currentEnvironment[key].set(val);
+ };
+ currentEnvironment[\busgroup] = Group.new;
+ },
+ Pfpar(
+ [
+ if(chain.notNil) {
+ chain <> Pbind(*respat) <> pat;
+ } {
+ Pbind(*respat) <> pat;
+ }
+ ]
+ ++ ctlpatlist
+ ),
+ {
+ buskeydict.debug("penvcontrol cleanup pfset");
+ buskeydict.keysValuesDo { arg key, val;
+ currentEnvironment[key].free;
+ };
+ currentEnvironment[\busgroup].freeAll;
+ currentEnvironment[\busgroup].free;
+ }
+ )
+};
View
211 crap32.sc
@@ -0,0 +1,211 @@
+
+(
+
+var data;
+
+w = Window.new("ParaSpace", Rect(10, 500, 400, 300)).front;
+
+a = ParaSpace.new(w, bounds: Rect(20, 20, 360, 260));
+
+
+9.do({arg d, i; a.createNode1(0.5, (i/10)+0.1).setNodeString_(i, (i+1).asString);
+a.setNodeSize_(i, 20);
+a.paraNodes[i].setLen = 100;
+a.paraNodes[i].temp = (i/10)+0.1;
+
+});
+
+
+8.do({arg i; a.createConnection(i, i+1)});
+
+
+a.setBackgrDrawFunc_({
+
+10.do{|i|
+//Color.blue(alpha:0.2).set;
+
+Pen.line((i*36)@0, (i*36)@280); Pen.stroke};
+
+13.do{|i|
+//Color.blue(alpha:0.2).set;
+
+Pen.line(0@(i*20), 380@(i*20)); Pen.stroke};
+
+});
+
+
+a.nodeTrackAction_({arg node;
+
+a.setNodeLoc1_(node.spritenum, a.getNodeLoc1(node.spritenum)[0].round(0.1), a.getNodeLoc1(node.spritenum)[1].round(0.1))
+
+});
+
+)
+
+(
+p = Pspawn(Pbind(
+ // Pbind returned by Pfunc is not embedded, just placed in the event
+ // So, it can be spawned
+ \pattern, Pseq([
+ Prout { Pbind(\degree, Pseries(rrand(0, 10), #[-1, 1].choose, rrand(4, 10)), \dur, 0.125).yield },
+ \rest,
+ Prout { Pbind(\degree, Pseries(rrand(0, 10), #[-1, 1].choose, rrand(4, 10)), \dur, 0.25).yield },
+ ],inf),
+ \delta, 1,
+ \method, \par
+)).play;
+)
+
+{SinOsc.ar}.play
+
+
+
+Mdef.main
+
+(
+Mdef.force_init;
+Mdef(\blabla, Pbind(
+ \instrument, \lead2,
+ \degree, Pseq([0,2,4,2],1),
+ \dur, 0.25
+));
+Mdef(\blabla2, Pbind(
+ \instrument, \default,
+ \degree, Pseq([0,1,2,1],1),
+ \dur, 0.25
+));
+~tl = ~class_timeline.new(Mdef.main);
+5.do { arg i; ~tl.add_track("track"++i);};
+~tl.make_gui;
+)
+~tl.add_block(\blabla, 0, 1);
+~tl.add_block(\blabla2, 1, 4);
+~tl.add_track("trackbla");
+~tl.tracks
+~tl.timerule_view.view.refresh
+~tl.timeline_view.timerule_view.view.refresh
+~tl.changed(\tracks)
+~tl.timeline_view.timeline.refresh
+
+Mdef.node("miaou1_l1007").get_duration
+Mdef.node(\blabla).get_duration
+
+Mdef.main.panels.side.song_manager.get_section_matrix(0,0)
+Mdef.main.node_manager.has_node
+
+(
+
+Mdef.force_init;
+Mdef.main.panels.side.song_manager.get_section_matrix(0,0)
+)
+Mdef.main.panels.side.song_manager.
+
+
+a = [[0,1,2,3],[4,5,6,7]]
+a.invert(1)
+a.flop
+
+~tl.play_timeline;
+
+~tl.timeline_score.get_abs_notes
+~tl.timeline_score.get_rel_notes
+~tl.timeline_score.notes
+~tl.timeline_score.compute_end(false)
+
+
+~tl.timeline_view.tracks(~tl)
+~t1.vpattern.pattern.postcs
+~t1.vpattern.play
+~t2.vpattern.play
+~t1.get_rel_notes
+
+
+a = (a:2)
+a.bla = 45
+a.identityHash
+
+
+
+
+(
+var width = 400, height = 400, mx = 0, my = 0, pt, r;
+
+w = Window("animation and mouse interaction", Rect(100, 200, width, height), false);
+
+u = UserView(w, Rect(0, 0, width, height));
+u.background = Color.black;
+u.animate = true; //animate this view
+
+// allocate data in advance, for optimization:
+pt = Point();
+r = Rect();
+
+u.drawFunc = {
+ Pen.fillColor = Color.green;
+ Pen.stringAtPoint(u.frameRate.asString, Point(10, 10)); // display frame rate
+ Pen.stringAtPoint(u.frame.asString, Point(10, 30)); // display frame counter
+ Pen.color = Color.white;
+ pt.x=mx;
+ pt.y=my;
+ 100.do{|i|
+ Pen.moveTo(pt);
+ pt.x = sin(u.frame*0.04.neg+i)*(5*i)+mx; //use .frame to drive animation
+ pt.y = cos(u.frame*0.05+i)*(5*i)+my;
+ r.left=pt.x;
+ r.top=pt.y;
+ r.width=i;
+ r.height=i;
+ Pen.lineTo(pt);
+ Pen.fillStroke;
+ Pen.addOval(r);
+ Pen.fillStroke;
+ };
+};
+u.mouseDownAction = {|v, x, y|
+ mx = x;
+ my = y;
+};
+u.mouseMoveAction = u.mouseDownAction;
+w.front;
+)
+
+u.animate = false; //animation can be paused and resumed
+u.animate = true;
+w.close; //stops animation
+
+(
+var width = 800, height = 20, mx = 0, my = 0, pt, r;
+var bounds = Rect(100, 200, width+10, height+10);
+w = Window("animation and mouse interaction", Rect(100, 200, width, height), false);
+~uv = UserView.new(w, Rect(0, 0, width, height));
+~uv.drawFunc = {
+
+ var beat_size_x = 10;
+ Pen.fillColor = Color.green;
+ (width/beat_size_x).asInteger.do{|i|
+ Pen.color = Color.black;
+ case
+ { i%32==0 } {
+ Pen.color = Color.blue;
+ Pen.line((i*beat_size_x)@0, (i*beat_size_x)@height); Pen.stroke
+ }
+ { i%8==0 } {
+
+ Pen.line((i*beat_size_x)@0, (i*beat_size_x)@height); Pen.stroke
+ }
+ { i%4==0 } {
+
+ Pen.line((i*beat_size_x)@(height/2), (i*beat_size_x)@height); Pen.stroke
+ }
+ //
+ {
+ Pen.line((i*beat_size_x)@(3*height/4), (i*beat_size_x)@height); Pen.stroke
+ }
+
+
+ };
+};
+w.front;
+)
+
+
View
298 crap33.sc
@@ -0,0 +1,298 @@
+// Granular display by T.Maisey.
+
+// Position in the sound file is (obviously) on the x-axis, amplitude on the y-axis.
+
+// The grain's transparency shows its position in its envelope (window).
+
+// The speed of the grain shows pitch.
+
+// ----------------------------------------------
+
+
+
+// Requires use of Qt gui kit.:
+
+GUI.qt;
+
+
+
+(
+
+var soundFile, buffer, window, fileView, grainView, granary, displayGrain;
+
+
+
+soundFile = SoundFile.openRead(Platform.resourceDir +/+ "sounds/a11wlk01.wav");
+
+buffer = Buffer.readChannel(s, soundFile.path, channels: [0]);
+
+
+
+{
+
+SynthDef(\grain, {
+
+ |bufNum = 0, pos, dur, env = 0.05, pitch = 1, pan = 0, amp = 0.5|
+
+ var envl, sig;
+
+ envl = EnvGen.kr(Env.linen(env, dur, env, amp, -3), doneAction: 2);
+
+ sig = PlayBuf.ar(1, bufNum, pitch, 0, pos.linlin(0,1,0,BufFrames.kr(bufNum))) * envl;
+
+
+
+ Out.ar(0, Pan2.ar(sig, pan));
+
+}).add;
+
+
+
+ s.sync;
+
+}.fork;
+
+
+
+~pos = { rrand(0.2, 0.6) };
+
+~dur = { rrand(0.1, 0.5) };
+
+~env = { rrand(0.3, 0.5) };
+
+~amp = { rrand(0.1, 0.7) };
+
+~pitch = { rrand(0.5, 2) }; // pitch is a ratio
+
+~pan = { rrand(-0.8, 0.8) };
+
+~wait = { 0.1 }; // time between grains
+
+
+
+~playTask = Task({ loop {
+
+ var pos, pitch, amp, dur, env;
+
+ Synth(\grain,
+
+ [
+
+ \bufNum, buffer,
+
+ \pos, pos = ~pos.value,
+
+ \pitch, pitch = ~pitch.value,
+
+ \amp, amp = ~amp.value,
+
+ \dur, dur = ~dur.value,
+
+ \env, env = ~env.value,
+
+ \pan, ~pan.value,
+
+ ]);
+
+ displayGrain.value(pos, pitch, amp, dur, env);
+
+
+
+ ~wait.value.wait;
+
+}});
+
+
+
+
+
+// Grain display
+
+
+
+window = Window.new("Grain display", Rect(200, 300, 740, 300));
+
+
+
+
+
+fileView = SoundFileView().readFile(soundFile).gridOn_(false);
+
+grainView = UserView().resize_(5);
+
+
+
+window.layout = StackLayout(fileView, grainView).mode_(\stackAll).index_(1);
+
+window.onClose = {p.stop};
+
+window.front;
+
+
+
+// Where information about currently playing grains is stored for drawFunc to access:
+
+granary = ();
+
+
+
+// Add a grain to the granary:
+
+displayGrain = {|pos, pitchRatio, amp, dur, env|
+
+ var time, routine;
+
+
+
+// I've limited it to displaying 30 grains, but I don't see why it couldn't do more.
+
+ if (granary.size < 30, {
+
+
+
+ time = Date.getDate().bootSeconds;
+
+ routine = Routine {
+
+ granary.put(time.asSymbol, [pos, pitchRatio, amp, dur, env]);
+
+ (dur + (env * 2)).wait;
+
+ granary.removeAt(time.asSymbol);
+
+ }.play
+
+ });
+
+};
+
+
+
+grainView.animate = true;
+
+
+
+grainView.drawFunc = {
+
+ var width, height, now, fileDur;
+
+
+
+ width = grainView.bounds.width;
+
+ height = grainView.bounds.height;
+
+ now = Date.getDate().bootSeconds;
+
+ fileDur = soundFile.duration;
+
+
+
+ Pen.fillColor = Color.white;
+
+ Pen.strokeColor = Color.black;
+
+
+
+ granary.keysValuesDo {|k, v|
+
+ var xP, yP, delta, alpha;
+
+
+
+ delta = now - k.asFloat;
+
+ xP = (width * v[0]) + (width * ((delta * v[1]) / fileDur));
+
+ yP = (height * (1 - v[2]));
+
+
+
+ if( delta < (v[3] + v[4]),
+
+ { alpha = (delta/v[4]).clip(0,1) },
+
+ { alpha = 1 - ((delta - (v[3] + v[4])) / v[4]) }
+
+ );
+
+
+
+ Pen.translate(xP, yP); // moveTo doesn't seem to work in this context, so translate...
+
+
+
+ Pen.addOval(Rect(0,0,10,10));
+
+ Pen.alpha = alpha;
+
+ Pen.fillStroke;
+
+
+
+ Pen.translate(xP.neg, yP.neg); // ...and translate back.
+
+ };
+
+};
+
+
+
+// Start the grains:
+
+p = ~playTask.play;
+
+
+
+)
+
+
+
+// Try some different granular parameters:
+
+(
+
+~pos = { rrand(0.3, 0.8) };
+
+~dur = { rrand(0.01, 0.05) };
+
+~env = { 0.02 };
+
+~amp = { rrand(0.2, 0.6) };
+
+~pitch = { rrand(2, 4.0) };
+
+~pan = { rrand(-0.8, 0.8) };
+
+~wait = { 0.01 }; // time between grains
+
+)
+
+
+
+// Or how about these:
+
+(
+
+~pos = { rrand(0, 0.5) };
+
+~dur = { rrand(0.1, 0.2) };
+
+~env = { rrand(0.3, 0.5) };
+
+~amp = { rrand(0.2, 0.8) };
+
+~pitch = { rrand(0.2, 0.7) };
+
+~pan = { rrand(-0.8, 0.8) };
+
+~wait = { 0.1 };
+
+)
+
+
+
+// To stop the grains, close the grain display window or evaluate:
+
+p.stop;
+
View
46 eventscore.sc
@@ -247,6 +247,11 @@
notes: List.new,
book: Dictionary.new,
notequant: nil, // used externally to quantify note time
+ abs_start: 0,
+
+ sort_func: { arg a, b;
+ a.time < b.time;
+ },
add_note: { arg self, note, abstime, num;
var no = note.deepCopy;
@@ -264,10 +269,32 @@
self.book.removeAt(num);
},
+ remove_note: { arg self, num;
+ // warning: old note id returned by add_note will be corrupted
+ self.notes.removeAt(num);
+ },
+
set_start: { arg self, abstime;
self.abs_start = abstime;
},
+ compute_end: { arg self, set=false;
+ var end = 0, tmpno = (sustain:1);
+ self.notes.do { arg no;
+ if(no.time.isNil) {
+ no.debug("ERROR: make_notescore: compute_end: note with time == nil");
+ } {
+ if(end < no.time) {
+ end = no.time;
+ tmpno = no;
+ }
+ }
+ };
+ end = end + tmpno.sustain;
+ if(set) { self.set_end(end); };
+ end;
+ };,
+
set_end: { arg self, abstime;
self.abs_end = abstime;
self.notes.do { arg no;
@@ -306,12 +333,17 @@
var notes, last, end;
start = self.abs_start + start;
end = if(dur.isNil) {
- self.abs_end;
+ if(self.abs_end.isNil) {
+ self.compute_end(false);
+ } {
+ self.abs_end;
+ }
} {
start + dur;
};
// add offset and last dur
- notes = self.notes.select { arg no;
+ notes = self.notes.copy.sort(self[\sort_func]);
+ notes = notes.select { arg no;
no.time >= start and: { no.time <= end }
};
notes = [(
@@ -370,11 +402,17 @@
var notes, last, end;
start = self.abs_start + start;
end = if(dur.isNil) {
- self.abs_end;
+ if(self.abs_end.isNil) {
+ self.compute_end(false);
+ } {
+ self.abs_end;
+ }
} {
start + dur;
};
- notes = self.notes.select { arg no;
+
+ notes = self.notes.copy.sort(self[\sort_func]);
+ notes = notes.select { arg no;
no.time >= start and: { no.time <= end }
};
notes;
View
2 live27.sc
@@ -43,7 +43,7 @@ Mdef.side_gui;
~tf = Pfunc({ arg ev; if(ev[\stepline] == 1) { \note } { \rest } });
~ff = Pfunc({ arg ev; if(ev[\stepline1] == 1) { 1 } { \rest } });
-Debug.enableDebug = true;
+Debug.enableDebug = false;
Mdef.sampledict((
kick0: "0.wav",
kick1: "1.wav",
View
332 live28.sc
@@ -0,0 +1,332 @@
+
+
+
+(
+s.waitForBoot{
+//~seq = Mdef.force_init(true);
+~seq = Mdef.force_init(true);
+~synthlib = [
+ \audiotrack_expander,
+ \lead2,
+ \pulsepass,
+ \flute1,
+ \miaou1,
+ \ringbpf1,
+ \piano2,
+ \pmosc,
+ \monosampler,
+ \stereosampler,
+ \ss_comb,
+ \ss_combfreq,
+].collect({ arg i; i -> i });
+
+~effectlib = [
+ \echo
+].collect({arg i; i -> i });
+
+~samplelib = [
+ "sounds/perc1.wav",
+ "sounds/pok1.wav",
+ "sounds/amen-break.wav",
+ "sounds/default.wav"
+];
+~seq.load_patlib( ~synthlib );
+~seq.load_effectlib( ~effectlib );
+~seq.set_presetlib_path("mypresets2");
+~seq.append_samplelib_from_path("sounds/" );
+~seq.append_samplelib_from_path("sounds/hydrogen/GMkit" );
+~seq.append_samplelib_from_path("sounds/hydrogen/HardElectro1" );
+
+Mdef.side_gui;
+
+
+
+~tf = Pfunc({ arg ev; if(ev[\stepline] == 1) { \note } { \rest } });
+~ff = Pfunc({ arg ev; if(ev[\stepline1] == 1) { 1 } { \rest } });
+
+//Debug.enableDebug = false;
+Debug.enableDebug = true;
+Mdef.sampledict((
+ kick0: "0.wav",
+ kick1: "1.wav",
+ kick2: "2.wav",
+ kick3: "3.wav",
+ kick4: "4.wav",
+ kick5: "5.wav",
+ kick6: "6.wav",
+ kick7: "7.wav",
+ kick8: "8.wav",
+ kick9: "9.wav",
+ kick10: "10.wav",
+ kick11: "11.wav",
+ kick12: "12.wav",
+ kick13: "13.wav",
+ kick14: "14.wav",
+ kick15: "15.wav",
+ kick16: "16.wav",
+ kick17: "17.wav",
+ kick18: "18.wav",
+ kick19: "19.wav",
+ ),
+ "/home/ggz/Musique/recording"
+);
+
+Mdef.samplekit(\deskkick, 20.collect{arg i; "/home/ggz/Musique/recording" +/+ i ++ ".wav"});
+//Mdef.main.samplekit_manager.get_samplekit_bank.keys
+
+~make_perc = { arg prefix, score, base_prefix=nil;
+ var ppar = List.new;
+ var key_list = List.new;
+ if(base_prefix.isNil) { base_prefix = prefix };
+ Mdef.main.node_manager.freeze_gui(true);
+ score.keys.do { arg key;
+
+
+ var name = (prefix++ "_" ++ key).asSymbol;
+ var base_name = (base_prefix++ "_" ++ key).asSymbol;
+ var scorepat = Pbind(
+ \instrument, \stereosampler,
+ \bufnum, score[key].collect({ arg x; if(x > 0) { Mdef.dsample(key) } { Rest() } }),
+ \dur, 0.125,
+ \amp, 1.0
+ );
+ var pat = if(Pdef(base_name).source.notNil) { Pdef(base_name) <> scorepat } { scorepat };
+ ppar.add(pat);
+ Mdef(name++"_score", pat, \stereosampler);
+ key_list.add(name++"_score");
+ };
+ Mdef(prefix++"_line", Ppar(key_list.collect({ arg x; Pdef(x) })));
+ Mdef.main.node_manager.freeze_gui(false);
+ Mdef.show(prefix++"_line");
+ ppar;
+};
+
+}
+)
+
+Debug.enableDebug = false;
+Debug.enableDebug = true;
+
+Mdef.main.save_project("live28");
+Mdef.main.load_project("live28");
+
+
+(
+Instr(\wop, { arg amp=0.1, gate=1, spread=1, pan=0, freq=200, modfratio=0.5, fratio=0.5;
+ var ou;
+ ou = SinOsc.ar(Instr(\oscform).wrap((freq:modfratio*freq))*freq*fratio*[1.6,1,0.99,1.011,1.1]+freq);
+ ou = ou * EnvGen.ar(\adsr.kr(Env.adsr(0.01,0.1,0.8,0.1)),gate,doneAction:2);
+ ou = Splay.ar(ou, spread, amp, pan);
+}).addSynthDef;
+
+Instr(\wopi, { arg amp=0.1, gate=1, spread=1, pan=0, freq=200, modfratio=0.5, fratio=0.5, delay=0;
+ var ou, ou2;
+ ou = SinOsc.ar(Instr(\oscform).wrap((freq:modfratio*freq))*freq*fratio*[1.6,1,0.99,1.011,1.1]+freq);
+ ou2 = CombC.ar(ou,0.3,[0.015,0.03,0.0105],0.14);
+ ou2 = ou2 * EnvGen.ar(Env.dadsr(0.03,0.01,0.1,0.8,0.1),gate,doneAction:2);
+ ou = ou + ou2;
+ ou = ou * EnvGen.ar(\adsr.kr(Env.adsr(0.01,0.1,0.8,0.1)),gate,doneAction:2);
+ ou = Splay.ar(ou, spread, amp, pan);
+ ou = DelayC.ar(ou, delay, delay);
+}).addSynthDef;
+
+Instr(\wopenv, { arg gate=1, freq=200, fmratio=0.5;
+ var ou;
+ var modfratio, fratio;
+ freq = EnvGen.kr(\freq_env.kr(Env.adsr(0.1,0.1,0.8,0.1)), gate) * fmratio * freq + freq;
+ modfratio = EnvGen.kr(\modfratio_env.kr(Env.adsr(0.1,0.1,0.8,0.1)), gate);
+ fratio = EnvGen.kr(\fratio_env.kr(Env.adsr(0.1,0.1,0.8,0.1)), gate);
+ Instr(\wopi).wrap((gate:gate, modfratio:modfratio, fratio:fratio, freq:freq))
+}).addSynthDef;
+)
+~group = Group.new;
+~group.deepFree
+(
+Mdef(\plop0, ~penvcontrol.(Pbind(
+ \instrument, \wopenv,
+ \freq, Pseq([0,0,1,0,1,0,0,0],inf) + [7, 4] * 10,
+ \pfreq_env, Pseq([
+ Env.adsr(0.1,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, Ref(Env([0.6,0.2,0.8,0.1],[0.5,0.1,0.4])),
+ \modfratio_env, [Env.adsr(0.7,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.5,0.75,0.2)],
+ \modfratio, Ref(Env([0.6,0.2,0.8,0.1,0.9,0.1],[0.1,0.5,0.4,0.2,0.8])),
+ \fratio, 1.7,
+ \group, ~group,
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/4,inf),
+ \pamp, Pseq([1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \spread, Pseq([0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \amp, Pkey(\pamp)*0.1
+)));
+);
+
+
+(
+Mdef(\plop1, ~penvcontrol.(Pbind(
+ \instrument, \wopenv,
+ \freq, Pseq([4,2,7,0,1,5,5,8],inf) + [9, 7] * 4,
+ \pfreq_env, Pseq([
+ Env.adsr(0.4,0.1,0.95,0.2),
+ Env.adsr(0.4,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, Ref(Env([0.6,0.2,0.8,0.1],[0.5,0.1,0.4])),
+ \modfratio_env, [Env.adsr(0.1,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.1,0.75,0.2)],
+ \modfratio, Ref(Env([0.1,0.2,0.8,0.1,0.9,0.1],[0.1,0.5,0.4,0.2,0.8])),
+ \fratio, 1.7,
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/4,inf),
+ \pamp, Pseq([1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \spread, Pseq([0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \amp, Pkey(\pamp)*0.1
+)));
+);
+
+(
+Mdef(\plop2, ~penvcontrol.(Pbind(
+ \instrument, \wopenv,
+ //\stut, Pseq([1,1,1,Prand([1,1,1,4]),1,1,1,Prand([1,4])],inf),
+ \stut, 1,
+ \freq, Pstutter(Pkey(\stut),
+ Pseq([4,2,7,0,1,5,5,8],inf) + [4, 1, -1] * 20 * Pseq([1,Prand([\r,1,1]),1,Prand([\r,1])],inf),
+ ),
+ \pfreq_env, Pseq([
+ Env.adsr(0.4,0.1,0.95,0.2),
+ Env.adsr(0.4,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, Ref(Env([0.6,0.2,1.8,0.1,1.2,0.1,1],[0.1,0.1,0.8,0.1,0.9,2])),
+ \modfratio_env, [Env.adsr(0.1,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.4,0.75,0.2)],
+ \modfratio, Ref(Env([0.8,0.4,0.8,0.1,0.9,0.1],[0.1,0.5,0.4,0.2,0.8])),
+ \fratio, 0.7,
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/2,inf) / Pkey(\stut),
+ \pamp, Pseq([1,1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1]/2,inf),
+ \spread, Pseq([1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,0.1,0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \delay, [0,0.03],
+ \amp, Pkey(\pamp)*0.1
+)));
+);
+
+(
+Mdef(\plop3_l1201, ~penvcontrol.(Pbind(
+ \instrument, \wopenv,
+ //\stut, Pseq([1,1,1,Prand([1,1,1,4]),1,1,1,Prand([1,4])],inf),
+ \stut, 1,
+ \freq, Pstutter(Pkey(\stut),
+ Pseq([4,2,7,0,1,5,5,8],inf) + [4, 1, -1] * 20 * Pseq([1,Prand([\r,1,1]),1,Prand([\r,1])],inf),
+ ),
+ \pfreq_env, Pseq([
+ Env.adsr(0.4,0.1,0.95,0.2),
+ Env.adsr(0.4,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, Ref(Env([0.6,0.2,1.8,0.1,1.2,0.1,1],[0.1,0.1,0.8,0.1,0.9,2])),
+ \modfratio_env, [Env.adsr(0.1,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.4,0.75,0.2)],
+ \modfratio, Ref(Env([0.8,0.4,0.8,0.1,0.9,0.1],[0.1,0.5,0.4,0.2,0.8])),
+ \fratio, 0.7,
+ \legato, Pseg(Pseq([1,0],inf),7.4),
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/2,inf) / Pkey(\stut),
+ \pamp, Pseq([1,1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1]/2,inf),
+ \spread, Pseq([1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,0.1,0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \delay, [0,0.03],
+ \amp, Pkey(\pamp)*0.1
+)));
+);
+
+(
+Mdef(\moo, ~penvcontrol.(Pbind(
+ \instrument, \wopenv,
+ //\stut, Pseq([1,1,1,Prand([1,1,1,4]),1,1,1,Prand([1,4])],inf),
+ \stut, 1,
+ \freq, Pstutter(Pkey(\stut),
+ Pseq([14,2,7,10,1,15,7,8],inf) + [4, 1, -1] * 10 * Pseq([1,Prand([\r,1,1]),1,Prand([\r,1])],inf),
+ ),
+ \pfreq_env, Pseq([
+ Env.adsr(0.4,0.1,0.95,0.2),
+ Env.adsr(0.4,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, Ref(Env([0.6,0.2,1.8,0.1,1.2,0.1,1],[0.1,0.1,0.8,0.1,0.9,2])),
+ \modfratio_env, [Env.adsr(0.1,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.4,0.75,0.2)],
+ \modfratio, Ref(Env([0.1,0.4,0.8,0.1,0.9,0.1],[0.1,0.5,0.4,0.2,0.8])),
+ \fratio, 0.7,
+ \legato, Pseg(Pseq([1,0],inf),7.4),
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/4,inf) / Pkey(\stut),
+ \pamp, Pseq([1,1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1]/2,inf),
+ \spread, Pseq([1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,0.1,0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \delay, [0,0.03],
+ \amp, Pkey(\pamp)*0.1
+)));
+);
+
+(
+Mdef(\moo2, ~penvcontrol.(Pbind(
+ \instrument, \wopenv,
+ //\stut, Pseq([1,1,1,Prand([1,1,1,4]),1,1,1,Prand([1,4])],inf),
+ \stut, 1,
+ \freq, Pstutter(Pkey(\stut),
+ Pseq([14,2,7,10,1,15,7,8],inf) + [4, 1, -1] * 10 * Pseq([1,Prand([\r,1,1]),1,Prand([\r,1])],inf),
+ ),
+ \pfreq_env, Pseq([
+ Env.adsr(0.4,0.1,0.95,0.2),
+ Env.adsr(0.4,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, Ref(Env([1.6,0.2,0.8,0.4,1.2,0.1,1],[0.4,0.1,0.5,0.1,0.9,2])),
+ \modfratio_env, [Env.adsr(0.1,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.4,0.75,0.2)],
+ \modfratio, Ref(Env([0.1,0.4,0.8,0.1,0.9,0.1],[0.1,0.5,0.4,0.2,0.8])),
+ \fratio, Ptuple([Prand([0.7,1]),Prand([1,7])],inf),
+ \legato, Pseg(Pseq([1,0],inf),7.4),
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/4,inf) / Pkey(\stut),
+ \pamp, Pseq([1,1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1]/2,inf),
+ \spread, Pseq([1,1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,0.1,0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \delay, [0,0.03],
+ \amp, Pkey(\pamp)*0.1
+)));
+);
+
+
+
+
+
+
+(
+Mdef(\plop0, Pbind(
+ \instrument, \wopenv,
+ \freq, Pseq([0,0,1,0,1,0,0,0],inf) + [7, 4] * 10,
+ \pfreq_env, Pseq([
+ Env.adsr(0.1,0.1,0.05,0.2),
+ Env.adsr(0.7,0.1,0.45,0.2),
+ ],inf),
+ \freq_env, Pfunc{arg in; [ in[\pfreq_env] ] },
+ \fmratio, 0.6,
+ \modfratio_env, [Env.adsr(0.7,0.4,0.75,0.2)],
+ \fratio_env, [Env.adsr(0.7,0.5,0.75,0.2)],
+ \modfratio, 0.6,
+ \fratio, 1.7,
+ \group, ~group,
+ \dur, Pseq([1,1,1,1,1,1,1,1, 1,1,1,1]/4,inf),
+ \pamp, Pseq([1,0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \spread, Pseq([0.91,1,1,1,1,0.9,1, 1.1,1,1,1],inf),
+ \pan, Pseq([0,-0.2,0.91,1,1,1.7,1,0.9,1, 1.1,1,1,1]-1,inf) + (Prand((1,2..100),inf)/500),
+ \amp, Pkey(\pamp)*0.1
+));
+);
View
2 main.sc
@@ -219,6 +219,7 @@
pgroup.addDependant( { arg grp, status;
if(status == \n_end) {
"fin!!".debug;
+ pgroup.releaseDependants;
blist.do(_.free)
}
});
@@ -324,6 +325,7 @@
"mixer",
"score",
"sidematrix",
+ "timeline",
"side",
].do { arg file;
("Loading " ++ file ++".sc...").inform;
View
179 matrix.sc
@@ -32,11 +32,13 @@
})
};
-~matrix_view = { arg parent, controller;
+~matrix_view = { arg parent, controller, matrix_size;
var sl_layout, ps_col_layout, curbank, address;
var width = 1350;
+ matrix_size = matrix_size ?? 8@4;
+
sl_layout = GUI.hLayoutView.new(parent, Rect(0,0,width,60*6));
//parent.view.background = ~editplayer_color_scheme.background;
@@ -46,7 +48,7 @@
controller.model.debug("rederaw");
sl_layout.removeAll;
sl_layout.focus(true);
- controller.model.datalist.clump(4).clump(8)[controller.model.bank].do { arg col;
+ controller.model.datalist.clump(matrix_size.y).clump(matrix_size.x)[controller.model.bank].do { arg col;
ps_col_layout = GUI.vLayoutView.new(sl_layout, Rect(0,0,(160),60*6));
ps_col_layout.background = ~editplayer_color_scheme.control;
@@ -108,13 +110,18 @@
model: (
datalist: [],
selection: nil,
- bank: 0
+ bank: 0,
+ matrix_size: 8@4,
),
kb_handler: Dictionary.new,
address_to_index: { arg self, ad;
- (ad.bank * 32) + (ad.x * 4) + ad.y;
+ self.coor_to_index(ad.x, ad.y, ad.bank);
+ },
+
+ coor_to_index: { arg self, x, y, bank;
+ (bank * self.model.matrix_size.x * self.model.matrix_size.y) + (x * self.model.matrix_size.y) + y;
},
refresh: { arg self;
@@ -133,11 +140,11 @@
},
get_cell_xy: { arg self, x, y;
- self.model.datalist[ (self.model.bank * 32) + (x * 4) + y ];
+ self.model.datalist[ self.coor_to_index(x, y, self.model.bank) ];
},
get_cell_by_address: { arg self, ad;
- self.model.datalist[ (ad.bank * 32) + (ad.x * 4) + ad.y ];
+ self.model.datalist[ self.address_to_index(ad) ];
},
get_selected_cell: { arg self;
@@ -217,7 +224,7 @@
show_window: { arg self;
- ~matrix_view.(self.window, self);
+ ~matrix_view.(self.window, self, self.model.matrix_size);
self.window.front;
},
@@ -247,6 +254,105 @@
);
+~class_sample_chooser = (
+ parent: ~class_matrix_chooser,
+ new: { arg self, main, action, samplekit=\default, player, group, param_name=\bufnum;
+ var samplelist = List.new;
+ self = self.parent[\new].(self, action, "Choose sample");
+
+ self.samples = Dictionary.new;
+ self.get_main = { arg self; main };
+ self.player = player;
+ self.nodegroup = group;
+ self.nodegroup.identityHash.debug("class_sample_chooser: init: nodegroup: identityHash");
+ self.param_name = param_name;
+
+ main.samplekit_manager.get_samplelist_from_samplekit(samplekit).do { arg sam;
+ self.samples[PathName.new(sam).fileName] = sam;
+ samplelist.add(PathName.new(sam).fileName);
+ };
+ self.set_datalist( samplelist );
+ self.show_window;
+ self;
+ },
+
+ selected: { arg self, sel, win, address;
+ sel.debug("selected");
+ if(self.oldsel == sel, {
+ self[\action].(self.samples[sel]);
+ win.close;
+ }, {
+ self.oldsel = sel;
+ });
+ },
+
+ play_selection: { arg self, sel, win, ad;
+ var pl;
+ //pl = main.get_node(main.model.presetlib[defname][sl.address_to_index(ad)]);
+ [self.samples[sel], sel].debug("play_selection: sel");
+ {
+ var buf;
+ buf = Buffer.read(s, self.samples[sel]);
+ s.sync;
+ //TODO: use player.vpiano
+ Synth(\monosampler, [\bufnum, buf, \amp, self.player.get_arg(\amp).get_val]).onFree {
+ buf.free;
+ };
+ }.fork;
+ },
+
+ create_batch: { arg self;
+ var sel = self.get_selected_cell;
+ var newnode;
+ self.nodegroup.identityHash.debug("class_sample_chooser: nodegroup: identityHash");
+ newnode = self.get_main.node_manager.duplicate_livenode(self.player.uname);
+ self.get_main.get_node(newnode).get_arg(self.param_name).set_val(self.samples[sel]);
+ self.nodegroup.add_children(newnode);
+ self.nodegroup.uname.debug("class_sample_chooser: create_batch: nodegroup");
+ }
+
+);
+
+~class_node_chooser = (
+ parent: ~class_matrix_chooser,
+
+ new: { arg self, main, action;
+ self = self.parent[\new].(self, action, "Choose samplekit");
+
+ self.model.part_bank = 0;
+ self.model.section_bank = 0;
+ self.model.matrix_size = 8@8;
+ self.get_main = { arg self; main };
+ self.update_datalist;
+ self.show_window;
+ self;
+ },
+
+ selected: { arg self, sel, win, address;
+ sel.dump.debug("selected");
+ if(sel != "" and: {self.oldsel == sel}) {
+ self[\action].(sel);
+ win.close;
+ } {
+ self.oldsel = sel;
+ };
+ },
+
+ set_bank: { arg self, idx;
+ self.model.section_bank = idx;
+ self.update_datalist;
+ self.changed(\redraw);
+ },
+
+ update_datalist: { arg self;
+ self.set_datalist(
+ self.get_main.panels.side.song_manager.get_section_matrix(self.model.part_bank,self.model.section_bank)
+ .collect{ arg name; if(name == \voidplayer) { "" } {name} }
+ );
+ },
+);
+
+/////////////////////// old matrix code
~make_matrix = { arg main, callbacks, winname="Matrix";
@@ -517,65 +623,6 @@
sl.show_window;
};
-~class_sample_chooser = (
- parent: ~class_matrix_chooser,
- new: { arg self, main, action, samplekit=\default, player, group, param_name=\bufnum;
- var samplelist = List.new;
- self = self.parent[\new].(self, action, "Choose sample");
-
- self.samples = Dictionary.new;
- self.get_main = { arg self; main };
- self.player = player;
- self.nodegroup = group;
- self.nodegroup.identityHash.debug("class_sample_chooser: init: nodegroup: identityHash");
- self.param_name = param_name;
-
- main.samplekit_manager.get_samplelist_from_samplekit(samplekit).do { arg sam;
- self.samples[PathName.new(sam).fileName] = sam;
- samplelist.add(PathName.new(sam).fileName);
- };
- self.set_datalist( samplelist );
- self.show_window;
- self;
- },
-
- selected: { arg self, sel, win, address;
- sel.debug("selected");
- if(self.oldsel == sel, {
- self[\action].(self.samples[sel]);
- win.close;
- }, {
- self.oldsel = sel;
- });
- },
-
- play_selection: { arg self, sel, win, ad;
- var pl;
- //pl = main.get_node(main.model.presetlib[defname][sl.address_to_index(ad)]);
- [self.samples[sel], sel].debug("play_selection: sel");
- {
- var buf;
- buf = Buffer.read(s, self.samples[sel]);
- s.sync;
- //TODO: use player.vpiano
- Synth(\monosampler, [\bufnum, buf, \amp, self.player.get_arg(\amp).get_val]).onFree {
- buf.free;
- };
- }.fork;
- },
-
- create_batch: { arg self;
- var sel = self.get_selected_cell;
- var newnode;
- self.nodegroup.identityHash.debug("class_sample_chooser: nodegroup: identityHash");
- newnode = self.get_main.node_manager.duplicate_livenode(self.player.uname);
- self.get_main.get_node(newnode).get_arg(self.param_name).set_val(self.samples[sel]);
- self.nodegroup.add_children(newnode);
- self.nodegroup.uname.debug("class_sample_chooser: create_batch: nodegroup");
- }
-
-);
-
~choose_sample = { arg main, action, samplekit;
var sl;
var callbacks;
View
127 node_manager.sc
@@ -319,10 +319,25 @@
});
},
+ cut_node: { arg self, node;
+ var uname, address;
+ uname = node.uname;
+ uname.debug("cuted node1");
+ main.model.clipboard_action_kind = \cut;
+ if(uname == \void || (uname == \voidplayer)) {
+ "Can't cut empty player".error;
+ } {
+ uname.debug("cuted node2");
+ main.model.clipboard = uname;
+ main.model.clipboard.debug("cuted node");
+ };
+ },
+
copy_node: { arg self, node;
var uname, address;
uname = node.uname;
uname.debug("copied node1");
+ main.model.clipboard_action_kind = \copy;
if(uname == \void || (uname == \voidplayer)) {
"Can't copy empty player".error;
} {
@@ -338,12 +353,18 @@
"Can't paste: clipboard is empty".error;
} {
node = main.get_node(main.model.clipboard);
- if( node.kind == \player ) {
- self.duplicate_livenode(main.model.clipboard);
+ if(main.model.clipboard_action_kind == \copy) {
+
+ if( node.kind == \player ) {
+ self.duplicate_livenode(main.model.clipboard);
+ } {
+ "paste_node: paste groupnode: not implemented".debug;
+ nil;
+ };
} {
- "paste_node: paste groupnode: not implemented".debug;
- nil;
- };
+ // cut paste
+ main.model.clipboard
+ }
};
},
@@ -583,6 +604,42 @@
res; // return real nodes (not names)
};
+~exclusive_play_set = {
+ (
+ set_dict: ~setDictionary.(),
+
+ add_expset: { arg self, name, list;
+ self.set_dict.bind_set(name, list);
+ },
+
+ del_expset: { arg self, name;
+ self.set_dict.unbind_key(name);
+ },
+
+ get_expsets_by_member: { arg self, mname;
+ self.set_dict.get_keys_by_val(mname);
+ },
+
+ get_nodes_to_stop: { arg self, mname, nodes;
+ var expsets, members = Set.new;
+ expsets = self.get_expsets_by_member(mname);
+ expsets.debug("expsets");
+ expsets.do { arg ex;
+ members = members.union(self.set_dict.get_vals_by_key(ex));
+ };
+ members.debug("members");
+ if(members.notNil) {
+ members.remove(mname);
+ members.sect(nodes);
+ } {
+ Set.new
+ }
+ },
+
+ )
+};
+
+
~make_playmanager = { arg main;
var obj;
@@ -844,7 +901,12 @@
node.node.source = node.vpattern_loop;
quant = if(self.is_playing) { self.get_quant } { 1 };
node.node.play(self.get_clock,quant:quant);
+
node.set_playing_state(\play);
+ children.do { arg child;
+ child.set_playing_state(\play);
+ };
+
// registering
@@ -981,12 +1043,13 @@
self.get_path([nil,nil,nil]);
},
- unvoid_child: { arg self, group, childname, index, pathlevel, prefix;
+ unvoid_child: { arg self, group, childname, index, pathlevel, prefix, path;
var newgroup;
childname.debug("unvoid_child");
if(childname == \voidplayer) {
newgroup = main.node_manager.make_groupplayer((prefix ++ index).asSymbol, self.type_tree[pathlevel]);
newgroup.uname.debug("---------- unvoid_child: CREATING new group uname");
+ newgroup.song_path = path[..pathlevel];
group.set_children_name(index-1, newgroup.uname);
[group.uname, group.children, index].debug("unvoid_child: group, children, index");
newgroup;
@@ -995,7 +1058,7 @@
};
},
- get_child: { arg self, group, index, pathlevel, prefix, select=false;
+ get_child: { arg self, group, index, pathlevel, prefix, select=false, path;
var newgroup;
if(index.notNil) {
if(index == 0) {
@@ -1004,10 +1067,34 @@
if(select) {
group.set_selected_child_index(index-1);
};
- self.unvoid_child(group, group.get_childname_by_index(index-1), index, pathlevel, prefix);
+ self.unvoid_child(group, group.get_childname_by_index(index-1), index, pathlevel, prefix, path);
}
} {
- self.unvoid_child(group, group.get_selected_childname, group.selected_child_index+1, pathlevel, prefix);
+ self.unvoid_child(group, group.get_selected_childname, group.selected_child_index+1, pathlevel, prefix, path);
+ }
+ },
+
+ get_section_matrix: { arg self, part_index, section_index;
+ var part, section;
+ var res;
+ part = self.current_song.get_childname_by_index(part_index);
+ if(part == \voidplayer) {
+ res = \voidplayer!8
+ } {
+ section = main.get_node(part).get_childname_by_index(section_index);
+ if(section == \voidplayer) {
+ res = \voidplayer!8
+ } {
+ res = List.new;
+ main.get_node(section).children.atSeries(0,1,7).do { arg variant;
+ if(variant != \voidplayer and: {main.node_exists(variant)}){
+ res.add(main.get_node(variant).debug("variant").children.atSeries(0,1,7))
+ } {
+ res.add(\voidplayer!8) // FIXME: hardcoded
+ }
+ };
+ res.flop.flatNoString;
+ }
}
},
@@ -1026,7 +1113,7 @@
pathlevel = pathlevel + 1;
prefix = prefix ++ "_" ++ self.name_tree[pathlevel];
old_group = current_group;
- current_group = self.get_child(current_group, index, pathlevel, prefix, select);
+ current_group = self.get_child(current_group, index, pathlevel, prefix, select, path);
prefix = prefix ++ (old_group.selected_child_index + 1);
}
};
@@ -1081,6 +1168,26 @@
self.print_tree_helper(main.get_node(childname), level);
}
}
+ },
+
+ /////// expset
+
+ update_expset: { arg self, index;
+ var section;
+ var name;
+ var list = List.new;
+ section = self.get_path([nil, nil, 0]);
+ name = (section.uname ++ "_expset" ++ index).asSymbol;
+ section.children.do { arg child;
+ var nodename;
+ if(child != \voidplayer) {
+ nodename = main.get_node(child).get_childname_by_index(index);
+ if(nodename.notNil and: {nodename != \voidplayer}) {
+ list.add(nodename);
+ }
+ }
+ };
+ main.play_manager.expset_manager.add_expset(name, list);
}
)
View
141 player.sc
@@ -177,6 +177,22 @@
main
},
+ destructor: { arg self;
+ // FIXME: implement it correctly
+ self.to_destruct.do { arg i;
+ i.destructor;
+ }
+ },
+
+ clone: { arg self;
+ var pl;
+ pl = ~make_player_from_synthdef.(main,defname);
+ pl.load_data( self.save_data.deepCopy );
+ pl;
+ },
+
+ ////////////////// effects
+
set_effects: { arg self, fxlist;
self.effects = fxlist.reject({arg fx; main.node_exists(fx).not }).asList;
self.build_real_sourcepat;
@@ -192,7 +208,10 @@
self.effects;
},
+ ////////////////// playing state
+
set_playing_state: { arg self, state;
+ [self.uname, state].debug("player: set_playing_state");
self.playing_state = state;
self.changed(\redraw_node);
},
@@ -214,6 +233,7 @@
)
},
+ ////////////////// live playing
get_piano: { arg self, kind=\normal;
var exclu, list = List[];
@@ -277,12 +297,7 @@
},
- destructor: { arg self;
- // FIXME: implement it correctly
- self.to_destruct.do { arg i;
- i.destructor;
- }
- },
+ ////////////////// wrapper
edit_wrapper: { arg self;
var tmp, file;
@@ -329,6 +344,8 @@
};
},
+ ////////////////// mode
+
set_mode: { arg self, val;
if(self.current_mode != val) {
if(val == \sampleline && (self.get_arg(\sampleline).isNil)) {
@@ -351,16 +368,43 @@
self.defname.asString.beginsWith("audiotrack")
},
- clone: { arg self;
- var pl;
- pl = ~make_player_from_synthdef.(main,defname);
- pl.load_data( self.save_data.deepCopy );
- pl;
+ set_env_mode: { arg self, val = true;
+ self.env_mode = val;
+ self.env_mode.debug("SET ENV MODE!!!");
+ self.build_real_sourcepat; // FIXME: already called just before setting env_mode (at init)
+ },
+
+ ////////////////// params
+
+ select_param: { arg self, name;
+ var oldsel;
+ if( self.get_arg(name).notNil ) {
+ oldsel = self.selected_param;
+ name.debug("player selected_param");
+ self.selected_param = name;
+ self.get_arg(oldsel).changed(\selected);
+ self.get_arg(name).changed(\selected);
+ } {
+ [self.uname, name].debug("can't select param: not found");
+ }
+ },
+
+ get_selected_param: { arg self;
+ self.selected_param;
+ },
+
+ get_selected_param_object: { arg self;
+ self.get_arg(self.selected_param);
},
+
+ get_raw_arg: ~player_get_arg,
+ set_arg: ~player_set_arg,
+
map_arg: { arg self, argName, val;
argName.debug("mapping hidden!!!");
~get_spec.(argName, defname).map(val);
},
+
unmap_arg: { arg self, argName, val;
~get_spec.(argName, defname).unmap(val);
},
@@ -406,6 +450,13 @@
self.bank;
},
+ get_duration: { arg self;
+ // TODO: return correct value for others modes
+ self.get_arg(\stepline).get_cells.size * self.get_arg(\dur).get_val
+ },
+
+ ////////////////// save/load
+
save_data: { arg self;
var argdat;
var data = ();
@@ -488,6 +539,8 @@
ev;
},
+ ////////////////// automation
+
add_ccbus: { arg self, param;
// a param is on recordbus mode, so include a pattern to set the bus while playing
var vpat;
@@ -501,6 +554,8 @@
self.build_real_sourcepat;
},
+ ////////////////// pattern
+
set_input_pattern: { arg self, pat;
if(self.input_pattern.isNil) {
self.input_pattern = EventPatternProxy.new;
@@ -511,12 +566,6 @@
}
},
- set_env_mode: { arg self, val = true;
- self.env_mode = val;
- self.env_mode.debug("SET ENV MODE!!!");
- self.build_real_sourcepat; // FIXME: already called just before setting env_mode (at init)
- },
-
build_real_sourcepat: { arg self;
var res, list;
var chain;
@@ -631,29 +680,6 @@
};
},
- select_param: { arg self, name;
- var oldsel;
- if( self.get_arg(name).notNil ) {
- oldsel = self.selected_param;
- name.debug("player selected_param");
- self.selected_param = name;
- self.get_arg(oldsel).changed(\selected);
- self.get_arg(name).changed(\selected);
- } {
- [self.uname, name].debug("can't select param: not found");
- }
- },
-
- get_selected_param: { arg self;
- self.selected_param;
- },
-
- get_selected_param_object: { arg self;
- self.get_arg(self.selected_param);
- },
-
- get_raw_arg: ~player_get_arg,
- set_arg: ~player_set_arg
);
player.init;
@@ -1530,41 +1556,6 @@
};
-~exclusive_play_set = {
- (
- set_dict: ~setDictionary.(),
-
- add_expset: { arg self, name, list;
- self.set_dict.bind_set(name, list);
- },
-
- del_expset: { arg self, name;
- self.set_dict.unbind_key(name);
- },
-
- get_expsets_by_member: { arg self, mname;
- self.set_dict.get_keys_by_val(mname);
- },
-
- get_nodes_to_stop: { arg self, mname, nodes;
- var expsets, members = Set.new;
- expsets = self.get_expsets_by_member(mname);
- expsets.debug("expsets");
- expsets.do { arg ex;
- members = members.union(self.set_dict.get_vals_by_key(ex));
- };
- members.debug("members");
- if(members.notNil) {
- members.remove(mname);
- members.sect(nodes);
- } {
- Set.new
- }
- },
-
- )
-};
-
//a = ~exclusive_play_set.()
//
//a.add_expset(\perc, [\kick1, \snare1, \hihat])
View
45 side.sc
@@ -371,7 +371,7 @@
]);
"class_player_view: new: after making responder".debug;
- //self;
+ self;
},
////// main responders
@@ -397,7 +397,7 @@
self.player_responder.remove;
"class_player_view: player: before making responder".debug;
self.player_responder = ~make_class_responder.(self, self.vlayout, player, [
- \mode, \redraw_node,
+ \mode,
]);
"class_player_view: player: after making responder".debug;
self.paramlist;
@@ -497,12 +497,6 @@
self.extparamlist;
},
- redraw_node: { arg self, obj;
- var player;
- "class_player_view: player: redraw_node".debug;
- player = self.current_player;
- player.get_arg(\amp).changed(\playingstate, player.name, player.get_playing_state);
- },
);
~class_groupnode_view = (
@@ -571,6 +565,7 @@
group = self.current_group;
children = group.get_children_and_void;
+ self.children_responder.do{_.remove};
self.mini_param_group_widget.paramview_list.do { arg groupview, x; // FIXME: hardcoded
var child = children[x];
var is_empty = false;
@@ -584,6 +579,10 @@
display = controller.make_param_display(amp, child);
display.set_parent_group(group);
groupview.set_group_param(child, amp, display);
+
+ self.children_responder.add(~make_class_responder.(self, self.vlayout, child, [
+ \redraw_node,
+ ]));
} {
groupview.clear_view;
};
@@ -616,6 +615,15 @@
}
},
+
+ ///// children responders
+
+ redraw_node: { arg self, obj;
+ var player;
+ player = obj;
+ player.uname.debug("class_player_view: player: redraw_node");
+ player.get_arg(\amp).changed(\playingstate, player.name, player.get_playing_state);
+ },
);
~class_groupnode_matrix_view = (
@@ -1445,6 +1453,9 @@
var supergroup;
var current_group;
+ self.timeline = ~class_timeline.new(main);
+ 8.do { arg i; self.timeline.add_track("Track "++i);};
+
self.song_manager = ~make_song_manager.(main);
current_group = self.song_manager.get_current_group;
@@ -1471,6 +1482,11 @@
main.commands.parse_action_bindings(\side, [
+
+ [\open_timeline, {
+ self.timeline.make_gui;
+ }],
+
///////// macro
[\add_sample_batch, {
@@ -1553,6 +1569,7 @@
}],
[\play_selected, {
+ self.song_manager.update_expset(self.get_current_group.selected_child_index);
self.get_current_player.play_node;
}],
@@ -1680,6 +1697,12 @@
self.remove_current_player;
}],
+ [\cut_node, {
+ var player = self.get_current_player;
+ main.node_manager.cut_node(player);
+ self.remove_current_player;
+ }],
+
[\copy_node, {
var player = self.get_current_player;
main.node_manager.copy_node(player);
@@ -1694,8 +1717,10 @@
var group = self.get_current_group;
var nodename;
nodename = main.node_manager.paste_node(player);
- group.set_selected_child(nodename);
- self.set_current_player(main.get_node(nodename));
+ if(nodename.notNil) {
+ group.set_selected_child(nodename);
+ self.set_current_player(main.get_node(nodename));
+ };
}],
[\load_node_from_lib, {
View
25 synthlab.sc
@@ -132,7 +132,7 @@ Ndef(\noiseenvir).set(\low, 1000, \high, 3000); // rain
Ndef(\noiseenvir).set(\low, 500, \high, 1000); // river
Ndef(\noiseenvir).set(\low, 250, \high, 500); // train cabin
Ndef(\noiseenvir).set(\low, 50, \high, 250); // thunder
-Ndef(\noiseenvir).set(\low, 0, \high, 50); // explosion rumble
+Ndef(\noiseenvir).set(\low, 1, \high, 50); // explosion rumble
// effect idea: process higher frequency differently than lower ones
@@ -416,3 +416,26 @@ Pdef(\saaa, Pbind(
\amp, 0.1
)).play;
)
+
+
+(
+Instr(\noiseman, { arg amp=0.1, gate=1, pan=0, freq=200;
+ var ou;
+ ou = WhiteNoise.ar(1);
+ ou = DynKlank.ar(`[[100,200,300,400,500],{1.0.rand}!5,{1.0.rand+0.001}!5],ou, LFNoise1.ar(5).range(0.9,1.1), LFNoise1.ar(5).range(1,101)) /8;
+ ou = LPF.ar(ou, 1500);
+ ou = HPF.ar(ou, 150);
+ ou = ou * EnvGen.ar(\adsr.kr(Env.adsr(0.01,0.1,0.8,0.1)),gate,doneAction:2);
+ ou = Pan2.ar(ou, pan, amp);
+}).addSynthDef;
+)
+
+
+(
+Pdef(\plop, Pbind(
+ \instrument, \noiseman,
+ \degree, Pseq([0],inf),
+ \dur, 1,
+ \amp, 0.1
+)).play;
+);
View
522 timeline.sc
@@ -0,0 +1,522 @@
+// TODO:
+// - keyboard shortcuts
+// - play/stop
+// - banks
+// - node_chooser banks
+// - solo/mute buttons
+// - add block shortcut
+// - current playing cursor
+// - stop cursor
+// - pause_cursor
+// - get block size from node
+
+
+~class_timerule_view = (
+
+ new: { arg self, parent, controller, header_size_x, beat_size_x=10, view_size;
+ self = self.deepCopy;
+
+ self.view_size = view_size ?? 800@30;
+ self.parent = parent;
+ self.header_size_x = header_size_x;
+
+ self.controller = controller;
+ self.beat_size_x = beat_size_x;
+ self.main_responder = ~make_class_responder.(self, self.parent, controller, [
+ \play_cursor,
+ ], false);
+
+ self.make_gui;
+
+ self;
+ },
+
+ make_gui: { arg self;
+
+ var beat_size_x = self.beat_size_x;
+ var width = self.view_size.x;
+ var height = self.view_size.y;
+ self.view = UserView.new(self.parent, Rect(self.header_size_x, 0, width, height));
+ self.view.drawFunc = {
+
+ Pen.color = Color.red;
+ Pen.line((self.controller.play_cursor*beat_size_x)@0, (self.controller.play_cursor*beat_size_x)@height);
+ Pen.stroke;
+
+ (width/beat_size_x).asInteger.do{|i|
+ Pen.color = Color.black;
+ case
+ { i%32==0 } {
+ Pen.color = Color.blue;
+ Pen.line((i*beat_size_x)@0, (i*beat_size_x)@height); Pen.stroke
+ }
+ { i%8==0 } {
+
+ Pen.line((i*beat_size_x)@0, (i*beat_size_x)@height); Pen.stroke
+ }
+ { i%4==0 } {
+
+ Pen.line((i*beat_size_x)@(height/2), (i*beat_size_x)@height); Pen.stroke
+ }
+ //
+ {
+ Pen.line((i*beat_size_x)@(3*height/4), (i*beat_size_x)@height); Pen.stroke
+ }
+
+
+ };
+ };
+ },
+
+ play_cursor: { arg self, controller;
+ controller = controller ?? self.controller;
+ self.view.refresh;
+
+ }
+
+);
+
+~class_timeline_view = (
+
+ block_top_padding: {arg self; self.track_size_y/10},
+ track_size_x: 800,
+ track_size_y: 30,
+ beat_size_x: 10,
+ block_size_y: 25,
+ header_size_x: 100,
+ timerule_size: 1234@1234,
+
+ block_dict: Dictionary.new, // spritenum -> block_index
+ track_dict: Dictionary.new, // spritenum -> track_index
+
+ current_selected_track: 0,
+
+ new: { arg self, controller;
+ self = self.deepCopy;
+
+ debug("class_timeline_view.new");
+ self.controller = controller;
+ self.make_gui;
+ self.main_responder = ~make_class_responder.(self, self.window.view, controller, [
+ \tracks, \blocks, \redraw, \insert_cursor,
+ ]);
+ self;
+ },
+
+ make_gui: { arg self;
+
+ self.timerule_size = (self.track_size_x+20+self.header_size_x)@(self.track_size_y-4);
+
+ self.window = Window.new("Timeline", Rect(10, 500,
+ self.track_size_x+20+self.header_size_x,
+ self.track_size_y*(self.controller.tracks.size+1)+10+self.timerule_size.y
+ ));
+ self.window.view.keyDownAction = self.controller.get_main.commands.get_kb_responder(\timeline);
+ self.tracks(self.controller);
+ self.window.front;
+ self.window;
+
+ },
+
+ // responders
+
+ tracks: { arg self, controller;
+ var tl;
+ var stext;
+ controller = controller ?? self.controller;
+
+ debug("timeline_view.tracks");
+
+ self.layout.remove;
+ self.layout = HLayoutView.new(self.window, Rect(0, 0,
+ self.track_size_x+10 + self.header_size_x,
+ self.track_size_y*( controller.tracks.size+1 )
+ ));
+
+ self.headerlayout = VLayoutView.new(self.layout, Rect(0, 0, self.header_size_x+5, self.track_size_y*(controller.tracks.size+1)));
+
+ stext = StaticText.new(self.headerlayout, Rect(0,0,self.header_size_x,self.track_size_y-4));
+ stext.background = Color.white;
+ stext.string = "timerule";
+
+ debug("timeline_view.tracks2");
+
+ self.track_headers = controller.tracks.collect { arg track;
+ stext = StaticText.new(self.headerlayout, Rect(0,0,self.header_size_x,self.track_size_y-4));
+ if(controller.current_track == i) {
+
+ } {
+
+ };
+ debug("timeline_view.tracks2 1");
+ stext.background = Color.gray(0.5);
+ stext.string = track.name.asString;
+ stext;
+ };
+
+ debug("timeline_view.tracks2 2");
+
+ self.vlayout = VLayoutView.new(self.layout, Rect(0,0,
+ self.track_size_x+10 + self.header_size_x,
+ self.track_size_y*(self.controller.tracks.size+1)+10+self.timerule_size.y
+ ));
+ self.timerule_view = ~class_timerule_view.new(self.vlayout, self.controller, self.header_size_x, self.beat_size_x, self.timerule_size);
+
+ debug("timeline_view.tracks2 3");
+
+ self.timeline = ParaTimeline.new(self.vlayout, bounds: Rect(20, 20, self.track_size_x, self.track_size_y * controller.tracks.size));
+ self.timeline.keyDownAction = self.controller.get_main.commands.get_kb_responder(\timeline);
+
+ debug("timeline_view.tracks2 4");
+ self.timeline.mouseDownAction = { arg view, x, y, modifiers, buttonNumber, clickCount;
+ var pos_x = (x/self.beat_size_x).asInteger;
+ var pos_y = (y/self.track_size_y).asInteger;
+ buttonNumber.debug("class_timeline_view: tracks: buttonNumber");
+ if( (modifiers & 0x00040000) != 0) { // == 262401 == ctrl
+ self.controller.add_block_from_lib(pos_y, pos_x);
+
+ } {
+ switch(buttonNumber,
+ 3, {
+ self.controller.set_start_cursor(pos_x);
+ },
+ 1, {
+ //self.controller.set_insert_cursor(pos_x, pos_y);
+ }
+ );
+ }
+ };
+ debug("timeline_view.tracks2 5");
+ self.blocks(controller);
+ debug("timeline_view.tracks2 6");
+
+ tl = self.timeline;
+
+ debug("timeline_view.tracks 3");
+
+ tl.nodeTrackAction_({arg node;
+ var old_track_index, new_track_index, old_block_index, new_block_time;
+ var newx, newy;
+
+ newx = tl.getNodeLoc(node.spritenum)[0].trunc(self.beat_size_x);
+ newy = tl.getNodeLoc(node.spritenum)[1].trunc(self.track_size_y) + self.block_top_padding;
+ //newx = tl.getNodeLoc(node.spritenum)[0].round(self.beat_size_x);
+ //newy = tl.getNodeLoc(node.spritenum)[1].round(self.track_size_y) + self.block_top_padding;
+
+ new_track_index = ( tl.getNodeLoc(node.spritenum)[1].trunc(self.track_size_y)/self.track_size_y ).asInteger;
+ new_block_time = ( tl.getNodeLoc(node.spritenum)[0].trunc(self.beat_size_x)/self.beat_size_x ).asInteger;
+
+ controller.timeline_score.move_block(self.block_dict[node.spritenum], new_track_index, new_block_time);
+ tl.setNodeLoc_( node.spritenum, newx, newy );
+
+ });
+
+ self.timeline.setBackgrDrawFunc_({
+ // play cursor
+ var cursors_pos;
+ //cursors_pos = (TempoClock.default.beats % 32 / 32 * self.track_size_x).asInteger;
+ cursors_pos = self.controller.start_cursor*self.beat_size_x;
+ Pen.color = Color.red;
+ Pen.line(cursors_pos@0, cursors_pos@( self.track_size_y*controller.tracks.size )); Pen.stroke;
+
+ // x lines
+ (self.track_size_x/self.beat_size_x).asInteger.do{|i|
+ Pen.color = if(i%8==0) {
+ Color.gray(0.2);
+ } {
+ Color.gray(0.8);
+ };
+ Pen.line((i*self.beat_size_x)@0, (i*self.beat_size_x)@( self.track_size_y*controller.tracks.size )); Pen.stroke
+ };
+
+ // y lines
+ controller.tracks.size.do{|i|
+ Pen.color = Color.gray(0.2);
+ Pen.line(0@(i*self.track_size_y), self.track_size_x@(i*self.track_size_y)); Pen.stroke
+ };
+
+ });
+ self.window.view.focus(true);
+ debug("timeline_view.tracks end");
+
+ },
+
+ blocks: { arg self, controller;
+ var spritenum = 0;
+ debug("timeline_view: blocks");
+ self.timeline.clearSpace;
+ self.block_dict = Dictionary.new;
+ controller.get_blocks.do { arg block, i;
+ [spritenum, block].debug("timeline_view: blocks: creating block");
+
+ self.timeline.createNode(block.time*self.beat_size_x, block.track_index*self.track_size_y+self.block_top_padding);
+ self.timeline.setNodeString_(spritenum, block.nodename.asString);
+ self.timeline.setNodeSize_(spritenum, self.block_size_y);
+ self.timeline.paraNodes[spritenum].setLen = block.sustain * self.beat_size_x;
+
+ self.block_dict[spritenum] = block;
+
+ spritenum = spritenum + 1;
+ }
+
+ },
+
+ redraw: { arg self, controller;
+ self.tracks;
+ },
+
+ //insert_cursor: { arg self, controller;
+ // self.track_headers[self.current_selected_track].background = Color.gray(0.5);
+ // self.track_headers[controller.current_track].background = Color.blue;
+ // self.current_selected_track = controller.current_track;
+ //},
+
+);
+
+~class_timeline_score = (
+
+ parent: ~make_notescore.(),
+ tracks: List.new,
+
+ new: { arg self, main;
+ self = self.deepCopy;
+
+ self.get_main = { arg self; main };
+ self;
+ },
+
+ add_track: { arg self, name="new track";
+ var track;
+ track = (name:name, number:self.tracks.size);
+ self.tracks.add( track );
+ self.changed(\tracks);
+ track;
+ },
+
+ add_block: { arg self, blockname, track_index, abstime;
+ var block, id;
+ block = ();
+ block.time = abstime;
+ block.nodename = blockname;
+ block.track_index = track_index;
+ block.sustain = 8;
+ self.notes.add(block);
+ id = block.identityHash;
+ self.changed(\blocks);
+ id;
+ },
+
+ move_block: { arg self, block, new_track_index, new_block_time;
+ var old_block, new_block_index;
+ [ block, new_track_index, new_block_time ].debug("class_timeline.move_block: block, new_track_index, new_block_time");
+ block.track_index = new_track_index;
+ block.time = new_block_time;
+
+ },
+
+ filter_by_track_index: { arg self, track_index;
+ var res = self.deepCopy;
+ //[slotnum, res.notes].debug("filter_by_slot: before");
+ res.notes = res.notes.select { arg no;
+ no.track_index == track_index
+ };
+ //res.notes.debug("filter_by_slot: after");
+ res;
+ },
+
+);
+
+~class_player = (
+
+ uname: nil,
+ name: nil,
+ node: EventPatternProxy.new,
+ kind: \player, // should be classtype, but backward compat...
+ sourcepat: nil,
+ selected_param: \stepline,
+ playing_state: \stop,
+ muted: false,
+ archive_param_data: [\control, \stepline, \adsr, \noteline, \nodeline, \sampleline, \buf],
+ archive_data: [\current_mode, \effects],
+
+ new: { arg self, main;
+ self = self.deepCopy;
+ //self.get_main = { arg self; main };
+
+ self;
+ },
+
+);
+
+~class_timeline = (
+
+ parent: ~class_player,
+ timeline_score: nil,
+ start_cursor: 0,
+ end_cursor: nil,
+ insert_cursor: 0,
+ play_cursor: 0,
+ current_track: 0,
+ node: EventPatternProxy.new,
+
+
+ new: { arg self, main;
+ self = self.parent[\new].(self, main);
+ self.get_main = { arg self; main };
+ self.timeline_score = ~class_timeline_score.(main);
+ self.bindings;
+
+ self;
+ },
+
+ set_start_cursor: { arg self, pos;
+ self.start_cursor = pos;
+ //self.changed(\start_cursor);
+ self.changed(\redraw);
+ },
+
+ set_insert_cursor: { arg self, pos, track_index;
+ self.insert_cursor = pos;
+ self.current_track = track_index;
+ self.changed(\insert_cursor);
+ },
+
+ tracks: { arg self; self.timeline_score.tracks },
+
+ add_track: { arg self, name;
+ var res;
+ res = self.timeline_score.add_track(name);
+ self.changed(\tracks);
+ res;
+ },
+
+ add_block: { arg self, blockname, track_index, abstime;
+ var res;
+ res = self.timeline_score.add_block(blockname, track_index, abstime);
+ self.changed(\blocks);
+ res;
+ },
+
+ add_block_from_lib: { arg self, track_index, abstime;
+ ~class_node_chooser.new(self.get_main, { arg blockname;
+ self.add_block(blockname, track_index, abstime);
+ })
+ },
+
+ refresh: { arg self;
+ self.changed(\tracks);
+ },