/[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 3225 - (hide annotations) (download)
Fri May 26 22:10:16 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 19020 byte(s)
* Assigned more useful default dimensions (and default position) for various
  windows and dialogs (if auto-restore of user's own custom window
  dimensions is disabled).
* Bumped version (1.0.0.svn51).

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC