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