summaryrefslogtreecommitdiff
path: root/gtk2_ardour/gtk_pianokeyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2_ardour/gtk_pianokeyboard.c')
-rw-r--r--gtk2_ardour/gtk_pianokeyboard.c91
1 files changed, 81 insertions, 10 deletions
diff --git a/gtk2_ardour/gtk_pianokeyboard.c b/gtk2_ardour/gtk_pianokeyboard.c
index 96742d7462..513dd17d43 100644
--- a/gtk2_ardour/gtk_pianokeyboard.c
+++ b/gtk2_ardour/gtk_pianokeyboard.c
@@ -139,7 +139,7 @@ draw_note(PianoKeyboard *pk, cairo_t* cr, int note)
}
static int
-press_key(PianoKeyboard *pk, int key)
+press_key(PianoKeyboard *pk, int key, int vel)
{
assert(key >= 0);
assert(key < NNOTES);
@@ -164,7 +164,7 @@ press_key(PianoKeyboard *pk, int key)
pk->notes[key].pressed = 1;
- g_signal_emit_by_name(GTK_WIDGET(pk), "note-on", key);
+ g_signal_emit_by_name(GTK_WIDGET(pk), "note-on", key, vel);
queue_note_draw(pk, key);
return 1;
@@ -405,8 +405,7 @@ keyboard_event_handler(GtkWidget *mk, GdkEventKey *event, gpointer ignored)
assert(note < NNOTES);
if (event->type == GDK_KEY_PRESS) {
- press_key(pk, note);
-
+ press_key(pk, note, pk->key_velocity);
} else if (event->type == GDK_KEY_RELEASE) {
release_key(pk, note);
}
@@ -441,6 +440,22 @@ get_note_for_xy(PianoKeyboard *pk, int x, int y)
return -1;
}
+static int
+get_velocity_for_note_at_y(PianoKeyboard *pk, int note, int y)
+{
+ if (note < 0) {
+ return 0;
+ }
+ int vel = pk->min_velocity + (pk->max_velocity - pk->min_velocity) * y / pk->notes[note].h;
+
+ if (vel < 1) {
+ return 1;
+ } else if (vel > 127) {
+ return 127;
+ }
+ return vel;
+}
+
static gboolean
mouse_button_event_handler(PianoKeyboard *pk, GdkEventButton *event, gpointer ignored)
{
@@ -464,7 +479,7 @@ mouse_button_event_handler(PianoKeyboard *pk, GdkEventButton *event, gpointer ig
if (pk->note_being_pressed_using_mouse >= 0)
release_key(pk, pk->note_being_pressed_using_mouse);
- press_key(pk, note);
+ press_key(pk, note, get_velocity_for_note_at_y (pk, note, y));
pk->note_being_pressed_using_mouse = note;
} else if (event->type == GDK_BUTTON_RELEASE) {
@@ -493,13 +508,16 @@ mouse_motion_event_handler(PianoKeyboard *pk, GdkEventMotion *event, gpointer ig
if ((event->state & GDK_BUTTON1_MASK) == 0)
return TRUE;
- note = get_note_for_xy(pk, event->x, event->y);
+ int x = event->x;
+ int y = event->y;
- if (note != pk->note_being_pressed_using_mouse && note >= 0) {
+ note = get_note_for_xy(pk, x, y);
- if (pk->note_being_pressed_using_mouse >= 0)
+ if (note != pk->note_being_pressed_using_mouse && note >= 0) {
+ if (pk->note_being_pressed_using_mouse >= 0) {
release_key(pk, pk->note_being_pressed_using_mouse);
- press_key(pk, note);
+ }
+ press_key(pk, note, get_velocity_for_note_at_y (pk, note, y));
pk->note_being_pressed_using_mouse = note;
}
@@ -610,6 +628,42 @@ piano_keyboard_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
}
}
+typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer data1,
+ gint arg1,
+ gint arg2,
+ gpointer data2);
+static void
+g_cclosure_user_marshal_VOID__INT_INT (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ GCClosure *cc = (GCClosure *) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__INT_INT callback;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ (param_values + 1)->data[0].v_int,
+ (param_values + 2)->data[0].v_int,
+ data2);
+}
+
static void
piano_keyboard_class_init(PianoKeyboardClass *klass)
{
@@ -618,7 +672,7 @@ piano_keyboard_class_init(PianoKeyboardClass *klass)
/* Set up signals. */
piano_keyboard_signals[NOTE_ON_SIGNAL] = g_signal_new ("note-on",
G_TYPE_FROM_CLASS (klass), (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
- 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+ 0, NULL, NULL, g_cclosure_user_marshal_VOID__INT_INT, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
piano_keyboard_signals[NOTE_OFF_SIGNAL] = g_signal_new ("note-off",
G_TYPE_FROM_CLASS (klass), (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
@@ -687,6 +741,10 @@ piano_keyboard_new(void)
pk->last_key = 0;
pk->monophonic = FALSE;
+ pk->min_velocity = 1;
+ pk->max_velocity = 127;
+ pk->key_velocity = 100;
+
memset((void *)pk->notes, 0, sizeof(struct PKNote) * NNOTES);
pk->key_bindings = g_hash_table_new(g_str_hash, g_str_equal);
@@ -708,6 +766,19 @@ piano_keyboard_set_monophonic(PianoKeyboard *pk, gboolean monophonic)
}
void
+piano_keyboard_set_velocities(PianoKeyboard *pk, int min_vel, int max_vel, int key_vel)
+{
+ if (min_vel <= max_vel && min_vel > 0 && max_vel < 128) {
+ pk->min_velocity = min_vel;
+ pk->max_velocity = max_vel;
+ }
+
+ if (key_vel > 0 && key_vel < 128) {
+ pk->key_velocity = key_vel;
+ }
+}
+
+void
piano_keyboard_sustain_press(PianoKeyboard *pk)
{
if (!pk->sustain_new_notes) {