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
30 #include <fltk/Group.h>
31 #include <fltk/Widget.h>
32 #include <fltk/events.h>
49 extern struct conf config
;
51 Keyboard::Keyboard(int x
, int y
, int w
, int h
, const char* label
= 0) : fltk::Widget(x
, y
, w
, h
, label
) {
54 fltk::add_event_handler(keyboard_handler
);
56 for(int i
=0; i
<128; i
++){
71 int keyboard_handler(int e
, fltk::Window
* w
){
72 combo E
= combo(event_key(),event_state());
75 if(fltk::event_key_repeated()){
78 if(E
==combo(fltk::SpaceKey
,0)){
79 ui
->keyboard
->set_sustain(1);
81 else if(ui
->kg_od
->cmp(E
)){
82 ui
->keyboard
->octave_down();
84 else if(ui
->kg_ou
->cmp(E
)){
85 ui
->keyboard
->octave_up();
87 else if(ui
->kg_l0
->cmp(E
))
88 ui
->keyboard
->kb_play_note(0);
89 else if(ui
->kg_l1
->cmp(E
))
90 ui
->keyboard
->kb_play_note(1);
91 else if(ui
->kg_l2
->cmp(E
))
92 ui
->keyboard
->kb_play_note(2);
93 else if(ui
->kg_l3
->cmp(E
))
94 ui
->keyboard
->kb_play_note(3);
95 else if(ui
->kg_l4
->cmp(E
))
96 ui
->keyboard
->kb_play_note(4);
97 else if(ui
->kg_l5
->cmp(E
))
98 ui
->keyboard
->kb_play_note(5);
99 else if(ui
->kg_l6
->cmp(E
))
100 ui
->keyboard
->kb_play_note(6);
101 else if(ui
->kg_l7
->cmp(E
))
102 ui
->keyboard
->kb_play_note(7);
103 else if(ui
->kg_l8
->cmp(E
))
104 ui
->keyboard
->kb_play_note(8);
105 else if(ui
->kg_l9
->cmp(E
))
106 ui
->keyboard
->kb_play_note(9);
107 else if(ui
->kg_l10
->cmp(E
))
108 ui
->keyboard
->kb_play_note(10);
109 else if(ui
->kg_l11
->cmp(E
))
110 ui
->keyboard
->kb_play_note(11);
111 else if(ui
->kg_l12
->cmp(E
))
112 ui
->keyboard
->kb_play_note(12);
113 else if(ui
->kg_l13
->cmp(E
))
114 ui
->keyboard
->kb_play_note(13);
115 else if(ui
->kg_l14
->cmp(E
))
116 ui
->keyboard
->kb_play_note(14);
117 else if(ui
->kg_l15
->cmp(E
))
118 ui
->keyboard
->kb_play_note(15);
119 else if(ui
->kg_l16
->cmp(E
))
120 ui
->keyboard
->kb_play_note(16);
121 else if(ui
->kg_u0
->cmp(E
))
122 ui
->keyboard
->kb_play_note(12);
123 else if(ui
->kg_u1
->cmp(E
))
124 ui
->keyboard
->kb_play_note(13);
125 else if(ui
->kg_u2
->cmp(E
))
126 ui
->keyboard
->kb_play_note(14);
127 else if(ui
->kg_u3
->cmp(E
))
128 ui
->keyboard
->kb_play_note(15);
129 else if(ui
->kg_u4
->cmp(E
))
130 ui
->keyboard
->kb_play_note(16);
131 else if(ui
->kg_u5
->cmp(E
))
132 ui
->keyboard
->kb_play_note(17);
133 else if(ui
->kg_u6
->cmp(E
))
134 ui
->keyboard
->kb_play_note(18);
135 else if(ui
->kg_u7
->cmp(E
))
136 ui
->keyboard
->kb_play_note(19);
137 else if(ui
->kg_u8
->cmp(E
))
138 ui
->keyboard
->kb_play_note(20);
139 else if(ui
->kg_u9
->cmp(E
))
140 ui
->keyboard
->kb_play_note(21);
141 else if(ui
->kg_u10
->cmp(E
))
142 ui
->keyboard
->kb_play_note(22);
143 else if(ui
->kg_u11
->cmp(E
))
144 ui
->keyboard
->kb_play_note(23);
145 else if(ui
->kg_u12
->cmp(E
))
146 ui
->keyboard
->kb_play_note(24);
147 else if(ui
->kg_u13
->cmp(E
))
148 ui
->keyboard
->kb_play_note(25);
149 else if(ui
->kg_u14
->cmp(E
))
150 ui
->keyboard
->kb_play_note(26);
151 else if(ui
->kg_u15
->cmp(E
))
152 ui
->keyboard
->kb_play_note(27);
153 else if(ui
->kg_u16
->cmp(E
))
154 ui
->keyboard
->kb_play_note(28);
155 else if(ui
->kg_u17
->cmp(E
))
156 ui
->keyboard
->kb_play_note(29);
157 else if(ui
->kg_u18
->cmp(E
))
158 ui
->keyboard
->kb_play_note(30);
159 else if(ui
->kg_u19
->cmp(E
))
160 ui
->keyboard
->kb_play_note(31);
161 else if(ui
->kg_u20
->cmp(E
))
162 ui
->keyboard
->kb_play_note(32);
167 if(E
==combo(fltk::SpaceKey
,0)){
168 ui
->keyboard
->set_sustain(0);
170 else if(ui
->kg_l0
->cmp(E
))
171 ui
->keyboard
->kb_release_note(0);
172 else if(ui
->kg_l1
->cmp(E
))
173 ui
->keyboard
->kb_release_note(1);
174 else if(ui
->kg_l2
->cmp(E
))
175 ui
->keyboard
->kb_release_note(2);
176 else if(ui
->kg_l3
->cmp(E
))
177 ui
->keyboard
->kb_release_note(3);
178 else if(ui
->kg_l4
->cmp(E
))
179 ui
->keyboard
->kb_release_note(4);
180 else if(ui
->kg_l5
->cmp(E
))
181 ui
->keyboard
->kb_release_note(5);
182 else if(ui
->kg_l6
->cmp(E
))
183 ui
->keyboard
->kb_release_note(6);
184 else if(ui
->kg_l7
->cmp(E
))
185 ui
->keyboard
->kb_release_note(7);
186 else if(ui
->kg_l8
->cmp(E
))
187 ui
->keyboard
->kb_release_note(8);
188 else if(ui
->kg_l9
->cmp(E
))
189 ui
->keyboard
->kb_release_note(9);
190 else if(ui
->kg_l10
->cmp(E
))
191 ui
->keyboard
->kb_release_note(10);
192 else if(ui
->kg_l11
->cmp(E
))
193 ui
->keyboard
->kb_release_note(11);
194 else if(ui
->kg_l12
->cmp(E
))
195 ui
->keyboard
->kb_release_note(12);
196 else if(ui
->kg_l13
->cmp(E
))
197 ui
->keyboard
->kb_release_note(13);
198 else if(ui
->kg_l14
->cmp(E
))
199 ui
->keyboard
->kb_release_note(14);
200 else if(ui
->kg_l15
->cmp(E
))
201 ui
->keyboard
->kb_release_note(15);
202 else if(ui
->kg_l16
->cmp(E
))
203 ui
->keyboard
->kb_release_note(16);
204 else if(ui
->kg_u0
->cmp(E
))
205 ui
->keyboard
->kb_release_note(12);
206 else if(ui
->kg_u1
->cmp(E
))
207 ui
->keyboard
->kb_release_note(13);
208 else if(ui
->kg_u2
->cmp(E
))
209 ui
->keyboard
->kb_release_note(14);
210 else if(ui
->kg_u3
->cmp(E
))
211 ui
->keyboard
->kb_release_note(15);
212 else if(ui
->kg_u4
->cmp(E
))
213 ui
->keyboard
->kb_release_note(16);
214 else if(ui
->kg_u5
->cmp(E
))
215 ui
->keyboard
->kb_release_note(17);
216 else if(ui
->kg_u6
->cmp(E
))
217 ui
->keyboard
->kb_release_note(18);
218 else if(ui
->kg_u7
->cmp(E
))
219 ui
->keyboard
->kb_release_note(19);
220 else if(ui
->kg_u8
->cmp(E
))
221 ui
->keyboard
->kb_release_note(20);
222 else if(ui
->kg_u9
->cmp(E
))
223 ui
->keyboard
->kb_release_note(21);
224 else if(ui
->kg_u10
->cmp(E
))
225 ui
->keyboard
->kb_release_note(22);
226 else if(ui
->kg_u11
->cmp(E
))
227 ui
->keyboard
->kb_release_note(23);
228 else if(ui
->kg_u12
->cmp(E
))
229 ui
->keyboard
->kb_release_note(24);
230 else if(ui
->kg_u13
->cmp(E
))
231 ui
->keyboard
->kb_release_note(25);
232 else if(ui
->kg_u14
->cmp(E
))
233 ui
->keyboard
->kb_release_note(26);
234 else if(ui
->kg_u15
->cmp(E
))
235 ui
->keyboard
->kb_release_note(27);
236 else if(ui
->kg_u16
->cmp(E
))
237 ui
->keyboard
->kb_release_note(28);
238 else if(ui
->kg_u17
->cmp(E
))
239 ui
->keyboard
->kb_release_note(29);
240 else if(ui
->kg_u18
->cmp(E
))
241 ui
->keyboard
->kb_release_note(30);
242 else if(ui
->kg_u19
->cmp(E
))
243 ui
->keyboard
->kb_release_note(31);
244 else if(ui
->kg_u20
->cmp(E
))
245 ui
->keyboard
->kb_release_note(32);
252 void note_on(int note
, int vel
, int channel
){
256 void Keyboard::set_sustain(int state
){
259 for(int i
=0; i
<128; i
++){
260 if(ons
[i
]==1 && helds
[i
]==0){
268 int Keyboard::handle(int event
){
276 note
= ypix2note(event_y()+scroll
, event_x() < w()/2 ? 1 : 0);
277 if(note
< 0 || note
> 127){
295 note
= ypix2note(event_y()+scroll
, event_x() < w()/2 ? 1 : 0);
296 if(note
< 0 || note
> 127){
299 if(cur_note
!= note
){
313 void Keyboard::play_note(int note
, int rec
){
319 buf
[0] = 0x90 | cur_chan
;
321 buf
[2] = config
.defaultvelocity
;
322 send_midi(buf
,3,cur_port
);
327 if(rec
&& is_backend_recording()){
328 send_midi_local(buf
,3);
334 void Keyboard::release_note(int note
, int rec
){
346 buf
[0] = 0x80 | cur_chan
;
349 send_midi(buf
,3,cur_port
);
352 if(rec
&& is_backend_recording()){
353 send_midi_local(buf
,3);
359 void Keyboard::kb_play_note(int note
){
360 int raw
= octave
*12 + note
;
361 if(raw
< 128 && raw
>= 0){
366 void Keyboard::kb_release_note(int note
){
367 int raw
= octave
*12 + note
;
368 if(raw
< 128 && raw
>= 0){
373 void Keyboard::octave_up(){
380 void Keyboard::octave_down(){
387 void Keyboard::cut_notes(int rec
){
388 for(int i
=0; i
<128; i
++){
396 void Keyboard::draw(){
397 fltk::setcolor(fltk::WHITE
);
398 fltk::fillrect(0,0,w(),h());
400 fltk::push_clip(0,0,w(),h());
402 //draw held white notes
404 for(int i
=0; i
<128; i
++){
406 int Y
= note2ypix(i
,&black
)-scroll
;
408 fltk::setcolor(fltk::GRAY50
);
409 fltk::fillrect(0,Y
,w(),12);
414 fltk::setcolor(fltk::BLACK
);
415 for(int i
=1; i
<=75; i
++){
416 fltk::fillrect(0,i
*12-scroll
,w(),1);
420 for(int i
=0; i
<11; i
++){
421 j
= 900 - 12 - i
*12*7 - scroll
;
422 fltk::fillrect(0,j
-3,w()/2,7);
423 fltk::fillrect(0,j
-12-3,w()/2,7);
425 fltk::fillrect(0,j
-12*3-3,w()/2,7);
427 fltk::fillrect(0,j
-12*4-3,w()/2,7);
428 fltk::fillrect(0,j
-12*5-3,w()/2,7);
432 //draw held black notes
433 for(int i
=0; i
<128; i
++){
435 int Y
= note2ypix(i
,&black
)-scroll
;
437 fltk::setcolor(fltk::GRAY70
);
438 fltk::fillrect(1,Y
+1,w()/2 - 2,5);
447 KeyGrabber::KeyGrabber(int x
, int y
, int w
, int h
, const char* label
= 0) : fltk::Widget(x
, y
, w
, h
, label
) {
450 strncpy(str
,get_keystring(key
,mod
),32);
454 int KeyGrabber::handle(int event
){
470 case fltk::KeypadEnter
:
471 case fltk::MultiplyKey
:
473 case fltk::SubtractKey
:
474 case fltk::DecimalKey
:
475 case fltk::DivideKey
:
486 case fltk::KeypadLast
:
490 if(specialok
|| event_key()<0x80){
491 set_key(event_key(),event_state());
503 void KeyGrabber::draw(){
505 setfont(fltk::COURIER
,10);
506 fltk::push_clip(0,0,w(),h());
509 fltk::setcolor(fltk::color(128,128,255));
512 fltk::setcolor(fltk::WHITE
);
514 fillrect(2,2,w()-4,h()-4);
516 fltk::setcolor(fltk::BLACK
);
522 int KeyGrabber::set_key(int zkey
, int zmod
){
525 strncpy(str
,get_keystring(key
,mod
),32);
529 int KeyGrabber::set_key(combo c
){
532 strncpy(str
,get_keystring(key
,mod
),32);
536 int KeyGrabber::cmp(combo c
){
537 return (key
==c
.key
&& mod
==c
.mod
) ? 1 : 0;
540 void KeyGrabber::save(fstream
& f
){
541 f
<< key
<< " " << mod
<< endl
;
544 void KeyGrabber::load(fstream
& f
){
551 char keystring
[32] = "";
552 char* get_keystring(int key
, int mod
){
559 fltk::SHIFT, fltk::CAPSLOCK, fltk::CTRL, fltk::ALT,
560 fltk::NUMLOCK, fltk::META, fltk::SCROLLLOCK, fltk::BUTTON1,
561 fltk::BUTTON2, fltk::BUTTON3, fltk::ANY_BUTTON, fltk::ACCELERATOR,
562 fltk::COMMAND, fltk::OPTION
566 if(mod
&fltk::SHIFT
) strcpy(keystring
,"shft+");
567 else if(mod
&fltk::CTRL
) strcpy(keystring
,"ctrl+");
568 else if(mod
&fltk::ALT
) strcpy(keystring
,"alt+");
569 else if(mod
&fltk::META
) strcpy(keystring
,"meta+");
570 else if(mod
&fltk::OPTION
) strcpy(keystring
,"opt+");
572 int N
= strlen(keystring
);
574 fltk::LeftButton, fltk::MiddleButton, fltk::RightButton, fltk::SpaceKey,
575 fltk::BackSpaceKey, fltk::TabKey, fltk::ClearKey, fltk::ReturnKey,
576 fltk::PauseKey, fltk::ScrollLockKey, fltk::EscapeKey, fltk::HomeKey,
577 fltk::LeftKey, fltk::UpKey, fltk::RightKey, fltk::DownKey,
578 fltk::PageUpKey, fltk::PageDownKey, fltk::EndKey, fltk::PrintKey,
579 fltk::InsertKey, fltk::MenuKey, fltk::HelpKey, fltk::NumLockKey,
580 fltk::Keypad, fltk::KeypadEnter, fltk::MultiplyKey, fltk::AddKey,
581 fltk::SubtractKey, fltk::DecimalKey, fltk::DivideKey, fltk::Keypad0,
582 fltk::Keypad1, fltk::Keypad2, fltk::Keypad3, fltk::Keypad4,
583 fltk::Keypad5, fltk::Keypad6, fltk::Keypad7, fltk::Keypad8,
584 fltk::Keypad9, fltk::KeypadLast, fltk::F0Key, fltk::F1Key,
585 fltk::F2Key, fltk::F3Key, fltk::F4Key, fltk::F5Key,
586 fltk::F6Key, fltk::F7Key, fltk::F8Key, fltk::F9Key,
587 fltk::F10Key, fltk::F11Key, fltk::F12Key, fltk::LastFunctionKey,
588 fltk::LeftShiftKey, fltk::RightShiftKey, fltk::LeftCtrlKey, fltk::RightCtrlKey,
589 fltk::CapsLockKey, fltk::LeftMetaKey, fltk::RightMetaKey, fltk::LeftAltKey,
590 fltk::RightAltKey, fltk::DeleteKey, LeftAccKey, RightAccKey,
591 LeftCmdKey, RightCmdKey
597 case fltk::Keypad
: strcpy(keystring
+N
,"keypad"); break;
598 case fltk::KeypadEnter
: strcpy(keystring
+N
,"enter"); break;
599 case fltk::MultiplyKey
: strcpy(keystring
+N
,"mult"); break;
600 case fltk::AddKey
: strcpy(keystring
+N
,"plus"); break;
601 case fltk::SubtractKey
: strcpy(keystring
+N
,"minus"); break;
602 case fltk::DecimalKey
: strcpy(keystring
+N
,"dec"); break;
603 case fltk::DivideKey
: strcpy(keystring
+N
,"div"); break;
604 case fltk::Keypad0
: strcpy(keystring
+N
,"0"); break;
605 case fltk::Keypad1
: strcpy(keystring
+N
,"1"); break;
606 case fltk::Keypad2
: strcpy(keystring
+N
,"2"); break;
607 case fltk::Keypad3
: strcpy(keystring
+N
,"3"); break;
608 case fltk::Keypad4
: strcpy(keystring
+N
,"4"); break;
609 case fltk::Keypad5
: strcpy(keystring
+N
,"5"); break;
610 case fltk::Keypad6
: strcpy(keystring
+N
,"6"); break;
611 case fltk::Keypad7
: strcpy(keystring
+N
,"7"); break;
612 case fltk::Keypad8
: strcpy(keystring
+N
,"8"); break;
613 case fltk::Keypad9
: strcpy(keystring
+N
,"9"); break;
614 default: strcpy(keystring
+N
,k
); break;
621 void load_keymap(std::fstream
& f
){
672 void save_keymap(fstream
& f
){
673 f
<< "keymap" << endl
;
722 void load_default_keymap(){
723 ui
->kg_l0
->set_key('z',0);
724 ui
->kg_l1
->set_key('s',0);
725 ui
->kg_l2
->set_key('x',0);
726 ui
->kg_l3
->set_key('d',0);
727 ui
->kg_l4
->set_key('c',0);
728 ui
->kg_l5
->set_key('v',0);
729 ui
->kg_l6
->set_key('g',0);
730 ui
->kg_l7
->set_key('b',0);
731 ui
->kg_l8
->set_key('h',0);
732 ui
->kg_l9
->set_key('n',0);
733 ui
->kg_l10
->set_key('j',0);
734 ui
->kg_l11
->set_key('m',0);
735 ui
->kg_l12
->set_key(',',0);
736 ui
->kg_l13
->set_key('l',0);
737 ui
->kg_l14
->set_key('.',0);
738 ui
->kg_l15
->set_key(';',0);
739 ui
->kg_l16
->set_key('/',0);
741 ui
->kg_u0
->set_key('q',0);
742 ui
->kg_u1
->set_key('2',0);
743 ui
->kg_u2
->set_key('w',0);
744 ui
->kg_u3
->set_key('3',0);
745 ui
->kg_u4
->set_key('e',0);
746 ui
->kg_u5
->set_key('r',0);
747 ui
->kg_u6
->set_key('5',0);
748 ui
->kg_u7
->set_key('t',0);
749 ui
->kg_u8
->set_key('6',0);
750 ui
->kg_u9
->set_key('y',0);
751 ui
->kg_u10
->set_key('7',0);
752 ui
->kg_u11
->set_key('u',0);
753 ui
->kg_u12
->set_key('i',0);
754 ui
->kg_u13
->set_key('9',0);
755 ui
->kg_u14
->set_key('o',0);
756 ui
->kg_u15
->set_key('0',0);
757 ui
->kg_u16
->set_key('p',0);
758 ui
->kg_u17
->set_key('[',0);
759 ui
->kg_u18
->set_key('=',0);
760 ui
->kg_u19
->set_key(']',0);
761 ui
->kg_u20
->set_key('\\',0);
763 ui
->kg_ou
->set_key(']',fltk::SHIFT
);
764 ui
->kg_od
->set_key('[',fltk::SHIFT
);
765 ui
->kg_zi
->set_key('=',fltk::SHIFT
);
766 ui
->kg_zo
->set_key('-',fltk::SHIFT
);
772 int zoom_out_key(unsigned key
,unsigned mod
){
773 if(ui
->kg_zo
->cmp(combo(key
,mod
))){return 1;}
777 int zoom_in_key(unsigned key
,unsigned mod
){
778 if(ui
->kg_zi
->cmp(combo(key
,mod
))){return 1;}