Update comments & icon of rubberband example Lua script
[ardour.git] / gtk2_ardour / pianokeyboard.cc
1 /* Piano-keyboard based on jack-keyboard
2  *
3  * Copyright (C) 2019 Robin Gareus <robin@gareus.org>
4  * Copyright (c) 2007, 2008 Edward Tomasz NapieraƂa <trasz@FreeBSD.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <assert.h>
22 #include <math.h>
23 #include <stdint.h>
24 #include <string.h>
25
26 #include <cairo/cairo.h>
27 #include <pango/pango.h>
28 #include <pango/pangocairo.h>
29
30 #include <gdk/gdkkeysyms.h>
31 #include <gtk/gtk.h>
32
33 #include "gtkmm2ext/keyboard.h"
34
35 #include "pianokeyboard.h"
36
37 #ifndef M_PI
38 #  define M_PI 3.14159265358979323846
39 #endif
40
41 #ifndef MIN
42 #  define MIN(A, B) ((A) < (B)) ? (A) : (B)
43 #endif
44
45 #ifndef MAX
46 #  define MAX(A, B) ((A) > (B)) ? (A) : (B)
47 #endif
48
49 #define PIANO_KEYBOARD_DEFAULT_WIDTH 730
50 #define PIANO_KEYBOARD_DEFAULT_HEIGHT 70
51
52 #define PIANO_MIN_NOTE 21
53 #define PIANO_MAX_NOTE 108
54 #define OCTAVE_MIN (-1)
55 #define OCTAVE_MAX (7)
56
57 void
58 APianoKeyboard::annotate_layout (cairo_t* cr, int note) const
59 {
60         int nkey = note - _octave * 12;
61
62         if (nkey < 0 || nkey >= NNOTES) {
63                 return;
64         }
65
66         std::map<int, std::string>::const_iterator kv = _note_bindings.find (nkey);
67         if (kv == _note_bindings.end ()) {
68                 return;
69         }
70
71         int x = _notes[note].x;
72         int w = _notes[note].w;
73         int h = _notes[note].h;
74
75         int  tw, th;
76         char buf[32];
77         snprintf (buf, 16, "%lc",
78                         gdk_keyval_to_unicode (gdk_keyval_to_upper (gdk_keyval_from_name (kv->second.c_str ()))));
79         PangoLayout* pl = pango_cairo_create_layout (cr);
80         pango_layout_set_font_description (pl, _font_cue);
81         pango_layout_set_text (pl, buf, -1);
82         pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT);
83         pango_layout_get_pixel_size (pl, &tw, &th);
84
85         if (_notes[note].white) {
86                 cairo_set_source_rgba (cr, 0.0, 0.0, 0.5, 1.0);
87         } else {
88                 cairo_set_source_rgba (cr, 1.0, 1.0, 0.5, 1.0);
89         }
90
91         if (tw < w) {
92                 cairo_save (cr);
93                 if (_notes[note].white) {
94                         cairo_move_to (cr, x + (w - tw) / 2, h * 2 / 3 + 3);
95                 } else {
96                         cairo_move_to (cr, x + (w - tw) / 2, h - th - 3);
97                 }
98                 pango_cairo_show_layout (cr, pl);
99                 cairo_restore (cr);
100         }
101         g_object_unref (pl);
102 }
103
104 void
105 APianoKeyboard::annotate_note (cairo_t* cr, int note) const
106 {
107         assert ((note % 12) == 0);
108
109         int x = _notes[note].x;
110         int w = _notes[note].w;
111         int h = _notes[note].h;
112
113         int  tw, th;
114         char buf[32];
115         sprintf (buf, "C%d", (note / 12) - 1);
116         PangoLayout* pl = pango_cairo_create_layout (cr);
117         pango_layout_set_font_description (pl, _font_octave);
118         pango_layout_set_text (pl, buf, -1);
119         pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT);
120         pango_layout_get_pixel_size (pl, &tw, &th);
121
122         if (th < w && tw < h * .3) {
123                 cairo_save (cr);
124                 cairo_move_to (cr, x + (w - th) / 2, h - 3);
125                 cairo_rotate (cr, M_PI / -2.0);
126
127                 cairo_set_line_width (cr, 1.0);
128                 cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
129                 pango_cairo_show_layout (cr, pl);
130
131 #if 0
132                 cairo_rel_move_to (cr, -.5, -.5);
133                 pango_cairo_update_layout (cr, pl);
134                 cairo_set_source_rgba (cr, 1, 1, 1, 0.3);
135                 pango_cairo_layout_path (cr, pl);
136                 cairo_set_line_width (cr, 1.5);
137                 cairo_stroke (cr);
138 #endif
139
140                 cairo_restore (cr);
141         }
142         g_object_unref (pl);
143 }
144
145 void
146 APianoKeyboard::draw_note (cairo_t* cr, int note) const
147 {
148         if (note < _min_note || note > _max_note) {
149                 return;
150         }
151
152         int is_white = _notes[note].white;
153         int x        = _notes[note].x;
154         int w        = _notes[note].w;
155         int h        = _notes[note].h;
156
157         if (_notes[note].pressed || _notes[note].sustained) {
158                 if (is_white) {
159                         cairo_set_source_rgb (cr, 0.7, 0.5, 0.5);
160                 } else {
161                         cairo_set_source_rgb (cr, 0.6, 0.4, 0.4);
162                 }
163         } else if (_highlight_grand_piano_range && (note < PIANO_MIN_NOTE || note > PIANO_MAX_NOTE)) {
164                 if (is_white) {
165                         cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
166                 } else {
167                         cairo_set_source_rgb (cr, 0.3, 0.3, 0.3);
168                 }
169         } else {
170                 if (is_white) {
171                         cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
172                 } else {
173                         cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
174                 }
175         }
176
177         cairo_set_line_width (cr, 1.0);
178
179         cairo_rectangle (cr, x, 0, w, h);
180         cairo_fill (cr);
181
182         cairo_set_source_rgb (cr, 0.0f, 0.0f, 0.0f); /* black outline */
183         cairo_rectangle (cr, x, 0, w, h);
184         cairo_stroke (cr);
185
186         if (_annotate_octave && (note % 12) == 0) {
187                 annotate_note (cr, note);
188         }
189
190         if (_annotate_layout) {
191                 annotate_layout (cr, note);
192         }
193
194         /* We need to redraw black keys that partially obscure the white one. */
195         if (note < NNOTES - 2 && !_notes[note + 1].white) {
196                 draw_note (cr, note + 1);
197         }
198
199         if (note > 0 && !_notes[note - 1].white) {
200                 draw_note (cr, note - 1);
201         }
202 }
203
204 void
205 APianoKeyboard::queue_note_draw (int note)
206 {
207         queue_draw_area (_notes[note].x, 0, _notes[note].w, _notes[note].h);
208 }
209
210 void
211 APianoKeyboard::press_key (int key, int vel)
212 {
213         assert (key >= 0);
214         assert (key < NNOTES);
215
216         /* This is for keyboard autorepeat protection. */
217         if (_notes[key].pressed) {
218                 return;
219         }
220
221         if (_sustain_new_notes) {
222                 _notes[key].sustained = true;
223         } else {
224                 _notes[key].sustained = false;
225         }
226
227         if (_monophonic && _last_key != key) {
228                 bool signal_off = _notes[_last_key].pressed || _notes[_last_key].sustained;
229                 _notes[_last_key].pressed = false;
230                 _notes[_last_key].sustained = false;
231                 if (signal_off) {
232                         NoteOff (_last_key); /* EMIT SIGNAL */
233                 }
234                 queue_note_draw (_last_key);
235         }
236         _last_key = key;
237
238         _notes[key].pressed = true;
239
240         NoteOn (key, vel); /* EMIT SIGNAL */
241         queue_note_draw (key);
242 }
243
244 void
245 APianoKeyboard::release_key (int key)
246 {
247         assert (key >= 0);
248         assert (key < NNOTES);
249
250         if (!_notes[key].pressed) {
251                 return;
252         }
253
254         if (_sustain_new_notes) {
255                 _notes[key].sustained = true;
256         }
257
258         _notes[key].pressed = false;
259
260         if (_notes[key].sustained) {
261                 return;
262         }
263
264         NoteOff (key); /* EMIT SIGNAL */
265         queue_note_draw (key);
266 }
267
268 void
269 APianoKeyboard::stop_unsustained_notes ()
270 {
271         for (int i = 0; i < NNOTES; ++i) {
272                 if (_notes[i].pressed && !_notes[i].sustained) {
273                         _notes[i].pressed = false;
274                         NoteOff (i); /* EMIT SIGNAL */
275                         queue_note_draw (i);
276                 }
277         }
278 }
279
280 void
281 APianoKeyboard::stop_sustained_notes ()
282 {
283         for (int i = 0; i < NNOTES; ++i) {
284                 if (_notes[i].sustained) {
285                         _notes[i].sustained = false;
286                         if (_notes[i].pressed) {
287                                 continue;
288                         }
289                         NoteOff (i); /* EMIT SIGNAL */
290                         queue_note_draw (i);
291                 }
292         }
293 }
294
295 int
296 APianoKeyboard::key_binding (const char* key) const
297 {
298         std::map<std::string, int>::const_iterator kv;
299         if (key && (kv = _key_bindings.find (key)) != _key_bindings.end ()) {
300                 return kv->second;
301         }
302         return -1;
303 }
304
305 void
306 APianoKeyboard::bind_key (const char* key, int note)
307 {
308         _key_bindings[key]   = note;
309         _note_bindings[note] = key;
310 }
311
312 void
313 APianoKeyboard::clear_notes ()
314 {
315         _key_bindings.clear ();
316         _note_bindings.clear ();
317 }
318
319 void
320 APianoKeyboard::bind_keys_qwerty ()
321 {
322         clear_notes ();
323
324         bind_key ("space", 128);
325         bind_key ("Tab", 129);
326
327         /* Lower keyboard row - "zxcvbnm". */
328         bind_key ("z", 12); /* C0 */
329         bind_key ("s", 13);
330         bind_key ("x", 14);
331         bind_key ("d", 15);
332         bind_key ("c", 16);
333         bind_key ("v", 17);
334         bind_key ("g", 18);
335         bind_key ("b", 19);
336         bind_key ("h", 20);
337         bind_key ("n", 21);
338         bind_key ("j", 22);
339         bind_key ("m", 23);
340
341         /* Upper keyboard row, first octave - "qwertyu". */
342         bind_key ("q", 24);
343         bind_key ("2", 25);
344         bind_key ("w", 26);
345         bind_key ("3", 27);
346         bind_key ("e", 28);
347         bind_key ("r", 29);
348         bind_key ("5", 30);
349         bind_key ("t", 31);
350         bind_key ("6", 32);
351         bind_key ("y", 33);
352         bind_key ("7", 34);
353         bind_key ("u", 35);
354
355         /* Upper keyboard row, the rest - "iop". */
356         bind_key ("i", 36);
357         bind_key ("9", 37);
358         bind_key ("o", 38);
359         bind_key ("0", 39);
360         bind_key ("p", 40);
361
362         /* ignore */
363         bind_key ("a", -2);
364         bind_key ("f", -3);
365         bind_key ("1", -4);
366         bind_key ("4", -5);
367         bind_key ("8", -6);
368 }
369
370 void
371 APianoKeyboard::bind_keys_qwertz ()
372 {
373         bind_keys_qwerty ();
374
375         /* The only difference between QWERTY and QWERTZ is that the "y" and "z" are swapped together. */
376         bind_key ("y", 12);
377         bind_key ("z", 33);
378 }
379
380 void
381 APianoKeyboard::bind_keys_azerty ()
382 {
383         clear_notes ();
384
385         bind_key ("space", 128);
386         bind_key ("Tab", 129);
387
388         /* Lower keyboard row - "wxcvbn,". */
389         bind_key ("w", 12); /* C0 */
390         bind_key ("s", 13);
391         bind_key ("x", 14);
392         bind_key ("d", 15);
393         bind_key ("c", 16);
394         bind_key ("v", 17);
395         bind_key ("g", 18);
396         bind_key ("b", 19);
397         bind_key ("h", 20);
398         bind_key ("n", 21);
399         bind_key ("j", 22);
400         bind_key ("comma", 23);
401
402         /* Upper keyboard row, first octave - "azertyu". */
403         bind_key ("a", 24);
404         bind_key ("eacute", 25);
405         bind_key ("z", 26);
406         bind_key ("quotedbl", 27);
407         bind_key ("e", 28);
408         bind_key ("r", 29);
409         bind_key ("parenleft", 30);
410         bind_key ("t", 31);
411         bind_key ("minus", 32);
412         bind_key ("y", 33);
413         bind_key ("egrave", 34);
414         bind_key ("u", 35);
415
416         /* Upper keyboard row, the rest - "iop". */
417         bind_key ("i", 36);
418         bind_key ("ccedilla", 37);
419         bind_key ("o", 38);
420         bind_key ("agrave", 39);
421         bind_key ("p", 40);
422 }
423
424 void
425 APianoKeyboard::bind_keys_dvorak ()
426 {
427         clear_notes ();
428
429         bind_key ("space", 128);
430         bind_key ("Tab", 129);
431
432         /* Lower keyboard row - ";qjkxbm". */
433         bind_key ("semicolon", 12); /* C0 */
434         bind_key ("o", 13);
435         bind_key ("q", 14);
436         bind_key ("e", 15);
437         bind_key ("j", 16);
438         bind_key ("k", 17);
439         bind_key ("i", 18);
440         bind_key ("x", 19);
441         bind_key ("d", 20);
442         bind_key ("b", 21);
443         bind_key ("h", 22);
444         bind_key ("m", 23);
445         bind_key ("w", 24); /* overlaps with upper row */
446         bind_key ("n", 25);
447         bind_key ("v", 26);
448         bind_key ("s", 27);
449         bind_key ("z", 28);
450
451         /* Upper keyboard row, first octave - "',.pyfg". */
452         bind_key ("apostrophe", 24);
453         bind_key ("2", 25);
454         bind_key ("comma", 26);
455         bind_key ("3", 27);
456         bind_key ("period", 28);
457         bind_key ("p", 29);
458         bind_key ("5", 30);
459         bind_key ("y", 31);
460         bind_key ("6", 32);
461         bind_key ("f", 33);
462         bind_key ("7", 34);
463         bind_key ("g", 35);
464
465         /* Upper keyboard row, the rest - "crl". */
466         bind_key ("c", 36);
467         bind_key ("9", 37);
468         bind_key ("r", 38);
469         bind_key ("0", 39);
470         bind_key ("l", 40);
471 #if 0
472         bind_key("slash", 41); /* extra F */
473         bind_key("bracketright", 42);
474         bind_key("equal", 43);
475 #endif
476 }
477
478 void
479 APianoKeyboard::bind_keys_basic_qwerty ()
480 {
481         clear_notes ();
482
483         bind_key ("space", 128);
484         bind_key ("Tab", 129);
485
486         /* simple - middle rows only */
487         bind_key ("a", 12); /* C0 */
488         bind_key ("w", 13);
489         bind_key ("s", 14);
490         bind_key ("e", 15);
491         bind_key ("d", 16);
492         bind_key ("f", 17);
493         bind_key ("t", 18);
494         bind_key ("g", 19);
495         bind_key ("y", 20);
496         bind_key ("h", 21);
497         bind_key ("u", 22);
498         bind_key ("j", 23);
499
500         bind_key ("k", 24); /* C1 */
501         bind_key ("o", 25);
502         bind_key ("l", 26);
503         bind_key ("p", 27);
504         bind_key ("semicolon", 28);
505         bind_key ("apostrophe", 29);
506 }
507
508 void
509 APianoKeyboard::bind_keys_basic_qwertz ()
510 {
511         clear_notes ();
512
513         bind_key ("space", 128);
514         bind_key ("Tab", 129);
515
516         /* simple - middle rows only */
517         bind_key ("a", 12); /* C0 */
518         bind_key ("w", 13);
519         bind_key ("s", 14);
520         bind_key ("e", 15);
521         bind_key ("d", 16);
522         bind_key ("f", 17);
523         bind_key ("t", 18);
524         bind_key ("g", 19);
525         bind_key ("z", 20);
526         bind_key ("h", 21);
527         bind_key ("u", 22);
528         bind_key ("j", 23);
529
530         bind_key ("k", 24); /* C1 */
531         bind_key ("o", 25);
532         bind_key ("l", 26);
533         bind_key ("p", 27);
534         bind_key ("semicolon", 28);
535         bind_key ("apostrophe", 29);
536 }
537
538 static const char*
539 get_keycode (GdkEventKey* event)
540 {
541         /* We're not using event->keyval, because we need keyval with level set to 0.
542            E.g. if user holds Shift and presses '7', we want to get a '7', not '&'. */
543
544 #ifdef __APPLE__
545         /* gdkkeys-quartz.c does not implement gdk_keymap_lookup_key */
546         guint keyval;
547         gdk_keymap_translate_keyboard_state (NULL, event->hardware_keycode,
548                                              (GdkModifierType)0, 0,
549                                              &keyval, NULL, NULL, NULL);
550 #else
551         GdkKeymapKey kk;
552         kk.keycode = event->hardware_keycode;
553         kk.level   = 0;
554         kk.group   = 0;
555
556         guint keyval = gdk_keymap_lookup_key (NULL, &kk);
557 #endif
558         return gdk_keyval_name (gdk_keyval_to_lower (keyval));
559 }
560
561 bool
562 APianoKeyboard::handle_fixed_keys (GdkEventKey* ev)
563 {
564         if (ev->type == GDK_KEY_PRESS) {
565                 switch (ev->keyval) {
566                         case GDK_KEY_Left:
567                                 SwitchOctave (false);
568                                 return true;
569                         case GDK_KEY_Right:
570                                 SwitchOctave (true);
571                                 return true;
572                         case GDK_KEY_F1:
573                                 PitchBend (0, false);
574                                 return true;
575                         case GDK_KEY_F2:
576                                 PitchBend (4096, false);
577                                 return true;
578                         case GDK_KEY_F3:
579                                 PitchBend (12288, false);
580                                 return true;
581                         case GDK_KEY_F4:
582                                 PitchBend (16383, false);
583                                 return true;
584                         case GDK_KEY_Down:
585                                 PitchBend (0, true);
586                                 return true;
587                         case GDK_KEY_Up:
588                                 PitchBend (16383, true);
589                                 return true;
590                         default:
591                                 break;
592                 }
593         } else if (ev->type == GDK_KEY_RELEASE) {
594                 switch (ev->keyval) {
595                         case GDK_KEY_F1:
596                                 /* fallthrough */
597                         case GDK_KEY_F2:
598                                 /* fallthrough */
599                         case GDK_KEY_F3:
600                                 /* fallthrough */
601                         case GDK_KEY_F4:
602                                 PitchBend (8192, false);
603                                 break;
604                         case GDK_KEY_Up:
605                                 /* fallthrough */
606                         case GDK_KEY_Down:
607                                 PitchBend (8192, true);
608                                 return true;
609                         default:
610                                 break;
611                 }
612         }
613         return false;
614 }
615
616 bool
617 APianoKeyboard::on_key_press_event (GdkEventKey* event)
618 {
619         if (Gtkmm2ext::Keyboard::modifier_state_contains (event->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
620                 return false;
621         }
622         if (handle_fixed_keys (event)) {
623                 return true;
624         }
625
626         char const* key = get_keycode (event);
627         int note = key_binding (key);
628
629         if (note < -1) {
630                 return true;
631         }
632         else if (note < 0) {
633                 return false;
634         }
635
636         if (note == 128) {
637                 /* Rest is used on release */
638                 return false;
639         }
640         if (note == 129) {
641                 sustain_press ();
642                 return true;
643         }
644
645         note += _octave * 12;
646
647         assert (key);
648         assert (note >= 0);
649         assert (note < NNOTES);
650
651         _note_stack[key] = note;
652
653         press_key (note, _key_velocity);
654
655         return true;
656 }
657
658 bool
659 APianoKeyboard::on_key_release_event (GdkEventKey* event)
660 {
661         if (Gtkmm2ext::Keyboard::modifier_state_contains (event->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
662                 return false;
663         }
664         if (handle_fixed_keys (event)) {
665                 return true;
666         }
667
668         char const* key = get_keycode (event);
669
670         if (!key) {
671                 return false;
672         }
673
674         int note = key_binding (key);
675
676         if (note == 128) {
677                 Rest (); /* EMIT SIGNAL */
678                 return true;
679         }
680         if (note == 129) {
681                 sustain_release ();
682                 return true;
683         }
684         if (note < -1) {
685                 return true;
686         }
687
688         std::map<std::string, int>::const_iterator kv = _note_stack.find (key);
689         if (kv == _note_stack.end ()) {
690                 return note != -1;
691         }
692
693         release_key (kv->second);
694         _note_stack.erase (key);
695
696         return true;
697 }
698
699 int
700 APianoKeyboard::get_note_for_xy (int x, int y) const
701 {
702         int height = get_height ();
703         int note;
704
705         if (y <= ((height * 2) / 3)) { /* might be a black key */
706                 for (note = 0; note <= _max_note; ++note) {
707                         if (_notes[note].white) {
708                                 continue;
709                         }
710
711                         if (x >= _notes[note].x && x <= _notes[note].x + _notes[note].w) {
712                                 return note;
713                         }
714                 }
715         }
716
717         for (note = 0; note <= _max_note; ++note) {
718                 if (!_notes[note].white) {
719                         continue;
720                 }
721
722                 if (x >= _notes[note].x && x <= _notes[note].x + _notes[note].w) {
723                         return note;
724                 }
725         }
726
727         return -1;
728 }
729
730 int
731 APianoKeyboard::get_velocity_for_note_at_y (int note, int y) const
732 {
733         if (note < 0) {
734                 return 0;
735         }
736         int vel = _min_velocity + (_max_velocity - _min_velocity) * y / _notes[note].h;
737
738         if (vel < 1) {
739                 return 1;
740         } else if (vel > 127) {
741                 return 127;
742         }
743         return vel;
744 }
745
746 bool
747 APianoKeyboard::on_button_press_event (GdkEventButton* event)
748 {
749         int x = event->x;
750         int y = event->y;
751
752         int note = get_note_for_xy (x, y);
753
754         if (event->button != 1)
755                 return true;
756
757         if (event->type == GDK_BUTTON_PRESS) {
758                 if (note < 0) {
759                         return true;
760                 }
761
762                 if (_note_being_pressed_using_mouse >= 0) {
763                         release_key (_note_being_pressed_using_mouse);
764                 }
765
766                 press_key (note, get_velocity_for_note_at_y (note, y));
767                 _note_being_pressed_using_mouse = note;
768
769         } else if (event->type == GDK_BUTTON_RELEASE) {
770                 if (note >= 0) {
771                         release_key (note);
772                 } else {
773                         if (_note_being_pressed_using_mouse >= 0) {
774                                 release_key (_note_being_pressed_using_mouse);
775                         }
776                 }
777                 _note_being_pressed_using_mouse = -1;
778         }
779
780         return true;
781 }
782
783 bool
784 APianoKeyboard::on_button_release_event (GdkEventButton* event)
785 {
786         return on_button_press_event (event);
787 }
788
789 bool
790 APianoKeyboard::on_motion_notify_event (GdkEventMotion* event)
791 {
792         int note;
793
794         if ((event->state & GDK_BUTTON1_MASK) == 0)
795                 return true;
796
797         int x = event->x;
798         int y = event->y;
799
800         note = get_note_for_xy (x, y);
801
802         if (note != _note_being_pressed_using_mouse && note >= 0) {
803                 if (_note_being_pressed_using_mouse >= 0) {
804                         release_key (_note_being_pressed_using_mouse);
805                 }
806                 press_key (note, get_velocity_for_note_at_y (note, y));
807                 _note_being_pressed_using_mouse = note;
808         }
809
810         return true;
811 }
812
813 bool
814 APianoKeyboard::on_expose_event (GdkEventExpose* event)
815 {
816         cairo_t* cr = gdk_cairo_create (GDK_DRAWABLE (get_window ()->gobj ()));
817         cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
818         cairo_clip (cr);
819
820         char buf[32];
821         sprintf (buf, "ArdourMono %dpx", MAX (8, MIN (20, _notes[1].w / 2 + 3)));
822         _font_cue = pango_font_description_from_string (buf);
823         sprintf (buf, "ArdourMono %dpx", MAX (8, MIN (20, MIN (_notes[0].w * 11 / 15 , _notes[0].h / 7))));
824         _font_octave = pango_font_description_from_string (buf);
825
826         for (int i = 0; i < NNOTES; ++i) {
827                 GdkRectangle r;
828
829                 r.x      = _notes[i].x;
830                 r.y      = 0;
831                 r.width  = _notes[i].w;
832                 r.height = _notes[i].h;
833
834                 switch (gdk_region_rect_in (event->region, &r)) {
835                         case GDK_OVERLAP_RECTANGLE_PART:
836                         case GDK_OVERLAP_RECTANGLE_IN:
837                                 draw_note (cr, i);
838                                 break;
839                         default:
840                                 break;
841                 }
842         }
843
844         pango_font_description_free (_font_cue);
845         pango_font_description_free (_font_octave);
846
847         cairo_destroy (cr);
848         return true;
849 }
850
851 void
852 APianoKeyboard::on_size_request (Gtk::Requisition* requisition)
853 {
854         requisition->width  = PIANO_KEYBOARD_DEFAULT_WIDTH;
855         requisition->height = PIANO_KEYBOARD_DEFAULT_HEIGHT;
856         if (_annotate_layout) {
857                 requisition->height += 16;
858         }
859         if (_annotate_octave) {
860                 requisition->height += 24;
861         }
862 }
863
864 int
865 APianoKeyboard::is_black (int key) const
866 {
867         int note_in_octave = key % 12;
868         switch (note_in_octave) {
869                 case 1:
870                 case 3:
871                 case 6:
872                 case 8:
873                 case 10:
874                         return 1;
875                 default:
876                         return 0;
877         }
878         return 0;
879 }
880
881 double
882 APianoKeyboard::black_key_left_shift (int key) const
883 {
884         int note_in_octave = key % 12;
885         switch (note_in_octave) {
886                 case 1:
887                         return 2.0 / 3.0;
888                 case 3:
889                         return 1.0 / 3.0;
890                 case 6:
891                         return 2.0 / 3.0;
892                 case 8:
893                         return 0.5;
894                 case 10:
895                         return 1.0 / 3.0;
896                 default:
897                         return 0;
898         }
899         return 0;
900 }
901
902 void
903 APianoKeyboard::recompute_dimensions ()
904 {
905         int note;
906         int number_of_white_keys = 0;
907         int skipped_white_keys   = 0;
908
909         for (note = _min_note; note <= _max_note; ++note) {
910                 if (!is_black (note)) {
911                         ++number_of_white_keys;
912                 }
913         }
914         for (note = 0; note < _min_note; ++note) {
915                 if (!is_black (note)) {
916                         ++skipped_white_keys;
917                 }
918         }
919
920         int width  = get_width ();
921         int height = get_height ();
922
923         int key_width       = width / number_of_white_keys;
924         int black_key_width = key_width * 0.8;
925         int useful_width    = number_of_white_keys * key_width;
926
927         int widget_margin = (width - useful_width) / 2;
928
929         int white_key;
930         for (note = 0, white_key = -skipped_white_keys; note < NNOTES; ++note) {
931                 if (is_black (note)) {
932                         /* This note is black key. */
933                         _notes[note].x = widget_margin +
934                                          (white_key * key_width) -
935                                          (black_key_width * black_key_left_shift (note));
936                         _notes[note].w     = black_key_width;
937                         _notes[note].h     = (height * 2) / 3;
938                         _notes[note].white = 0;
939                         continue;
940                 }
941
942                 /* This note is white key. */
943                 _notes[note].x     = widget_margin + white_key * key_width;
944                 _notes[note].w     = key_width;
945                 _notes[note].h     = height;
946                 _notes[note].white = 1;
947
948                 white_key++;
949         }
950 }
951
952 void
953 APianoKeyboard::on_size_allocate (Gtk::Allocation& allocation)
954 {
955         DrawingArea::on_size_allocate (allocation);
956         recompute_dimensions ();
957 }
958
959 APianoKeyboard::APianoKeyboard ()
960 {
961         using namespace Gdk;
962         add_events (KEY_PRESS_MASK | KEY_RELEASE_MASK | BUTTON_PRESS_MASK | BUTTON_RELEASE_MASK | POINTER_MOTION_MASK | POINTER_MOTION_HINT_MASK);
963
964         _sustain_new_notes              = false;
965         _highlight_grand_piano_range    = true;
966         _annotate_layout                = false;
967         _annotate_octave                = false;
968         _octave                         = 4;
969         _octave_range                   = 7;
970         _note_being_pressed_using_mouse = -1;
971         _min_note                       = 0;
972         _max_note                       = 127;
973         _last_key                       = 0;
974         _monophonic                     = false;
975
976         _min_velocity = 1;
977         _max_velocity = 127;
978         _key_velocity = 100;
979
980         bind_keys_qwerty ();
981 }
982
983 APianoKeyboard::~APianoKeyboard ()
984 {
985 }
986
987 void
988 APianoKeyboard::set_grand_piano_highlight (bool enabled)
989 {
990         _highlight_grand_piano_range = enabled;
991         queue_draw ();
992 }
993
994 void
995 APianoKeyboard::set_annotate_layout (bool enabled)
996 {
997         _annotate_layout = enabled;
998         queue_draw ();
999 }
1000
1001 void
1002 APianoKeyboard::set_annotate_octave (bool enabled)
1003 {
1004         _annotate_octave = enabled;
1005         queue_draw ();
1006 }
1007
1008 void
1009 APianoKeyboard::set_monophonic (bool monophonic)
1010 {
1011         _monophonic = monophonic;
1012 }
1013
1014 void
1015 APianoKeyboard::set_velocities (int min_vel, int max_vel, int key_vel)
1016 {
1017         if (min_vel <= max_vel && min_vel > 0 && max_vel < 128) {
1018                 _min_velocity = min_vel;
1019                 _max_velocity = max_vel;
1020         }
1021
1022         if (key_vel > 0 && key_vel < 128) {
1023                 _key_velocity = key_vel;
1024         }
1025 }
1026
1027 void
1028 APianoKeyboard::sustain_press ()
1029 {
1030         if (_sustain_new_notes) {
1031                 return;
1032         }
1033         _sustain_new_notes = true;
1034         SustainChanged (true); /* EMIT SIGNAL */
1035 }
1036
1037 void
1038 APianoKeyboard::sustain_release ()
1039 {
1040         stop_sustained_notes ();
1041         if (_sustain_new_notes) {
1042                 _sustain_new_notes = false;
1043                 SustainChanged (false); /* EMIT SIGNAL */
1044         }
1045 }
1046
1047 void
1048 APianoKeyboard::reset ()
1049 {
1050         sustain_release ();
1051         stop_unsustained_notes ();
1052 }
1053
1054 void
1055 APianoKeyboard::set_note_on (int note)
1056 {
1057         if (!_notes[note].pressed) {
1058                 _notes[note].pressed = true;
1059                 queue_note_draw (note);
1060         }
1061 }
1062
1063 void
1064 APianoKeyboard::set_note_off (int note)
1065 {
1066         if (_notes[note].pressed || _notes[note].sustained) {
1067                 _notes[note].pressed   = false;
1068                 _notes[note].sustained = false;
1069                 queue_note_draw (note);
1070         }
1071 }
1072
1073 void
1074 APianoKeyboard::set_octave (int octave)
1075 {
1076         if (octave < -1) {
1077                 octave = -1;
1078         } else if (octave > 7) {
1079                 octave = 7;
1080         }
1081
1082         _octave = octave;
1083         set_octave_range (_octave_range);
1084 }
1085
1086 void
1087 APianoKeyboard::set_octave_range (int octave_range)
1088 {
1089         if (octave_range < 2) {
1090                 octave_range = 2;
1091         }
1092         if (octave_range > 11) {
1093                 octave_range = 11;
1094         }
1095
1096         _octave_range = octave_range;
1097
1098         /* -1 <= _octave <= 7
1099          * key-bindings are at offset 12 .. 40
1100          * default piano range: _octave = 4, range = 7 -> note 21..108
1101          */
1102
1103         switch (_octave_range) {
1104                 default:
1105                         assert (0);
1106                         break;
1107                 case 2:
1108                 case 3:
1109                         _min_note = (_octave + 1) * 12;
1110                         break;
1111                 case 4:
1112                 case 5:
1113                         _min_note = (_octave + 0) * 12;
1114                         break;
1115                 case 6:
1116                         _min_note = (_octave - 1) * 12;
1117                         break;
1118                 case 7:
1119                 case 8:
1120                         _min_note = (_octave - 2) * 12;
1121                         break;
1122                 case 9:
1123                 case 10:
1124                         _min_note = (_octave - 3) * 12;
1125                         break;
1126                 case 11:
1127                         _min_note = (_octave - 4) * 12;
1128                         break;
1129         }
1130
1131         int upper_offset = 0;
1132
1133         if (_min_note < 3) {
1134                 upper_offset = 0;
1135                 _min_note    = 0;
1136         } else if (_octave_range > 5) {
1137                 /* extend down to A */
1138                 upper_offset = 3;
1139                 _min_note -= 3;
1140         }
1141
1142         _max_note = MIN (127, upper_offset + _min_note + _octave_range * 12);
1143
1144         if (_max_note == 127) {
1145                 _min_note = MAX (0, _max_note - _octave_range * 12);
1146         }
1147
1148         recompute_dimensions ();
1149         queue_draw ();
1150 }
1151
1152 void
1153 APianoKeyboard::set_keyboard_layout (Layout layout)
1154 {
1155         switch (layout) {
1156                 case QWERTY:
1157                         bind_keys_qwerty ();
1158                         break;
1159                 case QWERTZ:
1160                         bind_keys_qwertz ();
1161                         break;
1162                 case AZERTY:
1163                         bind_keys_azerty ();
1164                         break;
1165                 case DVORAK:
1166                         bind_keys_dvorak ();
1167                         break;
1168                 case S_QWERTY:
1169                         bind_keys_basic_qwerty ();
1170                         break;
1171                 case S_QWERTZ:
1172                         bind_keys_basic_qwertz ();
1173                         break;
1174         }
1175         queue_draw ();
1176 }