neo was told there was no spoon, i'm telling you there is no bsharp
[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         , beat_resync_button (_(">beat"))
64         , bar_resync_button (_(">bar"))
65         , sustain_button (_("sustain"))
66         , rest_button (_("rest"))
67         , grid_rest_button (_("g-rest"))
68         , channel_adjustment (1, 1, 16, 1, 4) 
69         , channel_spinner (channel_adjustment)
70         , octave_adjustment (0, 1, 11, 1, 4)
71         , octave_spinner (octave_adjustment)
72         , length_divisor_adjustment (1.0, 1.0, 128, 1.0, 4.0)
73         , length_divisor_spinner (length_divisor_adjustment)
74         , velocity_adjustment (64.0, 0.0, 127.0, 1.0, 4.0)
75         , velocity_spinner (velocity_adjustment)
76         , _piano (0)
77         , piano (0)
78         , _mtv (&mtv)
79 {
80         register_actions ();
81         load_bindings ();
82
83         /* set channel selector to first selected channel. if none
84            are selected, it will remain at the value set in its
85            constructor, above (1)
86         */
87
88         uint16_t chn_mask = _mtv->channel_selector().get_selected_channels();
89         
90         for (uint32_t i = 0; i < 16; ++i) {
91                 if (chn_mask & (1<<i)) {
92                         channel_adjustment.set_value (i+1);
93                         break;
94                 }
95         }
96
97         RadioButtonGroup length_group = length_1_button.get_group();
98         length_2_button.set_group (length_group);
99         length_4_button.set_group (length_group);
100         length_8_button.set_group (length_group);
101         length_12_button.set_group (length_group);
102         length_16_button.set_group (length_group);
103         length_32_button.set_group (length_group);
104         length_64_button.set_group (length_group);
105
106         Widget* w;
107
108         w = manage (new Image (::get_icon (X_("wholenote"))));
109         w->show();
110         length_1_button.add (*w);
111         w = manage (new Image (::get_icon (X_("halfnote"))));
112         w->show();
113         length_2_button.add (*w);
114         w = manage (new Image (::get_icon (X_("quarternote"))));
115         w->show();
116         length_4_button.add (*w);
117         w = manage (new Image (::get_icon (X_("eighthnote"))));
118         w->show();
119         length_8_button.add (*w);
120         w = manage (new Image (::get_icon (X_("sixteenthnote"))));
121         w->show();
122         length_16_button.add (*w);
123         w = manage (new Image (::get_icon (X_("thirtysecondnote"))));
124         w->show();
125         length_32_button.add (*w);
126         w = manage (new Image (::get_icon (X_("sixtyfourthnote"))));
127         w->show();
128         length_64_button.add (*w);
129
130         RefPtr<Action> act;
131
132         act = myactions.find_action ("StepEditing/note-length-whole");
133         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_1_button.gobj()), act->gobj());
134         act = myactions.find_action ("StepEditing/note-length-half");
135         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_2_button.gobj()), act->gobj());
136         act = myactions.find_action ("StepEditing/note-length-quarter");
137         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_4_button.gobj()), act->gobj());
138         act = myactions.find_action ("StepEditing/note-length-eighth");
139         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_8_button.gobj()), act->gobj());
140         act = myactions.find_action ("StepEditing/note-length-sixteenth");
141         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_16_button.gobj()), act->gobj());
142         act = myactions.find_action ("StepEditing/note-length-thirtysecond");
143         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_32_button.gobj()), act->gobj());
144         act = myactions.find_action ("StepEditing/note-length-sixtyfourth");
145         gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_64_button.gobj()), act->gobj());
146
147         length_1_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
148         length_1_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 1), false);
149         length_2_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
150         length_2_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 2), false);
151         length_4_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
152         length_4_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 4), false);
153         length_8_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
154         length_8_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 8), false);
155         length_16_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
156         length_16_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 16), false);
157         length_32_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
158         length_32_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 32), false);
159         length_64_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
160         length_64_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 64), false);
161
162         length_1_button.property_draw_indicator() = false;
163         length_2_button.property_draw_indicator() = false;
164         length_4_button.property_draw_indicator() = false;
165         length_8_button.property_draw_indicator() = false;
166         length_16_button.property_draw_indicator() = false;
167         length_32_button.property_draw_indicator() = false;
168         length_64_button.property_draw_indicator() = false;
169
170         note_length_box.pack_start (length_1_button, false, false);
171         note_length_box.pack_start (length_2_button, false, false);
172         note_length_box.pack_start (length_4_button, false, false);
173         note_length_box.pack_start (length_8_button, false, false);
174         note_length_box.pack_start (length_16_button, false, false);
175         note_length_box.pack_start (length_32_button, false, false);
176         note_length_box.pack_start (length_64_button, false, false);
177
178         ARDOUR_UI::instance()->set_tip (&length_1_button, _("Set note length to a whole note"), "");
179         ARDOUR_UI::instance()->set_tip (&length_2_button, _("Set note length to a half note"), "");
180         ARDOUR_UI::instance()->set_tip (&length_4_button, _("Set note length to a quarter note"), "");
181         ARDOUR_UI::instance()->set_tip (&length_8_button, _("Set note length to a eighth note"), "");
182         ARDOUR_UI::instance()->set_tip (&length_16_button, _("Set note length to a sixteenth note"), "");
183         ARDOUR_UI::instance()->set_tip (&length_32_button, _("Set note length to a thirty-second note"), "");
184         ARDOUR_UI::instance()->set_tip (&length_64_button, _("Set note length to a sixty-fourth note"), "");
185
186         RadioButtonGroup velocity_group = velocity_ppp_button.get_group();
187         velocity_pp_button.set_group (velocity_group);
188         velocity_p_button.set_group (velocity_group);
189         velocity_mp_button.set_group (velocity_group);
190         velocity_mf_button.set_group (velocity_group);
191         velocity_f_button.set_group (velocity_group);
192         velocity_ff_button.set_group (velocity_group);
193         velocity_fff_button.set_group (velocity_group);
194
195         w = manage (new Image (::get_icon (X_("pianississimo"))));
196         w->show();
197         velocity_ppp_button.add (*w);
198         w = manage (new Image (::get_icon (X_("pianissimo"))));
199         w->show();
200         velocity_pp_button.add (*w);
201         w = manage (new Image (::get_icon (X_("piano"))));
202         w->show();
203         velocity_p_button.add (*w);
204         w = manage (new Image (::get_icon (X_("mezzopiano"))));
205         w->show();
206         velocity_mp_button.add (*w);
207         w = manage (new Image (::get_icon (X_("mezzoforte"))));
208         w->show();
209         velocity_mf_button.add (*w);
210         w = manage (new Image (::get_icon (X_("forte"))));
211         w->show();
212         velocity_f_button.add (*w);
213         w = manage (new Image (::get_icon (X_("fortissimo"))));
214         w->show();
215         velocity_ff_button.add (*w);
216         w = manage (new Image (::get_icon (X_("fortississimo"))));
217         w->show();
218         velocity_fff_button.add (*w);
219
220         act = myactions.find_action ("StepEditing/note-velocity-ppp");
221         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ppp_button.gobj()), act->gobj());
222         act = myactions.find_action ("StepEditing/note-velocity-pp");
223         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_pp_button.gobj()), act->gobj());
224         act = myactions.find_action ("StepEditing/note-velocity-p");
225         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_p_button.gobj()), act->gobj());
226         act = myactions.find_action ("StepEditing/note-velocity-mp");
227         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mp_button.gobj()), act->gobj());
228         act = myactions.find_action ("StepEditing/note-velocity-mf");
229         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mf_button.gobj()), act->gobj());
230         act = myactions.find_action ("StepEditing/note-velocity-f");
231         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_f_button.gobj()), act->gobj());
232         act = myactions.find_action ("StepEditing/note-velocity-ff");
233         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ff_button.gobj()), act->gobj());
234         act = myactions.find_action ("StepEditing/note-velocity-fff");
235         gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_fff_button.gobj()), act->gobj());
236
237         velocity_ppp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
238         velocity_ppp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ppp_button, 1), false);
239         velocity_pp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
240         velocity_pp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_pp_button, 16), false);
241         velocity_p_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
242         velocity_p_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_p_button, 32), false);
243         velocity_mp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
244         velocity_mp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mp_button, 64), false);
245         velocity_mf_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
246         velocity_mf_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mf_button, 80), false);
247         velocity_f_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
248         velocity_f_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_f_button, 96), false);
249         velocity_ff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
250         velocity_ff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ff_button, 112), false);
251         velocity_fff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
252         velocity_fff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_fff_button, 127), false);
253
254         velocity_ppp_button.property_draw_indicator() = false;
255         velocity_pp_button.property_draw_indicator() = false;
256         velocity_p_button.property_draw_indicator() = false;
257         velocity_mp_button.property_draw_indicator() = false;
258         velocity_mf_button.property_draw_indicator() = false;
259         velocity_f_button.property_draw_indicator() = false;
260         velocity_ff_button.property_draw_indicator() = false;
261         velocity_fff_button.property_draw_indicator() = false;
262
263         ARDOUR_UI::instance()->set_tip (&velocity_ppp_button, _("Set volume (velocity) to pianississimo"), "");
264         ARDOUR_UI::instance()->set_tip (&velocity_pp_button, _("Set volume (velocity) to pianissimo"), "");
265         ARDOUR_UI::instance()->set_tip (&velocity_p_button, _("Set volume (velocity) to piano"), "");
266         ARDOUR_UI::instance()->set_tip (&velocity_mp_button, _("Set volume (velocity) to mezzo-piano"), "");
267         ARDOUR_UI::instance()->set_tip (&velocity_mf_button, _("Set volume (velocity) to mezzo-forte"), "");
268         ARDOUR_UI::instance()->set_tip (&velocity_f_button, _("Set volume (velocity) to forte"), "");
269         ARDOUR_UI::instance()->set_tip (&velocity_ff_button, _("Set volume (velocity) to forteissimo"), "");
270         ARDOUR_UI::instance()->set_tip (&velocity_fff_button, _("Set volume (velocity) to forteississimo"), "");
271
272         note_velocity_box.pack_start (velocity_ppp_button, false, false);
273         note_velocity_box.pack_start (velocity_pp_button, false, false);
274         note_velocity_box.pack_start (velocity_p_button, false, false);
275         note_velocity_box.pack_start (velocity_mp_button, false, false);
276         note_velocity_box.pack_start (velocity_mf_button, false, false);
277         note_velocity_box.pack_start (velocity_f_button, false, false);
278         note_velocity_box.pack_start (velocity_ff_button, false, false);
279         note_velocity_box.pack_start (velocity_fff_button, false, false);
280
281         Label* l = manage (new Label);
282         l->set_markup ("<b><big>.</big></b>");
283         l->show ();
284         dot_button.add (*l);
285
286         w = manage (new Image (::get_icon (X_("chord"))));
287         w->show();
288         chord_button.add (*w);
289
290         rest_box.pack_start (rest_button, false, false);
291         rest_box.pack_start (grid_rest_button, false, false);
292
293         resync_box.pack_start (beat_resync_button, false, false);
294         resync_box.pack_start (bar_resync_button, false, false);
295
296         ARDOUR_UI::instance()->set_tip (&chord_button, _("Stack inserted notes to form a chord"), "");
297         ARDOUR_UI::instance()->set_tip (&sustain_button, _("Extend selected notes by note length"), "");
298         ARDOUR_UI::instance()->set_tip (&dot_button, _("Use dotted note lengths"), "");
299         ARDOUR_UI::instance()->set_tip (&rest_button, _("Insert a note-length's rest"), "");
300         ARDOUR_UI::instance()->set_tip (&grid_rest_button, _("Insert a grid-unit's rest"), "");
301         ARDOUR_UI::instance()->set_tip (&beat_resync_button, _("Insert a rest until the next beat"), "");
302         ARDOUR_UI::instance()->set_tip (&bar_resync_button, _("Insert a rest until the next bar"), "");
303
304         upper_box.set_spacing (6);
305         upper_box.pack_start (chord_button, false, false);
306         upper_box.pack_start (note_length_box, false, false, 12);
307         upper_box.pack_start (triplet_button, false, false);
308         upper_box.pack_start (dot_button, false, false);
309         upper_box.pack_start (sustain_button, false, false);
310         upper_box.pack_start (rest_box, false, false);
311         upper_box.pack_start (resync_box, false, false);
312         upper_box.pack_start (note_velocity_box, false, false, 12);
313
314         VBox* v = manage (new VBox);
315         l = manage (new Label (_("Channel")));
316         v->set_spacing (6);
317         v->pack_start (*l, false, false);
318         v->pack_start (channel_spinner, false, false);
319         upper_box.pack_start (*v, false, false);
320
321         upper_box.pack_start (length_divisor_spinner, false, false);
322         upper_box.pack_start (velocity_spinner, false, false);
323         upper_box.pack_start (octave_spinner, false, false);
324
325         velocity_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::velocity_value_change));
326         length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_value_change));
327
328         _piano = (PianoKeyboard*) piano_keyboard_new ();
329         piano = wrap ((GtkWidget*) _piano);
330
331         piano->set_flags (Gtk::CAN_FOCUS);
332
333         g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
334         g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
335         
336         rest_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::rest_click));
337         grid_rest_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::grid_rest_click));
338         chord_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::chord_toggled));
339         triplet_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::triplet_toggled));
340         beat_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::beat_resync_click));
341         bar_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bar_resync_click));
342
343         length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_changed));
344
345         packer.set_spacing (6);
346         packer.pack_start (upper_box, false, false);
347         packer.pack_start (*piano, false, false);
348         packer.show_all ();
349
350         get_vbox()->add (packer);
351 }
352
353 StepEntry::~StepEntry()
354 {
355 }
356
357 void
358 StepEntry::length_changed ()
359 {
360         length_1_button.queue_draw ();
361         length_2_button.queue_draw ();
362         length_4_button.queue_draw ();
363         length_8_button.queue_draw ();
364         length_16_button.queue_draw ();
365         length_32_button.queue_draw ();
366         length_64_button.queue_draw ();
367 }
368
369 bool
370 StepEntry::on_key_press_event (GdkEventKey* ev)
371 {
372         /* focus widget gets first shot, then bindings, otherwise
373            forward to main window
374         */
375         
376         if (!gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
377                 KeyboardKey k (ev->state, ev->keyval);
378
379                 if (bindings.activate (k, KeyboardKey::Press)) {
380                         return true;
381                 }
382         }
383
384         return forward_key_press (ev);
385 }
386
387 bool
388 StepEntry::on_key_release_event (GdkEventKey* ev)
389 {
390         /* focus widget gets first shot, then bindings, otherwise
391            forward to main window
392         */
393
394         if (!gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
395                 KeyboardKey k (ev->state, ev->keyval);
396
397                 if (bindings.activate (k, KeyboardKey::Release)) {
398                         return true;
399                 }
400         }
401
402         return forward_key_press (ev);
403 }
404
405 void
406 StepEntry::rest_event_handler ()
407 {
408         _mtv->step_edit_rest (0.0);
409 }
410
411 Evoral::MusicalTime
412 StepEntry::note_length () const
413 {
414         return 1.0 / (Evoral::MusicalTime) length_divisor_adjustment.get_value();
415 }
416
417 uint8_t
418 StepEntry::note_velocity () const
419 {
420         return (Evoral::MusicalTime) velocity_adjustment.get_value();
421 }
422
423 uint8_t 
424 StepEntry::note_channel() const
425 {
426         return channel_adjustment.get_value() - 1;
427 }
428
429 void
430 StepEntry::note_off_event_handler (int note)
431 {
432         insert_note (note);
433 }
434
435 void
436 StepEntry::rest_click ()
437 {
438         insert_rest ();
439 }
440
441 void
442 StepEntry::grid_rest_click ()
443 {
444         insert_grid_rest ();
445 }
446
447 void
448 StepEntry::triplet_toggled ()
449 {
450         if (triplet_button.get_active () != _mtv->step_edit_within_triplet()) {
451                 _mtv->step_edit_toggle_triplet ();
452         }
453 }
454
455 void
456 StepEntry::chord_toggled ()
457 {
458         if (chord_button.get_active() != _mtv->step_edit_within_chord ()) {
459                 _mtv->step_edit_toggle_chord ();
460         }
461 }
462
463 void
464 StepEntry::on_show ()
465 {
466         ArdourDialog::on_show ();
467         piano->grab_focus ();
468 }
469
470 void
471 StepEntry::beat_resync_click ()
472 {
473         _mtv->step_edit_beat_sync ();
474 }
475
476 void
477 StepEntry::bar_resync_click ()
478 {
479         _mtv->step_edit_bar_sync ();
480 }
481
482 void
483 StepEntry::register_actions ()
484 {
485         /* add named actions for the editor */
486
487         myactions.register_action ("StepEditing", "insert-a", _("Insert Note A"), sigc::mem_fun (*this, &StepEntry::insert_a));
488         myactions.register_action ("StepEditing", "insert-asharp", _("Insert Note A-sharp"), sigc::mem_fun (*this, &StepEntry::insert_asharp));
489         myactions.register_action ("StepEditing", "insert-b", _("Insert Note B"), sigc::mem_fun (*this, &StepEntry::insert_b));
490         myactions.register_action ("StepEditing", "insert-c", _("Insert Note C"), sigc::mem_fun (*this, &StepEntry::insert_c));
491         myactions.register_action ("StepEditing", "insert-csharp", _("Insert Note C-sharp"), sigc::mem_fun (*this, &StepEntry::insert_csharp));
492         myactions.register_action ("StepEditing", "insert-d", _("Insert Note D"), sigc::mem_fun (*this, &StepEntry::insert_d));
493         myactions.register_action ("StepEditing", "insert-dsharp", _("Insert Note D-sharp"), sigc::mem_fun (*this, &StepEntry::insert_dsharp));
494         myactions.register_action ("StepEditing", "insert-e", _("Insert Note E"), sigc::mem_fun (*this, &StepEntry::insert_e));
495         myactions.register_action ("StepEditing", "insert-f", _("Insert Note F"), sigc::mem_fun (*this, &StepEntry::insert_f));
496         myactions.register_action ("StepEditing", "insert-fsharp", _("Insert Note F-sharp"), sigc::mem_fun (*this, &StepEntry::insert_fsharp));
497         myactions.register_action ("StepEditing", "insert-g", _("Insert Note G"), sigc::mem_fun (*this, &StepEntry::insert_g));
498         myactions.register_action ("StepEditing", "insert-gsharp", _("Insert Note G-sharp"), sigc::mem_fun (*this, &StepEntry::insert_gsharp));
499
500         RadioAction::Group note_length_group;
501
502         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-whole", 
503                                          _("Set Note Length to Whole"), sigc::mem_fun (*this, &StepEntry::note_length_change), 1);
504         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-half", 
505                                          _("Set Note Length to 1/2"), sigc::mem_fun (*this, &StepEntry::note_length_change), 2);
506         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-quarter",
507                                          _("Set Note Length to 1/4"), sigc::mem_fun (*this, &StepEntry::note_length_change), 4);
508         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-eighth",
509                                          _("Set Note Length to 1/8"), sigc::mem_fun (*this, &StepEntry::note_length_change), 8);
510         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-sixteenth",
511                                          _("Set Note Length to 1/16"), sigc::mem_fun (*this, &StepEntry::note_length_change), 16);
512         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-thirtysecond",
513                                          _("Set Note Length to 1/32"), sigc::mem_fun (*this, &StepEntry::note_length_change), 32);
514         myactions.register_radio_action ("StepEditing", note_length_group, "note-length-sixtyfourth",
515                                          _("Set Note Length to 1/64"), sigc::mem_fun (*this, &StepEntry::note_length_change), 64);
516
517         RadioAction::Group note_velocity_group;
518
519         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-ppp",
520                                          _("Set Note Velocity to Pianississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 1);
521         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-pp",
522                                          _("Set Note Velocity to Pianissimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 16);
523         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-p",
524                                          _("Set Note Velocity to Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 32);
525         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-mp",
526                                          _("Set Note Velocity to Mezzo-Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 64);
527         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-mf",
528                                          _("Set Note Velocity to Mezzo-Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 80);
529         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-f",
530                                          _("Set Note Velocity to Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 96);
531         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-ff",
532                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 112);
533         myactions.register_radio_action ("StepEditing", note_velocity_group, "note-velocity-fff",
534                                          _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 127);
535 }
536
537 void
538 StepEntry::load_bindings ()
539 {
540         bindings.set_action_map (myactions);
541
542         sys::path binding_file;
543         SearchPath spath = ardour_search_path() + user_config_directory() + system_config_search_path();
544
545         if (find_file_in_search_path (spath, "step_editing.bindings", binding_file)) {
546                 bindings.load (binding_file.to_string());
547         }
548 }
549
550 void
551 StepEntry::insert_rest ()
552 {
553         _mtv->step_edit_rest (note_length());
554 }
555
556 void
557 StepEntry::insert_grid_rest ()
558 {
559         _mtv->step_edit_rest (0.0);
560 }
561
562 void
563 StepEntry::insert_note (uint8_t note)
564 {
565         _mtv->step_add_note (note_channel(), note, note_velocity(), note_length());
566 }
567 void
568 StepEntry::insert_c ()
569 {
570         insert_note (0 + (current_octave() * 12));
571 }
572 void
573 StepEntry::insert_csharp ()
574 {
575         insert_note (1 + (current_octave() * 12));
576 }
577 void
578 StepEntry::insert_d ()
579 {
580         insert_note (2 + (current_octave() * 12));
581 }
582 void
583 StepEntry::insert_dsharp ()
584 {
585         insert_note (3 + (current_octave() * 12));
586 }
587 void
588 StepEntry::insert_e ()
589 {
590         insert_note (4 + (current_octave() * 12));
591 }
592 void
593 StepEntry::insert_f ()
594 {
595         insert_note (5 + (current_octave() * 12));
596 }
597 void
598 StepEntry::insert_fsharp ()
599 {
600         insert_note (6 + (current_octave() * 12));
601 }
602 void
603 StepEntry::insert_g ()
604 {
605         insert_note (7 + (current_octave() * 12));
606 }
607 void
608 StepEntry::insert_gsharp ()
609 {
610         insert_note (8 + (current_octave() * 12));
611 }
612
613 void
614 StepEntry::insert_a ()
615 {
616         insert_note (9 + (current_octave() * 12));
617 }
618
619 void
620 StepEntry::insert_asharp ()
621 {
622         insert_note (10 + (current_octave() * 12));
623 }
624 void
625 StepEntry::insert_b ()
626 {
627         insert_note (11 + (current_octave() * 12));
628 }
629
630 void
631 StepEntry::note_length_change (GtkAction* act)
632 {
633         /* it doesn't matter which note length action we look up - we are interested
634            in the current_value which is global across the whole group of note length
635            actions. this method is called twice for every user operation,
636            once for the action that became "inactive" and once for the action that
637            becaome "active". so ... only bother to actually change the value when this
638            is called for the "active" action.
639         */
640         
641         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
642                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
643                 length_divisor_adjustment.set_value (v);
644         }
645 }
646
647 void
648 StepEntry::note_velocity_change (GtkAction* act)
649 {
650         /* it doesn't matter which note length action we look up - we are interested
651            in the current_value which is global across the whole group of note length
652            actions. this method is called twice for every user operation,
653            once for the action that became "inactive" and once for the action that
654            becaome "active". so ... only bother to actually change the value when this
655            is called for the "active" action.
656         */
657         
658         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
659                 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
660                 cerr << "Velocity reset to " << v << endl;
661                 velocity_adjustment.set_value (v);
662         }
663 }
664
665 void
666 StepEntry::velocity_value_change ()
667 {
668         RefPtr<Action> act;
669         RefPtr<RadioAction> ract;
670         double val = velocity_adjustment.get_value();
671         bool inconsistent = true;
672         vector<const char*> velocity_actions;
673
674         velocity_actions.push_back ("StepEditing/note-velocity-ppp");
675         velocity_actions.push_back ("StepEditing/note-velocity-pp");
676         velocity_actions.push_back ("StepEditing/note-velocity-p");
677         velocity_actions.push_back ("StepEditing/note-velocity-mp");
678         velocity_actions.push_back ("StepEditing/note-velocity-mf");
679         velocity_actions.push_back ("StepEditing/note-velocity-f");
680         velocity_actions.push_back ("StepEditing/note-velocity-ff");
681         velocity_actions.push_back ("StepEditing/note-velocity-fff");
682
683         for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
684
685                 act = myactions.find_action (*i);
686                 
687                 if (act) {
688                         ract = RefPtr<RadioAction>::cast_dynamic (act);
689
690                         if (ract) { 
691                                 if (ract->property_value() == val) {
692                                         ract->set_active (true);
693                                         inconsistent = false;
694                                         break;
695                                 }
696                         }
697                 }
698         }
699
700         velocity_ppp_button.set_inconsistent (inconsistent);
701         velocity_pp_button.set_inconsistent (inconsistent);
702         velocity_p_button.set_inconsistent (inconsistent);
703         velocity_mp_button.set_inconsistent (inconsistent);
704         velocity_mf_button.set_inconsistent (inconsistent);
705         velocity_f_button.set_inconsistent (inconsistent);
706         velocity_ff_button.set_inconsistent (inconsistent);
707         velocity_fff_button.set_inconsistent (inconsistent);
708 }
709
710 void
711 StepEntry::length_value_change ()
712 {
713         RefPtr<Action> act;
714         RefPtr<RadioAction> ract;
715         double val = length_divisor_adjustment.get_value();
716         bool inconsistent = true;
717         vector<const char*> length_actions;
718
719         length_actions.push_back ("StepEditing/note-length-whole");
720         length_actions.push_back ("StepEditing/note-length-half");
721         length_actions.push_back ("StepEditing/note-length-quarter");
722         length_actions.push_back ("StepEditing/note-length-eighth");
723         length_actions.push_back ("StepEditing/note-length-sixteenth");
724         length_actions.push_back ("StepEditing/note-length-thirtysecond");
725         length_actions.push_back ("StepEditing/note-length-sixtyfourth");
726
727         for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
728
729                 act = myactions.find_action (*i);
730                 
731                 if (act) {
732                         ract = RefPtr<RadioAction>::cast_dynamic (act);
733
734                         if (ract) { 
735                                 if (ract->property_value() == val) {
736                                         ract->set_active (true);
737                                         inconsistent = false;
738                                         break;
739                                 }
740                         }
741                 }
742         }
743
744         length_1_button.set_inconsistent (inconsistent);
745         length_2_button.set_inconsistent (inconsistent);
746         length_4_button.set_inconsistent (inconsistent);
747         length_8_button.set_inconsistent (inconsistent);
748         length_16_button.set_inconsistent (inconsistent);
749         length_32_button.set_inconsistent (inconsistent);
750         length_64_button.set_inconsistent (inconsistent);
751 }
752
753 bool
754 StepEntry::radio_button_press (GdkEventButton* ev)
755 {
756         if (ev->button == 1) {
757                 return true;
758         } 
759
760         return false;
761 }
762
763 bool
764 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
765 {
766         if (ev->button == 1) {
767                 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
768                 
769                 if (act) {
770                         gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
771                 }
772                 
773                 return true;
774         } 
775
776         return false;
777 }