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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2558 - (hide annotations) (download)
Sat May 17 23:55:30 2014 UTC (9 years, 10 months ago) by schoenebeck
File size: 15230 byte(s)
* Combine instruments: generalized this tool to allow combining instruments
  based on any dimension (selectable by combo box), not only the 'layer'
  dimension. Also fixed some bugs that could lead to undesired results
  when combining instruments, i.e. source instruments being copied into
  wrong target zones or in wrong order under certain conditions.
* 'Dimension Manager' dialog: show dialog window with at least 460x300px on
  initial usage (was far too small by default).

1 persson 2169 /*
2 persson 2507 * Copyright (C) 2006-2014 Andreas Persson
3 schoenebeck 1225 *
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, or (at
7     * 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 program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20     #include "dimensionmanager.h"
21    
22     #include <gtkmm/stock.h>
23     #include <gtkmm/messagedialog.h>
24     #include <gtkmm/dialog.h>
25     #include <gtkmm/comboboxtext.h>
26 persson 1733 #include <gtkmm/spinbutton.h>
27     #include <gtkmm/table.h>
28 schoenebeck 1225
29 persson 1831 #include "global.h"
30 persson 2169 #include "compat.h"
31 persson 1831
32 schoenebeck 1225 // returns a human readable name of the given dimension type
33 schoenebeck 2558 Glib::ustring dimTypeAsString(gig::dimension_t d) {
34 schoenebeck 1225 char buf[32];
35     switch (d) {
36     case gig::dimension_none:
37 persson 1831 return _("None");
38 schoenebeck 1225 case gig::dimension_samplechannel:
39 persson 1831 return _("Sample Channel");
40 schoenebeck 1225 case gig::dimension_layer:
41 persson 1831 return _("Layer");
42 schoenebeck 1225 case gig::dimension_velocity:
43 persson 1831 return _("Velocity");
44 schoenebeck 1225 case gig::dimension_channelaftertouch:
45 persson 1831 return _("Aftertouch");
46 schoenebeck 1225 case gig::dimension_releasetrigger:
47 persson 1831 return _("Release Trigger");
48 schoenebeck 1225 case gig::dimension_keyboard:
49 persson 1831 return _("Keyswitching");
50 schoenebeck 1225 case gig::dimension_roundrobin:
51 persson 1831 return _("Round Robin");
52 schoenebeck 1225 case gig::dimension_random:
53 persson 1831 return _("Random Generator");
54 schoenebeck 1225 case gig::dimension_smartmidi:
55 persson 1831 return _("Smart MIDI");
56 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
57 persson 1831 return _("Keyboard Round Robin");
58 schoenebeck 1225 case gig::dimension_modwheel:
59 persson 1831 return _("Modulation Wheel");
60 schoenebeck 1225 case gig::dimension_breath:
61 persson 1831 return _("Breath Ctrl.");
62 schoenebeck 1225 case gig::dimension_foot:
63 persson 1831 return _("Foot Ctrl.");
64 schoenebeck 1225 case gig::dimension_portamentotime:
65 persson 1831 return _("Portamento Time Ctrl.");
66 schoenebeck 1225 case gig::dimension_effect1:
67 persson 1831 return _("Effect Ctrl. 1");
68 schoenebeck 1225 case gig::dimension_effect2:
69 persson 1831 return _("Effect Ctrl. 2");
70 schoenebeck 1225 case gig::dimension_genpurpose1:
71 persson 1831 return _("General Purpose Ctrl. 1");
72 schoenebeck 1225 case gig::dimension_genpurpose2:
73 persson 1831 return _("General Purpose Ctrl. 2");
74 schoenebeck 1225 case gig::dimension_genpurpose3:
75 persson 1831 return _("General Purpose Ctrl. 3");
76 schoenebeck 1225 case gig::dimension_genpurpose4:
77 persson 1831 return _("General Purpose Ctrl. 4");
78 schoenebeck 1225 case gig::dimension_sustainpedal:
79 persson 1831 return _("Sustain Pedal");
80 schoenebeck 1225 case gig::dimension_portamento:
81 persson 1831 return _("Portamento Ctrl.");
82 schoenebeck 1225 case gig::dimension_sostenutopedal:
83 persson 1831 return _("Sostenuto Pedal");
84 schoenebeck 1225 case gig::dimension_softpedal:
85 persson 1831 return _("Soft Pedal");
86 schoenebeck 1225 case gig::dimension_genpurpose5:
87 persson 1831 return _("General Purpose Ctrl. 5");
88 schoenebeck 1225 case gig::dimension_genpurpose6:
89 persson 1831 return _("General Purpose Ctrl. 6");
90 schoenebeck 1225 case gig::dimension_genpurpose7:
91 persson 1831 return _("General Purpose Ctrl. 7");
92 schoenebeck 1225 case gig::dimension_genpurpose8:
93 persson 1831 return _("General Purpose Ctrl. 8");
94 schoenebeck 1225 case gig::dimension_effect1depth:
95 persson 1831 return _("Effect 1 Depth");
96 schoenebeck 1225 case gig::dimension_effect2depth:
97 persson 1831 return _("Effect 2 Depth");
98 schoenebeck 1225 case gig::dimension_effect3depth:
99 persson 1831 return _("Effect 3 Depth");
100 schoenebeck 1225 case gig::dimension_effect4depth:
101 persson 1831 return _("Effect 4 Depth");
102 schoenebeck 1225 case gig::dimension_effect5depth:
103 persson 1831 return _("Effect 5 Depth");
104 schoenebeck 1225 default:
105     sprintf(buf, "Unknown Type (0x%x) !!!", d);
106     return buf;
107     }
108     }
109    
110     // returns a human readable description of the given dimension
111     static Glib::ustring __dimDescriptionAsString(gig::dimension_t d) {
112     switch (d) {
113     case gig::dimension_none:
114 persson 1831 return _("Dimension not in use");
115 schoenebeck 1225 case gig::dimension_samplechannel:
116 persson 1831 return _("If used sample has more than one channel (thus is not mono)");
117 schoenebeck 1225 case gig::dimension_layer:
118 persson 1831 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
119 schoenebeck 1225 case gig::dimension_velocity:
120 persson 1831 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
121 schoenebeck 1225 case gig::dimension_channelaftertouch:
122 persson 1831 return _("Channel Key Pressure");
123 schoenebeck 1225 case gig::dimension_releasetrigger:
124 persson 1831 return _("Special dimension for triggering samples on releasing a key");
125 schoenebeck 1225 case gig::dimension_keyboard:
126 persson 1831 return _("Dimension for keyswitching (keyboard)");
127 schoenebeck 1225 case gig::dimension_roundrobin:
128 persson 1831 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
129 schoenebeck 1225 case gig::dimension_random:
130 persson 1831 return _("Different samples triggered each time a note is played, random order");
131 schoenebeck 1225 case gig::dimension_smartmidi:
132 persson 1831 return _("For MIDI tools like legato and repetition mode");
133 schoenebeck 1225 case gig::dimension_roundrobinkeyboard:
134 persson 1831 return _("Different samples triggered each time a note is played, any key advances the counter");
135 schoenebeck 1225 case gig::dimension_modwheel:
136 persson 1831 return _("MIDI Controller 1");
137 schoenebeck 1225 case gig::dimension_breath:
138 persson 1831 return _("MIDI Controller 2");
139 schoenebeck 1225 case gig::dimension_foot:
140 persson 1831 return _("MIDI Controller 4");
141 schoenebeck 1225 case gig::dimension_portamentotime:
142 persson 1831 return _("MIDI Controller 5");
143 schoenebeck 1225 case gig::dimension_effect1:
144 persson 1831 return _("MIDI Controller 12");
145 schoenebeck 1225 case gig::dimension_effect2:
146 persson 1831 return _("MIDI Controller 13");
147 schoenebeck 1225 case gig::dimension_genpurpose1:
148 persson 1831 return _("Slider, MIDI Controller 16");
149 schoenebeck 1225 case gig::dimension_genpurpose2:
150 persson 1831 return _("Slider, MIDI Controller 17");
151 schoenebeck 1225 case gig::dimension_genpurpose3:
152 persson 1831 return _("Slider, MIDI Controller 18");
153 schoenebeck 1225 case gig::dimension_genpurpose4:
154 persson 1831 return _("Slider, MIDI Controller 19");
155 schoenebeck 1225 case gig::dimension_sustainpedal:
156 persson 1831 return _("MIDI Controller 64");
157 schoenebeck 1225 case gig::dimension_portamento:
158 persson 1831 return _("MIDI Controller 65");
159 schoenebeck 1225 case gig::dimension_sostenutopedal:
160 persson 1831 return _("MIDI Controller 66");
161 schoenebeck 1225 case gig::dimension_softpedal:
162 persson 1831 return _("MIDI Controller 67");
163 schoenebeck 1225 case gig::dimension_genpurpose5:
164 persson 1831 return _("Button, MIDI Controller 80");
165 schoenebeck 1225 case gig::dimension_genpurpose6:
166 persson 1831 return _("Button, MIDI Controller 81");
167 schoenebeck 1225 case gig::dimension_genpurpose7:
168 persson 1831 return _("Button, MIDI Controller 82");
169 schoenebeck 1225 case gig::dimension_genpurpose8:
170 persson 1831 return _("Button, MIDI Controller 83");
171 schoenebeck 1225 case gig::dimension_effect1depth:
172 persson 1831 return _("MIDI Controller 91");
173 schoenebeck 1225 case gig::dimension_effect2depth:
174 persson 1831 return _("MIDI Controller 92");
175 schoenebeck 1225 case gig::dimension_effect3depth:
176 persson 1831 return _("MIDI Controller 93");
177 schoenebeck 1225 case gig::dimension_effect4depth:
178 persson 1831 return _("MIDI Controller 94");
179 schoenebeck 1225 case gig::dimension_effect5depth:
180 persson 1831 return _("MIDI Controller 95");
181 schoenebeck 1225 default:
182 persson 1831 return _("Please report this !!!");
183 schoenebeck 1225 }
184     }
185    
186     DimensionManager::DimensionManager() :
187     addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE)
188     {
189 persson 1831 set_title(_("Dimensions of selected Region"));
190 schoenebeck 1225 add(vbox);
191     scrolledWindow.add(treeView);
192     vbox.pack_start(scrolledWindow);
193     scrolledWindow.show();
194 schoenebeck 1411 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
195 schoenebeck 1225 buttonBox.set_layout(Gtk::BUTTONBOX_END);
196     buttonBox.set_border_width(5);
197     buttonBox.show();
198 schoenebeck 1411 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
199     buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
200 schoenebeck 1225 addButton.show();
201     removeButton.show();
202    
203     // setup the table
204     refTableModel = Gtk::ListStore::create(tableModel);
205     treeView.set_model(refTableModel);
206 persson 1831 treeView.append_column(_("Dimension Type"), tableModel.m_dim_type);
207     treeView.append_column(_("Bits"), tableModel.m_bits);
208     treeView.append_column(_("Zones"), tableModel.m_zones);
209     treeView.append_column(_("Description"), tableModel.m_description);
210 schoenebeck 1225 treeView.show();
211    
212     addButton.signal_clicked().connect(
213     sigc::mem_fun(*this, &DimensionManager::addDimension)
214     );
215    
216     removeButton.signal_clicked().connect(
217     sigc::mem_fun(*this, &DimensionManager::removeDimension)
218     );
219    
220     show_all_children();
221 schoenebeck 2558
222     resize(460,300);
223 schoenebeck 1225 }
224    
225     // update all GUI elements according to current gig::Region informations
226     void DimensionManager::refreshManager() {
227     refTableModel->clear();
228 persson 1677 if (region) {
229     for (int i = 0; i < region->Dimensions; i++) {
230     gig::dimension_def_t* dim = &region->pDimensionDefinitions[i];
231     Gtk::TreeModel::Row row = *(refTableModel->append());
232 schoenebeck 2558 row[tableModel.m_dim_type] = dimTypeAsString(dim->dimension);
233 persson 1677 row[tableModel.m_bits] = dim->bits;
234 persson 1733 row[tableModel.m_zones] = dim->zones;
235 persson 1677 row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
236     row[tableModel.m_definition] = dim;
237     }
238 schoenebeck 1225 }
239 persson 1677 set_sensitive(region);
240 schoenebeck 1225 }
241    
242     void DimensionManager::show(gig::Region* region) {
243     this->region = region;
244     refreshManager();
245     Gtk::Window::show();
246     deiconify();
247     }
248    
249 persson 1677 void DimensionManager::set_region(gig::Region* region) {
250     this->region = region;
251     refreshManager();
252     }
253    
254 schoenebeck 1225 void DimensionManager::addDimension() {
255     try {
256 persson 1831 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
257 schoenebeck 1225 // add dimension type combo box to the dialog
258     Glib::RefPtr<Gtk::ListStore> refComboModel = Gtk::ListStore::create(comboModel);
259     for (int i = 0x01; i < 0xff; i++) {
260     Glib::ustring sType =
261 schoenebeck 2558 dimTypeAsString(static_cast<gig::dimension_t>(i));
262 schoenebeck 1225 if (sType.find("Unknown") != 0) {
263     Gtk::TreeModel::Row row = *(refComboModel->append());
264     row[comboModel.m_type_id] = i;
265     row[comboModel.m_type_name] = sType;
266     }
267     }
268 persson 1733 Gtk::Table table(2, 2);
269 persson 2169 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
270 schoenebeck 1225 Gtk::ComboBox comboDimType;
271     comboDimType.set_model(refComboModel);
272     comboDimType.pack_start(comboModel.m_type_id);
273     comboDimType.pack_start(comboModel.m_type_name);
274 persson 2169 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
275 persson 1733 table.attach(labelDimType, 0, 1, 0, 1);
276     table.attach(comboDimType, 1, 2, 0, 1);
277     table.attach(labelZones, 0, 1, 1, 2);
278     dialog.get_vbox()->pack_start(table);
279    
280     // number of zones: use a combo box with fix values for gig
281     // v2 and a spin button for v3
282 schoenebeck 1225 Gtk::ComboBoxText comboZones;
283 persson 1733 Gtk::SpinButton spinZones;
284     bool version2 = false;
285     if (region) {
286     gig::File* file = (gig::File*)region->GetParent()->GetParent();
287     version2 = file->pVersion && file->pVersion->major == 2;
288 schoenebeck 1225 }
289 persson 1733 if (version2) {
290     for (int i = 1; i <= 5; i++) {
291     char buf[3];
292     sprintf(buf, "%d", 1 << i);
293 persson 2507 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
294 persson 1733 comboZones.append_text(buf);
295 persson 2169 #else
296     comboZones.append(buf);
297     #endif
298 persson 1733 }
299     table.attach(comboZones, 1, 2, 1, 2);
300     } else {
301     spinZones.set_increments(1, 8);
302     spinZones.set_numeric(true);
303     spinZones.set_range(2, 128);
304     spinZones.set_value(2);
305     table.attach(spinZones, 1, 2, 1, 2);
306     }
307    
308 schoenebeck 1225 dialog.add_button(Gtk::Stock::OK, 0);
309     dialog.add_button(Gtk::Stock::CANCEL, 1);
310     dialog.show_all_children();
311 persson 1733
312 schoenebeck 1225 if (!dialog.run()) { // OK selected ...
313     Gtk::TreeModel::iterator iterType = comboDimType.get_active();
314     if (!iterType) return;
315     Gtk::TreeModel::Row rowType = *iterType;
316     if (!rowType) return;
317     gig::dimension_def_t dim;
318     int iTypeID = rowType[comboModel.m_type_id];
319     dim.dimension = static_cast<gig::dimension_t>(iTypeID);
320 persson 1733
321     if (version2) {
322     if (comboZones.get_active_row_number() < 0) return;
323     dim.bits = comboZones.get_active_row_number() + 1;
324     dim.zones = 1 << dim.bits;
325     } else {
326     dim.zones = spinZones.get_value_as_int();
327     // Find the number of bits required to hold the
328     // specified amount of zones.
329     int zoneBits = dim.zones - 1;
330     for (dim.bits = 0; zoneBits > 1; dim.bits += 2, zoneBits >>= 2);
331     dim.bits += zoneBits;
332     }
333 schoenebeck 1225 printf(
334     "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
335     dim.dimension, dim.bits, dim.zones
336     );
337 schoenebeck 1322 // notify everybody that we're going to update the region
338     region_to_be_changed_signal.emit(region);
339 schoenebeck 1225 // add the new dimension to the region
340     // (implicitly creates new dimension regions)
341     region->AddDimension(&dim);
342     // let everybody know there was a change
343 schoenebeck 1322 region_changed_signal.emit(region);
344 schoenebeck 1225 // update all GUI elements
345     refreshManager();
346     }
347     } catch (RIFF::Exception e) {
348 schoenebeck 1322 // notify that the changes are over (i.e. to avoid dead locks)
349     region_changed_signal.emit(region);
350     // show error message
351 persson 1831 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
352 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
353     msg.run();
354     }
355     }
356    
357     void DimensionManager::removeDimension() {
358     Glib::RefPtr<Gtk::TreeSelection> sel = treeView.get_selection();
359     Gtk::TreeModel::iterator it = sel->get_selected();
360     if (it) {
361     try {
362 schoenebeck 1322 // notify everybody that we're going to update the region
363     region_to_be_changed_signal.emit(region);
364 schoenebeck 1225 // remove selected dimension
365     Gtk::TreeModel::Row row = *it;
366     gig::dimension_def_t* dim = row[tableModel.m_definition];
367     region->DeleteDimension(dim);
368     // let everybody know there was a change
369 schoenebeck 1322 region_changed_signal.emit(region);
370 persson 1623 // update all GUI elements
371     refreshManager();
372 schoenebeck 1225 } catch (RIFF::Exception e) {
373 schoenebeck 1322 // notify that the changes are over (i.e. to avoid dead locks)
374     region_changed_signal.emit(region);
375     // show error message
376 persson 1831 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
377 schoenebeck 1225 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
378     msg.run();
379     }
380     }
381     }

  ViewVC Help
Powered by ViewVC