a bunch of tweaks for the step entry process (computer keyboard input now works,...
[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_keyboard_set_keyboard_cue (PIANO_KEYBOARD(_piano), 1);
177         
178         piano = Glib::wrap ((GtkWidget*) _piano);
179
180         piano->set_flags (Gtk::CAN_FOCUS);
181         piano->signal_enter_notify_event().connect (sigc::mem_fun (*this, &StepEntry::piano_enter_notify_event), false);
182
183         g_signal_connect(G_OBJECT(_piano), "note-off", G_CALLBACK(_note_off_event_handler), this);
184         g_signal_connect(G_OBJECT(_piano), "rest", G_CALLBACK(_rest_event_handler), this);
185         
186         rest_button.signal_clicked().connect (sigc::mem_fun (*this, &StepEntry::rest_click));
187         chord_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::chord_toggled));
188         triplet_button.signal_toggled().connect (sigc::mem_fun (*this, &StepEntry::triplet_toggled));
189
190         packer.set_spacing (6);
191         packer.pack_start (upper_box, false, false);
192         packer.pack_start (*piano, false, false);
193         packer.show_all ();
194
195         get_vbox()->add (packer);
196 }
197
198 StepEntry::~StepEntry()
199 {
200 }
201
202 bool
203 StepEntry::on_key_press_event (GdkEventKey* ev)
204 {
205         int ret;
206         g_signal_emit_by_name (G_OBJECT(_piano), "key-press-event", ev, &ret);
207         return ret;
208 }
209
210 bool
211 StepEntry::on_key_release_event (GdkEventKey* ev)
212 {
213         int ret;
214         g_signal_emit_by_name (G_OBJECT(_piano), "key-release-event", ev, &ret);
215         return ret;
216 }
217
218 void
219 StepEntry::rest_event_handler ()
220 {
221         _mtv->step_edit_rest();
222 }
223
224 void
225 StepEntry::note_off_event_handler (int note)
226 {
227         Evoral::MusicalTime length = 1.0;
228         uint8_t velocity = 64;
229
230         if (length_64_button.get_active()) {
231                 length = 1.0/64.0;
232         } else if (length_32_button.get_active()) {
233                 length = 1.0/32.0;
234         } else if (length_16_button.get_active()) {
235                 length = 1.0/16.0;
236         } else if (length_8_button.get_active()) {
237                 length = 1.0/8.0;
238         } else if (length_4_button.get_active()) {
239                 length = 1.0/4.0;
240         } else if (length_2_button.get_active()) {
241                 length = 1.0/2.0;
242         } else if (length_1_button.get_active()) {
243                 length = 1.0/1.0;
244         }
245
246         if (dot_button.get_active()) {
247                 length *= 0.5;
248         }
249
250         if (velocity_ppp_button.get_active()) {
251                 velocity = 16;
252         } else if (velocity_pp_button.get_active()) {
253                 velocity = 32;
254         } else if (velocity_p_button.get_active()) {
255                 velocity = 48;
256         } else if (velocity_mp_button.get_active()) {
257                 velocity = 64;
258         } else if (velocity_mf_button.get_active()) {
259                 velocity = 80;
260         } else if (velocity_f_button.get_active()) {
261                 velocity = 96;
262         } else if (velocity_ff_button.get_active()) {
263                 velocity = 112;
264         } else if (velocity_fff_button.get_active()) {
265                 velocity = 127;
266         }
267
268         if (_mtv->step_edit_within_triplet()) {
269                 length *= 2.0/3.0;
270         }
271
272         _mtv->step_add_note (channel_adjustment.get_value(), note, velocity, length);
273 }
274
275 void
276 StepEntry::rest_click ()
277 {
278         _mtv->step_edit_rest ();
279 }
280
281 void
282 StepEntry::triplet_toggled ()
283 {
284         if (triplet_button.get_active () != _mtv->step_edit_within_triplet()) {
285                 _mtv->step_edit_toggle_triplet ();
286         }
287 }
288
289 void
290 StepEntry::chord_toggled ()
291 {
292         if (chord_button.get_active() != _mtv->step_edit_within_chord ()) {
293                 _mtv->step_edit_toggle_chord ();
294         }
295 }
296
297 bool
298 StepEntry::piano_enter_notify_event (GdkEventCrossing *ev)
299 {
300         piano->grab_focus ();
301         return false;
302 }
303