small change to step edit bindings, plus make the spin button/adjustment able to...
[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/filesystem.h"
23 #include "pbd/file_utils.h"
24
25 #include "gtkmm2ext/keyboard.h"
26 #include "gtkmm2ext/actions.h"
27 #include "gtkmm2ext/bindings.h"
28
29 #include "ardour/filesystem_paths.h"
30
31 #include "ardour_ui.h"
32 #include "midi_channel_selector.h"
33 #include "midi_time_axis.h"
34 #include "step_editor.h"
35 #include "step_entry.h"
36 #include "utils.h"
37
38 #include "i18n.h"
39
40 using namespace std;
41 using namespace Gtk;
42 using namespace Glib;
43 using namespace Gtkmm2ext;
44 using namespace PBD;
45 using namespace ARDOUR;
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         : ArdourDialog (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         ARDOUR_UI::instance()->set_tip (&length_1_button, _("Set note length to a whole note"), "");
192         ARDOUR_UI::instance()->set_tip (&length_2_button, _("Set note length to a half note"), "");
193         ARDOUR_UI::instance()->set_tip (&length_4_button, _("Set note length to a quarter note"), "");
194         ARDOUR_UI::instance()->set_tip (&length_8_button, _("Set note length to a eighth note"), "");
195         ARDOUR_UI::instance()->set_tip (&length_16_button, _("Set note length to a sixteenth note"), "");
196         ARDOUR_UI::instance()->set_tip (&length_32_button, _("Set note length to a thirty-second note"), "");
197         ARDOUR_UI::instance()->set_tip (&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         ARDOUR_UI::instance()->set_tip (&velocity_ppp_button, _("Set volume (velocity) to pianississimo"), "");
277         ARDOUR_UI::instance()->set_tip (&velocity_pp_button, _("Set volume (velocity) to pianissimo"), "");
278         ARDOUR_UI::instance()->set_tip (&velocity_p_button, _("Set volume (velocity) to piano"), "");
279         ARDOUR_UI::instance()->set_tip (&velocity_mp_button, _("Set volume (velocity) to mezzo-piano"), "");
280         ARDOUR_UI::instance()->set_tip (&velocity_mf_button, _("Set volume (velocity) to mezzo-forte"), "");
281         ARDOUR_UI::instance()->set_tip (&velocity_f_button, _("Set volume (velocity) to forte"), "");
282         ARDOUR_UI::instance()->set_tip (&velocity_ff_button, _("Set volume (velocity) to forteissimo"), "");
283         ARDOUR_UI::instance()->set_tip (&velocity_fff_button, _("Set volume (velocity) to forteississimo"), "");
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         ARDOUR_UI::instance()->set_tip (&chord_button, _("Stack inserted notes to form a chord"), "");
332         ARDOUR_UI::instance()->set_tip (&sustain_button, _("Extend selected notes by note length"), "");
333         ARDOUR_UI::instance()->set_tip (&dot0_button, _("Use undotted note lengths"), "");
334         ARDOUR_UI::instance()->set_tip (&dot1_button, _("Use dotted (* 1.5) note lengths"), "");
335         ARDOUR_UI::instance()->set_tip (&dot2_button, _("Use double-dotted (* 1.75) note lengths"), "");
336         ARDOUR_UI::instance()->set_tip (&dot3_button, _("Use triple-dotted (* 1.875) note lengths"), "");
337         ARDOUR_UI::instance()->set_tip (&rest_button, _("Insert a note-length's rest"), "");
338         ARDOUR_UI::instance()->set_tip (&grid_rest_button, _("Insert a grid-unit's rest"), "");
339         ARDOUR_UI::instance()->set_tip (&beat_resync_button, _("Insert a rest until the next beat"), "");
340         ARDOUR_UI::instance()->set_tip (&bar_resync_button, _("Insert a rest until the next bar"), "");
341         ARDOUR_UI::instance()->set_tip (&bank_button, _("Insert a bank change message"), "");
342         ARDOUR_UI::instance()->set_tip (&program_button, _("Insert a program change message"), "");
343         ARDOUR_UI::instance()->set_tip (&back_button, _("Move Insert Position Back by Note Length"), "");
344         ARDOUR_UI::instance()->set_tip (&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         get_vbox()->add (packer);
462 }
463
464 StepEntry::~StepEntry()
465 {
466 }
467
468 void
469 StepEntry::length_changed ()
470 {
471         length_1_button.queue_draw ();
472         length_2_button.queue_draw ();
473         length_4_button.queue_draw ();
474         length_8_button.queue_draw ();
475         length_16_button.queue_draw ();
476         length_32_button.queue_draw ();
477         length_64_button.queue_draw ();
478 }
479
480 bool
481 StepEntry::on_key_press_event (GdkEventKey* ev)
482 {
483         /* focus widget gets first shot, then bindings, otherwise
484            forward to main window
485         */
486         
487         if (!gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
488                 KeyboardKey k (ev->state, ev->keyval);
489
490                 if (bindings.activate (k, KeyboardKey::Press)) {
491                         return true;
492                 }
493         }
494
495         return forward_key_press (ev);
496 }
497
498 bool
499 StepEntry::on_key_release_event (GdkEventKey* ev)
500 {
501         if (!gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
502                 KeyboardKey k (ev->state, ev->keyval);
503
504                 if (bindings.activate (k, KeyboardKey::Release)) {
505                         return true;
506                 }
507         }
508         
509         /* don't forward releases */
510
511         return true;
512 }
513
514 void
515 StepEntry::rest_event_handler ()
516 {
517         se->step_edit_rest (0.0);
518 }
519
520 Evoral::MusicalTime
521 StepEntry::note_length ()
522 {
523         Evoral::MusicalTime base_time = 1.0 / (Evoral::MusicalTime) length_divisor_adjustment.get_value();
524         
525         RefPtr<Action> act = myactions.find_action ("StepEditing/toggle-triplet");
526         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
527         bool triplets = tact->get_active ();
528
529         if (triplets) {
530                 base_time *= (2.0/3.0);
531         }
532
533         double dots = dot_adjustment.get_value ();
534
535         if (dots > 0) {
536                 dots = pow (2.0, dots);
537                 base_time *= 1 + ((dots - 1.0)/dots);
538         }
539
540         return base_time;
541 }
542
543 uint8_t
544 StepEntry::note_velocity () const
545 {
546         return (Evoral::MusicalTime) velocity_adjustment.get_value();
547 }
548
549 uint8_t 
550 StepEntry::note_channel() const
551 {
552         return channel_adjustment.get_value() - 1;
553 }
554
555 void
556 StepEntry::note_off_event_handler (int note)
557 {
558         insert_note (note);
559 }
560
561
562 void
563 StepEntry::on_show ()
564 {
565         ArdourDialog::on_show ();
566         //piano->grab_focus ();
567 }
568
569 void
570 StepEntry::beat_resync_click ()
571 {
572         se->step_edit_beat_sync ();
573 }
574
575 void
576 StepEntry::bar_resync_click ()
577 {
578         se->step_edit_bar_sync ();
579 }
580
581 void
582 StepEntry::register_actions ()
583 {
584         /* add named actions for the editor */
585
586         myactions.register_action ("StepEditing", "insert-a", _("Insert Note A"), sigc::mem_fun (*this, &StepEntry::insert_a));
587         myactions.register_action ("StepEditing", "insert-asharp", _("Insert Note A-sharp"), sigc::mem_fun (*this, &StepEntry::insert_asharp));
588         myactions.register_action ("StepEditing", "insert-b", _("Insert Note B"), sigc::mem_fun (*this, &StepEntry::insert_b));
589         myactions.register_action ("StepEditing", "insert-c", _("Insert Note C"), sigc::mem_fun (*this, &StepEntry::insert_c));
590         myactions.register_action ("StepEditing", "insert-csharp", _("Insert Note C-sharp"), sigc::mem_fun (*this, &StepEntry::insert_csharp));
591         myactions.register_action ("StepEditing", "insert-d", _("Insert Note D"), sigc::mem_fun (*this, &StepEntry::insert_d));
592         myactions.register_action ("StepEditing", "insert-dsharp", _("Insert Note D-sharp"), sigc::mem_fun (*this, &StepEntry::insert_dsharp));
593         myactions.register_action ("StepEditing", "insert-e", _("Insert Note E"), sigc::mem_fun (*this, &StepEntry::insert_e));
594         myactions.register_action ("StepEditing", "insert-f", _("Insert Note F"), sigc::mem_fun (*this, &StepEntry::insert_f));
595         myactions.register_action ("StepEditing", "insert-fsharp", _("Insert Note F-sharp"), sigc::mem_fun (*this, &StepEntry::insert_fsharp));
596         myactions.register_action ("StepEditing", "insert-g", _("Insert Note G"), sigc::mem_fun (*this, &StepEntry::insert_g));
597         myactions.register_action ("StepEditing", "insert-gsharp", _("Insert Note G-sharp"), sigc::mem_fun (*this, &StepEntry::insert_gsharp));
598
599         myactions.register_action ("StepEditing", "insert-rest", _("Insert a Note-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_rest));
600         myactions.register_action ("StepEditing", "insert-snap-rest", _("Insert a Snap-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_grid_rest));
601
602         myactions.register_action ("StepEditing", "next-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::next_octave));
603         myactions.register_action ("StepEditing", "prev-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::prev_octave));
604
605         myactions.register_action ("StepEditing", "next-note-length", _("Move to Next Note Length"), sigc::mem_fun (*this, &StepEntry::next_note_length));
606         myactions.register_action ("StepEditing", "prev-note-length", _("Move to Previous Note Length"), sigc::mem_fun (*this, &StepEntry::prev_note_length));
607
608         myactions.register_action ("StepEditing", "inc-note-length", _("Increase Note Length"), sigc::mem_fun (*this, &StepEntry::inc_note_length));
609         myactions.register_action ("StepEditing", "dec-note-length", _("Decrease Note Length"), sigc::mem_fun (*this, &StepEntry::dec_note_length));
610
611         myactions.register_action ("StepEditing", "next-note-velocity", _("Move to Next Note Velocity"), sigc::mem_fun (*this, &StepEntry::next_note_velocity));
612         myactions.register_action ("StepEditing", "prev-note-velocity", _("Move to Previous Note Velocity"), sigc::mem_fun (*this, &StepEntry::prev_note_velocity));
613
614         myactions.register_action ("StepEditing", "inc-note-velocity", _("Increase Note Velocity"), sigc::mem_fun (*this, &StepEntry::inc_note_velocity));
615         myactions.register_action ("StepEditing", "dec-note-velocity", _("Decrease Note Velocity"), sigc::mem_fun (*this, &StepEntry::dec_note_velocity));
616
617         myactions.register_action ("StepEditing", "octave-1", _("Switch to the 1st octave"), sigc::mem_fun (*this, &StepEntry::octave_0));
618         myactions.register_action ("StepEditing", "octave-2", _("Switch to the 2nd octave"), sigc::mem_fun (*this, &StepEntry::octave_1));
619         myactions.register_action ("StepEditing", "octave-3", _("Switch to the 3rd octave"), sigc::mem_fun (*this, &StepEntry::octave_2));
620         myactions.register_action ("StepEditing", "octave-4", _("Switch to the 4th octave"), sigc::mem_fun (*this, &StepEntry::octave_3));
621         myactions.register_action ("StepEditing", "octave-5", _("Switch to the 5th octave"), sigc::mem_fun (*this, &StepEntry::octave_4));
622         myactions.register_action ("StepEditing", "octave-6", _("Switch to the 6th octave"), sigc::mem_fun (*this, &StepEntry::octave_5));
623         myactions.register_action ("StepEditing", "octave-7", _("Switch to the 7th octave"), sigc::mem_fun (*this, &StepEntry::octave_6));
624         myactions.register_action ("StepEditing", "octave-8", _("Switch to the 8th octave"), sigc::mem_fun (*this, &StepEntry::octave_7));
625         myactions.register_action ("StepEditing", "octave-9", _("Switch to the 9th octave"), sigc::mem_fun (*this, &StepEntry::octave_8));
626         myactions.register_action ("StepEditing", "octave-10", _("Switch to the 10th octave"), sigc::mem_fun (*this, &StepEntry::octave_9));
627         myactions.register_action ("StepEditing", "octave-11", _("Switch to the 11th octave"), sigc::mem_fun (*this, &StepEntry::octave_10));
628
629         RadioAction::Group note_length_group;
630
631         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-whole", 
632                                          _("Set Note Length to Whole"), sigc::mem_fun (*this, &StepEntry::note_length_change), 1);
633         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-half", 
634                                          _("Set Note Length to 1/2"), sigc::mem_fun (*this, &StepEntry::note_length_change), 2);
635         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-third", 
636                                          _("Set Note Length to 1/3"), sigc::mem_fun (*this, &StepEntry::note_length_change), 3);
637         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-quarter",
638                                          _("Set Note Length to 1/4"), sigc::mem_fun (*this, &StepEntry::note_length_change), 4);
639         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-eighth",
640                                          _("Set Note Length to 1/8"), sigc::mem_fun (*this, &StepEntry::note_length_change), 8);
641         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-sixteenth",
642                                          _("Set Note Length to 1/16"), sigc::mem_fun (*this, &StepEntry::note_length_change), 16);
643         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-thirtysecond",
644                                          _("Set Note Length to 1/32"), sigc::mem_fun (*this, &StepEntry::note_length_change), 32);
645         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-sixtyfourth",
646                                          _("Set Note Length to 1/64"), sigc::mem_fun (*this, &StepEntry::note_length_change), 64);
647
648         RadioAction::Group note_velocity_group;
649
650         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-ppp",
651                                          _("Set Note Velocity to Pianississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 1);
652         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-pp",
653                                          _("Set Note Velocity to Pianissimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 16);
654         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-p",
655                                          _("Set Note Velocity to Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 32);
656         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-mp",
657                                          _("Set Note Velocity to Mezzo-Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 64);
658         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-mf",
659                                          _("Set Note Velocity to Mezzo-Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 80);
660         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-f",
661                                          _("Set Note Velocity to Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 96);
662         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-ff",
663                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 112);
664         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-fff",
665                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 127);
666
667         myactions.register_toggle_action ("StepEditing", "toggle-triplet", _("Toggle Triple Notes"),
668                                           sigc::mem_fun (*this, &StepEntry::toggle_triplet));
669
670         RadioAction::Group dot_group;
671
672         myactions.register_radio_action ("StepEditing", dot_group, "no-dotted", _("No Dotted Notes"), 
673                                          sigc::mem_fun (*this, &StepEntry::dot_change), 0);
674         myactions.register_radio_action ("StepEditing", dot_group, "toggle-dotted", _("Toggled Dotted Notes"), 
675                                          sigc::mem_fun (*this, &StepEntry::dot_change), 1);
676         myactions.register_radio_action ("StepEditing", dot_group, "toggle-double-dotted", _("Toggled Double-Dotted Notes"), 
677                                          sigc::mem_fun (*this, &StepEntry::dot_change), 2);
678         myactions.register_radio_action ("StepEditing", dot_group, "toggle-triple-dotted", _("Toggled Triple-Dotted Notes"), 
679                                          sigc::mem_fun (*this, &StepEntry::dot_change), 3);
680
681         myactions.register_toggle_action ("StepEditing", "toggle-chord", _("Toggle Chord Entry"),
682                                           sigc::mem_fun (*this, &StepEntry::toggle_chord));
683         myactions.register_action ("StepEditing", "sustain", _("Sustain Selected Notes by Note Length"),
684                                    sigc::mem_fun (*this, &StepEntry::do_sustain));
685
686         myactions.register_action ("StepEditing", "sync-to-edit-point", _("Move Insert Position to Edit Point"),
687                                    sigc::mem_fun (*this, &StepEntry::sync_to_edit_point));
688         myactions.register_action ("StepEditing", "back", _("Move Insert Position Back by Note Length"),
689                                    sigc::mem_fun (*this, &StepEntry::back));
690 }
691
692 void
693 StepEntry::load_bindings ()
694 {
695         /* XXX move this to a better place */
696         KeyboardKey::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
697
698         bindings.set_action_map (myactions);
699
700         sys::path binding_file;
701         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
702
703         if (find_file_in_search_path (spath, "step_editing.bindings", binding_file)) {
704                 bindings.load (binding_file.to_string());
705         }
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 (0.0);
789 }
790
791 void
792 StepEntry::insert_note (uint8_t note)
793 {
794         se->step_add_note (note_channel(), note, note_velocity(), note_length());
795 }
796 void
797 StepEntry::insert_c ()
798 {
799         insert_note (0 + (current_octave() * 12));
800 }
801 void
802 StepEntry::insert_csharp ()
803 {
804         insert_note (1 + (current_octave() * 12));
805 }
806 void
807 StepEntry::insert_d ()
808 {
809         insert_note (2 + (current_octave() * 12));
810 }
811 void
812 StepEntry::insert_dsharp ()
813 {
814         insert_note (3 + (current_octave() * 12));
815 }
816 void
817 StepEntry::insert_e ()
818 {
819         insert_note (4 + (current_octave() * 12));
820 }
821 void
822 StepEntry::insert_f ()
823 {
824         insert_note (5 + (current_octave() * 12));
825 }
826 void
827 StepEntry::insert_fsharp ()
828 {
829         insert_note (6 + (current_octave() * 12));
830 }
831 void
832 StepEntry::insert_g ()
833 {
834         insert_note (7 + (current_octave() * 12));
835 }
836 void
837 StepEntry::insert_gsharp ()
838 {
839         insert_note (8 + (current_octave() * 12));
840 }
841
842 void
843 StepEntry::insert_a ()
844 {
845         insert_note (9 + (current_octave() * 12));
846 }
847
848 void
849 StepEntry::insert_asharp ()
850 {
851         insert_note (10 + (current_octave() * 12));
852 }
853 void
854 StepEntry::insert_b ()
855 {
856         insert_note (11 + (current_octave() * 12));
857 }
858
859 void
860 StepEntry::note_length_change (GtkAction* act)
861 {
862         /* it doesn't matter which note length action we look up - we are interested
863            in the current_value which is global across the whole group of note length
864            actions. this method is called twice for every user operation,
865            once for the action that became "inactive" and once for the action that
866            becaome "active". so ... only bother to actually change the value when this
867            is called for the "active" action.
868         */
869         
870         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
871                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
872                 length_divisor_adjustment.set_value (v);
873         }
874 }
875
876 void
877 StepEntry::note_velocity_change (GtkAction* act)
878 {
879         /* it doesn't matter which note length action we look up - we are interested
880            in the current_value which is global across the whole group of note length
881            actions. this method is called twice for every user operation,
882            once for the action that became "inactive" and once for the action that
883            becaome "active". so ... only bother to actually change the value when this
884            is called for the "active" action.
885         */
886         
887         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
888                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
889                 velocity_adjustment.set_value (v);
890         }
891 }
892
893 void
894 StepEntry::velocity_value_change ()
895 {
896         RefPtr<Action> act;
897         RefPtr<RadioAction> ract;
898         double val = velocity_adjustment.get_value();
899         bool inconsistent = true;
900         vector<const char*> velocity_actions;
901
902         velocity_actions.push_back ("StepEditing/note-velocity-ppp");
903         velocity_actions.push_back ("StepEditing/note-velocity-pp");
904         velocity_actions.push_back ("StepEditing/note-velocity-p");
905         velocity_actions.push_back ("StepEditing/note-velocity-mp");
906         velocity_actions.push_back ("StepEditing/note-velocity-mf");
907         velocity_actions.push_back ("StepEditing/note-velocity-f");
908         velocity_actions.push_back ("StepEditing/note-velocity-ff");
909         velocity_actions.push_back ("StepEditing/note-velocity-fff");
910
911         for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
912
913                 act = myactions.find_action (*i);
914                 
915                 if (act) {
916                         ract = RefPtr<RadioAction>::cast_dynamic (act);
917
918                         if (ract) { 
919                                 if (ract->property_value() == val) {
920                                         ract->set_active (true);
921                                         inconsistent = false;
922                                         break;
923                                 }
924                         }
925                 }
926         }
927
928         velocity_ppp_button.set_inconsistent (inconsistent);
929         velocity_pp_button.set_inconsistent (inconsistent);
930         velocity_p_button.set_inconsistent (inconsistent);
931         velocity_mp_button.set_inconsistent (inconsistent);
932         velocity_mf_button.set_inconsistent (inconsistent);
933         velocity_f_button.set_inconsistent (inconsistent);
934         velocity_ff_button.set_inconsistent (inconsistent);
935         velocity_fff_button.set_inconsistent (inconsistent);
936 }
937
938 void
939 StepEntry::length_value_change ()
940 {
941         RefPtr<Action> act;
942         RefPtr<RadioAction> ract;
943         double val = length_divisor_adjustment.get_value();
944         bool inconsistent = true;
945         vector<const char*> length_actions;
946
947         length_actions.push_back ("StepEditing/note-length-whole");
948         length_actions.push_back ("StepEditing/note-length-half");
949         length_actions.push_back ("StepEditing/note-length-quarter");
950         length_actions.push_back ("StepEditing/note-length-eighth");
951         length_actions.push_back ("StepEditing/note-length-sixteenth");
952         length_actions.push_back ("StepEditing/note-length-thirtysecond");
953         length_actions.push_back ("StepEditing/note-length-sixtyfourth");
954
955         for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
956
957                 act = myactions.find_action (*i);
958                 
959                 if (act) {
960                         ract = RefPtr<RadioAction>::cast_dynamic (act);
961
962                         if (ract) { 
963                                 if (ract->property_value() == val) {
964                                         ract->set_active (true);
965                                         inconsistent = false;
966                                         break;
967                                 }
968                         }
969                 }
970         }
971
972         length_1_button.set_inconsistent (inconsistent);
973         length_2_button.set_inconsistent (inconsistent);
974         length_4_button.set_inconsistent (inconsistent);
975         length_8_button.set_inconsistent (inconsistent);
976         length_16_button.set_inconsistent (inconsistent);
977         length_32_button.set_inconsistent (inconsistent);
978         length_64_button.set_inconsistent (inconsistent);
979
980         se->set_step_edit_cursor_width (note_length());
981 }
982
983 bool
984 StepEntry::radio_button_press (GdkEventButton* ev)
985 {
986         if (ev->button == 1) {
987                 return true;
988         } 
989
990         return false;
991 }
992
993 bool
994 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
995 {
996         if (ev->button == 1) {
997                 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
998                 
999                 if (act) {
1000                         gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
1001                 }
1002                 
1003                 return true;
1004         } 
1005
1006         return false;
1007 }
1008
1009 void
1010 StepEntry::next_octave ()
1011 {
1012         octave_adjustment.set_value (octave_adjustment.get_value() + 1.0);
1013 }
1014
1015 void
1016 StepEntry::prev_octave ()
1017 {
1018         octave_adjustment.set_value (octave_adjustment.get_value() - 1.0);
1019 }
1020
1021 void
1022 StepEntry::inc_note_length ()
1023 {
1024         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() - 1.0);
1025 }
1026
1027 void
1028 StepEntry::dec_note_length ()
1029 {
1030         length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() + 1.0);
1031 }
1032
1033 void
1034 StepEntry::prev_note_length ()
1035 {
1036         double l = length_divisor_adjustment.get_value();
1037         int il = (int) lrintf (l); // round to nearest integer
1038         il = (il/2) * 2; // round to power of 2
1039
1040         if (il == 0) {
1041                 il = 1;
1042         }
1043
1044         il *= 2; // double
1045
1046         length_divisor_adjustment.set_value (il);
1047 }
1048
1049 void
1050 StepEntry::next_note_length ()
1051 {
1052         double l = length_divisor_adjustment.get_value();
1053         int il = (int) lrintf (l); // round to nearest integer
1054         il = (il/2) * 2; // round to power of 2
1055
1056         if (il == 0) {
1057                 il = 1;
1058         }
1059
1060         il /= 2; // half
1061
1062         if (il > 0) {
1063                 length_divisor_adjustment.set_value (il);
1064         }
1065 }
1066
1067 void
1068 StepEntry::inc_note_velocity ()
1069 {
1070         velocity_adjustment.set_value (velocity_adjustment.get_value() + 1.0);
1071 }
1072
1073 void
1074 StepEntry::dec_note_velocity ()
1075 {
1076         velocity_adjustment.set_value (velocity_adjustment.get_value() - 1.0);
1077 }
1078
1079 void
1080 StepEntry::next_note_velocity ()
1081 {
1082         double l = velocity_adjustment.get_value ();
1083
1084         if (l < 16) {
1085                 l = 16;
1086         } else if (l < 32) {
1087                 l = 32;
1088         } else if (l < 48) {
1089                 l = 48;
1090         } else if (l < 64) {
1091                 l = 64;
1092         } else if (l < 80) {
1093                 l = 80;
1094         } else if (l < 96) {
1095                 l = 96;
1096         } else if (l < 112) {
1097                 l = 112;
1098         } else if (l < 127) {
1099                 l = 127;
1100         }
1101         
1102         velocity_adjustment.set_value (l);
1103 }
1104
1105 void
1106 StepEntry::prev_note_velocity ()
1107 {
1108         double l = velocity_adjustment.get_value ();
1109
1110         if (l > 112) {
1111                 l = 112;
1112         } else if (l > 96) {
1113                 l = 96;
1114         } else if (l > 80) {
1115                 l = 80;
1116         } else if (l > 64) {
1117                 l = 64;
1118         } else if (l > 48) {
1119                 l = 48;
1120         } else if (l > 32) {
1121                 l = 32;
1122         } else if (l > 16) {
1123                 l = 16;
1124         } else {
1125                 l = 1;
1126         }
1127         
1128         velocity_adjustment.set_value (l);
1129 }
1130
1131 void
1132 StepEntry::octave_n (int n)
1133 {
1134         octave_adjustment.set_value (n);
1135 }
1136
1137 void
1138 StepEntry::do_sustain ()
1139 {
1140         se->step_edit_sustain (note_length());
1141 }
1142
1143 void
1144 StepEntry::back ()
1145 {
1146         se->move_step_edit_beat_pos (-note_length());
1147 }
1148
1149 void
1150 StepEntry::sync_to_edit_point ()
1151 {
1152         se->resync_step_edit_to_edit_point ();
1153 }