gint scorearea_keyrelease_event (GtkWidget * widget, GdkEventKey * event) { if(!Denemo.keyboard_state_locked) { Denemo.keyboard_state ^= (0xf & klock_mask (event->keyval)); if ((event->keyval == GDK_Alt_L) || (event->keyval == GDK_Alt_R)) { if ((Denemo.keyboard_state & CHORD_MASK)) //At least one note has been entered in a chord next_insert_or_editable_note (); Denemo.keyboard_state &= ~CHORD_MASK; } set_midi_in_status (); } //g_print("release %x state %x\n", Denemo.keyboard_state, event->state); // set_cursor_for(keyrelease_modify(event->state), event->keyval); gint state; if ((event->keyval == GDK_Caps_Lock) || (event->keyval == GDK_Num_Lock)) return TRUE; state = (lock_mask (event->keyval) ^ event->state); set_cursor_for (state); return TRUE; }
void process_midi_event (gchar * buf) { if (command == MIDI_CONTROL_CHANGE && (notenumber == 0x40)) { if (velocity == 0x7F) {//PEDAL DOWN if (Denemo.project->movement->cursor_appending || at_nonprinting ()) Denemo.keyboard_state |= ADDING_MASK; else Denemo.keyboard_state |= CHORD_MASK | ADDING_MASK; } else { Denemo.keyboard_state &= ~(CHORD_MASK | ADDING_MASK); next_insert_or_editable_note();//next_insert_or_editable_note (); } set_midi_in_status (); displayhelper (Denemo.project); } if ((0xFFFFFF & *(gint *) buf) == 0) { set_midi_capture (FALSE); g_queue_clear (&midi_queue); if (divert_midi_event) { *divert_midi_event = 0; divert_midi_event = NULL; gtk_main_quit (); } //g_debug("queue emptied %d\n", g_queue_get_length(&midi_queue)); } else { if (command == MIDI_NOTE_ON) midiaction (notenumber); else if (command == MIDI_CONTROL_CHANGE) { gchar *command_name = get_midi_control_command (notenumber, velocity); if (command_name) { execute_callback_from_name (command_name); g_free (command_name); } else { if (notenumber == 0x40) { //Foot Pedal if (velocity == 0x7F) { if ((Denemo.project->movement->cursor_appending) || at_nonprinting ()) Denemo.keyboard_state |= ADDING_MASK; else Denemo.keyboard_state |= CHORD_MASK | ADDING_MASK; } else { Denemo.keyboard_state &= ~(CHORD_MASK | ADDING_MASK); //next_editable_note (); this causes a double advance... } set_midi_in_status (); displayhelper (Denemo.project); } } } else if (command == MIDI_PITCH_BEND) { gchar *command_name = get_midi_pitch_bend_command ((notenumber << 8) + velocity); if (command_name) { execute_callback_from_name (command_name); g_free (command_name); } } } }
/* take an action for the passed note. Enter/edit/check the score following the mode and keyboard state. */ static gint midiaction (gint notenum) { gboolean new_measure = Denemo.project->movement->cursoroffend; DenemoProject *gui = Denemo.project; if (gui == NULL) return TRUE; if (gui->movement == NULL) return TRUE; DenemoStaff *curstaffstruct = (DenemoStaff *) gui->movement->currentstaff->data; enharmonic enote, prevenote; gboolean have_previous; //g_print("midiaction Adding mask %x, Chord mask %x\n", (Denemo.keyboard_state & ADDING_MASK) , (Denemo.keyboard_state & CHORD_MASK)); notenum2enharmonic (notenum, &enote.mid_c_offset, &enote.enshift, &enote.octave); if (Denemo.project->movement->cursor_appending) have_previous = get_current (&prevenote); else have_previous = get_previous (&prevenote); if (!(Denemo.keyboard_state & CHECKING_MASK)) stage_undo (gui->movement, ACTION_STAGE_END); //undo is a queue so this is the end :) if ((gui->mode & INPUTEDIT) || (Denemo.keyboard_state & CHECKING_MASK)) { static gboolean beep = FALSE; gboolean is_tied = FALSE; gint measure = gui->movement->currentmeasurenum; if (Denemo.project->movement->currentobject) { DenemoObject *curObj = Denemo.project->movement->currentobject->data; if (curObj->type == CHORD) { do { curObj = Denemo.project->movement->currentobject->data; chord *thechord = (chord *) curObj->object; is_tied = (!Denemo.prefs.ignore_ties) && thechord->is_tied; //#define check_midi_note(a,b,c,d) ((a->mid_c_offset==b)&&(a->enshift==c))?playnote(a,curstaffstruct->midi_channel):gdk_beep(); if ((Denemo.keyboard_state & CHECKING_MASK) && thechord->notes) { //later - find note nearest cursor and note *thenote = (note *) thechord->notes->data; // check_midi_note(thenote, enote.mid_c_offset + 7 *(enote.octave), enote.enshift, enote.octave); if ((!curObj->isinvisible) && (thenote->mid_c_offset == (enote.mid_c_offset + 7 * (enote.octave))) && (thenote->enshift == enote.enshift)) { gint midi = dia_to_midinote (thenote->mid_c_offset) + thenote->enshift; play_note (DEFAULT_BACKEND, 0 /*port */ , curstaffstruct->midi_channel, midi, 300 /*duration */ , 0); } else { gdk_beep (); break; //do not move on to next note } } else { do_one_note (enote.mid_c_offset, enote.enshift, enote.octave); } if (Denemo.project->movement->cursor_appending) break; curObj = Denemo.project->movement->currentobject->data; thechord = (chord *) curObj->object; is_tied = (!Denemo.prefs.ignore_ties) && thechord->is_tied; } while ((!(Denemo.keyboard_state & ADDING_MASK)) && next_editable_note () && is_tied); } else //there is a current object that is not a chord { if (gui->movement->cursor_appending) { do_one_note (enote.mid_c_offset, enote.enshift, enote.octave); next_insert_or_editable_note(); //in some circumstance this fails to advance to the next editable note, the following checks for that. if (Denemo.project->movement->currentobject) { curObj = Denemo.project->movement->currentobject->data; if(!curObj->isinvisible) next_editable_note (); } } else gdk_beep (); } if (gui->mode & INPUTRHYTHM) { //g_print("measure was %d now %d with appending %d\n", measure, gui->movement->currentmeasurenum, gui->movement->cursor_appending); if (!beep && (measure != gui->movement->currentmeasurenum) && !gui->movement->cursor_appending) beep = TRUE; else if (beep) signal_measure_end (), beep = FALSE; } } else { // no current object do_one_note (enote.mid_c_offset, enote.enshift, enote.octave); next_insert_or_editable_note();//next_editable_note ();//if we have gone back from an empty measure we need this. } } else { // not INPUTEDIT action_note_into_score (enote.mid_c_offset, enote.enshift, enote.octave); } if (!(Denemo.keyboard_state & CHECKING_MASK)) { stage_undo (gui->movement, ACTION_STAGE_START); } draw_score_area(); //just for advancing the cursor. if (!(Denemo.keyboard_state & CHECKING_MASK)) { if (Denemo.prefs.immediateplayback) { gint channel = curstaffstruct->midi_channel; if (have_previous && check_interval (enote.mid_c_offset, enote.enshift, prevenote.mid_c_offset, prevenote.enshift)) channel = Denemo.prefs.pitchspellingchannel; play_note (DEFAULT_BACKEND, 0 /*port */ , channel, notenum, 300 /*duration */ , 0); if(new_measure) signal_measure_end(); } } return TRUE; }