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