* keyboard". Any "piano keyboard" key knows its own octave and
* accidental already. */
int keyboard_octave;
- pitch_accidental_t keyboard_accidental;
int midi_fd;
snd_midi_event_t *snd_midi_event;
pitch_group_t notes_pedaled;
int pedal_pressed;
+
+ pitch_t key;
} scherzo_t;
/* Forward declarations. */
static void
_score_challenge (scherzo_t *scherzo);
+static void
+pitch_group_remove_pitches (pitch_group_t *group);
+
+static void
+scherzo_update_notes_and_chord (scherzo_t *scherzo);
+
static int
on_delete_event_quit (unused (GtkWidget *widget),
unused (GdkEvent *event),
{
scherzo_t *scherzo = user_data;
int octave;
- /* Initialize to keep the compiler quiet. */
- pitch_name_t pitch_name = PITCH_NATURAL (C, 0);
- pitch_t pitch;
+ pitch_t pitch = PITCH_NOT_A_PITCH;
if (scherzo->challenge.active)
octave = PITCH_OCTAVE (scherzo->challenge.pitch);
gtk_widget_queue_draw (widget);
return TRUE;
break;
- case GDK_KEY_q:
- case GDK_KEY_Q:
case GDK_KEY_Escape:
gtk_main_quit ();
return FALSE;
- case GDK_KEY_c:
- case GDK_KEY_C:
- pitch_name = PITCH_NAME_C;
+ /* Map a piano keyboard onto the computer keyboard with white keys
+ * along the home row, (piano C on computer A, up to next octave
+ * higher C on computer K). Black keys are in the expected
+ * positions, (C# is W, D# is E, etc.).
+ */
+ case GDK_KEY_a:
+ case GDK_KEY_A:
+ pitch = PITCH_LITERAL (C, NATURAL, octave);
+ break;
+ case GDK_KEY_s:
+ case GDK_KEY_S:
+ pitch = PITCH_LITERAL (D, NATURAL, octave);
break;
case GDK_KEY_d:
case GDK_KEY_D:
- pitch_name = PITCH_NAME_D;
- break;
- case GDK_KEY_e:
- case GDK_KEY_E:
- pitch_name = PITCH_NAME_E;
+ pitch = PITCH_LITERAL (E, NATURAL, octave);
break;
case GDK_KEY_f:
case GDK_KEY_F:
- pitch_name = PITCH_NAME_F;
+ pitch = PITCH_LITERAL (F, NATURAL, octave);
break;
case GDK_KEY_g:
case GDK_KEY_G:
- pitch_name = PITCH_NAME_G;
+ pitch = PITCH_LITERAL (G, NATURAL, octave);
break;
- case GDK_KEY_a:
- case GDK_KEY_A:
- pitch_name = PITCH_NAME_A;
+ case GDK_KEY_h:
+ case GDK_KEY_H:
+ pitch = PITCH_LITERAL (A, NATURAL, octave);
break;
- case GDK_KEY_b:
- case GDK_KEY_B:
- pitch_name = PITCH_NAME_B;
+ case GDK_KEY_j:
+ case GDK_KEY_J:
+ pitch = PITCH_LITERAL (B, NATURAL, octave);
+ break;
+ case GDK_KEY_k:
+ case GDK_KEY_K:
+ pitch = PITCH_LITERAL (C, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_l:
+ case GDK_KEY_L:
+ pitch = PITCH_LITERAL (D, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_semicolon:
+ case GDK_KEY_colon:
+ pitch = PITCH_LITERAL (E, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_apostrophe:
+ case GDK_KEY_quotedbl:
+ pitch = PITCH_LITERAL (F, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_w:
+ case GDK_KEY_W:
+ pitch = PITCH_LITERAL (C, SHARP, octave);
+ break;
+ case GDK_KEY_e:
+ case GDK_KEY_E:
+ pitch = PITCH_LITERAL (D, SHARP, octave);
+ break;
+ case GDK_KEY_t:
+ case GDK_KEY_T:
+ pitch = PITCH_LITERAL (F, SHARP, octave);
+ break;
+ case GDK_KEY_y:
+ case GDK_KEY_Y:
+ pitch = PITCH_LITERAL (G, SHARP, octave);
+ break;
+ case GDK_KEY_u:
+ case GDK_KEY_U:
+ pitch = PITCH_LITERAL (A, SHARP, octave);
+ break;
+ case GDK_KEY_o:
+ case GDK_KEY_O:
+ pitch = PITCH_LITERAL (C, SHARP, octave + 1);
+ break;
+ case GDK_KEY_p:
+ case GDK_KEY_P:
+ pitch = PITCH_LITERAL (D, SHARP, octave + 1);
+ break;
+ case GDK_KEY_bracketright:
+ case GDK_KEY_braceright:
+ pitch = PITCH_LITERAL (F, SHARP, octave + 1);
break;
case GDK_KEY_0:
case GDK_KEY_1:
case GDK_KEY_space:
scherzo_press_pedal (scherzo);
break;
- case GDK_KEY_Up:
- if (scherzo->keyboard_accidental < PITCH_ACCIDENTAL_DOUBLE_SHARP)
- scherzo->keyboard_accidental++;
- break;
- case GDK_KEY_Down:
- if (scherzo->keyboard_accidental > PITCH_ACCIDENTAL_DOUBLE_FLAT)
- scherzo->keyboard_accidental--;
+ case GDK_KEY_Return:
+ /* Clear all notes when Return is pressed. */
+ pitch_group_remove_pitches (&scherzo->notes_pressed);
+ pitch_group_remove_pitches (&scherzo->notes_pedaled);
+ scherzo_update_notes_and_chord (scherzo);
break;
}
- pitch = PITCH (pitch_name, scherzo->keyboard_accidental, octave);
-
- if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
- (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
+ if (pitch != PITCH_NOT_A_PITCH)
{
scherzo_press_note (scherzo, pitch);
_judge_pitch (scherzo, pitch);
return TRUE;
}
-
/* Allow an unhandled event to propagate to other handlers. */
return FALSE;
}
{
scherzo_t *scherzo = user_data;
int octave;
- /* Initialize to keep the compiler quiet. */
- pitch_name_t pitch_name = PITCH_NAME_C;
- pitch_t pitch;
+ pitch_t pitch = PITCH_NOT_A_PITCH;
if (scherzo->challenge.active)
octave = PITCH_OCTAVE (scherzo->challenge.pitch);
octave = scherzo->keyboard_octave;
switch (key->keyval) {
- case GDK_KEY_c:
- case GDK_KEY_C:
- pitch_name = PITCH_NAME_C;
+ case GDK_KEY_a:
+ case GDK_KEY_A:
+ pitch = PITCH_LITERAL (C, NATURAL, octave);
+ break;
+ case GDK_KEY_s:
+ case GDK_KEY_S:
+ pitch = PITCH_LITERAL (D, NATURAL, octave);
break;
case GDK_KEY_d:
case GDK_KEY_D:
- pitch_name = PITCH_NAME_D;
- break;
- case GDK_KEY_e:
- case GDK_KEY_E:
- pitch_name = PITCH_NAME_E;
+ pitch = PITCH_LITERAL (E, NATURAL, octave);
break;
case GDK_KEY_f:
case GDK_KEY_F:
- pitch_name = PITCH_NAME_F;
+ pitch = PITCH_LITERAL (F, NATURAL, octave);
break;
case GDK_KEY_g:
case GDK_KEY_G:
- pitch_name = PITCH_NAME_G;
+ pitch = PITCH_LITERAL (G, NATURAL, octave);
break;
- case GDK_KEY_a:
- case GDK_KEY_A:
- pitch_name = PITCH_NAME_A;
+ case GDK_KEY_h:
+ case GDK_KEY_H:
+ pitch = PITCH_LITERAL (A, NATURAL, octave);
break;
- case GDK_KEY_b:
- case GDK_KEY_B:
- pitch_name = PITCH_NAME_B;
+ case GDK_KEY_j:
+ case GDK_KEY_J:
+ pitch = PITCH_LITERAL (B, NATURAL, octave);
+ break;
+ case GDK_KEY_k:
+ case GDK_KEY_K:
+ pitch = PITCH_LITERAL (C, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_l:
+ case GDK_KEY_L:
+ pitch = PITCH_LITERAL (D, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_semicolon:
+ case GDK_KEY_colon:
+ pitch = PITCH_LITERAL (E, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_apostrophe:
+ case GDK_KEY_quotedbl:
+ pitch = PITCH_LITERAL (F, NATURAL, octave + 1);
+ break;
+ case GDK_KEY_w:
+ case GDK_KEY_W:
+ pitch = PITCH_LITERAL (C, SHARP, octave);
+ break;
+ case GDK_KEY_e:
+ case GDK_KEY_E:
+ pitch = PITCH_LITERAL (D, SHARP, octave);
+ break;
+ case GDK_KEY_t:
+ case GDK_KEY_T:
+ pitch = PITCH_LITERAL (F, SHARP, octave);
+ break;
+ case GDK_KEY_y:
+ case GDK_KEY_Y:
+ pitch = PITCH_LITERAL (G, SHARP, octave);
+ break;
+ case GDK_KEY_u:
+ case GDK_KEY_U:
+ pitch = PITCH_LITERAL (A, SHARP, octave);
+ break;
+ case GDK_KEY_o:
+ case GDK_KEY_O:
+ pitch = PITCH_LITERAL (C, SHARP, octave + 1);
+ break;
+ case GDK_KEY_p:
+ case GDK_KEY_P:
+ pitch = PITCH_LITERAL (D, SHARP, octave + 1);
+ break;
+ case GDK_KEY_bracketright:
+ case GDK_KEY_braceright:
+ pitch = PITCH_LITERAL (F, SHARP, octave + 1);
break;
case GDK_KEY_space:
scherzo_release_pedal (scherzo);
break;
}
- pitch = PITCH (pitch_name, scherzo->keyboard_accidental, octave);
-
- if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
- (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
+ if (pitch != PITCH_NOT_A_PITCH)
{
scherzo_release_note (scherzo, pitch);
_score_challenge (scherzo);
return 1;
}
-static const char *
-_pitch_str (pitch_t pitch)
-{
- static char double_flat[] = "X𝄫";
- static char flat[] = "X♭";
- static char natural[] = "X";
- static char sharp[] = "X♯";
- static char double_sharp[] = "X𝄪";
- char *ret;
-
- switch (PITCH_ACCIDENTAL (pitch)) {
- case PITCH_ACCIDENTAL_DOUBLE_FLAT:
- ret = double_flat;
- break;
- case PITCH_ACCIDENTAL_FLAT:
- ret = flat;
- break;
- case PITCH_ACCIDENTAL_NATURAL:
- ret = natural;
- break;
- case PITCH_ACCIDENTAL_SHARP:
- ret = sharp;
- break;
- case PITCH_ACCIDENTAL_DOUBLE_SHARP:
- ret = double_sharp;
- break;
- }
-
- switch (PITCH_NAME(pitch)) {
- case PITCH_NAME_C:
- ret[0] = 'C';
- break;
- case PITCH_NAME_D:
- ret[0] = 'D';
- break;
- case PITCH_NAME_E:
- ret[0] = 'E';
- break;
- case PITCH_NAME_F:
- ret[0] = 'F';
- break;
- case PITCH_NAME_G:
- ret[0] = 'G';
- break;
- case PITCH_NAME_A:
- ret[0] = 'A';
- break;
- case PITCH_NAME_B:
- ret[0] = 'B';
- break;
- }
-
- return ret;
-}
-
typedef struct chord_signature
{
int num_degrees;
}
*/
+/* Remove all pitches from a pitch_group_t */
+static void
+pitch_group_remove_pitches (pitch_group_t *group)
+{
+ talloc_free (group->pitches);
+ pitch_group_init (group->ctx, group);
+}
+
static void
scherzo_update_notes_and_chord (scherzo_t *scherzo)
{
signature, *root);
chord_name = talloc_asprintf (local, "%s%s",
- _pitch_str (*root),
+ pitch_string (*root),
signature->name);
}
} else if (chord->num_pitches > 2) {
scherzo.chord = NULL;
- /* Default to octave 4 and natural for computer keyboard keypresses. */
+ /* Default to octave 4 for computer keyboard keypresses. */
scherzo.keyboard_octave = 4;
- scherzo.keyboard_accidental = PITCH_ACCIDENTAL_NATURAL;
pitch_group_init (scherzo.ctx, &scherzo.notes_pressed);
pitch_group_init (scherzo.ctx, &scherzo.notes_pedaled);
scherzo.pedal_pressed = 0;
+ scherzo.key = PITCH_CLASS_LITERAL (C, NATURAL);
+ score_set_key (scherzo.score, scherzo.key);
+
mnemon_init (&scherzo.mnemon);
/* XXX: Should create a default file if one cannot be loaded. */
mnemon_load_category (&scherzo.mnemon, "scherzo-notes");