Apply MIDI keyboard and "scroomer" patch.
[ardour.git] / gtk2_ardour / midi_scroomer.cc
1 /*
2     Copyright (C) 2008 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include "midi_scroomer.h"
20
21 #include <cairomm/context.h>
22
23 #include <iostream>
24
25 using namespace Gtkmm2ext;
26 using namespace Gtk;
27 using namespace std;
28
29 //std::map<int, Glib::RefPtr<Gdk::Pixmap> > MidiScroomer::piano_pixmaps;
30
31 MidiScroomer::MidiScroomer(Adjustment& adj)
32         : Gtkmm2ext::Scroomer(adj) {
33
34         adj.set_lower(0);
35         adj.set_upper(127);
36
37         /* set minimum view range to one octave */
38         set_min_page_size(12);
39 }
40
41 MidiScroomer::~MidiScroomer() {
42 }
43
44 bool
45 MidiScroomer::on_expose_event(GdkEventExpose* ev) {
46         Cairo::RefPtr<Cairo::Context> cc = get_window()->create_cairo_context();
47         GdkRectangle comp_rect, clip_rect;
48         Component first_comp = point_in(ev->area.y);
49         Component last_comp = point_in(ev->area.y + ev->area.height);
50         int height = get_height();
51         int lnote, hnote;
52         double y2note = (double) 127 / height;
53         double note2y = (double) height / 127;
54         double note_width = 0.8 * get_width();
55         double note_height = 1.4 * note2y;
56         double black_shift = 0.1 * note2y;
57         double colors[6];
58
59         //cerr << ev->area.y << " " << ev->area.height << endl;
60
61         comp_rect.x = 0;
62         comp_rect.width = get_width();
63
64         for(int i = first_comp; i <= last_comp; ++i) {
65                 Component comp = (Component) i;
66                 set_comp_rect(comp_rect, comp);
67
68                 if(gdk_rectangle_intersect(&comp_rect, &ev->area, &clip_rect)) {
69                         get_colors(colors, comp);
70
71                         cc->rectangle(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
72                         cc->set_source_rgb (colors[3], colors[4], colors[5]);
73                         cc->fill_preserve();
74                         
75                         cc->clip();
76                         cc->set_source_rgb(colors[0], colors[1], colors[2]);
77                         cc->set_line_width(note_height);
78
79                         lnote = 127 - (int) floor((double) (clip_rect.y + clip_rect.height) * y2note) - 1;
80                         hnote = 127 - (int) floor((double) clip_rect.y * y2note) + 1;
81
82                         for(int note = lnote; note < hnote + 1; ++note) {
83                                 double y = height - note * note2y;
84                                 bool draw = false;
85                                 
86                                 switch(note % 12) {
87                                 case 1:
88                                 case 6:
89                                         y -= black_shift;
90                                         draw = true;
91                                         break;
92                                 case 3:
93                                 case 10:
94                                         y += black_shift;
95                                         draw = true;
96                                         break;
97                                 case 8:
98                                         draw = true;
99                                         break;
100                                 default:
101                                         break;
102                                 }
103                                 
104                                 if(draw) {
105                                         cc->set_line_width(1.4 * note2y);
106                                         cc->move_to(0, y);
107                                         cc->line_to(note_width, y);
108                                         cc->stroke();
109                                 }
110                         }
111
112                         cc->reset_clip();
113                 }
114         }
115
116         return true;
117 }
118
119 void
120 MidiScroomer::get_colors(double color[], Component comp) {
121         switch (comp) {
122         case TopBase:
123         case BottomBase:
124                 color[0] = 0.24;
125                 color[1] = 0.24;
126                 color[2] = 0.24;
127                 color[3] = 0.33;
128                 color[4] = 0.33;
129                 color[5] = 0.33;
130                 break;
131         case Handle1:
132         case Handle2:
133                 color[0] = 0.38;
134                 color[1] = 0.38;
135                 color[2] = 0.38;
136                 color[3] = 0.91;
137                 color[4] = 0.91;
138                 color[5] = 0.91;
139                 break;
140         case Slider:
141                 color[0] = 0.38;
142                 color[1] = 0.38;
143                 color[2] = 0.38;
144                 color[3] = 0.77;
145                 color[4] = 0.77;
146                 color[5] = 0.77;
147                 break;
148         default:
149                 break;
150         }
151 }
152
153 void
154 MidiScroomer::on_size_request(Gtk::Requisition* r) {
155         r->width = 16;
156         r->height = 100;
157         //r->width = 32;
158         //r->height = 512;
159 }
160
161 void
162 MidiScroomer::on_size_allocate(Gtk::Allocation& a) {
163         Scroomer::on_size_allocate(a);
164 }