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