add step editing sustain support
[ardour.git] / gtk2_ardour / step_entry.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <iostream>
21
22 #include "pbd/filesystem.h"
23 #include "pbd/file_utils.h"
24
25 #include "gtkmm2ext/keyboard.h"
26 #include "gtkmm2ext/actions.h"
27 #include "gtkmm2ext/bindings.h"
28
29 #include "ardour/filesystem_paths.h"
30
31 #include "ardour_ui.h"
32 #include "midi_channel_selector.h"
33 #include "midi_time_axis.h"
34 #include "step_entry.h"
35 #include "utils.h"
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace Gtk;
41 using namespace Glib;
42 using namespace Gtkmm2ext;
43 using namespace PBD;
44 using namespace ARDOUR;
45
46 static void
47 _note_off_event_handler (GtkWidget* widget, int note, gpointer arg)
48 {
49         ((StepEntry*)arg)->note_off_event_handler (note);
50 }
51
52 static void
53 _rest_event_handler (GtkWidget* widget, gpointer arg)
54 {
55         ((StepEntry*)arg)->rest_event_handler ();
56 }
57
58 StepEntry::StepEntry (MidiTimeAxisView& mtv)
59         : ArdourDialog (string_compose (_("Step Entry: %1"), mtv.name()))
60         , _current_note_length (1.0)
61         , _current_note_velocity (64)
62         , triplet_button ("3")
63         , beat_resync_button (_(">beat"))
64         , bar_resync_button (_(">bar"))
65         , sustain_button (_("sustain"))
66         , rest_button (_("rest"))
67         , grid_rest_button (_("g-rest"))
68         , channel_adjustment (1, 1, 16, 1, 4) 
69         , channel_spinner (channel_adjustment)
70         , octave_adjustment (4, 1, 11, 1, 4) // start in octave 4
71         , octave_spinner (octave_adjustment)
72         , length_divisor_adjustment (1.0, 1.0, 128, 1.0, 4.0)
73         , length_divisor_spinner (length_divisor_adjustment)
74         , velocity_adjustment (64.0, 0.0, 127.0, 1.0, 4.0)
75         , velocity_spinner (velocity_adjustment)
76         , bank_adjustment (0, 0.0, 127.0, 1.0, 4.0)
77         , bank_spinner (bank_adjustment)
78         , bank_button (_("+"))
79         , program_adjustment (0, 0.0, 127.0, 1.0, 4.0)
80         , program_spinner (program_adjustment)
81         , program_button (_("+"))
82         , _piano (0)
83         , piano (0)
84         , _mtv (&mtv)
85 {
86         register_actions ();
87         load_bindings ();
88
89         /* set channel selector to first selected channel. if none
90            are selected, it will remain at the value set in its
91            constructor, above (1)
92         */
93
94         uint16_t chn_mask = _mtv->channel_selector().get_selected_channels();
95         
96         for (uint32_t i = 0; i < 16; ++i) {
97                 if (chn_mask & (1<<i)) {
98                         channel_adjustment.set_value (i+1);
99                         break;
100                 }
101         }
102
103         RadioButtonGroup length_group = length_1_button.get_group();
104         length_2_button.set_group (length_group);
105         length_4_button.set_group (length_group);
106         length_8_button.set_group (length_group);
107         length_12_button.set_group (length_group);
108         length_16_button.set_group (length_group);
109         length_32_button.set_group (length_group);
110         length_64_button.set_group (length_group);
111
112         Widget* w;
113
114         w = manage (new Image (::get_icon (X_("wholenote"))));
115         w->show();
116         length_1_button.add (*w);
117         w = manage (new Image (::get_icon (X_("halfnote"))));
118         w->show();
119         length_2_button.add (*w);
120         w = manage (new Image (::get_icon (X_("quarternote"))));
121         w->show();
122         length_4_button.add (*w);
123         w = manage (new Image (::get_icon (X_("eighthnote"))));
124         w->show();
125         length_8_button.add (*w);
126         w = manage (new Image (::get_icon (X_("sixteenthnote"))));
127         w->show();
128         length_16_button.add (*w);
129         w = manage (new Image (::get_icon (X_("thirtysecondnote"))));
130         w->show();
131         length_32_button.add (*w);
132         w = manage (new Image (::get_icon (X_("sixtyfourthnote"))));
133         w->show();
134         length_64_button.add (*w);
135
136         RefPtr<Action> act;
137
138         act = myactions.find_action ("StepEditing/note-length-whole");
139         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_1_button.gobj()), act->gobj());
140         act = myactions.find_action ("StepEditing/note-length-half");
141         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_2_button.gobj()), act->gobj());
142         act = myactions.find_action ("StepEditing/note-length-quarter");
143         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_4_button.gobj()), act->gobj());
144         act = myactions.find_action ("StepEditing/note-length-eighth");
145         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_8_button.gobj()), act->gobj());
146         act = myactions.find_action ("StepEditing/note-length-sixteenth");
147         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_16_button.gobj()), act->gobj());
148         act = myactions.find_action ("StepEditing/note-length-thirtysecond");
149         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_32_button.gobj()), act->gobj());
150         act = myactions.find_action ("StepEditing/note-length-sixtyfourth");
151         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_64_button.gobj()), act->gobj());
152
153         length_1_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
154         length_1_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 1), false);
155         length_2_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
156         length_2_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 2), false);
157         length_4_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
158         length_4_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 4), false);
159         length_8_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
160         length_8_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 8), false);
161         length_16_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
162         length_16_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 16), false);
163         length_32_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
164         length_32_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 32), false);
165         length_64_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
166         length_64_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 64), false);
167
168         length_1_button.property_draw_indicator() = false;
169         length_2_button.property_draw_indicator() = false;
170         length_4_button.property_draw_indicator() = false;
171         length_8_button.property_draw_indicator() = false;
172         length_16_button.property_draw_indicator() = false;
173         length_32_button.property_draw_indicator() = false;
174         length_64_button.property_draw_indicator() = false;
175
176         note_length_box.pack_start (length_1_button, false, false);
177         note_length_box.pack_start (length_2_button, false, false);
178         note_length_box.pack_start (length_4_button, false, false);
179         note_length_box.pack_start (length_8_button, false, false);
180         note_length_box.pack_start (length_16_button, false, false);
181         note_length_box.pack_start (length_32_button, false, false);
182         note_length_box.pack_start (length_64_button, false, false);
183
184         ARDOUR_UI::instance()->set_tip (&length_1_button, _("Set note length to a whole note"), "");
185         ARDOUR_UI::instance()->set_tip (&length_2_button, _("Set note length to a half note"), "");
186         ARDOUR_UI::instance()->set_tip (&length_4_button, _("Set note length to a quarter note"), "");
187         ARDOUR_UI::instance()->set_tip (&length_8_button, _("Set note length to a eighth note"), "");
188         ARDOUR_UI::instance()->set_tip (&length_16_button, _("Set note length to a sixteenth note"), "");
189         ARDOUR_UI::instance()->set_tip (&length_32_button, _("Set note length to a thirty-second note"), "");
190         ARDOUR_UI::instance()->set_tip (&length_64_button, _("Set note length to a sixty-fourth note"), "");
191
192         RadioButtonGroup velocity_group = velocity_ppp_button.get_group();
193         velocity_pp_button.set_group (velocity_group);
194         velocity_p_button.set_group (velocity_group);
195         velocity_mp_button.set_group (velocity_group);
196         velocity_mf_button.set_group (velocity_group);
197         velocity_f_button.set_group (velocity_group);
198         velocity_ff_button.set_group (velocity_group);
199         velocity_fff_button.set_group (velocity_group);
200
201         w = manage (new Image (::get_icon (X_("pianississimo"))));
202         w->show();
203         velocity_ppp_button.add (*w);
204         w = manage (new Image (::get_icon (X_("pianissimo"))));
205         w->show();
206         velocity_pp_button.add (*w);
207         w = manage (new Image (::get_icon (X_("piano"))));
208         w->show();
209         velocity_p_button.add (*w);
210         w = manage (new Image (::get_icon (X_("mezzopiano"))));
211         w->show();
212         velocity_mp_button.add (*w);
213         w = manage (new Image (::get_icon (X_("mezzoforte"))));
214         w->show();
215         velocity_mf_button.add (*w);
216         w = manage (new Image (::get_icon (X_("forte"))));
217         w->show();
218         velocity_f_button.add (*w);
219         w = manage (new Image (::get_icon (X_("fortissimo"))));
220         w->show();
221         velocity_ff_button.add (*w);
222         w = manage (new Image (::get_icon (X_("fortississimo"))));
223         w->show();
224         velocity_fff_button.add (*w);
225
226         act = myactions.find_action ("StepEditing/note-velocity-ppp");
227         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ppp_button.gobj()), act->gobj());
228         act = myactions.find_action ("StepEditing/note-velocity-pp");
229         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_pp_button.gobj()), act->gobj());
230         act = myactions.find_action ("StepEditing/note-velocity-p");
231         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_p_button.gobj()), act->gobj());
232         act = myactions.find_action ("StepEditing/note-velocity-mp");
233         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mp_button.gobj()), act->gobj());
234         act = myactions.find_action ("StepEditing/note-velocity-mf");
235         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mf_button.gobj()), act->gobj());
236         act = myactions.find_action ("StepEditing/note-velocity-f");
237         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_f_button.gobj()), act->gobj());
238         act = myactions.find_action ("StepEditing/note-velocity-ff");
239         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ff_button.gobj()), act->gobj());
240         act = myactions.find_action ("StepEditing/note-velocity-fff");
241         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_fff_button.gobj()), act->gobj());
242
243         velocity_ppp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
244         velocity_ppp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ppp_button, 1), false);
245         velocity_pp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
246         velocity_pp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_pp_button, 16), false);
247         velocity_p_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
248         velocity_p_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_p_button, 32), false);
249         velocity_mp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
250         velocity_mp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mp_button, 64), false);
251         velocity_mf_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
252         velocity_mf_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mf_button, 80), false);
253         velocity_f_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
254         velocity_f_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_f_button, 96), false);
255         velocity_ff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
256         velocity_ff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ff_button, 112), false);
257         velocity_fff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
258         velocity_fff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_fff_button, 127), false);
259
260         velocity_ppp_button.property_draw_indicator() = false;
261         velocity_pp_button.property_draw_indicator() = false;
262         velocity_p_button.property_draw_indicator() = false;
263         velocity_mp_button.property_draw_indicator() = false;
264         velocity_mf_button.property_draw_indicator() = false;
265         velocity_f_button.property_draw_indicator() = false;
266         velocity_ff_button.property_draw_indicator() = false;
267         velocity_fff_button.property_draw_indicator() = false;
268
269         ARDOUR_UI::instance()->set_tip (&velocity_ppp_button, _("Set volume (velocity) to pianississimo"), "");
270         ARDOUR_UI::instance()->set_tip (&velocity_pp_button, _("Set volume (velocity) to pianissimo"), "");
271         ARDOUR_UI::instance()->set_tip (&velocity_p_button, _("Set volume (velocity) to piano"), "");
272         ARDOUR_UI::instance()->set_tip (&velocity_mp_button, _("Set volume (velocity) to mezzo-piano"), "");
273         ARDOUR_UI::instance()->set_tip (&velocity_mf_button, _("Set volume (velocity) to mezzo-forte"), "");
274         ARDOUR_UI::instance()->set_tip (&velocity_f_button, _("Set volume (velocity) to forte"), "");
275         ARDOUR_UI::instance()->set_tip (&velocity_ff_button, _("Set volume (velocity) to forteissimo"), "");
276         ARDOUR_UI::instance()->set_tip (&velocity_fff_button, _("Set volume (velocity) to forteississimo"), "");
277
278         note_velocity_box.pack_start (velocity_ppp_button, false, false);
279         note_velocity_box.pack_start (velocity_pp_button, false, false);
280         note_velocity_box.pack_start (velocity_p_button, false, false);
281         note_velocity_box.pack_start (velocity_mp_button, false, false);
282         note_velocity_box.pack_start (velocity_mf_button, false, false);
283         note_velocity_box.pack_start (velocity_f_button, false, false);
284         note_velocity_box.pack_start (velocity_ff_button, false, false);
285         note_velocity_box.pack_start (velocity_fff_button, false, false);
286
287         Label* l = manage (new Label);
288         l->set_markup ("<b><big>.</big></b>");
289         l->show ();
290         dot_button.add (*l);
291
292         w = manage (new Image (::get_icon (X_("chord"))));
293         w->show();
294         chord_button.add (*w);
295
296         rest_box.pack_start (rest_button, true, false);
297         rest_box.pack_start (grid_rest_button, true, false);
298
299         resync_box.pack_start (beat_resync_button, true, false);
300         resync_box.pack_start (bar_resync_button, true, false);
301
302         ARDOUR_UI::instance()->set_tip (&chord_button, _("Stack inserted notes to form a chord"), "");
303         ARDOUR_UI::instance()->set_tip (&sustain_button, _("Extend selected notes by note length"), "");
304         ARDOUR_UI::instance()->set_tip (&dot_button, _("Use dotted note lengths"), "");
305         ARDOUR_UI::instance()->set_tip (&rest_button, _("Insert a note-length's rest"), "");
306         ARDOUR_UI::instance()->set_tip (&grid_rest_button, _("Insert a grid-unit's rest"), "");
307         ARDOUR_UI::instance()->set_tip (&beat_resync_button, _("Insert a rest until the next beat"), "");
308         ARDOUR_UI::instance()->set_tip (&bar_resync_button, _("Insert a rest until the next bar"), "");
309         ARDOUR_UI::instance()->set_tip (&bank_button, _("Insert a bank change message"), "");
310         ARDOUR_UI::instance()->set_tip (&program_button, _("Insert a program change message"), "");
311
312         act = myactions.find_action ("StepEditing/toggle-triplet");
313         gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (triplet_button.gobj()), false);
314         gtk_activatable_set_related_action (GTK_ACTIVATABLE (triplet_button.gobj()), act->gobj());
315         act = myactions.find_action ("StepEditing/toggle-dotted");
316         gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot_button.gobj()), false);
317         gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot_button.gobj()), act->gobj());
318         act = myactions.find_action ("StepEditing/toggle-chord");
319         gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (chord_button.gobj()), false);
320         gtk_activatable_set_related_action (GTK_ACTIVATABLE (chord_button.gobj()), act->gobj());
321         act = myactions.find_action ("StepEditing/insert-rest");
322         gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (rest_button.gobj()), false);
323         gtk_activatable_set_related_action (GTK_ACTIVATABLE (rest_button.gobj()), act->gobj());
324         act = myactions.find_action ("StepEditing/insert-snap-rest");
325         gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (grid_rest_button.gobj()), false);
326         gtk_activatable_set_related_action (GTK_ACTIVATABLE (grid_rest_button.gobj()), act->gobj());
327         act = myactions.find_action ("StepEditing/sustain");
328         gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (sustain_button.gobj()), false);
329         gtk_activatable_set_related_action (GTK_ACTIVATABLE (sustain_button.gobj()), act->gobj());
330                 
331         upper_box.set_spacing (6);
332         upper_box.pack_start (chord_button, false, false);
333         upper_box.pack_start (note_length_box, false, false, 12);
334         upper_box.pack_start (triplet_button, false, false);
335         upper_box.pack_start (dot_button, false, false);
336         upper_box.pack_start (sustain_button, false, false);
337         upper_box.pack_start (rest_box, false, false);
338         upper_box.pack_start (resync_box, false, false);
339         upper_box.pack_start (note_velocity_box, false, false, 12);
340
341         VBox* v;
342
343         v = manage (new VBox);
344         l = manage (new Label (_("Channel")));
345         v->set_spacing (6);
346         v->pack_start (*l, false, false);
347         v->pack_start (channel_spinner, false, false);
348         upper_box.pack_start (*v, false, false);
349
350         v = manage (new VBox);
351         l = manage (new Label (_("1/Note")));
352         v->set_spacing (6);
353         v->pack_start (*l, false, false);
354         v->pack_start (length_divisor_spinner, false, false);
355         upper_box.pack_start (*v, false, false);
356
357         v = manage (new VBox);
358         l = manage (new Label (_("Velocity")));
359         v->set_spacing (6);
360         v->pack_start (*l, false, false);
361         v->pack_start (velocity_spinner, false, false);
362         upper_box.pack_start (*v, false, false);
363
364         v = manage (new VBox);
365         l = manage (new Label (_("Octave")));
366         v->set_spacing (6);
367         v->pack_start (*l, false, false);
368         v->pack_start (octave_spinner, false, false);
369         upper_box.pack_start (*v, false, false);
370
371         v = manage (new VBox);
372         l = manage (new Label (_("Bank")));
373         v->set_spacing (6);
374         v->pack_start (*l, false, false);
375         v->pack_start (bank_spinner, false, false);
376         v->pack_start (bank_button, false, false);
377         upper_box.pack_start (*v, false, false);
378
379         v = manage (new VBox);
380         l = manage (new Label (_("Program")));
381         v->set_spacing (6);
382         v->pack_start (*l, false, false);
383         v->pack_start (program_spinner, false, false);
384         v->pack_start (program_button, false, false);
385         upper_box.pack_start (*v, false, false);
386
387         velocity_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::velocity_value_change));
388         length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_value_change));
389
390         _piano = (PianoKeyboard*) piano_keyboard_new ();
391         piano = wrap ((GtkWidget*) _piano);
392
393         piano->set_flags (Gtk::CAN_FOCUS);
394
395         g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
396         g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
397         
398         program_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::program_click));
399         bank_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bank_click));
400         beat_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::beat_resync_click));
401         bar_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bar_resync_click));
402
403         length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_changed));
404
405         packer.set_spacing (6);
406         packer.pack_start (upper_box, false, false);
407         packer.pack_start (*piano, false, false);
408         packer.show_all ();
409
410         get_vbox()->add (packer);
411 }
412
413 StepEntry::~StepEntry()
414 {
415 }
416
417 void
418 StepEntry::length_changed ()
419 {
420         length_1_button.queue_draw ();
421         length_2_button.queue_draw ();
422         length_4_button.queue_draw ();
423         length_8_button.queue_draw ();
424         length_16_button.queue_draw ();
425         length_32_button.queue_draw ();
426         length_64_button.queue_draw ();
427 }
428
429 bool
430 StepEntry::on_key_press_event (GdkEventKey* ev)
431 {
432         /* focus widget gets first shot, then bindings, otherwise
433            forward to main window
434         */
435         
436         if (!gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
437                 KeyboardKey k (ev->state, ev->keyval);
438
439                 if (bindings.activate (k, KeyboardKey::Press)) {
440                         return true;
441                 }
442         }
443
444         return forward_key_press (ev);
445 }
446
447 bool
448 StepEntry::on_key_release_event (GdkEventKey* ev)
449 {
450         if (!gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
451                 KeyboardKey k (ev->state, ev->keyval);
452
453                 if (bindings.activate (k, KeyboardKey::Release)) {
454                         return true;
455                 }
456         }
457         
458         /* don't forward releases */
459
460         return true;
461 }
462
463 void
464 StepEntry::rest_event_handler ()
465 {
466         _mtv->step_edit_rest (0.0);
467 }
468
469 Evoral::MusicalTime
470 StepEntry::note_length ()
471 {
472         Evoral::MusicalTime base_time = 1.0 / (Evoral::MusicalTime) length_divisor_adjustment.get_value();
473         
474         RefPtr<Action> act = myactions.find_action ("StepEditing/toggle-triplet");
475         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
476         bool triplets = tact->get_active ();
477
478         act = myactions.find_action ("StepEditing/toggle-dotted");
479         tact = RefPtr<ToggleAction>::cast_dynamic (act);
480         bool dotted = tact->get_active ();
481
482         if (triplets) {
483                 base_time *= (2.0/3.0);
484         }
485
486         if (dotted) {
487                 base_time *= 1.5; // add support for multiple dots sometime
488         }
489
490         return base_time;
491 }
492
493 uint8_t
494 StepEntry::note_velocity () const
495 {
496         return (Evoral::MusicalTime) velocity_adjustment.get_value();
497 }
498
499 uint8_t 
500 StepEntry::note_channel() const
501 {
502         return channel_adjustment.get_value() - 1;
503 }
504
505 void
506 StepEntry::note_off_event_handler (int note)
507 {
508         insert_note (note);
509 }
510
511
512 void
513 StepEntry::on_show ()
514 {
515         ArdourDialog::on_show ();
516         //piano->grab_focus ();
517 }
518
519 void
520 StepEntry::beat_resync_click ()
521 {
522         _mtv->step_edit_beat_sync ();
523 }
524
525 void
526 StepEntry::bar_resync_click ()
527 {
528         _mtv->step_edit_bar_sync ();
529 }
530
531 void
532 StepEntry::register_actions ()
533 {
534         /* add named actions for the editor */
535
536         myactions.register_action ("StepEditing", "insert-a", _("Insert Note A"), sigc::mem_fun (*this, &StepEntry::insert_a));
537         myactions.register_action ("StepEditing", "insert-asharp", _("Insert Note A-sharp"), sigc::mem_fun (*this, &StepEntry::insert_asharp));
538         myactions.register_action ("StepEditing", "insert-b", _("Insert Note B"), sigc::mem_fun (*this, &StepEntry::insert_b));
539         myactions.register_action ("StepEditing", "insert-c", _("Insert Note C"), sigc::mem_fun (*this, &StepEntry::insert_c));
540         myactions.register_action ("StepEditing", "insert-csharp", _("Insert Note C-sharp"), sigc::mem_fun (*this, &StepEntry::insert_csharp));
541         myactions.register_action ("StepEditing", "insert-d", _("Insert Note D"), sigc::mem_fun (*this, &StepEntry::insert_d));
542         myactions.register_action ("StepEditing", "insert-dsharp", _("Insert Note D-sharp"), sigc::mem_fun (*this, &StepEntry::insert_dsharp));
543         myactions.register_action ("StepEditing", "insert-e", _("Insert Note E"), sigc::mem_fun (*this, &StepEntry::insert_e));
544         myactions.register_action ("StepEditing", "insert-f", _("Insert Note F"), sigc::mem_fun (*this, &StepEntry::insert_f));
545         myactions.register_action ("StepEditing", "insert-fsharp", _("Insert Note F-sharp"), sigc::mem_fun (*this, &StepEntry::insert_fsharp));
546         myactions.register_action ("StepEditing", "insert-g", _("Insert Note G"), sigc::mem_fun (*this, &StepEntry::insert_g));
547         myactions.register_action ("StepEditing", "insert-gsharp", _("Insert Note G-sharp"), sigc::mem_fun (*this, &StepEntry::insert_gsharp));
548
549         myactions.register_action ("StepEditing", "insert-rest", _("Insert a Note-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_rest));
550         myactions.register_action ("StepEditing", "insert-snap-rest", _("Insert a Snap-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_grid_rest));
551
552         myactions.register_action ("StepEditing", "next-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::next_octave));
553         myactions.register_action ("StepEditing", "prev-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::prev_octave));
554
555         myactions.register_action ("StepEditing", "next-note-length", _("Move to Next Note Length"), sigc::mem_fun (*this, &StepEntry::next_note_length));
556         myactions.register_action ("StepEditing", "prev-note-length", _("Move to Previous Note Length"), sigc::mem_fun (*this, &StepEntry::prev_note_length));
557
558         myactions.register_action ("StepEditing", "inc-note-length", _("Increase Note Length"), sigc::mem_fun (*this, &StepEntry::inc_note_length));
559         myactions.register_action ("StepEditing", "dec-note-length", _("Decrease Note Length"), sigc::mem_fun (*this, &StepEntry::dec_note_length));
560
561         myactions.register_action ("StepEditing", "next-note-velocity", _("Move to Next Note Velocity"), sigc::mem_fun (*this, &StepEntry::next_note_velocity));
562         myactions.register_action ("StepEditing", "prev-note-velocity", _("Move to Previous Note Velocity"), sigc::mem_fun (*this, &StepEntry::prev_note_velocity));
563
564         myactions.register_action ("StepEditing", "inc-note-velocity", _("Increase Note Velocity"), sigc::mem_fun (*this, &StepEntry::inc_note_velocity));
565         myactions.register_action ("StepEditing", "dec-note-velocity", _("Decrease Note Velocity"), sigc::mem_fun (*this, &StepEntry::dec_note_velocity));
566
567         myactions.register_action ("StepEditing", "octave-0", _("Switch to the 1st octave"), sigc::mem_fun (*this, &StepEntry::octave_0));
568         myactions.register_action ("StepEditing", "octave-1", _("Switch to the 2nd octave"), sigc::mem_fun (*this, &StepEntry::octave_1));
569         myactions.register_action ("StepEditing", "octave-2", _("Switch to the 3rd octave"), sigc::mem_fun (*this, &StepEntry::octave_2));
570         myactions.register_action ("StepEditing", "octave-3", _("Switch to the 4th octave"), sigc::mem_fun (*this, &StepEntry::octave_3));
571         myactions.register_action ("StepEditing", "octave-4", _("Switch to the 5th octave"), sigc::mem_fun (*this, &StepEntry::octave_4));
572         myactions.register_action ("StepEditing", "octave-5", _("Switch to the 6th octave"), sigc::mem_fun (*this, &StepEntry::octave_5));
573         myactions.register_action ("StepEditing", "octave-6", _("Switch to the 7th octave"), sigc::mem_fun (*this, &StepEntry::octave_6));
574         myactions.register_action ("StepEditing", "octave-7", _("Switch to the 8th octave"), sigc::mem_fun (*this, &StepEntry::octave_7));
575         myactions.register_action ("StepEditing", "octave-8", _("Switch to the 9th octave"), sigc::mem_fun (*this, &StepEntry::octave_8));
576         myactions.register_action ("StepEditing", "octave-9", _("Switch to the 10th octave"), sigc::mem_fun (*this, &StepEntry::octave_9));
577         myactions.register_action ("StepEditing", "octave-10", _("Switch to the 11th octave"), sigc::mem_fun (*this, &StepEntry::octave_10));
578
579
580         RadioAction::Group note_length_group;
581
582         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-whole", 
583                                          _("Set Note Length to Whole"), sigc::mem_fun (*this, &StepEntry::note_length_change), 1);
584         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-half", 
585                                          _("Set Note Length to 1/2"), sigc::mem_fun (*this, &StepEntry::note_length_change), 2);
586         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-quarter",
587                                          _("Set Note Length to 1/4"), sigc::mem_fun (*this, &StepEntry::note_length_change), 4);
588         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-eighth",
589                                          _("Set Note Length to 1/8"), sigc::mem_fun (*this, &StepEntry::note_length_change), 8);
590         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-sixteenth",
591                                          _("Set Note Length to 1/16"), sigc::mem_fun (*this, &StepEntry::note_length_change), 16);
592         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-thirtysecond",
593                                          _("Set Note Length to 1/32"), sigc::mem_fun (*this, &StepEntry::note_length_change), 32);
594         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-sixtyfourth",
595                                          _("Set Note Length to 1/64"), sigc::mem_fun (*this, &StepEntry::note_length_change), 64);
596
597         RadioAction::Group note_velocity_group;
598
599         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-ppp",
600                                          _("Set Note Velocity to Pianississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 1);
601         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-pp",
602                                          _("Set Note Velocity to Pianissimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 16);
603         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-p",
604                                          _("Set Note Velocity to Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 32);
605         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-mp",
606                                          _("Set Note Velocity to Mezzo-Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 64);
607         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-mf",
608                                          _("Set Note Velocity to Mezzo-Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 80);
609         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-f",
610                                          _("Set Note Velocity to Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 96);
611         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-ff",
612                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 112);
613         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-fff",
614                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 127);
615
616         myactions.register_toggle_action ("StepEditing", "toggle-triplet", _("Toggle Triple Notes"),
617                                           sigc::mem_fun (*this, &StepEntry::toggle_dotted));
618         myactions.register_toggle_action ("StepEditing", "toggle-dotted", _("Toggled Dotted Notes"), 
619                                           sigc::mem_fun (*this, &StepEntry::toggle_triplet));
620         myactions.register_toggle_action ("StepEditing", "toggle-chord", _("Toggle Chord Entry"),
621                                           sigc::mem_fun (*this, &StepEntry::toggle_chord));
622         myactions.register_action ("StepEditing", "sustain", _("Sustain Selected Notes by Note Length"),
623                                    sigc::mem_fun (*this, &StepEntry::do_sustain));
624 }
625
626 void
627 StepEntry::load_bindings ()
628 {
629         /* XXX move this to a better place */
630         KeyboardKey::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
631
632         bindings.set_action_map (myactions);
633
634         sys::path binding_file;
635         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
636
637         if (find_file_in_search_path (spath, "step_editing.bindings", binding_file)) {
638                 bindings.load (binding_file.to_string());
639         }
640 }
641
642 void
643 StepEntry::toggle_triplet ()
644 {
645         // nowt to be done
646 }
647
648 void
649 StepEntry::toggle_chord ()
650 {
651         _mtv->step_edit_toggle_chord ();
652 }
653
654 void
655 StepEntry::toggle_dotted ()
656 {
657         // nowt to be done
658 }
659
660 void
661 StepEntry::program_click ()
662 {
663         _mtv->step_add_program_change (note_channel(), (int8_t) floor (program_adjustment.get_value()));
664 }
665
666 void
667 StepEntry::bank_click ()
668 {
669         _mtv->step_add_bank_change (note_channel(), (int8_t) floor (bank_adjustment.get_value()));
670 }
671
672 void
673 StepEntry::insert_rest ()
674 {
675         _mtv->step_edit_rest (note_length());
676 }
677
678 void
679 StepEntry::insert_grid_rest ()
680 {
681         _mtv->step_edit_rest (0.0);
682 }
683
684 void
685 StepEntry::insert_note (uint8_t note)
686 {
687         _mtv->step_add_note (note_channel(), note, note_velocity(), note_length());
688 }
689 void
690 StepEntry::insert_c ()
691 {
692         insert_note (0 + (current_octave() * 12));
693 }
694 void
695 StepEntry::insert_csharp ()
696 {
697         insert_note (1 + (current_octave() * 12));
698 }
699 void
700 StepEntry::insert_d ()
701 {
702         insert_note (2 + (current_octave() * 12));
703 }
704 void
705 StepEntry::insert_dsharp ()
706 {
707         insert_note (3 + (current_octave() * 12));
708 }
709 void
710 StepEntry::insert_e ()
711 {
712         insert_note (4 + (current_octave() * 12));
713 }
714 void
715 StepEntry::insert_f ()
716 {
717         insert_note (5 + (current_octave() * 12));
718 }
719 void
720 StepEntry::insert_fsharp ()
721 {
722         insert_note (6 + (current_octave() * 12));
723 }
724 void
725 StepEntry::insert_g ()
726 {
727         insert_note (7 + (current_octave() * 12));
728 }
729 void
730 StepEntry::insert_gsharp ()
731 {
732         insert_note (8 + (current_octave() * 12));
733 }
734
735 void
736 StepEntry::insert_a ()
737 {
738         insert_note (9 + (current_octave() * 12));
739 }
740
741 void
742 StepEntry::insert_asharp ()
743 {
744         insert_note (10 + (current_octave() * 12));
745 }
746 void
747 StepEntry::insert_b ()
748 {
749         insert_note (11 + (current_octave() * 12));
750 }
751
752 void
753 StepEntry::note_length_change (GtkAction* act)
754 {
755         /* it doesn't matter which note length action we look up - we are interested
756            in the current_value which is global across the whole group of note length
757            actions. this method is called twice for every user operation,
758            once for the action that became "inactive" and once for the action that
759            becaome "active". so ... only bother to actually change the value when this
760            is called for the "active" action.
761         */
762         
763         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
764                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
765                 length_divisor_adjustment.set_value (v);
766         }
767 }
768
769 void
770 StepEntry::note_velocity_change (GtkAction* act)
771 {
772         /* it doesn't matter which note length action we look up - we are interested
773            in the current_value which is global across the whole group of note length
774            actions. this method is called twice for every user operation,
775            once for the action that became "inactive" and once for the action that
776            becaome "active". so ... only bother to actually change the value when this
777            is called for the "active" action.
778         */
779         
780         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
781                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
782                 velocity_adjustment.set_value (v);
783         }
784 }
785
786 void
787 StepEntry::velocity_value_change ()
788 {
789         RefPtr<Action> act;
790         RefPtr<RadioAction> ract;
791         double val = velocity_adjustment.get_value();
792         bool inconsistent = true;
793         vector<const char*> velocity_actions;
794
795         velocity_actions.push_back ("StepEditing/note-velocity-ppp");
796         velocity_actions.push_back ("StepEditing/note-velocity-pp");
797         velocity_actions.push_back ("StepEditing/note-velocity-p");
798         velocity_actions.push_back ("StepEditing/note-velocity-mp");
799         velocity_actions.push_back ("StepEditing/note-velocity-mf");
800         velocity_actions.push_back ("StepEditing/note-velocity-f");
801         velocity_actions.push_back ("StepEditing/note-velocity-ff");
802         velocity_actions.push_back ("StepEditing/note-velocity-fff");
803
804         for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
805
806                 act = myactions.find_action (*i);
807                 
808                 if (act) {
809                         ract = RefPtr<RadioAction>::cast_dynamic (act);
810
811                         if (ract) { 
812                                 if (ract->property_value() == val) {
813                                         ract->set_active (true);
814                                         inconsistent = false;
815                                         break;
816                                 }
817                         }
818                 }
819         }
820
821         velocity_ppp_button.set_inconsistent (inconsistent);
822         velocity_pp_button.set_inconsistent (inconsistent);
823         velocity_p_button.set_inconsistent (inconsistent);
824         velocity_mp_button.set_inconsistent (inconsistent);
825         velocity_mf_button.set_inconsistent (inconsistent);
826         velocity_f_button.set_inconsistent (inconsistent);
827         velocity_ff_button.set_inconsistent (inconsistent);
828         velocity_fff_button.set_inconsistent (inconsistent);
829 }
830
831 void
832 StepEntry::length_value_change ()
833 {
834         RefPtr<Action> act;
835         RefPtr<RadioAction> ract;
836         double val = length_divisor_adjustment.get_value();
837         bool inconsistent = true;
838         vector<const char*> length_actions;
839
840         length_actions.push_back ("StepEditing/note-length-whole");
841         length_actions.push_back ("StepEditing/note-length-half");
842         length_actions.push_back ("StepEditing/note-length-quarter");
843         length_actions.push_back ("StepEditing/note-length-eighth");
844         length_actions.push_back ("StepEditing/note-length-sixteenth");
845         length_actions.push_back ("StepEditing/note-length-thirtysecond");
846         length_actions.push_back ("StepEditing/note-length-sixtyfourth");
847
848         for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
849
850                 act = myactions.find_action (*i);
851                 
852                 if (act) {
853                         ract = RefPtr<RadioAction>::cast_dynamic (act);
854
855                         if (ract) { 
856                                 if (ract->property_value() == val) {
857                                         ract->set_active (true);
858                                         inconsistent = false;
859                                         break;
860                                 }
861                         }
862                 }
863         }
864
865         length_1_button.set_inconsistent (inconsistent);
866         length_2_button.set_inconsistent (inconsistent);
867         length_4_button.set_inconsistent (inconsistent);
868         length_8_button.set_inconsistent (inconsistent);
869         length_16_button.set_inconsistent (inconsistent);
870         length_32_button.set_inconsistent (inconsistent);
871         length_64_button.set_inconsistent (inconsistent);
872
873         _mtv->set_step_edit_cursor_width (note_length());
874 }
875
876 bool
877 StepEntry::radio_button_press (GdkEventButton* ev)
878 {
879         if (ev->button == 1) {
880                 return true;
881         } 
882
883         return false;
884 }
885
886 bool
887 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
888 {
889         if (ev->button == 1) {
890                 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
891                 
892                 if (act) {
893                         gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
894                 }
895                 
896                 return true;
897         } 
898
899         return false;
900 }
901
902 void
903 StepEntry::next_octave ()
904 {
905         octave_adjustment.set_value (octave_adjustment.get_value() + 1.0);
906 }
907
908 void
909 StepEntry::prev_octave ()
910 {
911         octave_adjustment.set_value (octave_adjustment.get_value() - 1.0);
912 }
913
914 void
915 StepEntry::inc_note_length ()
916 {
917         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() - 1.0);
918 }
919
920 void
921 StepEntry::dec_note_length ()
922 {
923         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() + 1.0);
924 }
925
926 void
927 StepEntry::prev_note_length ()
928 {
929         double l = length_divisor_adjustment.get_value();
930         int il = (int) lrintf (l); // round to nearest integer
931         il = (il/2) * 2; // round to power of 2
932
933         if (il == 0) {
934                 il = 1;
935         }
936
937         il *= 2; // double
938
939         length_divisor_adjustment.set_value (il);
940 }
941
942 void
943 StepEntry::next_note_length ()
944 {
945         double l = length_divisor_adjustment.get_value();
946         int il = (int) lrintf (l); // round to nearest integer
947         il = (il/2) * 2; // round to power of 2
948
949         if (il == 0) {
950                 il = 1;
951         }
952
953         il /= 2; // half
954
955         if (il > 0) {
956                 length_divisor_adjustment.set_value (il);
957         }
958 }
959
960 void
961 StepEntry::inc_note_velocity ()
962 {
963         velocity_adjustment.set_value (velocity_adjustment.get_value() + 1.0);
964 }
965
966 void
967 StepEntry::dec_note_velocity ()
968 {
969         velocity_adjustment.set_value (velocity_adjustment.get_value() - 1.0);
970 }
971
972 void
973 StepEntry::next_note_velocity ()
974 {
975         double l = velocity_adjustment.get_value ();
976
977         if (l < 16) {
978                 l = 16;
979         } else if (l < 32) {
980                 l = 32;
981         } else if (l < 48) {
982                 l = 48;
983         } else if (l < 64) {
984                 l = 64;
985         } else if (l < 80) {
986                 l = 80;
987         } else if (l < 96) {
988                 l = 96;
989         } else if (l < 112) {
990                 l = 112;
991         } else if (l < 127) {
992                 l = 127;
993         }
994         
995         velocity_adjustment.set_value (l);
996 }
997
998 void
999 StepEntry::prev_note_velocity ()
1000 {
1001         double l = velocity_adjustment.get_value ();
1002
1003         if (l > 112) {
1004                 l = 112;
1005         } else if (l > 96) {
1006                 l = 96;
1007         } else if (l > 80) {
1008                 l = 80;
1009         } else if (l > 64) {
1010                 l = 64;
1011         } else if (l > 48) {
1012                 l = 48;
1013         } else if (l > 32) {
1014                 l = 32;
1015         } else if (l > 16) {
1016                 l = 16;
1017         } else {
1018                 l = 1;
1019         }
1020         
1021         velocity_adjustment.set_value (l);
1022 }
1023
1024 void
1025 StepEntry::octave_n (int n)
1026 {
1027         octave_adjustment.set_value (n);
1028 }
1029
1030 void
1031 StepEntry::do_sustain ()
1032 {
1033         _mtv->step_edit_sustain (note_length());
1034 }