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