X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=scherzo.c;h=5de614807aca4c8b1f30b2d3a979f0f9803d1cb0;hb=1fe478f5aaa4f8ebff2a3f7771809c3d1aaa5ef4;hp=88cae44fe4cdb85bde4669a41e713f463767915c;hpb=05c28164f342656bd02bb4c6607b938bb8d3f2b1;p=scherzo diff --git a/scherzo.c b/scherzo.c index 88cae44..5de6148 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), @@ -92,7 +105,7 @@ on_expose_event_draw (GtkWidget *widget, cairo_paint (cr); /* Add some padding on the sides and top */ - cairo_translate (cr, pad, 2 * scherzo->staff_height); + cairo_translate (cr, pad, scherzo->staff_height); score_set_staff_height (score, scherzo->staff_height); score_set_width (score, widget_width - 2 * pad); @@ -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 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 the event to propagate to other handlers. */ + + /* 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) { @@ -325,10 +452,12 @@ _judge_note (scherzo_t *scherzo, score_note_t *note) note->octave == challenge->note->octave) { challenge->satisfied = 1; + score_set_note_color_rgb (note, 18/256., 130/256., 28/256.); /* green */ } else { challenge->mistaken = 1; + score_set_note_color_rgb (note, 184/256., 4/256., 22/256.); /* red */ } } @@ -358,6 +487,7 @@ on_midi_input (unused (GIOChannel *channel), ssize_t remaining; snd_seq_event_t event; score_note_t *note; + int need_redraw = FALSE; remaining = read (scherzo->midi_fd, buf, MIDI_BUF_SIZE); @@ -378,12 +508,12 @@ on_midi_input (unused (GIOChannel *channel), case SND_SEQ_EVENT_NOTEON: note = scherzo_add_note_midi (scherzo, event.data.note.note); _judge_note (scherzo, note); - gtk_widget_queue_draw (scherzo->window); + need_redraw = TRUE; break; case SND_SEQ_EVENT_NOTEOFF: scherzo_remove_note_midi (scherzo, event.data.note.note); _score_challenge (scherzo); - gtk_widget_queue_draw (scherzo->window); + need_redraw = TRUE; break; case SND_SEQ_EVENT_CLOCK: /* Ignore for now as my piano sends a constant stream of these. */ @@ -397,7 +527,10 @@ on_midi_input (unused (GIOChannel *channel), break; } } - + + if (need_redraw) + gtk_widget_queue_draw (scherzo->window); + /* Return TRUE to continue to get called in the future. */ return TRUE; } @@ -416,7 +549,7 @@ main (int argc, char *argv[]) scherzo.ctx = talloc_new (NULL); scherzo.score = score_create (scherzo.ctx); - scherzo.staff_height = 48; + scherzo.staff_height = 100; score_set_staff_height (scherzo.score, scherzo.staff_height); score_add_brace (scherzo.score, 2); @@ -428,7 +561,7 @@ main (int argc, char *argv[]) mnemon_init (&scherzo.mnemon); /* XXX: Should create a default file if one cannot be loaded. */ - mnemon_load_category (&scherzo.mnemon, "scherzo"); + mnemon_load_category (&scherzo.mnemon, "scherzo-notes"); scherzo.challenge.note = NULL; _select_challenge (&scherzo); @@ -453,7 +586,7 @@ main (int argc, char *argv[]) scherzo.window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size (GTK_WINDOW (scherzo.window), 600, 400); + gtk_window_set_default_size (GTK_WINDOW (scherzo.window), 1000, 600); g_signal_connect (scherzo.window, "delete-event", G_CALLBACK (on_delete_event_quit), NULL); @@ -466,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);