/[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 2841 - (hide annotations) (download)
Sun Aug 30 10:00:49 2015 UTC (8 years, 7 months ago) by persson
File size: 18939 byte(s)
* allow building with G_DISABLE_DEPRECATED
* fixed building without liblinuxsampler on Mac
* fixed some compiler and cppcheck warnings

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC