/*-
- * Copyright (c) 2007, 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * Copyright (c) 2007, 2008 Edward Tomasz Napiera�ła <trasz@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
enum {
NOTE_ON_SIGNAL,
NOTE_OFF_SIGNAL,
+ REST_SIGNAL,
LAST_SIGNAL
};
int first_note_in_higher_row = (pk->octave + 6) * 12;
int last_note_in_higher_row = (pk->octave + 7) * 12 + 4;
- cairo_set_source_rgb (cr, 1.0f, 0.0f, 0.0f);
- cairo_move_to (cr, pk->notes[first_note_in_lower_row].x + 3, h - 6);
- cairo_line_to (cr, pk->notes[last_note_in_lower_row].x + w - 3, h - 6);
- cairo_stroke (cr);
+ cairo_set_source_rgb (cr, 1.0f, 0.0f, 0.0f);
+ cairo_move_to (cr, pk->notes[first_note_in_lower_row].x + 3, h - 6);
+ cairo_line_to (cr, pk->notes[last_note_in_lower_row].x + w - 3, h - 6);
+ cairo_stroke (cr);
- cairo_set_source_rgb (cr, 0.0f, 0.0f, 1.0f);
- cairo_move_to (cr, pk->notes[first_note_in_higher_row].x + 3, h - 9);
- cairo_line_to (cr, pk->notes[last_note_in_higher_row].x + w - 3, h - 9);
- cairo_stroke (cr);
+ cairo_set_source_rgb (cr, 0.0f, 0.0f, 1.0f);
+ cairo_move_to (cr, pk->notes[first_note_in_higher_row].x + 3, h - 9);
+ cairo_line_to (cr, pk->notes[last_note_in_higher_row].x + w - 3, h - 9);
+ cairo_stroke (cr);
}
static void
queue_note_draw (PianoKeyboard* pk, int note)
{
- GdkWindow* w = GTK_WIDGET(pk)->window;
+ GdkWindow* w = GTK_WIDGET(pk)->window;
- if (w) {
- GdkRectangle r;
+ if (w) {
+ GdkRectangle r;
- r.x = pk->notes[note].x;
- r.y = 0;
- r.width = pk->notes[note].w;
- r.height = pk->notes[note].h;
+ r.x = pk->notes[note].x;
+ r.y = 0;
+ r.width = pk->notes[note].w;
+ r.height = pk->notes[note].h;
- gdk_window_invalidate_rect (w, &r, TRUE);
- }
+ gdk_window_invalidate_rect (w, &r, TRUE);
+ }
}
static void
int h = pk->notes[note].h;
if (pk->notes[note].pressed || pk->notes[note].sustained) {
- is_white = !is_white;
- }
-
- cairo_set_line_width (cr, 1.0);
+ if (is_white) {
+ cairo_set_source_rgb (cr, 0.60f, 0.60f, 0.60f);
+ } else {
+ cairo_set_source_rgb (cr, 0.50f, 0.50f, 0.50f);
+ }
+ } else {
+ if (is_white) {
+ cairo_set_source_rgb (cr, 1.0f, 1.0f, 1.0f);
+ } else {
+ cairo_set_source_rgb (cr, 0.0f, 0.0f, 0.0f);
+ }
+ }
- if (is_white) {
- cairo_set_source_rgb (cr, 1.0f, 1.0f, 1.0f);
- } else {
- cairo_set_source_rgb (cr, 0.0f, 0.0f, 0.0f);
- }
+ cairo_set_line_width (cr, 1.0);
- cairo_rectangle (cr, x, 0, w, h);
- cairo_fill (cr);
+ cairo_rectangle (cr, x, 0, w, h);
+ cairo_fill (cr);
- cairo_set_source_rgb(cr, 0.0f, 0.0f, 0.0f); /* black outline */
- cairo_rectangle (cr, x, 0, w, h);
- cairo_stroke (cr);
+ cairo_set_source_rgb(cr, 0.0f, 0.0f, 0.0f); /* black outline */
+ cairo_rectangle (cr, x, 0, w, h);
+ cairo_stroke (cr);
if (pk->enable_keyboard_cue) {
draw_keyboard_cue (pk, cr);
- }
+ }
/* We need to redraw black keys that partially obscure the white one. */
if (note < NNOTES - 2 && !pk->notes[note + 1].white) {
draw_note(pk, cr, note + 1);
- }
+ }
if (note > 0 && !pk->notes[note - 1].white) {
draw_note(pk, cr, note - 1);
- }
+ }
}
static int
return 1;
}
+static void
+rest (PianoKeyboard* pk)
+{
+ g_signal_emit_by_name(GTK_WIDGET(pk), "rest");
+}
+
static void
stop_unsustained_notes(PianoKeyboard *pk)
{
{
clear_notes(pk);
+ bind_key(pk, "space", 128);
+
/* Lower keyboard row - "zxcvbnm". */
bind_key(pk, "z", 12); /* C0 */
bind_key(pk, "s", 13);
{
clear_notes(pk);
+ bind_key(pk, "space", 128);
+
/* Lower keyboard row - "wxcvbn,". */
bind_key(pk, "w", 12); /* C0 */
bind_key(pk, "s", 13);
return FALSE;
}
+ if (note == 128) {
+ if (event->type == GDK_KEY_RELEASE) {
+ rest (pk);
+ }
+
+ return TRUE;
+ }
+
note += pk->octave * 12;
assert(note >= 0);
{
int i;
PianoKeyboard *pk = PIANO_KEYBOARD(widget);
- cairo_t* cr = gdk_cairo_create (GDK_DRAWABLE (GTK_WIDGET(pk)->window));
-
- gdk_cairo_region (cr, event->region);
- cairo_clip (cr);
+ cairo_t* cr = gdk_cairo_create (GDK_DRAWABLE (GTK_WIDGET(pk)->window));
+
+ gdk_cairo_region (cr, event->region);
+ cairo_clip (cr);
for (i = 0; i < NNOTES; i++) {
- GdkRectangle r;
-
- r.x = pk->notes[i].x;
- r.y = 0;
- r.width = pk->notes[i].w;
- r.height = pk->notes[i].h;
-
- switch (gdk_region_rect_in (event->region, &r)) {
- case GDK_OVERLAP_RECTANGLE_PART:
- case GDK_OVERLAP_RECTANGLE_IN:
- draw_note (pk, cr, i);
- break;
- default:
- break;
- }
- }
+ GdkRectangle r;
+
+ r.x = pk->notes[i].x;
+ r.y = 0;
+ r.width = pk->notes[i].w;
+ r.height = pk->notes[i].h;
+
+ switch (gdk_region_rect_in (event->region, &r)) {
+ case GDK_OVERLAP_RECTANGLE_PART:
+ case GDK_OVERLAP_RECTANGLE_IN:
+ draw_note (pk, cr, i);
+ break;
+ default:
+ break;
+ }
+ }
- cairo_destroy (cr);
+ cairo_destroy (cr);
return TRUE;
}
static void
-piano_keyboard_size_request(GtkWidget *widget, GtkRequisition *requisition)
+piano_keyboard_size_request(GtkWidget* widget, GtkRequisition *requisition)
{
requisition->width = PIANO_KEYBOARD_DEFAULT_WIDTH;
requisition->height = PIANO_KEYBOARD_DEFAULT_HEIGHT;
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+ piano_keyboard_signals[REST_SIGNAL] = g_signal_new ("rest",
+ G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
widget_klass = (GtkWidgetClass*) klass;
widget_klass->expose_event = piano_keyboard_expose;
g_signal_connect(G_OBJECT(mk), "button-press-event", G_CALLBACK(mouse_button_event_handler), NULL);
g_signal_connect(G_OBJECT(mk), "button-release-event", G_CALLBACK(mouse_button_event_handler), NULL);
g_signal_connect(G_OBJECT(mk), "motion-notify-event", G_CALLBACK(mouse_motion_event_handler), NULL);
- g_signal_connect(G_OBJECT(mk), "key-press-event", G_CALLBACK(keyboard_event_handler), NULL);
- g_signal_connect(G_OBJECT(mk), "key-release-event", G_CALLBACK(keyboard_event_handler), NULL);
+ g_signal_connect(G_OBJECT(mk), "key-press-event", G_CALLBACK(keyboard_event_handler), NULL);
+ g_signal_connect(G_OBJECT(mk), "key-release-event", G_CALLBACK(keyboard_event_handler), NULL);
}
GType
sizeof (PianoKeyboard),
0, /* n_preallocs */
(GInstanceInitFunc) piano_keyboard_init,
+ 0, /* value_table */
};
mk_type = g_type_register_static(GTK_TYPE_DRAWING_AREA, "PianoKeyboard", &mk_info, 0);
{
if (pk->notes[note].pressed == 0) {
pk->notes[note].pressed = 1;
- queue_note_draw (pk, note);
+ queue_note_draw (pk, note);
}
}
if (pk->notes[note].pressed || pk->notes[note].sustained) {
pk->notes[note].pressed = 0;
pk->notes[note].sustained = 0;
- queue_note_draw (pk, note);
+ queue_note_draw (pk, note);
}
}
return FALSE;
}
-