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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1085 - (show annotations) (download)
Thu Mar 8 19:18:23 2007 UTC (17 years, 1 month ago) by schoenebeck
File size: 63102 byte(s)
- started to implement "Add Samples" function
  (not yet fully working though)

1 /*
2 * Copyright (C) 2006, 2007 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 <libintl.h>
21 #include <iostream>
22
23 #include "mainwindow.h"
24
25 #include <gtkmm/filechooserdialog.h>
26 #include <gtkmm/stock.h>
27 #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6
28 #define ABOUT_DIALOG
29 #include <gtkmm/aboutdialog.h>
30 #include <gtkmm/messagedialog.h>
31 #endif
32
33 #include <stdio.h>
34 #include <sndfile.h>
35
36 #define _(String) gettext(String)
37
38 template<class T> inline std::string ToString(T o) {
39 std::stringstream ss;
40 ss << o;
41 return ss.str();
42 }
43
44 bool update_gui;
45
46 uint8_t& access_UnityNote(gig::DimensionRegion* dimreg)
47 {
48 return dimreg->UnityNote;
49 }
50 int16_t& access_FineTune(gig::DimensionRegion* dimreg)
51 {
52 return dimreg->FineTune;
53 }
54 uint32_t& access_SampleLoops(gig::DimensionRegion* dimreg)
55 {
56 return dimreg->SampleLoops;
57 }
58 uint8_t& access_Crossfade_in_start(gig::DimensionRegion* dimreg)
59 {
60 return dimreg->Crossfade.in_start;
61 }
62 uint8_t& access_Crossfade_in_end(gig::DimensionRegion* dimreg)
63 {
64 return dimreg->Crossfade.in_end;
65 }
66 uint8_t& access_Crossfade_out_start(gig::DimensionRegion* dimreg)
67 {
68 return dimreg->Crossfade.out_start;
69 }
70 uint8_t& access_Crossfade_out_end(gig::DimensionRegion* dimreg)
71 {
72 return dimreg->Crossfade.out_end;
73 }
74
75 namespace {
76 const char* const controlChangeTexts[] = {
77 "none", "channelaftertouch", "velocity",
78 0,
79 "modwheel", // "Modulation Wheel or Lever",
80 "breath", // "Breath Controller",
81 0,
82 "foot", // "Foot Controller",
83 "portamentotime", // "Portamento Time",
84 0, 0, 0, 0, 0, 0,
85 "effect1", // "Effect Control 1",
86 "effect2", // "Effect Control 2",
87 0, 0,
88 "genpurpose1", // "General Purpose Controller 1",
89 "genpurpose2", // "General Purpose Controller 2",
90 "genpurpose3", // "General Purpose Controller 3",
91 "genpurpose4", // "General Purpose Controller 4",
92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 0, 0, 0, 0, 0, 0,
95 "sustainpedal", // "Damper Pedal on/off (Sustain)",
96 "portamento", // "Portamento On/Off",
97 "sostenuto", // "Sustenuto On/Off",
98 "softpedal", // "Soft Pedal On/Off",
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 "genpurpose5", // "General Purpose Controller 5",
101 "genpurpose6", // "General Purpose Controller 6",
102 "genpurpose7", // "General Purpose Controller 7",
103 "genpurpose8", // "General Purpose Controller 8",
104 0, 0, 0, 0, 0, 0, 0,
105 "effect1depth", // "Effects 1 Depth",
106 "effect2depth", // "Effects 2 Depth",
107 "effect3depth", // "Effects 3 Depth",
108 "effect4depth", // "Effects 4 Depth",
109 "effect5depth", // "Effects 5 Depth"
110 };
111 }
112
113 void MainWindow::addString(char* labelText, Gtk::Label*& label,
114 Gtk::Entry*& widget)
115 {
116 label = new Gtk::Label(Glib::ustring(labelText) + ":");
117 label->set_alignment(Gtk::ALIGN_LEFT);
118
119 table[pageno]->attach(*label, 1, 2, rowno, rowno + 1,
120 Gtk::FILL, Gtk::SHRINK);
121
122 widget = new Gtk::Entry();
123
124 table[pageno]->attach(*widget, 2, 3, rowno, rowno + 1,
125 Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
126
127 rowno++;
128 }
129
130 LabelWidget::LabelWidget(char* labelText, Gtk::Widget& widget) :
131 label(Glib::ustring(labelText) + ":"),
132 widget(widget)
133 {
134 label.set_alignment(Gtk::ALIGN_LEFT);
135 }
136
137 void LabelWidget::set_sensitive(bool sensitive)
138 {
139 label.set_sensitive(sensitive);
140 widget.set_sensitive(sensitive);
141 }
142
143 NumEntryGain::NumEntryGain(char* labelText,
144 double lower = 0, double upper = 127,
145 int decimals = 0) :
146 NumEntry<gig::DimensionRegion>(labelText, lower, upper, decimals)
147 {
148 spinbutton.signal_value_changed().connect(
149 sigc::mem_fun(*this, &NumEntryGain::value_changed));
150 }
151
152 void NumEntryGain::value_changed()
153 {
154 if (dimreg && update_gui) {
155 dimreg->Gain = int32_t(spinbutton.get_value() * -655360.0);
156 }
157 }
158
159 void NumEntryGain::set_dimreg(gig::DimensionRegion* dimreg)
160 {
161 this->dimreg = 0;
162 set_value(dimreg->Gain / -655360.0);
163 this->dimreg = dimreg;
164 }
165
166
167 NumEntryPermille::NumEntryPermille(char* labelText,
168 uint16_t gig::DimensionRegion::* param,
169 double lower, double upper, int decimals) :
170 NumEntry<gig::DimensionRegion>(labelText, lower, upper, decimals),
171 param(param)
172 {
173 spinbutton.signal_value_changed().connect(
174 sigc::mem_fun(*this, &NumEntryPermille::value_changed));
175 }
176
177 void NumEntryPermille::value_changed()
178 {
179 if (dimreg && update_gui) {
180 dimreg->*param = uint16_t(spinbutton.get_value() * 10 + 0.5);
181 }
182 }
183
184 void NumEntryPermille::set_dimreg(gig::DimensionRegion* dimreg)
185 {
186 this->dimreg = 0;
187 set_value(dimreg->*param / 10.0);
188 this->dimreg = dimreg;
189 }
190
191
192 NoteEntry::NoteEntry(char* labelText, uint8_t& (*access)(gig::DimensionRegion*)) :
193 NumEntryX<uint8_t>(labelText, access)
194 {
195 spinbutton.signal_input().connect(
196 sigc::mem_fun(*this, &NoteEntry::on_input));
197 spinbutton.signal_output().connect(
198 sigc::mem_fun(*this, &NoteEntry::on_output));
199 }
200
201 const char* notes[] = {
202 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
203 };
204
205
206 // Convert the Entry text to a number
207 int NoteEntry::on_input(double* new_value)
208 {
209 const char* str = spinbutton.get_text().c_str();
210
211 int i;
212 for (i = 11 ; i >= 0 ; i--) {
213 if (strncmp(str, notes[i], strlen(notes[i])) == 0) break;
214 }
215 if (i >= 0) {
216 char* endptr;
217 long x = strtol(str + strlen(notes[i]), &endptr, 10);
218 if (endptr != str + strlen(notes[i])) {
219 *new_value = i + (x + 1) * 12;
220 return true;
221 }
222 }
223 return Gtk::INPUT_ERROR;
224 }
225
226 // Convert the Adjustment position to text
227 bool NoteEntry::on_output()
228 {
229 int x = int(spinbutton.get_adjustment()->get_value());
230 char buf[10];
231 sprintf(buf, "%s%d", notes[x % 12], x / 12 - 1);
232 spinbutton.set_text(buf);
233 return true;
234 }
235
236 BoolEntry::BoolEntry(char* labelText, bool gig::DimensionRegion::* param) :
237 LabelWidget(labelText, checkbutton),
238 param(param)
239 {
240 checkbutton.signal_toggled().connect(
241 sigc::mem_fun(*this, &BoolEntry::value_changed));
242 }
243
244 void BoolEntry::value_changed()
245 {
246 if (dimreg && update_gui) {
247 dimreg->*param = checkbutton.get_active();
248 }
249 }
250
251 void BoolEntry::set_dimreg(gig::DimensionRegion* dimreg)
252 {
253 this->dimreg = 0;
254 checkbutton.set_active(dimreg->*param);
255 this->dimreg = dimreg;
256 }
257
258 ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(
259 char* labelText,
260 gig::leverage_ctrl_t gig::DimensionRegion::* param) :
261 align(0, 0, 0, 0),
262 LabelWidget(labelText, align),
263 param(param)
264 {
265 for (int i = 0 ; i < 99 ; i++) {
266 if (controlChangeTexts[i]) {
267 combobox.append_text(controlChangeTexts[i]);
268 }
269 }
270 combobox.signal_changed().connect(
271 sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));
272 align.add(combobox);
273 }
274
275 void ChoiceEntryLeverageCtrl::value_changed()
276 {
277 if (dimreg && update_gui) {
278 int rowno = combobox.get_active_row_number();
279 switch (rowno)
280 {
281 case -1:
282 break;
283 case 0:
284 (dimreg->*param).type = gig::leverage_ctrl_t::type_none;
285 break;
286 case 1:
287 (dimreg->*param).type =
288 gig::leverage_ctrl_t::type_channelaftertouch;
289 break;
290 case 2:
291 (dimreg->*param).type = gig::leverage_ctrl_t::type_velocity;
292 break;
293 default:
294 (dimreg->*param).type = gig::leverage_ctrl_t::type_controlchange;
295 int x = 3;
296 for (int cc = 0 ; cc < 96 ; cc++) {
297 if (controlChangeTexts[cc + 3]) {
298 if (rowno == x) {
299 (dimreg->*param).controller_number = cc;
300 break;
301 }
302 x++;
303 }
304 }
305 break;
306 }
307 }
308 }
309
310 void ChoiceEntryLeverageCtrl::set_dimreg(gig::DimensionRegion* dimreg)
311 {
312 this->dimreg = 0;
313 gig::leverage_ctrl_t c = dimreg->*param;
314 int x;
315 switch (c.type)
316 {
317 case gig::leverage_ctrl_t::type_none:
318 x = 0;
319 break;
320 case gig::leverage_ctrl_t::type_channelaftertouch:
321 x = 1;
322 break;
323 case gig::leverage_ctrl_t::type_velocity:
324 x = 2;
325 break;
326 case gig::leverage_ctrl_t::type_controlchange:
327 x = -1;
328 for (int cc = 0 ; cc < 96 ; cc++) {
329 if (controlChangeTexts[cc + 3]) {
330 x++;
331 if (c.controller_number == cc) {
332 x += 3;
333 break;
334 }
335 }
336 }
337 break;
338 default:
339 x = -1;
340 break;
341 }
342 combobox.set_active(x);
343 this->dimreg = dimreg;
344 }
345
346 void MainWindow::addHeader(char* text)
347 {
348 if (firstRowInBlock < rowno - 1)
349 {
350 Gtk::Label* filler = new Gtk::Label(" ");
351 table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,
352 Gtk::FILL, Gtk::SHRINK);
353 }
354 Glib::ustring str = "<b>";
355 str += text;
356 str += "</b>";
357 Gtk::Label* label = new Gtk::Label(str);
358 label->set_use_markup();
359 label->set_alignment(Gtk::ALIGN_LEFT);
360 table[pageno]->attach(*label, 0, 3, rowno, rowno + 1,
361 Gtk::FILL, Gtk::SHRINK);
362 rowno++;
363 firstRowInBlock = rowno;
364 }
365
366 void MainWindow::nextPage()
367 {
368 if (firstRowInBlock < rowno - 1)
369 {
370 Gtk::Label* filler = new Gtk::Label(" ");
371 table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,
372 Gtk::FILL, Gtk::SHRINK);
373 }
374 pageno++;
375 rowno = 0;
376 firstRowInBlock = 0;
377 }
378
379 void MainWindow::addProp(LabelWidget& prop)
380 {
381 table[pageno]->attach(prop.label, 1, 2, rowno, rowno + 1,
382 Gtk::FILL, Gtk::SHRINK);
383 table[pageno]->attach(prop.widget, 2, 3, rowno, rowno + 1,
384 Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
385 rowno++;
386 }
387
388
389
390
391 MainWindow::MainWindow() :
392 // eSample("Sample", wSample),
393 eVelocityUpperLimit("VelocityUpperLimit",
394 &gig::DimensionRegion::VelocityUpperLimit),
395 eEG1PreAttack("PreAttack", &gig::DimensionRegion::EG1PreAttack, 0, 100, 2),
396 eEG1Attack("Attack", &gig::DimensionRegion::EG1Attack, 0, 60, 3),
397 eEG1Decay1("Decay1", &gig::DimensionRegion::EG1Decay1, 0.005, 60, 3),
398 eEG1Decay2("Decay2", &gig::DimensionRegion::EG1Decay2, 0, 60, 3),
399 eEG1InfiniteSustain("InfiniteSustain",
400 &gig::DimensionRegion::EG1InfiniteSustain),
401 eEG1Sustain("Sustain", &gig::DimensionRegion::EG1Sustain, 0, 100, 2),
402 eEG1Release("Release", &gig::DimensionRegion::EG1Release, 0, 60, 3),
403 eEG1Hold("Hold", &gig::DimensionRegion::EG1Hold),
404 eEG1Controller("Controller", &gig::DimensionRegion::EG1Controller),
405 eEG1ControllerInvert("ControllerInvert",
406 &gig::DimensionRegion::EG1ControllerInvert),
407 eEG1ControllerAttackInfluence("ControllerAttackInfluence",
408 &gig::DimensionRegion::EG1ControllerAttackInfluence,
409 0, 3),
410 eEG1ControllerDecayInfluence("ControllerDecayInfluence",
411 &gig::DimensionRegion::EG1ControllerDecayInfluence,
412 0, 3),
413 eEG1ControllerReleaseInfluence("ControllerReleaseInfluence",
414 &gig::DimensionRegion::EG1ControllerReleaseInfluence,
415 0, 3),
416 eLFO1Frequency("Frequency", &gig::DimensionRegion::LFO1Frequency,
417 0.1, 10, 2),
418 eLFO1InternalDepth("InternalDepth",
419 &gig::DimensionRegion::LFO1InternalDepth, 0, 1200),
420 eLFO1ControlDepth("ControlDepth", &gig::DimensionRegion::LFO1ControlDepth,
421 0, 1200),
422 eLFO1Controller("Controller", &gig::DimensionRegion::LFO1Controller),
423 eLFO1FlipPhase("FlipPhase", &gig::DimensionRegion::LFO1FlipPhase),
424 eLFO1Sync("Sync", &gig::DimensionRegion::LFO1Sync),
425 eEG2PreAttack("PreAttack", &gig::DimensionRegion::EG2PreAttack, 0, 100, 2),
426 eEG2Attack("Attack", &gig::DimensionRegion::EG2Attack, 0, 60, 3),
427 eEG2Decay1("Decay1", &gig::DimensionRegion::EG2Decay1, 0.005, 60, 3),
428 eEG2Decay2("Decay2", &gig::DimensionRegion::EG2Decay2, 0, 60, 3),
429 eEG2InfiniteSustain("InfiniteSustain",
430 &gig::DimensionRegion::EG2InfiniteSustain),
431 eEG2Sustain("Sustain", &gig::DimensionRegion::EG2Sustain, 0, 100, 2),
432 eEG2Release("Release", &gig::DimensionRegion::EG2Release, 0, 60, 3),
433 eEG2Controller("Controller", &gig::DimensionRegion::EG2Controller),
434 eEG2ControllerInvert("ControllerInvert",
435 &gig::DimensionRegion::EG2ControllerInvert),
436 eEG2ControllerAttackInfluence("ControllerAttackInfluence",
437 &gig::DimensionRegion::EG2ControllerAttackInfluence,
438 0, 3),
439 eEG2ControllerDecayInfluence("ControllerDecayInfluence",
440 &gig::DimensionRegion::EG2ControllerDecayInfluence,
441 0, 3),
442 eEG2ControllerReleaseInfluence("ControllerReleaseInfluence",
443 &gig::DimensionRegion::EG2ControllerReleaseInfluence,
444 0, 3),
445 eLFO2Frequency("Frequency", &gig::DimensionRegion::LFO2Frequency,
446 0.1, 10, 2),
447 eLFO2InternalDepth("InternalDepth",
448 &gig::DimensionRegion::LFO2InternalDepth, 0, 1200),
449 eLFO2ControlDepth("ControlDepth",
450 &gig::DimensionRegion::LFO2ControlDepth, 0, 1200),
451 eLFO2Controller("Controller", &gig::DimensionRegion::LFO2Controller),
452 eLFO2FlipPhase("FlipPhase", &gig::DimensionRegion::LFO2FlipPhase),
453 eLFO2Sync("Sync", &gig::DimensionRegion::LFO2Sync),
454 eEG3Attack("Attack", &gig::DimensionRegion::EG3Attack, 0, 10, 3),
455 eEG3Depth("Depth", &gig::DimensionRegion::EG3Depth, -1200, 1200),
456 eLFO3Frequency("Frequency", &gig::DimensionRegion::LFO3Frequency,
457 0.1, 10, 2),
458 eLFO3InternalDepth("InternalDepth",
459 &gig::DimensionRegion::LFO3InternalDepth, 0, 1200),
460 eLFO3ControlDepth("ControlDepth", &gig::DimensionRegion::LFO3ControlDepth,
461 0, 1200),
462 eLFO3Controller("Controller", &gig::DimensionRegion::LFO3Controller),
463 eLFO3Sync("Sync", &gig::DimensionRegion::LFO3Sync),
464 eVCFEnabled("Enabled", &gig::DimensionRegion::VCFEnabled),
465 eVCFType("Type", &gig::DimensionRegion::VCFType),
466 eVCFCutoffController("CutoffController",
467 &gig::DimensionRegion::VCFCutoffController),
468 eVCFCutoffControllerInvert("CutoffControllerInvert",
469 &gig::DimensionRegion::VCFCutoffControllerInvert),
470 eVCFCutoff("Cutoff", &gig::DimensionRegion::VCFCutoff),
471 eVCFVelocityCurve("VelocityCurve", &gig::DimensionRegion::VCFVelocityCurve),
472 eVCFVelocityScale("VelocityScale", &gig::DimensionRegion::VCFVelocityScale),
473 eVCFVelocityDynamicRange("VelocityDynamicRange",
474 &gig::DimensionRegion::VCFVelocityDynamicRange,
475 0, 4),
476 eVCFResonance("Resonance", &gig::DimensionRegion::VCFResonance),
477 eVCFResonanceDynamic("ResonanceDynamic",
478 &gig::DimensionRegion::VCFResonanceDynamic),
479 eVCFResonanceController("ResonanceController",
480 &gig::DimensionRegion::VCFResonanceController),
481 eVCFKeyboardTracking("KeyboardTracking",
482 &gig::DimensionRegion::VCFKeyboardTracking),
483 eVCFKeyboardTrackingBreakpoint("KeyboardTrackingBreakpoint",
484 &gig::DimensionRegion::VCFKeyboardTrackingBreakpoint),
485 eVelocityResponseCurve("VelocityResponseCurve",
486 &gig::DimensionRegion::VelocityResponseCurve),
487 eVelocityResponseDepth("VelocityResponseDepth",
488 &gig::DimensionRegion::VelocityResponseDepth, 0, 4),
489 eVelocityResponseCurveScaling("VelocityResponseCurveScaling",
490 &gig::DimensionRegion::VelocityResponseCurveScaling),
491 eReleaseVelocityResponseCurve("ReleaseVelocityResponseCurve",
492 &gig::DimensionRegion::ReleaseVelocityResponseCurve),
493 eReleaseVelocityResponseDepth("ReleaseVelocityResponseDepth",
494 &gig::DimensionRegion::ReleaseVelocityResponseDepth,
495 0, 4),
496 eReleaseTriggerDecay("ReleaseTriggerDecay",
497 &gig::DimensionRegion::ReleaseTriggerDecay, 0, 8),
498 eCrossfade_in_start("Crossfade.in_start", &access_Crossfade_in_start),
499 eCrossfade_in_end("Crossfade.in_end", &access_Crossfade_in_end),
500 eCrossfade_out_start("Crossfade.out_start", &access_Crossfade_out_start),
501 eCrossfade_out_end("Crossfade.out_end", &access_Crossfade_out_end),
502 ePitchTrack("PitchTrack", &gig::DimensionRegion::PitchTrack),
503 eDimensionBypass("DimensionBypass", &gig::DimensionRegion::DimensionBypass),
504 ePan("Pan", &gig::DimensionRegion::Pan, -64, 63),
505 eSelfMask("SelfMask", &gig::DimensionRegion::SelfMask),
506 eAttenuationController("AttenuationController",
507 &gig::DimensionRegion::AttenuationController),
508 eInvertAttenuationController("InvertAttenuationController",
509 &gig::DimensionRegion::InvertAttenuationController),
510 eAttenuationControllerThreshold("AttenuationControllerThreshold",
511 &gig::DimensionRegion::AttenuationControllerThreshold),
512 eChannelOffset("ChannelOffset", &gig::DimensionRegion::ChannelOffset, 0, 9),
513 eSustainDefeat("SustainDefeat", &gig::DimensionRegion::SustainDefeat),
514 eMSDecode("MSDecode", &gig::DimensionRegion::MSDecode),
515 eSampleStartOffset("SampleStartOffset",
516 &gig::DimensionRegion::SampleStartOffset, 0, 2000),
517 eUnityNote("UnityNote", &access_UnityNote),
518 eFineTune("FineTune", &access_FineTune, -49, 50),
519 eGain("Gain", -96, 0, 2),
520 eSampleLoops("SampleLoops", &access_SampleLoops, 0, 1)
521 {
522 // set_border_width(5);
523 set_default_size(400, 200);
524
525
526 add(m_VBox);
527
528 // Handle selection
529 Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
530 tree_sel_ref->signal_changed().connect(
531 sigc::mem_fun(*this, &MainWindow::on_sel_change));
532
533 m_TreeView.signal_button_press_event().connect_notify(
534 sigc::mem_fun(*this, &MainWindow::on_button_release));
535
536 // Add the TreeView tab, inside a ScrolledWindow, with the button underneath:
537 m_ScrolledWindow.add(m_TreeViewNotebook);
538 m_ScrolledWindow.set_size_request(400, 600);
539 m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
540
541 for (int i = 0 ; i < 5 ; i++) {
542 table[i] = new Gtk::Table(3, 1);
543 table[i]->set_col_spacings(5);
544 }
545
546 pageno = 0;
547 rowno = 0;
548 firstRowInBlock = 0;
549
550 addString("Sample", lSample, wSample);
551 addProp(eVelocityUpperLimit);
552 addHeader("EG1");
553 addProp(eEG1PreAttack);
554 addProp(eEG1Attack);
555 addProp(eEG1Decay1);
556 addProp(eEG1Decay2);
557 addProp(eEG1InfiniteSustain);
558 addProp(eEG1Sustain);
559 addProp(eEG1Release);
560 addProp(eEG1Hold);
561 addProp(eEG1Controller);
562 addProp(eEG1ControllerInvert);
563 addProp(eEG1ControllerAttackInfluence);
564 addProp(eEG1ControllerDecayInfluence);
565 addProp(eEG1ControllerReleaseInfluence);
566 addHeader("LFO1");
567 addProp(eLFO1Frequency);
568 addProp(eLFO1InternalDepth);
569 addProp(eLFO1ControlDepth);
570 {
571 char* choices[] = { "internal", "modwheel", "breath",
572 "internal+modwheel", "internal+breath", 0 };
573 static const gig::lfo1_ctrl_t values[] = {
574 gig::lfo1_ctrl_internal,
575 gig::lfo1_ctrl_modwheel,
576 gig::lfo1_ctrl_breath,
577 gig::lfo1_ctrl_internal_modwheel,
578 gig::lfo1_ctrl_internal_breath
579 };
580 eLFO1Controller.set_choices(choices, values);
581 }
582 addProp(eLFO1Controller);
583 addProp(eLFO1FlipPhase);
584 addProp(eLFO1Sync);
585
586 nextPage();
587 addHeader("EG2");
588 addProp(eEG2PreAttack);
589 addProp(eEG2Attack);
590 addProp(eEG2Decay1);
591 addProp(eEG2Decay2);
592 addProp(eEG2InfiniteSustain);
593 addProp(eEG2Sustain);
594 addProp(eEG2Release);
595 addProp(eEG2Controller);
596 addProp(eEG2ControllerInvert);
597 addProp(eEG2ControllerAttackInfluence);
598 addProp(eEG2ControllerDecayInfluence);
599 addProp(eEG2ControllerReleaseInfluence);
600 addHeader("LFO2");
601 addProp(eLFO2Frequency);
602 addProp(eLFO2InternalDepth);
603 addProp(eLFO2ControlDepth);
604 {
605 char* choices[] = { "internal", "modwheel", "foot",
606 "internal+modwheel", "internal+foot", 0 };
607 static const gig::lfo2_ctrl_t values[] = {
608 gig::lfo2_ctrl_internal,
609 gig::lfo2_ctrl_modwheel,
610 gig::lfo2_ctrl_foot,
611 gig::lfo2_ctrl_internal_modwheel,
612 gig::lfo2_ctrl_internal_foot
613 };
614 eLFO2Controller.set_choices(choices, values);
615 }
616 addProp(eLFO2Controller);
617 addProp(eLFO2FlipPhase);
618 addProp(eLFO2Sync);
619
620 nextPage();
621
622 addHeader("EG3");
623 addProp(eEG3Attack);
624 addProp(eEG3Depth);
625 addHeader("LFO3");
626 addProp(eLFO3Frequency);
627 addProp(eLFO3InternalDepth);
628 addProp(eLFO3ControlDepth);
629 {
630 char* choices[] = { "internal", "modwheel", "aftertouch",
631 "internal+modwheel", "internal+aftertouch", 0 };
632 static const gig::lfo3_ctrl_t values[] = {
633 gig::lfo3_ctrl_internal,
634 gig::lfo3_ctrl_modwheel,
635 gig::lfo3_ctrl_aftertouch,
636 gig::lfo3_ctrl_internal_modwheel,
637 gig::lfo3_ctrl_internal_aftertouch
638 };
639 eLFO3Controller.set_choices(choices, values);
640 }
641 addProp(eLFO3Controller);
642 addProp(eLFO3Sync);
643 addHeader("VCF");
644 addProp(eVCFEnabled);
645 {
646 char* choices[] = { "lowpass", "lowpassturbo", "bandpass",
647 "highpass", "bandreject", 0 };
648 static const gig::vcf_type_t values[] = {
649 gig::vcf_type_lowpass,
650 gig::vcf_type_lowpassturbo,
651 gig::vcf_type_bandpass,
652 gig::vcf_type_highpass,
653 gig::vcf_type_bandreject
654 };
655 eVCFType.set_choices(choices, values);
656 }
657 addProp(eVCFType);
658 {
659 char* choices[] = { "none", "none2", "modwheel", "effect1", "effect2",
660 "breath", "foot", "sustainpedal", "softpedal",
661 "genpurpose7", "genpurpose8", "aftertouch", 0 };
662 static const gig::vcf_cutoff_ctrl_t values[] = {
663 gig::vcf_cutoff_ctrl_none,
664 gig::vcf_cutoff_ctrl_none2,
665 gig::vcf_cutoff_ctrl_modwheel,
666 gig::vcf_cutoff_ctrl_effect1,
667 gig::vcf_cutoff_ctrl_effect2,
668 gig::vcf_cutoff_ctrl_breath,
669 gig::vcf_cutoff_ctrl_foot,
670 gig::vcf_cutoff_ctrl_sustainpedal,
671 gig::vcf_cutoff_ctrl_softpedal,
672 gig::vcf_cutoff_ctrl_genpurpose7,
673 gig::vcf_cutoff_ctrl_genpurpose8,
674 gig::vcf_cutoff_ctrl_aftertouch
675 };
676 eVCFCutoffController.set_choices(choices, values);
677 }
678 addProp(eVCFCutoffController);
679 addProp(eVCFCutoffControllerInvert);
680 addProp(eVCFCutoff);
681 char* curve_type_texts[] = { "nonlinear", "linear", "special", 0 };
682 static const gig::curve_type_t curve_type_values[] = {
683 gig::curve_type_nonlinear,
684 gig::curve_type_linear,
685 gig::curve_type_special
686 };
687 eVCFVelocityCurve.set_choices(curve_type_texts, curve_type_values);
688 addProp(eVCFVelocityCurve);
689 addProp(eVCFVelocityScale);
690 addProp(eVCFVelocityDynamicRange);
691 addProp(eVCFResonance);
692 addProp(eVCFResonanceDynamic);
693 {
694 char* choices[] = { "none", "genpurpose3", "genpurpose4",
695 "genpurpose5", "genpurpose6", 0 };
696 static const gig::vcf_res_ctrl_t values[] = {
697 gig::vcf_res_ctrl_none,
698 gig::vcf_res_ctrl_genpurpose3,
699 gig::vcf_res_ctrl_genpurpose4,
700 gig::vcf_res_ctrl_genpurpose5,
701 gig::vcf_res_ctrl_genpurpose6
702 };
703 eVCFResonanceController.set_choices(choices, values);
704 }
705 addProp(eVCFResonanceController);
706 addProp(eVCFKeyboardTracking);
707 addProp(eVCFKeyboardTrackingBreakpoint);
708
709 nextPage();
710
711 eVelocityResponseCurve.set_choices(curve_type_texts, curve_type_values);
712 addProp(eVelocityResponseCurve);
713 addProp(eVelocityResponseDepth);
714 addProp(eVelocityResponseCurveScaling);
715 eReleaseVelocityResponseCurve.set_choices(curve_type_texts,
716 curve_type_values);
717 addProp(eReleaseVelocityResponseCurve);
718 addProp(eReleaseVelocityResponseDepth);
719 addProp(eReleaseTriggerDecay);
720 addProp(eCrossfade_in_start);
721 addProp(eCrossfade_in_end);
722 addProp(eCrossfade_out_start);
723 addProp(eCrossfade_out_end);
724 addProp(ePitchTrack);
725 {
726 char* choices[] = { "none", "effect4depth", "effect5depth", 0 };
727 static const gig::dim_bypass_ctrl_t values[] = {
728 gig::dim_bypass_ctrl_none,
729 gig::dim_bypass_ctrl_94,
730 gig::dim_bypass_ctrl_95
731 };
732 eDimensionBypass.set_choices(choices, values);
733 }
734 addProp(eDimensionBypass);
735 addProp(ePan);
736 addProp(eSelfMask);
737 addProp(eAttenuationController);
738 addProp(eInvertAttenuationController);
739 addProp(eAttenuationControllerThreshold);
740 addProp(eChannelOffset);
741 addProp(eSustainDefeat);
742
743 nextPage();
744 addProp(eMSDecode);
745 addProp(eSampleStartOffset);
746 addProp(eUnityNote);
747 addProp(eFineTune);
748 addProp(eGain);
749 addProp(eSampleLoops);
750 nextPage();
751
752 eEG1InfiniteSustain.signal_toggled().connect(
753 sigc::mem_fun(*this, &MainWindow::EG1InfiniteSustain_toggled) );
754 eEG2InfiniteSustain.signal_toggled().connect(
755 sigc::mem_fun(*this, &MainWindow::EG2InfiniteSustain_toggled) );
756 eEG1Controller.signal_changed().connect(
757 sigc::mem_fun(*this, &MainWindow::EG1Controller_changed) );
758 eEG2Controller.signal_changed().connect(
759 sigc::mem_fun(*this, &MainWindow::EG2Controller_changed) );
760 eLFO1Controller.signal_changed().connect(
761 sigc::mem_fun(*this, &MainWindow::LFO1Controller_changed) );
762 eLFO2Controller.signal_changed().connect(
763 sigc::mem_fun(*this, &MainWindow::LFO2Controller_changed) );
764 eLFO3Controller.signal_changed().connect(
765 sigc::mem_fun(*this, &MainWindow::LFO3Controller_changed) );
766 eAttenuationController.signal_changed().connect(
767 sigc::mem_fun(*this, &MainWindow::AttenuationController_changed) );
768 eVCFEnabled.signal_toggled().connect(
769 sigc::mem_fun(*this, &MainWindow::VCFEnabled_toggled) );
770 eVCFCutoffController.signal_changed().connect(
771 sigc::mem_fun(*this, &MainWindow::VCFCutoffController_changed) );
772 eVCFResonanceController.signal_changed().connect(
773 sigc::mem_fun(*this, &MainWindow::VCFResonanceController_changed) );
774
775 eCrossfade_in_start.signal_value_changed().connect(
776 sigc::mem_fun(*this, &MainWindow::crossfade1_changed));
777 eCrossfade_in_end.signal_value_changed().connect(
778 sigc::mem_fun(*this, &MainWindow::crossfade2_changed));
779 eCrossfade_out_start.signal_value_changed().connect(
780 sigc::mem_fun(*this, &MainWindow::crossfade3_changed));
781 eCrossfade_out_end.signal_value_changed().connect(
782 sigc::mem_fun(*this, &MainWindow::crossfade4_changed));
783
784 //m_Notebook.append_page(m_ScrolledWindow2, "Table");
785 m_Notebook.append_page(*table[0], "EG1");
786 m_Notebook.append_page(*table[1], "EG2");
787 m_Notebook.append_page(*table[2], "EG3");
788 m_Notebook.append_page(*table[3], "Velocity");
789 m_Notebook.append_page(*table[4], "Misc");
790 m_Notebook.set_size_request(400, 500);
791
792 m_HPaned.add1(m_ScrolledWindow);
793 m_HPaned.add2(m_Notebook);
794
795
796 m_TreeViewNotebook.append_page(m_TreeViewSamples, "Samples");
797 m_TreeViewNotebook.append_page(m_TreeView, "Instruments");
798
799
800 actionGroup = Gtk::ActionGroup::create();
801
802 actionGroup->add(Gtk::Action::create("MenuFile", _("_File")));
803 actionGroup->add(Gtk::Action::create("New", Gtk::Stock::NEW),
804 sigc::mem_fun(
805 *this, &MainWindow::on_action_file_new));
806 Glib::RefPtr<Gtk::Action> action =
807 Gtk::Action::create("Open", Gtk::Stock::OPEN);
808 action->property_label() = action->property_label() + "...";
809 actionGroup->add(action,
810 sigc::mem_fun(
811 *this, &MainWindow::on_action_file_open));
812 actionGroup->add(Gtk::Action::create("Save", Gtk::Stock::SAVE),
813 sigc::mem_fun(
814 *this, &MainWindow::on_action_file_save));
815 action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);
816 action->property_label() = action->property_label() + "...";
817 actionGroup->add(action,
818 *(new Gtk::AccelKey("<shift><control>s")),
819 sigc::mem_fun(
820 *this, &MainWindow::on_action_file_save_as)
821 );
822 actionGroup->add(Gtk::Action::create("Properties",
823 Gtk::Stock::PROPERTIES),
824 sigc::mem_fun(
825 *this, &MainWindow::on_action_file_properties));
826 actionGroup->add(Gtk::Action::create("InstrProperties",
827 Gtk::Stock::PROPERTIES),
828 sigc::mem_fun(
829 *this, &MainWindow::on_action_file_properties));
830 actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
831 sigc::mem_fun(
832 *this, &MainWindow::hide));
833 actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
834
835 action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
836 actionGroup->add(Gtk::Action::create("MenuHelp",
837 action->property_label()));
838 #ifdef ABOUT_DIALOG
839 actionGroup->add(Gtk::Action::create("About", Gtk::Stock::ABOUT),
840 sigc::mem_fun(
841 *this, &MainWindow::on_action_help_about));
842 #endif
843 action = Gtk::Action::create("Remove", Gtk::Stock::REMOVE);
844 actionGroup->add(action,
845 sigc::mem_fun(
846 *this, &MainWindow::hide));
847
848 // sample right-click popup actions
849 actionGroup->add(
850 Gtk::Action::create("SampleProperties", Gtk::Stock::PROPERTIES),
851 sigc::mem_fun(*this, &MainWindow::on_action_sample_properties)
852 );
853 actionGroup->add(
854 Gtk::Action::create("AddGroup", _("Add _Group")),
855 sigc::mem_fun(*this, &MainWindow::on_action_add_group)
856 );
857 actionGroup->add(
858 Gtk::Action::create("AddSample", _("Add _Sample(s)")),
859 sigc::mem_fun(*this, &MainWindow::on_action_add_sample)
860 );
861 actionGroup->add(
862 Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),
863 sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)
864 );
865
866 uiManager = Gtk::UIManager::create();
867 uiManager->insert_action_group(actionGroup);
868 // add_accel_group(uiManager->get_accel_group());
869
870 Glib::ustring ui_info =
871 "<ui>"
872 " <menubar name='MenuBar'>"
873 " <menu action='MenuFile'>"
874 " <menuitem action='New'/>"
875 " <menuitem action='Open'/>"
876 " <separator/>"
877 " <menuitem action='Save'/>"
878 " <menuitem action='SaveAs'/>"
879 " <separator/>"
880 " <menuitem action='Properties'/>"
881 " <separator/>"
882 " <menuitem action='Quit'/>"
883 " </menu>"
884 " <menu action='MenuInstrument'>"
885 " </menu>"
886 #ifdef ABOUT_DIALOG
887 " <menu action='MenuHelp'>"
888 " <menuitem action='About'/>"
889 " </menu>"
890 #endif
891 " </menubar>"
892 " <popup name='PopupMenu'>"
893 " <menuitem action='InstrProperties'/>"
894 " <menuitem action='Remove'/>"
895 " </popup>"
896 " <popup name='SamplePopupMenu'>"
897 " <menuitem action='SampleProperties'/>"
898 " <menuitem action='AddGroup'/>"
899 " <menuitem action='AddSample'/>"
900 " <separator/>"
901 " <menuitem action='RemoveSample'/>"
902 " </popup>"
903 "</ui>";
904 uiManager->add_ui_from_string(ui_info);
905
906 popup_menu = dynamic_cast<Gtk::Menu*>(uiManager->get_widget("/PopupMenu"));
907
908 Gtk::Widget* menuBar = uiManager->get_widget("/MenuBar");
909 m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);
910 m_VBox.pack_start(m_HPaned);
911 m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
912 m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
913
914 m_RegionChooser.signal_sel_changed().connect(
915 sigc::mem_fun(*this, &MainWindow::region_changed) );
916 m_DimRegionChooser.signal_sel_changed().connect(
917 sigc::mem_fun(*this, &MainWindow::dimreg_changed) );
918
919
920 // Create the Tree model:
921 m_refTreeModel = Gtk::ListStore::create(m_Columns);
922 m_TreeView.set_model(m_refTreeModel);
923
924 // Add the TreeView's view columns:
925 m_TreeView.append_column("Instrument", m_Columns.m_col_name);
926 m_TreeView.set_headers_visible(false);
927
928 // create samples treeview (including its data model)
929 m_refSamplesTreeModel = Gtk::TreeStore::create(m_SamplesModel);
930 m_TreeViewSamples.set_model(m_refSamplesTreeModel);
931 m_TreeViewSamples.append_column("Samples", m_SamplesModel.m_col_name);
932 m_TreeViewSamples.set_headers_visible(false);
933 m_TreeViewSamples.signal_button_press_event().connect_notify(
934 sigc::mem_fun(*this, &MainWindow::on_sample_treeview_button_release)
935 );
936
937 file = 0;
938
939 show_all_children();
940 }
941
942 MainWindow::~MainWindow()
943 {
944 }
945
946 void MainWindow::region_changed()
947 {
948 m_DimRegionChooser.set_region(m_RegionChooser.get_region());
949 }
950
951 void MainWindow::dimreg_changed()
952 {
953 set_dim_region(m_DimRegionChooser.get_dimregion());
954 }
955
956 void MainWindow::on_sel_change()
957 {
958 Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
959
960 Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
961 if (it)
962 {
963 Gtk::TreeModel::Row row = *it;
964 std::cout << row[m_Columns.m_col_name] << std::endl;
965
966 if (row[m_Columns.m_col_instr])
967 m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]);
968 }
969 }
970
971 void MainWindow::set_dim_region(gig::DimensionRegion* d)
972 {
973 update_gui = false;
974 wSample->set_text(d->pSample ? d->pSample->pInfo->Name.c_str() : "NULL");
975 eVelocityUpperLimit.set_dimreg(d);
976 eEG1PreAttack.set_dimreg(d);
977 eEG1Attack.set_dimreg(d);
978 eEG1Decay1.set_dimreg(d);
979 eEG1Decay2.set_dimreg(d);
980 eEG1InfiniteSustain.set_dimreg(d);
981 eEG1Sustain.set_dimreg(d);
982 eEG1Release.set_dimreg(d);
983 eEG1Hold.set_dimreg(d);
984 eEG1Controller.set_dimreg(d);
985 eEG1ControllerInvert.set_dimreg(d);
986 eEG1ControllerAttackInfluence.set_dimreg(d);
987 eEG1ControllerDecayInfluence.set_dimreg(d);
988 eEG1ControllerReleaseInfluence.set_dimreg(d);
989 eLFO1Frequency.set_dimreg(d);
990 eLFO1InternalDepth.set_dimreg(d);
991 eLFO1ControlDepth.set_dimreg(d);
992 eLFO1Controller.set_dimreg(d);
993 eLFO1FlipPhase.set_dimreg(d);
994 eLFO1Sync.set_dimreg(d);
995 eEG2PreAttack.set_dimreg(d);
996 eEG2Attack.set_dimreg(d);
997 eEG2Decay1.set_dimreg(d);
998 eEG2Decay2.set_dimreg(d);
999 eEG2InfiniteSustain.set_dimreg(d);
1000 eEG2Sustain.set_dimreg(d);
1001 eEG2Release.set_dimreg(d);
1002 eEG2Controller.set_dimreg(d);
1003 eEG2ControllerInvert.set_dimreg(d);
1004 eEG2ControllerAttackInfluence.set_dimreg(d);
1005 eEG2ControllerDecayInfluence.set_dimreg(d);
1006 eEG2ControllerReleaseInfluence.set_dimreg(d);
1007 eLFO2Frequency.set_dimreg(d);
1008 eLFO2InternalDepth.set_dimreg(d);
1009 eLFO2ControlDepth.set_dimreg(d);
1010 eLFO2Controller.set_dimreg(d);
1011 eLFO2FlipPhase.set_dimreg(d);
1012 eLFO2Sync.set_dimreg(d);
1013 eEG3Attack.set_dimreg(d);
1014 eEG3Depth.set_dimreg(d);
1015 eLFO3Frequency.set_dimreg(d);
1016 eLFO3InternalDepth.set_dimreg(d);
1017 eLFO3ControlDepth.set_dimreg(d);
1018 eLFO3Controller.set_dimreg(d);
1019 eLFO3Sync.set_dimreg(d);
1020 eVCFEnabled.set_dimreg(d);
1021 eVCFType.set_dimreg(d);
1022 eVCFCutoffController.set_dimreg(d);
1023 eVCFCutoffControllerInvert.set_dimreg(d);
1024 eVCFCutoff.set_dimreg(d);
1025 eVCFVelocityCurve.set_dimreg(d);
1026 eVCFVelocityScale.set_dimreg(d);
1027 eVCFVelocityDynamicRange.set_dimreg(d);
1028 eVCFResonance.set_dimreg(d);
1029 eVCFResonanceDynamic.set_dimreg(d);
1030 eVCFResonanceController.set_dimreg(d);
1031 eVCFKeyboardTracking.set_dimreg(d);
1032 eVCFKeyboardTrackingBreakpoint.set_dimreg(d);
1033 eVelocityResponseCurve.set_dimreg(d);
1034 eVelocityResponseDepth.set_dimreg(d);
1035 eVelocityResponseCurveScaling.set_dimreg(d);
1036 eReleaseVelocityResponseCurve.set_dimreg(d);
1037 eReleaseVelocityResponseDepth.set_dimreg(d);
1038 eReleaseTriggerDecay.set_dimreg(d);
1039 eCrossfade_in_start.set_dimreg(d);
1040 eCrossfade_in_end.set_dimreg(d);
1041 eCrossfade_out_start.set_dimreg(d);
1042 eCrossfade_out_end.set_dimreg(d);
1043 ePitchTrack.set_dimreg(d);
1044 eDimensionBypass.set_dimreg(d);
1045 ePan.set_dimreg(d);
1046 eSelfMask.set_dimreg(d);
1047 eAttenuationController.set_dimreg(d);
1048 eInvertAttenuationController.set_dimreg(d);
1049 eAttenuationControllerThreshold.set_dimreg(d);
1050 eChannelOffset.set_dimreg(d);
1051 eSustainDefeat.set_dimreg(d);
1052 eMSDecode.set_dimreg(d);
1053 eSampleStartOffset.set_dimreg(d);
1054 eUnityNote.set_dimreg(d);
1055 eFineTune.set_dimreg(d);
1056 eGain.set_dimreg(d);
1057 eSampleLoops.set_dimreg(d);
1058
1059 VCFEnabled_toggled();
1060
1061 update_gui = true;
1062 }
1063
1064 void MainWindow::VCFEnabled_toggled()
1065 {
1066 bool sensitive = eVCFEnabled.get_active();
1067 eVCFType.set_sensitive(sensitive);
1068 eVCFCutoffController.set_sensitive(sensitive);
1069 eVCFVelocityCurve.set_sensitive(sensitive);
1070 eVCFVelocityScale.set_sensitive(sensitive);
1071 eVCFVelocityDynamicRange.set_sensitive(sensitive);
1072 eVCFResonance.set_sensitive(sensitive);
1073 eVCFResonanceController.set_sensitive(sensitive);
1074 eVCFKeyboardTracking.set_sensitive(sensitive);
1075 eVCFKeyboardTrackingBreakpoint.set_sensitive(sensitive);
1076 eEG2PreAttack.set_sensitive(sensitive);
1077 eEG2Attack.set_sensitive(sensitive);
1078 eEG2Decay1.set_sensitive(sensitive);
1079 eEG2InfiniteSustain.set_sensitive(sensitive);
1080 eEG2Sustain.set_sensitive(sensitive);
1081 eEG2Release.set_sensitive(sensitive);
1082 eEG2Controller.set_sensitive(sensitive);
1083 eEG2ControllerAttackInfluence.set_sensitive(sensitive);
1084 eEG2ControllerDecayInfluence.set_sensitive(sensitive);
1085 eEG2ControllerReleaseInfluence.set_sensitive(sensitive);
1086 eLFO2Frequency.set_sensitive(sensitive);
1087 eLFO2InternalDepth.set_sensitive(sensitive);
1088 eLFO2ControlDepth.set_sensitive(sensitive);
1089 eLFO2Controller.set_sensitive(sensitive);
1090 eLFO2FlipPhase.set_sensitive(sensitive);
1091 eLFO2Sync.set_sensitive(sensitive);
1092 if (sensitive) {
1093 VCFCutoffController_changed();
1094 VCFResonanceController_changed();
1095 EG2InfiniteSustain_toggled();
1096 EG2Controller_changed();
1097 LFO2Controller_changed();
1098 } else {
1099 eVCFCutoffControllerInvert.set_sensitive(false);
1100 eVCFCutoff.set_sensitive(false);
1101 eVCFResonanceDynamic.set_sensitive(false);
1102 eVCFResonance.set_sensitive(false);
1103 eEG2Decay2.set_sensitive(false);
1104 eEG2ControllerInvert.set_sensitive(false);
1105 eLFO2InternalDepth.set_sensitive(false);
1106 eLFO2ControlDepth.set_sensitive(false);
1107 }
1108 }
1109
1110 void MainWindow::VCFCutoffController_changed()
1111 {
1112 int rowno = eVCFCutoffController.get_active_row_number();
1113 bool hasController = rowno != 0 && rowno != 1;
1114
1115 eVCFCutoffControllerInvert.set_sensitive(hasController);
1116 eVCFCutoff.set_sensitive(!hasController);
1117 eVCFResonanceDynamic.set_sensitive(!hasController);
1118 eVCFVelocityScale.label.set_text(hasController ? "MinimumCutoff:" :
1119 "VelocityScale:");
1120 }
1121
1122 void MainWindow::VCFResonanceController_changed()
1123 {
1124 bool hasController = eVCFResonanceController.get_active_row_number() != 0;
1125 eVCFResonance.set_sensitive(!hasController);
1126 }
1127
1128 void MainWindow::EG1InfiniteSustain_toggled()
1129 {
1130 bool infSus = eEG1InfiniteSustain.get_active();
1131 eEG1Decay2.set_sensitive(!infSus);
1132 }
1133
1134 void MainWindow::EG2InfiniteSustain_toggled()
1135 {
1136 bool infSus = eEG2InfiniteSustain.get_active();
1137 eEG2Decay2.set_sensitive(!infSus);
1138 }
1139
1140 void MainWindow::EG1Controller_changed()
1141 {
1142 bool hasController = eEG1Controller.get_active_row_number() != 0;
1143 eEG1ControllerInvert.set_sensitive(hasController);
1144 }
1145
1146 void MainWindow::EG2Controller_changed()
1147 {
1148 bool hasController = eEG2Controller.get_active_row_number() != 0;
1149 eEG2ControllerInvert.set_sensitive(hasController);
1150 }
1151
1152 void MainWindow::AttenuationController_changed()
1153 {
1154 bool hasController = eAttenuationController.get_active_row_number() != 0;
1155 eInvertAttenuationController.set_sensitive(hasController);
1156 }
1157
1158 void MainWindow::LFO1Controller_changed()
1159 {
1160 int rowno = eLFO1Controller.get_active_row_number();
1161 eLFO1ControlDepth.set_sensitive(rowno != 0);
1162 eLFO1InternalDepth.set_sensitive(rowno != 1 && rowno != 2);
1163 }
1164
1165 void MainWindow::LFO2Controller_changed()
1166 {
1167 int rowno = eLFO2Controller.get_active_row_number();
1168 eLFO2ControlDepth.set_sensitive(rowno != 0);
1169 eLFO2InternalDepth.set_sensitive(rowno != 1 && rowno != 2);
1170 }
1171
1172 void MainWindow::LFO3Controller_changed()
1173 {
1174 int rowno = eLFO3Controller.get_active_row_number();
1175 eLFO3ControlDepth.set_sensitive(rowno != 0);
1176 eLFO3InternalDepth.set_sensitive(rowno != 1 && rowno != 2);
1177 }
1178
1179 void MainWindow::crossfade1_changed()
1180 {
1181 double c1 = eCrossfade_in_start.get_value();
1182 double c2 = eCrossfade_in_end.get_value();
1183 if (c1 > c2) eCrossfade_in_end.set_value(c1);
1184 }
1185
1186 void MainWindow::crossfade2_changed()
1187 {
1188 double c1 = eCrossfade_in_start.get_value();
1189 double c2 = eCrossfade_in_end.get_value();
1190 double c3 = eCrossfade_out_start.get_value();
1191
1192 if (c2 < c1) eCrossfade_in_start.set_value(c2);
1193 if (c2 > c3) eCrossfade_out_start.set_value(c2);
1194 }
1195
1196 void MainWindow::crossfade3_changed()
1197 {
1198 double c2 = eCrossfade_in_end.get_value();
1199 double c3 = eCrossfade_out_start.get_value();
1200 double c4 = eCrossfade_out_end.get_value();
1201
1202 if (c3 < c2) eCrossfade_in_end.set_value(c3);
1203 if (c3 > c4) eCrossfade_out_end.set_value(c3);
1204 }
1205
1206 void MainWindow::crossfade4_changed()
1207 {
1208 double c3 = eCrossfade_out_start.get_value();
1209 double c4 = eCrossfade_out_end.get_value();
1210
1211 if (c4 < c3) eCrossfade_out_start.set_value(c4);
1212 }
1213
1214 void loader_progress_callback(gig::progress_t* progress)
1215 {
1216 Loader* loader = static_cast<Loader*>(progress->custom);
1217 loader->progress_callback(progress->factor);
1218 }
1219
1220 void Loader::progress_callback(float fraction)
1221 {
1222 {
1223 Glib::Mutex::Lock lock(progressMutex);
1224 progress = fraction;
1225 }
1226 progress_dispatcher();
1227 }
1228
1229 void Loader::thread_function()
1230 {
1231 printf("thread_function self=%x\n", Glib::Thread::self());
1232 printf("Start %s\n", filename);
1233 RIFF::File* riff = new RIFF::File(filename);
1234 gig = new gig::File(riff);
1235 gig::progress_t progress;
1236 progress.callback = loader_progress_callback;
1237 progress.custom = this;
1238
1239 gig->GetInstrument(0, &progress);
1240 printf("End\n");
1241 finished_dispatcher();
1242 }
1243
1244 Loader::Loader(const char* filename)
1245 : thread(0), filename(filename)
1246 {
1247 }
1248
1249 void Loader::launch()
1250 {
1251 thread = Glib::Thread::create(sigc::mem_fun(*this, &Loader::thread_function), true);
1252 printf("launch thread=%x\n", thread);
1253 }
1254
1255 float Loader::get_progress()
1256 {
1257 float res;
1258 {
1259 Glib::Mutex::Lock lock(progressMutex);
1260 res = progress;
1261 }
1262 return res;
1263 }
1264
1265 Glib::Dispatcher& Loader::signal_progress()
1266 {
1267 return progress_dispatcher;
1268 }
1269
1270 Glib::Dispatcher& Loader::signal_finished()
1271 {
1272 return finished_dispatcher;
1273 }
1274
1275 LoadDialog::LoadDialog()
1276 {
1277 get_vbox()->pack_start(progressBar);
1278 show_all_children();
1279 }
1280
1281 void MainWindow::on_action_file_new()
1282 {
1283 }
1284
1285 void MainWindow::on_action_file_open()
1286 {
1287 Gtk::FileChooserDialog dialog(*this, _("Open file"));
1288 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1289 dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1290 Gtk::FileFilter filter;
1291 filter.add_pattern("*.gig");
1292 dialog.set_filter(filter);
1293 if (dialog.run() == Gtk::RESPONSE_OK) {
1294 printf("filename=%s\n", dialog.get_filename().c_str());
1295
1296 // remove all entries from "Instrument" menu
1297 Gtk::MenuItem* instrument_menu =
1298 dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));
1299 instrument_menu->hide();
1300 for (int i = 0; i < instrument_menu->get_submenu()->items().size(); i++) {
1301 delete &instrument_menu->get_submenu()->items()[i];
1302 }
1303 instrument_menu->get_submenu()->items().clear();
1304
1305 m_refTreeModel->clear();
1306 m_refSamplesTreeModel->clear();
1307 if (file) delete file;
1308
1309 // getInfo(dialog.get_filename().c_str(), *this);
1310
1311 printf("on_action_file_open self=%x\n", Glib::Thread::self());
1312 load_dialog = new LoadDialog(); // Gtk::Dialog("Loading...", *this, true);
1313 load_dialog->show_all();
1314 loader = new Loader(strdup(dialog.get_filename().c_str()));
1315 loader->signal_progress().connect(
1316 sigc::mem_fun(*this, &MainWindow::on_loader_progress));
1317 loader->signal_finished().connect(
1318 sigc::mem_fun(*this, &MainWindow::on_loader_finished));
1319
1320 loader->launch();
1321 }
1322 }
1323
1324 void MainWindow::on_loader_progress()
1325 {
1326 load_dialog->set_fraction(loader->get_progress());
1327 }
1328
1329 void MainWindow::on_loader_finished()
1330 {
1331 printf("Loader finished!\n");
1332 printf("on_loader_finished self=%x\n", Glib::Thread::self());
1333 load_gig(loader->gig, loader->filename);
1334
1335
1336 Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
1337 tree_sel_ref->select(Gtk::TreePath("0"));
1338
1339 load_dialog->hide();
1340 }
1341
1342 void MainWindow::on_action_file_save()
1343 {
1344 }
1345
1346 void MainWindow::on_action_file_save_as()
1347 {
1348 Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);
1349 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1350 dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
1351 Gtk::FileFilter filter;
1352 filter.add_pattern("*.gig");
1353 dialog.set_filter(filter);
1354 if (dialog.run() == Gtk::RESPONSE_OK) {
1355 printf("filename=%s\n", dialog.get_filename().c_str());
1356 file->Save(dialog.get_filename());
1357 }
1358 }
1359
1360 void MainWindow::on_action_file_properties()
1361 {
1362 propDialog.show();
1363 propDialog.deiconify();
1364 }
1365
1366 void MainWindow::on_action_help_about()
1367 {
1368 #ifdef ABOUT_DIALOG
1369 Gtk::AboutDialog dialog;
1370 dialog.set_version(VERSION);
1371 dialog.run();
1372 #endif
1373 }
1374
1375 PropDialog::PropDialog()
1376 : table(2,1)
1377 {
1378 table.set_col_spacings(5);
1379 char* propLabels[] = {
1380 "Name:",
1381 "CreationDate:",
1382 "Comments:", // TODO: multiline
1383 "Product:",
1384 "Copyright:",
1385 "Artists:",
1386 "Genre:",
1387 "Keywords:",
1388 "Engineer:",
1389 "Technician:",
1390 "Software:", // TODO: readonly
1391 "Medium:",
1392 "Source:",
1393 "SourceForm:",
1394 "Commissioned:",
1395 "Subject:"
1396 };
1397 for (int i = 0 ; i < sizeof(propLabels) / sizeof(char*) ; i++) {
1398 label[i].set_text(propLabels[i]);
1399 label[i].set_alignment(Gtk::ALIGN_LEFT);
1400 table.attach(label[i], 0, 1, i, i + 1, Gtk::FILL, Gtk::SHRINK);
1401 table.attach(entry[i], 1, 2, i, i + 1, Gtk::FILL | Gtk::EXPAND,
1402 Gtk::SHRINK);
1403 }
1404
1405 add(table);
1406 // add_button(Gtk::Stock::CANCEL, 0);
1407 // add_button(Gtk::Stock::OK, 1);
1408 show_all_children();
1409 }
1410
1411 void PropDialog::set_info(DLS::Info* info)
1412 {
1413 entry[0].set_text(info->Name);
1414 entry[1].set_text(info->CreationDate);
1415 entry[2].set_text(Glib::convert(info->Comments, "UTF-8", "ISO-8859-1"));
1416 entry[3].set_text(info->Product);
1417 entry[4].set_text(info->Copyright);
1418 entry[5].set_text(info->Artists);
1419 entry[6].set_text(info->Genre);
1420 entry[7].set_text(info->Keywords);
1421 entry[8].set_text(info->Engineer);
1422 entry[9].set_text(info->Technician);
1423 entry[10].set_text(info->Software);
1424 entry[11].set_text(info->Medium);
1425 entry[12].set_text(info->Source);
1426 entry[13].set_text(info->SourceForm);
1427 entry[14].set_text(info->Commissioned);
1428 entry[15].set_text(info->Subject);
1429 }
1430
1431
1432 InstrumentProps::InstrumentProps()
1433 : table(2,1),
1434 quitButton(Gtk::Stock::CLOSE)
1435 {
1436 table.set_col_spacings(5);
1437 char* propLabels[] = {
1438 "Name:",
1439 "IsDrum:",
1440 "MIDIBank:",
1441 "MIDIProgram:",
1442 "Attenuation:",
1443 "EffectSend:",
1444 "FineTune:",
1445 "PitchbendRange:",
1446 "PianoReleaseMode:",
1447 "DimensionKeyRange:",
1448 };
1449 int entryIdx = 0, checkIdx = 0;
1450 for (int i = 0 ; i < sizeof(propLabels) / sizeof(char*) ; i++) {
1451 label[i].set_text(propLabels[i]);
1452 label[i].set_alignment(Gtk::ALIGN_LEFT);
1453 table.attach(label[i], 0, 1, i, i + 1, Gtk::FILL, Gtk::SHRINK);
1454 if (i == 1 || i == 8)
1455 table.attach(check[checkIdx++], 1, 2, i, i + 1,
1456 Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
1457 else
1458 table.attach(entry[entryIdx++], 1, 2, i, i + 1,
1459 Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
1460 }
1461
1462 // vbox { table buttonBox { quitButton } }
1463
1464 //get_vbox()->pack_start(table);
1465 // set_border_width(6);
1466 add(vbox);
1467 table.set_border_width(2);
1468 vbox.pack_start(table);
1469 table.show();
1470 vbox.pack_start(buttonBox);
1471 buttonBox.set_layout(Gtk::BUTTONBOX_END);
1472 buttonBox.set_border_width(5);
1473 buttonBox.show();
1474 buttonBox.pack_start(quitButton);
1475 quitButton.set_flags(Gtk::CAN_DEFAULT);
1476 quitButton.grab_focus();
1477
1478 quitButton.signal_clicked().connect(
1479 sigc::mem_fun(*this, &InstrumentProps::hide));
1480
1481 // quitButton.grab_default();
1482 quitButton.show();
1483 // add(table);
1484 vbox.show();
1485 show_all_children();
1486 }
1487
1488
1489 void InstrumentProps::set_instrument(gig::Instrument* instrument)
1490 {
1491 char buf[100];
1492
1493 int entryIdx = 0, checkIdx = 0;
1494 entry[entryIdx++].set_text(instrument->pInfo->Name);
1495 check[checkIdx++].set_active(instrument->IsDrum);
1496 sprintf(buf, "%d", instrument->MIDIBank);
1497 entry[entryIdx++].set_text(buf);
1498 sprintf(buf, "%d", instrument->MIDIProgram);
1499 entry[entryIdx++].set_text(buf);
1500 sprintf(buf, "%d", instrument->Attenuation);
1501 entry[entryIdx++].set_text(buf);
1502 sprintf(buf, "%d", instrument->EffectSend);
1503 entry[entryIdx++].set_text(buf);
1504 sprintf(buf, "%d", instrument->FineTune);
1505 entry[entryIdx++].set_text(buf);
1506 sprintf(buf, "%d", instrument->PitchbendRange);
1507 entry[entryIdx++].set_text(buf);
1508 check[checkIdx++].set_active(instrument->PianoReleaseMode);
1509 sprintf(buf, "%s%d (%d)..%s%d (%d)",
1510 notes[instrument->DimensionKeyRange.low % 12],
1511 instrument->DimensionKeyRange.low / 12 - 1,
1512 instrument->DimensionKeyRange.low,
1513 notes[instrument->DimensionKeyRange.high % 12],
1514 instrument->DimensionKeyRange.high / 12 - 1,
1515 instrument->DimensionKeyRange.high);
1516 entry[entryIdx].set_text(buf);
1517 }
1518
1519 void MainWindow::getInfo(const char *filename)
1520 {
1521 RIFF::File* riff = new RIFF::File(filename);
1522 gig::File* gig = new gig::File(riff);
1523
1524 load_gig(gig, filename);
1525 }
1526
1527 void MainWindow::load_gig(gig::File* gig, const char* filename)
1528 {
1529 file = gig;
1530
1531 const char *basename = strrchr(filename, '/');
1532 basename = basename ? basename + 1 : filename;
1533
1534 set_title(basename);
1535
1536 propDialog.set_info(gig->pInfo);
1537
1538 Gtk::MenuItem* instrument_menu =
1539 dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));
1540
1541 int instrument_index = 0;
1542 Gtk::RadioMenuItem::Group instrument_group;
1543 for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ;
1544 instrument = gig->GetNextInstrument()) {
1545 Gtk::TreeModel::iterator iter = m_refTreeModel->append();
1546 Gtk::TreeModel::Row row = *iter;
1547 row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
1548 row[m_Columns.m_col_instr] = instrument;
1549 // create a menu item for this instrument
1550 Gtk::RadioMenuItem* item= new Gtk::RadioMenuItem(instrument_group, instrument->pInfo->Name.c_str());
1551 instrument_menu->get_submenu()->append(*item);
1552 item->signal_activate().connect(
1553 sigc::bind(
1554 sigc::mem_fun(*this, &MainWindow::on_instrument_selection_change),
1555 instrument_index
1556 )
1557 );
1558 instrument_index++;
1559 }
1560 instrument_menu->show();
1561 instrument_menu->get_submenu()->show_all_children();
1562
1563 for (gig::Group* group = gig->GetFirstGroup(); group; group = gig->GetNextGroup()) {
1564 Gtk::TreeModel::iterator iterGroup = m_refSamplesTreeModel->append();
1565 Gtk::TreeModel::Row rowGroup = *iterGroup;
1566 rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1567 rowGroup[m_SamplesModel.m_col_group] = group;
1568 rowGroup[m_SamplesModel.m_col_sample] = NULL;
1569 for (gig::Sample* sample = group->GetFirstSample(); sample; sample = group->GetNextSample()) {
1570 Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(rowGroup.children());
1571 Gtk::TreeModel::Row rowSample = *iterSample;
1572 rowSample[m_SamplesModel.m_col_name] = sample->pInfo->Name.c_str();
1573 rowSample[m_SamplesModel.m_col_sample] = sample;
1574 rowSample[m_SamplesModel.m_col_group] = NULL;
1575 }
1576 }
1577 }
1578
1579 void MainWindow::on_button_release(GdkEventButton* button)
1580 {
1581 if (button->type == GDK_2BUTTON_PRESS) {
1582 Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
1583 Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
1584 if (it)
1585 {
1586 Gtk::TreeModel::Row row = *it;
1587 if (row[m_Columns.m_col_instr])
1588 {
1589 instrumentProps.set_instrument(row[m_Columns.m_col_instr]);
1590 instrumentProps.show();
1591 instrumentProps.deiconify();
1592 }
1593 }
1594 } else if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
1595 popup_menu->popup(button->button, button->time);
1596 }
1597 }
1598
1599 void MainWindow::on_instrument_selection_change(int index) {
1600 m_RegionChooser.set_instrument(file->GetInstrument(index));
1601 }
1602
1603 void MainWindow::on_sample_treeview_button_release(GdkEventButton* button) {
1604 if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
1605 Gtk::Menu* sample_popup =
1606 dynamic_cast<Gtk::Menu*>(uiManager->get_widget("/SamplePopupMenu"));
1607 // update enabled/disabled state of sample popup items
1608 Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
1609 Gtk::TreeModel::iterator it = sel->get_selected();
1610 bool group_selected = false;
1611 bool sample_selected = false;
1612 if (it) {
1613 Gtk::TreeModel::Row row = *it;
1614 group_selected = row[m_SamplesModel.m_col_group];
1615 sample_selected = row[m_SamplesModel.m_col_sample];
1616 }
1617 dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/SampleProperties"))->set_sensitive(group_selected || sample_selected);
1618 dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddSample"))->set_sensitive(group_selected || sample_selected);
1619 dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddGroup"))->set_sensitive(file);
1620 dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/RemoveSample"))->set_sensitive(group_selected || sample_selected);
1621 // show sample popup
1622 sample_popup->popup(button->button, button->time);
1623 }
1624 }
1625
1626 void MainWindow::on_action_sample_properties() {
1627 //TODO: show a dialog where the selected sample's properties can be edited
1628 }
1629
1630 void MainWindow::on_action_add_group() {
1631 static int __sample_indexer = 0;
1632 if (!file) return;
1633 gig::Group* group = file->AddGroup();
1634 group->Name = "Unnamed Group";
1635 if (__sample_indexer) group->Name += " " + ToString(__sample_indexer);
1636 __sample_indexer++;
1637 // update sample tree view
1638 Gtk::TreeModel::iterator iterGroup = m_refSamplesTreeModel->append();
1639 Gtk::TreeModel::Row rowGroup = *iterGroup;
1640 rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1641 rowGroup[m_SamplesModel.m_col_sample] = NULL;
1642 rowGroup[m_SamplesModel.m_col_group] = group;
1643 }
1644
1645 void MainWindow::on_action_add_sample() {
1646 if (!file) return;
1647 // get selected group
1648 Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
1649 Gtk::TreeModel::iterator it = sel->get_selected();
1650 if (!it) return;
1651 Gtk::TreeModel::Row row = *it;
1652 gig::Group* group = row[m_SamplesModel.m_col_group];
1653 if (!group) { // not a group, but a sample is selected (probably)
1654 gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1655 if (!sample) return;
1656 it = row.parent(); // resolve parent (that is the sample's group)
1657 if (!it) return;
1658 row = *it;
1659 group = row[m_SamplesModel.m_col_group];
1660 if (!group) return;
1661 }
1662 // show 'browse for file' dialog
1663 Gtk::FileChooserDialog dialog(*this, _("Add Sample(s)"));
1664 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1665 dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1666 dialog.set_select_multiple(true);
1667 Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile (yet to do ;-)
1668 soundfilter.add_pattern("*.wav");
1669 soundfilter.set_name("Sound Files");
1670 Gtk::FileFilter allpassfilter; // matches every file
1671 allpassfilter.add_pattern("*.*");
1672 allpassfilter.set_name("All Files");
1673 dialog.add_filter(soundfilter);
1674 dialog.add_filter(allpassfilter);
1675 if (dialog.run() == Gtk::RESPONSE_OK) {
1676 Glib::ustring error_files;
1677 Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames();
1678 for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin(); iter != filenames.end(); ++iter) {
1679 printf("Adding sample %s\n",(*iter).c_str());
1680 // use libsndfile to retrieve file informations
1681 SF_INFO info;
1682 info.format = 0;
1683 SNDFILE* hFile = sf_open((*iter).c_str(), SFM_READ, &info);
1684 try {
1685 if (!hFile) throw std::string("could not open file");
1686 int bitdepth;
1687 switch (info.format & 0xff) {
1688 case SF_FORMAT_PCM_S8:
1689 bitdepth = 8;
1690 break;
1691 case SF_FORMAT_PCM_16:
1692 bitdepth = 16;
1693 break;
1694 case SF_FORMAT_PCM_24:
1695 bitdepth = 24;
1696 break;
1697 case SF_FORMAT_PCM_32:
1698 bitdepth = 32;
1699 break;
1700 default:
1701 sf_close(hFile); // close sound file
1702 throw std::string("format not supported"); // unsupported subformat (yet?)
1703 }
1704 // add a new sample to the .gig file
1705 gig::Sample* sample = file->AddSample();
1706 sample->pInfo->Name = (*iter).raw();
1707 sample->Channels = info.channels;
1708 sample->BitDepth = bitdepth;
1709 sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1710 sample->SamplesPerSecond = info.samplerate;
1711 // schedule resizing the sample (which will be done physically when File::Save() is called)
1712 sample->Resize(info.frames);
1713 // add sample to the tree view
1714 Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(row.children());
1715 Gtk::TreeModel::Row rowSample = *iterSample;
1716 rowSample[m_SamplesModel.m_col_name] = sample->pInfo->Name.c_str();
1717 rowSample[m_SamplesModel.m_col_sample] = sample;
1718 rowSample[m_SamplesModel.m_col_group] = NULL;
1719 // close sound file
1720 sf_close(hFile);
1721 } catch (std::string what) { // remember the files that made trouble (and their cause)
1722 if (error_files.size()) error_files += "\n";
1723 error_files += *iter += " (" + what + ")";
1724 }
1725 }
1726 // show error message box when some file(s) could not be opened / added
1727 if (error_files.size()) {
1728 Glib::ustring txt = "Could not add the following sample(s):\n" + error_files;
1729 Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1730 msg.run();
1731 }
1732 }
1733 }
1734
1735 void MainWindow::on_action_remove_sample() {
1736 if (!file) return;
1737 Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
1738 Gtk::TreeModel::iterator it = sel->get_selected();
1739 if (it) {
1740 Gtk::TreeModel::Row row = *it;
1741 gig::Group* group = row[m_SamplesModel.m_col_group];
1742 gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1743 try {
1744 // remove group or sample from the gig file
1745 if (group) {
1746 file->DeleteGroup(group);
1747 } else if (sample) {
1748 file->DeleteSample(sample);
1749 }
1750 // remove respective row(s) from samples tree view
1751 m_refSamplesTreeModel->erase(it);
1752 } catch (RIFF::Exception e) {
1753 Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1754 msg.run();
1755 }
1756 }
1757 }

  ViewVC Help
Powered by ViewVC