From 590c3f4f3b3ab138c67439d71be13f82446b69d4 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 27 Sep 2011 17:34:55 -0700 Subject: [PATCH] Add ability to perform input with computer (not midi) keyboard. This is useful for testing when away from a keyboard, and also useful in its own right for ensuring that the user knows the names of the notes (not just their position on the piano keyboard). When using a computer keyboard for input only the note name itself is needed---the correct octave is chosen automatically. --- scherzo.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 143 insertions(+), 12 deletions(-) diff --git a/scherzo.c b/scherzo.c index 2d43aee..8d6ca9a 100644 --- a/scherzo.c +++ b/scherzo.c @@ -58,6 +58,19 @@ typedef struct scherzo score_note_t **notes_pressed; } scherzo_t; +/* Forward declarations. */ +static score_note_t * +scherzo_add_note (scherzo_t *scherzo, score_pitch_t pitch, int octave); + +static void +scherzo_remove_note (scherzo_t *scherzo, score_pitch_t pitch, int octave); + +static void +_judge_note (scherzo_t *scherzo, score_note_t *note); + +static void +_score_challenge (scherzo_t *scherzo); + static int on_delete_event_quit (unused (GtkWidget *widget), unused (GdkEvent *event), @@ -107,6 +120,8 @@ on_key_press_event (GtkWidget *widget, void *user_data) { scherzo_t *scherzo = user_data; + int octave = scherzo->challenge.note->octave; + score_pitch_t pitch; switch (key->keyval) { case GDK_KEY_plus: @@ -128,9 +143,105 @@ on_key_press_event (GtkWidget *widget, case GDK_KEY_Escape: gtk_main_quit (); return FALSE; + case GDK_KEY_c: + case GDK_KEY_C: + pitch = SCORE_PITCH_C; + break; + case GDK_KEY_d: + case GDK_KEY_D: + pitch = SCORE_PITCH_D; + break; + case GDK_KEY_e: + case GDK_KEY_E: + pitch = SCORE_PITCH_E; + break; + case GDK_KEY_f: + case GDK_KEY_F: + pitch = SCORE_PITCH_F; + break; + case GDK_KEY_g: + case GDK_KEY_G: + pitch = SCORE_PITCH_G; + break; + case GDK_KEY_a: + case GDK_KEY_A: + pitch = SCORE_PITCH_A; + break; + case GDK_KEY_b: + case GDK_KEY_B: + pitch = SCORE_PITCH_B; + break; + } + + if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) || + (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g)) + { + score_note_t *note; + + note = scherzo_add_note (scherzo, pitch, octave); + _judge_note (scherzo, note); + gtk_widget_queue_draw (scherzo->window); + + return TRUE; } - /* Allow the event to propagate to other handlers. */ + + /* Allow an unhandled event to propagate to other handlers. */ + return FALSE; +} + +static int +on_key_release_event (unused (GtkWidget *widget), + GdkEventKey *key, + void *user_data) +{ + scherzo_t *scherzo = user_data; + int octave = scherzo->challenge.note->octave; + score_pitch_t pitch; + + switch (key->keyval) { + case GDK_KEY_c: + case GDK_KEY_C: + pitch = SCORE_PITCH_C; + break; + case GDK_KEY_d: + case GDK_KEY_D: + pitch = SCORE_PITCH_D; + break; + case GDK_KEY_e: + case GDK_KEY_E: + pitch = SCORE_PITCH_E; + break; + case GDK_KEY_f: + case GDK_KEY_F: + pitch = SCORE_PITCH_F; + break; + case GDK_KEY_g: + case GDK_KEY_G: + pitch = SCORE_PITCH_G; + break; + case GDK_KEY_a: + case GDK_KEY_A: + pitch = SCORE_PITCH_A; + break; + case GDK_KEY_b: + case GDK_KEY_B: + pitch = SCORE_PITCH_B; + break; + } + + if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) || + (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g)) + { + scherzo_remove_note (scherzo, pitch, octave); + _score_challenge (scherzo); + gtk_widget_queue_draw (scherzo->window); + + return TRUE; + } + + + /* Allow an unhandled event to propagate to other handlers. */ return FALSE; } @@ -183,17 +294,13 @@ _midi_to_score_pitch_and_octave (unsigned char midi_note, } static score_note_t * -scherzo_add_note_midi (scherzo_t *scherzo, unsigned char midi_note) +scherzo_add_note (scherzo_t *scherzo, score_pitch_t pitch, int octave) { score_staff_t *staff; - score_pitch_t pitch; - int octave; score_note_t *note; staff = scherzo->challenge.staff; - _midi_to_score_pitch_and_octave (midi_note, &pitch, &octave); - note = score_add_note (staff, pitch, octave, SCORE_DURATION_WHOLE); scherzo->num_notes_pressed++; @@ -211,16 +318,13 @@ scherzo_add_note_midi (scherzo_t *scherzo, unsigned char midi_note) return note; } + static void -scherzo_remove_note_midi (scherzo_t *scherzo, unsigned char midi_note) +scherzo_remove_note (scherzo_t *scherzo, score_pitch_t pitch, int octave) { - score_pitch_t pitch; - int octave; score_note_t *note; int i; - _midi_to_score_pitch_and_octave (midi_note, &pitch, &octave); - for (i = 0; i < scherzo->num_notes_pressed; i++) { note = scherzo->notes_pressed[i]; if (note->pitch == pitch && note->octave == octave) { @@ -236,6 +340,29 @@ scherzo_remove_note_midi (scherzo_t *scherzo, unsigned char midi_note) } } +static score_note_t * +scherzo_add_note_midi (scherzo_t *scherzo, unsigned char midi_note) +{ + score_pitch_t pitch; + int octave; + + _midi_to_score_pitch_and_octave (midi_note, &pitch, &octave); + + return scherzo_add_note (scherzo, pitch, octave); +} + + +static void +scherzo_remove_note_midi (scherzo_t *scherzo, unsigned char midi_note) +{ + score_pitch_t pitch; + int octave; + + _midi_to_score_pitch_and_octave (midi_note, &pitch, &octave); + + scherzo_remove_note (scherzo, pitch, octave); +} + void _select_challenge (scherzo_t *scherzo) { @@ -472,9 +599,13 @@ main (int argc, char *argv[]) G_CALLBACK (on_expose_event_draw), &scherzo); - g_signal_connect (scherzo.window, "key-press-event", + g_signal_connect (scherzo.window, "key-press-event", G_CALLBACK (on_key_press_event), &scherzo); + + g_signal_connect (scherzo.window, "key-release-event", + G_CALLBACK (on_key_release_event), + &scherzo); gtk_widget_show_all (scherzo.window); -- 2.43.0