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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1085 - (hide 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 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 schoenebeck 1085 #include <stdio.h>
34     #include <sndfile.h>
35    
36 persson 1052 #define _(String) gettext(String)
37    
38 schoenebeck 1082 template<class T> inline std::string ToString(T o) {
39     std::stringstream ss;
40     ss << o;
41     return ss.str();
42     }
43    
44 persson 1052 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 schoenebeck 1080 // Add the TreeView tab, inside a ScrolledWindow, with the button underneath:
537     m_ScrolledWindow.add(m_TreeViewNotebook);
538 persson 1052 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 schoenebeck 1080 m_TreeViewNotebook.append_page(m_TreeViewSamples, "Samples");
797     m_TreeViewNotebook.append_page(m_TreeView, "Instruments");
798    
799    
800 persson 1052 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 schoenebeck 1069 actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
834    
835 persson 1052 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 schoenebeck 1082 action = Gtk::Action::create("Remove", Gtk::Stock::REMOVE);
844 persson 1052 actionGroup->add(action,
845     sigc::mem_fun(
846     *this, &MainWindow::hide));
847    
848 schoenebeck 1082 // 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 schoenebeck 1085 Gtk::Action::create("AddSample", _("Add _Sample(s)")),
859 schoenebeck 1082 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 persson 1052 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 schoenebeck 1069 " <menu action='MenuInstrument'>"
885     " </menu>"
886 persson 1052 #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 schoenebeck 1082 " <popup name='SamplePopupMenu'>"
897     " <menuitem action='SampleProperties'/>"
898     " <menuitem action='AddGroup'/>"
899     " <menuitem action='AddSample'/>"
900     " <separator/>"
901     " <menuitem action='RemoveSample'/>"
902     " </popup>"
903 persson 1052 "</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 schoenebeck 1080 // 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 schoenebeck 1082 m_TreeViewSamples.signal_button_press_event().connect_notify(
934     sigc::mem_fun(*this, &MainWindow::on_sample_treeview_button_release)
935     );
936 schoenebeck 1080
937 persson 1052 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 schoenebeck 1069 // 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 persson 1052 m_refTreeModel->clear();
1306 schoenebeck 1080 m_refSamplesTreeModel->clear();
1307 persson 1052 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 schoenebeck 1069 Gtk::MenuItem* instrument_menu =
1539     dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));
1540    
1541     int instrument_index = 0;
1542 schoenebeck 1075 Gtk::RadioMenuItem::Group instrument_group;
1543 persson 1052 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 schoenebeck 1069 // create a menu item for this instrument
1550 schoenebeck 1075 Gtk::RadioMenuItem* item= new Gtk::RadioMenuItem(instrument_group, instrument->pInfo->Name.c_str());
1551 schoenebeck 1069 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 persson 1052 }
1560 schoenebeck 1069 instrument_menu->show();
1561     instrument_menu->get_submenu()->show_all_children();
1562 schoenebeck 1080
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 schoenebeck 1082 rowGroup[m_SamplesModel.m_col_group] = group;
1568     rowGroup[m_SamplesModel.m_col_sample] = NULL;
1569 schoenebeck 1080 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 schoenebeck 1082 rowSample[m_SamplesModel.m_col_group] = NULL;
1575 schoenebeck 1080 }
1576     }
1577 persson 1052 }
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 schoenebeck 1069
1599     void MainWindow::on_instrument_selection_change(int index) {
1600     m_RegionChooser.set_instrument(file->GetInstrument(index));
1601     }
1602 schoenebeck 1082
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 schoenebeck 1085 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 schoenebeck 1082 }
1734    
1735     void MainWindow::on_action_remove_sample() {
1736 schoenebeck 1084 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 schoenebeck 1082 }

  ViewVC Help
Powered by ViewVC