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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

gigedit/branches/linuxsampler_org/src/mainwindow.cpp revision 1052 by persson, Sat Mar 3 12:20:01 2007 UTC gigedit/trunk/src/mainwindow.cpp revision 1100 by persson, Sat Mar 17 09:20:19 2007 UTC
# Line 20  Line 20 
20  #include <libintl.h>  #include <libintl.h>
21  #include <iostream>  #include <iostream>
22    
 #include "mainwindow.h"  
   
23  #include <gtkmm/filechooserdialog.h>  #include <gtkmm/filechooserdialog.h>
24    #include <gtkmm/messagedialog.h>
25  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
26    #include <gtkmm/targetentry.h>
27    
28  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6
29  #define ABOUT_DIALOG  #define ABOUT_DIALOG
30  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
31  #endif  #endif
32    
33  #define _(String) gettext(String)  #include <stdio.h>
34    #include <sndfile.h>
   
 bool update_gui;  
   
 uint8_t& access_UnityNote(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->UnityNote;  
 }  
 int16_t& access_FineTune(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->FineTune;  
 }  
 uint32_t& access_SampleLoops(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->SampleLoops;  
 }  
 uint8_t& access_Crossfade_in_start(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->Crossfade.in_start;  
 }  
 uint8_t& access_Crossfade_in_end(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->Crossfade.in_end;  
 }  
 uint8_t& access_Crossfade_out_start(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->Crossfade.out_start;  
 }  
 uint8_t& access_Crossfade_out_end(gig::DimensionRegion* dimreg)  
 {  
     return dimreg->Crossfade.out_end;  
 }  
   
 namespace {  
     const char* const controlChangeTexts[] = {  
         "none", "channelaftertouch", "velocity",  
         0,  
         "modwheel", // "Modulation Wheel or Lever",  
         "breath", // "Breath Controller",  
         0,  
         "foot", // "Foot Controller",  
         "portamentotime", // "Portamento Time",  
         0, 0, 0, 0, 0, 0,  
         "effect1", // "Effect Control 1",  
         "effect2", // "Effect Control 2",  
         0, 0,  
         "genpurpose1", // "General Purpose Controller 1",  
         "genpurpose2", // "General Purpose Controller 2",  
         "genpurpose3", // "General Purpose Controller 3",  
         "genpurpose4", // "General Purpose Controller 4",  
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
         0, 0, 0, 0, 0, 0,  
         "sustainpedal", // "Damper Pedal on/off (Sustain)",  
         "portamento", // "Portamento On/Off",  
         "sostenuto", // "Sustenuto On/Off",  
         "softpedal", // "Soft Pedal On/Off",  
         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
         "genpurpose5", // "General Purpose Controller 5",  
         "genpurpose6", // "General Purpose Controller 6",  
         "genpurpose7", // "General Purpose Controller 7",  
         "genpurpose8", // "General Purpose Controller 8",  
         0, 0, 0, 0, 0, 0, 0,  
         "effect1depth", // "Effects 1 Depth",  
         "effect2depth", // "Effects 2 Depth",  
         "effect3depth", // "Effects 3 Depth",  
         "effect4depth", // "Effects 4 Depth",  
         "effect5depth", // "Effects 5 Depth"  
     };  
 }  
   
 void MainWindow::addString(char* labelText, Gtk::Label*& label,  
                            Gtk::Entry*& widget)  
 {  
     label = new Gtk::Label(Glib::ustring(labelText) + ":");  
     label->set_alignment(Gtk::ALIGN_LEFT);  
   
     table[pageno]->attach(*label, 1, 2, rowno, rowno + 1,  
                           Gtk::FILL, Gtk::SHRINK);  
   
     widget = new Gtk::Entry();  
   
     table[pageno]->attach(*widget, 2, 3, rowno, rowno + 1,  
                           Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);  
   
     rowno++;  
 }  
   
 LabelWidget::LabelWidget(char* labelText, Gtk::Widget& widget) :  
     label(Glib::ustring(labelText) + ":"),  
     widget(widget)  
 {  
     label.set_alignment(Gtk::ALIGN_LEFT);  
 }  
   
 void LabelWidget::set_sensitive(bool sensitive)  
 {  
     label.set_sensitive(sensitive);  
     widget.set_sensitive(sensitive);  
 }  
   
 NumEntryGain::NumEntryGain(char* labelText,  
                            double lower = 0, double upper = 127,  
                            int decimals = 0) :  
     NumEntry<gig::DimensionRegion>(labelText, lower, upper, decimals)  
 {  
     spinbutton.signal_value_changed().connect(  
         sigc::mem_fun(*this, &NumEntryGain::value_changed));  
 }  
   
 void NumEntryGain::value_changed()  
 {  
     if (dimreg && update_gui) {  
       dimreg->Gain = int32_t(spinbutton.get_value() * -655360.0);  
     }  
 }  
   
 void NumEntryGain::set_dimreg(gig::DimensionRegion* dimreg)  
 {  
     this->dimreg = 0;  
     set_value(dimreg->Gain / -655360.0);  
     this->dimreg = dimreg;  
 }  
   
   
 NumEntryPermille::NumEntryPermille(char* labelText,  
                                    uint16_t gig::DimensionRegion::* param,  
                                    double lower, double upper, int decimals) :  
     NumEntry<gig::DimensionRegion>(labelText, lower, upper, decimals),  
     param(param)  
 {  
     spinbutton.signal_value_changed().connect(  
         sigc::mem_fun(*this, &NumEntryPermille::value_changed));  
 }  
   
 void NumEntryPermille::value_changed()  
 {  
     if (dimreg && update_gui) {  
         dimreg->*param = uint16_t(spinbutton.get_value() * 10 + 0.5);  
     }  
 }  
   
 void NumEntryPermille::set_dimreg(gig::DimensionRegion* dimreg)  
 {  
     this->dimreg = 0;  
     set_value(dimreg->*param / 10.0);  
     this->dimreg = dimreg;  
 }  
   
   
 NoteEntry::NoteEntry(char* labelText, uint8_t& (*access)(gig::DimensionRegion*)) :  
     NumEntryX<uint8_t>(labelText, access)  
 {  
     spinbutton.signal_input().connect(  
         sigc::mem_fun(*this, &NoteEntry::on_input));  
     spinbutton.signal_output().connect(  
         sigc::mem_fun(*this, &NoteEntry::on_output));  
 }  
   
 const char* notes[] = {  
     "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"  
 };  
   
   
 // Convert the Entry text to a number  
 int NoteEntry::on_input(double* new_value)  
 {  
     const char* str = spinbutton.get_text().c_str();  
   
     int i;  
     for (i = 11 ; i >= 0 ; i--) {  
         if (strncmp(str, notes[i], strlen(notes[i])) == 0) break;  
     }  
     if (i >= 0) {  
         char* endptr;  
         long x = strtol(str + strlen(notes[i]), &endptr, 10);  
         if (endptr != str + strlen(notes[i])) {  
             *new_value = i + (x + 1) * 12;  
             return true;  
         }  
     }  
     return Gtk::INPUT_ERROR;  
 }  
   
 // Convert the Adjustment position to text  
 bool NoteEntry::on_output()  
 {  
     int x = int(spinbutton.get_adjustment()->get_value());  
     char buf[10];  
     sprintf(buf, "%s%d", notes[x % 12], x / 12 - 1);  
     spinbutton.set_text(buf);  
     return true;  
 }  
   
 BoolEntry::BoolEntry(char* labelText, bool gig::DimensionRegion::* param) :  
     LabelWidget(labelText, checkbutton),  
     param(param)  
 {  
     checkbutton.signal_toggled().connect(  
         sigc::mem_fun(*this, &BoolEntry::value_changed));  
 }  
   
 void BoolEntry::value_changed()  
 {  
     if (dimreg && update_gui) {  
         dimreg->*param = checkbutton.get_active();  
     }  
 }  
   
 void BoolEntry::set_dimreg(gig::DimensionRegion* dimreg)  
 {  
     this->dimreg = 0;  
     checkbutton.set_active(dimreg->*param);  
     this->dimreg = dimreg;  
 }  
35    
36  ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(  #include "mainwindow.h"
     char* labelText,  
     gig::leverage_ctrl_t gig::DimensionRegion::* param) :  
     align(0, 0, 0, 0),  
     LabelWidget(labelText, align),  
     param(param)  
 {  
     for (int i = 0 ; i < 99 ; i++) {  
         if (controlChangeTexts[i]) {  
             combobox.append_text(controlChangeTexts[i]);  
         }  
     }  
     combobox.signal_changed().connect(  
         sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));  
     align.add(combobox);  
 }  
   
 void ChoiceEntryLeverageCtrl::value_changed()  
 {  
     if (dimreg && update_gui) {  
         int rowno = combobox.get_active_row_number();  
         switch (rowno)  
         {  
         case -1:  
             break;  
         case 0:  
             (dimreg->*param).type = gig::leverage_ctrl_t::type_none;  
             break;  
         case 1:  
             (dimreg->*param).type =  
                 gig::leverage_ctrl_t::type_channelaftertouch;  
             break;  
         case 2:  
             (dimreg->*param).type = gig::leverage_ctrl_t::type_velocity;  
             break;  
         default:  
             (dimreg->*param).type = gig::leverage_ctrl_t::type_controlchange;  
             int x = 3;  
             for (int cc = 0 ; cc < 96 ; cc++) {  
                 if (controlChangeTexts[cc + 3]) {  
                     if (rowno == x) {  
                         (dimreg->*param).controller_number = cc;  
                         break;  
                     }  
                     x++;  
                 }  
             }  
             break;  
         }  
     }  
 }  
   
 void ChoiceEntryLeverageCtrl::set_dimreg(gig::DimensionRegion* dimreg)  
 {  
     this->dimreg = 0;  
     gig::leverage_ctrl_t c = dimreg->*param;  
     int x;  
     switch (c.type)  
     {  
     case gig::leverage_ctrl_t::type_none:  
         x = 0;  
         break;  
     case gig::leverage_ctrl_t::type_channelaftertouch:  
         x = 1;  
         break;  
     case gig::leverage_ctrl_t::type_velocity:  
         x = 2;  
         break;  
     case gig::leverage_ctrl_t::type_controlchange:  
         x = -1;  
         for (int cc = 0 ; cc < 96 ; cc++) {  
             if (controlChangeTexts[cc + 3]) {  
                 x++;  
                 if (c.controller_number == cc) {  
                     x += 3;  
                     break;  
                 }  
             }  
         }  
         break;  
     default:  
         x = -1;  
         break;  
     }  
     combobox.set_active(x);  
     this->dimreg = dimreg;  
 }  
37    
38  void MainWindow::addHeader(char* text)  #define _(String) gettext(String)
 {  
     if (firstRowInBlock < rowno - 1)  
     {  
         Gtk::Label* filler = new Gtk::Label("    ");  
         table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,  
                               Gtk::FILL, Gtk::SHRINK);  
     }  
     Glib::ustring str = "<b>";  
     str += text;  
     str += "</b>";  
     Gtk::Label* label = new Gtk::Label(str);  
     label->set_use_markup();  
     label->set_alignment(Gtk::ALIGN_LEFT);  
     table[pageno]->attach(*label, 0, 3, rowno, rowno + 1,  
                           Gtk::FILL, Gtk::SHRINK);  
     rowno++;  
     firstRowInBlock = rowno;  
 }  
39    
40  void MainWindow::nextPage()  template<class T> inline std::string ToString(T o) {
41  {      std::stringstream ss;
42      if (firstRowInBlock < rowno - 1)      ss << o;
43      {      return ss.str();
         Gtk::Label* filler = new Gtk::Label("    ");  
         table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,  
                               Gtk::FILL, Gtk::SHRINK);  
     }  
     pageno++;  
     rowno = 0;  
     firstRowInBlock = 0;  
 }  
   
 void MainWindow::addProp(LabelWidget& prop)  
 {  
     table[pageno]->attach(prop.label, 1, 2, rowno, rowno + 1,  
                           Gtk::FILL, Gtk::SHRINK);  
     table[pageno]->attach(prop.widget, 2, 3, rowno, rowno + 1,  
                           Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);  
     rowno++;  
44  }  }
45    
46    MainWindow::MainWindow()
   
   
 MainWindow::MainWindow() :  
 //    eSample("Sample", wSample),  
     eVelocityUpperLimit("VelocityUpperLimit",  
                         &gig::DimensionRegion::VelocityUpperLimit),  
     eEG1PreAttack("PreAttack", &gig::DimensionRegion::EG1PreAttack, 0, 100, 2),  
     eEG1Attack("Attack", &gig::DimensionRegion::EG1Attack, 0, 60, 3),  
     eEG1Decay1("Decay1", &gig::DimensionRegion::EG1Decay1, 0.005, 60, 3),  
     eEG1Decay2("Decay2", &gig::DimensionRegion::EG1Decay2, 0, 60, 3),  
     eEG1InfiniteSustain("InfiniteSustain",  
                         &gig::DimensionRegion::EG1InfiniteSustain),  
     eEG1Sustain("Sustain", &gig::DimensionRegion::EG1Sustain, 0, 100, 2),  
     eEG1Release("Release", &gig::DimensionRegion::EG1Release, 0, 60, 3),  
     eEG1Hold("Hold", &gig::DimensionRegion::EG1Hold),  
     eEG1Controller("Controller", &gig::DimensionRegion::EG1Controller),  
     eEG1ControllerInvert("ControllerInvert",  
                          &gig::DimensionRegion::EG1ControllerInvert),  
     eEG1ControllerAttackInfluence("ControllerAttackInfluence",  
                                   &gig::DimensionRegion::EG1ControllerAttackInfluence,  
                                   0, 3),  
     eEG1ControllerDecayInfluence("ControllerDecayInfluence",  
                                  &gig::DimensionRegion::EG1ControllerDecayInfluence,  
                                  0, 3),  
     eEG1ControllerReleaseInfluence("ControllerReleaseInfluence",  
                                    &gig::DimensionRegion::EG1ControllerReleaseInfluence,  
                                    0, 3),  
     eLFO1Frequency("Frequency", &gig::DimensionRegion::LFO1Frequency,  
                    0.1, 10, 2),  
     eLFO1InternalDepth("InternalDepth",  
                        &gig::DimensionRegion::LFO1InternalDepth, 0, 1200),  
     eLFO1ControlDepth("ControlDepth", &gig::DimensionRegion::LFO1ControlDepth,  
                       0, 1200),  
     eLFO1Controller("Controller", &gig::DimensionRegion::LFO1Controller),  
     eLFO1FlipPhase("FlipPhase", &gig::DimensionRegion::LFO1FlipPhase),  
     eLFO1Sync("Sync", &gig::DimensionRegion::LFO1Sync),  
     eEG2PreAttack("PreAttack", &gig::DimensionRegion::EG2PreAttack, 0, 100, 2),  
     eEG2Attack("Attack", &gig::DimensionRegion::EG2Attack, 0, 60, 3),  
     eEG2Decay1("Decay1", &gig::DimensionRegion::EG2Decay1, 0.005, 60, 3),  
     eEG2Decay2("Decay2", &gig::DimensionRegion::EG2Decay2, 0, 60, 3),  
     eEG2InfiniteSustain("InfiniteSustain",  
                         &gig::DimensionRegion::EG2InfiniteSustain),  
     eEG2Sustain("Sustain", &gig::DimensionRegion::EG2Sustain, 0, 100, 2),  
     eEG2Release("Release", &gig::DimensionRegion::EG2Release, 0, 60, 3),  
     eEG2Controller("Controller", &gig::DimensionRegion::EG2Controller),  
     eEG2ControllerInvert("ControllerInvert",  
                          &gig::DimensionRegion::EG2ControllerInvert),  
     eEG2ControllerAttackInfluence("ControllerAttackInfluence",  
                                   &gig::DimensionRegion::EG2ControllerAttackInfluence,  
                                   0, 3),  
     eEG2ControllerDecayInfluence("ControllerDecayInfluence",  
                                  &gig::DimensionRegion::EG2ControllerDecayInfluence,  
                                  0, 3),  
     eEG2ControllerReleaseInfluence("ControllerReleaseInfluence",  
                                    &gig::DimensionRegion::EG2ControllerReleaseInfluence,  
                                    0, 3),  
     eLFO2Frequency("Frequency", &gig::DimensionRegion::LFO2Frequency,  
                    0.1, 10, 2),  
     eLFO2InternalDepth("InternalDepth",  
                        &gig::DimensionRegion::LFO2InternalDepth, 0, 1200),  
     eLFO2ControlDepth("ControlDepth",  
                       &gig::DimensionRegion::LFO2ControlDepth, 0, 1200),  
     eLFO2Controller("Controller", &gig::DimensionRegion::LFO2Controller),  
     eLFO2FlipPhase("FlipPhase", &gig::DimensionRegion::LFO2FlipPhase),  
     eLFO2Sync("Sync", &gig::DimensionRegion::LFO2Sync),  
     eEG3Attack("Attack", &gig::DimensionRegion::EG3Attack, 0, 10, 3),  
     eEG3Depth("Depth", &gig::DimensionRegion::EG3Depth, -1200, 1200),  
     eLFO3Frequency("Frequency", &gig::DimensionRegion::LFO3Frequency,  
                    0.1, 10, 2),  
     eLFO3InternalDepth("InternalDepth",  
                        &gig::DimensionRegion::LFO3InternalDepth, 0, 1200),  
     eLFO3ControlDepth("ControlDepth", &gig::DimensionRegion::LFO3ControlDepth,  
                       0, 1200),  
     eLFO3Controller("Controller", &gig::DimensionRegion::LFO3Controller),  
     eLFO3Sync("Sync", &gig::DimensionRegion::LFO3Sync),  
     eVCFEnabled("Enabled", &gig::DimensionRegion::VCFEnabled),  
     eVCFType("Type", &gig::DimensionRegion::VCFType),  
     eVCFCutoffController("CutoffController",  
                          &gig::DimensionRegion::VCFCutoffController),  
     eVCFCutoffControllerInvert("CutoffControllerInvert",  
                                &gig::DimensionRegion::VCFCutoffControllerInvert),  
     eVCFCutoff("Cutoff", &gig::DimensionRegion::VCFCutoff),  
     eVCFVelocityCurve("VelocityCurve", &gig::DimensionRegion::VCFVelocityCurve),  
     eVCFVelocityScale("VelocityScale", &gig::DimensionRegion::VCFVelocityScale),  
     eVCFVelocityDynamicRange("VelocityDynamicRange",  
                              &gig::DimensionRegion::VCFVelocityDynamicRange,  
                              0, 4),  
     eVCFResonance("Resonance", &gig::DimensionRegion::VCFResonance),  
     eVCFResonanceDynamic("ResonanceDynamic",  
                          &gig::DimensionRegion::VCFResonanceDynamic),  
     eVCFResonanceController("ResonanceController",  
                             &gig::DimensionRegion::VCFResonanceController),  
     eVCFKeyboardTracking("KeyboardTracking",  
                          &gig::DimensionRegion::VCFKeyboardTracking),  
     eVCFKeyboardTrackingBreakpoint("KeyboardTrackingBreakpoint",  
                                    &gig::DimensionRegion::VCFKeyboardTrackingBreakpoint),  
     eVelocityResponseCurve("VelocityResponseCurve",  
                            &gig::DimensionRegion::VelocityResponseCurve),  
     eVelocityResponseDepth("VelocityResponseDepth",  
                            &gig::DimensionRegion::VelocityResponseDepth, 0, 4),  
     eVelocityResponseCurveScaling("VelocityResponseCurveScaling",  
                                   &gig::DimensionRegion::VelocityResponseCurveScaling),  
     eReleaseVelocityResponseCurve("ReleaseVelocityResponseCurve",  
                                   &gig::DimensionRegion::ReleaseVelocityResponseCurve),  
     eReleaseVelocityResponseDepth("ReleaseVelocityResponseDepth",  
                                   &gig::DimensionRegion::ReleaseVelocityResponseDepth,  
                                   0, 4),  
     eReleaseTriggerDecay("ReleaseTriggerDecay",  
                          &gig::DimensionRegion::ReleaseTriggerDecay, 0, 8),  
     eCrossfade_in_start("Crossfade.in_start", &access_Crossfade_in_start),  
     eCrossfade_in_end("Crossfade.in_end", &access_Crossfade_in_end),  
     eCrossfade_out_start("Crossfade.out_start", &access_Crossfade_out_start),  
     eCrossfade_out_end("Crossfade.out_end", &access_Crossfade_out_end),  
     ePitchTrack("PitchTrack", &gig::DimensionRegion::PitchTrack),  
     eDimensionBypass("DimensionBypass", &gig::DimensionRegion::DimensionBypass),  
     ePan("Pan", &gig::DimensionRegion::Pan, -64, 63),  
     eSelfMask("SelfMask", &gig::DimensionRegion::SelfMask),  
     eAttenuationController("AttenuationController",  
                            &gig::DimensionRegion::AttenuationController),  
     eInvertAttenuationController("InvertAttenuationController",  
                                  &gig::DimensionRegion::InvertAttenuationController),  
     eAttenuationControllerThreshold("AttenuationControllerThreshold",  
                                     &gig::DimensionRegion::AttenuationControllerThreshold),  
     eChannelOffset("ChannelOffset", &gig::DimensionRegion::ChannelOffset, 0, 9),  
     eSustainDefeat("SustainDefeat", &gig::DimensionRegion::SustainDefeat),  
     eMSDecode("MSDecode", &gig::DimensionRegion::MSDecode),  
     eSampleStartOffset("SampleStartOffset",  
                        &gig::DimensionRegion::SampleStartOffset, 0, 2000),  
     eUnityNote("UnityNote", &access_UnityNote),  
     eFineTune("FineTune", &access_FineTune, -49, 50),  
     eGain("Gain", -96, 0, 2),  
     eSampleLoops("SampleLoops", &access_SampleLoops, 0, 1)  
47  {  {
48  //    set_border_width(5);  //    set_border_width(5);
49      set_default_size(400, 200);  //    set_default_size(400, 200);
50    
51    
52      add(m_VBox);      add(m_VBox);
# Line 521  MainWindow::MainWindow() : Line 56  MainWindow::MainWindow() :
56      tree_sel_ref->signal_changed().connect(      tree_sel_ref->signal_changed().connect(
57          sigc::mem_fun(*this, &MainWindow::on_sel_change));          sigc::mem_fun(*this, &MainWindow::on_sel_change));
58    
59        // m_TreeView.set_reorderable();
60    
61      m_TreeView.signal_button_press_event().connect_notify(      m_TreeView.signal_button_press_event().connect_notify(
62          sigc::mem_fun(*this, &MainWindow::on_button_release));          sigc::mem_fun(*this, &MainWindow::on_button_release));
63    
64      // Add the TreeView, inside a ScrolledWindow, with the button underneath:      // Add the TreeView tab, inside a ScrolledWindow, with the button underneath:
65      m_ScrolledWindow.add(m_TreeView);      m_ScrolledWindow.add(m_TreeView);
66      m_ScrolledWindow.set_size_request(400, 600);  //    m_ScrolledWindow.set_size_request(200, 600);
67      m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);      m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
68    
69      for (int i = 0 ; i < 5 ; i++) {      m_ScrolledWindowSamples.add(m_TreeViewSamples);
70          table[i] = new Gtk::Table(3, 1);      m_ScrolledWindowSamples.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
71          table[i]->set_col_spacings(5);  
72      }  
73        m_TreeViewNotebook.set_size_request(300);
74      pageno = 0;  
75      rowno = 0;      m_HPaned.add1(m_TreeViewNotebook);
76      firstRowInBlock = 0;      m_HPaned.add2(dimreg_edit);
   
     addString("Sample", lSample, wSample);  
     addProp(eVelocityUpperLimit);  
     addHeader("EG1");  
     addProp(eEG1PreAttack);  
     addProp(eEG1Attack);  
     addProp(eEG1Decay1);  
     addProp(eEG1Decay2);  
     addProp(eEG1InfiniteSustain);  
     addProp(eEG1Sustain);  
     addProp(eEG1Release);  
     addProp(eEG1Hold);  
     addProp(eEG1Controller);  
     addProp(eEG1ControllerInvert);  
     addProp(eEG1ControllerAttackInfluence);  
     addProp(eEG1ControllerDecayInfluence);  
     addProp(eEG1ControllerReleaseInfluence);  
     addHeader("LFO1");  
     addProp(eLFO1Frequency);  
     addProp(eLFO1InternalDepth);  
     addProp(eLFO1ControlDepth);  
     {  
         char* choices[] = { "internal", "modwheel", "breath",  
                             "internal+modwheel", "internal+breath", 0 };  
         static const gig::lfo1_ctrl_t values[] = {  
             gig::lfo1_ctrl_internal,  
             gig::lfo1_ctrl_modwheel,  
             gig::lfo1_ctrl_breath,  
             gig::lfo1_ctrl_internal_modwheel,  
             gig::lfo1_ctrl_internal_breath  
         };  
         eLFO1Controller.set_choices(choices, values);  
     }  
     addProp(eLFO1Controller);  
     addProp(eLFO1FlipPhase);  
     addProp(eLFO1Sync);  
   
     nextPage();  
     addHeader("EG2");  
     addProp(eEG2PreAttack);  
     addProp(eEG2Attack);  
     addProp(eEG2Decay1);  
     addProp(eEG2Decay2);  
     addProp(eEG2InfiniteSustain);  
     addProp(eEG2Sustain);  
     addProp(eEG2Release);  
     addProp(eEG2Controller);  
     addProp(eEG2ControllerInvert);  
     addProp(eEG2ControllerAttackInfluence);  
     addProp(eEG2ControllerDecayInfluence);  
     addProp(eEG2ControllerReleaseInfluence);  
     addHeader("LFO2");  
     addProp(eLFO2Frequency);  
     addProp(eLFO2InternalDepth);  
     addProp(eLFO2ControlDepth);  
     {  
         char* choices[] = { "internal", "modwheel", "foot",  
                             "internal+modwheel", "internal+foot", 0 };  
         static const gig::lfo2_ctrl_t values[] = {  
             gig::lfo2_ctrl_internal,  
             gig::lfo2_ctrl_modwheel,  
             gig::lfo2_ctrl_foot,  
             gig::lfo2_ctrl_internal_modwheel,  
             gig::lfo2_ctrl_internal_foot  
         };  
         eLFO2Controller.set_choices(choices, values);  
     }  
     addProp(eLFO2Controller);  
     addProp(eLFO2FlipPhase);  
     addProp(eLFO2Sync);  
   
     nextPage();  
   
     addHeader("EG3");  
     addProp(eEG3Attack);  
     addProp(eEG3Depth);  
     addHeader("LFO3");  
     addProp(eLFO3Frequency);  
     addProp(eLFO3InternalDepth);  
     addProp(eLFO3ControlDepth);  
     {  
         char* choices[] = { "internal", "modwheel", "aftertouch",  
                             "internal+modwheel", "internal+aftertouch", 0 };  
         static const gig::lfo3_ctrl_t values[] = {  
             gig::lfo3_ctrl_internal,  
             gig::lfo3_ctrl_modwheel,  
             gig::lfo3_ctrl_aftertouch,  
             gig::lfo3_ctrl_internal_modwheel,  
             gig::lfo3_ctrl_internal_aftertouch  
         };  
         eLFO3Controller.set_choices(choices, values);  
     }  
     addProp(eLFO3Controller);  
     addProp(eLFO3Sync);  
     addHeader("VCF");  
     addProp(eVCFEnabled);  
     {  
         char* choices[] = { "lowpass", "lowpassturbo", "bandpass",  
                             "highpass", "bandreject", 0 };  
         static const gig::vcf_type_t values[] = {  
             gig::vcf_type_lowpass,  
             gig::vcf_type_lowpassturbo,  
             gig::vcf_type_bandpass,  
             gig::vcf_type_highpass,  
             gig::vcf_type_bandreject  
         };  
         eVCFType.set_choices(choices, values);  
     }  
     addProp(eVCFType);  
     {  
         char* choices[] = { "none", "none2", "modwheel", "effect1", "effect2",  
                             "breath", "foot", "sustainpedal", "softpedal",  
                             "genpurpose7", "genpurpose8", "aftertouch", 0 };  
         static const gig::vcf_cutoff_ctrl_t values[] = {  
             gig::vcf_cutoff_ctrl_none,  
             gig::vcf_cutoff_ctrl_none2,  
             gig::vcf_cutoff_ctrl_modwheel,  
             gig::vcf_cutoff_ctrl_effect1,  
             gig::vcf_cutoff_ctrl_effect2,  
             gig::vcf_cutoff_ctrl_breath,  
             gig::vcf_cutoff_ctrl_foot,  
             gig::vcf_cutoff_ctrl_sustainpedal,  
             gig::vcf_cutoff_ctrl_softpedal,  
             gig::vcf_cutoff_ctrl_genpurpose7,  
             gig::vcf_cutoff_ctrl_genpurpose8,  
             gig::vcf_cutoff_ctrl_aftertouch  
         };  
         eVCFCutoffController.set_choices(choices, values);  
     }  
     addProp(eVCFCutoffController);  
     addProp(eVCFCutoffControllerInvert);  
     addProp(eVCFCutoff);  
     char* curve_type_texts[] = { "nonlinear", "linear", "special", 0 };  
     static const gig::curve_type_t curve_type_values[] = {  
         gig::curve_type_nonlinear,  
         gig::curve_type_linear,  
         gig::curve_type_special  
     };  
     eVCFVelocityCurve.set_choices(curve_type_texts, curve_type_values);  
     addProp(eVCFVelocityCurve);  
     addProp(eVCFVelocityScale);  
     addProp(eVCFVelocityDynamicRange);  
     addProp(eVCFResonance);  
     addProp(eVCFResonanceDynamic);  
     {  
         char* choices[] = { "none", "genpurpose3", "genpurpose4",  
                             "genpurpose5", "genpurpose6", 0 };  
         static const gig::vcf_res_ctrl_t values[] = {  
             gig::vcf_res_ctrl_none,  
             gig::vcf_res_ctrl_genpurpose3,  
             gig::vcf_res_ctrl_genpurpose4,  
             gig::vcf_res_ctrl_genpurpose5,  
             gig::vcf_res_ctrl_genpurpose6  
         };  
         eVCFResonanceController.set_choices(choices, values);  
     }  
     addProp(eVCFResonanceController);  
     addProp(eVCFKeyboardTracking);  
     addProp(eVCFKeyboardTrackingBreakpoint);  
   
     nextPage();  
   
     eVelocityResponseCurve.set_choices(curve_type_texts, curve_type_values);  
     addProp(eVelocityResponseCurve);  
     addProp(eVelocityResponseDepth);  
     addProp(eVelocityResponseCurveScaling);  
     eReleaseVelocityResponseCurve.set_choices(curve_type_texts,  
                                               curve_type_values);  
     addProp(eReleaseVelocityResponseCurve);  
     addProp(eReleaseVelocityResponseDepth);  
     addProp(eReleaseTriggerDecay);  
     addProp(eCrossfade_in_start);  
     addProp(eCrossfade_in_end);  
     addProp(eCrossfade_out_start);  
     addProp(eCrossfade_out_end);  
     addProp(ePitchTrack);  
     {  
         char* choices[] = { "none", "effect4depth", "effect5depth", 0 };  
         static const gig::dim_bypass_ctrl_t values[] = {  
             gig::dim_bypass_ctrl_none,  
             gig::dim_bypass_ctrl_94,  
             gig::dim_bypass_ctrl_95  
         };  
         eDimensionBypass.set_choices(choices, values);  
     }  
     addProp(eDimensionBypass);  
     addProp(ePan);  
     addProp(eSelfMask);  
     addProp(eAttenuationController);  
     addProp(eInvertAttenuationController);  
     addProp(eAttenuationControllerThreshold);  
     addProp(eChannelOffset);  
     addProp(eSustainDefeat);  
   
     nextPage();  
     addProp(eMSDecode);  
     addProp(eSampleStartOffset);  
     addProp(eUnityNote);  
     addProp(eFineTune);  
     addProp(eGain);  
     addProp(eSampleLoops);  
     nextPage();  
   
     eEG1InfiniteSustain.signal_toggled().connect(  
         sigc::mem_fun(*this, &MainWindow::EG1InfiniteSustain_toggled) );  
     eEG2InfiniteSustain.signal_toggled().connect(  
         sigc::mem_fun(*this, &MainWindow::EG2InfiniteSustain_toggled) );  
     eEG1Controller.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::EG1Controller_changed) );  
     eEG2Controller.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::EG2Controller_changed) );  
     eLFO1Controller.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::LFO1Controller_changed) );  
     eLFO2Controller.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::LFO2Controller_changed) );  
     eLFO3Controller.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::LFO3Controller_changed) );  
     eAttenuationController.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::AttenuationController_changed) );  
     eVCFEnabled.signal_toggled().connect(  
         sigc::mem_fun(*this, &MainWindow::VCFEnabled_toggled) );  
     eVCFCutoffController.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::VCFCutoffController_changed) );  
     eVCFResonanceController.signal_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::VCFResonanceController_changed) );  
   
     eCrossfade_in_start.signal_value_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::crossfade1_changed));  
     eCrossfade_in_end.signal_value_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::crossfade2_changed));  
     eCrossfade_out_start.signal_value_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::crossfade3_changed));  
     eCrossfade_out_end.signal_value_changed().connect(  
         sigc::mem_fun(*this, &MainWindow::crossfade4_changed));  
   
     //m_Notebook.append_page(m_ScrolledWindow2, "Table");  
     m_Notebook.append_page(*table[0], "EG1");  
     m_Notebook.append_page(*table[1], "EG2");  
     m_Notebook.append_page(*table[2], "EG3");  
     m_Notebook.append_page(*table[3], "Velocity");  
     m_Notebook.append_page(*table[4], "Misc");  
     m_Notebook.set_size_request(400, 500);  
77    
78      m_HPaned.add1(m_ScrolledWindow);  
79      m_HPaned.add2(m_Notebook);      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");
80        m_TreeViewNotebook.append_page(m_ScrolledWindow, "Instruments");
81    
82    
83      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
# Line 813  MainWindow::MainWindow() : Line 109  MainWindow::MainWindow() :
109      actionGroup->add(Gtk::Action::create("InstrProperties",      actionGroup->add(Gtk::Action::create("InstrProperties",
110                                           Gtk::Stock::PROPERTIES),                                           Gtk::Stock::PROPERTIES),
111                       sigc::mem_fun(                       sigc::mem_fun(
112                           *this, &MainWindow::on_action_file_properties));                           *this, &MainWindow::show_instr_props));
113      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
114                       sigc::mem_fun(                       sigc::mem_fun(
115                           *this, &MainWindow::hide));                           *this, &MainWindow::hide));
116        actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
117    
118      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
119      actionGroup->add(Gtk::Action::create("MenuHelp",      actionGroup->add(Gtk::Action::create("MenuHelp",
120                                           action->property_label()));                                           action->property_label()));
# Line 825  MainWindow::MainWindow() : Line 123  MainWindow::MainWindow() :
123                       sigc::mem_fun(                       sigc::mem_fun(
124                           *this, &MainWindow::on_action_help_about));                           *this, &MainWindow::on_action_help_about));
125  #endif  #endif
126      action = Gtk::Action::create("Remove", "Ta bort");      action = Gtk::Action::create("Remove", Gtk::Stock::REMOVE);
127      actionGroup->add(action,      actionGroup->add(action,
128                       sigc::mem_fun(                       sigc::mem_fun(
129                           *this, &MainWindow::hide));                           *this, &MainWindow::hide));
130    
131        // sample right-click popup actions
132        actionGroup->add(
133            Gtk::Action::create("SampleProperties", Gtk::Stock::PROPERTIES),
134            sigc::mem_fun(*this, &MainWindow::on_action_sample_properties)
135        );
136        actionGroup->add(
137            Gtk::Action::create("AddGroup", _("Add _Group")),
138            sigc::mem_fun(*this, &MainWindow::on_action_add_group)
139        );
140        actionGroup->add(
141            Gtk::Action::create("AddSample", _("Add _Sample(s)")),
142            sigc::mem_fun(*this, &MainWindow::on_action_add_sample)
143        );
144        actionGroup->add(
145            Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),
146            sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)
147        );
148    
149      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
150      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
151      // add_accel_group(uiManager->get_accel_group());      // add_accel_group(uiManager->get_accel_group());
# Line 848  MainWindow::MainWindow() : Line 164  MainWindow::MainWindow() :
164          "      <separator/>"          "      <separator/>"
165          "      <menuitem action='Quit'/>"          "      <menuitem action='Quit'/>"
166          "    </menu>"          "    </menu>"
167            "    <menu action='MenuInstrument'>"
168            "    </menu>"
169  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
170          "    <menu action='MenuHelp'>"          "    <menu action='MenuHelp'>"
171          "      <menuitem action='About'/>"          "      <menuitem action='About'/>"
# Line 858  MainWindow::MainWindow() : Line 176  MainWindow::MainWindow() :
176          "    <menuitem action='InstrProperties'/>"          "    <menuitem action='InstrProperties'/>"
177          "    <menuitem action='Remove'/>"          "    <menuitem action='Remove'/>"
178          "  </popup>"          "  </popup>"
179            "  <popup name='SamplePopupMenu'>"
180            "    <menuitem action='SampleProperties'/>"
181            "    <menuitem action='AddGroup'/>"
182            "    <menuitem action='AddSample'/>"
183            "    <separator/>"
184            "    <menuitem action='RemoveSample'/>"
185            "  </popup>"
186          "</ui>";          "</ui>";
187      uiManager->add_ui_from_string(ui_info);      uiManager->add_ui_from_string(ui_info);
188    
# Line 878  MainWindow::MainWindow() : Line 203  MainWindow::MainWindow() :
203      // Create the Tree model:      // Create the Tree model:
204      m_refTreeModel = Gtk::ListStore::create(m_Columns);      m_refTreeModel = Gtk::ListStore::create(m_Columns);
205      m_TreeView.set_model(m_refTreeModel);      m_TreeView.set_model(m_refTreeModel);
206        m_refTreeModel->signal_row_changed().connect(
207            sigc::mem_fun(*this, &MainWindow::instrument_name_changed)
208        );
209    
210      // Add the TreeView's view columns:      // Add the TreeView's view columns:
211      m_TreeView.append_column("Instrument", m_Columns.m_col_name);      m_TreeView.append_column_editable("Instrument", m_Columns.m_col_name);
212      m_TreeView.set_headers_visible(false);      m_TreeView.set_headers_visible(false);
213    
214        // create samples treeview (including its data model)
215        m_refSamplesTreeModel = SamplesTreeStore::create(m_SamplesModel);
216        m_TreeViewSamples.set_model(m_refSamplesTreeModel);
217        // m_TreeViewSamples.set_reorderable();
218        m_TreeViewSamples.append_column_editable("Samples", m_SamplesModel.m_col_name);
219        m_TreeViewSamples.set_headers_visible(false);
220        m_TreeViewSamples.signal_button_press_event().connect_notify(
221            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_button_release)
222        );
223        m_refSamplesTreeModel->signal_row_changed().connect(
224            sigc::mem_fun(*this, &MainWindow::sample_name_changed)
225        );
226    
227        // establish drag&drop between samples tree view and dimension region 'Sample' text entry
228        std::list<Gtk::TargetEntry> drag_target_gig_sample;
229        drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
230    //drag_target_gig_sample.push_back( Gtk::TargetEntry("STRING") );
231    //drag_target_gig_sample.push_back( Gtk::TargetEntry("text/plain") );
232        m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
233        m_TreeViewSamples.signal_drag_data_get().connect(
234            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
235        );
236        dimreg_edit.wSample->drag_dest_set(drag_target_gig_sample);
237        dimreg_edit.wSample->signal_drag_data_received().connect(
238            sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
239        );
240    
241      file = 0;      file = 0;
242    
243      show_all_children();      show_all_children();
# Line 899  void MainWindow::region_changed() Line 254  void MainWindow::region_changed()
254    
255  void MainWindow::dimreg_changed()  void MainWindow::dimreg_changed()
256  {  {
257      set_dim_region(m_DimRegionChooser.get_dimregion());      dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());
258  }  }
259    
260  void MainWindow::on_sel_change()  void MainWindow::on_sel_change()
# Line 917  void MainWindow::on_sel_change() Line 272  void MainWindow::on_sel_change()
272      }      }
273  }  }
274    
 void MainWindow::set_dim_region(gig::DimensionRegion* d)  
 {  
     update_gui = false;  
     wSample->set_text(d->pSample ? d->pSample->pInfo->Name.c_str() : "NULL");  
     eVelocityUpperLimit.set_dimreg(d);  
     eEG1PreAttack.set_dimreg(d);  
     eEG1Attack.set_dimreg(d);  
     eEG1Decay1.set_dimreg(d);  
     eEG1Decay2.set_dimreg(d);  
     eEG1InfiniteSustain.set_dimreg(d);  
     eEG1Sustain.set_dimreg(d);  
     eEG1Release.set_dimreg(d);  
     eEG1Hold.set_dimreg(d);  
     eEG1Controller.set_dimreg(d);  
     eEG1ControllerInvert.set_dimreg(d);  
     eEG1ControllerAttackInfluence.set_dimreg(d);  
     eEG1ControllerDecayInfluence.set_dimreg(d);  
     eEG1ControllerReleaseInfluence.set_dimreg(d);  
     eLFO1Frequency.set_dimreg(d);  
     eLFO1InternalDepth.set_dimreg(d);  
     eLFO1ControlDepth.set_dimreg(d);  
     eLFO1Controller.set_dimreg(d);  
     eLFO1FlipPhase.set_dimreg(d);  
     eLFO1Sync.set_dimreg(d);  
     eEG2PreAttack.set_dimreg(d);  
     eEG2Attack.set_dimreg(d);  
     eEG2Decay1.set_dimreg(d);  
     eEG2Decay2.set_dimreg(d);  
     eEG2InfiniteSustain.set_dimreg(d);  
     eEG2Sustain.set_dimreg(d);  
     eEG2Release.set_dimreg(d);  
     eEG2Controller.set_dimreg(d);  
     eEG2ControllerInvert.set_dimreg(d);  
     eEG2ControllerAttackInfluence.set_dimreg(d);  
     eEG2ControllerDecayInfluence.set_dimreg(d);  
     eEG2ControllerReleaseInfluence.set_dimreg(d);  
     eLFO2Frequency.set_dimreg(d);  
     eLFO2InternalDepth.set_dimreg(d);  
     eLFO2ControlDepth.set_dimreg(d);  
     eLFO2Controller.set_dimreg(d);  
     eLFO2FlipPhase.set_dimreg(d);  
     eLFO2Sync.set_dimreg(d);  
     eEG3Attack.set_dimreg(d);  
     eEG3Depth.set_dimreg(d);  
     eLFO3Frequency.set_dimreg(d);  
     eLFO3InternalDepth.set_dimreg(d);  
     eLFO3ControlDepth.set_dimreg(d);  
     eLFO3Controller.set_dimreg(d);  
     eLFO3Sync.set_dimreg(d);  
     eVCFEnabled.set_dimreg(d);  
     eVCFType.set_dimreg(d);  
     eVCFCutoffController.set_dimreg(d);  
     eVCFCutoffControllerInvert.set_dimreg(d);  
     eVCFCutoff.set_dimreg(d);  
     eVCFVelocityCurve.set_dimreg(d);  
     eVCFVelocityScale.set_dimreg(d);  
     eVCFVelocityDynamicRange.set_dimreg(d);  
     eVCFResonance.set_dimreg(d);  
     eVCFResonanceDynamic.set_dimreg(d);  
     eVCFResonanceController.set_dimreg(d);  
     eVCFKeyboardTracking.set_dimreg(d);  
     eVCFKeyboardTrackingBreakpoint.set_dimreg(d);  
     eVelocityResponseCurve.set_dimreg(d);  
     eVelocityResponseDepth.set_dimreg(d);  
     eVelocityResponseCurveScaling.set_dimreg(d);  
     eReleaseVelocityResponseCurve.set_dimreg(d);  
     eReleaseVelocityResponseDepth.set_dimreg(d);  
     eReleaseTriggerDecay.set_dimreg(d);  
     eCrossfade_in_start.set_dimreg(d);  
     eCrossfade_in_end.set_dimreg(d);  
     eCrossfade_out_start.set_dimreg(d);  
     eCrossfade_out_end.set_dimreg(d);  
     ePitchTrack.set_dimreg(d);  
     eDimensionBypass.set_dimreg(d);  
     ePan.set_dimreg(d);  
     eSelfMask.set_dimreg(d);  
     eAttenuationController.set_dimreg(d);  
     eInvertAttenuationController.set_dimreg(d);  
     eAttenuationControllerThreshold.set_dimreg(d);  
     eChannelOffset.set_dimreg(d);  
     eSustainDefeat.set_dimreg(d);  
     eMSDecode.set_dimreg(d);  
     eSampleStartOffset.set_dimreg(d);  
     eUnityNote.set_dimreg(d);  
     eFineTune.set_dimreg(d);  
     eGain.set_dimreg(d);  
     eSampleLoops.set_dimreg(d);  
   
     VCFEnabled_toggled();  
   
     update_gui = true;  
 }  
   
 void MainWindow::VCFEnabled_toggled()  
 {  
     bool sensitive = eVCFEnabled.get_active();  
     eVCFType.set_sensitive(sensitive);  
     eVCFCutoffController.set_sensitive(sensitive);  
     eVCFVelocityCurve.set_sensitive(sensitive);  
     eVCFVelocityScale.set_sensitive(sensitive);  
     eVCFVelocityDynamicRange.set_sensitive(sensitive);  
     eVCFResonance.set_sensitive(sensitive);  
     eVCFResonanceController.set_sensitive(sensitive);  
     eVCFKeyboardTracking.set_sensitive(sensitive);  
     eVCFKeyboardTrackingBreakpoint.set_sensitive(sensitive);  
     eEG2PreAttack.set_sensitive(sensitive);  
     eEG2Attack.set_sensitive(sensitive);  
     eEG2Decay1.set_sensitive(sensitive);  
     eEG2InfiniteSustain.set_sensitive(sensitive);  
     eEG2Sustain.set_sensitive(sensitive);  
     eEG2Release.set_sensitive(sensitive);  
     eEG2Controller.set_sensitive(sensitive);  
     eEG2ControllerAttackInfluence.set_sensitive(sensitive);  
     eEG2ControllerDecayInfluence.set_sensitive(sensitive);  
     eEG2ControllerReleaseInfluence.set_sensitive(sensitive);  
     eLFO2Frequency.set_sensitive(sensitive);  
     eLFO2InternalDepth.set_sensitive(sensitive);  
     eLFO2ControlDepth.set_sensitive(sensitive);  
     eLFO2Controller.set_sensitive(sensitive);  
     eLFO2FlipPhase.set_sensitive(sensitive);  
     eLFO2Sync.set_sensitive(sensitive);  
     if (sensitive) {  
         VCFCutoffController_changed();  
         VCFResonanceController_changed();  
         EG2InfiniteSustain_toggled();  
         EG2Controller_changed();  
         LFO2Controller_changed();  
     } else {  
         eVCFCutoffControllerInvert.set_sensitive(false);  
         eVCFCutoff.set_sensitive(false);  
         eVCFResonanceDynamic.set_sensitive(false);  
         eVCFResonance.set_sensitive(false);  
         eEG2Decay2.set_sensitive(false);  
         eEG2ControllerInvert.set_sensitive(false);  
         eLFO2InternalDepth.set_sensitive(false);  
         eLFO2ControlDepth.set_sensitive(false);  
     }  
 }  
   
 void MainWindow::VCFCutoffController_changed()  
 {  
     int rowno = eVCFCutoffController.get_active_row_number();  
     bool hasController = rowno != 0 && rowno != 1;  
   
     eVCFCutoffControllerInvert.set_sensitive(hasController);  
     eVCFCutoff.set_sensitive(!hasController);  
     eVCFResonanceDynamic.set_sensitive(!hasController);  
     eVCFVelocityScale.label.set_text(hasController ? "MinimumCutoff:" :  
                                      "VelocityScale:");  
 }  
   
 void MainWindow::VCFResonanceController_changed()  
 {  
     bool hasController = eVCFResonanceController.get_active_row_number() != 0;  
     eVCFResonance.set_sensitive(!hasController);  
 }  
   
 void MainWindow::EG1InfiniteSustain_toggled()  
 {  
     bool infSus = eEG1InfiniteSustain.get_active();  
     eEG1Decay2.set_sensitive(!infSus);  
 }  
   
 void MainWindow::EG2InfiniteSustain_toggled()  
 {  
     bool infSus = eEG2InfiniteSustain.get_active();  
     eEG2Decay2.set_sensitive(!infSus);  
 }  
   
 void MainWindow::EG1Controller_changed()  
 {  
     bool hasController = eEG1Controller.get_active_row_number() != 0;  
     eEG1ControllerInvert.set_sensitive(hasController);  
 }  
   
 void MainWindow::EG2Controller_changed()  
 {  
     bool hasController = eEG2Controller.get_active_row_number() != 0;  
     eEG2ControllerInvert.set_sensitive(hasController);  
 }  
   
 void MainWindow::AttenuationController_changed()  
 {  
     bool hasController = eAttenuationController.get_active_row_number() != 0;  
     eInvertAttenuationController.set_sensitive(hasController);  
 }  
   
 void MainWindow::LFO1Controller_changed()  
 {  
     int rowno = eLFO1Controller.get_active_row_number();  
     eLFO1ControlDepth.set_sensitive(rowno != 0);  
     eLFO1InternalDepth.set_sensitive(rowno != 1 && rowno != 2);  
 }  
   
 void MainWindow::LFO2Controller_changed()  
 {  
     int rowno = eLFO2Controller.get_active_row_number();  
     eLFO2ControlDepth.set_sensitive(rowno != 0);  
     eLFO2InternalDepth.set_sensitive(rowno != 1 && rowno != 2);  
 }  
   
 void MainWindow::LFO3Controller_changed()  
 {  
     int rowno = eLFO3Controller.get_active_row_number();  
     eLFO3ControlDepth.set_sensitive(rowno != 0);  
     eLFO3InternalDepth.set_sensitive(rowno != 1 && rowno != 2);  
 }  
   
 void MainWindow::crossfade1_changed()  
 {  
     double c1 = eCrossfade_in_start.get_value();  
     double c2 = eCrossfade_in_end.get_value();  
     if (c1 > c2) eCrossfade_in_end.set_value(c1);  
 }  
   
 void MainWindow::crossfade2_changed()  
 {  
     double c1 = eCrossfade_in_start.get_value();  
     double c2 = eCrossfade_in_end.get_value();  
     double c3 = eCrossfade_out_start.get_value();  
   
     if (c2 < c1) eCrossfade_in_start.set_value(c2);  
     if (c2 > c3) eCrossfade_out_start.set_value(c2);  
 }  
   
 void MainWindow::crossfade3_changed()  
 {  
     double c2 = eCrossfade_in_end.get_value();  
     double c3 = eCrossfade_out_start.get_value();  
     double c4 = eCrossfade_out_end.get_value();  
   
     if (c3 < c2) eCrossfade_in_end.set_value(c3);  
     if (c3 > c4) eCrossfade_out_end.set_value(c3);  
 }  
   
 void MainWindow::crossfade4_changed()  
 {  
     double c3 = eCrossfade_out_start.get_value();  
     double c4 = eCrossfade_out_end.get_value();  
   
     if (c4 < c3) eCrossfade_out_start.set_value(c4);  
 }  
   
275  void loader_progress_callback(gig::progress_t* progress)  void loader_progress_callback(gig::progress_t* progress)
276  {  {
277      Loader* loader = static_cast<Loader*>(progress->custom);      Loader* loader = static_cast<Loader*>(progress->custom);
# Line 1221  Glib::Dispatcher& Loader::signal_finishe Line 333  Glib::Dispatcher& Loader::signal_finishe
333      return finished_dispatcher;      return finished_dispatcher;
334  }  }
335    
336  LoadDialog::LoadDialog()  LoadDialog::LoadDialog(const Glib::ustring& title, Gtk::Window& parent)
337        : Gtk::Dialog(title, parent, true)
338  {  {
339      get_vbox()->pack_start(progressBar);      get_vbox()->pack_start(progressBar);
340      show_all_children();      show_all_children();
# Line 1229  LoadDialog::LoadDialog() Line 342  LoadDialog::LoadDialog()
342    
343  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
344  {  {
345        m_SampleImportQueue.clear();
346  }  }
347    
348  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
# Line 1242  void MainWindow::on_action_file_open() Line 356  void MainWindow::on_action_file_open()
356      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
357          printf("filename=%s\n", dialog.get_filename().c_str());          printf("filename=%s\n", dialog.get_filename().c_str());
358    
359            // remove all entries from "Instrument" menu
360            Gtk::MenuItem* instrument_menu =
361                dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));
362            instrument_menu->hide();
363            for (int i = 0; i < instrument_menu->get_submenu()->items().size(); i++) {
364                delete &instrument_menu->get_submenu()->items()[i];
365            }
366            instrument_menu->get_submenu()->items().clear();
367    
368            m_SampleImportQueue.clear();
369          m_refTreeModel->clear();          m_refTreeModel->clear();
370            m_refSamplesTreeModel->clear();
371          if (file) delete file;          if (file) delete file;
372    
         // getInfo(dialog.get_filename().c_str(), *this);  
   
373          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
374          load_dialog = new LoadDialog(); // Gtk::Dialog("Loading...", *this, true);          load_file(dialog.get_filename().c_str());
         load_dialog->show_all();  
         loader = new Loader(strdup(dialog.get_filename().c_str()));  
         loader->signal_progress().connect(  
             sigc::mem_fun(*this, &MainWindow::on_loader_progress));  
         loader->signal_finished().connect(  
             sigc::mem_fun(*this, &MainWindow::on_loader_finished));  
   
         loader->launch();  
375      }      }
376  }  }
377    
378    void MainWindow::load_file(const char* name)
379    {
380        load_dialog = new LoadDialog("Loading...", *this);
381        load_dialog->show_all();
382        loader = new Loader(strdup(name));
383        loader->signal_progress().connect(
384            sigc::mem_fun(*this, &MainWindow::on_loader_progress));
385        loader->signal_finished().connect(
386            sigc::mem_fun(*this, &MainWindow::on_loader_finished));
387        loader->launch();
388    }
389    
390  void MainWindow::on_loader_progress()  void MainWindow::on_loader_progress()
391  {  {
392      load_dialog->set_fraction(loader->get_progress());      load_dialog->set_fraction(loader->get_progress());
# Line 1280  void MainWindow::on_loader_finished() Line 407  void MainWindow::on_loader_finished()
407    
408  void MainWindow::on_action_file_save()  void MainWindow::on_action_file_save()
409  {  {
410        if (!file) return;
411        std::cout << "Saving file\n" << std::flush;
412        try {
413            file->Save();
414        } catch (RIFF::Exception e) {
415            Glib::ustring txt = "Could not save file: " + e.Message;
416            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
417            msg.run();
418            return;
419        }
420        std::cout << "Saving file done\n" << std::flush;
421        __import_queued_samples();
422  }  }
423    
424  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
425  {  {
426        if (!file) return;
427      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);
428      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
429      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
# Line 1292  void MainWindow::on_action_file_save_as( Line 432  void MainWindow::on_action_file_save_as(
432      dialog.set_filter(filter);      dialog.set_filter(filter);
433      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
434          printf("filename=%s\n", dialog.get_filename().c_str());          printf("filename=%s\n", dialog.get_filename().c_str());
435          file->Save(dialog.get_filename());          try {
436                file->Save(dialog.get_filename());
437            } catch (RIFF::Exception e) {
438                Glib::ustring txt = "Could not save file: " + e.Message;
439                Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
440                msg.run();
441                return;
442            }
443            __import_queued_samples();
444        }
445    }
446    
447    // actually write the sample(s)' data to the gig file
448    void MainWindow::__import_queued_samples() {
449        std::cout << "Starting sample import\n" << std::flush;
450        Glib::ustring error_files;
451        printf("Samples to import: %d\n", m_SampleImportQueue.size());
452        for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
453             iter != m_SampleImportQueue.end(); ) {
454            printf("Importing sample %s\n",(*iter).sample_path.c_str());
455            SF_INFO info;
456            info.format = 0;
457            SNDFILE* hFile = sf_open((*iter).sample_path.c_str(), SFM_READ, &info);
458            try {
459                if (!hFile) throw std::string("could not open file");
460                // determine sample's bit depth
461                int bitdepth;
462                switch (info.format & 0xff) {
463                    case SF_FORMAT_PCM_S8:
464                        bitdepth = 16; // we simply convert to 16 bit for now
465                        break;
466                    case SF_FORMAT_PCM_16:
467                        bitdepth = 16;
468                        break;
469                    case SF_FORMAT_PCM_24:
470                        bitdepth = 32; // we simply convert to 32 bit for now
471                        break;
472                    case SF_FORMAT_PCM_32:
473                        bitdepth = 32;
474                        break;
475                    case SF_FORMAT_PCM_U8:
476                        bitdepth = 16; // we simply convert to 16 bit for now
477                        break;
478                    case SF_FORMAT_FLOAT:
479                        bitdepth = 32;
480                        break;
481                    case SF_FORMAT_DOUBLE:
482                        bitdepth = 32; // I guess we will always truncate this to 32 bit
483                        break;
484                    default:
485                        sf_close(hFile); // close sound file
486                        throw std::string("format not supported"); // unsupported subformat (yet?)
487                }
488                // allocate appropriate copy buffer (TODO: for now we copy
489                // it in one piece, might be tough for very long samples)
490                // and copy sample data into buffer
491                int8_t* buffer = NULL;
492                switch (bitdepth) {
493                    case 16:
494                        buffer = new int8_t[2 * info.channels * info.frames];
495                        // libsndfile does the conversion for us (if needed)
496                        sf_readf_short(hFile, (short*) buffer, info.frames);
497                        break;
498                    case 32:
499                        buffer = new int8_t[4 * info.channels * info.frames];
500                        // libsndfile does the conversion for us (if needed)
501                        sf_readf_int(hFile, (int*) buffer, info.frames);
502                        break;
503                }
504                // write from buffer directly (physically) into .gig file
505                (*iter).gig_sample->Write(buffer, info.frames);
506                // cleanup
507                sf_close(hFile);
508                delete buffer;
509                // on success we remove the sample from the import queue,
510                // otherwise keep it, maybe it works the next time ?
511                std::list<SampleImportItem>::iterator cur = iter;
512                ++iter;
513                m_SampleImportQueue.erase(cur);
514            } catch (std::string what) {
515                // remember the files that made trouble (and their cause)
516                if (error_files.size()) error_files += "\n";
517                error_files += (*iter).sample_path += " (" + what + ")";
518                ++iter;
519            }
520        }
521        // show error message box when some sample(s) could not be imported
522        if (error_files.size()) {
523            Glib::ustring txt = "Could not import the following sample(s):\n" + error_files;
524            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
525            msg.run();
526      }      }
527  }  }
528    
# Line 1424  InstrumentProps::InstrumentProps() Line 654  InstrumentProps::InstrumentProps()
654      show_all_children();      show_all_children();
655  }  }
656    
657    extern char* notes[];
658    
659  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
660  {  {
# Line 1455  void InstrumentProps::set_instrument(gig Line 686  void InstrumentProps::set_instrument(gig
686      entry[entryIdx].set_text(buf);      entry[entryIdx].set_text(buf);
687  }  }
688    
 void MainWindow::getInfo(const char *filename)  
 {  
     RIFF::File* riff = new RIFF::File(filename);  
     gig::File* gig = new gig::File(riff);  
   
     load_gig(gig, filename);  
 }  
   
689  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename)
690  {  {
691      file = gig;      file = gig;
# Line 1474  void MainWindow::load_gig(gig::File* gig Line 697  void MainWindow::load_gig(gig::File* gig
697    
698      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
699    
700        Gtk::MenuItem* instrument_menu =
701            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));
702    
703        int instrument_index = 0;
704        Gtk::RadioMenuItem::Group instrument_group;
705      for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ;      for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ;
706           instrument = gig->GetNextInstrument()) {           instrument = gig->GetNextInstrument()) {
707          Gtk::TreeModel::iterator iter = m_refTreeModel->append();          Gtk::TreeModel::iterator iter = m_refTreeModel->append();
708          Gtk::TreeModel::Row row = *iter;          Gtk::TreeModel::Row row = *iter;
709          row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();          row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
710          row[m_Columns.m_col_instr] = instrument;          row[m_Columns.m_col_instr] = instrument;
711            // create a menu item for this instrument
712            Gtk::RadioMenuItem* item =
713                new Gtk::RadioMenuItem(instrument_group, instrument->pInfo->Name.c_str());
714            instrument_menu->get_submenu()->append(*item);
715            item->signal_activate().connect(
716                sigc::bind(
717                    sigc::mem_fun(*this, &MainWindow::on_instrument_selection_change),
718                    instrument_index
719                )
720            );
721            instrument_index++;
722        }
723        instrument_menu->show();
724        instrument_menu->get_submenu()->show_all_children();
725    
726        for (gig::Group* group = gig->GetFirstGroup(); group; group = gig->GetNextGroup()) {
727            if (group->Name != "") {
728                Gtk::TreeModel::iterator iterGroup = m_refSamplesTreeModel->append();
729                Gtk::TreeModel::Row rowGroup = *iterGroup;
730                rowGroup[m_SamplesModel.m_col_name]   = group->Name.c_str();
731                rowGroup[m_SamplesModel.m_col_group]  = group;
732                rowGroup[m_SamplesModel.m_col_sample] = NULL;
733                for (gig::Sample* sample = group->GetFirstSample();
734                     sample; sample = group->GetNextSample()) {
735                    Gtk::TreeModel::iterator iterSample =
736                        m_refSamplesTreeModel->append(rowGroup.children());
737                    Gtk::TreeModel::Row rowSample = *iterSample;
738                    rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();
739                    rowSample[m_SamplesModel.m_col_sample] = sample;
740                    rowSample[m_SamplesModel.m_col_group]  = NULL;
741                }
742            }
743        }
744    }
745    
746    void MainWindow::show_instr_props()
747    {
748        Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
749        Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
750        if (it)
751        {
752            Gtk::TreeModel::Row row = *it;
753            if (row[m_Columns.m_col_instr])
754            {
755                instrumentProps.set_instrument(row[m_Columns.m_col_instr]);
756                instrumentProps.show();
757                instrumentProps.deiconify();
758            }
759      }      }
760  }  }
761    
762  void MainWindow::on_button_release(GdkEventButton* button)  void MainWindow::on_button_release(GdkEventButton* button)
763  {  {
764      if (button->type == GDK_2BUTTON_PRESS) {      if (button->type == GDK_2BUTTON_PRESS) {
765          Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();          show_instr_props();
766          Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      } else if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
767          if (it)          popup_menu->popup(button->button, button->time);
768          {      }
769    }
770    
771    void MainWindow::on_instrument_selection_change(int index) {
772        m_RegionChooser.set_instrument(file->GetInstrument(index));
773    }
774    
775    void MainWindow::on_sample_treeview_button_release(GdkEventButton* button) {
776        if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
777            Gtk::Menu* sample_popup =
778                dynamic_cast<Gtk::Menu*>(uiManager->get_widget("/SamplePopupMenu"));
779            // update enabled/disabled state of sample popup items
780            Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
781            Gtk::TreeModel::iterator it = sel->get_selected();
782            bool group_selected  = false;
783            bool sample_selected = false;
784            if (it) {
785              Gtk::TreeModel::Row row = *it;              Gtk::TreeModel::Row row = *it;
786              if (row[m_Columns.m_col_instr])              group_selected  = row[m_SamplesModel.m_col_group];
787              {              sample_selected = row[m_SamplesModel.m_col_sample];
788                  instrumentProps.set_instrument(row[m_Columns.m_col_instr]);          }
789                  instrumentProps.show();          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/SampleProperties"))->
790                  instrumentProps.deiconify();              set_sensitive(group_selected || sample_selected);
791            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddSample"))->
792                set_sensitive(group_selected || sample_selected);
793            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddGroup"))->
794                set_sensitive(file);
795            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/RemoveSample"))->
796                set_sensitive(group_selected || sample_selected);
797            // show sample popup
798            sample_popup->popup(button->button, button->time);
799        }
800    }
801    
802    void MainWindow::on_action_sample_properties() {
803         //TODO: show a dialog where the selected sample's properties can be edited
804    }
805    
806    void MainWindow::on_action_add_group() {
807        static int __sample_indexer = 0;
808        if (!file) return;
809        gig::Group* group = file->AddGroup();
810        group->Name = "Unnamed Group";
811        if (__sample_indexer) group->Name += " " + ToString(__sample_indexer);
812        __sample_indexer++;
813        // update sample tree view
814        Gtk::TreeModel::iterator iterGroup = m_refSamplesTreeModel->append();
815        Gtk::TreeModel::Row rowGroup = *iterGroup;
816        rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
817        rowGroup[m_SamplesModel.m_col_sample] = NULL;
818        rowGroup[m_SamplesModel.m_col_group] = group;
819    }
820    
821    void MainWindow::on_action_add_sample() {
822        if (!file) return;
823        // get selected group
824        Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
825        Gtk::TreeModel::iterator it = sel->get_selected();
826        if (!it) return;
827        Gtk::TreeModel::Row row = *it;
828        gig::Group* group = row[m_SamplesModel.m_col_group];
829        if (!group) { // not a group, but a sample is selected (probably)
830            gig::Sample* sample = row[m_SamplesModel.m_col_sample];
831            if (!sample) return;
832            it = row.parent(); // resolve parent (that is the sample's group)
833            if (!it) return;
834            row = *it;
835            group = row[m_SamplesModel.m_col_group];
836            if (!group) return;
837        }
838        // show 'browse for file' dialog
839        Gtk::FileChooserDialog dialog(*this, _("Add Sample(s)"));
840        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
841        dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
842        dialog.set_select_multiple(true);
843        Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
844        const char* supportedFileTypes[] = {
845            "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
846            "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
847            "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
848            "*.W64", "*.pvf", "*.PVF", "*.xi", "*.XI", "*.htk", "*.HTK",
849            "*.caf", "*.CAF", NULL
850        };
851        for (int i = 0; supportedFileTypes[i]; i++)
852            soundfilter.add_pattern(supportedFileTypes[i]);
853        soundfilter.set_name("Sound Files");
854        Gtk::FileFilter allpassfilter; // matches every file
855        allpassfilter.add_pattern("*.*");
856        allpassfilter.set_name("All Files");
857        dialog.add_filter(soundfilter);
858        dialog.add_filter(allpassfilter);
859        if (dialog.run() == Gtk::RESPONSE_OK) {
860            Glib::ustring error_files;
861            Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames();
862            for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin();
863                 iter != filenames.end(); ++iter) {
864                printf("Adding sample %s\n",(*iter).c_str());
865                // use libsndfile to retrieve file informations
866                SF_INFO info;
867                info.format = 0;
868                SNDFILE* hFile = sf_open((*iter).c_str(), SFM_READ, &info);
869                try {
870                    if (!hFile) throw std::string("could not open file");
871                    int bitdepth;
872                    switch (info.format & 0xff) {
873                        case SF_FORMAT_PCM_S8:
874                            bitdepth = 16; // we simply convert to 16 bit for now
875                            break;
876                        case SF_FORMAT_PCM_16:
877                            bitdepth = 16;
878                            break;
879                        case SF_FORMAT_PCM_24:
880                            bitdepth = 32; // we simply convert to 32 bit for now
881                            break;
882                        case SF_FORMAT_PCM_32:
883                            bitdepth = 32;
884                            break;
885                        case SF_FORMAT_PCM_U8:
886                            bitdepth = 16; // we simply convert to 16 bit for now
887                            break;
888                        case SF_FORMAT_FLOAT:
889                            bitdepth = 32;
890                            break;
891                        case SF_FORMAT_DOUBLE:
892                            bitdepth = 32; // I guess we will always truncate this to 32 bit
893                            break;
894                        default:
895                            sf_close(hFile); // close sound file
896                            throw std::string("format not supported"); // unsupported subformat (yet?)
897                    }
898                    // add a new sample to the .gig file
899                    gig::Sample* sample = file->AddSample();
900                    // file name without path
901                    sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();
902                    sample->Channels = info.channels;
903                    sample->BitDepth = bitdepth;
904                    sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
905                    sample->SamplesPerSecond = info.samplerate;
906                    // schedule resizing the sample (which will be done
907                    // physically when File::Save() is called)
908                    sample->Resize(info.frames);
909                    // make sure sample is part of the selected group
910                    group->AddSample(sample);
911                    // schedule that physical resize and sample import
912                    // (data copying), performed when "Save" is requested
913                    SampleImportItem sched_item;
914                    sched_item.gig_sample  = sample;
915                    sched_item.sample_path = *iter;
916                    m_SampleImportQueue.push_back(sched_item);
917                    // add sample to the tree view
918                    Gtk::TreeModel::iterator iterSample =
919                        m_refSamplesTreeModel->append(row.children());
920                    Gtk::TreeModel::Row rowSample = *iterSample;
921                    rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();
922                    rowSample[m_SamplesModel.m_col_sample] = sample;
923                    rowSample[m_SamplesModel.m_col_group]  = NULL;
924                    // close sound file
925                    sf_close(hFile);
926                } catch (std::string what) { // remember the files that made trouble (and their cause)
927                    if (error_files.size()) error_files += "\n";
928                    error_files += *iter += " (" + what + ")";
929              }              }
930          }          }
931      } else if (button->type == GDK_BUTTON_PRESS && button->button == 3) {          // show error message box when some file(s) could not be opened / added
932          popup_menu->popup(button->button, button->time);          if (error_files.size()) {
933                Glib::ustring txt = "Could not add the following sample(s):\n" + error_files;
934                Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
935                msg.run();
936            }
937        }
938    }
939    
940    void MainWindow::on_action_remove_sample() {
941        if (!file) return;
942        Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
943        Gtk::TreeModel::iterator it = sel->get_selected();
944        if (it) {
945            Gtk::TreeModel::Row row = *it;
946            gig::Group* group   = row[m_SamplesModel.m_col_group];
947            gig::Sample* sample = row[m_SamplesModel.m_col_sample];
948            Glib::ustring name  = row[m_SamplesModel.m_col_name];
949            try {
950                // remove group or sample from the gig file
951                if (group) {
952                    // temporarily remember the samples that bolong to
953                    // that group (we need that to clean the queue)
954                    std::list<gig::Sample*> members;
955                    for (gig::Sample* pSample = group->GetFirstSample();
956                         pSample; pSample = group->GetNextSample()) {
957                        members.push_back(pSample);
958                    }
959                    // delete the group in the .gig file including the
960                    // samples that belong to the group
961                    file->DeleteGroup(group);
962                    // if sample(s) were just previously added, remove
963                    // them from the import queue
964                    for (std::list<gig::Sample*>::iterator member = members.begin();
965                         member != members.end(); ++member) {
966                        for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
967                             iter != m_SampleImportQueue.end(); ++iter) {
968                            if ((*iter).gig_sample == *member) {
969                                printf("Removing previously added sample '%s' from group '%s'\n",
970                                       (*iter).sample_path.c_str(), name.c_str());
971                                m_SampleImportQueue.erase(iter);
972                                break;
973                            }
974                        }
975                    }
976                } else if (sample) {
977                    // remove sample from the .gig file
978                    file->DeleteSample(sample);
979                    // if sample was just previously added, remove it from
980                    // the import queue
981                    for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
982                         iter != m_SampleImportQueue.end(); ++iter) {
983                        if ((*iter).gig_sample == sample) {
984                            printf("Removing previously added sample '%s'\n",
985                                   (*iter).sample_path.c_str());
986                            m_SampleImportQueue.erase(iter);
987                            break;
988                        }
989                    }
990                }
991                // remove respective row(s) from samples tree view
992                m_refSamplesTreeModel->erase(it);
993            } catch (RIFF::Exception e) {
994                Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
995                msg.run();
996            }
997        }
998    }
999    
1000    void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&,
1001                                                      Gtk::SelectionData& selection_data, guint, guint)
1002    {
1003        // get selected sample
1004        gig::Sample* sample = NULL;
1005        Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
1006        Gtk::TreeModel::iterator it = sel->get_selected();
1007        if (it) {
1008            Gtk::TreeModel::Row row = *it;
1009            sample = row[m_SamplesModel.m_col_sample];
1010        }
1011        // pass the gig::Sample as pointer
1012        selection_data.set(selection_data.get_target(), 0/*unused*/, (const guchar*)&sample,
1013                           sizeof(sample)/*length of data in bytes*/);
1014    }
1015    
1016    void MainWindow::on_sample_label_drop_drag_data_received(
1017        const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1018        const Gtk::SelectionData& selection_data, guint, guint time)
1019    {
1020        gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();
1021        gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1022    
1023        if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {
1024            if (sample != dimregion->pSample) {
1025                dimregion->pSample = sample;
1026                dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());
1027                std::cout << "Drop received sample \"" <<
1028                    dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;
1029                // drop success
1030                context->drop_reply(true, time);
1031                return;
1032            }
1033      }      }
1034        // drop failed
1035        context->drop_reply(false, time);
1036    }
1037    
1038    void MainWindow::sample_name_changed(const Gtk::TreeModel::Path& path,
1039                                         const Gtk::TreeModel::iterator& iter) {
1040        if (!iter) return;
1041        Gtk::TreeModel::Row row = *iter;
1042        Glib::ustring name  = row[m_SamplesModel.m_col_name];
1043        gig::Group* group   = row[m_SamplesModel.m_col_group];
1044        gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1045        if (group) {
1046            group->Name = name;
1047            std::cout << "Group name changed\n" << std::flush;
1048        } else if (sample) {
1049            sample->pInfo->Name = name.raw();
1050            std::cout << "Sample name changed\n" << std::flush;
1051        }
1052    }
1053    
1054    void MainWindow::instrument_name_changed(const Gtk::TreeModel::Path& path,
1055                                             const Gtk::TreeModel::iterator& iter) {
1056        std::cout << "Instrument name changed\n" << std::flush;
1057        if (!iter) return;
1058        Gtk::TreeModel::Row row = *iter;
1059        Glib::ustring name = row[m_Columns.m_col_name];
1060        gig::Instrument* instrument = row[m_Columns.m_col_instr];
1061        if (instrument) instrument->pInfo->Name = name.raw();
1062  }  }

Legend:
Removed from v.1052  
changed lines
  Added in v.1100

  ViewVC Help
Powered by ViewVC