enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[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 "pbd/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                 return true;
501         }
502
503         return relay_key_press (ev, this);
504 }
505
506 bool
507 StepEntry::on_key_release_event (GdkEventKey* ev)
508 {
509         if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
510                 return true;
511         }
512
513         /* don't forward releases */
514
515         return true;
516 }
517
518 void
519 StepEntry::rest_event_handler ()
520 {
521         se->step_edit_rest (Evoral::Beats());
522 }
523
524 Evoral::Beats
525 StepEntry::note_length ()
526 {
527         double base_time = 4.0 / (double) length_divisor_adjustment.get_value();
528
529         RefPtr<Action> act = myactions.find_action ("StepEditing/toggle-triplet");
530         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
531         bool triplets = tact->get_active ();
532
533         if (triplets) {
534                 base_time *= (2.0/3.0);
535         }
536
537         double dots = dot_adjustment.get_value ();
538
539         if (dots > 0) {
540                 dots = pow (2.0, dots);
541                 base_time *= 1 + ((dots - 1.0)/dots);
542         }
543
544         return Evoral::Beats(base_time);
545 }
546
547 uint8_t
548 StepEntry::note_velocity () const
549 {
550         return velocity_adjustment.get_value();
551 }
552
553 uint8_t
554 StepEntry::note_channel() const
555 {
556         return channel_adjustment.get_value() - 1;
557 }
558
559 void
560 StepEntry::note_off_event_handler (int note)
561 {
562         insert_note (note);
563 }
564
565
566 void
567 StepEntry::on_show ()
568 {
569         ArdourWindow::on_show ();
570         //piano->grab_focus ();
571 }
572
573 void
574 StepEntry::beat_resync_click ()
575 {
576         se->step_edit_beat_sync ();
577 }
578
579 void
580 StepEntry::bar_resync_click ()
581 {
582         se->step_edit_bar_sync ();
583 }
584
585 void
586 StepEntry::register_actions ()
587 {
588         /* add named actions for the step editor */
589
590         Glib::RefPtr<ActionGroup> group = myactions.create_action_group (X_("StepEditing"));
591
592         myactions.register_action (group, "insert-a", _("Insert Note A"), sigc::mem_fun (*this, &StepEntry::insert_a));
593         myactions.register_action (group, "insert-asharp", _("Insert Note A-sharp"), sigc::mem_fun (*this, &StepEntry::insert_asharp));
594         myactions.register_action (group, "insert-b", _("Insert Note B"), sigc::mem_fun (*this, &StepEntry::insert_b));
595         myactions.register_action (group, "insert-c", _("Insert Note C"), sigc::mem_fun (*this, &StepEntry::insert_c));
596         myactions.register_action (group, "insert-csharp", _("Insert Note C-sharp"), sigc::mem_fun (*this, &StepEntry::insert_csharp));
597         myactions.register_action (group, "insert-d", _("Insert Note D"), sigc::mem_fun (*this, &StepEntry::insert_d));
598         myactions.register_action (group, "insert-dsharp", _("Insert Note D-sharp"), sigc::mem_fun (*this, &StepEntry::insert_dsharp));
599         myactions.register_action (group, "insert-e", _("Insert Note E"), sigc::mem_fun (*this, &StepEntry::insert_e));
600         myactions.register_action (group, "insert-f", _("Insert Note F"), sigc::mem_fun (*this, &StepEntry::insert_f));
601         myactions.register_action (group, "insert-fsharp", _("Insert Note F-sharp"), sigc::mem_fun (*this, &StepEntry::insert_fsharp));
602         myactions.register_action (group, "insert-g", _("Insert Note G"), sigc::mem_fun (*this, &StepEntry::insert_g));
603         myactions.register_action (group, "insert-gsharp", _("Insert Note G-sharp"), sigc::mem_fun (*this, &StepEntry::insert_gsharp));
604
605         myactions.register_action (group, "insert-rest", _("Insert a Note-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_rest));
606         myactions.register_action (group, "insert-snap-rest", _("Insert a Snap-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_grid_rest));
607
608         myactions.register_action (group, "next-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::next_octave));
609         myactions.register_action (group, "prev-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::prev_octave));
610
611         myactions.register_action (group, "next-note-length", _("Move to Next Note Length"), sigc::mem_fun (*this, &StepEntry::next_note_length));
612         myactions.register_action (group, "prev-note-length", _("Move to Previous Note Length"), sigc::mem_fun (*this, &StepEntry::prev_note_length));
613
614         myactions.register_action (group, "inc-note-length", _("Increase Note Length"), sigc::mem_fun (*this, &StepEntry::inc_note_length));
615         myactions.register_action (group, "dec-note-length", _("Decrease Note Length"), sigc::mem_fun (*this, &StepEntry::dec_note_length));
616
617         myactions.register_action (group, "next-note-velocity", _("Move to Next Note Velocity"), sigc::mem_fun (*this, &StepEntry::next_note_velocity));
618         myactions.register_action (group, "prev-note-velocity", _("Move to Previous Note Velocity"), sigc::mem_fun (*this, &StepEntry::prev_note_velocity));
619
620         myactions.register_action (group, "inc-note-velocity", _("Increase Note Velocity"), sigc::mem_fun (*this, &StepEntry::inc_note_velocity));
621         myactions.register_action (group, "dec-note-velocity", _("Decrease Note Velocity"), sigc::mem_fun (*this, &StepEntry::dec_note_velocity));
622
623         myactions.register_action (group, "octave-0", _("Switch to the 1st octave"), sigc::mem_fun (*this, &StepEntry::octave_0));
624         myactions.register_action (group, "octave-1", _("Switch to the 2nd octave"), sigc::mem_fun (*this, &StepEntry::octave_1));
625         myactions.register_action (group, "octave-2", _("Switch to the 3rd octave"), sigc::mem_fun (*this, &StepEntry::octave_2));
626         myactions.register_action (group, "octave-3", _("Switch to the 4th octave"), sigc::mem_fun (*this, &StepEntry::octave_3));
627         myactions.register_action (group, "octave-4", _("Switch to the 5th octave"), sigc::mem_fun (*this, &StepEntry::octave_4));
628         myactions.register_action (group, "octave-5", _("Switch to the 6th octave"), sigc::mem_fun (*this, &StepEntry::octave_5));
629         myactions.register_action (group, "octave-6", _("Switch to the 7th octave"), sigc::mem_fun (*this, &StepEntry::octave_6));
630         myactions.register_action (group, "octave-7", _("Switch to the 8th octave"), sigc::mem_fun (*this, &StepEntry::octave_7));
631         myactions.register_action (group, "octave-8", _("Switch to the 9th octave"), sigc::mem_fun (*this, &StepEntry::octave_8));
632         myactions.register_action (group, "octave-9", _("Switch to the 10th octave"), sigc::mem_fun (*this, &StepEntry::octave_9));
633         myactions.register_action (group, "octave-10", _("Switch to the 11th octave"), sigc::mem_fun (*this, &StepEntry::octave_10));
634
635         myactions.register_toggle_action (group, "toggle-triplet", _("Toggle Triple Notes"),
636                                           sigc::mem_fun (*this, &StepEntry::toggle_triplet));
637
638         myactions.register_toggle_action (group, "toggle-chord", _("Toggle Chord Entry"),
639                                           sigc::mem_fun (*this, &StepEntry::toggle_chord));
640         myactions.register_action (group, "sustain", _("Sustain Selected Notes by Note Length"),
641                                    sigc::mem_fun (*this, &StepEntry::do_sustain));
642
643         myactions.register_action (group, "sync-to-edit-point", _("Move Insert Position to Edit Point"),
644                                    sigc::mem_fun (*this, &StepEntry::sync_to_edit_point));
645         myactions.register_action (group, "back", _("Move Insert Position Back by Note Length"),
646                                    sigc::mem_fun (*this, &StepEntry::back));
647         RadioAction::Group note_length_group;
648
649         myactions.register_radio_action (group, note_length_group, "note-length-whole",
650                                          _("Set Note Length to Whole"), sigc::mem_fun (*this, &StepEntry::note_length_change), 1);
651         myactions.register_radio_action (group, note_length_group, "note-length-half",
652                                          _("Set Note Length to 1/2"), sigc::mem_fun (*this, &StepEntry::note_length_change), 2);
653         myactions.register_radio_action (group, note_length_group, "note-length-third",
654                                          _("Set Note Length to 1/3"), sigc::mem_fun (*this, &StepEntry::note_length_change), 3);
655         myactions.register_radio_action (group, note_length_group, "note-length-quarter",
656                                          _("Set Note Length to 1/4"), sigc::mem_fun (*this, &StepEntry::note_length_change), 4);
657         myactions.register_radio_action (group, note_length_group, "note-length-eighth",
658                                          _("Set Note Length to 1/8"), sigc::mem_fun (*this, &StepEntry::note_length_change), 8);
659         myactions.register_radio_action (group, note_length_group, "note-length-sixteenth",
660                                          _("Set Note Length to 1/16"), sigc::mem_fun (*this, &StepEntry::note_length_change), 16);
661         myactions.register_radio_action (group, note_length_group, "note-length-thirtysecond",
662                                          _("Set Note Length to 1/32"), sigc::mem_fun (*this, &StepEntry::note_length_change), 32);
663         myactions.register_radio_action (group, note_length_group, "note-length-sixtyfourth",
664                                          _("Set Note Length to 1/64"), sigc::mem_fun (*this, &StepEntry::note_length_change), 64);
665
666         RadioAction::Group note_velocity_group;
667
668         myactions.register_radio_action (group, note_velocity_group, "note-velocity-ppp",
669                                          _("Set Note Velocity to Pianississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 1);
670         myactions.register_radio_action (group, note_velocity_group, "note-velocity-pp",
671                                          _("Set Note Velocity to Pianissimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 16);
672         myactions.register_radio_action (group, note_velocity_group, "note-velocity-p",
673                                          _("Set Note Velocity to Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 32);
674         myactions.register_radio_action (group, note_velocity_group, "note-velocity-mp",
675                                          _("Set Note Velocity to Mezzo-Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 64);
676         myactions.register_radio_action (group, note_velocity_group, "note-velocity-mf",
677                                          _("Set Note Velocity to Mezzo-Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 80);
678         myactions.register_radio_action (group, note_velocity_group, "note-velocity-f",
679                                          _("Set Note Velocity to Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 96);
680         myactions.register_radio_action (group, note_velocity_group, "note-velocity-ff",
681                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 112);
682         myactions.register_radio_action (group, note_velocity_group, "note-velocity-fff",
683                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 127);
684
685
686         RadioAction::Group dot_group;
687
688         myactions.register_radio_action (group, dot_group, "no-dotted", _("No Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 0);
689         myactions.register_radio_action (group, dot_group, "toggle-dotted", _("Toggled Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 1);
690         myactions.register_radio_action (group, dot_group, "toggle-double-dotted", _("Toggled Double-Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 2);
691         myactions.register_radio_action (group, dot_group, "toggle-triple-dotted", _("Toggled Triple-Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 3);
692 }
693
694 void
695 StepEntry::load_bindings ()
696 {
697         bindings = Bindings::get_bindings (X_("Step Editing"), myactions);
698         set_data ("ardour-bindings", bindings);
699 }
700
701 void
702 StepEntry::toggle_triplet ()
703 {
704         se->set_step_edit_cursor_width (note_length());
705 }
706
707 void
708 StepEntry::toggle_chord ()
709 {
710         se->step_edit_toggle_chord ();
711 }
712
713 void
714 StepEntry::dot_change (GtkAction* act)
715 {
716         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
717                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
718                 dot_adjustment.set_value (v);
719         }
720 }
721
722 void
723 StepEntry::dot_value_change ()
724 {
725         RefPtr<Action> act;
726         RefPtr<RadioAction> ract;
727         double val = dot_adjustment.get_value();
728         bool inconsistent = true;
729         vector<const char*> dot_actions;
730
731         dot_actions.push_back ("StepEditing/no-dotted");
732         dot_actions.push_back ("StepEditing/toggle-dotted");
733         dot_actions.push_back ("StepEditing/toggle-double-dotted");
734         dot_actions.push_back ("StepEditing/toggle-triple-dotted");
735
736         for (vector<const char*>::iterator i = dot_actions.begin(); i != dot_actions.end(); ++i) {
737
738                 act = myactions.find_action (*i);
739
740                 if (act) {
741                         ract = RefPtr<RadioAction>::cast_dynamic (act);
742
743                         if (ract) {
744                                 if (ract->property_value() == val) {
745                                         ract->set_active (true);
746                                         inconsistent = false;
747                                         break;
748                                 }
749                         }
750                 }
751         }
752
753         dot1_button.set_inconsistent (inconsistent);
754         dot2_button.set_inconsistent (inconsistent);
755         dot3_button.set_inconsistent (inconsistent);
756
757         se->set_step_edit_cursor_width (note_length());
758 }
759
760 void
761 StepEntry::program_click ()
762 {
763         se->step_add_program_change (note_channel(), (int8_t) floor (program_adjustment.get_value()));
764 }
765
766 void
767 StepEntry::bank_click ()
768 {
769         se->step_add_bank_change (note_channel(), (int8_t) floor (bank_adjustment.get_value()));
770 }
771
772 void
773 StepEntry::insert_rest ()
774 {
775         se->step_edit_rest (note_length());
776 }
777
778 void
779 StepEntry::insert_grid_rest ()
780 {
781         se->step_edit_rest (Evoral::Beats());
782 }
783
784 void
785 StepEntry::insert_note (uint8_t note)
786 {
787         if (note > 127) {
788                 return;
789         }
790
791         se->step_add_note (note_channel(), note, note_velocity(), note_length());
792 }
793 void
794 StepEntry::insert_c ()
795 {
796         insert_note (0 + (current_octave() * 12));
797 }
798 void
799 StepEntry::insert_csharp ()
800 {
801         insert_note (1 + (current_octave() * 12));
802 }
803 void
804 StepEntry::insert_d ()
805 {
806         insert_note (2 + (current_octave() * 12));
807 }
808 void
809 StepEntry::insert_dsharp ()
810 {
811         insert_note (3 + (current_octave() * 12));
812 }
813 void
814 StepEntry::insert_e ()
815 {
816         insert_note (4 + (current_octave() * 12));
817 }
818 void
819 StepEntry::insert_f ()
820 {
821         insert_note (5 + (current_octave() * 12));
822 }
823 void
824 StepEntry::insert_fsharp ()
825 {
826         insert_note (6 + (current_octave() * 12));
827 }
828 void
829 StepEntry::insert_g ()
830 {
831         insert_note (7 + (current_octave() * 12));
832 }
833 void
834 StepEntry::insert_gsharp ()
835 {
836         insert_note (8 + (current_octave() * 12));
837 }
838
839 void
840 StepEntry::insert_a ()
841 {
842         insert_note (9 + (current_octave() * 12));
843 }
844
845 void
846 StepEntry::insert_asharp ()
847 {
848         insert_note (10 + (current_octave() * 12));
849 }
850 void
851 StepEntry::insert_b ()
852 {
853         insert_note (11 + (current_octave() * 12));
854 }
855
856 void
857 StepEntry::note_length_change (GtkAction* act)
858 {
859         /* it doesn't matter which note length action we look up - we are interested
860            in the current_value which is global across the whole group of note length
861            actions. this method is called twice for every user operation,
862            once for the action that became "inactive" and once for the action that
863            becaome "active". so ... only bother to actually change the value when this
864            is called for the "active" action.
865         */
866
867         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
868                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
869                 length_divisor_adjustment.set_value (v);
870         }
871 }
872
873 void
874 StepEntry::note_velocity_change (GtkAction* act)
875 {
876         /* it doesn't matter which note length action we look up - we are interested
877            in the current_value which is global across the whole group of note length
878            actions. this method is called twice for every user operation,
879            once for the action that became "inactive" and once for the action that
880            becaome "active". so ... only bother to actually change the value when this
881            is called for the "active" action.
882         */
883
884         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
885                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
886                 velocity_adjustment.set_value (v);
887         }
888 }
889
890 void
891 StepEntry::velocity_value_change ()
892 {
893         RefPtr<Action> act;
894         RefPtr<RadioAction> ract;
895         double val = velocity_adjustment.get_value();
896         bool inconsistent = true;
897         vector<const char*> velocity_actions;
898
899         velocity_actions.push_back ("StepEditing/note-velocity-ppp");
900         velocity_actions.push_back ("StepEditing/note-velocity-pp");
901         velocity_actions.push_back ("StepEditing/note-velocity-p");
902         velocity_actions.push_back ("StepEditing/note-velocity-mp");
903         velocity_actions.push_back ("StepEditing/note-velocity-mf");
904         velocity_actions.push_back ("StepEditing/note-velocity-f");
905         velocity_actions.push_back ("StepEditing/note-velocity-ff");
906         velocity_actions.push_back ("StepEditing/note-velocity-fff");
907
908         for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
909
910                 act = myactions.find_action (*i);
911
912                 if (act) {
913                         ract = RefPtr<RadioAction>::cast_dynamic (act);
914
915                         if (ract) {
916                                 if (ract->property_value() == val) {
917                                         ract->set_active (true);
918                                         inconsistent = false;
919                                         break;
920                                 }
921                         }
922                 }
923         }
924
925         velocity_ppp_button.set_inconsistent (inconsistent);
926         velocity_pp_button.set_inconsistent (inconsistent);
927         velocity_p_button.set_inconsistent (inconsistent);
928         velocity_mp_button.set_inconsistent (inconsistent);
929         velocity_mf_button.set_inconsistent (inconsistent);
930         velocity_f_button.set_inconsistent (inconsistent);
931         velocity_ff_button.set_inconsistent (inconsistent);
932         velocity_fff_button.set_inconsistent (inconsistent);
933 }
934
935 void
936 StepEntry::length_value_change ()
937 {
938         RefPtr<Action> act;
939         RefPtr<RadioAction> ract;
940         double val = length_divisor_adjustment.get_value();
941         bool inconsistent = true;
942         vector<const char*> length_actions;
943
944         length_actions.push_back ("StepEditing/note-length-whole");
945         length_actions.push_back ("StepEditing/note-length-half");
946         length_actions.push_back ("StepEditing/note-length-quarter");
947         length_actions.push_back ("StepEditing/note-length-eighth");
948         length_actions.push_back ("StepEditing/note-length-sixteenth");
949         length_actions.push_back ("StepEditing/note-length-thirtysecond");
950         length_actions.push_back ("StepEditing/note-length-sixtyfourth");
951
952         for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
953
954                 act = myactions.find_action (*i);
955
956                 if (act) {
957                         ract = RefPtr<RadioAction>::cast_dynamic (act);
958
959                         if (ract) {
960                                 if (ract->property_value() == val) {
961                                         ract->set_active (true);
962                                         inconsistent = false;
963                                         break;
964                                 }
965                         }
966                 }
967         }
968
969         length_1_button.set_inconsistent (inconsistent);
970         length_2_button.set_inconsistent (inconsistent);
971         length_4_button.set_inconsistent (inconsistent);
972         length_8_button.set_inconsistent (inconsistent);
973         length_16_button.set_inconsistent (inconsistent);
974         length_32_button.set_inconsistent (inconsistent);
975         length_64_button.set_inconsistent (inconsistent);
976
977         se->set_step_edit_cursor_width (note_length());
978 }
979
980 bool
981 StepEntry::radio_button_press (GdkEventButton* ev)
982 {
983         if (ev->button == 1) {
984                 return true;
985         }
986
987         return false;
988 }
989
990 bool
991 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
992 {
993         if (ev->button == 1) {
994                 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
995
996                 if (act) {
997                         gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
998                 }
999
1000                 return true;
1001         }
1002
1003         return false;
1004 }
1005
1006 void
1007 StepEntry::next_octave ()
1008 {
1009         octave_adjustment.set_value (octave_adjustment.get_value() + 1.0);
1010 }
1011
1012 void
1013 StepEntry::prev_octave ()
1014 {
1015         octave_adjustment.set_value (octave_adjustment.get_value() - 1.0);
1016 }
1017
1018 void
1019 StepEntry::inc_note_length ()
1020 {
1021         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() - 1.0);
1022 }
1023
1024 void
1025 StepEntry::dec_note_length ()
1026 {
1027         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() + 1.0);
1028 }
1029
1030 void
1031 StepEntry::prev_note_length ()
1032 {
1033         double l = length_divisor_adjustment.get_value();
1034         int il = (int) lrintf (l); // round to nearest integer
1035         il = (il/2) * 2; // round to power of 2
1036
1037         if (il == 0) {
1038                 il = 1;
1039         }
1040
1041         il *= 2; // double
1042
1043         length_divisor_adjustment.set_value (il);
1044 }
1045
1046 void
1047 StepEntry::next_note_length ()
1048 {
1049         double l = length_divisor_adjustment.get_value();
1050         int il = (int) lrintf (l); // round to nearest integer
1051         il = (il/2) * 2; // round to power of 2
1052
1053         if (il == 0) {
1054                 il = 1;
1055         }
1056
1057         il /= 2; // half
1058
1059         if (il > 0) {
1060                 length_divisor_adjustment.set_value (il);
1061         }
1062 }
1063
1064 void
1065 StepEntry::inc_note_velocity ()
1066 {
1067         velocity_adjustment.set_value (velocity_adjustment.get_value() + 1.0);
1068 }
1069
1070 void
1071 StepEntry::dec_note_velocity ()
1072 {
1073         velocity_adjustment.set_value (velocity_adjustment.get_value() - 1.0);
1074 }
1075
1076 void
1077 StepEntry::next_note_velocity ()
1078 {
1079         double l = velocity_adjustment.get_value ();
1080
1081         if (l < 16) {
1082                 l = 16;
1083         } else if (l < 32) {
1084                 l = 32;
1085         } else if (l < 48) {
1086                 l = 48;
1087         } else if (l < 64) {
1088                 l = 64;
1089         } else if (l < 80) {
1090                 l = 80;
1091         } else if (l < 96) {
1092                 l = 96;
1093         } else if (l < 112) {
1094                 l = 112;
1095         } else if (l < 127) {
1096                 l = 127;
1097         }
1098
1099         velocity_adjustment.set_value (l);
1100 }
1101
1102 void
1103 StepEntry::prev_note_velocity ()
1104 {
1105         double l = velocity_adjustment.get_value ();
1106
1107         if (l > 112) {
1108                 l = 112;
1109         } else if (l > 96) {
1110                 l = 96;
1111         } else if (l > 80) {
1112                 l = 80;
1113         } else if (l > 64) {
1114                 l = 64;
1115         } else if (l > 48) {
1116                 l = 48;
1117         } else if (l > 32) {
1118                 l = 32;
1119         } else if (l > 16) {
1120                 l = 16;
1121         } else {
1122                 l = 1;
1123         }
1124
1125         velocity_adjustment.set_value (l);
1126 }
1127
1128 void
1129 StepEntry::octave_n (int n)
1130 {
1131         octave_adjustment.set_value (n);
1132 }
1133
1134 void
1135 StepEntry::do_sustain ()
1136 {
1137         se->step_edit_sustain (note_length());
1138 }
1139
1140 void
1141 StepEntry::back ()
1142 {
1143         se->move_step_edit_beat_pos (-note_length());
1144 }
1145
1146 void
1147 StepEntry::sync_to_edit_point ()
1148 {
1149         se->resync_step_edit_to_edit_point ();
1150 }