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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2558 - (show 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 /*
2 * Copyright (C) 2006-2014 Andreas Persson
3 *
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 #include <gtkmm/spinbutton.h>
27 #include <gtkmm/table.h>
28
29 #include "global.h"
30 #include "compat.h"
31
32 // returns a human readable name of the given dimension type
33 Glib::ustring dimTypeAsString(gig::dimension_t d) {
34 char buf[32];
35 switch (d) {
36 case gig::dimension_none:
37 return _("None");
38 case gig::dimension_samplechannel:
39 return _("Sample Channel");
40 case gig::dimension_layer:
41 return _("Layer");
42 case gig::dimension_velocity:
43 return _("Velocity");
44 case gig::dimension_channelaftertouch:
45 return _("Aftertouch");
46 case gig::dimension_releasetrigger:
47 return _("Release Trigger");
48 case gig::dimension_keyboard:
49 return _("Keyswitching");
50 case gig::dimension_roundrobin:
51 return _("Round Robin");
52 case gig::dimension_random:
53 return _("Random Generator");
54 case gig::dimension_smartmidi:
55 return _("Smart MIDI");
56 case gig::dimension_roundrobinkeyboard:
57 return _("Keyboard Round Robin");
58 case gig::dimension_modwheel:
59 return _("Modulation Wheel");
60 case gig::dimension_breath:
61 return _("Breath Ctrl.");
62 case gig::dimension_foot:
63 return _("Foot Ctrl.");
64 case gig::dimension_portamentotime:
65 return _("Portamento Time Ctrl.");
66 case gig::dimension_effect1:
67 return _("Effect Ctrl. 1");
68 case gig::dimension_effect2:
69 return _("Effect Ctrl. 2");
70 case gig::dimension_genpurpose1:
71 return _("General Purpose Ctrl. 1");
72 case gig::dimension_genpurpose2:
73 return _("General Purpose Ctrl. 2");
74 case gig::dimension_genpurpose3:
75 return _("General Purpose Ctrl. 3");
76 case gig::dimension_genpurpose4:
77 return _("General Purpose Ctrl. 4");
78 case gig::dimension_sustainpedal:
79 return _("Sustain Pedal");
80 case gig::dimension_portamento:
81 return _("Portamento Ctrl.");
82 case gig::dimension_sostenutopedal:
83 return _("Sostenuto Pedal");
84 case gig::dimension_softpedal:
85 return _("Soft Pedal");
86 case gig::dimension_genpurpose5:
87 return _("General Purpose Ctrl. 5");
88 case gig::dimension_genpurpose6:
89 return _("General Purpose Ctrl. 6");
90 case gig::dimension_genpurpose7:
91 return _("General Purpose Ctrl. 7");
92 case gig::dimension_genpurpose8:
93 return _("General Purpose Ctrl. 8");
94 case gig::dimension_effect1depth:
95 return _("Effect 1 Depth");
96 case gig::dimension_effect2depth:
97 return _("Effect 2 Depth");
98 case gig::dimension_effect3depth:
99 return _("Effect 3 Depth");
100 case gig::dimension_effect4depth:
101 return _("Effect 4 Depth");
102 case gig::dimension_effect5depth:
103 return _("Effect 5 Depth");
104 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 return _("Dimension not in use");
115 case gig::dimension_samplechannel:
116 return _("If used sample has more than one channel (thus is not mono)");
117 case gig::dimension_layer:
118 return _("For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers");
119 case gig::dimension_velocity:
120 return _("Key Velocity (this is the only dimension in gig2 where the ranges can exactly be defined)");
121 case gig::dimension_channelaftertouch:
122 return _("Channel Key Pressure");
123 case gig::dimension_releasetrigger:
124 return _("Special dimension for triggering samples on releasing a key");
125 case gig::dimension_keyboard:
126 return _("Dimension for keyswitching (keyboard)");
127 case gig::dimension_roundrobin:
128 return _("Different samples triggered each time a note is played, dimension regions selected in sequence");
129 case gig::dimension_random:
130 return _("Different samples triggered each time a note is played, random order");
131 case gig::dimension_smartmidi:
132 return _("For MIDI tools like legato and repetition mode");
133 case gig::dimension_roundrobinkeyboard:
134 return _("Different samples triggered each time a note is played, any key advances the counter");
135 case gig::dimension_modwheel:
136 return _("MIDI Controller 1");
137 case gig::dimension_breath:
138 return _("MIDI Controller 2");
139 case gig::dimension_foot:
140 return _("MIDI Controller 4");
141 case gig::dimension_portamentotime:
142 return _("MIDI Controller 5");
143 case gig::dimension_effect1:
144 return _("MIDI Controller 12");
145 case gig::dimension_effect2:
146 return _("MIDI Controller 13");
147 case gig::dimension_genpurpose1:
148 return _("Slider, MIDI Controller 16");
149 case gig::dimension_genpurpose2:
150 return _("Slider, MIDI Controller 17");
151 case gig::dimension_genpurpose3:
152 return _("Slider, MIDI Controller 18");
153 case gig::dimension_genpurpose4:
154 return _("Slider, MIDI Controller 19");
155 case gig::dimension_sustainpedal:
156 return _("MIDI Controller 64");
157 case gig::dimension_portamento:
158 return _("MIDI Controller 65");
159 case gig::dimension_sostenutopedal:
160 return _("MIDI Controller 66");
161 case gig::dimension_softpedal:
162 return _("MIDI Controller 67");
163 case gig::dimension_genpurpose5:
164 return _("Button, MIDI Controller 80");
165 case gig::dimension_genpurpose6:
166 return _("Button, MIDI Controller 81");
167 case gig::dimension_genpurpose7:
168 return _("Button, MIDI Controller 82");
169 case gig::dimension_genpurpose8:
170 return _("Button, MIDI Controller 83");
171 case gig::dimension_effect1depth:
172 return _("MIDI Controller 91");
173 case gig::dimension_effect2depth:
174 return _("MIDI Controller 92");
175 case gig::dimension_effect3depth:
176 return _("MIDI Controller 93");
177 case gig::dimension_effect4depth:
178 return _("MIDI Controller 94");
179 case gig::dimension_effect5depth:
180 return _("MIDI Controller 95");
181 default:
182 return _("Please report this !!!");
183 }
184 }
185
186 DimensionManager::DimensionManager() :
187 addButton(Gtk::Stock::ADD), removeButton(Gtk::Stock::REMOVE)
188 {
189 set_title(_("Dimensions of selected Region"));
190 add(vbox);
191 scrolledWindow.add(treeView);
192 vbox.pack_start(scrolledWindow);
193 scrolledWindow.show();
194 vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
195 buttonBox.set_layout(Gtk::BUTTONBOX_END);
196 buttonBox.set_border_width(5);
197 buttonBox.show();
198 buttonBox.pack_start(addButton, Gtk::PACK_SHRINK);
199 buttonBox.pack_start(removeButton, Gtk::PACK_SHRINK);
200 addButton.show();
201 removeButton.show();
202
203 // setup the table
204 refTableModel = Gtk::ListStore::create(tableModel);
205 treeView.set_model(refTableModel);
206 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 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
222 resize(460,300);
223 }
224
225 // update all GUI elements according to current gig::Region informations
226 void DimensionManager::refreshManager() {
227 refTableModel->clear();
228 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 row[tableModel.m_dim_type] = dimTypeAsString(dim->dimension);
233 row[tableModel.m_bits] = dim->bits;
234 row[tableModel.m_zones] = dim->zones;
235 row[tableModel.m_description] = __dimDescriptionAsString(dim->dimension);
236 row[tableModel.m_definition] = dim;
237 }
238 }
239 set_sensitive(region);
240 }
241
242 void DimensionManager::show(gig::Region* region) {
243 this->region = region;
244 refreshManager();
245 Gtk::Window::show();
246 deiconify();
247 }
248
249 void DimensionManager::set_region(gig::Region* region) {
250 this->region = region;
251 refreshManager();
252 }
253
254 void DimensionManager::addDimension() {
255 try {
256 Gtk::Dialog dialog(_("New Dimension"), true /*modal*/);
257 // 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 dimTypeAsString(static_cast<gig::dimension_t>(i));
262 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 Gtk::Table table(2, 2);
269 Gtk::Label labelDimType(_("Dimension:"), Gtk::ALIGN_START);
270 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 Gtk::Label labelZones(_("Zones:"), Gtk::ALIGN_START);
275 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 Gtk::ComboBoxText comboZones;
283 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 }
289 if (version2) {
290 for (int i = 1; i <= 5; i++) {
291 char buf[3];
292 sprintf(buf, "%d", 1 << i);
293 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
294 comboZones.append_text(buf);
295 #else
296 comboZones.append(buf);
297 #endif
298 }
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 dialog.add_button(Gtk::Stock::OK, 0);
309 dialog.add_button(Gtk::Stock::CANCEL, 1);
310 dialog.show_all_children();
311
312 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
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 printf(
334 "Adding dimension (type=0x%x, bits=%d, zones=%d)\n",
335 dim.dimension, dim.bits, dim.zones
336 );
337 // notify everybody that we're going to update the region
338 region_to_be_changed_signal.emit(region);
339 // 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 region_changed_signal.emit(region);
344 // update all GUI elements
345 refreshManager();
346 }
347 } catch (RIFF::Exception e) {
348 // notify that the changes are over (i.e. to avoid dead locks)
349 region_changed_signal.emit(region);
350 // show error message
351 Glib::ustring txt = _("Could not add dimension: ") + e.Message;
352 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 // notify everybody that we're going to update the region
363 region_to_be_changed_signal.emit(region);
364 // 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 region_changed_signal.emit(region);
370 // update all GUI elements
371 refreshManager();
372 } catch (RIFF::Exception e) {
373 // notify that the changes are over (i.e. to avoid dead locks)
374 region_changed_signal.emit(region);
375 // show error message
376 Glib::ustring txt = _("Could not remove dimension: ") + e.Message;
377 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
378 msg.run();
379 }
380 }
381 }

  ViewVC Help
Powered by ViewVC