Rearranged the GUI.
[epichord.git] / src / seq.cpp
blobf1b8fd67270d274ddeb2e1d1d09314d439fb6b56
1 /*
2 Epichord - a midi sequencer
3 Copyright (C) 2008 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
23 #include <stdlib.h>
24 #include <math.h>
25 #include <list>
26 #include <vector>
28 #include "seq.h"
30 #include <fltk/TextDisplay.h>
31 #include "util.h"
33 #include "backend.h"
35 std::vector<track*> tracks;
37 std::list<Command*> undo_stack;
38 std::list<Command*>::iterator undo_ptr;
39 std::list<int> undo_number;
40 std::list<int>::iterator undo_nptr;
43 int solo_flag = 0;
45 int rec_track = 0;
47 static float default_hsv_value = 0.8;
53 int play_seq(int cur_tick, void (*dispatch_event)(mevent*, int port, int tick)){
55 seqpat* s;
56 pattern* p;
57 mevent* e;
58 int base;
60 /* start at skip s, and skip e
61 if e is in the past, dispatch event and set new skip
62 if next e is past pattern dur, switch patseq
63 if next e is null, switch patseq
64 switch patseq sets skip s
65 do the above until e is in the future and not past end
66 then go to next track and start over
69 //printf("playing. cur_tick = %d\n",cur_tick);
70 s = tracks[0]->skip;
71 for(int i=0; i<tracks.size(); i++){
72 //if(tracks[i]->alive == 0){continue;}
73 s = tracks[i]->skip;
74 if(!s){continue;}
75 p = s->p;
76 e = s->skip;
78 if(!e){ goto switchpatseq; }//no more events in this seqpat
80 again:
82 if(e->tick+s->tick <= cur_tick && e->tick <= s->dur){//should have happened
84 if(e->tick != s->dur || e->type == MIDI_NOTE_OFF)
85 if(tracks[i]->mute == 0)
86 if((get_solo() && tracks[i]->solo != 0) || !get_solo())
87 dispatch_event(e, i, s->tick);
89 e = e->next;
90 s->skip = e;
91 if(!e){//no more events in this seqpat
92 goto switchpatseq;
95 else if(e->tick > s->dur){//went past the end
96 goto switchpatseq;
98 else{//no more events on this track right now
99 continue;
101 goto again;//try to play next event
102 switchpatseq:
103 s = s->next;
105 tracks[i]->skip = s;
106 if(!s){continue;}//no more seqpats
107 p = s->p;
108 if(!p){continue;}//this shouldnt happen anymore
109 e = s->skip;
110 if(!e){continue;}//...means this pattern has played already...
112 goto again;//play some or all of the next seqpat
116 int set_seq_pos(int new_tick){
117 //reset all skip
118 //reset cur_seqpat
119 seqpat* s;
120 pattern* p;
121 mevent* e;
123 for(int i=0; i<tracks.size(); i++){
125 s = tracks[i]->head;
126 tracks[i]->skip = s;
128 while(s){
129 s->skip = s->p->events;
130 s = s->next;
133 s = tracks[i]->head;
134 while(s){
135 if(s->tick+s->dur <= new_tick){
136 tracks[i]->skip = s;
138 else{
139 tracks[i]->skip = s;
140 break;
142 s = s->next;
145 if(!s){
146 tracks[i]->skip = NULL;
147 continue;
150 if(!s->p){continue;}
151 e = s->p->events;
153 while(1){
154 if(e == NULL){
155 s->skip = e;
156 break;
158 else if(e->tick >= new_tick - s->tick){
159 s->skip = e;
160 break;
162 e = e->next;
167 void set_rec_track(int t){
168 rec_track = t;
171 int get_rec_track(){
172 return rec_track;
175 int set_default_hsv_value(float v){
176 default_hsv_value = v;
185 CreateSeqpat::CreateSeqpat(int track, int tick, seqpat* zs, int copy){
186 s = new seqpat(zs);
187 if(copy){
188 s->p = new pattern(zs->p);
189 s->skip = s->p->events;
191 s->track = track;
192 s->tick = tick;
194 s->prev = tfind<seqpat>(tracks[track]->head,tick);
195 s->next = s->prev->next;
198 void CreateSeqpat::redo(){
199 tinsert<seqpat>(s->prev, s);
202 void CreateSeqpat::undo(){
203 tremove<seqpat>(s);
206 CreateSeqpatBlank::CreateSeqpatBlank(int track, int tick, int len){
207 s = new seqpat(track, tick, len, new pattern());
208 unsigned char r,g,b;
210 pattern* p = s->p;
211 p->ref_c = 1;
212 p->h = ((track%16) / 16.0) * 360;
213 p->v = default_hsv_value;
214 p->regen_colors();
216 s->scrolly = 300;
217 s->scrollx = 0;
219 s->prev = tfind<seqpat>(tracks[track]->head,tick);
220 s->next = s->prev->next;
221 s->skip = s->p->events;
225 void DeleteSeqpat::redo(){
226 //check for restate
227 int pos = get_play_position();
228 if(pos >= s->tick && pos <= s->tick+s->dur){
229 tracks[s->track]->skip = s->next;
232 tremove<seqpat>(s);
235 void DeleteSeqpat::undo(){
236 tinsert<seqpat>(s->prev, s);
237 //check for restate
240 void ResizeSeqpat::redo(){
241 tremove<seqpat>(s1);
242 tinsert<seqpat>(s1->prev,s2);
244 //check for restate
247 void ResizeSeqpat::undo(){
248 tremove<seqpat>(s2);
249 tinsert<seqpat>(s1->prev,s1);
252 MoveSeqpat::MoveSeqpat(seqpat* zs, int track, int tick){
253 s = zs;
254 track1 = s->track;
255 track2 = track;
256 tick1 = s->tick;
257 tick2 = tick;
258 targ1 = s->prev;
259 targ2 = tfind<seqpat>(tracks[track2]->head,tick);
260 if(targ2 == zs){//dont put it after itself
261 targ2 = zs->prev;
265 void MoveSeqpat::redo(){
267 tremove<seqpat>(s);
270 int play_pos = get_play_position();
271 if(play_pos >= s->tick && play_pos <= s->tick+s->dur){//no entry into s by cb
272 tracks[track1]->skip = s->next;
275 track* t = tracks[track2];
277 //here possibly wait a few ms for the audio to leave s if it was in
279 //perform nitty gritty
280 s->track = track2;
282 s->tick = tick2;
284 s->skip = tfind<mevent>(s->p->events, play_pos - s->tick)->next;
285 tinsert<seqpat>(targ2,s);
288 void MoveSeqpat::undo(){
290 tremove<seqpat>(s);
292 int play_pos = get_play_position();
293 if(play_pos >= s->tick && play_pos <= s->tick+s->dur){
294 tracks[track2]->skip = s->next;
296 s->track = track1;
297 s->tick = tick1;
300 s->skip = tfind<mevent>(s->p->events, play_pos - s->tick)->next;
302 tinsert<seqpat>(targ1,s);
305 void SplitSeqpat::redo(){
309 void SplitSeqpat::undo(){
313 void JoinSeqpat::redo(){
317 void JoinSeqpat::undo(){
321 void ClearSeqpat::redo(){
322 s->p = p2;
325 void ClearSeqpat::undo(){
326 s->p = p1;
329 void LayerSeqpat::redo(){
330 if(s->layers == NULL){
331 s->layers = new layerstack(s->p);
333 s->layers->push(p);
334 s->p = p;
337 void LayerSeqpat::undo(){
338 s->p = s->layers->pop();
339 printf("ok...%d\n",s->layers->total);
340 if(s->layers->total == 1){
341 printf("deleting layers\n");
342 delete s->layers;
343 s->layers = NULL;
348 void CreateNote::redo(){
349 mevent* targ = tfind<mevent>(p->events, e1->tick);
350 tinsert<mevent>(targ, e1);
351 targ = tfind<mevent>(p->events, e2->tick);
352 tinsert<mevent>(targ, e2);
355 void CreateNote::undo(){
356 tremove<mevent>(e1);
357 tremove<mevent>(e2);
360 void CreateNoteOn::redo(){
361 mevent* targ = tfind<mevent>(p->events, e1->tick);
362 tinsert<mevent>(targ, e1);
363 //targ = tfind<mevent>(p->events, e2->tick);
364 //tinsert<mevent>(targ, e2);
367 void CreateNoteOn::undo(){
368 tremove<mevent>(e1);
369 //tremove<mevent>(e2);
373 CreateNoteOff::CreateNoteOff(pattern* zp, int note, int vel, int tick){
374 p = zp;
375 e1 = NULL;
376 mevent* ptr = tfind<mevent>(zp->events,tick);
377 while(ptr){
378 if(ptr->type == MIDI_NOTE_ON && ptr->value1 == note){
379 dur1 = ptr->dur;
380 dur2 = tick - ptr->tick;
381 e1 = ptr;
382 break;
384 if(ptr->type == MIDI_NOTE_OFF && ptr->value1 == note){
385 break;
387 ptr = ptr->prev;
389 e2 = new mevent(MIDI_NOTE_OFF, tick, note);
390 e2->value2 = vel;
393 void CreateNoteOff::redo(){
394 //mevent* targ = tfind<mevent>(p->events, e1->tick);
395 //tinsert<mevent>(targ, e1);
396 mevent* targ;
397 targ = tfind<mevent>(p->events, e2->tick);
398 tinsert<mevent>(targ, e2);
399 if(e1){
400 e1->dur = dur2;
404 void CreateNoteOff::undo(){
405 //tremove<mevent>(e1);
406 if(e1){
407 e1->dur = dur1;
409 tremove<mevent>(e2);
412 void DeleteNote::redo(){
413 tremove<mevent>(e1);
414 if(e2){
415 tremove<mevent>(e2);
419 void DeleteNote::undo(){
420 tinsert<mevent>(e1->prev,e1);
421 if(e2){
422 tinsert<mevent>(e2->prev,e2);
428 void MoveNote::arrive(int t){
429 mevent* targ = tfind<mevent>(p->events, t);
430 tinsert<mevent>(targ, e1);
431 if(e2){
432 targ = tfind<mevent>(p->events, t+e1->dur);
433 tinsert<mevent>(targ, e2);
437 void MoveNote::redo(){
438 tremove<mevent>(e1);
439 e1->tick = t2;
440 e1->value1 = note2;
441 if(e2){
442 tremove<mevent>(e2);
443 e2->tick = t2+e1->dur;
444 e2->value1 = note2;
446 arrive(t2);
449 void MoveNote::undo(){
450 tremove<mevent>(e1);
451 e1->tick = t1;
452 e1->value1 = note1;
453 if(e2){
454 tremove<mevent>(e2);
455 e2->tick = t1+e1->dur;
456 e2->value1 = note1;
458 arrive(t1);
464 ResizeNote::ResizeNote(pattern* zp, mevent* ze, int dur){
465 p = zp;
466 l1 = ze;
467 l2 = new mevent(ze);
468 l2->dur = dur;
470 r2 = NULL;
471 r1 = find_off(ze);
472 if(r1){
473 r2 = new mevent(r1);
474 r2->prev = tfind<mevent>(p->events, ze->tick + dur);
475 if(r2->prev == r1 || r2->prev == l1){
476 r2->prev = l2;
478 r2->tick = ze->tick + dur;
482 void ResizeNote::redo(){
483 tremove<mevent>(l1);
484 if(r1){
485 tremove<mevent>(r1);
488 tinsert<mevent>(l2->prev, l2);
489 if(r2){
490 tinsert<mevent>(r2->prev, r2);
494 void ResizeNote::undo(){
495 if(r2){
496 tremove<mevent>(r2);
498 tremove<mevent>(l2);
500 tinsert<mevent>(l1->prev, l1);
501 if(r1){
502 tinsert<mevent>(r1->prev, r1);
509 void CreateEvent::redo(){
510 tinsert<mevent>(e->prev, e);
513 void CreateEvent::undo(){
514 tremove<mevent>(e);
517 void DeleteEvent::redo(){
518 tremove<mevent>(e);
521 void DeleteEvent::undo(){
522 tinsert<mevent>(e->prev, e);
525 void ChangeEvent::redo(){
526 tswap<mevent>(e1,e2);
529 void ChangeEvent::undo(){
530 tswap<mevent>(e2,e1);
537 mevent* find_off(mevent* e){
538 mevent* ptr = e;
539 while(ptr){
540 if(ptr->type == MIDI_NOTE_OFF && ptr->value1 == e->value1){
541 return ptr;
543 ptr = ptr->next;
545 return NULL;
555 pattern::pattern(){
556 events = new mevent();//dummy
557 events->tick = 0;
558 next = NULL;
559 ref_c = 0;
560 h=0;
561 s=1;
562 v=0.8;
563 regen_colors();
567 pattern::~pattern(){
568 mevent* e = events;
569 mevent* next;
570 while(e){
571 next = e->next;
572 delete e;
573 e = next;
578 pattern::pattern(pattern* p){
579 mevent* ptr = p->events;
580 mevent* ptr2;
581 events = new mevent(ptr);
582 ptr2 = events;
583 ptr=ptr->next;
584 while(ptr){
585 ptr2->next = new mevent(ptr);
586 ptr2->next->prev = ptr2;
587 ptr=ptr->next;
588 ptr2=ptr2->next;
590 ptr2->next = NULL;
592 next = NULL;
593 ref_c = 0;
594 h = p->h;
595 s = p->s;
596 v = p->v;
597 regen_colors();
601 void pattern::regen_colors(){
603 while(h>360){h-=360;}
604 while(h<0){h+=360;}
605 if(s < 0){s = 0;}
606 if(s > 1){s = 1;}
607 if(v < 0.2){v = 0.2;}
608 if(v > 0.8){v = 0.8;}
610 hsv_to_rgb(h,s,v,&r1,&g1,&b1);
611 hsv_to_rgb(h,s,v/2,&r2,&g2,&b2);
612 hsv_to_rgb(h,s,v+0.2 > 1 ? 1 : v+0.2,&r3,&g3,&b3);
613 if(v > 0.5){
614 hsv_to_rgb(h,s,v-0.3,&rx,&gx,&bx);
616 else{
617 hsv_to_rgb(h,s,0.7,&rx,&gx,&bx);
622 void pattern::append(mevent* ze){
623 mevent* e = events;
624 while(e->next){
625 e = e->next;
627 e->next = ze;
628 ze->prev = e;
631 void pattern::insert(mevent* ze, int tick){
632 mevent* ptr = events;
633 while(ptr->next){
634 if(ptr->next->tick > tick){
635 ze->next = ptr->next;
636 ze->next->prev = ze;
637 ptr->next = ze;
638 ze->prev = ptr;
639 return;
641 ptr=ptr->next;
643 ptr->next = ze;
644 ze->prev = ptr;
648 void pattern::fixdur(){
649 mevent* e = events;
650 mevent* f;
651 while(e->next){
652 if(e->type == MIDI_NOTE_ON){
653 f = find_off(e);
654 if(f){e->dur = f->tick - e->tick;}
656 e = e->next;
662 //used when the sequence is changed in such a way
663 //that the sequencer state needs to be updated
664 void track::restate(){
665 int pos = get_play_position();
666 seqpat* s = head->next;
667 int snullflag = 1;
668 int pnullflag = 1;
669 int pointfound = 0;
670 while(s){
671 //printf("trying block: pos %d, tick %d, t2 %d\n",pos,s->tick,s->tick+s->dur);
672 if(pointfound){//we are past the point, reset up coming blocks
673 //printf("future block\n");
674 s->skip = s->p->events->next;
677 else if(s->tick+s->dur < pos){//we are past this block
678 //printf("past block\n");
679 s->skip = NULL;
682 else if(s->tick+s->dur > pos && s->tick <= pos){//we are inside this block, point found
683 //printf("inside block\n");
684 pointfound = 1;
685 snullflag = 0;
686 skip = s;
687 mevent* e = s->p->events->next;
688 while(e){
689 if(e->tick+s->tick >= pos){
690 s->skip = e;
691 pointfound = 1;
692 pnullflag = 0;
693 break;
695 e = e->next;
697 if(pnullflag){
698 s->skip = NULL;
702 else{//we are not in a block, point found
703 //printf("pointfound outside block\n");
704 skip = s;
705 snullflag = 0;
706 pointfound = 1;
709 s = s->next;
712 if(snullflag){skip = NULL;}
716 void seqpat::restate(){
717 mevent* e = p->events->next;
718 int pos = get_play_position();
719 while(e){
720 if(e->tick+tick >= pos){
721 skip = e;
722 return;
724 e = e->next;
726 skip = NULL;
730 //clear the pattern
731 void seqpat::apply_erase(){
733 Command* c;
735 c = new ClearSeqpat(this);
736 set_undo(c);
737 undo_push(1);
740 //create new pattern and make it current
741 void seqpat::apply_layer(){
742 Command* c = new LayerSeqpat(this);
743 set_undo(c);
744 undo_push(1);
747 void seqpat::next_layer(){
748 if(layers){
749 p = layers->next();
753 void seqpat::prev_layer(){
754 if(layers){
755 p = layers->prev();
759 int seqpat::layer_index(){
760 if(layers){
761 return layers->index;
763 else{
764 return 0;
768 int seqpat::layer_total(){
769 if(layers){
770 return layers->total;
772 else{
773 return 1;
777 void seqpat::record_check(int mode){
778 if(record_flag==0){
779 if(mode==1 || mode==2){
780 autocomplete();//end stuck notes
781 if(mode == 1){apply_erase();}
782 else if(mode == 2){apply_layer();}
783 tracks[track]->restate();
785 record_flag = 1;
789 //sends note off if it determines that
790 //we are in between two notes
791 void seqpat::autocomplete(){
792 mevent* ptr;
793 mevent* e = p->events->next;
794 mevent* eoff;
796 int pos = get_play_position()-tick;
798 int chan = tracks[track]->chan;
799 int port = tracks[track]->port;
801 while(e){
802 if(e->type == MIDI_NOTE_ON && e->tick < pos){
803 eoff = find_off(e);
804 if(eoff){
805 if(eoff->tick > pos){
806 midi_note_off(e->value1,chan,port);
810 e = e->next;
820 pattern* layerstack::push_new(){
821 if(total==memsize){
822 reallocate();
824 total++;
825 array[total-1] = new pattern();
826 array[total-1]->h = array[0]->h;
827 array[total-1]->s = array[0]->s;
828 array[total-1]->v = array[0]->v;
829 array[total-1]->regen_colors();
830 index=total-1;
831 return array[index];
834 void layerstack::push(pattern* p){
835 if(total==memsize){
836 reallocate();
839 total++;
840 array[total-1] = p;
841 index = total-1;
842 p->ref_c++;
845 void layerstack::reallocate(){
846 pattern** ptmp = new pattern*[memsize*2];
847 for(int i=0; i<memsize; i++){
848 ptmp[i] = array[i];
850 memsize *= 2;
851 delete [] array;
852 array = ptmp;
855 pattern* layerstack::pop(){
856 if(index == 0){
857 return NULL;
859 if(index == total-1){
860 index--;
862 array[total-1]=NULL;
863 total--;
864 return array[index];
867 void layerstack::remove(int n){
871 void layerstack::insert(pattern* p, int n){
876 pattern* layerstack::next(){
877 if(index==total-1){
878 index=0;
880 else{
881 index++;
883 return array[index];
886 pattern* layerstack::prev(){
887 if(index==0){
888 index=total-1;
890 else{
891 index--;
893 return array[index];
896 layerstack::layerstack(pattern* p){
897 index = 0;
898 total = 1;
899 array = new pattern*[16];
900 memsize = 16;
901 array[0] = p;
902 // ptr = array[0];
903 ref_c = 0;
906 layerstack::~layerstack(){
907 for(int i=0; i<total; i++){
908 array[i]->ref_c--;
909 if(array[i]->ref_c == 0){
910 delete array[i];
917 void reset_record_flags(){
918 for(int i=0; i<tracks.size(); i++){
919 seqpat* s = tracks[i]->head->next;
920 while(s){
921 if(s->record_flag == 1){
922 s->record_flag = 0;
924 s = s->next;
932 void set_undo(Command* c){
933 if(undo_ptr != undo_stack.end()){
934 printf("changing the past, need to erase the future\n");
935 std::list<int>::iterator nptr = undo_number.end();
936 nptr--;
937 while(nptr != undo_nptr){
938 int N = *nptr;
939 printf("deleting %d commands\n",N);
940 for(int i=0; i<N; i++){
941 //delete this command
942 undo_stack.pop_back();
944 nptr--;
945 undo_number.pop_back();
948 printf("pushing command\n");
949 undo_stack.push_back(c);
950 undo_ptr = undo_stack.end();
951 c->redo();
954 void undo_push(int n){
955 if(n==0){return;}
956 printf("pushing number of commands %d\n",n);
957 undo_number.push_back(n);
958 undo_nptr++;
961 void do_undo(){
962 if(undo_ptr==undo_stack.begin()){
963 printf("no more to undo!\n");
964 return;
966 printf("undoing\n");
967 int N = *undo_nptr;
968 undo_nptr--;
969 for(int i=0; i<N; i++){
970 undo_ptr--;
971 (*undo_ptr)->undo();
975 void do_redo(){
976 if(undo_ptr==undo_stack.end()){
977 printf("no more to redo!\n");
978 return;
980 printf("redoing\n");
981 undo_nptr++;
982 int N = *undo_nptr;
983 for(int i=0; i<N; i++){
984 (*undo_ptr)->redo();
985 undo_ptr++;
989 void undo_reset(){
990 printf("undo reset\n");
991 int N = undo_stack.size();
992 for(int i=0; i<N; i++){
993 std::list<Command*>::iterator c = undo_stack.end();
994 c--;
995 //delete (*c);
996 undo_stack.pop_back();
999 N = undo_number.size();
1000 for(int i=0; i<N; i++){
1001 undo_number.pop_back();
1004 undo_nptr = undo_number.begin();
1005 undo_ptr = undo_stack.begin();