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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1084 - (hide annotations) (download)
Thu Mar 8 16:47:15 2007 UTC (13 years, 4 months ago) by schoenebeck
File size: 58863 byte(s)
* implemented "Remove" operation in right-click popup on
  samples and groups (in samples tree view)
  Note: you need latest CVS version of libgig for this to work!

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

  ViewVC Help
Powered by ViewVC