more changes to Bindings, Keyboard APIs
[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 = Bindings::get_bindings (X_("step-editing"), myactions);
705         set_data ("ardour-bindings", bindings);
706 }
707
708 void
709 StepEntry::toggle_triplet ()
710 {
711         se->set_step_edit_cursor_width (note_length());
712 }
713
714 void
715 StepEntry::toggle_chord ()
716 {
717         se->step_edit_toggle_chord ();
718 }
719
720 void
721 StepEntry::dot_change (GtkAction* act)
722 {
723         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
724                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
725                 dot_adjustment.set_value (v);
726         }
727 }
728
729 void
730 StepEntry::dot_value_change ()
731 {
732         RefPtr<Action> act;
733         RefPtr<RadioAction> ract;
734         double val = dot_adjustment.get_value();
735         bool inconsistent = true;
736         vector<const char*> dot_actions;
737
738         dot_actions.push_back ("StepEditing/no-dotted");
739         dot_actions.push_back ("StepEditing/toggle-dotted");
740         dot_actions.push_back ("StepEditing/toggle-double-dotted");
741         dot_actions.push_back ("StepEditing/toggle-triple-dotted");
742
743         for (vector<const char*>::iterator i = dot_actions.begin(); i != dot_actions.end(); ++i) {
744
745                 act = myactions.find_action (*i);
746
747                 if (act) {
748                         ract = RefPtr<RadioAction>::cast_dynamic (act);
749
750                         if (ract) {
751                                 if (ract->property_value() == val) {
752                                         ract->set_active (true);
753                                         inconsistent = false;
754                                         break;
755                                 }
756                         }
757                 }
758         }
759
760         dot1_button.set_inconsistent (inconsistent);
761         dot2_button.set_inconsistent (inconsistent);
762         dot3_button.set_inconsistent (inconsistent);
763
764         se->set_step_edit_cursor_width (note_length());
765 }
766
767 void
768 StepEntry::program_click ()
769 {
770         se->step_add_program_change (note_channel(), (int8_t) floor (program_adjustment.get_value()));
771 }
772
773 void
774 StepEntry::bank_click ()
775 {
776         se->step_add_bank_change (note_channel(), (int8_t) floor (bank_adjustment.get_value()));
777 }
778
779 void
780 StepEntry::insert_rest ()
781 {
782         se->step_edit_rest (note_length());
783 }
784
785 void
786 StepEntry::insert_grid_rest ()
787 {
788         se->step_edit_rest (Evoral::Beats());
789 }
790
791 void
792 StepEntry::insert_note (uint8_t note)
793 {
794         if (note > 127) {
795                 return;
796         }
797
798         se->step_add_note (note_channel(), note, note_velocity(), note_length());
799 }
800 void
801 StepEntry::insert_c ()
802 {
803         insert_note (0 + (current_octave() * 12));
804 }
805 void
806 StepEntry::insert_csharp ()
807 {
808         insert_note (1 + (current_octave() * 12));
809 }
810 void
811 StepEntry::insert_d ()
812 {
813         insert_note (2 + (current_octave() * 12));
814 }
815 void
816 StepEntry::insert_dsharp ()
817 {
818         insert_note (3 + (current_octave() * 12));
819 }
820 void
821 StepEntry::insert_e ()
822 {
823         insert_note (4 + (current_octave() * 12));
824 }
825 void
826 StepEntry::insert_f ()
827 {
828         insert_note (5 + (current_octave() * 12));
829 }
830 void
831 StepEntry::insert_fsharp ()
832 {
833         insert_note (6 + (current_octave() * 12));
834 }
835 void
836 StepEntry::insert_g ()
837 {
838         insert_note (7 + (current_octave() * 12));
839 }
840 void
841 StepEntry::insert_gsharp ()
842 {
843         insert_note (8 + (current_octave() * 12));
844 }
845
846 void
847 StepEntry::insert_a ()
848 {
849         insert_note (9 + (current_octave() * 12));
850 }
851
852 void
853 StepEntry::insert_asharp ()
854 {
855         insert_note (10 + (current_octave() * 12));
856 }
857 void
858 StepEntry::insert_b ()
859 {
860         insert_note (11 + (current_octave() * 12));
861 }
862
863 void
864 StepEntry::note_length_change (GtkAction* act)
865 {
866         /* it doesn't matter which note length action we look up - we are interested
867            in the current_value which is global across the whole group of note length
868            actions. this method is called twice for every user operation,
869            once for the action that became "inactive" and once for the action that
870            becaome "active". so ... only bother to actually change the value when this
871            is called for the "active" action.
872         */
873
874         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
875                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
876                 length_divisor_adjustment.set_value (v);
877         }
878 }
879
880 void
881 StepEntry::note_velocity_change (GtkAction* act)
882 {
883         /* it doesn't matter which note length action we look up - we are interested
884            in the current_value which is global across the whole group of note length
885            actions. this method is called twice for every user operation,
886            once for the action that became "inactive" and once for the action that
887            becaome "active". so ... only bother to actually change the value when this
888            is called for the "active" action.
889         */
890
891         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
892                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
893                 velocity_adjustment.set_value (v);
894         }
895 }
896
897 void
898 StepEntry::velocity_value_change ()
899 {
900         RefPtr<Action> act;
901         RefPtr<RadioAction> ract;
902         double val = velocity_adjustment.get_value();
903         bool inconsistent = true;
904         vector<const char*> velocity_actions;
905
906         velocity_actions.push_back ("StepEditing/note-velocity-ppp");
907         velocity_actions.push_back ("StepEditing/note-velocity-pp");
908         velocity_actions.push_back ("StepEditing/note-velocity-p");
909         velocity_actions.push_back ("StepEditing/note-velocity-mp");
910         velocity_actions.push_back ("StepEditing/note-velocity-mf");
911         velocity_actions.push_back ("StepEditing/note-velocity-f");
912         velocity_actions.push_back ("StepEditing/note-velocity-ff");
913         velocity_actions.push_back ("StepEditing/note-velocity-fff");
914
915         for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
916
917                 act = myactions.find_action (*i);
918
919                 if (act) {
920                         ract = RefPtr<RadioAction>::cast_dynamic (act);
921
922                         if (ract) {
923                                 if (ract->property_value() == val) {
924                                         ract->set_active (true);
925                                         inconsistent = false;
926                                         break;
927                                 }
928                         }
929                 }
930         }
931
932         velocity_ppp_button.set_inconsistent (inconsistent);
933         velocity_pp_button.set_inconsistent (inconsistent);
934         velocity_p_button.set_inconsistent (inconsistent);
935         velocity_mp_button.set_inconsistent (inconsistent);
936         velocity_mf_button.set_inconsistent (inconsistent);
937         velocity_f_button.set_inconsistent (inconsistent);
938         velocity_ff_button.set_inconsistent (inconsistent);
939         velocity_fff_button.set_inconsistent (inconsistent);
940 }
941
942 void
943 StepEntry::length_value_change ()
944 {
945         RefPtr<Action> act;
946         RefPtr<RadioAction> ract;
947         double val = length_divisor_adjustment.get_value();
948         bool inconsistent = true;
949         vector<const char*> length_actions;
950
951         length_actions.push_back ("StepEditing/note-length-whole");
952         length_actions.push_back ("StepEditing/note-length-half");
953         length_actions.push_back ("StepEditing/note-length-quarter");
954         length_actions.push_back ("StepEditing/note-length-eighth");
955         length_actions.push_back ("StepEditing/note-length-sixteenth");
956         length_actions.push_back ("StepEditing/note-length-thirtysecond");
957         length_actions.push_back ("StepEditing/note-length-sixtyfourth");
958
959         for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
960
961                 act = myactions.find_action (*i);
962
963                 if (act) {
964                         ract = RefPtr<RadioAction>::cast_dynamic (act);
965
966                         if (ract) {
967                                 if (ract->property_value() == val) {
968                                         ract->set_active (true);
969                                         inconsistent = false;
970                                         break;
971                                 }
972                         }
973                 }
974         }
975
976         length_1_button.set_inconsistent (inconsistent);
977         length_2_button.set_inconsistent (inconsistent);
978         length_4_button.set_inconsistent (inconsistent);
979         length_8_button.set_inconsistent (inconsistent);
980         length_16_button.set_inconsistent (inconsistent);
981         length_32_button.set_inconsistent (inconsistent);
982         length_64_button.set_inconsistent (inconsistent);
983
984         se->set_step_edit_cursor_width (note_length());
985 }
986
987 bool
988 StepEntry::radio_button_press (GdkEventButton* ev)
989 {
990         if (ev->button == 1) {
991                 return true;
992         }
993
994         return false;
995 }
996
997 bool
998 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
999 {
1000         if (ev->button == 1) {
1001                 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
1002
1003                 if (act) {
1004                         gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
1005                 }
1006
1007                 return true;
1008         }
1009
1010         return false;
1011 }
1012
1013 void
1014 StepEntry::next_octave ()
1015 {
1016         octave_adjustment.set_value (octave_adjustment.get_value() + 1.0);
1017 }
1018
1019 void
1020 StepEntry::prev_octave ()
1021 {
1022         octave_adjustment.set_value (octave_adjustment.get_value() - 1.0);
1023 }
1024
1025 void
1026 StepEntry::inc_note_length ()
1027 {
1028         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() - 1.0);
1029 }
1030
1031 void
1032 StepEntry::dec_note_length ()
1033 {
1034         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() + 1.0);
1035 }
1036
1037 void
1038 StepEntry::prev_note_length ()
1039 {
1040         double l = length_divisor_adjustment.get_value();
1041         int il = (int) lrintf (l); // round to nearest integer
1042         il = (il/2) * 2; // round to power of 2
1043
1044         if (il == 0) {
1045                 il = 1;
1046         }
1047
1048         il *= 2; // double
1049
1050         length_divisor_adjustment.set_value (il);
1051 }
1052
1053 void
1054 StepEntry::next_note_length ()
1055 {
1056         double l = length_divisor_adjustment.get_value();
1057         int il = (int) lrintf (l); // round to nearest integer
1058         il = (il/2) * 2; // round to power of 2
1059
1060         if (il == 0) {
1061                 il = 1;
1062         }
1063
1064         il /= 2; // half
1065
1066         if (il > 0) {
1067                 length_divisor_adjustment.set_value (il);
1068         }
1069 }
1070
1071 void
1072 StepEntry::inc_note_velocity ()
1073 {
1074         velocity_adjustment.set_value (velocity_adjustment.get_value() + 1.0);
1075 }
1076
1077 void
1078 StepEntry::dec_note_velocity ()
1079 {
1080         velocity_adjustment.set_value (velocity_adjustment.get_value() - 1.0);
1081 }
1082
1083 void
1084 StepEntry::next_note_velocity ()
1085 {
1086         double l = velocity_adjustment.get_value ();
1087
1088         if (l < 16) {
1089                 l = 16;
1090         } else if (l < 32) {
1091                 l = 32;
1092         } else if (l < 48) {
1093                 l = 48;
1094         } else if (l < 64) {
1095                 l = 64;
1096         } else if (l < 80) {
1097                 l = 80;
1098         } else if (l < 96) {
1099                 l = 96;
1100         } else if (l < 112) {
1101                 l = 112;
1102         } else if (l < 127) {
1103                 l = 127;
1104         }
1105
1106         velocity_adjustment.set_value (l);
1107 }
1108
1109 void
1110 StepEntry::prev_note_velocity ()
1111 {
1112         double l = velocity_adjustment.get_value ();
1113
1114         if (l > 112) {
1115                 l = 112;
1116         } else if (l > 96) {
1117                 l = 96;
1118         } else if (l > 80) {
1119                 l = 80;
1120         } else if (l > 64) {
1121                 l = 64;
1122         } else if (l > 48) {
1123                 l = 48;
1124         } else if (l > 32) {
1125                 l = 32;
1126         } else if (l > 16) {
1127                 l = 16;
1128         } else {
1129                 l = 1;
1130         }
1131
1132         velocity_adjustment.set_value (l);
1133 }
1134
1135 void
1136 StepEntry::octave_n (int n)
1137 {
1138         octave_adjustment.set_value (n);
1139 }
1140
1141 void
1142 StepEntry::do_sustain ()
1143 {
1144         se->step_edit_sustain (note_length());
1145 }
1146
1147 void
1148 StepEntry::back ()
1149 {
1150         se->move_step_edit_beat_pos (-note_length());
1151 }
1152
1153 void
1154 StepEntry::sync_to_edit_point ()
1155 {
1156         se->resync_step_edit_to_edit_point ();
1157 }