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