/[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

revision 1097 by schoenebeck, Wed Mar 14 23:19:26 2007 UTC revision 1213 by schoenebeck, Wed May 30 00:14:05 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    #include <gtkmm/main.h>
28    
29  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6
30  #define ABOUT_DIALOG  #define ABOUT_DIALOG
31  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
 #include <gtkmm/messagedialog.h>  
 #include <gtkmm/targetentry.h>  
32  #endif  #endif
33    
34  #include <stdio.h>  #include <stdio.h>
35  #include <sndfile.h>  #include <sndfile.h>
36    
37    #include "mainwindow.h"
38    
39  #define _(String) gettext(String)  #define _(String) gettext(String)
40    
41  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
# Line 42  template<class T> inline std::string ToS Line 44  template<class T> inline std::string ToS
44      return ss.str();      return ss.str();
45  }  }
46    
47  bool update_gui;  MainWindow::MainWindow()
   
 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;  
 }  
   
 ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(  
     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;  
 }  
   
 void MainWindow::addHeader(char* text)  
 {  
     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;  
 }  
   
 void MainWindow::nextPage()  
 {  
     if (firstRowInBlock < rowno - 1)  
     {  
         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++;  
 }  
   
   
   
   
 MainWindow::MainWindow() :  
 //    eSample("Sample", wSample),  
     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)  
48  {  {
49  //    set_border_width(5);  //    set_border_width(5);
50  //    set_default_size(400, 200);  //    set_default_size(400, 200);
# Line 527  MainWindow::MainWindow() : Line 55  MainWindow::MainWindow() :
55      // Handle selection      // Handle selection
56      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
57      tree_sel_ref->signal_changed().connect(      tree_sel_ref->signal_changed().connect(
58          sigc::mem_fun(*this, &MainWindow::on_sel_change));          sigc::mem_fun(*this, &MainWindow::on_sel_change));
59    
60        // m_TreeView.set_reorderable();
61    
62      m_TreeView.signal_button_press_event().connect_notify(      m_TreeView.signal_button_press_event().connect_notify(
63          sigc::mem_fun(*this, &MainWindow::on_button_release));          sigc::mem_fun(*this, &MainWindow::on_button_release));
# Line 541  MainWindow::MainWindow() : Line 71  MainWindow::MainWindow() :
71      m_ScrolledWindowSamples.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);      m_ScrolledWindowSamples.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
72    
73    
     for (int i = 0 ; i < 5 ; i++) {  
         table[i] = new Gtk::Table(3, 1);  
         table[i]->set_col_spacings(5);  
     }  
   
     pageno = 0;  
     rowno = 0;  
     firstRowInBlock = 0;  
   
     addString("Sample", lSample, wSample);  
     //TODO: the following would break drag&drop:   wSample->property_editable().set_value(false);  or this:    wSample->set_editable(false);  
     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);  
   
74      m_TreeViewNotebook.set_size_request(300);      m_TreeViewNotebook.set_size_request(300);
75    
76      m_HPaned.add1(m_TreeViewNotebook);      m_HPaned.add1(m_TreeViewNotebook);
77      m_HPaned.add2(m_Notebook);      m_HPaned.add2(dimreg_edit);
78    
79    
80      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");
# Line 830  MainWindow::MainWindow() : Line 110  MainWindow::MainWindow() :
110      actionGroup->add(Gtk::Action::create("InstrProperties",      actionGroup->add(Gtk::Action::create("InstrProperties",
111                                           Gtk::Stock::PROPERTIES),                                           Gtk::Stock::PROPERTIES),
112                       sigc::mem_fun(                       sigc::mem_fun(
113                           *this, &MainWindow::on_action_file_properties));                           *this, &MainWindow::show_instr_props));
114      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
115                       sigc::mem_fun(                       sigc::mem_fun(
116                           *this, &MainWindow::hide));                           *this, &MainWindow::hide));
# Line 844  MainWindow::MainWindow() : Line 124  MainWindow::MainWindow() :
124                       sigc::mem_fun(                       sigc::mem_fun(
125                           *this, &MainWindow::on_action_help_about));                           *this, &MainWindow::on_action_help_about));
126  #endif  #endif
127      action = Gtk::Action::create("Remove", Gtk::Stock::REMOVE);      actionGroup->add(
128      actionGroup->add(action,          Gtk::Action::create("AddInstrument", _("Add _Instrument")),
129                       sigc::mem_fun(          sigc::mem_fun(*this, &MainWindow::on_action_add_instrument)
130                           *this, &MainWindow::hide));      );
131        actionGroup->add(
132            Gtk::Action::create("RemoveInstrument", Gtk::Stock::REMOVE),
133            sigc::mem_fun(*this, &MainWindow::on_action_remove_instrument)
134        );
135    
136      // sample right-click popup actions      // sample right-click popup actions
137      actionGroup->add(      actionGroup->add(
# Line 895  MainWindow::MainWindow() : Line 179  MainWindow::MainWindow() :
179          "  </menubar>"          "  </menubar>"
180          "  <popup name='PopupMenu'>"          "  <popup name='PopupMenu'>"
181          "    <menuitem action='InstrProperties'/>"          "    <menuitem action='InstrProperties'/>"
182          "    <menuitem action='Remove'/>"          "    <menuitem action='AddInstrument'/>"
183            "    <separator/>"
184            "    <menuitem action='RemoveInstrument'/>"
185          "  </popup>"          "  </popup>"
186          "  <popup name='SamplePopupMenu'>"          "  <popup name='SamplePopupMenu'>"
187          "    <menuitem action='SampleProperties'/>"          "    <menuitem action='SampleProperties'/>"
# Line 916  MainWindow::MainWindow() : Line 202  MainWindow::MainWindow() :
202      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
203    
204      m_RegionChooser.signal_sel_changed().connect(      m_RegionChooser.signal_sel_changed().connect(
205          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
206      m_DimRegionChooser.signal_sel_changed().connect(      m_DimRegionChooser.signal_sel_changed().connect(
207          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );
208    
209    
210      // Create the Tree model:      // Create the Tree model:
# Line 935  MainWindow::MainWindow() : Line 221  MainWindow::MainWindow() :
221      // create samples treeview (including its data model)      // create samples treeview (including its data model)
222      m_refSamplesTreeModel = SamplesTreeStore::create(m_SamplesModel);      m_refSamplesTreeModel = SamplesTreeStore::create(m_SamplesModel);
223      m_TreeViewSamples.set_model(m_refSamplesTreeModel);      m_TreeViewSamples.set_model(m_refSamplesTreeModel);
224        // m_TreeViewSamples.set_reorderable();
225      m_TreeViewSamples.append_column_editable("Samples", m_SamplesModel.m_col_name);      m_TreeViewSamples.append_column_editable("Samples", m_SamplesModel.m_col_name);
226      m_TreeViewSamples.set_headers_visible(false);      m_TreeViewSamples.set_headers_visible(false);
227      m_TreeViewSamples.signal_button_press_event().connect_notify(      m_TreeViewSamples.signal_button_press_event().connect_notify(
# Line 947  MainWindow::MainWindow() : Line 234  MainWindow::MainWindow() :
234      // establish drag&drop between samples tree view and dimension region 'Sample' text entry      // establish drag&drop between samples tree view and dimension region 'Sample' text entry
235      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
236      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
 //drag_target_gig_sample.push_back( Gtk::TargetEntry("STRING") );  
 //drag_target_gig_sample.push_back( Gtk::TargetEntry("text/plain") );  
237      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
238      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
239          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
240      );      );
241      wSample->drag_dest_set(drag_target_gig_sample);      dimreg_edit.wSample->drag_dest_set(drag_target_gig_sample);
242      wSample->signal_drag_data_received().connect(      dimreg_edit.wSample->signal_drag_data_received().connect(
243          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
244      );      );
245    
# Line 974  void MainWindow::region_changed() Line 259  void MainWindow::region_changed()
259    
260  void MainWindow::dimreg_changed()  void MainWindow::dimreg_changed()
261  {  {
262      set_dim_region(m_DimRegionChooser.get_dimregion());      dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());
263  }  }
264    
265  void MainWindow::on_sel_change()  void MainWindow::on_sel_change()
# Line 982  void MainWindow::on_sel_change() Line 267  void MainWindow::on_sel_change()
267      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
268    
269      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
270      if (it)      if (it) {
271      {          Gtk::TreeModel::Row row = *it;
272          Gtk::TreeModel::Row row = *it;          std::cout << row[m_Columns.m_col_name] << std::endl;
         std::cout << row[m_Columns.m_col_name] << std::endl;  
   
         if (row[m_Columns.m_col_instr])  
             m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]);  
     }  
 }  
   
 void MainWindow::set_dim_region(gig::DimensionRegion* d)  
 {  
     update_gui = false;  
     wSample->set_text(d->pSample ? d->pSample->pInfo->Name.c_str() : "NULL");  
     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;  
 }  
273    
274  void MainWindow::VCFEnabled_toggled()          m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]);
 {  
     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();  
275      } else {      } else {
276          eVCFCutoffControllerInvert.set_sensitive(false);          m_RegionChooser.set_instrument(0);
         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);  
277      }      }
278  }  }
279    
 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);  
 }  
   
280  void loader_progress_callback(gig::progress_t* progress)  void loader_progress_callback(gig::progress_t* progress)
281  {  {
282      Loader* loader = static_cast<Loader*>(progress->custom);      Loader* loader = static_cast<Loader*>(progress->custom);
# Line 1295  Glib::Dispatcher& Loader::signal_finishe Line 338  Glib::Dispatcher& Loader::signal_finishe
338      return finished_dispatcher;      return finished_dispatcher;
339  }  }
340    
341  LoadDialog::LoadDialog()  LoadDialog::LoadDialog(const Glib::ustring& title, Gtk::Window& parent)
342        : Gtk::Dialog(title, parent, true)
343  {  {
344      get_vbox()->pack_start(progressBar);      get_vbox()->pack_start(progressBar);
345      show_all_children();      show_all_children();
346  }  }
347    
348    // Clear all GUI elements / controls. This method is typically called
349    // before a new .gig file is to be created or to be loaded.
350    void MainWindow::__clear() {
351        // remove all entries from "Instrument" menu
352        Gtk::MenuItem* instrument_menu =
353            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));
354        instrument_menu->hide();
355        for (int i = 0; i < instrument_menu->get_submenu()->items().size(); i++) {
356            delete &instrument_menu->get_submenu()->items()[i];
357        }
358        instrument_menu->get_submenu()->items().clear();
359        // forget all samples that ought to be imported
360        m_SampleImportQueue.clear();
361        // clear the samples and instruments tree views
362        m_refTreeModel->clear();
363        m_refSamplesTreeModel->clear();
364        // free libgig's gig::File instance
365        if (file) {
366            delete file;
367            file = NULL;
368        }
369    }
370    
371  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
372  {  {
373      m_SampleImportQueue.clear();      // clear all GUI elements
374        __clear();
375        // create a new .gig file (virtually yet)
376        gig::File* pFile = new gig::File;
377        // already add one new instrument by default
378        gig::Instrument* pInstrument = pFile->AddInstrument();
379        pInstrument->pInfo->Name = "Unnamed Instrument";
380        // update GUI with that new gig::File
381        load_gig(pFile, NULL /*no file name yet*/);
382  }  }
383    
384  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
# Line 1316  void MainWindow::on_action_file_open() Line 391  void MainWindow::on_action_file_open()
391      dialog.set_filter(filter);      dialog.set_filter(filter);
392      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
393          printf("filename=%s\n", dialog.get_filename().c_str());          printf("filename=%s\n", dialog.get_filename().c_str());
394            __clear();
         // remove all entries from "Instrument" menu  
         Gtk::MenuItem* instrument_menu =  
             dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/MenuBar/MenuInstrument"));  
         instrument_menu->hide();  
         for (int i = 0; i < instrument_menu->get_submenu()->items().size(); i++) {  
             delete &instrument_menu->get_submenu()->items()[i];  
         }  
         instrument_menu->get_submenu()->items().clear();  
   
         m_SampleImportQueue.clear();  
         m_refTreeModel->clear();  
         m_refSamplesTreeModel->clear();  
         if (file) delete file;  
   
         // getInfo(dialog.get_filename().c_str(), *this);  
   
395          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
396          load_dialog = new LoadDialog(); // Gtk::Dialog("Loading...", *this, true);          load_file(dialog.get_filename().c_str());
397          load_dialog->show_all();      }
398          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));  
399    
400          loader->launch();  void MainWindow::load_file(const char* name)
401    {
402        load_dialog = new LoadDialog("Loading...", *this);
403        load_dialog->show_all();
404        loader = new Loader(strdup(name));
405        loader->signal_progress().connect(
406            sigc::mem_fun(*this, &MainWindow::on_loader_progress));
407        loader->signal_finished().connect(
408            sigc::mem_fun(*this, &MainWindow::on_loader_finished));
409        loader->launch();
410    }
411    
412    void MainWindow::load_instrument(gig::Instrument* instr) {
413        if (!instr) {
414            Glib::ustring txt = "Provided instrument is NULL!\n";
415            Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
416            msg.run();
417            Gtk::Main::quit();
418      }      }
419        gig::File* pFile = (gig::File*) instr->GetParent();
420        load_gig(pFile, NULL /*file name*/);
421        //TODO: automatically select the given instrument
422  }  }
423    
424  void MainWindow::on_loader_progress()  void MainWindow::on_loader_progress()
# Line 1356  void MainWindow::on_loader_finished() Line 431  void MainWindow::on_loader_finished()
431      printf("Loader finished!\n");      printf("Loader finished!\n");
432      printf("on_loader_finished self=%x\n", Glib::Thread::self());      printf("on_loader_finished self=%x\n", Glib::Thread::self());
433      load_gig(loader->gig, loader->filename);      load_gig(loader->gig, loader->filename);
   
   
     Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();  
     tree_sel_ref->select(Gtk::TreePath("0"));  
   
434      load_dialog->hide();      load_dialog->hide();
435  }  }
436    
# Line 1408  void MainWindow::__import_queued_samples Line 478  void MainWindow::__import_queued_samples
478      std::cout << "Starting sample import\n" << std::flush;      std::cout << "Starting sample import\n" << std::flush;
479      Glib::ustring error_files;      Glib::ustring error_files;
480      printf("Samples to import: %d\n", m_SampleImportQueue.size());      printf("Samples to import: %d\n", m_SampleImportQueue.size());
481      for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ) {      for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
482             iter != m_SampleImportQueue.end(); ) {
483          printf("Importing sample %s\n",(*iter).sample_path.c_str());          printf("Importing sample %s\n",(*iter).sample_path.c_str());
484          SF_INFO info;          SF_INFO info;
485          info.format = 0;          info.format = 0;
# Line 1443  void MainWindow::__import_queued_samples Line 514  void MainWindow::__import_queued_samples
514                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
515                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
516              }              }
517              // allocate appropriate copy buffer (TODO: for now we copy it in one piece, might be tough for very long samples)              // allocate appropriate copy buffer (TODO: for now we copy
518                // it in one piece, might be tough for very long samples)
519              // and copy sample data into buffer              // and copy sample data into buffer
520              int8_t* buffer = NULL;              int8_t* buffer = NULL;
521              switch (bitdepth) {              switch (bitdepth) {
522                  case 16:                  case 16:
523                      buffer = new int8_t[2 * info.channels * info.frames];                      buffer = new int8_t[2 * info.channels * info.frames];
524                      sf_readf_short(hFile, (short*) buffer, info.frames); // libsndfile does the conversion for us (if needed)                      // libsndfile does the conversion for us (if needed)
525                        sf_readf_short(hFile, (short*) buffer, info.frames);
526                      break;                      break;
527                  case 32:                  case 32:
528                      buffer = new int8_t[4 * info.channels * info.frames];                      buffer = new int8_t[4 * info.channels * info.frames];
529                      sf_readf_int(hFile, (int*) buffer, info.frames); // libsndfile does the conversion for us (if needed)                      // libsndfile does the conversion for us (if needed)
530                        sf_readf_int(hFile, (int*) buffer, info.frames);
531                      break;                      break;
532              }              }
533              // write from buffer directly (physically) into .gig file              // write from buffer directly (physically) into .gig file
534              (*iter).gig_sample->Write(buffer, info.frames);              (*iter).gig_sample->Write(buffer, info.frames);
535              // cleanup              // cleanup
536              sf_close(hFile);              sf_close(hFile);
537              delete buffer;              delete[] buffer;
538              // on success we remove the sample from the import queue, otherwise keep it, maybe it works the next time ?              // on success we remove the sample from the import queue,
539                // otherwise keep it, maybe it works the next time ?
540              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
541              ++iter;              ++iter;
542              m_SampleImportQueue.erase(cur);              m_SampleImportQueue.erase(cur);
543          } catch (std::string what) { // remember the files that made trouble (and their cause)          } catch (std::string what) {
544                // remember the files that made trouble (and their cause)
545              if (error_files.size()) error_files += "\n";              if (error_files.size()) error_files += "\n";
546              error_files += (*iter).sample_path += " (" + what + ")";              error_files += (*iter).sample_path += " (" + what + ")";
547              ++iter;              ++iter;
# Line 1550  void PropDialog::set_info(DLS::Info* inf Line 626  void PropDialog::set_info(DLS::Info* inf
626      entry[15].set_text(info->Subject);      entry[15].set_text(info->Subject);
627  }  }
628    
629    void InstrumentProps::add_prop(LabelWidget& prop)
630    {
631        table.attach(prop.label, 0, 1, rowno, rowno + 1,
632                     Gtk::FILL, Gtk::SHRINK);
633        table.attach(prop.widget, 1, 2, rowno, rowno + 1,
634                     Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
635        rowno++;
636    }
637    
638  InstrumentProps::InstrumentProps()  InstrumentProps::InstrumentProps()
639      : table(2,1),      : table(2,1),
640        quitButton(Gtk::Stock::CLOSE)        quitButton(Gtk::Stock::CLOSE),
641          eName("Name"),
642          eIsDrum("IsDrum"),
643          eMIDIBank("MIDIBank", 0, 16383),
644          eMIDIProgram("MIDIProgram"),
645          eAttenuation("Attenuation", 0, 96, 0, 1),
646          eGainPlus6("Gain +6dB", eAttenuation, -6),
647          eEffectSend("EffectSend", 0, 65535),
648          eFineTune("FineTune", -8400, 8400),
649          ePitchbendRange("PitchbendRange", 0, 12),
650          ePianoReleaseMode("PianoReleaseMode"),
651          eDimensionKeyRangeLow("DimensionKeyRangeLow"),
652          eDimensionKeyRangeHigh("DimensionKeyRangeHigh")
653  {  {
654        set_title("Instrument properties");
655    
656        rowno = 0;
657      table.set_col_spacings(5);      table.set_col_spacings(5);
     char* propLabels[] = {  
         "Name:",  
         "IsDrum:",  
         "MIDIBank:",  
         "MIDIProgram:",  
         "Attenuation:",  
         "EffectSend:",  
         "FineTune:",  
         "PitchbendRange:",  
         "PianoReleaseMode:",  
         "DimensionKeyRange:",  
     };  
     int entryIdx = 0, checkIdx = 0;  
     for (int i = 0 ; i < sizeof(propLabels) / sizeof(char*) ; i++) {  
         label[i].set_text(propLabels[i]);  
         label[i].set_alignment(Gtk::ALIGN_LEFT);  
         table.attach(label[i], 0, 1, i, i + 1, Gtk::FILL, Gtk::SHRINK);  
         if (i == 1 || i == 8)  
             table.attach(check[checkIdx++], 1, 2, i, i + 1,  
                          Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);  
         else  
             table.attach(entry[entryIdx++], 1, 2, i, i + 1,  
                          Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);  
     }  
658    
659      // vbox { table buttonBox { quitButton } }      add_prop(eName);
660        add_prop(eIsDrum);
661        add_prop(eMIDIBank);
662        add_prop(eMIDIProgram);
663        add_prop(eAttenuation);
664        add_prop(eGainPlus6);
665        add_prop(eEffectSend);
666        add_prop(eFineTune);
667        add_prop(ePitchbendRange);
668        add_prop(ePianoReleaseMode);
669        add_prop(eDimensionKeyRangeLow);
670        add_prop(eDimensionKeyRangeHigh);
671    
672        eDimensionKeyRangeLow.signal_value_changed().connect(
673            sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));
674        eDimensionKeyRangeHigh.signal_value_changed().connect(
675            sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));
676    
     //get_vbox()->pack_start(table);  
     // set_border_width(6);  
677      add(vbox);      add(vbox);
678      table.set_border_width(2);      table.set_border_width(5);
679      vbox.pack_start(table);      vbox.pack_start(table);
680      table.show();      table.show();
681      vbox.pack_start(buttonBox);      vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
682      buttonBox.set_layout(Gtk::BUTTONBOX_END);      buttonBox.set_layout(Gtk::BUTTONBOX_END);
683      buttonBox.set_border_width(5);      buttonBox.set_border_width(5);
684      buttonBox.show();      buttonBox.show();
# Line 1598  InstrumentProps::InstrumentProps() Line 687  InstrumentProps::InstrumentProps()
687      quitButton.grab_focus();      quitButton.grab_focus();
688    
689      quitButton.signal_clicked().connect(      quitButton.signal_clicked().connect(
690          sigc::mem_fun(*this, &InstrumentProps::hide));          sigc::mem_fun(*this, &InstrumentProps::hide));
691    
     // quitButton.grab_default();  
692      quitButton.show();      quitButton.show();
     // add(table);  
693      vbox.show();      vbox.show();
694      show_all_children();      show_all_children();
695  }  }
696    
   
697  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
698  {  {
699      char buf[100];      update_gui = false;
700        eName.set_ptr(&instrument->pInfo->Name);
701      int entryIdx = 0, checkIdx = 0;      eIsDrum.set_ptr(&instrument->IsDrum);
702      entry[entryIdx++].set_text(instrument->pInfo->Name);      eMIDIBank.set_ptr(&instrument->MIDIBank);
703      check[checkIdx++].set_active(instrument->IsDrum);      eMIDIProgram.set_ptr(&instrument->MIDIProgram);
704      sprintf(buf, "%d", instrument->MIDIBank);      eAttenuation.set_ptr(&instrument->Attenuation);
705      entry[entryIdx++].set_text(buf);      eGainPlus6.set_ptr(&instrument->Attenuation);
706      sprintf(buf, "%d", instrument->MIDIProgram);      eEffectSend.set_ptr(&instrument->EffectSend);
707      entry[entryIdx++].set_text(buf);      eFineTune.set_ptr(&instrument->FineTune);
708      sprintf(buf, "%d", instrument->Attenuation);      ePitchbendRange.set_ptr(&instrument->PitchbendRange);
709      entry[entryIdx++].set_text(buf);      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);
710      sprintf(buf, "%d", instrument->EffectSend);      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);
711      entry[entryIdx++].set_text(buf);      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);
712      sprintf(buf, "%d", instrument->FineTune);      update_gui = true;
     entry[entryIdx++].set_text(buf);  
     sprintf(buf, "%d", instrument->PitchbendRange);  
     entry[entryIdx++].set_text(buf);  
     check[checkIdx++].set_active(instrument->PianoReleaseMode);  
     sprintf(buf, "%s%d (%d)..%s%d (%d)",  
             notes[instrument->DimensionKeyRange.low % 12],  
             instrument->DimensionKeyRange.low / 12 - 1,  
             instrument->DimensionKeyRange.low,  
             notes[instrument->DimensionKeyRange.high % 12],  
             instrument->DimensionKeyRange.high / 12 - 1,  
             instrument->DimensionKeyRange.high);  
     entry[entryIdx].set_text(buf);  
713  }  }
714    
715  void MainWindow::getInfo(const char *filename)  void InstrumentProps::key_range_low_changed()
716  {  {
717      RIFF::File* riff = new RIFF::File(filename);      double l = eDimensionKeyRangeLow.get_value();
718      gig::File* gig = new gig::File(riff);      double h = eDimensionKeyRangeHigh.get_value();
719        if (h < l) eDimensionKeyRangeHigh.set_value(l);
720    }
721    
722      load_gig(gig, filename);  void InstrumentProps::key_range_high_changed()
723    {
724        double l = eDimensionKeyRangeLow.get_value();
725        double h = eDimensionKeyRangeHigh.get_value();
726        if (h < l) eDimensionKeyRangeLow.set_value(h);
727  }  }
728    
729  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename)
730  {  {
731      file = gig;      file = gig;
732    
733      const char *basename = strrchr(filename, '/');      if (filename) {
734      basename = basename ? basename + 1 : filename;          const char *basename = strrchr(filename, '/');
735            basename = basename ? basename + 1 : filename;
736      set_title(basename);          set_title(basename);
737        } else {
738            set_title("unnamed");
739        }
740    
741      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
742    
# Line 1663  void MainWindow::load_gig(gig::File* gig Line 746  void MainWindow::load_gig(gig::File* gig
746      int instrument_index = 0;      int instrument_index = 0;
747      Gtk::RadioMenuItem::Group instrument_group;      Gtk::RadioMenuItem::Group instrument_group;
748      for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ;      for (gig::Instrument* instrument = gig->GetFirstInstrument() ; instrument ;
749           instrument = gig->GetNextInstrument()) {           instrument = gig->GetNextInstrument()) {
750          Gtk::TreeModel::iterator iter = m_refTreeModel->append();          Gtk::TreeModel::iterator iter = m_refTreeModel->append();
751          Gtk::TreeModel::Row row = *iter;          Gtk::TreeModel::Row row = *iter;
752          row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();          row[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
753          row[m_Columns.m_col_instr] = instrument;          row[m_Columns.m_col_instr] = instrument;
754          // create a menu item for this instrument          // create a menu item for this instrument
755          Gtk::RadioMenuItem* item= new Gtk::RadioMenuItem(instrument_group, instrument->pInfo->Name.c_str());          Gtk::RadioMenuItem* item =
756                new Gtk::RadioMenuItem(instrument_group, instrument->pInfo->Name.c_str());
757          instrument_menu->get_submenu()->append(*item);          instrument_menu->get_submenu()->append(*item);
758          item->signal_activate().connect(          item->signal_activate().connect(
759              sigc::bind(              sigc::bind(
# Line 1689  void MainWindow::load_gig(gig::File* gig Line 773  void MainWindow::load_gig(gig::File* gig
773              rowGroup[m_SamplesModel.m_col_name]   = group->Name.c_str();              rowGroup[m_SamplesModel.m_col_name]   = group->Name.c_str();
774              rowGroup[m_SamplesModel.m_col_group]  = group;              rowGroup[m_SamplesModel.m_col_group]  = group;
775              rowGroup[m_SamplesModel.m_col_sample] = NULL;              rowGroup[m_SamplesModel.m_col_sample] = NULL;
776              for (gig::Sample* sample = group->GetFirstSample(); sample; sample = group->GetNextSample()) {              for (gig::Sample* sample = group->GetFirstSample();
777                  Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(rowGroup.children());                   sample; sample = group->GetNextSample()) {
778                    Gtk::TreeModel::iterator iterSample =
779                        m_refSamplesTreeModel->append(rowGroup.children());
780                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
781                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();
782                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
# Line 1698  void MainWindow::load_gig(gig::File* gig Line 784  void MainWindow::load_gig(gig::File* gig
784              }              }
785          }          }
786      }      }
787    
788        // select the first instrument
789        Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
790        tree_sel_ref->select(Gtk::TreePath("0"));
791  }  }
792    
793  void MainWindow::on_button_release(GdkEventButton* button)  void MainWindow::show_instr_props()
794  {  {
795      if (button->type == GDK_2BUTTON_PRESS) {      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
796          Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
797          Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      if (it)
798          if (it)      {
799            Gtk::TreeModel::Row row = *it;
800            if (row[m_Columns.m_col_instr])
801          {          {
802              Gtk::TreeModel::Row row = *it;              instrumentProps.set_instrument(row[m_Columns.m_col_instr]);
803              if (row[m_Columns.m_col_instr])              instrumentProps.show();
804              {              instrumentProps.deiconify();
                 instrumentProps.set_instrument(row[m_Columns.m_col_instr]);  
                 instrumentProps.show();  
                 instrumentProps.deiconify();  
             }  
805          }          }
806        }
807    }
808    
809    void MainWindow::on_button_release(GdkEventButton* button)
810    {
811        if (button->type == GDK_2BUTTON_PRESS) {
812            show_instr_props();
813      } else if (button->type == GDK_BUTTON_PRESS && button->button == 3) {      } else if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
814          popup_menu->popup(button->button, button->time);          popup_menu->popup(button->button, button->time);
815      }      }
# Line 1738  void MainWindow::on_sample_treeview_butt Line 833  void MainWindow::on_sample_treeview_butt
833              group_selected  = row[m_SamplesModel.m_col_group];              group_selected  = row[m_SamplesModel.m_col_group];
834              sample_selected = row[m_SamplesModel.m_col_sample];              sample_selected = row[m_SamplesModel.m_col_sample];
835          }          }
836          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/SampleProperties"))->set_sensitive(group_selected || sample_selected);          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/SampleProperties"))->
837          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddSample"))->set_sensitive(group_selected || sample_selected);              set_sensitive(group_selected || sample_selected);
838          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddGroup"))->set_sensitive(file);          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddSample"))->
839          dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/RemoveSample"))->set_sensitive(group_selected || sample_selected);              set_sensitive(group_selected || sample_selected);
840            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/AddGroup"))->
841                set_sensitive(file);
842            dynamic_cast<Gtk::MenuItem*>(uiManager->get_widget("/SamplePopupMenu/RemoveSample"))->
843                set_sensitive(group_selected || sample_selected);
844          // show sample popup          // show sample popup
845          sample_popup->popup(button->button, button->time);          sample_popup->popup(button->button, button->time);
846      }      }
847  }  }
848    
849    void MainWindow::on_action_add_instrument() {
850        static int __instrument_indexer = 0;
851        if (!file) return;
852        gig::Instrument* instrument = file->AddInstrument();
853        __instrument_indexer++;
854        instrument->pInfo->Name =
855            "Unnamed Instrument " + ToString(__instrument_indexer);
856        // update instrument tree view
857        Gtk::TreeModel::iterator iterInstr = m_refTreeModel->append();
858        Gtk::TreeModel::Row rowInstr = *iterInstr;
859        rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
860        rowInstr[m_Columns.m_col_instr] = instrument;
861    }
862    
863    void MainWindow::on_action_remove_instrument() {
864        if (!file) return;
865        Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
866        Gtk::TreeModel::iterator it = sel->get_selected();
867        if (it) {
868            Gtk::TreeModel::Row row = *it;
869            gig::Instrument* instr = row[m_Columns.m_col_instr];
870            try {
871                // remove instrument from the gig file
872                if (instr) file->DeleteInstrument(instr);
873                // remove respective row from instruments tree view
874                m_refTreeModel->erase(it);
875            } catch (RIFF::Exception e) {
876                Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
877                msg.run();
878            }
879        }
880    }
881    
882  void MainWindow::on_action_sample_properties() {  void MainWindow::on_action_sample_properties() {
883       //TODO: show a dialog where the selected sample's properties can be edited      //TODO: show a dialog where the selected sample's properties can be edited
884        Gtk::MessageDialog msg(
885            *this, "Sorry, yet to be implemented!", false, Gtk::MESSAGE_INFO
886        );
887        msg.run();
888  }  }
889    
890  void MainWindow::on_action_add_group() {  void MainWindow::on_action_add_group() {
# Line 1807  void MainWindow::on_action_add_sample() Line 943  void MainWindow::on_action_add_sample()
943      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
944          Glib::ustring error_files;          Glib::ustring error_files;
945          Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames();          Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames();
946          for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin(); iter != filenames.end(); ++iter) {          for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin();
947                 iter != filenames.end(); ++iter) {
948              printf("Adding sample %s\n",(*iter).c_str());              printf("Adding sample %s\n",(*iter).c_str());
949              // use libsndfile to retrieve file informations              // use libsndfile to retrieve file informations
950              SF_INFO info;              SF_INFO info;
# Line 1844  void MainWindow::on_action_add_sample() Line 981  void MainWindow::on_action_add_sample()
981                  }                  }
982                  // add a new sample to the .gig file                  // add a new sample to the .gig file
983                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
984                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw(); // file name without path                  // file name without path
985                    sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();
986                  sample->Channels = info.channels;                  sample->Channels = info.channels;
987                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
988                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
989                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
990                  // schedule resizing the sample (which will be done physically when File::Save() is called)                  // schedule resizing the sample (which will be done
991                    // physically when File::Save() is called)
992                  sample->Resize(info.frames);                  sample->Resize(info.frames);
993                  // make sure sample is part of the selected group                  // make sure sample is part of the selected group
994                  group->AddSample(sample);                  group->AddSample(sample);
995                  // schedule that physical resize and sample import (data copying), performed when "Save" is requested                  // schedule that physical resize and sample import
996                    // (data copying), performed when "Save" is requested
997                  SampleImportItem sched_item;                  SampleImportItem sched_item;
998                  sched_item.gig_sample  = sample;                  sched_item.gig_sample  = sample;
999                  sched_item.sample_path = *iter;                  sched_item.sample_path = *iter;
1000                  m_SampleImportQueue.push_back(sched_item);                  m_SampleImportQueue.push_back(sched_item);
1001                  // add sample to the tree view                  // add sample to the tree view
1002                  Gtk::TreeModel::iterator iterSample = m_refSamplesTreeModel->append(row.children());                  Gtk::TreeModel::iterator iterSample =
1003                        m_refSamplesTreeModel->append(row.children());
1004                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1005                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();
1006                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
# Line 1892  void MainWindow::on_action_remove_sample Line 1033  void MainWindow::on_action_remove_sample
1033          try {          try {
1034              // remove group or sample from the gig file              // remove group or sample from the gig file
1035              if (group) {              if (group) {
1036                  // temporarily remember the samples that bolong to that group (we need that to clean the queue)                  // temporarily remember the samples that bolong to
1037                    // that group (we need that to clean the queue)
1038                  std::list<gig::Sample*> members;                  std::list<gig::Sample*> members;
1039                  for (gig::Sample* pSample = group->GetFirstSample(); pSample; pSample = group->GetNextSample()) {                  for (gig::Sample* pSample = group->GetFirstSample();
1040                         pSample; pSample = group->GetNextSample()) {
1041                      members.push_back(pSample);                      members.push_back(pSample);
1042                  }                  }
1043                  // delete the group in the .gig file including the samples that belong to the group                  // delete the group in the .gig file including the
1044                    // samples that belong to the group
1045                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1046                  // if sample(s) were just previously added, remove them from the import queue                  // if sample(s) were just previously added, remove
1047                  for (std::list<gig::Sample*>::iterator member = members.begin(); member != members.end(); ++member) {                  // them from the import queue
1048                      for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ++iter) {                  for (std::list<gig::Sample*>::iterator member = members.begin();
1049                         member != members.end(); ++member) {
1050                        for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
1051                             iter != m_SampleImportQueue.end(); ++iter) {
1052                          if ((*iter).gig_sample == *member) {                          if ((*iter).gig_sample == *member) {
1053                              printf("Removing previously added sample '%s' from group '%s'\n", (*iter).sample_path.c_str(), name.c_str());                              printf("Removing previously added sample '%s' from group '%s'\n",
1054                                       (*iter).sample_path.c_str(), name.c_str());
1055                              m_SampleImportQueue.erase(iter);                              m_SampleImportQueue.erase(iter);
1056                              break;                              break;
1057                          }                          }
# Line 1912  void MainWindow::on_action_remove_sample Line 1060  void MainWindow::on_action_remove_sample
1060              } else if (sample) {              } else if (sample) {
1061                  // remove sample from the .gig file                  // remove sample from the .gig file
1062                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1063                  // if sample was just previously added, remove it from the import queue                  // if sample was just previously added, remove it from
1064                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin(); iter != m_SampleImportQueue.end(); ++iter) {                  // the import queue
1065                    for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
1066                         iter != m_SampleImportQueue.end(); ++iter) {
1067                      if ((*iter).gig_sample == sample) {                      if ((*iter).gig_sample == sample) {
1068                          printf("Removing previously added sample '%s'\n", (*iter).sample_path.c_str());                          printf("Removing previously added sample '%s'\n",
1069                                   (*iter).sample_path.c_str());
1070                          m_SampleImportQueue.erase(iter);                          m_SampleImportQueue.erase(iter);
1071                          break;                          break;
1072                      }                      }
# Line 1930  void MainWindow::on_action_remove_sample Line 1081  void MainWindow::on_action_remove_sample
1081      }      }
1082  }  }
1083    
1084  void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&, Gtk::SelectionData& selection_data, guint, guint)  void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&,
1085                                                      Gtk::SelectionData& selection_data, guint, guint)
1086  {  {
1087      // get selected sample      // get selected sample
1088      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
# Line 1941  void MainWindow::on_sample_treeview_drag Line 1093  void MainWindow::on_sample_treeview_drag
1093          sample = row[m_SamplesModel.m_col_sample];          sample = row[m_SamplesModel.m_col_sample];
1094      }      }
1095      // pass the gig::Sample as pointer      // pass the gig::Sample as pointer
1096      selection_data.set(selection_data.get_target(), 0/*unused*/, (const guchar*)&sample, sizeof(sample)/*length of data in bytes*/);      selection_data.set(selection_data.get_target(), 0/*unused*/, (const guchar*)&sample,
1097                           sizeof(sample)/*length of data in bytes*/);
1098  }  }
1099    
1100  void MainWindow::on_sample_label_drop_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int, int, const Gtk::SelectionData& selection_data, guint, guint time)  void MainWindow::on_sample_label_drop_drag_data_received(
1101        const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1102        const Gtk::SelectionData& selection_data, guint, guint time)
1103  {  {
1104      gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();      gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();
1105      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
# Line 1952  void MainWindow::on_sample_label_drop_dr Line 1107  void MainWindow::on_sample_label_drop_dr
1107      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {
1108          if (sample != dimregion->pSample) {          if (sample != dimregion->pSample) {
1109              dimregion->pSample = sample;              dimregion->pSample = sample;
1110              wSample->set_text(dimregion->pSample->pInfo->Name.c_str());              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());
1111              std::cout << "Drop received sample \"" << dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;              std::cout << "Drop received sample \"" <<
1112                    dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;
1113              // drop success              // drop success
1114              context->drop_reply(true, time);              context->drop_reply(true, time);
1115              return;              return;
# Line 1963  void MainWindow::on_sample_label_drop_dr Line 1119  void MainWindow::on_sample_label_drop_dr
1119      context->drop_reply(false, time);      context->drop_reply(false, time);
1120  }  }
1121    
1122  void MainWindow::sample_name_changed(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter) {  void MainWindow::sample_name_changed(const Gtk::TreeModel::Path& path,
1123                                         const Gtk::TreeModel::iterator& iter) {
1124      if (!iter) return;      if (!iter) return;
1125      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1126      Glib::ustring name  = row[m_SamplesModel.m_col_name];      Glib::ustring name  = row[m_SamplesModel.m_col_name];
# Line 1971  void MainWindow::sample_name_changed(con Line 1128  void MainWindow::sample_name_changed(con
1128      gig::Sample* sample = row[m_SamplesModel.m_col_sample];      gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1129      if (group) {      if (group) {
1130          group->Name = name;          group->Name = name;
         std::cout << "Group name changed\n" << std::flush;  
1131      } else if (sample) {      } else if (sample) {
1132          sample->pInfo->Name = name.raw();          sample->pInfo->Name = name.raw();
         std::cout << "Sample name changed\n" << std::flush;  
1133      }      }
1134  }  }
1135    
1136  void MainWindow::instrument_name_changed(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter) {  void MainWindow::instrument_name_changed(const Gtk::TreeModel::Path& path,
1137      std::cout << "Instrument name changed\n" << std::flush;                                           const Gtk::TreeModel::iterator& iter) {
1138      if (!iter) return;      if (!iter) return;
1139      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1140      Glib::ustring name = row[m_Columns.m_col_name];      Glib::ustring name = row[m_Columns.m_col_name];

Legend:
Removed from v.1097  
changed lines
  Added in v.1213

  ViewVC Help
Powered by ViewVC