properly track step edit status in editor & mixer windows
[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 "gtkmm2ext/keyboard.h"
23
24 #include "midi_time_axis.h"
25 #include "step_entry.h"
26 #include "utils.h"
27
28 #include "i18n.h"
29
30 using namespace Gtk;
31
32 static void
33 _note_off_event_handler (GtkWidget* widget, int note, gpointer arg)
34 {
35         ((StepEntry*)arg)->note_off_event_handler (note);
36 }
37
38 static void
39 _rest_event_handler (GtkWidget* widget, gpointer arg)
40 {
41         ((StepEntry*)arg)->rest_event_handler ();
42 }
43
44 StepEntry::StepEntry (MidiTimeAxisView& mtv)
45         : ArdourDialog (string_compose (_("Step Entry: %1"), mtv.name()))
46         , triplet_button ("3")
47         , sustain_button ("sustain")
48         , rest_button ("rest")
49         , channel_adjustment (0, 15, 0, 1, 4)
50         , channel_spinner (channel_adjustment)
51         , _piano (0)
52         , piano (0)
53         , _mtv (&mtv)
54 {
55         RadioButtonGroup length_group = length_1_button.get_group();
56         length_2_button.set_group (length_group);
57         length_4_button.set_group (length_group);
58         length_8_button.set_group (length_group);
59         length_12_button.set_group (length_group);
60         length_16_button.set_group (length_group);
61         length_32_button.set_group (length_group);
62         length_64_button.set_group (length_group);
63
64         Widget* w;
65
66         w = manage (new Image (::get_icon (X_("wholenote"))));
67         w->show();
68         length_1_button.add (*w);
69         w = manage (new Image (::get_icon (X_("halfnote"))));
70         w->show();
71         length_2_button.add (*w);
72         w = manage (new Image (::get_icon (X_("quarternote"))));
73         w->show();
74         length_4_button.add (*w);
75         w = manage (new Image (::get_icon (X_("eighthnote"))));
76         w->show();
77         length_8_button.add (*w);
78         w = manage (new Image (::get_icon (X_("sixteenthnote"))));
79         w->show();
80         length_16_button.add (*w);
81         w = manage (new Image (::get_icon (X_("thirtysecondnote"))));
82         w->show();
83         length_32_button.add (*w);
84         w = manage (new Image (::get_icon (X_("sixtyfourthnote"))));
85         w->show();
86         length_64_button.add (*w);
87
88         length_1_button.property_draw_indicator() = false;
89         length_2_button.property_draw_indicator() = false;
90         length_4_button.property_draw_indicator() = false;
91         length_8_button.property_draw_indicator() = false;
92         length_16_button.property_draw_indicator() = false;
93         length_32_button.property_draw_indicator() = false;
94         length_64_button.property_draw_indicator() = false;
95
96         note_length_box.pack_start (length_1_button, false, false);
97         note_length_box.pack_start (length_2_button, false, false);
98         note_length_box.pack_start (length_4_button, false, false);
99         note_length_box.pack_start (length_8_button, false, false);
100         note_length_box.pack_start (length_16_button, false, false);
101         note_length_box.pack_start (length_32_button, false, false);
102         note_length_box.pack_start (length_64_button, false, false);
103
104         RadioButtonGroup velocity_group = velocity_ppp_button.get_group();
105         velocity_pp_button.set_group (velocity_group);
106         velocity_p_button.set_group (velocity_group);
107         velocity_mp_button.set_group (velocity_group);
108         velocity_mf_button.set_group (velocity_group);
109         velocity_f_button.set_group (velocity_group);
110         velocity_ff_button.set_group (velocity_group);
111         velocity_fff_button.set_group (velocity_group);
112
113         w = manage (new Image (::get_icon (X_("pianississimo"))));
114         w->show();
115         velocity_ppp_button.add (*w);
116         w = manage (new Image (::get_icon (X_("pianissimo"))));
117         w->show();
118         velocity_pp_button.add (*w);
119         w = manage (new Image (::get_icon (X_("piano"))));
120         w->show();
121         velocity_p_button.add (*w);
122         w = manage (new Image (::get_icon (X_("mezzopiano"))));
123         w->show();
124         velocity_mp_button.add (*w);
125         w = manage (new Image (::get_icon (X_("mezzoforte"))));
126         w->show();
127         velocity_mf_button.add (*w);
128         w = manage (new Image (::get_icon (X_("forte"))));
129         w->show();
130         velocity_f_button.add (*w);
131         w = manage (new Image (::get_icon (X_("fortissimo"))));
132         w->show();
133         velocity_ff_button.add (*w);
134         w = manage (new Image (::get_icon (X_("fortississimo"))));
135         w->show();
136         velocity_fff_button.add (*w);
137
138         velocity_ppp_button.property_draw_indicator() = false;
139         velocity_pp_button.property_draw_indicator() = false;
140         velocity_p_button.property_draw_indicator() = false;
141         velocity_mp_button.property_draw_indicator() = false;
142         velocity_mf_button.property_draw_indicator() = false;
143         velocity_f_button.property_draw_indicator() = false;
144         velocity_ff_button.property_draw_indicator() = false;
145         velocity_fff_button.property_draw_indicator() = false;
146
147         note_velocity_box.pack_start (velocity_ppp_button, false, false);
148         note_velocity_box.pack_start (velocity_pp_button, false, false);
149         note_velocity_box.pack_start (velocity_p_button, false, false);
150         note_velocity_box.pack_start (velocity_mp_button, false, false);
151         note_velocity_box.pack_start (velocity_mf_button, false, false);
152         note_velocity_box.pack_start (velocity_f_button, false, false);
153         note_velocity_box.pack_start (velocity_ff_button, false, false);
154         note_velocity_box.pack_start (velocity_fff_button, false, false);
155
156         Label* l = manage (new Label);
157         l->set_markup ("<b><big>.</big></b>");
158         l->show ();
159         dot_button.add (*l);
160
161         w = manage (new Image (::get_icon (X_("chord"))));
162         w->show();
163         chord_button.add (*w);
164
165         upper_box.set_spacing (6);
166         upper_box.pack_start (chord_button, false, false);
167         upper_box.pack_start (note_length_box, false, false, 12);
168         upper_box.pack_start (triplet_button, false, false);
169         upper_box.pack_start (dot_button, false, false);
170         upper_box.pack_start (sustain_button, false, false);
171         upper_box.pack_start (rest_button, false, false);
172         upper_box.pack_start (note_velocity_box, false, false, 12);
173         upper_box.pack_start (channel_spinner, false, false);
174
175         _piano = (PianoKeyboard*) piano_keyboard_new ();
176         piano = Glib::wrap ((GtkWidget*) _piano);
177
178         piano->set_flags (Gtk::CAN_FOCUS);
179         piano->signal_enter_notify_event().connect (sigc::mem_fun (*this, &StepEntry::piano_enter_notify_event), false);
180
181         g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
182         g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
183         
184         rest_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::rest_click));
185         chord_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::chord_toggled));
186         triplet_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::triplet_toggled));
187
188         packer.set_spacing (6);
189         packer.pack_start (upper_box, false, false);
190         packer.pack_start (*piano, false, false);
191         packer.show_all ();
192
193         get_vbox()->add (packer);
194 }
195
196 StepEntry::~StepEntry()
197 {
198 }
199
200 bool
201 StepEntry::on_key_press_event (GdkEventKey* ev)
202 {
203         int ret;
204         g_signal_emit_by_name (G_OBJECT(_piano), "key-press-event", ev, &ret);
205         return ret;
206 }
207
208 bool
209 StepEntry::on_key_release_event (GdkEventKey* ev)
210 {
211         int ret;
212         g_signal_emit_by_name (G_OBJECT(_piano), "key-release-event", ev, &ret);
213         return ret;
214 }
215
216 void
217 StepEntry::rest_event_handler ()
218 {
219         _mtv->step_edit_rest();
220 }
221
222 void
223 StepEntry::note_off_event_handler (int note)
224 {
225         Evoral::MusicalTime length = 1.0;
226         uint8_t velocity = 64;
227
228         if (length_64_button.get_active()) {
229                 length = 1.0/64.0;
230         } else if (length_32_button.get_active()) {
231                 length = 1.0/32.0;
232         } else if (length_16_button.get_active()) {
233                 length = 1.0/16.0;
234         } else if (length_8_button.get_active()) {
235                 length = 1.0/8.0;
236         } else if (length_4_button.get_active()) {
237                 length = 1.0/4.0;
238         } else if (length_2_button.get_active()) {
239                 length = 1.0/2.0;
240         } else if (length_1_button.get_active()) {
241                 length = 1.0/1.0;
242         }
243
244         if (dot_button.get_active()) {
245                 length *= 0.5;
246         }
247
248         if (velocity_ppp_button.get_active()) {
249                 velocity = 16;
250         } else if (velocity_pp_button.get_active()) {
251                 velocity = 32;
252         } else if (velocity_p_button.get_active()) {
253                 velocity = 48;
254         } else if (velocity_mp_button.get_active()) {
255                 velocity = 64;
256         } else if (velocity_mf_button.get_active()) {
257                 velocity = 80;
258         } else if (velocity_f_button.get_active()) {
259                 velocity = 96;
260         } else if (velocity_ff_button.get_active()) {
261                 velocity = 112;
262         } else if (velocity_fff_button.get_active()) {
263                 velocity = 127;
264         }
265
266         if (_mtv->step_edit_within_triplet()) {
267                 length *= 2.0/3.0;
268         }
269
270         _mtv->step_add_note (channel_adjustment.get_value(), note, velocity, length);
271 }
272
273 void
274 StepEntry::rest_click ()
275 {
276         _mtv->step_edit_rest ();
277 }
278
279 void
280 StepEntry::triplet_toggled ()
281 {
282         if (triplet_button.get_active () != _mtv->step_edit_within_triplet()) {
283                 _mtv->step_edit_toggle_triplet ();
284         }
285 }
286
287 void
288 StepEntry::chord_toggled ()
289 {
290         if (chord_button.get_active() != _mtv->step_edit_within_chord ()) {
291                 _mtv->step_edit_toggle_chord ();
292         }
293 }
294
295 bool
296 StepEntry::piano_enter_notify_event (GdkEventCrossing *ev)
297 {
298         piano->grab_focus ();
299         return false;
300 }
301