/[svn]/gigedit/trunk/src/gigedit/midirules.cpp
ViewVC logotype

Annotation of /gigedit/trunk/src/gigedit/midirules.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2845 - (hide annotations) (download)
Sun Sep 20 10:18:22 2015 UTC (8 years, 7 months ago) by persson
File size: 18964 byte(s)
* avoid using gtk stock items, as they are deprecated in gtk 3.10

1 persson 2845 /*
2 persson 2841 * Copyright (C) 2013-2015 Andreas Persson
3 persson 2507 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2 of the
7     * License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * 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., 51 Franklin Street, Fifth Floor, Boston, MA
17     * 02110-1301, USA.
18     */
19    
20     #include "midirules.h"
21    
22 persson 2845 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
23 persson 2507 #include <gtkmm/stock.h>
24 persson 2845 #endif
25 persson 2507
26     #include "global.h"
27    
28     MidiRules::MidiRules() :
29     label(_("Midi rule:")),
30 persson 2845 quit_button(_("_Close"), true),
31 persson 2841 unknown(_("unknown"))
32 persson 2507 {
33     set_title(_("Midi Rules"));
34     set_border_width(6);
35    
36     add(vbox);
37    
38     hbox.set_border_width(6);
39     hbox.set_spacing(6);
40     hbox.pack_start(label, Gtk::PACK_SHRINK);
41     hbox.pack_start(combo, Gtk::PACK_SHRINK);
42     const char* choices[] = { _("none"), _("Controller trigger"),
43     _("Legato"), 0 };
44     for (int i = 0 ; choices[i] ; i++) {
45     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
46     combo.append_text(choices[i]);
47     #else
48     combo.append(choices[i]);
49     #endif
50     }
51     combo.signal_changed().connect(
52     sigc::mem_fun(*this, &MidiRules::combo_changed));
53     vbox.pack_start(hbox, Gtk::PACK_SHRINK);
54    
55     box.set_border_width(6);
56     vbox.pack_start(box);
57    
58     button_box.set_border_width(6);
59     button_box.set_layout(Gtk::BUTTONBOX_END);
60     button_box.pack_start(quit_button);
61     quit_button.set_can_default();
62     quit_button.grab_focus();
63     quit_button.signal_clicked().connect(
64     sigc::mem_fun(*this, &MidiRules::hide));
65     vbox.pack_start(button_box, Gtk::PACK_SHRINK);
66    
67     legato.signal_changed().connect(sig_changed.make_slot());
68     ctrl_trigger.signal_changed().connect(sig_changed.make_slot());
69    
70     show_all_children();
71     }
72    
73     void MidiRules::combo_changed() {
74     if (update_model) return;
75    
76     int rowno = combo.get_active_row_number();
77    
78     if (remove_unknown_from_combo()) {
79     rowno--;
80     }
81    
82     gig::MidiRule* rule = m->GetMidiRule(0);
83     switch (rowno) {
84     case NONE:
85     if (rule) {
86     m->DeleteMidiRule(0);
87     set_instrument(m);
88     }
89     break;
90     case CTRL_TRIGGER:
91     if (!dynamic_cast<gig::MidiRuleCtrlTrigger*>(rule)) {
92     m->AddMidiRuleCtrlTrigger();
93     set_instrument(m);
94     }
95     break;
96     case LEGATO:
97     if (!dynamic_cast<gig::MidiRuleLegato*>(rule)) {
98     m->AddMidiRuleLegato();
99     set_instrument(m);
100     }
101     break;
102     }
103     sig_changed();
104     }
105    
106     void MidiRules::set_instrument(gig::Instrument* instrument) {
107     m = instrument;
108     update_model++;
109    
110     std::vector<Widget*> children = box.get_children();
111     if (children.size() == 1) {
112     box.remove(*children[0]);
113     }
114    
115     gig::MidiRule* rule = instrument->GetMidiRule(0);
116     int active = -1;
117     if (!rule) {
118     active = NONE;
119     } else if (gig::MidiRuleLegato* r =
120     dynamic_cast<gig::MidiRuleLegato*>(rule)) {
121     active = LEGATO;
122     box.add(legato);
123     legato.set_rule(r);
124     } else if (gig::MidiRuleCtrlTrigger* r =
125     dynamic_cast<gig::MidiRuleCtrlTrigger*>(rule)) {
126     active = CTRL_TRIGGER;
127     box.add(ctrl_trigger);
128     ctrl_trigger.set_rule(r);
129     } else {
130     if (combo.get_model()->children().size() == NUMBER_OF_RULES) {
131     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
132     combo.prepend_text(unknown);
133     #else
134     combo.prepend(unknown);
135     #endif
136     }
137     combo.set_active(0);
138     }
139     if (active != -1) {
140     remove_unknown_from_combo();
141     combo.set_active(active);
142     }
143     show_all_children();
144     update_model--;
145     }
146    
147     bool MidiRules::remove_unknown_from_combo() {
148     if (combo.get_model()->children().size() == NUMBER_OF_RULES + 1) {
149     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
150     combo.remove_text(unknown);
151     #else
152     combo.remove_text(0);
153     #endif
154     return true;
155     }
156     return false;
157     }
158    
159    
160     MidiRuleCtrlTrigger::MidiRuleCtrlTrigger() :
161     table(2, 1),
162     eControllerNumber(_("Controller"))
163     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
164     , add_button(Gtk::Stock::ADD),
165     remove_button(Gtk::Stock::REMOVE)
166     #endif
167     {
168     connect(eControllerNumber, &gig::MidiRuleCtrlTrigger::ControllerNumber);
169    
170     set_spacing(6);
171    
172     scrolled_window.set_size_request(-1, 120);
173    
174     list_store = Gtk::ListStore::create(columns);
175     tree_view.set_model(list_store);
176     list_store->signal_row_changed().connect(
177     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::row_changed));
178     list_store->signal_row_inserted().connect(
179     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::row_inserted));
180     list_store->signal_row_deleted().connect(
181     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::row_deleted));
182    
183     append_num_column(_("Trigger point"), columns.trigger_point);
184     tree_view.append_column_editable(_("Descending"), columns.descending);
185     append_num_column(_("Vel sensitivity"), columns.vel_sensitivity, 1, 100);
186     append_note_column(_("Key"), columns.key);
187     tree_view.append_column_editable(_("Note off"), columns.note_off);
188     tree_view.append_column_editable(_("Switch"), columns.switch_logic);
189    
190     int cols_count = append_num_column(_("Velocity"), columns.velocity);
191     Gtk::TreeViewColumn* col = tree_view.get_column(cols_count - 1);
192     col->add_attribute(*col->get_first_cell(), "visible", columns.switch_logic);
193     cols_count = tree_view.append_column_editable(_("Override pedal"),
194     columns.override_pedal);
195     col = tree_view.get_column(cols_count - 1);
196     col->add_attribute(*col->get_first_cell(), "visible", columns.note_off);
197    
198     tree_view.get_selection()->signal_changed().connect(
199     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::sel_changed));
200    
201     scrolled_window.add(tree_view);
202     scrolled_window.set_shadow_type(Gtk::SHADOW_IN);
203     scrolled_window.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
204    
205     table.set_col_spacings(5);
206     table.add(eControllerNumber);
207     pack_start(table, Gtk::PACK_SHRINK);
208    
209     vbox.add(scrolled_window);
210    
211     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
212     vbox.set_spacing(6);
213     toolbar.set_layout(Gtk::BUTTONBOX_START);
214     toolbar.set_homogeneous();
215     toolbar.set_spacing(6);
216     #else
217     toolbar.set_toolbar_style(Gtk::TOOLBAR_ICONS);
218     toolbar.set_show_arrow(false);
219     toolbar.set_icon_size(Gtk::IconSize(1));
220     toolbar.get_style_context()->add_class("inline-toolbar");
221    
222     add_button.set_icon_name("list-add-symbolic");
223     remove_button.set_icon_name("list-remove-symbolic");
224     #endif
225    
226     add_button.signal_clicked().connect(
227     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::add_row));
228     toolbar.add(add_button);
229    
230     remove_button.signal_clicked().connect(
231     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::remove_row));
232     toolbar.add(remove_button);
233    
234     vbox.pack_start(toolbar, Gtk::PACK_SHRINK);
235     add(vbox);
236     }
237    
238     int MidiRuleCtrlTrigger::append_num_column(
239     const char* title,
240     const Gtk::TreeModelColumn<int>& column,
241     int lower, int upper) {
242     Gtk::CellRendererSpin* renderer = Gtk::manage(new Gtk::CellRendererSpin());
243     renderer->property_editable() = true;
244     renderer->signal_editing_started().connect(
245     sigc::bind(
246     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::num_editing_started),
247     renderer));
248     renderer->signal_edited().connect(
249     sigc::bind(
250     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::num_edited),
251     column));
252     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
253     renderer->property_adjustment() = new Gtk::Adjustment(lower, lower, upper);
254     #else
255     renderer->property_adjustment() =
256     Gtk::Adjustment::create(lower, lower, upper);
257     #endif
258    
259     int cols_count = tree_view.append_column(title, *renderer);
260     Gtk::TreeViewColumn* col = tree_view.get_column(cols_count - 1);
261     col->add_attribute(*renderer, "text", column);
262     col->set_min_width(92);
263     return cols_count;
264     }
265    
266     int MidiRuleCtrlTrigger::append_note_column(
267     const char* title,
268     const Gtk::TreeModelColumn<Glib::ustring>& column) {
269     Gtk::CellRendererSpin* renderer = Gtk::manage(new Gtk::CellRendererSpin());
270     renderer->property_editable() = true;
271     renderer->signal_editing_started().connect(
272     sigc::bind(
273     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::note_editing_started),
274     renderer));
275     renderer->signal_edited().connect(
276     sigc::bind(
277     sigc::mem_fun(*this, &MidiRuleCtrlTrigger::note_edited),
278     column));
279     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
280     renderer->property_adjustment() = new Gtk::Adjustment(0, 0, 127);
281     #else
282     renderer->property_adjustment() = Gtk::Adjustment::create(0, 0, 127);
283     #endif
284    
285     int cols_count = tree_view.append_column(title, *renderer);
286     Gtk::TreeViewColumn* col = tree_view.get_column(cols_count - 1);
287     col->add_attribute(*renderer, "text", column);
288     col->set_min_width(98);
289     return cols_count;
290     }
291    
292     void MidiRuleCtrlTrigger::set_rule(gig::MidiRuleCtrlTrigger* r) {
293     update_model++;
294     update(r);
295     list_store->clear();
296     for (int i = 0 ; i < r->Triggers ; i++) {
297     Gtk::TreeModel::Row row = *list_store->append();
298     row[columns.trigger_point] = r->pTriggers[i].TriggerPoint;
299     row[columns.descending] = r->pTriggers[i].Descending;
300     row[columns.vel_sensitivity] = r->pTriggers[i].VelSensitivity;
301     row[columns.key] = note_str(r->pTriggers[i].Key);
302     row[columns.note_off] = r->pTriggers[i].NoteOff;
303     row[columns.switch_logic] = r->pTriggers[i].Velocity != 255;
304     if (r->pTriggers[i].Velocity != 255) {
305     row[columns.velocity] = r->pTriggers[i].Velocity;
306     }
307     row[columns.override_pedal] = r->pTriggers[i].OverridePedal;
308     }
309     sel_changed();
310     add_button.set_sensitive();
311     if (r->Triggers == 32) add_button.set_sensitive(false);
312     update_model--;
313     }
314    
315     void MidiRuleCtrlTrigger::num_editing_started(
316     Gtk::CellEditable* editable,
317     const Glib::ustring& path,
318     Gtk::CellRendererSpin* renderer) {
319     int lower = renderer->property_adjustment().get_value()->get_lower();
320     int upper = renderer->property_adjustment().get_value()->get_upper();
321     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
322     renderer->property_adjustment() = new Gtk::Adjustment(lower, lower, upper);
323     #else
324     renderer->property_adjustment() =
325     Gtk::Adjustment::create(lower, lower, upper);
326     #endif
327     Gtk::SpinButton* spin_button = dynamic_cast<Gtk::SpinButton*>(editable);
328     if (spin_button) {
329     spin_button->set_numeric();
330     }
331     }
332    
333     void MidiRuleCtrlTrigger::note_editing_started(
334     Gtk::CellEditable* editable,
335     const Glib::ustring& path,
336     Gtk::CellRendererSpin* renderer) {
337     int value = note_value(renderer->property_text());
338     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
339     renderer->property_adjustment() = new Gtk::Adjustment(0, 0, 127);
340     #else
341     renderer->property_adjustment() = Gtk::Adjustment::create(0, 0, 127);
342     #endif
343     Gtk::SpinButton* spin_button = dynamic_cast<Gtk::SpinButton*>(editable);
344     if (spin_button) {
345     spin_button->get_adjustment()->set_value(value);
346     spin_button_show_notes(*spin_button);
347     }
348     }
349    
350     void MidiRuleCtrlTrigger::num_edited(
351     const Glib::ustring& path,
352     const Glib::ustring& new_text,
353     const Gtk::TreeModelColumn<int>& column) {
354     Gtk::TreeModel::Row row = *list_store->get_iter(path);
355    
356     Gtk::TreeModel::Path cpath;
357     Gtk::TreeViewColumn* col;
358     tree_view.get_cursor(cpath, col);
359    
360     int lower = 0;
361     int upper = 127;
362     const Gtk::CellRenderer* r = col->get_first_cell();
363     if (const Gtk::CellRendererSpin* renderer =
364     dynamic_cast<const Gtk::CellRendererSpin*>(r)) {
365     lower = renderer->property_adjustment().get_value()->get_lower();
366     upper = renderer->property_adjustment().get_value()->get_upper();
367     }
368    
369     row[column] = std::max(lower, std::min(atoi(new_text.c_str()), upper));
370     }
371    
372     void MidiRuleCtrlTrigger::note_edited(
373     const Glib::ustring& path,
374     const Glib::ustring& new_text,
375     const Gtk::TreeModelColumn<Glib::ustring>& column) {
376     Gtk::TreeModel::Row row = *list_store->get_iter(path);
377    
378     row[column] = note_str(note_value(new_text));
379     }
380    
381     void MidiRuleCtrlTrigger::sel_changed() {
382     Gtk::TreeModel::iterator it = tree_view.get_selection()->get_selected();
383     remove_button.set_sensitive();
384     if (!it) remove_button.set_sensitive(false);
385     }
386    
387     void MidiRuleCtrlTrigger::add_row() {
388     Gtk::TreeModel::Path path;
389     Gtk::TreeViewColumn* col;
390     tree_view.get_cursor(path, col);
391     if (!path.empty()) tree_view.set_cursor(path);
392    
393     Gtk::TreeModel::iterator it = list_store->append();
394     Gtk::TreeModel::Row row = *it;
395    
396     update_model++;
397     row[columns.trigger_point] = 64;
398     row[columns.descending] = false;
399     row[columns.vel_sensitivity] = 50;
400     row[columns.key] = note_str(60);
401     row[columns.note_off] = false;
402     row[columns.switch_logic] = false;
403     row[columns.override_pedal] = false;
404     update_model--;
405    
406     tree_view.get_selection()->select(row);
407     path = list_store->get_path(it);
408     tree_view.scroll_to_row(path);
409     tree_view.set_cursor(path);
410     }
411    
412     void MidiRuleCtrlTrigger::remove_row() {
413     Gtk::TreeModel::Path cpath;
414     Gtk::TreeViewColumn* col;
415     tree_view.get_cursor(cpath, col);
416     if (!cpath.empty()) tree_view.set_cursor(cpath);
417    
418     Gtk::TreeModel::iterator it = tree_view.get_selection()->get_selected();
419     if (it) {
420     Gtk::TreePath path = list_store->get_path(it);
421     list_store->erase(it);
422    
423     it = tree_view.get_selection()->get_selected();
424     if (!it) {
425     int i = path[0];
426     int n = list_store->children().size();
427     if (n) {
428     if (i >= n) i = n - 1;
429     path[0] = i;
430     tree_view.get_selection()->select(path);
431     }
432     }
433     }
434     }
435    
436     void MidiRuleCtrlTrigger::row_changed(const Gtk::TreeModel::Path& path,
437     const Gtk::TreeModel::iterator& iter) {
438     if (update_model) return;
439    
440     Gtk::TreeModel::Row row = *iter;
441     int i = path[0];
442    
443     if (m->pTriggers[i].Velocity == 255 && row[columns.switch_logic]) {
444     update_model++;
445     row[columns.velocity] = 100;
446     update_model--;
447     }
448    
449     int key = note_value(row[columns.key]);
450    
451     if (m->pTriggers[i].TriggerPoint != row[columns.trigger_point] ||
452     m->pTriggers[i].Descending != row[columns.descending] ||
453     m->pTriggers[i].VelSensitivity != row[columns.vel_sensitivity] ||
454     m->pTriggers[i].Key != key ||
455     m->pTriggers[i].NoteOff != row[columns.note_off] ||
456     (m->pTriggers[i].Velocity != 255) != row[columns.switch_logic] ||
457     m->pTriggers[i].Velocity != row[columns.velocity] ||
458     m->pTriggers[i].OverridePedal != row[columns.override_pedal])
459     {
460     m->pTriggers[i].TriggerPoint = row[columns.trigger_point];
461     m->pTriggers[i].Descending = row[columns.descending];
462     m->pTriggers[i].VelSensitivity = row[columns.vel_sensitivity];
463     m->pTriggers[i].Key = key;
464     m->pTriggers[i].NoteOff = row[columns.note_off];
465     m->pTriggers[i].Velocity =
466     row[columns.switch_logic] ? row[columns.velocity] : 255;
467     m->pTriggers[i].OverridePedal = row[columns.override_pedal];
468     sig_changed();
469     }
470     }
471    
472     void MidiRuleCtrlTrigger::row_inserted(const Gtk::TreeModel::Path& path,
473     const Gtk::TreeModel::iterator& iter) {
474     if (update_model) return;
475     int i = m->Triggers++;
476     m->pTriggers[i].TriggerPoint = 64;
477     m->pTriggers[i].Descending = false;
478     m->pTriggers[i].VelSensitivity = 50;
479     m->pTriggers[i].Key = 60;
480     m->pTriggers[i].NoteOff = false;
481     m->pTriggers[i].Velocity = 255;
482     m->pTriggers[i].OverridePedal = false;
483     add_button.set_sensitive();
484     if (m->Triggers == 32) add_button.set_sensitive(false);
485     sig_changed();
486     }
487    
488     void MidiRuleCtrlTrigger::row_deleted(const Gtk::TreeModel::Path& path) {
489     if (update_model) return;
490     for (int i = path[0] + 1 ; i < m->Triggers ; i++) {
491     m->pTriggers[i - 1] = m->pTriggers[i];
492     }
493     m->Triggers--;
494     add_button.set_sensitive();
495     sig_changed();
496     }
497    
498    
499    
500     MidiRuleLegato::MidiRuleLegato() :
501     Table(2, 1),
502     eBypassUseController(_("Bypass use controller")),
503     eBypassKey(_("Bypass key")),
504     eBypassController(_("Bypass controller")),
505     eThresholdTime(_("Threshold time"), 10, 500),
506     eReleaseTime(_("Release time"), 10, 500),
507     eKeyRangeLow(_("Key range low")),
508     eKeyRangeHigh(_("Key range high")),
509     eReleaseTriggerKey(_("Release trigger key")),
510     eAltSustain1Key(_("Alt sustain 1 key")),
511     eAltSustain2Key(_("Alt sustain 2 key"))
512     {
513     connect(eBypassUseController, &gig::MidiRuleLegato::BypassUseController);
514     connect(eBypassKey, &gig::MidiRuleLegato::BypassKey);
515     connect(eBypassController, &gig::MidiRuleLegato::BypassController);
516     connect(eThresholdTime, &gig::MidiRuleLegato::ThresholdTime);
517     connect(eReleaseTime, &gig::MidiRuleLegato::ReleaseTime);
518     connect(eKeyRangeLow, eKeyRangeHigh, &gig::MidiRuleLegato::KeyRange);
519     connect(eReleaseTriggerKey, &gig::MidiRuleLegato::ReleaseTriggerKey);
520     connect(eAltSustain1Key, &gig::MidiRuleLegato::AltSustain1Key);
521     connect(eAltSustain2Key, &gig::MidiRuleLegato::AltSustain2Key);
522    
523     set_col_spacings(5);
524    
525     add(eBypassUseController);
526     add(eBypassKey);
527     add(eBypassController);
528     add(eThresholdTime);
529     add(eReleaseTime);
530     add(eKeyRangeLow);
531     add(eKeyRangeHigh);
532     add(eReleaseTriggerKey);
533     add(eAltSustain1Key);
534     add(eAltSustain2Key);
535    
536     eBypassUseController.signal_value_changed().connect(
537     sigc::mem_fun(*this, &MidiRuleLegato::BypassUseController_toggled));
538     }
539    
540     void MidiRuleLegato::BypassUseController_toggled() {
541     bool useController = eBypassUseController.get_value();
542     eBypassKey.set_sensitive(!useController);
543     eBypassController.set_sensitive(useController);
544     }
545    
546     void MidiRuleLegato::set_rule(gig::MidiRuleLegato* r) {
547     update_model++;
548     update(r);
549     BypassUseController_toggled();
550     update_model--;
551     }

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC