27 |
|
|
28 |
#include "global.h" |
#include "global.h" |
29 |
|
|
30 |
|
#define REGION_BLOCK_HEIGHT 20 |
31 |
|
#define KEYBOARD_HEIGHT 40 |
32 |
|
|
33 |
void SortedRegions::update(gig::Instrument* instrument) { |
void SortedRegions::update(gig::Instrument* instrument) { |
34 |
// Usually, the regions in a gig file are ordered after their key |
// Usually, the regions in a gig file are ordered after their key |
35 |
// range, but there are files where they are not. The |
// range, but there are files where they are not. The |
63 |
|
|
64 |
red = Gdk::Color("#8070ff"); |
red = Gdk::Color("#8070ff"); |
65 |
grey1 = Gdk::Color("#b0b0b0"); |
grey1 = Gdk::Color("#b0b0b0"); |
66 |
|
activeKeyColor = Gdk::Color("#ff0000"); |
67 |
|
white = Gdk::Color("#ffffff"); |
68 |
|
black = Gdk::Color("#000000"); |
69 |
|
|
70 |
colormap->alloc_color(red); |
colormap->alloc_color(red); |
71 |
colormap->alloc_color(grey1); |
colormap->alloc_color(grey1); |
72 |
|
colormap->alloc_color(activeKeyColor); |
73 |
|
colormap->alloc_color(white); |
74 |
|
colormap->alloc_color(black); |
75 |
instrument = 0; |
instrument = 0; |
76 |
region = 0; |
region = 0; |
77 |
resize.active = false; |
resize.active = false; |
78 |
move.active = false; |
move.active = false; |
79 |
cursor_is_resize = false; |
cursor_is_resize = false; |
80 |
h1 = 20; |
h1 = REGION_BLOCK_HEIGHT; |
81 |
|
|
82 |
actionGroup = Gtk::ActionGroup::create(); |
actionGroup = Gtk::ActionGroup::create(); |
83 |
actionGroup->add(Gtk::Action::create("Properties", |
actionGroup->add(Gtk::Action::create("Properties", |
125 |
sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed) |
sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed) |
126 |
) |
) |
127 |
); |
); |
128 |
|
keyboard_key_hit_signal.connect( |
129 |
|
sigc::mem_fun(*this, &RegionChooser::on_note_on_event) |
130 |
|
); |
131 |
|
keyboard_key_released_signal.connect( |
132 |
|
sigc::mem_fun(*this, &RegionChooser::on_note_off_event) |
133 |
|
); |
134 |
} |
} |
135 |
|
|
136 |
RegionChooser::~RegionChooser() |
RegionChooser::~RegionChooser() |
137 |
{ |
{ |
138 |
} |
} |
139 |
|
|
140 |
|
void RegionChooser::on_note_on_event(int key, int velocity) { |
141 |
|
draw_region(key, key+1, activeKeyColor); |
142 |
|
} |
143 |
|
|
144 |
|
void RegionChooser::on_note_off_event(int key, int velocity) { |
145 |
|
if (is_black_key(key)) |
146 |
|
draw_region(key, key+1, black); |
147 |
|
else |
148 |
|
draw_region(key, key+1, white); |
149 |
|
} |
150 |
|
|
151 |
void RegionChooser::on_realize() |
void RegionChooser::on_realize() |
152 |
{ |
{ |
153 |
// We need to call the base on_realize() |
// We need to call the base on_realize() |
163 |
{ |
{ |
164 |
Glib::RefPtr<Gdk::Window> window = get_window(); |
Glib::RefPtr<Gdk::Window> window = get_window(); |
165 |
window->clear(); |
window->clear(); |
166 |
const int h = 40; |
const int h = KEYBOARD_HEIGHT; |
167 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
168 |
const int bh = int(h * 0.55); |
const int bh = int(h * 0.55); |
169 |
|
|
170 |
Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc(); |
Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc(); |
171 |
Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc(); |
Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc(); |
172 |
|
|
|
Glib::RefPtr<Pango::Context> context = get_pango_context(); |
|
|
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context); |
|
|
|
|
173 |
window->draw_rectangle(black, false, 0, h1, w, h - 1); |
window->draw_rectangle(black, false, 0, h1, w, h - 1); |
174 |
gc->set_foreground(grey1); |
gc->set_foreground(grey1); |
175 |
int x1 = int(w * 20.5 / 128.0 + 0.5); |
int x1 = int(w * 20.5 / 128.0 + 0.5); |
179 |
window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2); |
window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2); |
180 |
window->draw_rectangle(gc, true, x2 + 1, h1 + 1, |
window->draw_rectangle(gc, true, x2 + 1, h1 + 1, |
181 |
w - x2 - 1, h - 2); |
w - x2 - 1, h - 2); |
|
int octave = -1; |
|
182 |
for (int i = 0 ; i < 128 ; i++) { |
for (int i = 0 ; i < 128 ; i++) { |
183 |
int note = (i + 3) % 12; |
int note = (i + 3) % 12; |
184 |
int x = int(w * i / 128.0 + 0.5); |
int x = int(w * i / 128.0 + 0.5); |
192 |
} else if (note == 3 || note == 8) { |
} else if (note == 3 || note == 8) { |
193 |
window->draw_line(black, x, h1 + 1, x, h1 + h); |
window->draw_line(black, x, h1 + 1, x, h1 + h); |
194 |
} |
} |
195 |
if (note == 3) { |
if (note == 3) draw_digit(i); |
|
char buf[30]; |
|
|
sprintf(buf, "<span size=\"8000\">%d</span>", octave); |
|
|
layout->set_markup(buf); |
|
|
Pango::Rectangle rectangle = layout->get_logical_extents(); |
|
|
double text_w = double(rectangle.get_width()) / Pango::SCALE; |
|
|
double text_h = double(rectangle.get_height()) / Pango::SCALE; |
|
|
double x2 = w * (i + 0.75) / 128.0; |
|
|
window->draw_layout(black, int(x2 - text_w / 2 + 1), |
|
|
int(h1 + h - text_h + 0.5), layout); |
|
|
octave++; |
|
|
} |
|
196 |
} |
} |
197 |
|
|
198 |
if (instrument) { |
if (instrument) { |
233 |
void RegionChooser::on_size_request(GtkRequisition* requisition) |
void RegionChooser::on_size_request(GtkRequisition* requisition) |
234 |
{ |
{ |
235 |
*requisition = GtkRequisition(); |
*requisition = GtkRequisition(); |
236 |
requisition->height = 40 + 20; |
requisition->height = KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT; |
237 |
requisition->width = 500; |
requisition->width = 500; |
238 |
} |
} |
239 |
|
|
240 |
|
bool RegionChooser::is_black_key(int key) { |
241 |
|
const int note = (key + 3) % 12; |
242 |
|
return note == 1 || note == 4 || note == 6 || note == 9 || note == 11; |
243 |
|
} |
244 |
|
|
245 |
|
void RegionChooser::draw_digit(int key) { |
246 |
|
const int h = KEYBOARD_HEIGHT; |
247 |
|
const int w = get_width() - 1; |
248 |
|
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context()); |
249 |
|
char buf[30]; |
250 |
|
sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1); |
251 |
|
layout->set_markup(buf); |
252 |
|
Pango::Rectangle rectangle = layout->get_logical_extents(); |
253 |
|
double text_w = double(rectangle.get_width()) / Pango::SCALE; |
254 |
|
double text_h = double(rectangle.get_height()) / Pango::SCALE; |
255 |
|
double x = w * (key + 0.75) / 128.0; |
256 |
|
get_window()->draw_layout(get_style()->get_black_gc(), int(x - text_w / 2 + 1), |
257 |
|
int(h1 + h - text_h + 0.5), layout); |
258 |
|
} |
259 |
|
|
|
// not used |
|
260 |
void RegionChooser::draw_region(int from, int to, const Gdk::Color& color) |
void RegionChooser::draw_region(int from, int to, const Gdk::Color& color) |
261 |
{ |
{ |
262 |
const int h = 40; |
const int h = KEYBOARD_HEIGHT; |
263 |
const int w = get_width(); |
const int w = get_width() - 1; |
264 |
const int bh = int(h * 0.55); |
const int bh = int(h * 0.55); |
265 |
|
|
266 |
Glib::RefPtr<Gdk::Window> window = get_window(); |
Glib::RefPtr<Gdk::Window> window = get_window(); |
271 |
int x = int(w * i / 128.0 + 0.5) + 1; |
int x = int(w * i / 128.0 + 0.5) + 1; |
272 |
int x2 = int(w * (i + 1.5) / 128.0 + 0.5); |
int x2 = int(w * (i + 1.5) / 128.0 + 0.5); |
273 |
int x3 = int(w * (i + 1) / 128.0 + 0.5); |
int x3 = int(w * (i + 1) / 128.0 + 0.5); |
274 |
int x4 = int(w * (i - 0.5) / 128 + 0.5) + 1; |
int x4 = int(w * (i - 0.5) / 128.0 + 0.5); |
275 |
int w1 = x3 - x; |
int w1 = x3 - x; |
276 |
switch (note) { |
switch (note) { |
277 |
case 0: case 5: case 10: |
case 0: case 5: case 10: |
278 |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh); |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh); |
279 |
window->draw_rectangle(gc, true, x4, h1 + bh + 1, x2 - x4, h - bh - 2); |
window->draw_rectangle(gc, true, x4 + 1, h1 + bh + 1, x2 - x4 - 1, h - bh - 2); |
280 |
break; |
break; |
281 |
case 2: case 7: |
case 2: case 7: |
282 |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh); |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh); |
283 |
window->draw_rectangle(gc, true, x4, h1 + bh + 1, x3 - x4, h - bh - 2); |
window->draw_rectangle(gc, true, x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2); |
284 |
break; |
break; |
285 |
case 3: case 8: |
case 3: case 8: |
286 |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh); |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh); |
287 |
window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2); |
window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2); |
288 |
|
if (note == 3) draw_digit(i); |
289 |
break; |
break; |
290 |
default: |
default: |
291 |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh - 1); |
window->draw_rectangle(gc, true, x, h1 + 1, w1, bh - 1); |
305 |
|
|
306 |
bool RegionChooser::on_button_release_event(GdkEventButton* event) |
bool RegionChooser::on_button_release_event(GdkEventButton* event) |
307 |
{ |
{ |
308 |
|
const int k = int(event->x / (get_width() - 1) * 128.0); |
309 |
|
|
310 |
|
if (event->type == GDK_BUTTON_RELEASE) { |
311 |
|
if (event->y >= REGION_BLOCK_HEIGHT) { |
312 |
|
int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : |
313 |
|
int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1; |
314 |
|
keyboard_key_released_signal.emit(k, velocity); |
315 |
|
} |
316 |
|
} |
317 |
|
|
318 |
if (resize.active) { |
if (resize.active) { |
319 |
get_window()->pointer_ungrab(event->time); |
get_window()->pointer_ungrab(event->time); |
320 |
resize.active = false; |
resize.active = false; |
374 |
{ |
{ |
375 |
if (!instrument) return true; |
if (!instrument) return true; |
376 |
|
|
377 |
int k = int(event->x / (get_width() - 1) * 128.0); |
const int k = int(event->x / (get_width() - 1) * 128.0); |
378 |
|
|
379 |
|
if (event->type == GDK_BUTTON_PRESS) { |
380 |
|
if (event->y >= REGION_BLOCK_HEIGHT) { |
381 |
|
int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : |
382 |
|
int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1; |
383 |
|
keyboard_key_hit_signal.emit(k, velocity); |
384 |
|
} |
385 |
|
} |
386 |
|
|
387 |
|
if (event->y >= REGION_BLOCK_HEIGHT) return true; |
388 |
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
389 |
gig::Region* r = get_region(k); |
gig::Region* r = get_region(k); |
390 |
if (r) { |
if (r) { |
779 |
sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() { |
sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() { |
780 |
return region_changed_signal; |
return region_changed_signal; |
781 |
} |
} |
782 |
|
|
783 |
|
sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_hit() { |
784 |
|
return keyboard_key_hit_signal; |
785 |
|
} |
786 |
|
|
787 |
|
sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_released() { |
788 |
|
return keyboard_key_released_signal; |
789 |
|
} |