2 Copyright (C) 2010 Paul Davis
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.
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.
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.
22 #include "pbd/file_utils.h"
24 #include "gtkmm2ext/actions.h"
25 #include "gtkmm2ext/keyboard.h"
27 #include "ardour/filesystem_paths.h"
29 #include "midi_channel_selector.h"
30 #include "midi_time_axis.h"
31 #include "step_editor.h"
32 #include "step_entry.h"
41 using namespace Gtkmm2ext;
43 using namespace ARDOUR;
44 using namespace ARDOUR_UI_UTILS;
47 _note_off_event_handler (GtkWidget* /*widget*/, int note, gpointer arg)
49 ((StepEntry*)arg)->note_off_event_handler (note);
53 _rest_event_handler (GtkWidget* /*widget*/, gpointer arg)
55 ((StepEntry*)arg)->rest_event_handler ();
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 (_("+"))
88 , myactions (X_("step entry"))
94 /* set channel selector to first selected channel. if none
95 are selected, it will remain at the value set in its
96 constructor, above (1)
99 uint16_t chn_mask = se->channel_selector().get_selected_channels();
101 for (uint32_t i = 0; i < 16; ++i) {
102 if (chn_mask & (1<<i)) {
103 channel_adjustment.set_value (i+1);
110 RadioButtonGroup length_group = length_1_button.get_group();
111 length_2_button.set_group (length_group);
112 length_4_button.set_group (length_group);
113 length_8_button.set_group (length_group);
114 length_12_button.set_group (length_group);
115 length_16_button.set_group (length_group);
116 length_32_button.set_group (length_group);
117 length_64_button.set_group (length_group);
121 w = manage (new Image (::get_icon (X_("wholenote"))));
123 length_1_button.add (*w);
124 w = manage (new Image (::get_icon (X_("halfnote"))));
126 length_2_button.add (*w);
127 w = manage (new Image (::get_icon (X_("quarternote"))));
129 length_4_button.add (*w);
130 w = manage (new Image (::get_icon (X_("eighthnote"))));
132 length_8_button.add (*w);
133 w = manage (new Image (::get_icon (X_("sixteenthnote"))));
135 length_16_button.add (*w);
136 w = manage (new Image (::get_icon (X_("thirtysecondnote"))));
138 length_32_button.add (*w);
139 w = manage (new Image (::get_icon (X_("sixtyfourthnote"))));
141 length_64_button.add (*w);
145 act = myactions.find_action ("StepEditing/note-length-whole");
146 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_1_button.gobj()), act->gobj());
147 act = myactions.find_action ("StepEditing/note-length-half");
148 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_2_button.gobj()), act->gobj());
149 act = myactions.find_action ("StepEditing/note-length-quarter");
150 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_4_button.gobj()), act->gobj());
151 act = myactions.find_action ("StepEditing/note-length-eighth");
152 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_8_button.gobj()), act->gobj());
153 act = myactions.find_action ("StepEditing/note-length-sixteenth");
154 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_16_button.gobj()), act->gobj());
155 act = myactions.find_action ("StepEditing/note-length-thirtysecond");
156 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_32_button.gobj()), act->gobj());
157 act = myactions.find_action ("StepEditing/note-length-sixtyfourth");
158 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_64_button.gobj()), act->gobj());
160 length_1_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
161 length_1_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 1), false);
162 length_2_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
163 length_2_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 2), false);
164 length_4_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
165 length_4_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 4), false);
166 length_8_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
167 length_8_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 8), false);
168 length_16_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
169 length_16_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 16), false);
170 length_32_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
171 length_32_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 32), false);
172 length_64_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
173 length_64_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 64), false);
175 length_1_button.property_draw_indicator() = false;
176 length_2_button.property_draw_indicator() = false;
177 length_4_button.property_draw_indicator() = false;
178 length_8_button.property_draw_indicator() = false;
179 length_16_button.property_draw_indicator() = false;
180 length_32_button.property_draw_indicator() = false;
181 length_64_button.property_draw_indicator() = false;
183 note_length_box.pack_start (length_1_button, false, false);
184 note_length_box.pack_start (length_2_button, false, false);
185 note_length_box.pack_start (length_4_button, false, false);
186 note_length_box.pack_start (length_8_button, false, false);
187 note_length_box.pack_start (length_16_button, false, false);
188 note_length_box.pack_start (length_32_button, false, false);
189 note_length_box.pack_start (length_64_button, false, false);
191 set_tooltip (&length_1_button, _("Set note length to a whole note"), "");
192 set_tooltip (&length_2_button, _("Set note length to a half note"), "");
193 set_tooltip (&length_4_button, _("Set note length to a quarter note"), "");
194 set_tooltip (&length_8_button, _("Set note length to a eighth note"), "");
195 set_tooltip (&length_16_button, _("Set note length to a sixteenth note"), "");
196 set_tooltip (&length_32_button, _("Set note length to a thirty-second note"), "");
197 set_tooltip (&length_64_button, _("Set note length to a sixty-fourth note"), "");
199 RadioButtonGroup velocity_group = velocity_ppp_button.get_group();
200 velocity_pp_button.set_group (velocity_group);
201 velocity_p_button.set_group (velocity_group);
202 velocity_mp_button.set_group (velocity_group);
203 velocity_mf_button.set_group (velocity_group);
204 velocity_f_button.set_group (velocity_group);
205 velocity_ff_button.set_group (velocity_group);
206 velocity_fff_button.set_group (velocity_group);
208 w = manage (new Image (::get_icon (X_("pianississimo"))));
210 velocity_ppp_button.add (*w);
211 w = manage (new Image (::get_icon (X_("pianissimo"))));
213 velocity_pp_button.add (*w);
214 w = manage (new Image (::get_icon (X_("piano"))));
216 velocity_p_button.add (*w);
217 w = manage (new Image (::get_icon (X_("mezzopiano"))));
219 velocity_mp_button.add (*w);
220 w = manage (new Image (::get_icon (X_("mezzoforte"))));
222 velocity_mf_button.add (*w);
223 w = manage (new Image (::get_icon (X_("forte"))));
225 velocity_f_button.add (*w);
226 w = manage (new Image (::get_icon (X_("fortissimo"))));
228 velocity_ff_button.add (*w);
229 w = manage (new Image (::get_icon (X_("fortississimo"))));
231 velocity_fff_button.add (*w);
233 act = myactions.find_action ("StepEditing/note-velocity-ppp");
234 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ppp_button.gobj()), act->gobj());
235 act = myactions.find_action ("StepEditing/note-velocity-pp");
236 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_pp_button.gobj()), act->gobj());
237 act = myactions.find_action ("StepEditing/note-velocity-p");
238 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_p_button.gobj()), act->gobj());
239 act = myactions.find_action ("StepEditing/note-velocity-mp");
240 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mp_button.gobj()), act->gobj());
241 act = myactions.find_action ("StepEditing/note-velocity-mf");
242 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mf_button.gobj()), act->gobj());
243 act = myactions.find_action ("StepEditing/note-velocity-f");
244 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_f_button.gobj()), act->gobj());
245 act = myactions.find_action ("StepEditing/note-velocity-ff");
246 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ff_button.gobj()), act->gobj());
247 act = myactions.find_action ("StepEditing/note-velocity-fff");
248 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_fff_button.gobj()), act->gobj());
250 velocity_ppp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
251 velocity_ppp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ppp_button, 1), false);
252 velocity_pp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
253 velocity_pp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_pp_button, 16), false);
254 velocity_p_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
255 velocity_p_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_p_button, 32), false);
256 velocity_mp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
257 velocity_mp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mp_button, 64), false);
258 velocity_mf_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
259 velocity_mf_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mf_button, 80), false);
260 velocity_f_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
261 velocity_f_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_f_button, 96), false);
262 velocity_ff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
263 velocity_ff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ff_button, 112), false);
264 velocity_fff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
265 velocity_fff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_fff_button, 127), false);
267 velocity_ppp_button.property_draw_indicator() = false;
268 velocity_pp_button.property_draw_indicator() = false;
269 velocity_p_button.property_draw_indicator() = false;
270 velocity_mp_button.property_draw_indicator() = false;
271 velocity_mf_button.property_draw_indicator() = false;
272 velocity_f_button.property_draw_indicator() = false;
273 velocity_ff_button.property_draw_indicator() = false;
274 velocity_fff_button.property_draw_indicator() = false;
276 set_tooltip (&velocity_ppp_button, _("Set volume (velocity) to pianississimo"), "");
277 set_tooltip (&velocity_pp_button, _("Set volume (velocity) to pianissimo"), "");
278 set_tooltip (&velocity_p_button, _("Set volume (velocity) to piano"), "");
279 set_tooltip (&velocity_mp_button, _("Set volume (velocity) to mezzo-piano"), "");
280 set_tooltip (&velocity_mf_button, _("Set volume (velocity) to mezzo-forte"), "");
281 set_tooltip (&velocity_f_button, _("Set volume (velocity) to forte"), "");
282 set_tooltip (&velocity_ff_button, _("Set volume (velocity) to fortissimo"), "");
283 set_tooltip (&velocity_fff_button, _("Set volume (velocity) to fortississimo"), "");
285 note_velocity_box.pack_start (velocity_ppp_button, false, false);
286 note_velocity_box.pack_start (velocity_pp_button, false, false);
287 note_velocity_box.pack_start (velocity_p_button, false, false);
288 note_velocity_box.pack_start (velocity_mp_button, false, false);
289 note_velocity_box.pack_start (velocity_mf_button, false, false);
290 note_velocity_box.pack_start (velocity_f_button, false, false);
291 note_velocity_box.pack_start (velocity_ff_button, false, false);
292 note_velocity_box.pack_start (velocity_fff_button, false, false);
294 Label* l = manage (new Label);
295 l->set_markup ("<b><big>-</big></b>");
297 dot0_button.add (*l);
299 l = manage (new Label);
300 l->set_markup ("<b><big>.</big></b>");
302 dot1_button.add (*l);
304 l = manage (new Label);
305 l->set_markup ("<b><big>..</big></b>");
307 dot2_button.add (*l);
309 l = manage (new Label);
310 l->set_markup ("<b><big>...</big></b>");
312 dot3_button.add (*l);
314 w = manage (new Image (::get_icon (X_("chord"))));
316 chord_button.add (*w);
318 dot_box1.pack_start (dot0_button, true, false);
319 dot_box1.pack_start (dot1_button, true, false);
320 dot_box2.pack_start (dot2_button, true, false);
321 dot_box2.pack_start (dot3_button, true, false);
323 rest_box.pack_start (rest_button, true, false);
324 rest_box.pack_start (grid_rest_button, true, false);
325 rest_box.pack_start (back_button, true, false);
327 resync_box.pack_start (beat_resync_button, true, false);
328 resync_box.pack_start (bar_resync_button, true, false);
329 resync_box.pack_start (resync_button, true, false);
331 set_tooltip (&chord_button, _("Stack inserted notes to form a chord"), "");
332 set_tooltip (&sustain_button, _("Extend selected notes by note length"), "");
333 set_tooltip (&dot0_button, _("Use undotted note lengths"), "");
334 set_tooltip (&dot1_button, _("Use dotted (* 1.5) note lengths"), "");
335 set_tooltip (&dot2_button, _("Use double-dotted (* 1.75) note lengths"), "");
336 set_tooltip (&dot3_button, _("Use triple-dotted (* 1.875) note lengths"), "");
337 set_tooltip (&rest_button, _("Insert a note-length's rest"), "");
338 set_tooltip (&grid_rest_button, _("Insert a grid-unit's rest"), "");
339 set_tooltip (&beat_resync_button, _("Insert a rest until the next beat"), "");
340 set_tooltip (&bar_resync_button, _("Insert a rest until the next bar"), "");
341 set_tooltip (&bank_button, _("Insert a bank change message"), "");
342 set_tooltip (&program_button, _("Insert a program change message"), "");
343 set_tooltip (&back_button, _("Move Insert Position Back by Note Length"), "");
344 set_tooltip (&resync_button, _("Move Insert Position to Edit Point"), "");
346 act = myactions.find_action ("StepEditing/back");
347 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (back_button.gobj()), false);
348 gtk_activatable_set_related_action (GTK_ACTIVATABLE (back_button.gobj()), act->gobj());
349 act = myactions.find_action ("StepEditing/sync-to-edit-point");
350 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (resync_button.gobj()), false);
351 gtk_activatable_set_related_action (GTK_ACTIVATABLE (resync_button.gobj()), act->gobj());
352 act = myactions.find_action ("StepEditing/toggle-triplet");
353 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (triplet_button.gobj()), false);
354 gtk_activatable_set_related_action (GTK_ACTIVATABLE (triplet_button.gobj()), act->gobj());
355 act = myactions.find_action ("StepEditing/no-dotted");
356 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot0_button.gobj()), false);
357 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot0_button.gobj()), act->gobj());
358 act = myactions.find_action ("StepEditing/toggle-dotted");
359 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot1_button.gobj()), false);
360 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot1_button.gobj()), act->gobj());
361 act = myactions.find_action ("StepEditing/toggle-double-dotted");
362 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot2_button.gobj()), false);
363 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot2_button.gobj()), act->gobj());
364 act = myactions.find_action ("StepEditing/toggle-triple-dotted");
365 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot3_button.gobj()), false);
366 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot3_button.gobj()), act->gobj());
367 act = myactions.find_action ("StepEditing/toggle-chord");
368 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (chord_button.gobj()), false);
369 gtk_activatable_set_related_action (GTK_ACTIVATABLE (chord_button.gobj()), act->gobj());
370 act = myactions.find_action ("StepEditing/insert-rest");
371 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (rest_button.gobj()), false);
372 gtk_activatable_set_related_action (GTK_ACTIVATABLE (rest_button.gobj()), act->gobj());
373 act = myactions.find_action ("StepEditing/insert-snap-rest");
374 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (grid_rest_button.gobj()), false);
375 gtk_activatable_set_related_action (GTK_ACTIVATABLE (grid_rest_button.gobj()), act->gobj());
376 act = myactions.find_action ("StepEditing/sustain");
377 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (sustain_button.gobj()), false);
378 gtk_activatable_set_related_action (GTK_ACTIVATABLE (sustain_button.gobj()), act->gobj());
380 upper_box.set_spacing (6);
381 upper_box.pack_start (chord_button, false, false);
382 upper_box.pack_start (note_length_box, false, false, 12);
383 upper_box.pack_start (triplet_button, false, false);
384 upper_box.pack_start (dot_box1, false, false);
385 upper_box.pack_start (dot_box2, false, false);
386 upper_box.pack_start (sustain_button, false, false);
387 upper_box.pack_start (rest_box, false, false);
388 upper_box.pack_start (resync_box, false, false);
389 upper_box.pack_start (note_velocity_box, false, false, 12);
393 v = manage (new VBox);
394 l = manage (new Label (_("Channel")));
396 v->pack_start (*l, false, false);
397 v->pack_start (channel_spinner, false, false);
398 upper_box.pack_start (*v, false, false);
400 v = manage (new VBox);
401 l = manage (new Label (_("1/Note")));
403 v->pack_start (*l, false, false);
404 v->pack_start (length_divisor_spinner, false, false);
405 upper_box.pack_start (*v, false, false);
407 v = manage (new VBox);
408 l = manage (new Label (_("Velocity")));
410 v->pack_start (*l, false, false);
411 v->pack_start (velocity_spinner, false, false);
412 upper_box.pack_start (*v, false, false);
414 v = manage (new VBox);
415 l = manage (new Label (_("Octave")));
417 v->pack_start (*l, false, false);
418 v->pack_start (octave_spinner, false, false);
419 upper_box.pack_start (*v, false, false);
421 v = manage (new VBox);
422 l = manage (new Label (_("Bank")));
424 v->pack_start (*l, false, false);
425 v->pack_start (bank_spinner, false, false);
426 v->pack_start (bank_button, false, false);
427 upper_box.pack_start (*v, false, false);
429 v = manage (new VBox);
430 l = manage (new Label (_("Program")));
432 v->pack_start (*l, false, false);
433 v->pack_start (program_spinner, false, false);
434 v->pack_start (program_button, false, false);
435 upper_box.pack_start (*v, false, false);
437 velocity_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::velocity_value_change));
438 length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_value_change));
439 dot_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::dot_value_change));
441 _piano = (PianoKeyboard*) piano_keyboard_new ();
442 piano = wrap ((GtkWidget*) _piano);
444 piano->set_flags (Gtk::CAN_FOCUS);
446 g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
447 g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
449 program_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::program_click));
450 bank_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bank_click));
451 beat_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::beat_resync_click));
452 bar_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bar_resync_click));
454 length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_changed));
456 packer.set_spacing (6);
457 packer.pack_start (upper_box, false, false);
458 packer.pack_start (*piano, false, false);
463 /* initial settings: quarter note and mezzo forte */
465 act = myactions.find_action ("StepEditing/note-length-quarter");
466 RefPtr<RadioAction> r = RefPtr<RadioAction>::cast_dynamic (act);
468 r->set_active (true);
470 act = myactions.find_action ("StepEditing/note-velocity-mf");
471 r = RefPtr<RadioAction>::cast_dynamic (act);
473 r->set_active (true);
476 StepEntry::~StepEntry()
481 StepEntry::length_changed ()
483 length_1_button.queue_draw ();
484 length_2_button.queue_draw ();
485 length_4_button.queue_draw ();
486 length_8_button.queue_draw ();
487 length_16_button.queue_draw ();
488 length_32_button.queue_draw ();
489 length_64_button.queue_draw ();
493 StepEntry::on_key_press_event (GdkEventKey* ev)
495 /* focus widget gets first shot, then bindings, otherwise
496 forward to main window
499 if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
503 return relay_key_press (ev, this);
507 StepEntry::on_key_release_event (GdkEventKey* ev)
509 if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
513 /* don't forward releases */
519 StepEntry::rest_event_handler ()
521 se->step_edit_rest (Evoral::Beats());
525 StepEntry::note_length ()
527 double base_time = 4.0 / (double) length_divisor_adjustment.get_value();
529 RefPtr<Action> act = myactions.find_action ("StepEditing/toggle-triplet");
530 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
531 bool triplets = tact->get_active ();
534 base_time *= (2.0/3.0);
537 double dots = dot_adjustment.get_value ();
540 dots = pow (2.0, dots);
541 base_time *= 1 + ((dots - 1.0)/dots);
544 return Evoral::Beats(base_time);
548 StepEntry::note_velocity () const
550 return velocity_adjustment.get_value();
554 StepEntry::note_channel() const
556 return channel_adjustment.get_value() - 1;
560 StepEntry::note_off_event_handler (int note)
567 StepEntry::on_show ()
569 ArdourWindow::on_show ();
570 //piano->grab_focus ();
574 StepEntry::beat_resync_click ()
576 se->step_edit_beat_sync ();
580 StepEntry::bar_resync_click ()
582 se->step_edit_bar_sync ();
586 StepEntry::register_actions ()
588 /* add named actions for the step editor */
590 Glib::RefPtr<ActionGroup> group = myactions.create_action_group (X_("StepEditing"));
592 myactions.register_action (group, "insert-a", _("Insert Note A"), sigc::mem_fun (*this, &StepEntry::insert_a));
593 myactions.register_action (group, "insert-asharp", _("Insert Note A-sharp"), sigc::mem_fun (*this, &StepEntry::insert_asharp));
594 myactions.register_action (group, "insert-b", _("Insert Note B"), sigc::mem_fun (*this, &StepEntry::insert_b));
595 myactions.register_action (group, "insert-c", _("Insert Note C"), sigc::mem_fun (*this, &StepEntry::insert_c));
596 myactions.register_action (group, "insert-csharp", _("Insert Note C-sharp"), sigc::mem_fun (*this, &StepEntry::insert_csharp));
597 myactions.register_action (group, "insert-d", _("Insert Note D"), sigc::mem_fun (*this, &StepEntry::insert_d));
598 myactions.register_action (group, "insert-dsharp", _("Insert Note D-sharp"), sigc::mem_fun (*this, &StepEntry::insert_dsharp));
599 myactions.register_action (group, "insert-e", _("Insert Note E"), sigc::mem_fun (*this, &StepEntry::insert_e));
600 myactions.register_action (group, "insert-f", _("Insert Note F"), sigc::mem_fun (*this, &StepEntry::insert_f));
601 myactions.register_action (group, "insert-fsharp", _("Insert Note F-sharp"), sigc::mem_fun (*this, &StepEntry::insert_fsharp));
602 myactions.register_action (group, "insert-g", _("Insert Note G"), sigc::mem_fun (*this, &StepEntry::insert_g));
603 myactions.register_action (group, "insert-gsharp", _("Insert Note G-sharp"), sigc::mem_fun (*this, &StepEntry::insert_gsharp));
605 myactions.register_action (group, "insert-rest", _("Insert a Note-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_rest));
606 myactions.register_action (group, "insert-snap-rest", _("Insert a Snap-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_grid_rest));
608 myactions.register_action (group, "next-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::next_octave));
609 myactions.register_action (group, "prev-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::prev_octave));
611 myactions.register_action (group, "next-note-length", _("Move to Next Note Length"), sigc::mem_fun (*this, &StepEntry::next_note_length));
612 myactions.register_action (group, "prev-note-length", _("Move to Previous Note Length"), sigc::mem_fun (*this, &StepEntry::prev_note_length));
614 myactions.register_action (group, "inc-note-length", _("Increase Note Length"), sigc::mem_fun (*this, &StepEntry::inc_note_length));
615 myactions.register_action (group, "dec-note-length", _("Decrease Note Length"), sigc::mem_fun (*this, &StepEntry::dec_note_length));
617 myactions.register_action (group, "next-note-velocity", _("Move to Next Note Velocity"), sigc::mem_fun (*this, &StepEntry::next_note_velocity));
618 myactions.register_action (group, "prev-note-velocity", _("Move to Previous Note Velocity"), sigc::mem_fun (*this, &StepEntry::prev_note_velocity));
620 myactions.register_action (group, "inc-note-velocity", _("Increase Note Velocity"), sigc::mem_fun (*this, &StepEntry::inc_note_velocity));
621 myactions.register_action (group, "dec-note-velocity", _("Decrease Note Velocity"), sigc::mem_fun (*this, &StepEntry::dec_note_velocity));
623 myactions.register_action (group, "octave-0", _("Switch to the 1st octave"), sigc::mem_fun (*this, &StepEntry::octave_0));
624 myactions.register_action (group, "octave-1", _("Switch to the 2nd octave"), sigc::mem_fun (*this, &StepEntry::octave_1));
625 myactions.register_action (group, "octave-2", _("Switch to the 3rd octave"), sigc::mem_fun (*this, &StepEntry::octave_2));
626 myactions.register_action (group, "octave-3", _("Switch to the 4th octave"), sigc::mem_fun (*this, &StepEntry::octave_3));
627 myactions.register_action (group, "octave-4", _("Switch to the 5th octave"), sigc::mem_fun (*this, &StepEntry::octave_4));
628 myactions.register_action (group, "octave-5", _("Switch to the 6th octave"), sigc::mem_fun (*this, &StepEntry::octave_5));
629 myactions.register_action (group, "octave-6", _("Switch to the 7th octave"), sigc::mem_fun (*this, &StepEntry::octave_6));
630 myactions.register_action (group, "octave-7", _("Switch to the 8th octave"), sigc::mem_fun (*this, &StepEntry::octave_7));
631 myactions.register_action (group, "octave-8", _("Switch to the 9th octave"), sigc::mem_fun (*this, &StepEntry::octave_8));
632 myactions.register_action (group, "octave-9", _("Switch to the 10th octave"), sigc::mem_fun (*this, &StepEntry::octave_9));
633 myactions.register_action (group, "octave-10", _("Switch to the 11th octave"), sigc::mem_fun (*this, &StepEntry::octave_10));
635 myactions.register_toggle_action (group, "toggle-triplet", _("Toggle Triple Notes"),
636 sigc::mem_fun (*this, &StepEntry::toggle_triplet));
638 myactions.register_toggle_action (group, "toggle-chord", _("Toggle Chord Entry"),
639 sigc::mem_fun (*this, &StepEntry::toggle_chord));
640 myactions.register_action (group, "sustain", _("Sustain Selected Notes by Note Length"),
641 sigc::mem_fun (*this, &StepEntry::do_sustain));
643 myactions.register_action (group, "sync-to-edit-point", _("Move Insert Position to Edit Point"),
644 sigc::mem_fun (*this, &StepEntry::sync_to_edit_point));
645 myactions.register_action (group, "back", _("Move Insert Position Back by Note Length"),
646 sigc::mem_fun (*this, &StepEntry::back));
647 RadioAction::Group note_length_group;
649 myactions.register_radio_action (group, note_length_group, "note-length-whole",
650 _("Set Note Length to Whole"), sigc::mem_fun (*this, &StepEntry::note_length_change), 1);
651 myactions.register_radio_action (group, note_length_group, "note-length-half",
652 _("Set Note Length to 1/2"), sigc::mem_fun (*this, &StepEntry::note_length_change), 2);
653 myactions.register_radio_action (group, note_length_group, "note-length-third",
654 _("Set Note Length to 1/3"), sigc::mem_fun (*this, &StepEntry::note_length_change), 3);
655 myactions.register_radio_action (group, note_length_group, "note-length-quarter",
656 _("Set Note Length to 1/4"), sigc::mem_fun (*this, &StepEntry::note_length_change), 4);
657 myactions.register_radio_action (group, note_length_group, "note-length-eighth",
658 _("Set Note Length to 1/8"), sigc::mem_fun (*this, &StepEntry::note_length_change), 8);
659 myactions.register_radio_action (group, note_length_group, "note-length-sixteenth",
660 _("Set Note Length to 1/16"), sigc::mem_fun (*this, &StepEntry::note_length_change), 16);
661 myactions.register_radio_action (group, note_length_group, "note-length-thirtysecond",
662 _("Set Note Length to 1/32"), sigc::mem_fun (*this, &StepEntry::note_length_change), 32);
663 myactions.register_radio_action (group, note_length_group, "note-length-sixtyfourth",
664 _("Set Note Length to 1/64"), sigc::mem_fun (*this, &StepEntry::note_length_change), 64);
666 RadioAction::Group note_velocity_group;
668 myactions.register_radio_action (group, note_velocity_group, "note-velocity-ppp",
669 _("Set Note Velocity to Pianississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 1);
670 myactions.register_radio_action (group, note_velocity_group, "note-velocity-pp",
671 _("Set Note Velocity to Pianissimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 16);
672 myactions.register_radio_action (group, note_velocity_group, "note-velocity-p",
673 _("Set Note Velocity to Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 32);
674 myactions.register_radio_action (group, note_velocity_group, "note-velocity-mp",
675 _("Set Note Velocity to Mezzo-Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 64);
676 myactions.register_radio_action (group, note_velocity_group, "note-velocity-mf",
677 _("Set Note Velocity to Mezzo-Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 80);
678 myactions.register_radio_action (group, note_velocity_group, "note-velocity-f",
679 _("Set Note Velocity to Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 96);
680 myactions.register_radio_action (group, note_velocity_group, "note-velocity-ff",
681 _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 112);
682 myactions.register_radio_action (group, note_velocity_group, "note-velocity-fff",
683 _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 127);
686 RadioAction::Group dot_group;
688 myactions.register_radio_action (group, dot_group, "no-dotted", _("No Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 0);
689 myactions.register_radio_action (group, dot_group, "toggle-dotted", _("Toggled Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 1);
690 myactions.register_radio_action (group, dot_group, "toggle-double-dotted", _("Toggled Double-Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 2);
691 myactions.register_radio_action (group, dot_group, "toggle-triple-dotted", _("Toggled Triple-Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 3);
695 StepEntry::load_bindings ()
697 bindings = Bindings::get_bindings (X_("Step Editing"), myactions);
698 set_data ("ardour-bindings", bindings);
702 StepEntry::toggle_triplet ()
704 se->set_step_edit_cursor_width (note_length());
708 StepEntry::toggle_chord ()
710 se->step_edit_toggle_chord ();
714 StepEntry::dot_change (GtkAction* act)
716 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
717 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
718 dot_adjustment.set_value (v);
723 StepEntry::dot_value_change ()
726 RefPtr<RadioAction> ract;
727 double val = dot_adjustment.get_value();
728 bool inconsistent = true;
729 vector<const char*> dot_actions;
731 dot_actions.push_back ("StepEditing/no-dotted");
732 dot_actions.push_back ("StepEditing/toggle-dotted");
733 dot_actions.push_back ("StepEditing/toggle-double-dotted");
734 dot_actions.push_back ("StepEditing/toggle-triple-dotted");
736 for (vector<const char*>::iterator i = dot_actions.begin(); i != dot_actions.end(); ++i) {
738 act = myactions.find_action (*i);
741 ract = RefPtr<RadioAction>::cast_dynamic (act);
744 if (ract->property_value() == val) {
745 ract->set_active (true);
746 inconsistent = false;
753 dot1_button.set_inconsistent (inconsistent);
754 dot2_button.set_inconsistent (inconsistent);
755 dot3_button.set_inconsistent (inconsistent);
757 se->set_step_edit_cursor_width (note_length());
761 StepEntry::program_click ()
763 se->step_add_program_change (note_channel(), (int8_t) floor (program_adjustment.get_value()));
767 StepEntry::bank_click ()
769 se->step_add_bank_change (note_channel(), (int8_t) floor (bank_adjustment.get_value()));
773 StepEntry::insert_rest ()
775 se->step_edit_rest (note_length());
779 StepEntry::insert_grid_rest ()
781 se->step_edit_rest (Evoral::Beats());
785 StepEntry::insert_note (uint8_t note)
791 se->step_add_note (note_channel(), note, note_velocity(), note_length());
794 StepEntry::insert_c ()
796 insert_note (0 + (current_octave() * 12));
799 StepEntry::insert_csharp ()
801 insert_note (1 + (current_octave() * 12));
804 StepEntry::insert_d ()
806 insert_note (2 + (current_octave() * 12));
809 StepEntry::insert_dsharp ()
811 insert_note (3 + (current_octave() * 12));
814 StepEntry::insert_e ()
816 insert_note (4 + (current_octave() * 12));
819 StepEntry::insert_f ()
821 insert_note (5 + (current_octave() * 12));
824 StepEntry::insert_fsharp ()
826 insert_note (6 + (current_octave() * 12));
829 StepEntry::insert_g ()
831 insert_note (7 + (current_octave() * 12));
834 StepEntry::insert_gsharp ()
836 insert_note (8 + (current_octave() * 12));
840 StepEntry::insert_a ()
842 insert_note (9 + (current_octave() * 12));
846 StepEntry::insert_asharp ()
848 insert_note (10 + (current_octave() * 12));
851 StepEntry::insert_b ()
853 insert_note (11 + (current_octave() * 12));
857 StepEntry::note_length_change (GtkAction* act)
859 /* it doesn't matter which note length action we look up - we are interested
860 in the current_value which is global across the whole group of note length
861 actions. this method is called twice for every user operation,
862 once for the action that became "inactive" and once for the action that
863 becaome "active". so ... only bother to actually change the value when this
864 is called for the "active" action.
867 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
868 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
869 length_divisor_adjustment.set_value (v);
874 StepEntry::note_velocity_change (GtkAction* act)
876 /* it doesn't matter which note length action we look up - we are interested
877 in the current_value which is global across the whole group of note length
878 actions. this method is called twice for every user operation,
879 once for the action that became "inactive" and once for the action that
880 becaome "active". so ... only bother to actually change the value when this
881 is called for the "active" action.
884 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
885 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
886 velocity_adjustment.set_value (v);
891 StepEntry::velocity_value_change ()
894 RefPtr<RadioAction> ract;
895 double val = velocity_adjustment.get_value();
896 bool inconsistent = true;
897 vector<const char*> velocity_actions;
899 velocity_actions.push_back ("StepEditing/note-velocity-ppp");
900 velocity_actions.push_back ("StepEditing/note-velocity-pp");
901 velocity_actions.push_back ("StepEditing/note-velocity-p");
902 velocity_actions.push_back ("StepEditing/note-velocity-mp");
903 velocity_actions.push_back ("StepEditing/note-velocity-mf");
904 velocity_actions.push_back ("StepEditing/note-velocity-f");
905 velocity_actions.push_back ("StepEditing/note-velocity-ff");
906 velocity_actions.push_back ("StepEditing/note-velocity-fff");
908 for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
910 act = myactions.find_action (*i);
913 ract = RefPtr<RadioAction>::cast_dynamic (act);
916 if (ract->property_value() == val) {
917 ract->set_active (true);
918 inconsistent = false;
925 velocity_ppp_button.set_inconsistent (inconsistent);
926 velocity_pp_button.set_inconsistent (inconsistent);
927 velocity_p_button.set_inconsistent (inconsistent);
928 velocity_mp_button.set_inconsistent (inconsistent);
929 velocity_mf_button.set_inconsistent (inconsistent);
930 velocity_f_button.set_inconsistent (inconsistent);
931 velocity_ff_button.set_inconsistent (inconsistent);
932 velocity_fff_button.set_inconsistent (inconsistent);
936 StepEntry::length_value_change ()
939 RefPtr<RadioAction> ract;
940 double val = length_divisor_adjustment.get_value();
941 bool inconsistent = true;
942 vector<const char*> length_actions;
944 length_actions.push_back ("StepEditing/note-length-whole");
945 length_actions.push_back ("StepEditing/note-length-half");
946 length_actions.push_back ("StepEditing/note-length-quarter");
947 length_actions.push_back ("StepEditing/note-length-eighth");
948 length_actions.push_back ("StepEditing/note-length-sixteenth");
949 length_actions.push_back ("StepEditing/note-length-thirtysecond");
950 length_actions.push_back ("StepEditing/note-length-sixtyfourth");
952 for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
954 act = myactions.find_action (*i);
957 ract = RefPtr<RadioAction>::cast_dynamic (act);
960 if (ract->property_value() == val) {
961 ract->set_active (true);
962 inconsistent = false;
969 length_1_button.set_inconsistent (inconsistent);
970 length_2_button.set_inconsistent (inconsistent);
971 length_4_button.set_inconsistent (inconsistent);
972 length_8_button.set_inconsistent (inconsistent);
973 length_16_button.set_inconsistent (inconsistent);
974 length_32_button.set_inconsistent (inconsistent);
975 length_64_button.set_inconsistent (inconsistent);
977 se->set_step_edit_cursor_width (note_length());
981 StepEntry::radio_button_press (GdkEventButton* ev)
983 if (ev->button == 1) {
991 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
993 if (ev->button == 1) {
994 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
997 gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
1007 StepEntry::next_octave ()
1009 octave_adjustment.set_value (octave_adjustment.get_value() + 1.0);
1013 StepEntry::prev_octave ()
1015 octave_adjustment.set_value (octave_adjustment.get_value() - 1.0);
1019 StepEntry::inc_note_length ()
1021 length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() - 1.0);
1025 StepEntry::dec_note_length ()
1027 length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() + 1.0);
1031 StepEntry::prev_note_length ()
1033 double l = length_divisor_adjustment.get_value();
1034 int il = (int) lrintf (l); // round to nearest integer
1035 il = (il/2) * 2; // round to power of 2
1043 length_divisor_adjustment.set_value (il);
1047 StepEntry::next_note_length ()
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
1060 length_divisor_adjustment.set_value (il);
1065 StepEntry::inc_note_velocity ()
1067 velocity_adjustment.set_value (velocity_adjustment.get_value() + 1.0);
1071 StepEntry::dec_note_velocity ()
1073 velocity_adjustment.set_value (velocity_adjustment.get_value() - 1.0);
1077 StepEntry::next_note_velocity ()
1079 double l = velocity_adjustment.get_value ();
1083 } else if (l < 32) {
1085 } else if (l < 48) {
1087 } else if (l < 64) {
1089 } else if (l < 80) {
1091 } else if (l < 96) {
1093 } else if (l < 112) {
1095 } else if (l < 127) {
1099 velocity_adjustment.set_value (l);
1103 StepEntry::prev_note_velocity ()
1105 double l = velocity_adjustment.get_value ();
1109 } else if (l > 96) {
1111 } else if (l > 80) {
1113 } else if (l > 64) {
1115 } else if (l > 48) {
1117 } else if (l > 32) {
1119 } else if (l > 16) {
1125 velocity_adjustment.set_value (l);
1129 StepEntry::octave_n (int n)
1131 octave_adjustment.set_value (n);
1135 StepEntry::do_sustain ()
1137 se->step_edit_sustain (note_length());
1143 se->move_step_edit_beat_pos (-note_length());
1147 StepEntry::sync_to_edit_point ()
1149 se->resync_step_edit_to_edit_point ();