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
;
52 #define MOD_MASK (fltk::SHIFT|fltk::CTRL|fltk::ALT|fltk::META|fltk::OPTION)
55 Keyboard::Keyboard(int x
, int y
, int w
, int h
, const char* label
= 0) : fltk::Widget(x
, y
, w
, h
, label
) {
58 fltk::add_event_handler(keyboard_handler
);
60 for(int i
=0; i
<128; i
++){
75 int keyboard_handler(int e
, fltk::Window
* w
){
76 combo E
= combo(event_key(),event_state()&MOD_MASK
);
79 if(fltk::event_key_repeated()){
82 if(E
==combo(fltk::SpaceKey
,0)){
83 ui
->keyboard
->set_sustain(1);
85 else if(E
==combo('z',fltk::CTRL
)){
87 ui
->main_window
->redraw();
89 else if(E
==combo('r',fltk::CTRL
)){
91 ui
->main_window
->redraw();
93 else if(ui
->kg_od
->cmp(E
)){
94 ui
->keyboard
->octave_down();
96 else if(ui
->kg_ou
->cmp(E
)){
97 ui
->keyboard
->octave_up();
99 else if(ui
->kg_l0
->cmp(E
))
100 ui
->keyboard
->kb_play_note(0);
101 else if(ui
->kg_l1
->cmp(E
))
102 ui
->keyboard
->kb_play_note(1);
103 else if(ui
->kg_l2
->cmp(E
))
104 ui
->keyboard
->kb_play_note(2);
105 else if(ui
->kg_l3
->cmp(E
))
106 ui
->keyboard
->kb_play_note(3);
107 else if(ui
->kg_l4
->cmp(E
))
108 ui
->keyboard
->kb_play_note(4);
109 else if(ui
->kg_l5
->cmp(E
))
110 ui
->keyboard
->kb_play_note(5);
111 else if(ui
->kg_l6
->cmp(E
))
112 ui
->keyboard
->kb_play_note(6);
113 else if(ui
->kg_l7
->cmp(E
))
114 ui
->keyboard
->kb_play_note(7);
115 else if(ui
->kg_l8
->cmp(E
))
116 ui
->keyboard
->kb_play_note(8);
117 else if(ui
->kg_l9
->cmp(E
))
118 ui
->keyboard
->kb_play_note(9);
119 else if(ui
->kg_l10
->cmp(E
))
120 ui
->keyboard
->kb_play_note(10);
121 else if(ui
->kg_l11
->cmp(E
))
122 ui
->keyboard
->kb_play_note(11);
123 else if(ui
->kg_l12
->cmp(E
))
124 ui
->keyboard
->kb_play_note(12);
125 else if(ui
->kg_l13
->cmp(E
))
126 ui
->keyboard
->kb_play_note(13);
127 else if(ui
->kg_l14
->cmp(E
))
128 ui
->keyboard
->kb_play_note(14);
129 else if(ui
->kg_l15
->cmp(E
))
130 ui
->keyboard
->kb_play_note(15);
131 else if(ui
->kg_l16
->cmp(E
))
132 ui
->keyboard
->kb_play_note(16);
133 else if(ui
->kg_u0
->cmp(E
))
134 ui
->keyboard
->kb_play_note(12);
135 else if(ui
->kg_u1
->cmp(E
))
136 ui
->keyboard
->kb_play_note(13);
137 else if(ui
->kg_u2
->cmp(E
))
138 ui
->keyboard
->kb_play_note(14);
139 else if(ui
->kg_u3
->cmp(E
))
140 ui
->keyboard
->kb_play_note(15);
141 else if(ui
->kg_u4
->cmp(E
))
142 ui
->keyboard
->kb_play_note(16);
143 else if(ui
->kg_u5
->cmp(E
))
144 ui
->keyboard
->kb_play_note(17);
145 else if(ui
->kg_u6
->cmp(E
))
146 ui
->keyboard
->kb_play_note(18);
147 else if(ui
->kg_u7
->cmp(E
))
148 ui
->keyboard
->kb_play_note(19);
149 else if(ui
->kg_u8
->cmp(E
))
150 ui
->keyboard
->kb_play_note(20);
151 else if(ui
->kg_u9
->cmp(E
))
152 ui
->keyboard
->kb_play_note(21);
153 else if(ui
->kg_u10
->cmp(E
))
154 ui
->keyboard
->kb_play_note(22);
155 else if(ui
->kg_u11
->cmp(E
))
156 ui
->keyboard
->kb_play_note(23);
157 else if(ui
->kg_u12
->cmp(E
))
158 ui
->keyboard
->kb_play_note(24);
159 else if(ui
->kg_u13
->cmp(E
))
160 ui
->keyboard
->kb_play_note(25);
161 else if(ui
->kg_u14
->cmp(E
))
162 ui
->keyboard
->kb_play_note(26);
163 else if(ui
->kg_u15
->cmp(E
))
164 ui
->keyboard
->kb_play_note(27);
165 else if(ui
->kg_u16
->cmp(E
))
166 ui
->keyboard
->kb_play_note(28);
167 else if(ui
->kg_u17
->cmp(E
))
168 ui
->keyboard
->kb_play_note(29);
169 else if(ui
->kg_u18
->cmp(E
))
170 ui
->keyboard
->kb_play_note(30);
171 else if(ui
->kg_u19
->cmp(E
))
172 ui
->keyboard
->kb_play_note(31);
173 else if(ui
->kg_u20
->cmp(E
))
174 ui
->keyboard
->kb_play_note(32);
179 if(E
==combo(fltk::SpaceKey
,0)){
180 ui
->keyboard
->set_sustain(0);
182 else if(ui
->kg_l0
->cmp(E
))
183 ui
->keyboard
->kb_release_note(0);
184 else if(ui
->kg_l1
->cmp(E
))
185 ui
->keyboard
->kb_release_note(1);
186 else if(ui
->kg_l2
->cmp(E
))
187 ui
->keyboard
->kb_release_note(2);
188 else if(ui
->kg_l3
->cmp(E
))
189 ui
->keyboard
->kb_release_note(3);
190 else if(ui
->kg_l4
->cmp(E
))
191 ui
->keyboard
->kb_release_note(4);
192 else if(ui
->kg_l5
->cmp(E
))
193 ui
->keyboard
->kb_release_note(5);
194 else if(ui
->kg_l6
->cmp(E
))
195 ui
->keyboard
->kb_release_note(6);
196 else if(ui
->kg_l7
->cmp(E
))
197 ui
->keyboard
->kb_release_note(7);
198 else if(ui
->kg_l8
->cmp(E
))
199 ui
->keyboard
->kb_release_note(8);
200 else if(ui
->kg_l9
->cmp(E
))
201 ui
->keyboard
->kb_release_note(9);
202 else if(ui
->kg_l10
->cmp(E
))
203 ui
->keyboard
->kb_release_note(10);
204 else if(ui
->kg_l11
->cmp(E
))
205 ui
->keyboard
->kb_release_note(11);
206 else if(ui
->kg_l12
->cmp(E
))
207 ui
->keyboard
->kb_release_note(12);
208 else if(ui
->kg_l13
->cmp(E
))
209 ui
->keyboard
->kb_release_note(13);
210 else if(ui
->kg_l14
->cmp(E
))
211 ui
->keyboard
->kb_release_note(14);
212 else if(ui
->kg_l15
->cmp(E
))
213 ui
->keyboard
->kb_release_note(15);
214 else if(ui
->kg_l16
->cmp(E
))
215 ui
->keyboard
->kb_release_note(16);
216 else if(ui
->kg_u0
->cmp(E
))
217 ui
->keyboard
->kb_release_note(12);
218 else if(ui
->kg_u1
->cmp(E
))
219 ui
->keyboard
->kb_release_note(13);
220 else if(ui
->kg_u2
->cmp(E
))
221 ui
->keyboard
->kb_release_note(14);
222 else if(ui
->kg_u3
->cmp(E
))
223 ui
->keyboard
->kb_release_note(15);
224 else if(ui
->kg_u4
->cmp(E
))
225 ui
->keyboard
->kb_release_note(16);
226 else if(ui
->kg_u5
->cmp(E
))
227 ui
->keyboard
->kb_release_note(17);
228 else if(ui
->kg_u6
->cmp(E
))
229 ui
->keyboard
->kb_release_note(18);
230 else if(ui
->kg_u7
->cmp(E
))
231 ui
->keyboard
->kb_release_note(19);
232 else if(ui
->kg_u8
->cmp(E
))
233 ui
->keyboard
->kb_release_note(20);
234 else if(ui
->kg_u9
->cmp(E
))
235 ui
->keyboard
->kb_release_note(21);
236 else if(ui
->kg_u10
->cmp(E
))
237 ui
->keyboard
->kb_release_note(22);
238 else if(ui
->kg_u11
->cmp(E
))
239 ui
->keyboard
->kb_release_note(23);
240 else if(ui
->kg_u12
->cmp(E
))
241 ui
->keyboard
->kb_release_note(24);
242 else if(ui
->kg_u13
->cmp(E
))
243 ui
->keyboard
->kb_release_note(25);
244 else if(ui
->kg_u14
->cmp(E
))
245 ui
->keyboard
->kb_release_note(26);
246 else if(ui
->kg_u15
->cmp(E
))
247 ui
->keyboard
->kb_release_note(27);
248 else if(ui
->kg_u16
->cmp(E
))
249 ui
->keyboard
->kb_release_note(28);
250 else if(ui
->kg_u17
->cmp(E
))
251 ui
->keyboard
->kb_release_note(29);
252 else if(ui
->kg_u18
->cmp(E
))
253 ui
->keyboard
->kb_release_note(30);
254 else if(ui
->kg_u19
->cmp(E
))
255 ui
->keyboard
->kb_release_note(31);
256 else if(ui
->kg_u20
->cmp(E
))
257 ui
->keyboard
->kb_release_note(32);
264 void note_on(int note
, int vel
, int channel
){
268 void Keyboard::set_sustain(int state
){
271 for(int i
=0; i
<128; i
++){
272 if(ons
[i
]==1 && helds
[i
]==0){
280 int Keyboard::handle(int event
){
288 note
= ypix2note(event_y()+scroll
, event_x() < w()/2 ? 1 : 0);
289 if(note
< 0 || note
> 127){
307 note
= ypix2note(event_y()+scroll
, event_x() < w()/2 ? 1 : 0);
308 if(note
< 0 || note
> 127){
311 if(cur_note
!= note
){
325 void Keyboard::play_note(int note
, int rec
){
331 buf
[0] = 0x90 | cur_chan
;
333 buf
[2] = config
.defaultvelocity
;
334 send_midi(buf
,3,cur_port
);
339 if(rec
&& is_backend_recording()){
340 send_midi_local(buf
,3);
346 void Keyboard::release_note(int note
, int rec
){
358 buf
[0] = 0x80 | cur_chan
;
361 send_midi(buf
,3,cur_port
);
364 if(rec
&& is_backend_recording()){
365 send_midi_local(buf
,3);
371 void Keyboard::kb_play_note(int note
){
372 int raw
= octave
*12 + note
;
373 if(raw
< 128 && raw
>= 0){
378 void Keyboard::kb_release_note(int note
){
379 int raw
= octave
*12 + note
;
380 if(raw
< 128 && raw
>= 0){
385 void Keyboard::octave_up(){
392 void Keyboard::octave_down(){
399 void Keyboard::cut_notes(int rec
){
400 for(int i
=0; i
<128; i
++){
408 void Keyboard::highlight_note(int note
){
415 void Keyboard::highlight_clear(){
423 void Keyboard::draw(){
424 fltk::setcolor(fltk::WHITE
);
425 fltk::fillrect(0,0,w(),h());
427 fltk::push_clip(0,0,w(),h());
429 //draw held white notes
431 for(int i
=0; i
<128; i
++){
432 if(ons
[i
] || i
==highlight
){
433 int Y
= note2ypix(i
,&black
)-scroll
;
435 fltk::setcolor(fltk::GRAY50
);
436 fltk::fillrect(0,Y
,w(),12);
441 fltk::setcolor(fltk::BLACK
);
442 for(int i
=1; i
<=75; i
++){
443 fltk::fillrect(0,i
*12-scroll
,w(),1);
447 for(int i
=0; i
<11; i
++){
448 j
= 900 - 12 - i
*12*7 - scroll
;
449 fltk::fillrect(0,j
-3,w()/2,7);
450 fltk::fillrect(0,j
-12-3,w()/2,7);
452 fltk::fillrect(0,j
-12*3-3,w()/2,7);
454 fltk::fillrect(0,j
-12*4-3,w()/2,7);
455 fltk::fillrect(0,j
-12*5-3,w()/2,7);
459 //draw held black notes
460 for(int i
=0; i
<128; i
++){
461 if(ons
[i
] || i
== highlight
){
462 int Y
= note2ypix(i
,&black
)-scroll
;
464 fltk::setcolor(fltk::GRAY70
);
465 fltk::fillrect(1,Y
+1,w()/2 - 2,5);
474 KeyGrabber::KeyGrabber(int x
, int y
, int w
, int h
, const char* label
= 0) : fltk::Widget(x
, y
, w
, h
, label
) {
477 strncpy(str
,get_keystring(key
,mod
),32);
481 int KeyGrabber::handle(int event
){
497 case fltk::KeypadEnter
:
498 case fltk::MultiplyKey
:
500 case fltk::SubtractKey
:
501 case fltk::DecimalKey
:
502 case fltk::DivideKey
:
513 case fltk::KeypadLast
:
514 case fltk::PageUpKey
:
515 case fltk::PageDownKey
:
521 if(specialok
|| event_key()<0x80){
522 set_key(event_key(),event_state());
534 void KeyGrabber::draw(){
536 setfont(fltk::COURIER
,10);
537 fltk::push_clip(0,0,w(),h());
540 fltk::setcolor(fltk::color(128,128,255));
543 fltk::setcolor(fltk::WHITE
);
545 fillrect(2,2,w()-4,h()-4);
547 fltk::setcolor(fltk::BLACK
);
553 int KeyGrabber::set_key(int zkey
, int zmod
){
556 strncpy(str
,get_keystring(key
,mod
),32);
560 int KeyGrabber::set_key(combo c
){
563 strncpy(str
,get_keystring(key
,mod
),32);
567 int KeyGrabber::cmp(combo c
){
568 return (key
==c
.key
&& mod
==c
.mod
) ? 1 : 0;
571 void KeyGrabber::save(fstream
& f
){
572 f
<< key
<< " " << mod
<< endl
;
575 void KeyGrabber::load(fstream
& f
){
582 char keystring
[32] = "";
583 char* get_keystring(int key
, int mod
){
590 fltk::SHIFT, fltk::CAPSLOCK, fltk::CTRL, fltk::ALT,
591 fltk::NUMLOCK, fltk::META, fltk::SCROLLLOCK, fltk::BUTTON1,
592 fltk::BUTTON2, fltk::BUTTON3, fltk::ANY_BUTTON, fltk::ACCELERATOR,
593 fltk::COMMAND, fltk::OPTION
597 if(mod
&fltk::SHIFT
) strcpy(keystring
,"shft+");
598 else if(mod
&fltk::CTRL
) strcpy(keystring
,"ctrl+");
599 else if(mod
&fltk::ALT
) strcpy(keystring
,"alt+");
600 else if(mod
&fltk::META
) strcpy(keystring
,"meta+");
601 else if(mod
&fltk::OPTION
) strcpy(keystring
,"opt+");
603 int N
= strlen(keystring
);
605 fltk::LeftButton, fltk::MiddleButton, fltk::RightButton, fltk::SpaceKey,
606 fltk::BackSpaceKey, fltk::TabKey, fltk::ClearKey, fltk::ReturnKey,
607 fltk::PauseKey, fltk::ScrollLockKey, fltk::EscapeKey, fltk::HomeKey,
608 fltk::LeftKey, fltk::UpKey, fltk::RightKey, fltk::DownKey,
609 fltk::PageUpKey, fltk::PageDownKey, fltk::EndKey, fltk::PrintKey,
610 fltk::InsertKey, fltk::MenuKey, fltk::HelpKey, fltk::NumLockKey,
611 fltk::Keypad, fltk::KeypadEnter, fltk::MultiplyKey, fltk::AddKey,
612 fltk::SubtractKey, fltk::DecimalKey, fltk::DivideKey, fltk::Keypad0,
613 fltk::Keypad1, fltk::Keypad2, fltk::Keypad3, fltk::Keypad4,
614 fltk::Keypad5, fltk::Keypad6, fltk::Keypad7, fltk::Keypad8,
615 fltk::Keypad9, fltk::KeypadLast, fltk::F0Key, fltk::F1Key,
616 fltk::F2Key, fltk::F3Key, fltk::F4Key, fltk::F5Key,
617 fltk::F6Key, fltk::F7Key, fltk::F8Key, fltk::F9Key,
618 fltk::F10Key, fltk::F11Key, fltk::F12Key, fltk::LastFunctionKey,
619 fltk::LeftShiftKey, fltk::RightShiftKey, fltk::LeftCtrlKey, fltk::RightCtrlKey,
620 fltk::CapsLockKey, fltk::LeftMetaKey, fltk::RightMetaKey, fltk::LeftAltKey,
621 fltk::RightAltKey, fltk::DeleteKey, LeftAccKey, RightAccKey,
622 LeftCmdKey, RightCmdKey
628 case fltk::Keypad
: strcpy(keystring
+N
,"keypad"); break;
629 case fltk::KeypadEnter
: strcpy(keystring
+N
,"enter"); break;
630 case fltk::MultiplyKey
: strcpy(keystring
+N
,"mult"); break;
631 case fltk::AddKey
: strcpy(keystring
+N
,"plus"); break;
632 case fltk::SubtractKey
: strcpy(keystring
+N
,"minus"); break;
633 case fltk::DecimalKey
: strcpy(keystring
+N
,"dec"); break;
634 case fltk::DivideKey
: strcpy(keystring
+N
,"div"); break;
635 case fltk::Keypad0
: strcpy(keystring
+N
,"0"); break;
636 case fltk::Keypad1
: strcpy(keystring
+N
,"1"); break;
637 case fltk::Keypad2
: strcpy(keystring
+N
,"2"); break;
638 case fltk::Keypad3
: strcpy(keystring
+N
,"3"); break;
639 case fltk::Keypad4
: strcpy(keystring
+N
,"4"); break;
640 case fltk::Keypad5
: strcpy(keystring
+N
,"5"); break;
641 case fltk::Keypad6
: strcpy(keystring
+N
,"6"); break;
642 case fltk::Keypad7
: strcpy(keystring
+N
,"7"); break;
643 case fltk::Keypad8
: strcpy(keystring
+N
,"8"); break;
644 case fltk::Keypad9
: strcpy(keystring
+N
,"9"); break;
645 case fltk::PageUpKey
: strcpy(keystring
+N
,"pgup"); break;
646 case fltk::PageDownKey
: strcpy(keystring
+N
,"pgdn"); break;
647 case fltk::HomeKey
: strcpy(keystring
+N
,"home"); break;
648 case fltk::EndKey
: strcpy(keystring
+N
,"end"); break;
649 default: strcpy(keystring
+N
,k
); break;
656 void load_keymap(std::fstream
& f
){
707 void save_keymap(fstream
& f
){
708 f
<< "keymap" << endl
;
757 void load_default_keymap(){
758 ui
->kg_l0
->set_key('z',0);
759 ui
->kg_l1
->set_key('s',0);
760 ui
->kg_l2
->set_key('x',0);
761 ui
->kg_l3
->set_key('d',0);
762 ui
->kg_l4
->set_key('c',0);
763 ui
->kg_l5
->set_key('v',0);
764 ui
->kg_l6
->set_key('g',0);
765 ui
->kg_l7
->set_key('b',0);
766 ui
->kg_l8
->set_key('h',0);
767 ui
->kg_l9
->set_key('n',0);
768 ui
->kg_l10
->set_key('j',0);
769 ui
->kg_l11
->set_key('m',0);
770 ui
->kg_l12
->set_key(',',0);
771 ui
->kg_l13
->set_key('l',0);
772 ui
->kg_l14
->set_key('.',0);
773 ui
->kg_l15
->set_key(';',0);
774 ui
->kg_l16
->set_key('/',0);
776 ui
->kg_u0
->set_key('q',0);
777 ui
->kg_u1
->set_key('2',0);
778 ui
->kg_u2
->set_key('w',0);
779 ui
->kg_u3
->set_key('3',0);
780 ui
->kg_u4
->set_key('e',0);
781 ui
->kg_u5
->set_key('r',0);
782 ui
->kg_u6
->set_key('5',0);
783 ui
->kg_u7
->set_key('t',0);
784 ui
->kg_u8
->set_key('6',0);
785 ui
->kg_u9
->set_key('y',0);
786 ui
->kg_u10
->set_key('7',0);
787 ui
->kg_u11
->set_key('u',0);
788 ui
->kg_u12
->set_key('i',0);
789 ui
->kg_u13
->set_key('9',0);
790 ui
->kg_u14
->set_key('o',0);
791 ui
->kg_u15
->set_key('0',0);
792 ui
->kg_u16
->set_key('p',0);
793 ui
->kg_u17
->set_key('[',0);
794 ui
->kg_u18
->set_key('=',0);
795 ui
->kg_u19
->set_key(']',0);
796 ui
->kg_u20
->set_key('\\',0);
798 ui
->kg_ou
->set_key(']',fltk::SHIFT
);
799 ui
->kg_od
->set_key('[',fltk::SHIFT
);
800 ui
->kg_zi
->set_key('=',fltk::SHIFT
);
801 ui
->kg_zo
->set_key('-',fltk::SHIFT
);
807 int zoom_out_key(unsigned key
,unsigned mod
){
808 if(ui
->kg_zo
->cmp(combo(key
,mod
&MOD_MASK
))){return 1;}
812 int zoom_in_key(unsigned key
,unsigned mod
){
813 if(ui
->kg_zi
->cmp(combo(key
,mod
&MOD_MASK
))){return 1;}