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