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