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