Fixed bug that crashed on saving after importing.
[epichord.git] / src / seq.h
blob3669bdd158423ff425999d2e467de8a95908c348
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 #ifndef seq_h
24 #define seq_h
26 #define MIDI_NOTE_OFF 0x80
27 #define MIDI_NOTE_ON 0x90
28 #define MIDI_AFTERTOUCH 0xA0
29 #define MIDI_CONTROLLER_CHANGE 0xB0
30 #define MIDI_PROGRAM_CHANGE 0xC0
31 #define MIDI_CHANNEL_PRESSURE 0xD0
32 #define MIDI_PITCH_WHEEL 0xE0
34 #include <stdlib.h>
35 #include <stdio.h>
36 struct mevent {
38 public:
39 int tick;
41 int type;
42 int value1;
43 int value2;
44 int dur; //for note on events
46 //struct mevent* off; //for note on events
47 //int off_index; //used when reloading
49 struct mevent* prev;
50 struct mevent* next;
52 int selected;
53 int modified;
55 mevent(){
56 type = -1;
57 //off = NULL;
58 prev = NULL;
59 next = NULL;
60 dur = 32;
61 selected = 0;
62 modified = 0;
65 mevent(int ztype, int ztick, int zv1){
66 //off=NULL;
67 prev=NULL;
68 next=NULL;
69 dur = 32;
70 type=ztype;
71 tick=ztick;
72 value1=zv1;
73 value2=0x7f;
74 selected = 0;
75 modified = 0;
78 mevent(mevent* e){
79 type = e->type;
80 tick = e->tick;
81 value1 = e->value1;
82 value2 = e->value2;
83 dur = e->dur;
84 //off = e->off;
85 prev = e->prev;
86 next = e->next;
87 selected = e->selected;
88 modified = e->modified;
93 struct pattern {
94 public:
95 struct mevent* events;
96 struct pattern* next;
97 int ref_c;
99 unsigned char r1,g1,b1;//main color
100 unsigned char r2,g2,b2;//bottom color
101 unsigned char r3,g3,b3;//top color
102 unsigned char rx,gx,bx;//xray color
104 float h, s, v; //color
106 void regen_colors();
108 pattern();
109 pattern(pattern* p);
110 ~pattern();
111 void append(mevent* ze);
112 void insert(mevent* ze, int tick);
113 void fixdur();
118 struct layerstack {
119 pattern** array;
121 int index;
122 int total;
123 int memsize;
125 int ref_c;
127 pattern* push_new();
128 void push_new(pattern* p);
129 pattern* next();
130 pattern* prev();
131 void reallocate();
133 layerstack(){};
134 layerstack(pattern* p);
135 ~layerstack();
139 struct seqpat {
140 int track;
141 int tick;
142 int dur;
143 struct pattern* p;
144 struct mevent* skip;
145 struct seqpat* prev;
146 struct seqpat* next;
148 layerstack* layers;
150 // unsigned char color[3][3];
151 int selected;
152 int modified;
153 int record_flag;//0=on record, erase/save. 1=dont
154 int rhandle;
155 int lhandle;
157 int scrollx, scrolly;
159 void restate();
160 void apply_erase();
161 void apply_layer();
162 void next_layer();
163 void prev_layer();
164 int layer_index();
165 int layer_total();
166 void record_check(int mode);
167 void autocomplete();
170 seqpat(){
171 p = NULL;
172 skip = NULL;
173 prev = NULL;
174 next = NULL;
175 dur=0;
176 selected=0;
177 modified=0;
178 rhandle=0;
179 lhandle=0;
180 record_flag=1;
181 layers = NULL;
182 scrollx = 0;
183 scrolly = 300;
186 seqpat(int ztrack, int ztick, int zdur, pattern* zp){
187 p = zp;
188 p->ref_c++;
189 track = ztrack;
190 dur = zdur;
191 tick = ztick;
192 skip = NULL;
193 prev = NULL;
194 next = NULL;
195 selected = 0;
196 modified = 0;
197 rhandle = 0;
198 lhandle = 0;
199 record_flag = 1;
200 layers = NULL;
201 scrollx = 0;
202 scrolly = 300;
205 seqpat(seqpat* zs){
206 p = zs->p;
207 p->ref_c++;
208 track = zs->track;
209 dur = zs->dur;
210 tick = zs->tick;
211 if(p){p->ref_c++;}
213 skip = p->events;
214 prev = zs->prev;
215 next = zs->next;
217 scrollx = zs->scrollx;
218 scrolly = zs->scrolly;
220 selected = zs->selected;
221 modified = zs->modified;
223 rhandle = 0;
224 lhandle = 0;
225 record_flag = 1;
226 layers = NULL;
229 seqpat(seqpat* zs, pattern* zp){
230 p = zp;
231 p->ref_c++;
232 track = zs->track;
233 dur = zs->dur;
234 tick = zs->tick;
235 if(p){p->ref_c++;}
237 skip = p->events;
238 prev = zs->prev;
239 next = zs->next;
241 scrollx = zs->scrollx;
242 scrolly = zs->scrolly;
244 selected = zs->selected;
245 modified = zs->modified;
247 rhandle=0;
248 lhandle=0;
249 record_flag=1;
250 layers = NULL;
253 ~seqpat(){
254 if(p){
255 p->ref_c--;
256 if(p->ref_c == 0){
257 delete p;
260 if(layers){
261 layers->ref_c--;
262 if(layers->ref_c == 0){
263 delete layers;
275 struct track {
276 int port;
277 int chan;
278 int prog;
279 int bank;
280 int mute;
281 int solo;
282 int vol;
283 int pan;
284 char* name;
285 int alive;
286 seqpat* head;
287 seqpat* skip;
289 int modified;
291 void restate();
293 track(){
294 port = 0;
295 chan = 0;
296 prog = 0;
297 bank = 0;
298 mute = 0;
299 solo = 0;
300 vol = 127;
301 pan = 64;
302 name = (char*)malloc(8);
303 name[0] = '\0';
304 alive = 1;
305 head = new seqpat(0,0,0,new pattern());
306 head->tick = 0;
307 skip = head;
308 modified = 0;
311 ~track(){
312 free(name);
313 seqpat* s = head;
314 seqpat* next;
315 while(s){
316 next = s->next;
317 delete s;
318 s = next;
327 template <class T>
328 void tswap(T* old, T* nu){
329 nu->next = old->next;
330 nu->prev = old->prev;
332 if(old->prev){
333 old->prev->next = nu; //'atomic'
335 if(old->next){
336 old->next->prev = nu; //prev ptrs are only read by gui thread
340 template <class T>
341 void tremove(T* old){
342 if(old->prev){
343 old->prev->next = old->next; //'atomic'
345 if(old->next){
346 old->next->prev = old->prev; //prev ptrs are only read by gui thread
350 template <class T>
351 void tinsert(T* targ, T* nu){
352 nu->prev = targ;
353 nu->next = targ->next;
355 targ->next = nu; //'atomic'
356 if(nu->next){
357 nu->next->prev = nu; //prev ptrs are only read by gui thread
361 template <class T>
362 T* tfind(T* begin, int tick){
363 T* ptr = begin;
364 while(ptr->next){
365 if(ptr->next->tick > tick){
366 break;
368 ptr = ptr->next;
370 return ptr;
373 mevent* find_off(mevent* e);
376 class Command {
378 public:
380 virtual void undo() {}
381 virtual void redo() {}
385 void set_undo(Command* c);
386 void push_undo(int n);
387 void do_undo();
388 void do_redo();
390 int clear_undos(int number);
394 class CreateSeqpat : public Command {
395 protected:
396 seqpat* s;
398 public:
400 CreateSeqpat(){}
401 CreateSeqpat(int track, int tick, seqpat* zs, int copy);
403 ~CreateSeqpat(){
404 if(s->p->ref_c-- == 0){
405 delete s->p;
407 delete s;
410 void redo();
411 void undo();
414 class CreateSeqpatBlank : public CreateSeqpat {
416 public:
418 CreateSeqpatBlank(int track, int tick, int len);
423 class DeleteSeqpat : public Command {
424 seqpat* s;
426 public:
428 DeleteSeqpat(seqpat* zs){
429 s = zs;
432 void redo();
433 void undo();
436 class ResizeSeqpat : public Command {
437 seqpat* s1;
438 seqpat* s2;
440 public:
442 ResizeSeqpat(seqpat* zs, int dur){
443 s1 = zs;
444 s2 = new seqpat(zs);
445 s2->dur = dur;
447 ~ResizeSeqpat(){
448 delete s2;
451 void redo();
452 void undo();
455 class MoveSeqpat : public Command {
456 seqpat* s;
457 seqpat *targ1, *targ2;
458 int track1, track2;
459 int tick1, tick2;
461 public:
463 MoveSeqpat(seqpat* zs, int track, int tick);
465 void redo();
466 void undo();
469 class SplitSeqpat : public Command {
470 seqpat* s;
471 pattern* p1;
472 pattern* p2;
474 public:
476 SplitSeqpat(seqpat* zs){
477 s = zs;
478 p1 = s->p;
479 p2 = new pattern();
480 p2->ref_c = 1;
483 SplitSeqpat(){
484 if(--(p2->ref_c) == 0){
485 delete p2;
489 void redo();
490 void undo();
496 class CreateNote : public Command {
497 pattern* p;
498 mevent* e1;
499 mevent* e2;
501 public:
503 CreateNote(pattern* zp, int note, int vel, int tick, int dur){
504 p = zp;
505 e1 = new mevent(MIDI_NOTE_ON, tick, note);
506 e1->dur = dur;
507 e1->value2 = vel;
508 e2 = new mevent(MIDI_NOTE_OFF, tick+dur, note);
509 e2->value2 = 0;
510 //e->off = new mevent(MIDI_NOTE_OFF, tick+dur, note);
512 ~CreateNote(){
513 //delete e->off;
514 delete e1;
515 delete e2;
518 void redo();
519 void undo();
522 class CreateNoteOn : public Command {
523 pattern* p;
524 mevent* e1;
526 public:
528 CreateNoteOn(pattern* zp, int note, int vel, int tick, int dur){
529 p = zp;
530 e1 = new mevent(MIDI_NOTE_ON, tick, note);
531 e1->value2 = vel;
532 e1->dur = dur;
534 ~CreateNoteOn(){
535 delete e1;
538 void redo();
539 void undo();
542 class CreateNoteOff : public Command {
543 pattern* p;
544 mevent* e1;
545 mevent* e2;
547 int dur1;
548 int dur2;
550 public:
552 CreateNoteOff(pattern* zp, int note, int vel, int tick);
553 ~CreateNoteOff(){
554 delete e2;
557 void redo();
558 void undo();
561 class DeleteNote : public Command {
562 pattern* p;
563 mevent* e1;
564 mevent* e2;
566 public:
568 DeleteNote(pattern* zp, mevent* ze){
569 p = zp;
570 e1 = ze;
571 e2 = find_off(e1);
574 void redo();
575 void undo();
578 class MoveNote : public Command {
579 pattern* p;
580 mevent* e1;
581 mevent* e2;
582 int t1;
583 int t2;
584 int note1;
585 int note2;
587 void arrive(int t);
589 public:
591 MoveNote(pattern* zp, mevent* ze, int zt, int znote){
592 p = zp;
593 e1 = ze;
594 e2 = find_off(e1);
595 note1 = ze->value1;
596 note2 = znote;
597 t1 = ze->tick;
598 t2 = zt;
601 void redo();
602 void undo();
606 class ResizeNote : public Command {
607 pattern* p;
608 mevent* l1;
609 mevent* l2;
610 mevent* r1;
611 mevent* r2;
613 public:
615 ResizeNote(pattern* zp, mevent* ze, int dur);
616 ~ResizeNote(){
617 delete l2;
618 delete r2;
621 void redo();
622 void undo();
628 class CreateEvent : public Command {
629 pattern* p;
630 mevent* e;
632 public:
634 CreateEvent(pattern* zp, int type, int tick, int value1, int value2){
635 p = zp;
636 e = new mevent(type,tick,value1);
637 e->value2 = value2;
638 e->prev = tfind<mevent>(zp->events,tick);
639 e->next = e->prev->next;
641 ~CreateEvent(){
642 delete e;
645 void redo();
646 void undo();
649 class DeleteEvent : public Command {
650 mevent* e;
652 public:
654 DeleteEvent(mevent* ze){
655 e = ze;
658 void redo();
659 void undo();
662 class ChangeEvent : public Command {
663 mevent* e1;
664 mevent* e2;
666 public:
668 ChangeEvent(mevent* ze, int zv1, int zv2){
669 e1 = ze;
670 e2 = new mevent(ze);
671 e2->value1 = zv1;
672 e2->value2 = zv2;
675 void redo();
676 void undo();
681 int play_seq(int cur_tick, void (*dispatch_event)(mevent*, int port, int tick));
682 int set_seq_pos(int new_tick);
684 void set_rec_track(int t);
685 int get_rec_track();
687 int set_default_hsv_value(float v);
689 void set_undo(Command* c);
690 void undo_push(int n);
691 void do_undo();
692 void do_redo();
695 void reset_record_flags();
698 //encodes data in e as a midi event placed in buf
699 int midi_encode(mevent* e, int chan, unsigned char* buf, size_t* n);
701 //decodes midi data and creates a new mevent
702 int midi_decode(char* buf, mevent* e);
704 #endif