diff --git a/gtk2_ardour/gtk_pianokeyboard.c b/gtk2_ardour/gtk_pianokeyboard.c index b3cfa4f410..bc51edb371 100644 --- a/gtk2_ardour/gtk_pianokeyboard.c +++ b/gtk2_ardour/gtk_pianokeyboard.c @@ -47,6 +47,7 @@ enum { NOTE_ON_SIGNAL, NOTE_OFF_SIGNAL, + REST_SIGNAL, LAST_SIGNAL }; @@ -183,6 +184,12 @@ release_key(PianoKeyboard *pk, int key) return 1; } +static void +rest (PianoKeyboard* pk) +{ + g_signal_emit_by_name(GTK_WIDGET(pk), "rest"); +} + static void stop_unsustained_notes(PianoKeyboard *pk) { @@ -249,6 +256,8 @@ bind_keys_qwerty(PianoKeyboard *pk) { clear_notes(pk); + bind_key(pk, "space", 128); + /* Lower keyboard row - "zxcvbnm". */ bind_key(pk, "z", 12); /* C0 */ bind_key(pk, "s", 13); @@ -300,6 +309,8 @@ bind_keys_azerty(PianoKeyboard *pk) { clear_notes(pk); + bind_key(pk, "space", 128); + /* Lower keyboard row - "wxcvbn,". */ bind_key(pk, "w", 12); /* C0 */ bind_key(pk, "s", 13); @@ -367,6 +378,14 @@ keyboard_event_handler(GtkWidget *mk, GdkEventKey *event, gpointer notused) return FALSE; } + if (note == 128) { + if (event->type == GDK_KEY_RELEASE) { + rest (pk); + } + + return TRUE; + } + note += pk->octave * 12; assert(note >= 0); @@ -586,6 +605,10 @@ piano_keyboard_class_init(PianoKeyboardClass *klass) G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + piano_keyboard_signals[REST_SIGNAL] = g_signal_new ("rest", + G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + widget_klass = (GtkWidgetClass*) klass; widget_klass->expose_event = piano_keyboard_expose; @@ -621,6 +644,7 @@ piano_keyboard_get_type(void) sizeof (PianoKeyboard), 0, /* n_preallocs */ (GInstanceInitFunc) piano_keyboard_init, + 0, /* value_table */ }; mk_type = g_type_register_static(GTK_TYPE_DRAWING_AREA, "PianoKeyboard", &mk_info, 0); diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 0287a1c0ea..098b96b5b2 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -116,6 +116,7 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session* sess, , _midi_thru_item (0) , default_channel_menu (0) , controller_menu (0) + , step_editor (0) { subplugin_menu.set_name ("ArdourContextMenu"); @@ -924,16 +925,30 @@ MidiTimeAxisView::start_step_editing () midi_track()->set_step_editing (true); - StepEntry* se = new StepEntry (*this); + if (step_editor == 0) { + step_editor = new StepEntry (*this); + step_editor->signal_delete_event().connect (sigc::mem_fun (*this, &MidiTimeAxisView::step_editor_hidden)); + } - se->set_position (WIN_POS_MOUSE); - se->present (); + step_editor->set_position (WIN_POS_MOUSE); + step_editor->present (); +} + +bool +MidiTimeAxisView::step_editor_hidden (GdkEventAny*) +{ + stop_step_editing (); + return true; } void MidiTimeAxisView::stop_step_editing () { midi_track()->set_step_editing (false); + + if (step_editor) { + step_editor->hide (); + } } void diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index fe1835266f..abe5218be3 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -53,6 +53,7 @@ class PublicEditor; class MidiStreamView; class MidiScroomer; class PianoRollHeader; +class StepEntry; class MidiTimeAxisView : public RouteTimeAxisView { @@ -172,6 +173,9 @@ class MidiTimeAxisView : public RouteTimeAxisView ParameterMenuMap _channel_command_menu_map; /** parameter -> menu item map for the controller menu */ ParameterMenuMap _controller_menu_map; + + StepEntry* step_editor; + bool step_editor_hidden (GdkEventAny*); }; #endif /* __ardour_midi_time_axis_h__ */ diff --git a/gtk2_ardour/step_entry.cc b/gtk2_ardour/step_entry.cc index 09bdb076d2..f585cba057 100644 --- a/gtk2_ardour/step_entry.cc +++ b/gtk2_ardour/step_entry.cc @@ -19,6 +19,8 @@ #include +#include "gtkmm2ext/keyboard.h" + #include "midi_time_axis.h" #include "step_entry.h" #include "utils.h" @@ -33,9 +35,14 @@ _note_off_event_handler (GtkWidget* widget, int note, gpointer arg) ((StepEntry*)arg)->note_off_event_handler (note); } +static void +_rest_event_handler (GtkWidget* widget, gpointer arg) +{ + ((StepEntry*)arg)->rest_event_handler (); +} StepEntry::StepEntry (MidiTimeAxisView& mtv) - : ArdourDialog (_("Step Entry Editor")) + : ArdourDialog (string_compose (_("Step Entry: %1"), mtv.name())) , triplet_button ("3") , sustain_button ("sustain") , rest_button ("rest") @@ -166,10 +173,15 @@ StepEntry::StepEntry (MidiTimeAxisView& mtv) upper_box.pack_start (channel_spinner, false, false); _piano = (PianoKeyboard*) piano_keyboard_new (); - piano = Glib::wrap ((GtkWidget*) _piano); piano_keyboard_set_keyboard_cue (PIANO_KEYBOARD(_piano), 1); + + piano = Glib::wrap ((GtkWidget*) _piano); + + piano->set_flags (Gtk::CAN_FOCUS); + piano->signal_enter_notify_event().connect (sigc::mem_fun (*this, &StepEntry::piano_enter_notify_event), false); g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this); + g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this); rest_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::rest_click)); chord_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::chord_toggled)); @@ -187,6 +199,28 @@ StepEntry::~StepEntry() { } +bool +StepEntry::on_key_press_event (GdkEventKey* ev) +{ + int ret; + g_signal_emit_by_name (G_OBJECT(_piano), "key-press-event", ev, &ret); + return ret; +} + +bool +StepEntry::on_key_release_event (GdkEventKey* ev) +{ + int ret; + g_signal_emit_by_name (G_OBJECT(_piano), "key-release-event", ev, &ret); + return ret; +} + +void +StepEntry::rest_event_handler () +{ + _mtv->step_edit_rest(); +} + void StepEntry::note_off_event_handler (int note) { @@ -259,3 +293,11 @@ StepEntry::chord_toggled () _mtv->step_edit_toggle_chord (); } } + +bool +StepEntry::piano_enter_notify_event (GdkEventCrossing *ev) +{ + piano->grab_focus (); + return false; +} + diff --git a/gtk2_ardour/step_entry.h b/gtk2_ardour/step_entry.h index d57ac3fadf..d65cbe17db 100644 --- a/gtk2_ardour/step_entry.h +++ b/gtk2_ardour/step_entry.h @@ -38,7 +38,8 @@ class StepEntry : public ArdourDialog ~StepEntry (); void note_off_event_handler (int note); - + void rest_event_handler (); + private: Gtk::VBox packer; Gtk::HBox upper_box; @@ -81,6 +82,10 @@ class StepEntry : public ArdourDialog void sustain_click (); void chord_toggled (); void triplet_toggled (); + + bool piano_enter_notify_event (GdkEventCrossing *ev); + bool on_key_release_event (GdkEventKey*); + bool on_key_press_event (GdkEventKey*); }; #endif /* __gtk2_ardour_step_entry_h__ */