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
++){
70 int keyboard_handler(int e
, fltk::Window
* w
){
71 combo E
= combo(event_key(),event_state());
74 if(fltk::event_key_repeated()){
77 if(E
==combo(fltk::SpaceKey
,0)){
78 ui
->keyboard
->set_sustain(1);
80 else if(ui
->kg_od
->cmp(E
)){
81 ui
->keyboard
->octave_down();
83 else if(ui
->kg_ou
->cmp(E
)){
84 ui
->keyboard
->octave_up();
86 else if(ui
->kg_l0
->cmp(E
))
87 ui
->keyboard
->kb_play_note(0);
88 else if(ui
->kg_l1
->cmp(E
))
89 ui
->keyboard
->kb_play_note(1);
90 else if(ui
->kg_l2
->cmp(E
))
91 ui
->keyboard
->kb_play_note(2);
92 else if(ui
->kg_l3
->cmp(E
))
93 ui
->keyboard
->kb_play_note(3);
94 else if(ui
->kg_l4
->cmp(E
))
95 ui
->keyboard
->kb_play_note(4);
96 else if(ui
->kg_l5
->cmp(E
))
97 ui
->keyboard
->kb_play_note(5);
98 else if(ui
->kg_l6
->cmp(E
))
99 ui
->keyboard
->kb_play_note(6);
100 else if(ui
->kg_l7
->cmp(E
))
101 ui
->keyboard
->kb_play_note(7);
102 else if(ui
->kg_l8
->cmp(E
))
103 ui
->keyboard
->kb_play_note(8);
104 else if(ui
->kg_l9
->cmp(E
))
105 ui
->keyboard
->kb_play_note(9);
106 else if(ui
->kg_l10
->cmp(E
))
107 ui
->keyboard
->kb_play_note(10);
108 else if(ui
->kg_l11
->cmp(E
))
109 ui
->keyboard
->kb_play_note(11);
110 else if(ui
->kg_l12
->cmp(E
))
111 ui
->keyboard
->kb_play_note(12);
112 else if(ui
->kg_l13
->cmp(E
))
113 ui
->keyboard
->kb_play_note(13);
114 else if(ui
->kg_l14
->cmp(E
))
115 ui
->keyboard
->kb_play_note(14);
116 else if(ui
->kg_l15
->cmp(E
))
117 ui
->keyboard
->kb_play_note(15);
118 else if(ui
->kg_l16
->cmp(E
))
119 ui
->keyboard
->kb_play_note(16);
120 else if(ui
->kg_u0
->cmp(E
))
121 ui
->keyboard
->kb_play_note(12);
122 else if(ui
->kg_u1
->cmp(E
))
123 ui
->keyboard
->kb_play_note(13);
124 else if(ui
->kg_u2
->cmp(E
))
125 ui
->keyboard
->kb_play_note(14);
126 else if(ui
->kg_u3
->cmp(E
))
127 ui
->keyboard
->kb_play_note(15);
128 else if(ui
->kg_u4
->cmp(E
))
129 ui
->keyboard
->kb_play_note(16);
130 else if(ui
->kg_u5
->cmp(E
))
131 ui
->keyboard
->kb_play_note(17);
132 else if(ui
->kg_u6
->cmp(E
))
133 ui
->keyboard
->kb_play_note(18);
134 else if(ui
->kg_u7
->cmp(E
))
135 ui
->keyboard
->kb_play_note(19);
136 else if(ui
->kg_u8
->cmp(E
))
137 ui
->keyboard
->kb_play_note(20);
138 else if(ui
->kg_u9
->cmp(E
))
139 ui
->keyboard
->kb_play_note(21);
140 else if(ui
->kg_u10
->cmp(E
))
141 ui
->keyboard
->kb_play_note(22);
142 else if(ui
->kg_u11
->cmp(E
))
143 ui
->keyboard
->kb_play_note(23);
144 else if(ui
->kg_u12
->cmp(E
))
145 ui
->keyboard
->kb_play_note(24);
146 else if(ui
->kg_u13
->cmp(E
))
147 ui
->keyboard
->kb_play_note(25);
148 else if(ui
->kg_u14
->cmp(E
))
149 ui
->keyboard
->kb_play_note(26);
150 else if(ui
->kg_u15
->cmp(E
))
151 ui
->keyboard
->kb_play_note(27);
152 else if(ui
->kg_u16
->cmp(E
))
153 ui
->keyboard
->kb_play_note(28);
154 else if(ui
->kg_u17
->cmp(E
))
155 ui
->keyboard
->kb_play_note(29);
156 else if(ui
->kg_u18
->cmp(E
))
157 ui
->keyboard
->kb_play_note(30);
158 else if(ui
->kg_u19
->cmp(E
))
159 ui
->keyboard
->kb_play_note(31);
160 else if(ui
->kg_u20
->cmp(E
))
161 ui
->keyboard
->kb_play_note(32);
166 if(E
==combo(fltk::SpaceKey
,0)){
167 ui
->keyboard
->set_sustain(0);
169 else if(ui
->kg_l0
->cmp(E
))
170 ui
->keyboard
->kb_release_note(0);
171 else if(ui
->kg_l1
->cmp(E
))
172 ui
->keyboard
->kb_release_note(1);
173 else if(ui
->kg_l2
->cmp(E
))
174 ui
->keyboard
->kb_release_note(2);
175 else if(ui
->kg_l3
->cmp(E
))
176 ui
->keyboard
->kb_release_note(3);
177 else if(ui
->kg_l4
->cmp(E
))
178 ui
->keyboard
->kb_release_note(4);
179 else if(ui
->kg_l5
->cmp(E
))
180 ui
->keyboard
->kb_release_note(5);
181 else if(ui
->kg_l6
->cmp(E
))
182 ui
->keyboard
->kb_release_note(6);
183 else if(ui
->kg_l7
->cmp(E
))
184 ui
->keyboard
->kb_release_note(7);
185 else if(ui
->kg_l8
->cmp(E
))
186 ui
->keyboard
->kb_release_note(8);
187 else if(ui
->kg_l9
->cmp(E
))
188 ui
->keyboard
->kb_release_note(9);
189 else if(ui
->kg_l10
->cmp(E
))
190 ui
->keyboard
->kb_release_note(10);
191 else if(ui
->kg_l11
->cmp(E
))
192 ui
->keyboard
->kb_release_note(11);
193 else if(ui
->kg_l12
->cmp(E
))
194 ui
->keyboard
->kb_release_note(12);
195 else if(ui
->kg_l13
->cmp(E
))
196 ui
->keyboard
->kb_release_note(13);
197 else if(ui
->kg_l14
->cmp(E
))
198 ui
->keyboard
->kb_release_note(14);
199 else if(ui
->kg_l15
->cmp(E
))
200 ui
->keyboard
->kb_release_note(15);
201 else if(ui
->kg_l16
->cmp(E
))
202 ui
->keyboard
->kb_release_note(16);
203 else if(ui
->kg_u0
->cmp(E
))
204 ui
->keyboard
->kb_release_note(12);
205 else if(ui
->kg_u1
->cmp(E
))
206 ui
->keyboard
->kb_release_note(13);
207 else if(ui
->kg_u2
->cmp(E
))
208 ui
->keyboard
->kb_release_note(14);
209 else if(ui
->kg_u3
->cmp(E
))
210 ui
->keyboard
->kb_release_note(15);
211 else if(ui
->kg_u4
->cmp(E
))
212 ui
->keyboard
->kb_release_note(16);
213 else if(ui
->kg_u5
->cmp(E
))
214 ui
->keyboard
->kb_release_note(17);
215 else if(ui
->kg_u6
->cmp(E
))
216 ui
->keyboard
->kb_release_note(18);
217 else if(ui
->kg_u7
->cmp(E
))
218 ui
->keyboard
->kb_release_note(19);
219 else if(ui
->kg_u8
->cmp(E
))
220 ui
->keyboard
->kb_release_note(20);
221 else if(ui
->kg_u9
->cmp(E
))
222 ui
->keyboard
->kb_release_note(21);
223 else if(ui
->kg_u10
->cmp(E
))
224 ui
->keyboard
->kb_release_note(22);
225 else if(ui
->kg_u11
->cmp(E
))
226 ui
->keyboard
->kb_release_note(23);
227 else if(ui
->kg_u12
->cmp(E
))
228 ui
->keyboard
->kb_release_note(24);
229 else if(ui
->kg_u13
->cmp(E
))
230 ui
->keyboard
->kb_release_note(25);
231 else if(ui
->kg_u14
->cmp(E
))
232 ui
->keyboard
->kb_release_note(26);
233 else if(ui
->kg_u15
->cmp(E
))
234 ui
->keyboard
->kb_release_note(27);
235 else if(ui
->kg_u16
->cmp(E
))
236 ui
->keyboard
->kb_release_note(28);
237 else if(ui
->kg_u17
->cmp(E
))
238 ui
->keyboard
->kb_release_note(29);
239 else if(ui
->kg_u18
->cmp(E
))
240 ui
->keyboard
->kb_release_note(30);
241 else if(ui
->kg_u19
->cmp(E
))
242 ui
->keyboard
->kb_release_note(31);
243 else if(ui
->kg_u20
->cmp(E
))
244 ui
->keyboard
->kb_release_note(32);
251 void note_on(int note
, int vel
, int channel
){
255 void Keyboard::set_sustain(int state
){
258 for(int i
=0; i
<128; i
++){
259 if(ons
[i
]==1 && helds
[i
]==0){
267 int Keyboard::handle(int event
){
275 note
= ypix2note(event_y()+scroll
, event_x() < w()/2 ? 1 : 0);
291 if(event_y() > h() || event_y() < 12){
294 note
= ypix2note(event_y()+scroll
, event_x() < w()/2 ? 1 : 0);
295 if(cur_note
!= note
){
309 void Keyboard::play_note(int note
, int rec
){
315 buf
[0] = 0x90 | cur_chan
;
317 buf
[2] = config
.defaultvelocity
;
318 send_midi(buf
,3,cur_port
);
323 if(rec
&& is_backend_recording()){
324 send_midi_local(buf
,3);
330 void Keyboard::release_note(int note
, int rec
){
342 buf
[0] = 0x80 | cur_chan
;
345 send_midi(buf
,3,cur_port
);
348 if(rec
&& is_backend_recording()){
349 send_midi_local(buf
,3);
355 void Keyboard::kb_play_note(int note
){
356 int raw
= octave
*12 + note
;
357 if(raw
< 128 && raw
>= 0){
362 void Keyboard::kb_release_note(int note
){
363 int raw
= octave
*12 + note
;
364 if(raw
< 128 && raw
>= 0){
369 void Keyboard::octave_up(){
376 void Keyboard::octave_down(){
383 void Keyboard::cut_notes(int rec
){
384 for(int i
=0; i
<128; i
++){
392 void Keyboard::draw(){
393 fltk::setcolor(fltk::WHITE
);
394 fltk::fillrect(0,0,w(),h());
396 fltk::push_clip(0,0,w(),h());
398 //draw held white notes
400 for(int i
=0; i
<128; i
++){
402 int Y
= note2ypix(i
,&black
)-scroll
;
404 fltk::setcolor(fltk::GRAY50
);
405 fltk::fillrect(0,Y
,w(),12);
410 fltk::setcolor(fltk::BLACK
);
411 for(int i
=-scroll
; i
<h(); i
+=12){
412 fltk::drawline(0,i
,w(),i
);
416 for(int i
=0; i
<11; i
++){
417 j
= 900 - 12 - i
*12*7 - scroll
;
418 fltk::fillrect(0,j
-3,w()/2,7);
419 fltk::fillrect(0,j
-12-3,w()/2,7);
421 fltk::fillrect(0,j
-12*3-3,w()/2,7);
423 fltk::fillrect(0,j
-12*4-3,w()/2,7);
424 fltk::fillrect(0,j
-12*5-3,w()/2,7);
428 //draw held black notes
429 for(int i
=0; i
<128; i
++){
431 int Y
= note2ypix(i
,&black
)-scroll
;
433 fltk::setcolor(fltk::GRAY70
);
434 fltk::fillrect(1,Y
+1,w()/2 - 2,5);
443 KeyGrabber::KeyGrabber(int x
, int y
, int w
, int h
, const char* label
= 0) : fltk::Widget(x
, y
, w
, h
, label
) {
446 strncpy(str
,get_keystring(key
,mod
),32);
450 int KeyGrabber::handle(int event
){
466 case fltk::KeypadEnter
:
467 case fltk::MultiplyKey
:
469 case fltk::SubtractKey
:
470 case fltk::DecimalKey
:
471 case fltk::DivideKey
:
482 case fltk::KeypadLast
:
486 if(specialok
|| event_key()<0x80){
487 set_key(event_key(),event_state());
499 void KeyGrabber::draw(){
501 setfont(fltk::COURIER
,10);
502 fltk::push_clip(0,0,w(),h());
505 fltk::setcolor(fltk::color(128,128,255));
508 fltk::setcolor(fltk::WHITE
);
510 fillrect(2,2,w()-4,h()-4);
512 fltk::setcolor(fltk::BLACK
);
518 int KeyGrabber::set_key(int zkey
, int zmod
){
521 strncpy(str
,get_keystring(key
,mod
),32);
525 int KeyGrabber::set_key(combo c
){
528 strncpy(str
,get_keystring(key
,mod
),32);
532 int KeyGrabber::cmp(combo c
){
533 return (key
==c
.key
&& mod
==c
.mod
) ? 1 : 0;
536 void KeyGrabber::save(fstream
& f
){
537 f
<< key
<< " " << mod
<< endl
;
540 void KeyGrabber::load(fstream
& f
){
547 char keystring
[32] = "";
548 char* get_keystring(int key
, int mod
){
555 fltk::SHIFT, fltk::CAPSLOCK, fltk::CTRL, fltk::ALT,
556 fltk::NUMLOCK, fltk::META, fltk::SCROLLLOCK, fltk::BUTTON1,
557 fltk::BUTTON2, fltk::BUTTON3, fltk::ANY_BUTTON, fltk::ACCELERATOR,
558 fltk::COMMAND, fltk::OPTION
562 if(mod
&fltk::SHIFT
) strcpy(keystring
,"shft+");
563 else if(mod
&fltk::CTRL
) strcpy(keystring
,"ctrl+");
564 else if(mod
&fltk::ALT
) strcpy(keystring
,"alt+");
565 else if(mod
&fltk::META
) strcpy(keystring
,"meta+");
566 else if(mod
&fltk::OPTION
) strcpy(keystring
,"opt+");
568 int N
= strlen(keystring
);
570 fltk::LeftButton, fltk::MiddleButton, fltk::RightButton, fltk::SpaceKey,
571 fltk::BackSpaceKey, fltk::TabKey, fltk::ClearKey, fltk::ReturnKey,
572 fltk::PauseKey, fltk::ScrollLockKey, fltk::EscapeKey, fltk::HomeKey,
573 fltk::LeftKey, fltk::UpKey, fltk::RightKey, fltk::DownKey,
574 fltk::PageUpKey, fltk::PageDownKey, fltk::EndKey, fltk::PrintKey,
575 fltk::InsertKey, fltk::MenuKey, fltk::HelpKey, fltk::NumLockKey,
576 fltk::Keypad, fltk::KeypadEnter, fltk::MultiplyKey, fltk::AddKey,
577 fltk::SubtractKey, fltk::DecimalKey, fltk::DivideKey, fltk::Keypad0,
578 fltk::Keypad1, fltk::Keypad2, fltk::Keypad3, fltk::Keypad4,
579 fltk::Keypad5, fltk::Keypad6, fltk::Keypad7, fltk::Keypad8,
580 fltk::Keypad9, fltk::KeypadLast, fltk::F0Key, fltk::F1Key,
581 fltk::F2Key, fltk::F3Key, fltk::F4Key, fltk::F5Key,
582 fltk::F6Key, fltk::F7Key, fltk::F8Key, fltk::F9Key,
583 fltk::F10Key, fltk::F11Key, fltk::F12Key, fltk::LastFunctionKey,
584 fltk::LeftShiftKey, fltk::RightShiftKey, fltk::LeftCtrlKey, fltk::RightCtrlKey,
585 fltk::CapsLockKey, fltk::LeftMetaKey, fltk::RightMetaKey, fltk::LeftAltKey,
586 fltk::RightAltKey, fltk::DeleteKey, LeftAccKey, RightAccKey,
587 LeftCmdKey, RightCmdKey
593 case fltk::Keypad
: strcpy(keystring
+N
,"keypad"); break;
594 case fltk::KeypadEnter
: strcpy(keystring
+N
,"enter"); break;
595 case fltk::MultiplyKey
: strcpy(keystring
+N
,"mult"); break;
596 case fltk::AddKey
: strcpy(keystring
+N
,"plus"); break;
597 case fltk::SubtractKey
: strcpy(keystring
+N
,"minus"); break;
598 case fltk::DecimalKey
: strcpy(keystring
+N
,"dec"); break;
599 case fltk::DivideKey
: strcpy(keystring
+N
,"div"); break;
600 case fltk::Keypad0
: strcpy(keystring
+N
,"0"); break;
601 case fltk::Keypad1
: strcpy(keystring
+N
,"1"); break;
602 case fltk::Keypad2
: strcpy(keystring
+N
,"2"); break;
603 case fltk::Keypad3
: strcpy(keystring
+N
,"3"); break;
604 case fltk::Keypad4
: strcpy(keystring
+N
,"4"); break;
605 case fltk::Keypad5
: strcpy(keystring
+N
,"5"); break;
606 case fltk::Keypad6
: strcpy(keystring
+N
,"6"); break;
607 case fltk::Keypad7
: strcpy(keystring
+N
,"7"); break;
608 case fltk::Keypad8
: strcpy(keystring
+N
,"8"); break;
609 case fltk::Keypad9
: strcpy(keystring
+N
,"9"); break;
610 default: strcpy(keystring
+N
,k
); break;
617 void load_keymap(std::fstream
& f
){
668 void save_keymap(fstream
& f
){
669 f
<< "keymap" << endl
;
718 void load_default_keymap(){
719 ui
->kg_l0
->set_key('z',0);
720 ui
->kg_l1
->set_key('s',0);
721 ui
->kg_l2
->set_key('x',0);
722 ui
->kg_l3
->set_key('d',0);
723 ui
->kg_l4
->set_key('c',0);
724 ui
->kg_l5
->set_key('v',0);
725 ui
->kg_l6
->set_key('g',0);
726 ui
->kg_l7
->set_key('b',0);
727 ui
->kg_l8
->set_key('h',0);
728 ui
->kg_l9
->set_key('n',0);
729 ui
->kg_l10
->set_key('j',0);
730 ui
->kg_l11
->set_key('m',0);
731 ui
->kg_l12
->set_key(',',0);
732 ui
->kg_l13
->set_key('l',0);
733 ui
->kg_l14
->set_key('.',0);
734 ui
->kg_l15
->set_key(';',0);
735 ui
->kg_l16
->set_key('/',0);
737 ui
->kg_u0
->set_key('q',0);
738 ui
->kg_u1
->set_key('2',0);
739 ui
->kg_u2
->set_key('w',0);
740 ui
->kg_u3
->set_key('3',0);
741 ui
->kg_u4
->set_key('e',0);
742 ui
->kg_u5
->set_key('r',0);
743 ui
->kg_u6
->set_key('5',0);
744 ui
->kg_u7
->set_key('t',0);
745 ui
->kg_u8
->set_key('6',0);
746 ui
->kg_u9
->set_key('y',0);
747 ui
->kg_u10
->set_key('7',0);
748 ui
->kg_u11
->set_key('u',0);
749 ui
->kg_u12
->set_key('i',0);
750 ui
->kg_u13
->set_key('9',0);
751 ui
->kg_u14
->set_key('o',0);
752 ui
->kg_u15
->set_key('0',0);
753 ui
->kg_u16
->set_key('p',0);
754 ui
->kg_u17
->set_key('[',0);
755 ui
->kg_u18
->set_key('=',0);
756 ui
->kg_u19
->set_key(']',0);
757 ui
->kg_u20
->set_key('\\',0);
759 ui
->kg_ou
->set_key(']',fltk::SHIFT
);
760 ui
->kg_od
->set_key('[',fltk::SHIFT
);
761 ui
->kg_zi
->set_key('=',fltk::SHIFT
);
762 ui
->kg_zo
->set_key('-',fltk::SHIFT
);
768 int zoom_out_key(unsigned key
,unsigned mod
){
769 if(ui
->kg_zo
->cmp(combo(key
,mod
))){return 1;}
773 int zoom_in_key(unsigned key
,unsigned mod
){
774 if(ui
->kg_zi
->cmp(combo(key
,mod
))){return 1;}