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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1082 - (hide annotations) (download)
Thu Mar 8 01:43:18 2007 UTC (17 years, 1 month ago) by schoenebeck
File size: 58039 byte(s)
* added right-click popup for sample list view
  (only item "Add Group" implemented yet)

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

  ViewVC Help
Powered by ViewVC