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

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

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

revision 1261 by persson, Thu Jul 5 17:12:20 2007 UTC revision 1673 by schoenebeck, Wed Feb 6 22:08:29 2008 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006 - 2008 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
 #include <libintl.h>  
20  #include <iostream>  #include <iostream>
21    
22  #include <gtkmm/filechooserdialog.h>  #include <gtkmm/filechooserdialog.h>
# Line 25  Line 24 
24  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
25  #include <gtkmm/targetentry.h>  #include <gtkmm/targetentry.h>
26  #include <gtkmm/main.h>  #include <gtkmm/main.h>
27    #include <gtkmm/toggleaction.h>
28    
29    #include "global.h"
30    
31  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
32  #define ABOUT_DIALOG  #define ABOUT_DIALOG
33  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
34  #endif  #endif
35    
36    #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION < 6) || GLIBMM_MAJOR_VERSION < 2
37    namespace Glib {
38    Glib::ustring filename_display_basename(const std::string& filename)
39    {
40        gchar* gstr = g_path_get_basename(filename.c_str());
41        Glib::ustring str(gstr);
42        g_free(gstr);
43        return Glib::filename_to_utf8(str);
44    }
45    }
46    #endif
47    
48  #include <stdio.h>  #include <stdio.h>
49  #include <sndfile.h>  #include <sndfile.h>
50    
51  #include "mainwindow.h"  #include "mainwindow.h"
52    
53  #define _(String) gettext(String)  #include "../../gfx/status_attached.xpm"
54    #include "../../gfx/status_detached.xpm"
55    
56  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
57      std::stringstream ss;      std::stringstream ss;
# Line 44  template<class T> inline std::string ToS Line 59  template<class T> inline std::string ToS
59      return ss.str();      return ss.str();
60  }  }
61    
62  MainWindow::MainWindow()  Table::Table(int x, int y) : Gtk::Table(x, y), rowno(0) {  }
63    
64    void Table::add(BoolEntry& boolentry)
65    {
66        attach(boolentry.widget, 0, 2, rowno, rowno + 1,
67               Gtk::FILL, Gtk::SHRINK);
68        rowno++;
69    }
70    
71    void Table::add(BoolEntryPlus6& boolentry)
72    {
73        attach(boolentry.widget, 0, 2, rowno, rowno + 1,
74               Gtk::FILL, Gtk::SHRINK);
75        rowno++;
76    }
77    
78    void Table::add(LabelWidget& prop)
79    {
80        attach(prop.label, 1, 2, rowno, rowno + 1,
81               Gtk::FILL, Gtk::SHRINK);
82        attach(prop.widget, 2, 3, rowno, rowno + 1,
83               Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
84        rowno++;
85    }
86    
87    MainWindow::MainWindow() :
88        dimreg_label(_("Changes apply to:")),
89        dimreg_all_regions(_("all regions")),
90        dimreg_all_dimregs(_("all dimension splits")),
91        dimreg_stereo(_("both channels"))
92  {  {
93  //    set_border_width(5);  //    set_border_width(5);
94  //    set_default_size(400, 200);  //    set_default_size(400, 200);
# Line 74  MainWindow::MainWindow() Line 118  MainWindow::MainWindow()
118      m_TreeViewNotebook.set_size_request(300);      m_TreeViewNotebook.set_size_request(300);
119    
120      m_HPaned.add1(m_TreeViewNotebook);      m_HPaned.add1(m_TreeViewNotebook);
121      m_HPaned.add2(dimreg_edit);      dimreg_hbox.add(dimreg_label);
122        dimreg_hbox.add(dimreg_all_regions);
123        dimreg_hbox.add(dimreg_all_dimregs);
124        dimreg_stereo.set_active();
125        dimreg_hbox.add(dimreg_stereo);
126        dimreg_vbox.add(dimreg_edit);
127        dimreg_vbox.pack_start(dimreg_hbox, Gtk::PACK_SHRINK);
128        m_HPaned.add2(dimreg_vbox);
129    
130    
131      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");
# Line 115  MainWindow::MainWindow() Line 166  MainWindow::MainWindow()
166                           *this, &MainWindow::on_action_quit));                           *this, &MainWindow::on_action_quit));
167      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
168    
169        actionGroup->add(Gtk::Action::create("MenuView", _("_View")));
170        Glib::RefPtr<Gtk::ToggleAction> toggle_action =
171            Gtk::ToggleAction::create("Statusbar", _("_Statusbar"));
172        toggle_action->set_active(true);
173        actionGroup->add(toggle_action,
174                         sigc::mem_fun(
175                             *this, &MainWindow::on_action_view_status_bar));
176    
177      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
178      actionGroup->add(Gtk::Action::create("MenuHelp",      actionGroup->add(Gtk::Action::create("MenuHelp",
179                                           action->property_label()));                                           action->property_label()));
# Line 149  MainWindow::MainWindow() Line 208  MainWindow::MainWindow()
208          Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),          Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),
209          sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)          sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)
210      );      );
211        actionGroup->add(
212            Gtk::Action::create("ReplaceAllSamplesInAllGroups", _("Replace All Samples In All Groups")),
213            sigc::mem_fun(*this, &MainWindow::on_action_replace_all_samples_in_all_groups)
214        );
215    
216      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
217      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
# Line 170  MainWindow::MainWindow() Line 233  MainWindow::MainWindow()
233          "    </menu>"          "    </menu>"
234          "    <menu action='MenuInstrument'>"          "    <menu action='MenuInstrument'>"
235          "    </menu>"          "    </menu>"
236            "    <menu action='MenuView'>"
237            "      <menuitem action='Statusbar'/>"
238            "    </menu>"
239  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
240          "    <menu action='MenuHelp'>"          "    <menu action='MenuHelp'>"
241          "      <menuitem action='About'/>"          "      <menuitem action='About'/>"
# Line 186  MainWindow::MainWindow() Line 252  MainWindow::MainWindow()
252          "    <menuitem action='SampleProperties'/>"          "    <menuitem action='SampleProperties'/>"
253          "    <menuitem action='AddGroup'/>"          "    <menuitem action='AddGroup'/>"
254          "    <menuitem action='AddSample'/>"          "    <menuitem action='AddSample'/>"
255            "    <menuitem action='ReplaceAllSamplesInAllGroups' />"
256          "    <separator/>"          "    <separator/>"
257          "    <menuitem action='RemoveSample'/>"          "    <menuitem action='RemoveSample'/>"
258          "  </popup>"          "  </popup>"
# Line 198  MainWindow::MainWindow() Line 265  MainWindow::MainWindow()
265      m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);      m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);
266      m_VBox.pack_start(m_HPaned);      m_VBox.pack_start(m_HPaned);
267      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
268        m_VBox.pack_start(m_RegionChooser.m_VirtKeybPropsBox, Gtk::PACK_SHRINK);
269      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
270        m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK);
271    
272        // Status Bar:
273        m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK);
274        m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK);
275        m_StatusBar.show();
276    
277      m_RegionChooser.signal_region_selected().connect(      m_RegionChooser.signal_region_selected().connect(
278          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
# Line 234  MainWindow::MainWindow() Line 308  MainWindow::MainWindow()
308      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
309      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
310      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
311        m_TreeViewSamples.signal_drag_begin().connect(
312            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
313        );
314      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
315          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
316      );      );
# Line 242  MainWindow::MainWindow() Line 319  MainWindow::MainWindow()
319          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
320      );      );
321      dimreg_edit.signal_dimreg_changed().connect(      dimreg_edit.signal_dimreg_changed().connect(
322          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
323      m_RegionChooser.signal_instrument_changed().connect(      m_RegionChooser.signal_instrument_changed().connect(
324          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
325      m_DimRegionChooser.signal_region_changed().connect(      m_DimRegionChooser.signal_region_changed().connect(
326          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
327      instrumentProps.signal_instrument_changed().connect(      instrumentProps.signal_instrument_changed().connect(
328          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
329        propDialog.signal_info_changed().connect(
330            sigc::mem_fun(*this, &MainWindow::file_changed));
331    
332        dimreg_edit.signal_dimreg_to_be_changed().connect(
333            dimreg_to_be_changed_signal.make_slot());
334        dimreg_edit.signal_dimreg_changed().connect(
335            dimreg_changed_signal.make_slot());
336        dimreg_edit.signal_sample_ref_changed().connect(
337            sample_ref_changed_signal.make_slot());
338    
339        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
340            sigc::hide(
341                sigc::bind(
342                    file_structure_to_be_changed_signal.make_slot(),
343                    sigc::ref(this->file)
344                )
345            )
346        );
347        m_RegionChooser.signal_instrument_struct_changed().connect(
348            sigc::hide(
349                sigc::bind(
350                    file_structure_changed_signal.make_slot(),
351                    sigc::ref(this->file)
352                )
353            )
354        );
355        m_RegionChooser.signal_region_to_be_changed().connect(
356            region_to_be_changed_signal.make_slot());
357        m_RegionChooser.signal_region_changed_signal().connect(
358            region_changed_signal.make_slot());
359    
360        note_on_signal.connect(
361            sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_on_event));
362        note_off_signal.connect(
363            sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_off_event));
364    
365        dimreg_all_regions.signal_toggled().connect(
366            sigc::mem_fun(*this, &MainWindow::update_dimregs));
367        dimreg_all_dimregs.signal_toggled().connect(
368            sigc::mem_fun(*this, &MainWindow::dimreg_all_dimregs_toggled));
369        dimreg_stereo.signal_toggled().connect(
370            sigc::mem_fun(*this, &MainWindow::update_dimregs));
371    
372      file = 0;      file = 0;
373      file_is_changed = false;      file_is_changed = false;
374        set_file_is_shared(false);
375    
376      show_all_children();      show_all_children();
377    
378        // start with a new gig file by default
379        on_action_file_new();
380  }  }
381    
382  MainWindow::~MainWindow()  MainWindow::~MainWindow()
# Line 261  MainWindow::~MainWindow() Line 385  MainWindow::~MainWindow()
385    
386  bool MainWindow::on_delete_event(GdkEventAny* event)  bool MainWindow::on_delete_event(GdkEventAny* event)
387  {  {
388      return file_is_changed && !close_confirmation_dialog();      return !file_is_shared && file_is_changed && !close_confirmation_dialog();
389  }  }
390    
391  void MainWindow::on_action_quit()  void MainWindow::on_action_quit()
392  {  {
393      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
394      hide();      hide();
395  }  }
396    
# Line 275  void MainWindow::region_changed() Line 399  void MainWindow::region_changed()
399      m_DimRegionChooser.set_region(m_RegionChooser.get_region());      m_DimRegionChooser.set_region(m_RegionChooser.get_region());
400  }  }
401    
402  void MainWindow::dimreg_changed()  gig::Instrument* MainWindow::get_instrument()
 {  
     dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());  
 }  
   
 void MainWindow::on_sel_change()  
403  {  {
404        gig::Instrument* instrument = 0;
405      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
406    
407      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
408      if (it) {      if (it) {
409          Gtk::TreeModel::Row row = *it;          Gtk::TreeModel::Row row = *it;
410          std::cout << row[m_Columns.m_col_name] << std::endl;          instrument = row[m_Columns.m_col_instr];
411        }
412        return instrument;
413    }
414    
415          m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]);  void MainWindow::add_region_to_dimregs(gig::Region* region, bool stereo, bool all_dimregs)
416    {
417        if (all_dimregs) {
418            for (int i = 0 ; i < region->DimensionRegions ; i++) {
419                if (region->pDimensionRegions[i]) {
420                    dimreg_edit.dimregs.insert(region->pDimensionRegions[i]);
421                }
422            }
423      } else {      } else {
424          m_RegionChooser.set_instrument(0);          m_DimRegionChooser.get_dimregions(region, stereo, dimreg_edit.dimregs);
425      }      }
426  }  }
427    
428    void MainWindow::update_dimregs()
429    {
430        dimreg_edit.dimregs.clear();
431        bool all_regions = dimreg_all_regions.get_active();
432        bool stereo = dimreg_stereo.get_active();
433        bool all_dimregs = dimreg_all_dimregs.get_active();
434    
435        if (all_regions) {
436            gig::Instrument* instrument = get_instrument();
437            if (instrument) {
438                for (gig::Region* region = instrument->GetFirstRegion() ;
439                     region ;
440                     region = instrument->GetNextRegion()) {
441                    add_region_to_dimregs(region, stereo, all_dimregs);
442                }
443            }
444        } else {
445            gig::Region* region = m_RegionChooser.get_region();
446            if (region) {
447                add_region_to_dimregs(region, stereo, all_dimregs);
448            }
449        }
450    }
451    
452    void MainWindow::dimreg_all_dimregs_toggled()
453    {
454        dimreg_stereo.set_sensitive(!dimreg_all_dimregs.get_active());
455        update_dimregs();
456    }
457    
458    void MainWindow::dimreg_changed()
459    {
460        update_dimregs();
461        dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());
462    }
463    
464    void MainWindow::on_sel_change()
465    {
466        m_RegionChooser.set_instrument(get_instrument());
467    }
468    
469  void loader_progress_callback(gig::progress_t* progress)  void loader_progress_callback(gig::progress_t* progress)
470  {  {
471      Loader* loader = static_cast<Loader*>(progress->custom);      Loader* loader = static_cast<Loader*>(progress->custom);
# Line 380  void MainWindow::__clear() { Line 551  void MainWindow::__clear() {
551      m_refTreeModel->clear();      m_refTreeModel->clear();
552      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
553      // free libgig's gig::File instance      // free libgig's gig::File instance
554      if (file) {      if (file && !file_is_shared) delete file;
555          delete file;      file = NULL;
556          file = NULL;      set_file_is_shared(false);
     }  
557  }  }
558    
559  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
560  {  {
561      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
562    
563        if (file_is_shared && !leaving_shared_mode_dialog()) return;
564    
565      // clear all GUI elements      // clear all GUI elements
566      __clear();      __clear();
# Line 407  bool MainWindow::close_confirmation_dial Line 579  bool MainWindow::close_confirmation_dial
579                                   Glib::filename_display_basename(filename).c_str());                                   Glib::filename_display_basename(filename).c_str());
580      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
581      g_free(msg);      g_free(msg);
582    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
583      dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));      dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));
584    #endif
585      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
586      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
587      dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);      dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);
588      dialog.set_default_response(Gtk::RESPONSE_YES);      dialog.set_default_response(Gtk::RESPONSE_YES);
589      int response = dialog.run();      int response = dialog.run();
590        dialog.hide();
591      if (response == Gtk::RESPONSE_YES) return file_save();      if (response == Gtk::RESPONSE_YES) return file_save();
592      return response != Gtk::RESPONSE_CANCEL;      return response != Gtk::RESPONSE_CANCEL;
593  }  }
594    
595    bool MainWindow::leaving_shared_mode_dialog() {
596        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
597        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
598    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
599        dialog.set_secondary_text(
600            _("If you proceed to work on another instrument file, it won't be "
601              "used by the sampler until you tell the sampler explicitly to "
602              "load it.")
603       );
604    #endif
605        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
606        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
607        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
608        int response = dialog.run();
609        dialog.hide();
610        return response == Gtk::RESPONSE_YES;
611    }
612    
613  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
614  {  {
615      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
616    
617        if (file_is_shared && !leaving_shared_mode_dialog()) return;
618    
619      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
620      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
# Line 434  void MainWindow::on_action_file_open() Line 629  void MainWindow::on_action_file_open()
629      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
630          std::string filename = dialog.get_filename();          std::string filename = dialog.get_filename();
631          printf("filename=%s\n", filename.c_str());          printf("filename=%s\n", filename.c_str());
         __clear();  
632          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
633          load_file(filename.c_str());          load_file(filename.c_str());
634          current_dir = Glib::path_get_dirname(filename);          current_dir = Glib::path_get_dirname(filename);
# Line 443  void MainWindow::on_action_file_open() Line 637  void MainWindow::on_action_file_open()
637    
638  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
639  {  {
640        __clear();
641      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
642      load_dialog->show_all();      load_dialog->show_all();
643      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 460  void MainWindow::load_instrument(gig::In Line 655  void MainWindow::load_instrument(gig::In
655          msg.run();          msg.run();
656          Gtk::Main::quit();          Gtk::Main::quit();
657      }      }
658        // clear all GUI elements
659        __clear();
660        // load the instrument
661      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
662      load_gig(pFile, 0 /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
663      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
664  }  }
665    
# Line 483  void MainWindow::on_action_file_save() Line 681  void MainWindow::on_action_file_save()
681      file_save();      file_save();
682  }  }
683    
684  bool MainWindow::file_save()  bool MainWindow::check_if_savable()
685  {  {
686      if (!file) return false;      if (!file) return false;
687      if (!file_has_name) return file_save_as();  
688        if (!file->GetFirstSample()) {
689            Gtk::MessageDialog(*this, _("The file could not be saved "
690                                        "because it contains no samples"),
691                               false, Gtk::MESSAGE_ERROR).run();
692            return false;
693        }
694    
695        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
696             instrument = file->GetNextInstrument()) {
697            if (!instrument->GetFirstRegion()) {
698                Gtk::MessageDialog(*this, _("The file could not be saved "
699                                            "because there are instruments "
700                                            "that have no regions"),
701                                   false, Gtk::MESSAGE_ERROR).run();
702                return false;
703            }
704        }
705        return true;
706    }
707    
708    bool MainWindow::file_save()
709    {
710        if (!check_if_savable()) return false;
711        if (!file_is_shared && !file_has_name) return file_save_as();
712    
713      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
714        file_structure_to_be_changed_signal.emit(this->file);
715      try {      try {
716          file->Save();          file->Save();
717          if (file_is_changed) {          if (file_is_changed) {
# Line 496  bool MainWindow::file_save() Line 719  bool MainWindow::file_save()
719              file_is_changed = false;              file_is_changed = false;
720          }          }
721      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
722          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
723            Glib::ustring txt = _("Could not save file: ") + e.Message;
724          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
725          msg.run();          msg.run();
726          return false;          return false;
727      }      }
728      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
729      __import_queued_samples();      __import_queued_samples();
730        file_structure_changed_signal.emit(this->file);
731      return true;      return true;
732  }  }
733    
734  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
735  {  {
736        if (!check_if_savable()) return;
737      file_save_as();      file_save_as();
738  }  }
739    
740  bool MainWindow::file_save_as()  bool MainWindow::file_save_as()
741  {  {
     if (!file) return false;  
742      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
743      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
744      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
# Line 535  bool MainWindow::file_save_as() Line 760  bool MainWindow::file_save_as()
760      dialog.set_current_name(Glib::filename_display_basename(filename));      dialog.set_current_name(Glib::filename_display_basename(filename));
761    
762      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
763            file_structure_to_be_changed_signal.emit(this->file);
764          try {          try {
765              std::string filename = dialog.get_filename();              std::string filename = dialog.get_filename();
766              if (!Glib::str_has_suffix(filename, ".gig")) {              if (!Glib::str_has_suffix(filename, ".gig")) {
# Line 548  bool MainWindow::file_save_as() Line 774  bool MainWindow::file_save_as()
774              file_has_name = true;              file_has_name = true;
775              file_is_changed = false;              file_is_changed = false;
776          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
777              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
778                Glib::ustring txt = _("Could not save file: ") + e.Message;
779              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
780              msg.run();              msg.run();
781              return false;              return false;
782          }          }
783          __import_queued_samples();          __import_queued_samples();
784            file_structure_changed_signal.emit(this->file);
785          return true;          return true;
786      }      }
787      return false;      return false;
# Line 576  void MainWindow::__import_queued_samples Line 804  void MainWindow::__import_queued_samples
804              int bitdepth;              int bitdepth;
805              switch (info.format & 0xff) {              switch (info.format & 0xff) {
806                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
807                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
808                    case SF_FORMAT_PCM_U8:
809                      bitdepth = 16;                      bitdepth = 16;
810                      break;                      break;
811                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
812                  case SF_FORMAT_PCM_32:                  case SF_FORMAT_PCM_32:
                     bitdepth = 32;  
                     break;  
                 case SF_FORMAT_PCM_U8:  
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
813                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
814                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
815                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
816                      break;                      break;
817                  default:                  default:
818                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
819                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
820              }              }
821              // allocate appropriate copy buffer (TODO: for now we copy  
822              // it in one piece, might be tough for very long samples)              const int bufsize = 10000;
             // and copy sample data into buffer  
             int8_t* buffer = NULL;  
823              switch (bitdepth) {              switch (bitdepth) {
824                  case 16:                  case 16: {
825                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
826                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
827                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
828                            // libsndfile does the conversion for us (if needed)
829                            int n = sf_readf_short(hFile, buffer, bufsize);
830                            // write from buffer directly (physically) into .gig file
831                            iter->gig_sample->Write(buffer, n);
832                            cnt -= n;
833                        }
834                        delete[] buffer;
835                      break;                      break;
836                  case 32:                  }
837                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
838                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
839                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
840                        sf_count_t cnt = info.frames;
841                        while (cnt) {
842                            // libsndfile returns 32 bits, convert to 24
843                            int n = sf_readf_int(hFile, srcbuf, bufsize);
844                            int j = 0;
845                            for (int i = 0 ; i < n * info.channels ; i++) {
846                                dstbuf[j++] = srcbuf[i] >> 8;
847                                dstbuf[j++] = srcbuf[i] >> 16;
848                                dstbuf[j++] = srcbuf[i] >> 24;
849                            }
850                            // write from buffer directly (physically) into .gig file
851                            iter->gig_sample->Write(dstbuf, n);
852                            cnt -= n;
853                        }
854                        delete[] srcbuf;
855                        delete[] dstbuf;
856                      break;                      break;
857                    }
858              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
859              // cleanup              // cleanup
860              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
861              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
862              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
863              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 635  void MainWindow::__import_queued_samples Line 872  void MainWindow::__import_queued_samples
872      }      }
873      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
874      if (error_files.size()) {      if (error_files.size()) {
875          Glib::ustring txt = "Could not import the following sample(s):\n" + error_files;          Glib::ustring txt = _("Could not import the following sample(s):\n") + error_files;
876          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
877          msg.run();          msg.run();
878      }      }
# Line 652  void MainWindow::on_action_help_about() Line 889  void MainWindow::on_action_help_about()
889  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
890      Gtk::AboutDialog dialog;      Gtk::AboutDialog dialog;
891      dialog.set_version(VERSION);      dialog.set_version(VERSION);
892        dialog.set_copyright("Copyright (C) 2006,2007 Andreas Persson");
893        dialog.set_comments(
894            "Released under the GNU General Public License.\n"
895            "\n"
896            "Please notice that this is still a very young instrument editor. "
897            "So better backup your Gigasampler files before editing them with "
898            "this application.\n"
899            "\n"
900            "Please report bugs to: http://bugs.linuxsampler.org"
901        );
902        dialog.set_website("http://www.linuxsampler.org");
903        dialog.set_website_label("http://www.linuxsampler.org");
904      dialog.run();      dialog.run();
905  #endif  #endif
906  }  }
907    
908  PropDialog::PropDialog()  PropDialog::PropDialog()
909      : table(2,1)      : table(2,1),
910          eName("Name"),
911          eCreationDate("Creation date"),
912          eComments("Comments"),
913          eProduct("Product"),
914          eCopyright("Copyright"),
915          eArtists("Artists"),
916          eGenre("Genre"),
917          eKeywords("Keywords"),
918          eEngineer("Engineer"),
919          eTechnician("Technician"),
920          eSoftware("Software"),
921          eMedium("Medium"),
922          eSource("Source"),
923          eSourceForm("Source form"),
924          eCommissioned("Commissioned"),
925          eSubject("Subject"),
926          quitButton(Gtk::Stock::CLOSE),
927          update_model(0)
928  {  {
929        set_title("File Properties");
930        eName.set_width_chars(50);
931    
932        connect(eName, &DLS::Info::Name);
933        connect(eCreationDate, &DLS::Info::CreationDate);
934        connect(eComments, &DLS::Info::Comments);
935        connect(eProduct, &DLS::Info::Product);
936        connect(eCopyright, &DLS::Info::Copyright);
937        connect(eArtists, &DLS::Info::Artists);
938        connect(eGenre, &DLS::Info::Genre);
939        connect(eKeywords, &DLS::Info::Keywords);
940        connect(eEngineer, &DLS::Info::Engineer);
941        connect(eTechnician, &DLS::Info::Technician);
942        connect(eSoftware, &DLS::Info::Software);
943        connect(eMedium, &DLS::Info::Medium);
944        connect(eSource, &DLS::Info::Source);
945        connect(eSourceForm, &DLS::Info::SourceForm);
946        connect(eCommissioned, &DLS::Info::Commissioned);
947        connect(eSubject, &DLS::Info::Subject);
948    
949        table.add(eName);
950        table.add(eCreationDate);
951        table.add(eComments);
952        table.add(eProduct);
953        table.add(eCopyright);
954        table.add(eArtists);
955        table.add(eGenre);
956        table.add(eKeywords);
957        table.add(eEngineer);
958        table.add(eTechnician);
959        table.add(eSoftware);
960        table.add(eMedium);
961        table.add(eSource);
962        table.add(eSourceForm);
963        table.add(eCommissioned);
964        table.add(eSubject);
965    
966      table.set_col_spacings(5);      table.set_col_spacings(5);
967      const char* propLabels[] = {      add(vbox);
968          "Name:",      table.set_border_width(5);
969          "CreationDate:",      vbox.add(table);
970          "Comments:", // TODO: multiline      vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
971          "Product:",      buttonBox.set_layout(Gtk::BUTTONBOX_END);
972          "Copyright:",      buttonBox.set_border_width(5);
973          "Artists:",      buttonBox.show();
974          "Genre:",      buttonBox.pack_start(quitButton);
975          "Keywords:",      quitButton.set_flags(Gtk::CAN_DEFAULT);
976          "Engineer:",      quitButton.grab_focus();
977          "Technician:",      quitButton.signal_clicked().connect(
978          "Software:", // TODO: readonly          sigc::mem_fun(*this, &PropDialog::hide));
         "Medium:",  
         "Source:",  
         "SourceForm:",  
         "Commissioned:",  
         "Subject:"  
     };  
     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);  
         table.attach(entry[i], 1, 2, i, i + 1, Gtk::FILL | Gtk::EXPAND,  
                      Gtk::SHRINK);  
     }  
979    
980      add(table);      quitButton.show();
981      // add_button(Gtk::Stock::CANCEL, 0);      vbox.show();
     // add_button(Gtk::Stock::OK, 1);  
982      show_all_children();      show_all_children();
983  }  }
984    
985  void PropDialog::set_info(DLS::Info* info)  void PropDialog::set_info(DLS::Info* info)
986  {  {
987      entry[0].set_text(info->Name);      this->info = info;
988      entry[1].set_text(info->CreationDate);      update_model++;
989      entry[2].set_text(Glib::convert(info->Comments, "UTF-8", "ISO-8859-1"));      eName.set_value(info->Name);
990      entry[3].set_text(info->Product);      eCreationDate.set_value(info->CreationDate);
991      entry[4].set_text(info->Copyright);      eComments.set_value(info->Comments);
992      entry[5].set_text(info->Artists);      eProduct.set_value(info->Product);
993      entry[6].set_text(info->Genre);      eCopyright.set_value(info->Copyright);
994      entry[7].set_text(info->Keywords);      eArtists.set_value(info->Artists);
995      entry[8].set_text(info->Engineer);      eGenre.set_value(info->Genre);
996      entry[9].set_text(info->Technician);      eKeywords.set_value(info->Keywords);
997      entry[10].set_text(info->Software);      eEngineer.set_value(info->Engineer);
998      entry[11].set_text(info->Medium);      eTechnician.set_value(info->Technician);
999      entry[12].set_text(info->Source);      eSoftware.set_value(info->Software);
1000      entry[13].set_text(info->SourceForm);      eMedium.set_value(info->Medium);
1001      entry[14].set_text(info->Commissioned);      eSource.set_value(info->Source);
1002      entry[15].set_text(info->Subject);      eSourceForm.set_value(info->SourceForm);
1003  }      eCommissioned.set_value(info->Commissioned);
1004        eSubject.set_value(info->Subject);
1005  void InstrumentProps::add_prop(LabelWidget& prop)      update_model--;
1006  {  }
1007      table.attach(prop.label, 0, 1, rowno, rowno + 1,  
1008                   Gtk::FILL, Gtk::SHRINK);  sigc::signal<void>& PropDialog::signal_info_changed()
1009      table.attach(prop.widget, 1, 2, rowno, rowno + 1,  {
1010                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);      return info_changed;
1011      rowno++;  }
1012      prop.signal_changed_by_user().connect(instrument_changed.make_slot());  
1013    void InstrumentProps::set_IsDrum(bool value)
1014    {
1015        instrument->IsDrum = value;
1016    }
1017    
1018    void InstrumentProps::set_MIDIBank(uint16_t value)
1019    {
1020        instrument->MIDIBank = value;
1021    }
1022    
1023    void InstrumentProps::set_MIDIProgram(uint32_t value)
1024    {
1025        instrument->MIDIProgram = value;
1026    }
1027    
1028    void InstrumentProps::set_DimensionKeyRange_low(uint8_t value)
1029    {
1030        instrument->DimensionKeyRange.low = value;
1031        if (value > instrument->DimensionKeyRange.high) {
1032            eDimensionKeyRangeHigh.set_value(value);
1033        }
1034    }
1035    
1036    void InstrumentProps::set_DimensionKeyRange_high(uint8_t value)
1037    {
1038        instrument->DimensionKeyRange.high = value;
1039        if (value < instrument->DimensionKeyRange.low) {
1040            eDimensionKeyRangeLow.set_value(value);
1041        }
1042  }  }
1043    
1044  InstrumentProps::InstrumentProps()  InstrumentProps::InstrumentProps()
1045      : table(2,1),      : table(2,1),
1046        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
1047        eName("Name"),        eName("Name"),
1048        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
1049        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
1050        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
1051        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
1052        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
1053        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
1054        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
1055        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
1056        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
1057        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Keyswitching range low"),
1058        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Keyswitching range high"),
1059  {        update_model(0)
1060      set_title("Instrument properties");  {
1061        set_title("Instrument Properties");
1062    
1063        eDimensionKeyRangeLow.set_tip(
1064            _("start of the keyboard area which should switch the "
1065              "\"keyswitching\" dimension")
1066        );
1067        eDimensionKeyRangeHigh.set_tip(
1068            _("end of the keyboard area which should switch the "
1069              "\"keyswitching\" dimension")
1070        );
1071    
1072        connect(eIsDrum, &InstrumentProps::set_IsDrum);
1073        connect(eMIDIBank, &InstrumentProps::set_MIDIBank);
1074        connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram);
1075        connect(eAttenuation, &gig::Instrument::Attenuation);
1076        connect(eGainPlus6, &gig::Instrument::Attenuation);
1077        connect(eEffectSend, &gig::Instrument::EffectSend);
1078        connect(eFineTune, &gig::Instrument::FineTune);
1079        connect(ePitchbendRange, &gig::Instrument::PitchbendRange);
1080        connect(ePianoReleaseMode, &gig::Instrument::PianoReleaseMode);
1081        connect(eDimensionKeyRangeLow,
1082                &InstrumentProps::set_DimensionKeyRange_low);
1083        connect(eDimensionKeyRangeHigh,
1084                &InstrumentProps::set_DimensionKeyRange_high);
1085    
     rowno = 0;  
1086      table.set_col_spacings(5);      table.set_col_spacings(5);
1087    
1088      add_prop(eName);      table.add(eName);
1089      add_prop(eIsDrum);      table.add(eIsDrum);
1090      add_prop(eMIDIBank);      table.add(eMIDIBank);
1091      add_prop(eMIDIProgram);      table.add(eMIDIProgram);
1092      add_prop(eAttenuation);      table.add(eAttenuation);
1093      add_prop(eGainPlus6);      table.add(eGainPlus6);
1094      add_prop(eEffectSend);      table.add(eEffectSend);
1095      add_prop(eFineTune);      table.add(eFineTune);
1096      add_prop(ePitchbendRange);      table.add(ePitchbendRange);
1097      add_prop(ePianoReleaseMode);      table.add(ePianoReleaseMode);
1098      add_prop(eDimensionKeyRangeLow);      table.add(eDimensionKeyRangeLow);
1099      add_prop(eDimensionKeyRangeHigh);      table.add(eDimensionKeyRangeHigh);
   
     eDimensionKeyRangeLow.signal_changed_by_user().connect(  
         sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));  
     eDimensionKeyRangeHigh.signal_changed_by_user().connect(  
         sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));  
1100    
1101      add(vbox);      add(vbox);
1102      table.set_border_width(5);      table.set_border_width(5);
# Line 783  InstrumentProps::InstrumentProps() Line 1120  InstrumentProps::InstrumentProps()
1120    
1121  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
1122  {  {
1123      eName.set_ptr(&instrument->pInfo->Name);      this->instrument = instrument;
     eIsDrum.set_ptr(&instrument->IsDrum);  
     eMIDIBank.set_ptr(&instrument->MIDIBank);  
     eMIDIProgram.set_ptr(&instrument->MIDIProgram);  
     eAttenuation.set_ptr(&instrument->Attenuation);  
     eGainPlus6.set_ptr(&instrument->Attenuation);  
     eEffectSend.set_ptr(&instrument->EffectSend);  
     eFineTune.set_ptr(&instrument->FineTune);  
     ePitchbendRange.set_ptr(&instrument->PitchbendRange);  
     ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);  
     eDimensionKeyRangeLow.set_ptr(0);  
     eDimensionKeyRangeHigh.set_ptr(0);  
     eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);  
     eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);  
 }  
   
 void InstrumentProps::key_range_low_changed()  
 {  
     double l = eDimensionKeyRangeLow.get_value();  
     double h = eDimensionKeyRangeHigh.get_value();  
     if (h < l) eDimensionKeyRangeHigh.set_value(l);  
 }  
1124    
1125  void InstrumentProps::key_range_high_changed()      update_model++;
1126  {      eName.set_value(instrument->pInfo->Name);
1127      double l = eDimensionKeyRangeLow.get_value();      eIsDrum.set_value(instrument->IsDrum);
1128      double h = eDimensionKeyRangeHigh.get_value();      eMIDIBank.set_value(instrument->MIDIBank);
1129      if (h < l) eDimensionKeyRangeLow.set_value(h);      eMIDIProgram.set_value(instrument->MIDIProgram);
1130        eAttenuation.set_value(instrument->Attenuation);
1131        eGainPlus6.set_value(instrument->Attenuation);
1132        eEffectSend.set_value(instrument->EffectSend);
1133        eFineTune.set_value(instrument->FineTune);
1134        ePitchbendRange.set_value(instrument->PitchbendRange);
1135        ePianoReleaseMode.set_value(instrument->PianoReleaseMode);
1136        eDimensionKeyRangeLow.set_value(instrument->DimensionKeyRange.low);
1137        eDimensionKeyRangeHigh.set_value(instrument->DimensionKeyRange.high);
1138        update_model--;
1139  }  }
1140    
1141  sigc::signal<void> InstrumentProps::signal_instrument_changed()  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
1142  {  {
1143      return instrument_changed;      return instrument_changed;
1144  }  }
# Line 826  void MainWindow::file_changed() Line 1151  void MainWindow::file_changed()
1151      }      }
1152  }  }
1153    
1154  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
1155  {  {
1156      file = 0;      file = 0;
1157        set_file_is_shared(isSharedInstrument);
1158    
1159      this->filename = filename ? filename : _("Unsaved Gig File");      this->filename = filename ? filename : _("Unsaved Gig File");
1160      set_title(Glib::filename_display_basename(this->filename));      set_title(Glib::filename_display_basename(this->filename));
# Line 891  void MainWindow::load_gig(gig::File* gig Line 1217  void MainWindow::load_gig(gig::File* gig
1217    
1218  void MainWindow::show_instr_props()  void MainWindow::show_instr_props()
1219  {  {
1220      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      gig::Instrument* instrument = get_instrument();
1221      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      if (instrument)
     if (it)  
1222      {      {
1223          Gtk::TreeModel::Row row = *it;          instrumentProps.set_instrument(instrument);
1224          if (row[m_Columns.m_col_instr])          instrumentProps.show();
1225          {          instrumentProps.deiconify();
1226              instrumentProps.set_instrument(row[m_Columns.m_col_instr]);      }
1227              instrumentProps.show();  }
1228              instrumentProps.deiconify();  
1229          }  void MainWindow::on_action_view_status_bar() {
1230        Gtk::CheckMenuItem* item =
1231            dynamic_cast<Gtk::CheckMenuItem*>(uiManager->get_widget("/MenuBar/MenuView/Statusbar"));
1232        if (!item) {
1233            std::cerr << "/MenuBar/MenuView/Statusbar == NULL\n";
1234            return;
1235      }      }
1236        if (item->get_active()) m_StatusBar.show();
1237        else                    m_StatusBar.hide();
1238  }  }
1239    
1240  void MainWindow::on_button_release(GdkEventButton* button)  void MainWindow::on_button_release(GdkEventButton* button)
# Line 962  void MainWindow::on_action_add_instrumen Line 1294  void MainWindow::on_action_add_instrumen
1294    
1295  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1296      if (!file) return;      if (!file) return;
1297        if (file_is_shared) {
1298            Gtk::MessageDialog msg(
1299                *this,
1300                 _("You cannot delete an instrument from this file, since it's "
1301                   "currently used by the sampler."),
1302                 false, Gtk::MESSAGE_INFO
1303            );
1304            msg.run();
1305            return;
1306        }
1307    
1308      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1309      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1310      if (it) {      if (it) {
# Line 1027  void MainWindow::on_action_add_sample() Line 1370  void MainWindow::on_action_add_sample()
1370      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1371      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1372      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1373      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1374          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1375          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1376          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 1057  void MainWindow::on_action_add_sample() Line 1400  void MainWindow::on_action_add_sample()
1400                  int bitdepth;                  int bitdepth;
1401                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1402                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1403                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1404                        case SF_FORMAT_PCM_U8:
1405                          bitdepth = 16;                          bitdepth = 16;
1406                          break;                          break;
1407                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1408                      case SF_FORMAT_PCM_32:                      case SF_FORMAT_PCM_32:
                         bitdepth = 32;  
                         break;  
                     case SF_FORMAT_PCM_U8:  
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1409                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1410                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1411                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1412                          break;                          break;
1413                      default:                      default:
1414                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 1084  void MainWindow::on_action_add_sample() Line 1417  void MainWindow::on_action_add_sample()
1417                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1418                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1419                  // file name without path                  // file name without path
1420                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1421                    // remove file extension if there is one
1422                    for (int i = 0; supportedFileTypes[i]; i++) {
1423                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1424                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1425                            break;
1426                        }
1427                    }
1428                    sample->pInfo->Name = filename;
1429                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1430                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1431                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1432                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1433                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1434                    sample->BlockAlign = sample->FrameSize;
1435                    sample->SamplesTotal = info.frames;
1436    
1437                    SF_INSTRUMENT instrument;
1438                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1439                                   &instrument, sizeof(instrument)) != SF_FALSE)
1440                    {
1441                        sample->MIDIUnityNote = instrument.basenote;
1442    
1443    #if HAVE_SF_INSTRUMENT_LOOPS
1444                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1445                            sample->Loops = 1;
1446    
1447                            switch (instrument.loops[0].mode) {
1448                            case SF_LOOP_FORWARD:
1449                                sample->LoopType = gig::loop_type_normal;
1450                                break;
1451                            case SF_LOOP_BACKWARD:
1452                                sample->LoopType = gig::loop_type_backward;
1453                                break;
1454                            case SF_LOOP_ALTERNATING:
1455                                sample->LoopType = gig::loop_type_bidirectional;
1456                                break;
1457                            }
1458                            sample->LoopStart = instrument.loops[0].start;
1459                            sample->LoopEnd = instrument.loops[0].end;
1460                            sample->LoopPlayCount = instrument.loops[0].count;
1461                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1462                        }
1463    #endif
1464                    }
1465    
1466                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1467                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1468                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1104  void MainWindow::on_action_add_sample() Line 1478  void MainWindow::on_action_add_sample()
1478                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1479                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1480                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1481                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1482                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1483                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1484                  // close sound file                  // close sound file
# Line 1117  void MainWindow::on_action_add_sample() Line 1491  void MainWindow::on_action_add_sample()
1491          }          }
1492          // show error message box when some file(s) could not be opened / added          // show error message box when some file(s) could not be opened / added
1493          if (error_files.size()) {          if (error_files.size()) {
1494              Glib::ustring txt = "Could not add the following sample(s):\n" + error_files;              Glib::ustring txt = _("Could not add the following sample(s):\n") + error_files;
1495                Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1496                msg.run();
1497            }
1498        }
1499    }
1500    
1501    void MainWindow::on_action_replace_all_samples_in_all_groups()
1502    {
1503        if (!file) return;
1504        Gtk::FileChooserDialog dialog(*this, _("Select Folder"),
1505                                      Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
1506        Gtk::Label description(
1507            _("This is a very specific function. It tries to replace all samples "
1508              "in the current gig file by samples located in the directory chosen "
1509              "by you above.\n\n"
1510              "It works like this: For each sample in the gig file it tries to "
1511              "find a sample file in the selected directory with the same name as "
1512              "the sample in the gig file. Optionally you can add a filename "
1513              "postfix below, which will be added to the filename expected to be "
1514              "found. That is, assume you have a gig file with a sample called "
1515              "'Snare', if you enter '.wav' below (like it's done by default), it "
1516              "assumes to find a sample file called 'Snare.wav' and will replace "
1517              "the sample in the gig file accordingly. If you don't need such a "
1518              "postfix, blank the field below. Any gig sample where no "
1519              "appropriate sample file could be found, will be reported and left "
1520              "untouched.\n\n")
1521        );
1522        description.set_line_wrap(true);
1523        Gtk::HBox entryArea;
1524        Gtk::Label entryLabel( _("Add Filename Extension: "), Gtk::ALIGN_RIGHT);
1525        Gtk::Entry postfixEntryBox;
1526        postfixEntryBox.set_text(".wav");
1527        entryArea.pack_start(entryLabel);
1528        entryArea.pack_start(postfixEntryBox);
1529        dialog.get_vbox()->pack_start(description, Gtk::PACK_SHRINK);
1530        dialog.get_vbox()->pack_start(entryArea, Gtk::PACK_SHRINK);
1531        description.show();
1532        entryLabel.show();
1533        postfixEntryBox.show();
1534        entryArea.show();
1535        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1536        dialog.add_button(_("Select"), Gtk::RESPONSE_OK);
1537        dialog.set_select_multiple(false);
1538        // fix label width (because Gtk by design doesn't
1539        // know anything about the parent's size)
1540    #if 0 //FIXME: doesn't work
1541        int dialogW, dialogH, labelW, labelH;
1542        dialog.get_size_request(dialogW, dialogH);
1543        description.get_size_request(labelW, labelH);
1544        std::cout << "dialog(" << dialogW << "," << dialogH << ")\nlabel(" << labelW << "," << labelH << ")\n" << std::flush;
1545        description.set_size_request(dialogW, labelH);
1546    #endif
1547        if (dialog.run() == Gtk::RESPONSE_OK)
1548        {
1549            Glib::ustring error_files;
1550            Glib::ustring folder = dialog.get_filename();
1551            for (gig::Sample* sample = file->GetFirstSample();
1552                 sample; sample = file->GetNextSample())
1553            {
1554                std::string filename =
1555                    folder + G_DIR_SEPARATOR_S + sample->pInfo->Name +
1556                    postfixEntryBox.get_text().raw();
1557                SF_INFO info;
1558                info.format = 0;
1559                SNDFILE* hFile = sf_open(filename.c_str(), SFM_READ, &info);
1560                try
1561                {
1562                    if (!hFile) throw std::string("could not open file");
1563                    int bitdepth;
1564                    switch (info.format & 0xff) {
1565                        case SF_FORMAT_PCM_S8:
1566                        case SF_FORMAT_PCM_16:
1567                        case SF_FORMAT_PCM_U8:
1568                            bitdepth = 16;
1569                            break;
1570                        case SF_FORMAT_PCM_24:
1571                        case SF_FORMAT_PCM_32:
1572                        case SF_FORMAT_FLOAT:
1573                        case SF_FORMAT_DOUBLE:
1574                            bitdepth = 24;
1575                            break;
1576                        default:
1577                            sf_close(hFile);
1578                            throw std::string("format not supported");
1579                    }
1580                    SampleImportItem sched_item;
1581                    sched_item.gig_sample  = sample;
1582                    sched_item.sample_path = filename;
1583                    m_SampleImportQueue.push_back(sched_item);
1584                    sf_close(hFile);
1585                    file_changed();
1586                }
1587                catch (std::string what)
1588                {
1589                    if (error_files.size()) error_files += "\n";
1590                        error_files += filename += " (" + what + ")";
1591                }
1592            }
1593            // show error message box when some file(s) could not be opened / added
1594            if (error_files.size()) {
1595                Glib::ustring txt =
1596                    _("Could not replace the following sample(s):\n") + error_files;
1597              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1598              msg.run();              msg.run();
1599          }          }
# Line 1143  void MainWindow::on_action_remove_sample Line 1619  void MainWindow::on_action_remove_sample
1619                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1620                      members.push_back(pSample);                      members.push_back(pSample);
1621                  }                  }
1622                    // notify everybody that we're going to remove these samples
1623                    samples_to_be_removed_signal.emit(members);
1624                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1625                  // samples that belong to the group                  // samples that belong to the group
1626                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1627                    // notify that we're done with removal
1628                    samples_removed_signal.emit();
1629                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1630                  // them from the import queue                  // them from the import queue
1631                  for (std::list<gig::Sample*>::iterator member = members.begin();                  for (std::list<gig::Sample*>::iterator member = members.begin();
# Line 1162  void MainWindow::on_action_remove_sample Line 1642  void MainWindow::on_action_remove_sample
1642                  }                  }
1643                  file_changed();                  file_changed();
1644              } else if (sample) {              } else if (sample) {
1645                    // notify everybody that we're going to remove this sample
1646                    std::list<gig::Sample*> lsamples;
1647                    lsamples.push_back(sample);
1648                    samples_to_be_removed_signal.emit(lsamples);
1649                  // remove sample from the .gig file                  // remove sample from the .gig file
1650                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1651                    // notify that we're done with removal
1652                    samples_removed_signal.emit();
1653                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1654                  // the import queue                  // the import queue
1655                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
# Line 1175  void MainWindow::on_action_remove_sample Line 1661  void MainWindow::on_action_remove_sample
1661                          break;                          break;
1662                      }                      }
1663                  }                  }
1664                    dimreg_changed();
1665                  file_changed();                  file_changed();
1666              }              }
1667              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1668              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1669          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1670                // pretend we're done with removal (i.e. to avoid dead locks)
1671                samples_removed_signal.emit();
1672                // show error message
1673              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1674              msg.run();              msg.run();
1675          }          }
1676      }      }
1677  }  }
1678    
1679    // For some reason drag_data_get gets called two times for each
1680    // drag'n'drop (at least when target is an Entry). This work-around
1681    // makes sure the code in drag_data_get and drop_drag_data_received is
1682    // only executed once, as drag_begin only gets called once.
1683    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1684    {
1685        first_call_to_drag_data_get = true;
1686    }
1687    
1688  void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&,  void MainWindow::on_sample_treeview_drag_data_get(const Glib::RefPtr<Gdk::DragContext>&,
1689                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1690  {  {
1691        if (!first_call_to_drag_data_get) return;
1692        first_call_to_drag_data_get = false;
1693    
1694      // get selected sample      // get selected sample
1695      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1696      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
# Line 1206  void MainWindow::on_sample_label_drop_dr Line 1708  void MainWindow::on_sample_label_drop_dr
1708      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1709      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1710  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1711      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1712    
1713      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1714          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1715              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1716              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1717              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1718                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1719              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1720              context->drop_reply(true, time);  
1721              file_changed();          // notify everybody that we're going to alter the region
1722              return;          gig::Region* region = m_RegionChooser.get_region();
1723            region_to_be_changed_signal.emit(region);
1724    
1725            // find the samplechannel dimension
1726            gig::dimension_def_t* stereo_dimension = 0;
1727            for (int i = 0 ; i < region->Dimensions ; i++) {
1728                if (region->pDimensionDefinitions[i].dimension ==
1729                    gig::dimension_samplechannel) {
1730                    stereo_dimension = &region->pDimensionDefinitions[i];
1731                    break;
1732                }
1733            }
1734            bool channels_changed = false;
1735            if (sample->Channels == 1 && stereo_dimension) {
1736                // remove the samplechannel dimension
1737                region->DeleteDimension(stereo_dimension);
1738                channels_changed = true;
1739                region_changed();
1740          }          }
1741            dimreg_edit.set_sample(sample);
1742    
1743            if (sample->Channels == 2 && !stereo_dimension) {
1744                // add samplechannel dimension
1745                gig::dimension_def_t dim;
1746                dim.dimension = gig::dimension_samplechannel;
1747                dim.bits = 1;
1748                dim.zones = 2;
1749                region->AddDimension(&dim);
1750                channels_changed = true;
1751                region_changed();
1752            }
1753            if (channels_changed) {
1754                // unmap all samples with wrong number of channels
1755                // TODO: maybe there should be a warning dialog for this
1756                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1757                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1758                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1759                        gig::Sample* oldref = d->pSample;
1760                        d->pSample = NULL;
1761                        sample_ref_changed_signal.emit(oldref, NULL);
1762                    }
1763                }
1764            }
1765    
1766            // notify we're done with altering
1767            region_changed_signal.emit(region);
1768    
1769            file_changed();
1770    
1771            return;
1772      }      }
1773      // drop failed      // drop failed
1774      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1258  void MainWindow::instrument_name_changed Line 1807  void MainWindow::instrument_name_changed
1807          file_changed();          file_changed();
1808      }      }
1809  }  }
1810    
1811    void MainWindow::set_file_is_shared(bool b) {
1812        this->file_is_shared = b;
1813    
1814        if (file_is_shared) {
1815            m_AttachedStateLabel.set_label(_("live-mode"));
1816            m_AttachedStateImage.set(
1817                Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm)
1818            );
1819        } else {
1820            m_AttachedStateLabel.set_label(_("stand-alone"));
1821            m_AttachedStateImage.set(
1822                Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm)
1823            );
1824        }
1825    }
1826    
1827    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1828        return file_structure_to_be_changed_signal;
1829    }
1830    
1831    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1832        return file_structure_changed_signal;
1833    }
1834    
1835    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1836        return samples_to_be_removed_signal;
1837    }
1838    
1839    sigc::signal<void>& MainWindow::signal_samples_removed() {
1840        return samples_removed_signal;
1841    }
1842    
1843    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1844        return region_to_be_changed_signal;
1845    }
1846    
1847    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1848        return region_changed_signal;
1849    }
1850    
1851    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1852        return sample_ref_changed_signal;
1853    }
1854    
1855    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1856        return dimreg_to_be_changed_signal;
1857    }
1858    
1859    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1860        return dimreg_changed_signal;
1861    }
1862    
1863    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_note_on() {
1864        return note_on_signal;
1865    }
1866    
1867    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_note_off() {
1868        return note_off_signal;
1869    }
1870    
1871    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_keyboard_key_hit() {
1872        return m_RegionChooser.signal_keyboard_key_hit();
1873    }
1874    
1875    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_keyboard_key_released() {
1876        return m_RegionChooser.signal_keyboard_key_released();
1877    }

Legend:
Removed from v.1261  
changed lines
  Added in v.1673

  ViewVC Help
Powered by ViewVC