Group move blocks. Fixed some bugs.
[epichord.git] / src / seq.h
blobae7a374c97d98af7e258fd7a836b2adbcdfc4a0b
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 #define MAX_TRACK_NAME 256
36 #include <stdio.h>
37 struct mevent {
39 public:
40 int tick;
42 int type;
43 int value1;
44 int value2;
45 int dur; //for note on events
47 //struct mevent* off; //for note on events
48 //int off_index; //used when reloading
50 struct mevent* prev;
51 struct mevent* next;
53 int selected;
55 mevent(){
56 type = -1;
57 //off = NULL;
58 prev = NULL;
59 next = NULL;
60 dur = 32;
61 selected = 0;
64 mevent(int ztype, int ztick, int zv1){
65 //off=NULL;
66 prev=NULL;
67 next=NULL;
68 dur = 32;
69 type=ztype;
70 tick=ztick;
71 value1=zv1;
72 value2=0x7f;
73 selected = 0;
76 mevent(mevent* e){
77 type = e->type;
78 tick = e->tick;
79 value1 = e->value1;
80 value2 = e->value2;
81 dur = e->dur;
82 //off = e->off;
83 prev = e->prev;
84 next = e->next;
85 selected = e->selected;
90 struct pattern {
91 public:
92 struct mevent* events;
93 struct pattern* next;
94 int ref_c;
96 unsigned char r1,g1,b1;//main color
97 unsigned char r2,g2,b2;//bottom color
98 unsigned char r3,g3,b3;//top color
99 unsigned char rx,gx,bx;//xray color
101 float h, s, v; //color
103 void regen_colors();
105 pattern(){
106 events = new mevent();//dummy
107 events->tick = 0;
108 next = NULL;
109 ref_c = 0;
110 h=0;
111 s=1;
112 v=0.8;
113 regen_colors();
116 pattern(pattern* p);
118 ~pattern(){
119 mevent* e = events;
120 mevent* next;
121 while(e){
122 next = e->next;
123 delete e;
124 e = next;
132 struct seqpat {
133 int track;
134 int tick;
135 int dur;
136 struct pattern* p;
137 struct mevent* skip;
138 struct seqpat* prev;
139 struct seqpat* next;
141 // unsigned char color[3][3];
142 int selected;
143 int modified;
145 int scrollx, scrolly;
147 seqpat(){
148 p = NULL;
149 skip = NULL;
150 prev = NULL;
151 next = NULL;
152 dur=0;
153 selected=0;
154 modified=0;
157 seqpat(int ztrack, int ztick, int zdur, pattern* zp){
158 p = zp;
159 track = ztrack;
160 dur = zdur;
161 tick = ztick;
162 skip = NULL;
163 prev = NULL;
164 next = NULL;
165 selected = 0;
166 modified=0;
169 seqpat(seqpat* zs){
170 p = zs->p;
171 track = zs->track;
172 dur = zs->dur;
173 tick = zs->tick;
174 if(p){p->ref_c++;}
176 skip = p->events;
177 prev = zs->prev;
178 next = zs->next;
180 scrollx = zs->scrollx;
181 scrolly = zs->scrolly;
183 selected = zs->selected;
184 modified = zs->modified;
187 seqpat(seqpat* zs, pattern* zp){
188 p = zp;
189 track = zs->track;
190 dur = zs->dur;
191 tick = zs->tick;
192 if(p){p->ref_c++;}
194 skip = p->events;
195 prev = zs->prev;
196 next = zs->next;
198 scrollx = zs->scrollx;
199 scrolly = zs->scrolly;
201 selected = zs->selected;
202 modified = zs->modified;
205 ~seqpat(){
210 struct track {
211 int port;
212 int chan;
213 int prog;
214 int bank;
215 int mute;
216 int solo;
217 int vol;
218 int pan;
219 char name[MAX_TRACK_NAME];
220 int alive;
221 seqpat* head;
222 seqpat* skip;
224 int modified;
226 void restate();
228 track(){
229 port = 0;
230 chan = 0;
231 prog = 0;
232 bank = 0;
233 mute = 0;
234 solo = 0;
235 vol = 127;
236 pan = 64;
237 name[0] = '\0';
238 alive = 1;
239 head = new seqpat(0,0,0,new pattern());
240 head->tick = 0;
241 skip = head;
242 modified = 0;
245 ~track(){
246 seqpat* s = head;
247 seqpat* next;
248 while(s){
249 next = s->next;
250 delete s;
251 s = next;
260 template <class T>
261 void tswap(T* old, T* nu){
262 nu->next = old->next;
263 nu->prev = old->prev;
265 if(old->prev){
266 old->prev->next = nu; //'atomic'
268 if(old->next){
269 old->next->prev = nu; //prev ptrs are only read by gui thread
273 template <class T>
274 void tremove(T* old){
275 if(old->prev){
276 old->prev->next = old->next; //'atomic'
278 if(old->next){
279 old->next->prev = old->prev; //prev ptrs are only read by gui thread
283 template <class T>
284 void tinsert(T* targ, T* nu){
285 nu->prev = targ;
286 nu->next = targ->next;
288 targ->next = nu; //'atomic'
289 if(nu->next){
290 nu->next->prev = nu; //prev ptrs are only read by gui thread
294 template <class T>
295 T* tfind(T* begin, int tick){
296 T* ptr = begin;
297 while(ptr->next){
298 if(ptr->next->tick > tick){
299 break;
301 ptr = ptr->next;
303 return ptr;
306 mevent* find_off(mevent* e);
309 class Command {
311 public:
313 virtual void undo() {}
314 virtual void redo() {}
318 void set_undo(Command* c);
319 void push_undo(int n);
320 void do_undo();
321 void do_redo();
323 int clear_undos(int number);
327 class CreateSeqpat : public Command {
328 protected:
329 seqpat* s;
331 public:
333 CreateSeqpat(){}
334 CreateSeqpat(int track, int tick, seqpat* zs, int copy);
336 ~CreateSeqpat(){
337 if(s->p->ref_c-- == 0){
338 delete s->p;
340 delete s;
343 void redo();
344 void undo();
347 class CreateSeqpatBlank : public CreateSeqpat {
349 public:
351 CreateSeqpatBlank(int track, int tick, int len);
356 class DeleteSeqpat : public Command {
357 seqpat* s;
359 public:
361 DeleteSeqpat(seqpat* zs){
362 s = zs;
365 void redo();
366 void undo();
369 class ResizeSeqpat : public Command {
370 seqpat* s1;
371 seqpat* s2;
373 public:
375 ResizeSeqpat(seqpat* zs, int dur){
376 s1 = zs;
377 s2 = new seqpat(zs);
378 s2->dur = dur;
380 ~ResizeSeqpat(){
381 delete s2;
384 void redo();
385 void undo();
388 class MoveSeqpat : public Command {
389 seqpat* s;
390 seqpat *targ1, *targ2;
391 int track1, track2;
392 int tick1, tick2;
394 public:
396 MoveSeqpat(seqpat* zs, int track, int tick);
398 void redo();
399 void undo();
402 class SplitSeqpat : public Command {
403 seqpat* s;
404 pattern* p1;
405 pattern* p2;
407 public:
409 SplitSeqpat(seqpat* zs){
410 s = zs;
411 p1 = s->p;
412 p2 = new pattern();
413 p2->ref_c = 1;
416 SplitSeqpat(){
417 if(p2->ref_c-- == 0){
418 delete p2;
422 void redo();
423 void undo();
429 class CreateNote : public Command {
430 pattern* p;
431 mevent* e1;
432 mevent* e2;
434 public:
436 CreateNote(pattern* zp, int note, int vel, int tick, int dur){
437 p = zp;
438 e1 = new mevent(MIDI_NOTE_ON, tick, note);
439 e1->dur = dur;
440 e1->value2 = vel;
441 e2 = new mevent(MIDI_NOTE_OFF, tick+dur, note);
442 //e->off = new mevent(MIDI_NOTE_OFF, tick+dur, note);
444 ~CreateNote(){
445 //delete e->off;
446 delete e1;
447 delete e2;
450 void redo();
451 void undo();
454 class CreateNoteOn : public Command {
455 pattern* p;
456 mevent* e1;
458 public:
460 CreateNoteOn(pattern* zp, int note, int vel, int tick, int dur){
461 p = zp;
462 e1 = new mevent(MIDI_NOTE_ON, tick, note);
463 e1->value2 = vel;
464 e1->dur = dur;
466 ~CreateNoteOn(){
467 delete e1;
470 void redo();
471 void undo();
474 class CreateNoteOff : public Command {
475 pattern* p;
476 mevent* e1;
477 mevent* e2;
479 int dur1;
480 int dur2;
482 public:
484 CreateNoteOff(pattern* zp, int note, int vel, int tick);
485 ~CreateNoteOff(){
486 delete e2;
489 void redo();
490 void undo();
493 class DeleteNote : public Command {
494 pattern* p;
495 mevent* e1;
496 mevent* e2;
498 public:
500 DeleteNote(pattern* zp, mevent* ze){
501 p = zp;
502 e1 = ze;
503 e2 = find_off(e1);
506 void redo();
507 void undo();
510 class MoveNote : public Command {
511 pattern* p;
512 mevent* e1;
513 mevent* e2;
514 int t1;
515 int t2;
516 int note1;
517 int note2;
519 void arrive(int t);
521 public:
523 MoveNote(pattern* zp, mevent* ze, int zt, int znote){
524 p = zp;
525 e1 = ze;
526 e2 = find_off(e1);
527 note1 = ze->value1;
528 note2 = znote;
529 t1 = ze->tick;
530 t2 = zt;
533 void redo();
534 void undo();
538 class ResizeNote : public Command {
539 pattern* p;
540 mevent* l1;
541 mevent* l2;
542 mevent* r1;
543 mevent* r2;
545 public:
547 ResizeNote(pattern* zp, mevent* ze, int dur){
548 p = zp;
549 l1 = ze;
550 r1 = find_off(ze);
551 l2 = new mevent(ze);
552 l2->dur = dur;
553 r2 = new mevent(r1);
554 r2->prev = tfind<mevent>(p->events, ze->tick + dur);
555 r2->tick = ze->tick + dur;
557 ~ResizeNote(){
558 delete l2;
559 delete r2;
562 void redo();
563 void undo();
569 class CreateEvent : public Command {
570 pattern* p;
571 mevent* e;
573 public:
575 CreateEvent(pattern* zp, int type, int tick, int value1, int value2){
576 p = zp;
577 e = new mevent(type,tick,value1);
578 e->value2 = value2;
579 e->prev = tfind<mevent>(zp->events,tick);
580 e->next = e->prev->next;
582 ~CreateEvent(){
583 delete e;
586 void redo();
587 void undo();
590 class DeleteEvent : public Command {
591 mevent* e;
593 public:
595 DeleteEvent(mevent* ze){
596 e = ze;
599 void redo();
600 void undo();
603 class ChangeEvent : public Command {
604 mevent* e1;
605 mevent* e2;
607 public:
609 ChangeEvent(mevent* ze, int zv1, int zv2){
610 e1 = ze;
611 e2 = new mevent(ze);
612 e2->value1 = zv1;
613 e2->value2 = zv2;
616 void redo();
617 void undo();
622 int init_seq();
624 int play_seq(int cur_tick, void (*dispatch_event)(mevent*, int port, int tick));
625 int set_seq_pos(int new_tick);
627 void set_rec_track(int t);
628 int get_rec_track();
630 int set_default_hsv_value(float v);
632 void set_undo(Command* c);
633 void undo_push(int n);
634 void do_undo();
635 void do_redo();
640 //encodes data in e as a midi event placed in buf
641 int midi_encode(mevent* e, int chan, unsigned char* buf, size_t* n);
643 //decodes midi data and creates a new mevent
644 int midi_decode(char* buf, mevent* e);
646 #endif