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 "widgets/tooltips.h"
29 #include "ardour/filesystem_paths.h"
31 #include "midi_channel_selector.h"
32 #include "midi_time_axis.h"
33 #include "step_editor.h"
34 #include "step_entry.h"
42 using namespace Gtkmm2ext;
44 using namespace ARDOUR;
45 using namespace ARDOUR_UI_UTILS;
46 using namespace ArdourWidgets;
49 _note_off_event_handler (GtkWidget* /*widget*/, int note, gpointer arg)
51 ((StepEntry*)arg)->note_off_event_handler (note);
55 _rest_event_handler (GtkWidget* /*widget*/, gpointer arg)
57 ((StepEntry*)arg)->rest_event_handler ();
60 StepEntry::StepEntry (StepEditor& seditor)
61 : ArdourWindow (string_compose (_("Step Entry: %1"), seditor.name()))
62 , ActionMapOwner (X_("step entry"))
63 , _current_note_length (1.0)
64 , _current_note_velocity (64)
65 , triplet_button ("3")
66 , dot_adjustment (0.0, 0.0, 3.0, 1.0, 1.0)
67 , beat_resync_button (_(">beat"))
68 , bar_resync_button (_(">bar"))
69 , resync_button (_(">EP"))
70 , sustain_button (_("sustain"))
71 , rest_button (_("rest"))
72 , grid_rest_button (_("g-rest"))
73 , back_button (_("back"))
74 , channel_adjustment (1, 1, 16, 1, 4)
75 , channel_spinner (channel_adjustment)
76 , octave_adjustment (4, 0, 10, 1, 4) // start in octave 4
77 , octave_spinner (octave_adjustment)
78 , length_divisor_adjustment (1.0, 1.0, 128, 1.0, 4.0)
79 , length_divisor_spinner (length_divisor_adjustment)
80 , velocity_adjustment (64.0, 0.0, 127.0, 1.0, 4.0)
81 , velocity_spinner (velocity_adjustment)
82 , bank_adjustment (0, 0.0, 127.0, 1.0, 4.0)
83 , bank_spinner (bank_adjustment)
84 , bank_button (_("+"))
85 , program_adjustment (0, 0.0, 127.0, 1.0, 4.0)
86 , program_spinner (program_adjustment)
87 , program_button (_("+"))
96 /* set channel selector to first selected channel. if none
97 are selected, it will remain at the value set in its
98 constructor, above (1)
101 uint16_t chn_mask = se->channel_selector().get_selected_channels();
103 for (uint32_t i = 0; i < 16; ++i) {
104 if (chn_mask & (1<<i)) {
105 channel_adjustment.set_value (i+1);
112 RadioButtonGroup length_group = length_1_button.get_group();
113 length_2_button.set_group (length_group);
114 length_4_button.set_group (length_group);
115 length_8_button.set_group (length_group);
116 length_12_button.set_group (length_group);
117 length_16_button.set_group (length_group);
118 length_32_button.set_group (length_group);
119 length_64_button.set_group (length_group);
123 w = manage (new Image (::get_icon (X_("wholenote"))));
125 length_1_button.add (*w);
126 w = manage (new Image (::get_icon (X_("halfnote"))));
128 length_2_button.add (*w);
129 w = manage (new Image (::get_icon (X_("quarternote"))));
131 length_4_button.add (*w);
132 w = manage (new Image (::get_icon (X_("eighthnote"))));
134 length_8_button.add (*w);
135 w = manage (new Image (::get_icon (X_("sixteenthnote"))));
137 length_16_button.add (*w);
138 w = manage (new Image (::get_icon (X_("thirtysecondnote"))));
140 length_32_button.add (*w);
141 w = manage (new Image (::get_icon (X_("sixtyfourthnote"))));
143 length_64_button.add (*w);
147 act = myactions.find_action ("StepEditing/note-length-whole");
148 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_1_button.gobj()), act->gobj());
149 act = myactions.find_action ("StepEditing/note-length-half");
150 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_2_button.gobj()), act->gobj());
151 act = myactions.find_action ("StepEditing/note-length-quarter");
152 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_4_button.gobj()), act->gobj());
153 act = myactions.find_action ("StepEditing/note-length-eighth");
154 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_8_button.gobj()), act->gobj());
155 act = myactions.find_action ("StepEditing/note-length-sixteenth");
156 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_16_button.gobj()), act->gobj());
157 act = myactions.find_action ("StepEditing/note-length-thirtysecond");
158 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_32_button.gobj()), act->gobj());
159 act = myactions.find_action ("StepEditing/note-length-sixtyfourth");
160 gtk_activatable_set_related_action (GTK_ACTIVATABLE (length_64_button.gobj()), act->gobj());
162 length_1_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
163 length_1_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 1), false);
164 length_2_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
165 length_2_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 2), false);
166 length_4_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
167 length_4_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 4), false);
168 length_8_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
169 length_8_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 8), false);
170 length_16_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
171 length_16_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 16), false);
172 length_32_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
173 length_32_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 32), false);
174 length_64_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
175 length_64_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &length_1_button, 64), false);
177 length_1_button.property_draw_indicator() = false;
178 length_2_button.property_draw_indicator() = false;
179 length_4_button.property_draw_indicator() = false;
180 length_8_button.property_draw_indicator() = false;
181 length_16_button.property_draw_indicator() = false;
182 length_32_button.property_draw_indicator() = false;
183 length_64_button.property_draw_indicator() = false;
185 note_length_box.pack_start (length_1_button, false, false);
186 note_length_box.pack_start (length_2_button, false, false);
187 note_length_box.pack_start (length_4_button, false, false);
188 note_length_box.pack_start (length_8_button, false, false);
189 note_length_box.pack_start (length_16_button, false, false);
190 note_length_box.pack_start (length_32_button, false, false);
191 note_length_box.pack_start (length_64_button, false, false);
193 set_tooltip (&length_1_button, _("Set note length to a whole note"), "");
194 set_tooltip (&length_2_button, _("Set note length to a half note"), "");
195 set_tooltip (&length_4_button, _("Set note length to a quarter note"), "");
196 set_tooltip (&length_8_button, _("Set note length to a eighth note"), "");
197 set_tooltip (&length_16_button, _("Set note length to a sixteenth note"), "");
198 set_tooltip (&length_32_button, _("Set note length to a thirty-second note"), "");
199 set_tooltip (&length_64_button, _("Set note length to a sixty-fourth note"), "");
201 RadioButtonGroup velocity_group = velocity_ppp_button.get_group();
202 velocity_pp_button.set_group (velocity_group);
203 velocity_p_button.set_group (velocity_group);
204 velocity_mp_button.set_group (velocity_group);
205 velocity_mf_button.set_group (velocity_group);
206 velocity_f_button.set_group (velocity_group);
207 velocity_ff_button.set_group (velocity_group);
208 velocity_fff_button.set_group (velocity_group);
210 w = manage (new Image (::get_icon (X_("pianississimo"))));
212 velocity_ppp_button.add (*w);
213 w = manage (new Image (::get_icon (X_("pianissimo"))));
215 velocity_pp_button.add (*w);
216 w = manage (new Image (::get_icon (X_("piano"))));
218 velocity_p_button.add (*w);
219 w = manage (new Image (::get_icon (X_("mezzopiano"))));
221 velocity_mp_button.add (*w);
222 w = manage (new Image (::get_icon (X_("mezzoforte"))));
224 velocity_mf_button.add (*w);
225 w = manage (new Image (::get_icon (X_("forte"))));
227 velocity_f_button.add (*w);
228 w = manage (new Image (::get_icon (X_("fortissimo"))));
230 velocity_ff_button.add (*w);
231 w = manage (new Image (::get_icon (X_("fortississimo"))));
233 velocity_fff_button.add (*w);
235 act = myactions.find_action ("StepEditing/note-velocity-ppp");
236 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ppp_button.gobj()), act->gobj());
237 act = myactions.find_action ("StepEditing/note-velocity-pp");
238 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_pp_button.gobj()), act->gobj());
239 act = myactions.find_action ("StepEditing/note-velocity-p");
240 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_p_button.gobj()), act->gobj());
241 act = myactions.find_action ("StepEditing/note-velocity-mp");
242 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mp_button.gobj()), act->gobj());
243 act = myactions.find_action ("StepEditing/note-velocity-mf");
244 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_mf_button.gobj()), act->gobj());
245 act = myactions.find_action ("StepEditing/note-velocity-f");
246 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_f_button.gobj()), act->gobj());
247 act = myactions.find_action ("StepEditing/note-velocity-ff");
248 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_ff_button.gobj()), act->gobj());
249 act = myactions.find_action ("StepEditing/note-velocity-fff");
250 gtk_activatable_set_related_action (GTK_ACTIVATABLE (velocity_fff_button.gobj()), act->gobj());
252 velocity_ppp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
253 velocity_ppp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ppp_button, 1), false);
254 velocity_pp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
255 velocity_pp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_pp_button, 16), false);
256 velocity_p_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
257 velocity_p_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_p_button, 32), false);
258 velocity_mp_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
259 velocity_mp_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mp_button, 64), false);
260 velocity_mf_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
261 velocity_mf_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_mf_button, 80), false);
262 velocity_f_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
263 velocity_f_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_f_button, 96), false);
264 velocity_ff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
265 velocity_ff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_ff_button, 112), false);
266 velocity_fff_button.signal_button_press_event().connect (sigc::mem_fun (*this, &StepEntry::radio_button_press), false);
267 velocity_fff_button.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &StepEntry::radio_button_release), &velocity_fff_button, 127), false);
269 velocity_ppp_button.property_draw_indicator() = false;
270 velocity_pp_button.property_draw_indicator() = false;
271 velocity_p_button.property_draw_indicator() = false;
272 velocity_mp_button.property_draw_indicator() = false;
273 velocity_mf_button.property_draw_indicator() = false;
274 velocity_f_button.property_draw_indicator() = false;
275 velocity_ff_button.property_draw_indicator() = false;
276 velocity_fff_button.property_draw_indicator() = false;
278 set_tooltip (&velocity_ppp_button, _("Set volume (velocity) to pianississimo"), "");
279 set_tooltip (&velocity_pp_button, _("Set volume (velocity) to pianissimo"), "");
280 set_tooltip (&velocity_p_button, _("Set volume (velocity) to piano"), "");
281 set_tooltip (&velocity_mp_button, _("Set volume (velocity) to mezzo-piano"), "");
282 set_tooltip (&velocity_mf_button, _("Set volume (velocity) to mezzo-forte"), "");
283 set_tooltip (&velocity_f_button, _("Set volume (velocity) to forte"), "");
284 set_tooltip (&velocity_ff_button, _("Set volume (velocity) to fortissimo"), "");
285 set_tooltip (&velocity_fff_button, _("Set volume (velocity) to fortississimo"), "");
287 note_velocity_box.pack_start (velocity_ppp_button, false, false);
288 note_velocity_box.pack_start (velocity_pp_button, false, false);
289 note_velocity_box.pack_start (velocity_p_button, false, false);
290 note_velocity_box.pack_start (velocity_mp_button, false, false);
291 note_velocity_box.pack_start (velocity_mf_button, false, false);
292 note_velocity_box.pack_start (velocity_f_button, false, false);
293 note_velocity_box.pack_start (velocity_ff_button, false, false);
294 note_velocity_box.pack_start (velocity_fff_button, false, false);
296 Label* l = manage (new Label);
297 l->set_markup ("<b><big>-</big></b>");
299 dot0_button.add (*l);
301 l = manage (new Label);
302 l->set_markup ("<b><big>.</big></b>");
304 dot1_button.add (*l);
306 l = manage (new Label);
307 l->set_markup ("<b><big>..</big></b>");
309 dot2_button.add (*l);
311 l = manage (new Label);
312 l->set_markup ("<b><big>...</big></b>");
314 dot3_button.add (*l);
316 w = manage (new Image (::get_icon (X_("chord"))));
318 chord_button.add (*w);
320 dot_box1.pack_start (dot0_button, true, false);
321 dot_box1.pack_start (dot1_button, true, false);
322 dot_box2.pack_start (dot2_button, true, false);
323 dot_box2.pack_start (dot3_button, true, false);
325 rest_box.pack_start (rest_button, true, false);
326 rest_box.pack_start (grid_rest_button, true, false);
327 rest_box.pack_start (back_button, true, false);
329 resync_box.pack_start (beat_resync_button, true, false);
330 resync_box.pack_start (bar_resync_button, true, false);
331 resync_box.pack_start (resync_button, true, false);
333 set_tooltip (&chord_button, _("Stack inserted notes to form a chord"), "");
334 set_tooltip (&sustain_button, _("Extend selected notes by note length"), "");
335 set_tooltip (&dot0_button, _("Use undotted note lengths"), "");
336 set_tooltip (&dot1_button, _("Use dotted (* 1.5) note lengths"), "");
337 set_tooltip (&dot2_button, _("Use double-dotted (* 1.75) note lengths"), "");
338 set_tooltip (&dot3_button, _("Use triple-dotted (* 1.875) note lengths"), "");
339 set_tooltip (&rest_button, _("Insert a note-length's rest"), "");
340 set_tooltip (&grid_rest_button, _("Insert a grid-unit's rest"), "");
341 set_tooltip (&beat_resync_button, _("Insert a rest until the next beat"), "");
342 set_tooltip (&bar_resync_button, _("Insert a rest until the next bar"), "");
343 set_tooltip (&bank_button, _("Insert a bank change message"), "");
344 set_tooltip (&program_button, _("Insert a program change message"), "");
345 set_tooltip (&back_button, _("Move Insert Position Back by Note Length"), "");
346 set_tooltip (&resync_button, _("Move Insert Position to Edit Point"), "");
348 act = myactions.find_action ("StepEditing/back");
349 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (back_button.gobj()), false);
350 gtk_activatable_set_related_action (GTK_ACTIVATABLE (back_button.gobj()), act->gobj());
351 act = myactions.find_action ("StepEditing/sync-to-edit-point");
352 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (resync_button.gobj()), false);
353 gtk_activatable_set_related_action (GTK_ACTIVATABLE (resync_button.gobj()), act->gobj());
354 act = myactions.find_action ("StepEditing/toggle-triplet");
355 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (triplet_button.gobj()), false);
356 gtk_activatable_set_related_action (GTK_ACTIVATABLE (triplet_button.gobj()), act->gobj());
357 act = myactions.find_action ("StepEditing/no-dotted");
358 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot0_button.gobj()), false);
359 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot0_button.gobj()), act->gobj());
360 act = myactions.find_action ("StepEditing/toggle-dotted");
361 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot1_button.gobj()), false);
362 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot1_button.gobj()), act->gobj());
363 act = myactions.find_action ("StepEditing/toggle-double-dotted");
364 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot2_button.gobj()), false);
365 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot2_button.gobj()), act->gobj());
366 act = myactions.find_action ("StepEditing/toggle-triple-dotted");
367 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (dot3_button.gobj()), false);
368 gtk_activatable_set_related_action (GTK_ACTIVATABLE (dot3_button.gobj()), act->gobj());
369 act = myactions.find_action ("StepEditing/toggle-chord");
370 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (chord_button.gobj()), false);
371 gtk_activatable_set_related_action (GTK_ACTIVATABLE (chord_button.gobj()), act->gobj());
372 act = myactions.find_action ("StepEditing/insert-rest");
373 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (rest_button.gobj()), false);
374 gtk_activatable_set_related_action (GTK_ACTIVATABLE (rest_button.gobj()), act->gobj());
375 act = myactions.find_action ("StepEditing/insert-snap-rest");
376 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (grid_rest_button.gobj()), false);
377 gtk_activatable_set_related_action (GTK_ACTIVATABLE (grid_rest_button.gobj()), act->gobj());
378 act = myactions.find_action ("StepEditing/sustain");
379 gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (sustain_button.gobj()), false);
380 gtk_activatable_set_related_action (GTK_ACTIVATABLE (sustain_button.gobj()), act->gobj());
382 upper_box.set_spacing (6);
383 upper_box.pack_start (chord_button, false, false);
384 upper_box.pack_start (note_length_box, false, false, 12);
385 upper_box.pack_start (triplet_button, false, false);
386 upper_box.pack_start (dot_box1, false, false);
387 upper_box.pack_start (dot_box2, false, false);
388 upper_box.pack_start (sustain_button, false, false);
389 upper_box.pack_start (rest_box, false, false);
390 upper_box.pack_start (resync_box, false, false);
391 upper_box.pack_start (note_velocity_box, false, false, 12);
395 v = manage (new VBox);
396 l = manage (new Label (_("Channel")));
398 v->pack_start (*l, false, false);
399 v->pack_start (channel_spinner, false, false);
400 upper_box.pack_start (*v, false, false);
402 v = manage (new VBox);
403 l = manage (new Label (_("1/Note")));
405 v->pack_start (*l, false, false);
406 v->pack_start (length_divisor_spinner, false, false);
407 upper_box.pack_start (*v, false, false);
409 v = manage (new VBox);
410 l = manage (new Label (_("Velocity")));
412 v->pack_start (*l, false, false);
413 v->pack_start (velocity_spinner, false, false);
414 upper_box.pack_start (*v, false, false);
416 v = manage (new VBox);
417 l = manage (new Label (_("Octave")));
419 v->pack_start (*l, false, false);
420 v->pack_start (octave_spinner, false, false);
421 upper_box.pack_start (*v, false, false);
423 v = manage (new VBox);
424 l = manage (new Label (_("Bank")));
426 v->pack_start (*l, false, false);
427 v->pack_start (bank_spinner, false, false);
428 v->pack_start (bank_button, false, false);
429 upper_box.pack_start (*v, false, false);
431 v = manage (new VBox);
432 l = manage (new Label (_("Program")));
434 v->pack_start (*l, false, false);
435 v->pack_start (program_spinner, false, false);
436 v->pack_start (program_button, false, false);
437 upper_box.pack_start (*v, false, false);
439 velocity_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::velocity_value_change));
440 length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_value_change));
441 dot_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::dot_value_change));
443 _piano = (PianoKeyboard*) piano_keyboard_new ();
444 piano = wrap ((GtkWidget*) _piano);
446 piano->set_flags (Gtk::CAN_FOCUS);
448 g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
449 g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
451 program_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::program_click));
452 bank_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bank_click));
453 beat_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::beat_resync_click));
454 bar_resync_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::bar_resync_click));
456 length_divisor_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &StepEntry::length_changed));
458 packer.set_spacing (6);
459 packer.pack_start (upper_box, false, false);
460 packer.pack_start (*piano, false, false);
465 /* initial settings: quarter note and mezzo forte */
467 act = myactions.find_action ("StepEditing/note-length-quarter");
468 RefPtr<RadioAction> r = RefPtr<RadioAction>::cast_dynamic (act);
470 r->set_active (true);
472 act = myactions.find_action ("StepEditing/note-velocity-mf");
473 r = RefPtr<RadioAction>::cast_dynamic (act);
475 r->set_active (true);
478 StepEntry::~StepEntry()
483 StepEntry::length_changed ()
485 length_1_button.queue_draw ();
486 length_2_button.queue_draw ();
487 length_4_button.queue_draw ();
488 length_8_button.queue_draw ();
489 length_16_button.queue_draw ();
490 length_32_button.queue_draw ();
491 length_64_button.queue_draw ();
495 StepEntry::on_key_press_event (GdkEventKey* ev)
497 /* focus widget gets first shot, then bindings, otherwise
498 forward to main window
501 if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
505 return relay_key_press (ev, this);
509 StepEntry::on_key_release_event (GdkEventKey* ev)
511 if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
515 /* don't forward releases */
521 StepEntry::rest_event_handler ()
523 se->step_edit_rest (Temporal::Beats());
527 StepEntry::note_length ()
529 double base_time = 4.0 / (double) length_divisor_adjustment.get_value();
531 RefPtr<Action> act = myactions.find_action ("StepEditing/toggle-triplet");
532 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
533 bool triplets = tact->get_active ();
536 base_time *= (2.0/3.0);
539 double dots = dot_adjustment.get_value ();
542 dots = pow (2.0, dots);
543 base_time *= 1 + ((dots - 1.0)/dots);
546 return Temporal::Beats(base_time);
550 StepEntry::note_velocity () const
552 return velocity_adjustment.get_value();
556 StepEntry::note_channel() const
558 return channel_adjustment.get_value() - 1;
562 StepEntry::note_off_event_handler (int note)
569 StepEntry::on_show ()
571 ArdourWindow::on_show ();
572 //piano->grab_focus ();
576 StepEntry::beat_resync_click ()
578 se->step_edit_beat_sync ();
582 StepEntry::bar_resync_click ()
584 se->step_edit_bar_sync ();
588 StepEntry::register_actions ()
590 /* add named actions for the step editor */
592 Glib::RefPtr<ActionGroup> group = myactions.create_action_group (X_("StepEditing"));
594 myactions.register_action (group, "insert-a", _("Insert Note A"), sigc::mem_fun (*this, &StepEntry::insert_a));
595 myactions.register_action (group, "insert-asharp", _("Insert Note A-sharp"), sigc::mem_fun (*this, &StepEntry::insert_asharp));
596 myactions.register_action (group, "insert-b", _("Insert Note B"), sigc::mem_fun (*this, &StepEntry::insert_b));
597 myactions.register_action (group, "insert-c", _("Insert Note C"), sigc::mem_fun (*this, &StepEntry::insert_c));
598 myactions.register_action (group, "insert-csharp", _("Insert Note C-sharp"), sigc::mem_fun (*this, &StepEntry::insert_csharp));
599 myactions.register_action (group, "insert-d", _("Insert Note D"), sigc::mem_fun (*this, &StepEntry::insert_d));
600 myactions.register_action (group, "insert-dsharp", _("Insert Note D-sharp"), sigc::mem_fun (*this, &StepEntry::insert_dsharp));
601 myactions.register_action (group, "insert-e", _("Insert Note E"), sigc::mem_fun (*this, &StepEntry::insert_e));
602 myactions.register_action (group, "insert-f", _("Insert Note F"), sigc::mem_fun (*this, &StepEntry::insert_f));
603 myactions.register_action (group, "insert-fsharp", _("Insert Note F-sharp"), sigc::mem_fun (*this, &StepEntry::insert_fsharp));
604 myactions.register_action (group, "insert-g", _("Insert Note G"), sigc::mem_fun (*this, &StepEntry::insert_g));
605 myactions.register_action (group, "insert-gsharp", _("Insert Note G-sharp"), sigc::mem_fun (*this, &StepEntry::insert_gsharp));
607 myactions.register_action (group, "insert-rest", _("Insert a Note-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_rest));
608 myactions.register_action (group, "insert-snap-rest", _("Insert a Snap-length Rest"), sigc::mem_fun (*this, &StepEntry::insert_grid_rest));
610 myactions.register_action (group, "next-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::next_octave));
611 myactions.register_action (group, "prev-octave", _("Move to next octave"), sigc::mem_fun (*this, &StepEntry::prev_octave));
613 myactions.register_action (group, "next-note-length", _("Move to Next Note Length"), sigc::mem_fun (*this, &StepEntry::next_note_length));
614 myactions.register_action (group, "prev-note-length", _("Move to Previous Note Length"), sigc::mem_fun (*this, &StepEntry::prev_note_length));
616 myactions.register_action (group, "inc-note-length", _("Increase Note Length"), sigc::mem_fun (*this, &StepEntry::inc_note_length));
617 myactions.register_action (group, "dec-note-length", _("Decrease Note Length"), sigc::mem_fun (*this, &StepEntry::dec_note_length));
619 myactions.register_action (group, "next-note-velocity", _("Move to Next Note Velocity"), sigc::mem_fun (*this, &StepEntry::next_note_velocity));
620 myactions.register_action (group, "prev-note-velocity", _("Move to Previous Note Velocity"), sigc::mem_fun (*this, &StepEntry::prev_note_velocity));
622 myactions.register_action (group, "inc-note-velocity", _("Increase Note Velocity"), sigc::mem_fun (*this, &StepEntry::inc_note_velocity));
623 myactions.register_action (group, "dec-note-velocity", _("Decrease Note Velocity"), sigc::mem_fun (*this, &StepEntry::dec_note_velocity));
625 myactions.register_action (group, "octave-0", _("Switch to the 1st octave"), sigc::mem_fun (*this, &StepEntry::octave_0));
626 myactions.register_action (group, "octave-1", _("Switch to the 2nd octave"), sigc::mem_fun (*this, &StepEntry::octave_1));
627 myactions.register_action (group, "octave-2", _("Switch to the 3rd octave"), sigc::mem_fun (*this, &StepEntry::octave_2));
628 myactions.register_action (group, "octave-3", _("Switch to the 4th octave"), sigc::mem_fun (*this, &StepEntry::octave_3));
629 myactions.register_action (group, "octave-4", _("Switch to the 5th octave"), sigc::mem_fun (*this, &StepEntry::octave_4));
630 myactions.register_action (group, "octave-5", _("Switch to the 6th octave"), sigc::mem_fun (*this, &StepEntry::octave_5));
631 myactions.register_action (group, "octave-6", _("Switch to the 7th octave"), sigc::mem_fun (*this, &StepEntry::octave_6));
632 myactions.register_action (group, "octave-7", _("Switch to the 8th octave"), sigc::mem_fun (*this, &StepEntry::octave_7));
633 myactions.register_action (group, "octave-8", _("Switch to the 9th octave"), sigc::mem_fun (*this, &StepEntry::octave_8));
634 myactions.register_action (group, "octave-9", _("Switch to the 10th octave"), sigc::mem_fun (*this, &StepEntry::octave_9));
635 myactions.register_action (group, "octave-10", _("Switch to the 11th octave"), sigc::mem_fun (*this, &StepEntry::octave_10));
637 myactions.register_toggle_action (group, "toggle-triplet", _("Toggle Triple Notes"),
638 sigc::mem_fun (*this, &StepEntry::toggle_triplet));
640 myactions.register_toggle_action (group, "toggle-chord", _("Toggle Chord Entry"),
641 sigc::mem_fun (*this, &StepEntry::toggle_chord));
642 myactions.register_action (group, "sustain", _("Sustain Selected Notes by Note Length"),
643 sigc::mem_fun (*this, &StepEntry::do_sustain));
645 myactions.register_action (group, "sync-to-edit-point", _("Move Insert Position to Edit Point"),
646 sigc::mem_fun (*this, &StepEntry::sync_to_edit_point));
647 myactions.register_action (group, "back", _("Move Insert Position Back by Note Length"),
648 sigc::mem_fun (*this, &StepEntry::back));
649 RadioAction::Group note_length_group;
651 myactions.register_radio_action (group, note_length_group, "note-length-whole",
652 _("Set Note Length to Whole"), sigc::mem_fun (*this, &StepEntry::note_length_change), 1);
653 myactions.register_radio_action (group, note_length_group, "note-length-half",
654 _("Set Note Length to 1/2"), sigc::mem_fun (*this, &StepEntry::note_length_change), 2);
655 myactions.register_radio_action (group, note_length_group, "note-length-third",
656 _("Set Note Length to 1/3"), sigc::mem_fun (*this, &StepEntry::note_length_change), 3);
657 myactions.register_radio_action (group, note_length_group, "note-length-quarter",
658 _("Set Note Length to 1/4"), sigc::mem_fun (*this, &StepEntry::note_length_change), 4);
659 myactions.register_radio_action (group, note_length_group, "note-length-eighth",
660 _("Set Note Length to 1/8"), sigc::mem_fun (*this, &StepEntry::note_length_change), 8);
661 myactions.register_radio_action (group, note_length_group, "note-length-sixteenth",
662 _("Set Note Length to 1/16"), sigc::mem_fun (*this, &StepEntry::note_length_change), 16);
663 myactions.register_radio_action (group, note_length_group, "note-length-thirtysecond",
664 _("Set Note Length to 1/32"), sigc::mem_fun (*this, &StepEntry::note_length_change), 32);
665 myactions.register_radio_action (group, note_length_group, "note-length-sixtyfourth",
666 _("Set Note Length to 1/64"), sigc::mem_fun (*this, &StepEntry::note_length_change), 64);
668 RadioAction::Group note_velocity_group;
670 myactions.register_radio_action (group, note_velocity_group, "note-velocity-ppp",
671 _("Set Note Velocity to Pianississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 1);
672 myactions.register_radio_action (group, note_velocity_group, "note-velocity-pp",
673 _("Set Note Velocity to Pianissimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 16);
674 myactions.register_radio_action (group, note_velocity_group, "note-velocity-p",
675 _("Set Note Velocity to Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 32);
676 myactions.register_radio_action (group, note_velocity_group, "note-velocity-mp",
677 _("Set Note Velocity to Mezzo-Piano"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 64);
678 myactions.register_radio_action (group, note_velocity_group, "note-velocity-mf",
679 _("Set Note Velocity to Mezzo-Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 80);
680 myactions.register_radio_action (group, note_velocity_group, "note-velocity-f",
681 _("Set Note Velocity to Forte"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 96);
682 myactions.register_radio_action (group, note_velocity_group, "note-velocity-ff",
683 _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 112);
684 myactions.register_radio_action (group, note_velocity_group, "note-velocity-fff",
685 _("Set Note Velocity to Fortississimo"), sigc::mem_fun (*this, &StepEntry::note_velocity_change), 127);
688 RadioAction::Group dot_group;
690 myactions.register_radio_action (group, dot_group, "no-dotted", _("No Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 0);
691 myactions.register_radio_action (group, dot_group, "toggle-dotted", _("Toggled Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 1);
692 myactions.register_radio_action (group, dot_group, "toggle-double-dotted", _("Toggled Double-Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 2);
693 myactions.register_radio_action (group, dot_group, "toggle-triple-dotted", _("Toggled Triple-Dotted Notes"), sigc::mem_fun (*this, &StepEntry::dot_change), 3);
697 StepEntry::load_bindings ()
699 bindings = Bindings::get_bindings (X_("Step Editing"), myactions);
700 set_data ("ardour-bindings", bindings);
704 StepEntry::toggle_triplet ()
706 se->set_step_edit_cursor_width (note_length());
710 StepEntry::toggle_chord ()
712 se->step_edit_toggle_chord ();
716 StepEntry::dot_change (GtkAction* act)
718 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
719 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
720 dot_adjustment.set_value (v);
725 StepEntry::dot_value_change ()
728 RefPtr<RadioAction> ract;
729 double val = dot_adjustment.get_value();
730 bool inconsistent = true;
731 vector<const char*> dot_actions;
733 dot_actions.push_back ("StepEditing/no-dotted");
734 dot_actions.push_back ("StepEditing/toggle-dotted");
735 dot_actions.push_back ("StepEditing/toggle-double-dotted");
736 dot_actions.push_back ("StepEditing/toggle-triple-dotted");
738 for (vector<const char*>::iterator i = dot_actions.begin(); i != dot_actions.end(); ++i) {
740 act = myactions.find_action (*i);
743 ract = RefPtr<RadioAction>::cast_dynamic (act);
746 if (ract->property_value() == val) {
747 ract->set_active (true);
748 inconsistent = false;
755 dot1_button.set_inconsistent (inconsistent);
756 dot2_button.set_inconsistent (inconsistent);
757 dot3_button.set_inconsistent (inconsistent);
759 se->set_step_edit_cursor_width (note_length());
763 StepEntry::program_click ()
765 se->step_add_program_change (note_channel(), (int8_t) floor (program_adjustment.get_value()));
769 StepEntry::bank_click ()
771 se->step_add_bank_change (note_channel(), (int8_t) floor (bank_adjustment.get_value()));
775 StepEntry::insert_rest ()
777 se->step_edit_rest (note_length());
781 StepEntry::insert_grid_rest ()
783 se->step_edit_rest (Temporal::Beats());
787 StepEntry::insert_note (uint8_t note)
793 se->step_add_note (note_channel(), note, note_velocity(), note_length());
796 StepEntry::insert_c ()
798 insert_note (0 + (current_octave() * 12));
801 StepEntry::insert_csharp ()
803 insert_note (1 + (current_octave() * 12));
806 StepEntry::insert_d ()
808 insert_note (2 + (current_octave() * 12));
811 StepEntry::insert_dsharp ()
813 insert_note (3 + (current_octave() * 12));
816 StepEntry::insert_e ()
818 insert_note (4 + (current_octave() * 12));
821 StepEntry::insert_f ()
823 insert_note (5 + (current_octave() * 12));
826 StepEntry::insert_fsharp ()
828 insert_note (6 + (current_octave() * 12));
831 StepEntry::insert_g ()
833 insert_note (7 + (current_octave() * 12));
836 StepEntry::insert_gsharp ()
838 insert_note (8 + (current_octave() * 12));
842 StepEntry::insert_a ()
844 insert_note (9 + (current_octave() * 12));
848 StepEntry::insert_asharp ()
850 insert_note (10 + (current_octave() * 12));
853 StepEntry::insert_b ()
855 insert_note (11 + (current_octave() * 12));
859 StepEntry::note_length_change (GtkAction* act)
861 /* it doesn't matter which note length action we look up - we are interested
862 in the current_value which is global across the whole group of note length
863 actions. this method is called twice for every user operation,
864 once for the action that became "inactive" and once for the action that
865 becaome "active". so ... only bother to actually change the value when this
866 is called for the "active" action.
869 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
870 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
871 length_divisor_adjustment.set_value (v);
876 StepEntry::note_velocity_change (GtkAction* act)
878 /* it doesn't matter which note length action we look up - we are interested
879 in the current_value which is global across the whole group of note length
880 actions. this method is called twice for every user operation,
881 once for the action that became "inactive" and once for the action that
882 becaome "active". so ... only bother to actually change the value when this
883 is called for the "active" action.
886 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(act))) {
887 gint v = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (act));
888 velocity_adjustment.set_value (v);
893 StepEntry::velocity_value_change ()
896 RefPtr<RadioAction> ract;
897 double val = velocity_adjustment.get_value();
898 bool inconsistent = true;
899 vector<const char*> velocity_actions;
901 velocity_actions.push_back ("StepEditing/note-velocity-ppp");
902 velocity_actions.push_back ("StepEditing/note-velocity-pp");
903 velocity_actions.push_back ("StepEditing/note-velocity-p");
904 velocity_actions.push_back ("StepEditing/note-velocity-mp");
905 velocity_actions.push_back ("StepEditing/note-velocity-mf");
906 velocity_actions.push_back ("StepEditing/note-velocity-f");
907 velocity_actions.push_back ("StepEditing/note-velocity-ff");
908 velocity_actions.push_back ("StepEditing/note-velocity-fff");
910 for (vector<const char*>::iterator i = velocity_actions.begin(); i != velocity_actions.end(); ++i) {
912 act = myactions.find_action (*i);
915 ract = RefPtr<RadioAction>::cast_dynamic (act);
918 if (ract->property_value() == val) {
919 ract->set_active (true);
920 inconsistent = false;
927 velocity_ppp_button.set_inconsistent (inconsistent);
928 velocity_pp_button.set_inconsistent (inconsistent);
929 velocity_p_button.set_inconsistent (inconsistent);
930 velocity_mp_button.set_inconsistent (inconsistent);
931 velocity_mf_button.set_inconsistent (inconsistent);
932 velocity_f_button.set_inconsistent (inconsistent);
933 velocity_ff_button.set_inconsistent (inconsistent);
934 velocity_fff_button.set_inconsistent (inconsistent);
938 StepEntry::length_value_change ()
941 RefPtr<RadioAction> ract;
942 double val = length_divisor_adjustment.get_value();
943 bool inconsistent = true;
944 vector<const char*> length_actions;
946 length_actions.push_back ("StepEditing/note-length-whole");
947 length_actions.push_back ("StepEditing/note-length-half");
948 length_actions.push_back ("StepEditing/note-length-quarter");
949 length_actions.push_back ("StepEditing/note-length-eighth");
950 length_actions.push_back ("StepEditing/note-length-sixteenth");
951 length_actions.push_back ("StepEditing/note-length-thirtysecond");
952 length_actions.push_back ("StepEditing/note-length-sixtyfourth");
954 for (vector<const char*>::iterator i = length_actions.begin(); i != length_actions.end(); ++i) {
956 act = myactions.find_action (*i);
959 ract = RefPtr<RadioAction>::cast_dynamic (act);
962 if (ract->property_value() == val) {
963 ract->set_active (true);
964 inconsistent = false;
971 length_1_button.set_inconsistent (inconsistent);
972 length_2_button.set_inconsistent (inconsistent);
973 length_4_button.set_inconsistent (inconsistent);
974 length_8_button.set_inconsistent (inconsistent);
975 length_16_button.set_inconsistent (inconsistent);
976 length_32_button.set_inconsistent (inconsistent);
977 length_64_button.set_inconsistent (inconsistent);
979 se->set_step_edit_cursor_width (note_length());
983 StepEntry::radio_button_press (GdkEventButton* ev)
985 if (ev->button == 1) {
993 StepEntry::radio_button_release (GdkEventButton* ev, RadioButton* btn, int v)
995 if (ev->button == 1) {
996 GtkAction* act = gtk_activatable_get_related_action (GTK_ACTIVATABLE (btn->gobj()));
999 gtk_radio_action_set_current_value (GTK_RADIO_ACTION(act), v);
1009 StepEntry::next_octave ()
1011 octave_adjustment.set_value (octave_adjustment.get_value() + 1.0);
1015 StepEntry::prev_octave ()
1017 octave_adjustment.set_value (octave_adjustment.get_value() - 1.0);
1021 StepEntry::inc_note_length ()
1023 length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() - 1.0);
1027 StepEntry::dec_note_length ()
1029 length_divisor_adjustment.set_value (length_divisor_adjustment.get_value() + 1.0);
1033 StepEntry::prev_note_length ()
1035 double l = length_divisor_adjustment.get_value();
1036 int il = (int) lrintf (l); // round to nearest integer
1037 il = (il/2) * 2; // round to power of 2
1045 length_divisor_adjustment.set_value (il);
1049 StepEntry::next_note_length ()
1051 double l = length_divisor_adjustment.get_value();
1052 int il = (int) lrintf (l); // round to nearest integer
1053 il = (il/2) * 2; // round to power of 2
1062 length_divisor_adjustment.set_value (il);
1067 StepEntry::inc_note_velocity ()
1069 velocity_adjustment.set_value (velocity_adjustment.get_value() + 1.0);
1073 StepEntry::dec_note_velocity ()
1075 velocity_adjustment.set_value (velocity_adjustment.get_value() - 1.0);
1079 StepEntry::next_note_velocity ()
1081 double l = velocity_adjustment.get_value ();
1085 } else if (l < 32) {
1087 } else if (l < 48) {
1089 } else if (l < 64) {
1091 } else if (l < 80) {
1093 } else if (l < 96) {
1095 } else if (l < 112) {
1097 } else if (l < 127) {
1101 velocity_adjustment.set_value (l);
1105 StepEntry::prev_note_velocity ()
1107 double l = velocity_adjustment.get_value ();
1111 } else if (l > 96) {
1113 } else if (l > 80) {
1115 } else if (l > 64) {
1117 } else if (l > 48) {
1119 } else if (l > 32) {
1121 } else if (l > 16) {
1127 velocity_adjustment.set_value (l);
1131 StepEntry::octave_n (int n)
1133 octave_adjustment.set_value (n);
1137 StepEntry::do_sustain ()
1139 se->step_edit_sustain (note_length());
1145 se->move_step_edit_beat_pos (-note_length());
1149 StepEntry::sync_to_edit_point ()
1151 se->resync_step_edit_to_edit_point ();