/[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 1725 by persson, Sat Apr 26 08:52:15 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    #include <cstring>
22    
23  #include <gtkmm/filechooserdialog.h>  #include <gtkmm/filechooserdialog.h>
24  #include <gtkmm/messagedialog.h>  #include <gtkmm/messagedialog.h>
25  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
26  #include <gtkmm/targetentry.h>  #include <gtkmm/targetentry.h>
27  #include <gtkmm/main.h>  #include <gtkmm/main.h>
28    #include <gtkmm/toggleaction.h>
29    
30    #include "global.h"
31    
32  #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
33  #define ABOUT_DIALOG  #define ABOUT_DIALOG
34  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
35  #endif  #endif
36    
37    #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION < 6) || GLIBMM_MAJOR_VERSION < 2
38    namespace Glib {
39    Glib::ustring filename_display_basename(const std::string& filename)
40    {
41        gchar* gstr = g_path_get_basename(filename.c_str());
42        Glib::ustring str(gstr);
43        g_free(gstr);
44        return Glib::filename_to_utf8(str);
45    }
46    }
47    #endif
48    
49  #include <stdio.h>  #include <stdio.h>
50  #include <sndfile.h>  #include <sndfile.h>
51    
52  #include "mainwindow.h"  #include "mainwindow.h"
53    
54  #define _(String) gettext(String)  #include "../../gfx/status_attached.xpm"
55    #include "../../gfx/status_detached.xpm"
56    
57  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
58      std::stringstream ss;      std::stringstream ss;
# Line 44  template<class T> inline std::string ToS Line 60  template<class T> inline std::string ToS
60      return ss.str();      return ss.str();
61  }  }
62    
63  MainWindow::MainWindow()  Table::Table(int x, int y) : Gtk::Table(x, y), rowno(0) {  }
64    
65    void Table::add(BoolEntry& boolentry)
66    {
67        attach(boolentry.widget, 0, 2, rowno, rowno + 1,
68               Gtk::FILL, Gtk::SHRINK);
69        rowno++;
70    }
71    
72    void Table::add(BoolEntryPlus6& boolentry)
73    {
74        attach(boolentry.widget, 0, 2, rowno, rowno + 1,
75               Gtk::FILL, Gtk::SHRINK);
76        rowno++;
77    }
78    
79    void Table::add(LabelWidget& prop)
80    {
81        attach(prop.label, 1, 2, rowno, rowno + 1,
82               Gtk::FILL, Gtk::SHRINK);
83        attach(prop.widget, 2, 3, rowno, rowno + 1,
84               Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
85        rowno++;
86    }
87    
88    MainWindow::MainWindow() :
89        dimreg_label(_("Changes apply to:")),
90        dimreg_all_regions(_("all regions")),
91        dimreg_all_dimregs(_("all dimension splits")),
92        dimreg_stereo(_("both channels"))
93  {  {
94  //    set_border_width(5);  //    set_border_width(5);
95  //    set_default_size(400, 200);  //    set_default_size(400, 200);
# Line 74  MainWindow::MainWindow() Line 119  MainWindow::MainWindow()
119      m_TreeViewNotebook.set_size_request(300);      m_TreeViewNotebook.set_size_request(300);
120    
121      m_HPaned.add1(m_TreeViewNotebook);      m_HPaned.add1(m_TreeViewNotebook);
122      m_HPaned.add2(dimreg_edit);      dimreg_hbox.add(dimreg_label);
123        dimreg_hbox.add(dimreg_all_regions);
124        dimreg_hbox.add(dimreg_all_dimregs);
125        dimreg_stereo.set_active();
126        dimreg_hbox.add(dimreg_stereo);
127        dimreg_vbox.add(dimreg_edit);
128        dimreg_vbox.pack_start(dimreg_hbox, Gtk::PACK_SHRINK);
129        m_HPaned.add2(dimreg_vbox);
130    
131    
132      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");
# Line 115  MainWindow::MainWindow() Line 167  MainWindow::MainWindow()
167                           *this, &MainWindow::on_action_quit));                           *this, &MainWindow::on_action_quit));
168      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
169    
170        actionGroup->add(Gtk::Action::create("MenuView", _("_View")));
171        Glib::RefPtr<Gtk::ToggleAction> toggle_action =
172            Gtk::ToggleAction::create("Statusbar", _("_Statusbar"));
173        toggle_action->set_active(true);
174        actionGroup->add(toggle_action,
175                         sigc::mem_fun(
176                             *this, &MainWindow::on_action_view_status_bar));
177    
178      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
179      actionGroup->add(Gtk::Action::create("MenuHelp",      actionGroup->add(Gtk::Action::create("MenuHelp",
180                                           action->property_label()));                                           action->property_label()));
# Line 149  MainWindow::MainWindow() Line 209  MainWindow::MainWindow()
209          Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),          Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),
210          sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)          sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)
211      );      );
212        actionGroup->add(
213            Gtk::Action::create("ReplaceAllSamplesInAllGroups", _("Replace All Samples In All Groups")),
214            sigc::mem_fun(*this, &MainWindow::on_action_replace_all_samples_in_all_groups)
215        );
216    
217      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
218      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
# Line 170  MainWindow::MainWindow() Line 234  MainWindow::MainWindow()
234          "    </menu>"          "    </menu>"
235          "    <menu action='MenuInstrument'>"          "    <menu action='MenuInstrument'>"
236          "    </menu>"          "    </menu>"
237            "    <menu action='MenuView'>"
238            "      <menuitem action='Statusbar'/>"
239            "    </menu>"
240  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
241          "    <menu action='MenuHelp'>"          "    <menu action='MenuHelp'>"
242          "      <menuitem action='About'/>"          "      <menuitem action='About'/>"
# Line 186  MainWindow::MainWindow() Line 253  MainWindow::MainWindow()
253          "    <menuitem action='SampleProperties'/>"          "    <menuitem action='SampleProperties'/>"
254          "    <menuitem action='AddGroup'/>"          "    <menuitem action='AddGroup'/>"
255          "    <menuitem action='AddSample'/>"          "    <menuitem action='AddSample'/>"
256            "    <menuitem action='ReplaceAllSamplesInAllGroups' />"
257          "    <separator/>"          "    <separator/>"
258          "    <menuitem action='RemoveSample'/>"          "    <menuitem action='RemoveSample'/>"
259          "  </popup>"          "  </popup>"
# Line 198  MainWindow::MainWindow() Line 266  MainWindow::MainWindow()
266      m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);      m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);
267      m_VBox.pack_start(m_HPaned);      m_VBox.pack_start(m_HPaned);
268      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
269        m_VBox.pack_start(m_RegionChooser.m_VirtKeybPropsBox, Gtk::PACK_SHRINK);
270      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
271        m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK);
272    
273        // Status Bar:
274        m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK);
275        m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK);
276        m_StatusBar.show();
277    
278      m_RegionChooser.signal_region_selected().connect(      m_RegionChooser.signal_region_selected().connect(
279          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
# Line 234  MainWindow::MainWindow() Line 309  MainWindow::MainWindow()
309      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
310      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
311      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
312        m_TreeViewSamples.signal_drag_begin().connect(
313            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
314        );
315      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
316          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
317      );      );
# Line 242  MainWindow::MainWindow() Line 320  MainWindow::MainWindow()
320          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
321      );      );
322      dimreg_edit.signal_dimreg_changed().connect(      dimreg_edit.signal_dimreg_changed().connect(
323          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
324      m_RegionChooser.signal_instrument_changed().connect(      m_RegionChooser.signal_instrument_changed().connect(
325          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
326      m_DimRegionChooser.signal_region_changed().connect(      m_DimRegionChooser.signal_region_changed().connect(
327          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
328      instrumentProps.signal_instrument_changed().connect(      instrumentProps.signal_instrument_changed().connect(
329          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
330        propDialog.signal_info_changed().connect(
331            sigc::mem_fun(*this, &MainWindow::file_changed));
332    
333        dimreg_edit.signal_dimreg_to_be_changed().connect(
334            dimreg_to_be_changed_signal.make_slot());
335        dimreg_edit.signal_dimreg_changed().connect(
336            dimreg_changed_signal.make_slot());
337        dimreg_edit.signal_sample_ref_changed().connect(
338            sample_ref_changed_signal.make_slot());
339    
340        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
341            sigc::hide(
342                sigc::bind(
343                    file_structure_to_be_changed_signal.make_slot(),
344                    sigc::ref(this->file)
345                )
346            )
347        );
348        m_RegionChooser.signal_instrument_struct_changed().connect(
349            sigc::hide(
350                sigc::bind(
351                    file_structure_changed_signal.make_slot(),
352                    sigc::ref(this->file)
353                )
354            )
355        );
356        m_RegionChooser.signal_region_to_be_changed().connect(
357            region_to_be_changed_signal.make_slot());
358        m_RegionChooser.signal_region_changed_signal().connect(
359            region_changed_signal.make_slot());
360    
361        note_on_signal.connect(
362            sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_on_event));
363        note_off_signal.connect(
364            sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_off_event));
365    
366        dimreg_all_regions.signal_toggled().connect(
367            sigc::mem_fun(*this, &MainWindow::update_dimregs));
368        dimreg_all_dimregs.signal_toggled().connect(
369            sigc::mem_fun(*this, &MainWindow::dimreg_all_dimregs_toggled));
370        dimreg_stereo.signal_toggled().connect(
371            sigc::mem_fun(*this, &MainWindow::update_dimregs));
372    
373      file = 0;      file = 0;
374      file_is_changed = false;      file_is_changed = false;
375        set_file_is_shared(false);
376    
377      show_all_children();      show_all_children();
378    
379        // start with a new gig file by default
380        on_action_file_new();
381  }  }
382    
383  MainWindow::~MainWindow()  MainWindow::~MainWindow()
# Line 261  MainWindow::~MainWindow() Line 386  MainWindow::~MainWindow()
386    
387  bool MainWindow::on_delete_event(GdkEventAny* event)  bool MainWindow::on_delete_event(GdkEventAny* event)
388  {  {
389      return file_is_changed && !close_confirmation_dialog();      return !file_is_shared && file_is_changed && !close_confirmation_dialog();
390  }  }
391    
392  void MainWindow::on_action_quit()  void MainWindow::on_action_quit()
393  {  {
394      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
395      hide();      hide();
396  }  }
397    
# Line 275  void MainWindow::region_changed() Line 400  void MainWindow::region_changed()
400      m_DimRegionChooser.set_region(m_RegionChooser.get_region());      m_DimRegionChooser.set_region(m_RegionChooser.get_region());
401  }  }
402    
403  void MainWindow::dimreg_changed()  gig::Instrument* MainWindow::get_instrument()
 {  
     dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());  
 }  
   
 void MainWindow::on_sel_change()  
404  {  {
405        gig::Instrument* instrument = 0;
406      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
407    
408      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
409      if (it) {      if (it) {
410          Gtk::TreeModel::Row row = *it;          Gtk::TreeModel::Row row = *it;
411          std::cout << row[m_Columns.m_col_name] << std::endl;          instrument = row[m_Columns.m_col_instr];
412        }
413        return instrument;
414    }
415    
416    void MainWindow::add_region_to_dimregs(gig::Region* region, bool stereo, bool all_dimregs)
417    {
418        if (all_dimregs) {
419            for (int i = 0 ; i < region->DimensionRegions ; i++) {
420                if (region->pDimensionRegions[i]) {
421                    dimreg_edit.dimregs.insert(region->pDimensionRegions[i]);
422                }
423            }
424        } else {
425            m_DimRegionChooser.get_dimregions(region, stereo, dimreg_edit.dimregs);
426        }
427    }
428    
429    void MainWindow::update_dimregs()
430    {
431        dimreg_edit.dimregs.clear();
432        bool all_regions = dimreg_all_regions.get_active();
433        bool stereo = dimreg_stereo.get_active();
434        bool all_dimregs = dimreg_all_dimregs.get_active();
435    
436          m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]);      if (all_regions) {
437            gig::Instrument* instrument = get_instrument();
438            if (instrument) {
439                for (gig::Region* region = instrument->GetFirstRegion() ;
440                     region ;
441                     region = instrument->GetNextRegion()) {
442                    add_region_to_dimregs(region, stereo, all_dimregs);
443                }
444            }
445      } else {      } else {
446          m_RegionChooser.set_instrument(0);          gig::Region* region = m_RegionChooser.get_region();
447            if (region) {
448                add_region_to_dimregs(region, stereo, all_dimregs);
449            }
450      }      }
451  }  }
452    
453    void MainWindow::dimreg_all_dimregs_toggled()
454    {
455        dimreg_stereo.set_sensitive(!dimreg_all_dimregs.get_active());
456        update_dimregs();
457    }
458    
459    void MainWindow::dimreg_changed()
460    {
461        update_dimregs();
462        dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());
463    }
464    
465    void MainWindow::on_sel_change()
466    {
467        m_RegionChooser.set_instrument(get_instrument());
468    }
469    
470  void loader_progress_callback(gig::progress_t* progress)  void loader_progress_callback(gig::progress_t* progress)
471  {  {
472      Loader* loader = static_cast<Loader*>(progress->custom);      Loader* loader = static_cast<Loader*>(progress->custom);
# Line 380  void MainWindow::__clear() { Line 552  void MainWindow::__clear() {
552      m_refTreeModel->clear();      m_refTreeModel->clear();
553      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
554      // free libgig's gig::File instance      // free libgig's gig::File instance
555      if (file) {      if (file && !file_is_shared) delete file;
556          delete file;      file = NULL;
557          file = NULL;      set_file_is_shared(false);
     }  
558  }  }
559    
560  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
561  {  {
562      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
563    
564        if (file_is_shared && !leaving_shared_mode_dialog()) return;
565    
566      // clear all GUI elements      // clear all GUI elements
567      __clear();      __clear();
# Line 407  bool MainWindow::close_confirmation_dial Line 580  bool MainWindow::close_confirmation_dial
580                                   Glib::filename_display_basename(filename).c_str());                                   Glib::filename_display_basename(filename).c_str());
581      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
582      g_free(msg);      g_free(msg);
583    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
584      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."));
585    #endif
586      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
587      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
588      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);
589      dialog.set_default_response(Gtk::RESPONSE_YES);      dialog.set_default_response(Gtk::RESPONSE_YES);
590      int response = dialog.run();      int response = dialog.run();
591        dialog.hide();
592      if (response == Gtk::RESPONSE_YES) return file_save();      if (response == Gtk::RESPONSE_YES) return file_save();
593      return response != Gtk::RESPONSE_CANCEL;      return response != Gtk::RESPONSE_CANCEL;
594  }  }
595    
596    bool MainWindow::leaving_shared_mode_dialog() {
597        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
598        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
599    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
600        dialog.set_secondary_text(
601            _("If you proceed to work on another instrument file, it won't be "
602              "used by the sampler until you tell the sampler explicitly to "
603              "load it.")
604       );
605    #endif
606        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
607        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
608        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
609        int response = dialog.run();
610        dialog.hide();
611        return response == Gtk::RESPONSE_YES;
612    }
613    
614  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
615  {  {
616      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
617    
618        if (file_is_shared && !leaving_shared_mode_dialog()) return;
619    
620      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
621      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
# Line 428  void MainWindow::on_action_file_open() Line 624  void MainWindow::on_action_file_open()
624      Gtk::FileFilter filter;      Gtk::FileFilter filter;
625      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
626      dialog.set_filter(filter);      dialog.set_filter(filter);
627      if (current_dir != "") {      if (current_gig_dir != "") {
628          dialog.set_current_folder(current_dir);          dialog.set_current_folder(current_gig_dir);
629      }      }
630      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
631          std::string filename = dialog.get_filename();          std::string filename = dialog.get_filename();
632          printf("filename=%s\n", filename.c_str());          printf("filename=%s\n", filename.c_str());
         __clear();  
633          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
634          load_file(filename.c_str());          load_file(filename.c_str());
635          current_dir = Glib::path_get_dirname(filename);          current_gig_dir = Glib::path_get_dirname(filename);
636      }      }
637  }  }
638    
639  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
640  {  {
641        __clear();
642      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
643      load_dialog->show_all();      load_dialog->show_all();
644      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 460  void MainWindow::load_instrument(gig::In Line 656  void MainWindow::load_instrument(gig::In
656          msg.run();          msg.run();
657          Gtk::Main::quit();          Gtk::Main::quit();
658      }      }
659        // clear all GUI elements
660        __clear();
661        // load the instrument
662      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
663      load_gig(pFile, 0 /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
664      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
665  }  }
666    
# Line 483  void MainWindow::on_action_file_save() Line 682  void MainWindow::on_action_file_save()
682      file_save();      file_save();
683  }  }
684    
685  bool MainWindow::file_save()  bool MainWindow::check_if_savable()
686  {  {
687      if (!file) return false;      if (!file) return false;
688      if (!file_has_name) return file_save_as();  
689        if (!file->GetFirstSample()) {
690            Gtk::MessageDialog(*this, _("The file could not be saved "
691                                        "because it contains no samples"),
692                               false, Gtk::MESSAGE_ERROR).run();
693            return false;
694        }
695    
696        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
697             instrument = file->GetNextInstrument()) {
698            if (!instrument->GetFirstRegion()) {
699                Gtk::MessageDialog(*this, _("The file could not be saved "
700                                            "because there are instruments "
701                                            "that have no regions"),
702                                   false, Gtk::MESSAGE_ERROR).run();
703                return false;
704            }
705        }
706        return true;
707    }
708    
709    bool MainWindow::file_save()
710    {
711        if (!check_if_savable()) return false;
712        if (!file_is_shared && !file_has_name) return file_save_as();
713    
714      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
715        file_structure_to_be_changed_signal.emit(this->file);
716      try {      try {
717          file->Save();          file->Save();
718          if (file_is_changed) {          if (file_is_changed) {
# Line 496  bool MainWindow::file_save() Line 720  bool MainWindow::file_save()
720              file_is_changed = false;              file_is_changed = false;
721          }          }
722      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
723          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
724            Glib::ustring txt = _("Could not save file: ") + e.Message;
725          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
726          msg.run();          msg.run();
727          return false;          return false;
728      }      }
729      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
730      __import_queued_samples();      __import_queued_samples();
731        file_structure_changed_signal.emit(this->file);
732      return true;      return true;
733  }  }
734    
735  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
736  {  {
737        if (!check_if_savable()) return;
738      file_save_as();      file_save_as();
739  }  }
740    
741  bool MainWindow::file_save_as()  bool MainWindow::file_save_as()
742  {  {
     if (!file) return false;  
743      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
744      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
745      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
# Line 527  bool MainWindow::file_save_as() Line 753  bool MainWindow::file_save_as()
753      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
754      dialog.set_filter(filter);      dialog.set_filter(filter);
755    
756      if (Glib::path_is_absolute(filename)) {      // set initial dir and filename of the Save As dialog
757          dialog.set_filename(filename);      // and prepare that initial filename as a copy of the gig
758      } else if (current_dir != "") {      {
759          dialog.set_current_folder(current_dir);          std::string basename = Glib::path_get_basename(filename);
760            std::string dir = Glib::path_get_dirname(filename);
761            basename = std::string("copy_of_") + basename;
762            Glib::ustring copyFileName = Glib::build_filename(dir, basename);
763            if (Glib::path_is_absolute(filename)) {
764                dialog.set_filename(copyFileName);
765            } else {
766                if (current_gig_dir != "") dialog.set_current_folder(current_gig_dir);
767            }
768            dialog.set_current_name(Glib::filename_display_basename(copyFileName));
769      }      }
770      dialog.set_current_name(Glib::filename_display_basename(filename));  
771        // show warning in the dialog
772        Gtk::HBox descriptionArea;
773        descriptionArea.set_spacing(15);
774        Gtk::Image warningIcon(Gtk::Stock::DIALOG_WARNING, Gtk::IconSize(Gtk::ICON_SIZE_DIALOG));
775        descriptionArea.pack_start(warningIcon, Gtk::PACK_SHRINK);
776        warningIcon.show();
777        Gtk::Label description;
778        description.set_markup(
779            _("\n<b>CAUTION:</b> You <b>MUST</b> use the "
780              "<span style=\"italic\">\"Save\"</span> dialog instead of "
781              "<span style=\"italic\">\"Save As...\"</span> if you want to save "
782              "to the same .gig file. Using "
783              "<span style=\"italic\">\"Save As...\"</span> for writing to the "
784              "same .gig file will end up in corrupted sample wave data!\n")
785        );
786        description.set_line_wrap(true);
787        descriptionArea.pack_start(description, Gtk::PACK_SHRINK);
788        description.show();
789        dialog.get_vbox()->pack_start(descriptionArea, Gtk::PACK_SHRINK);
790        descriptionArea.show();
791    
792      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
793            file_structure_to_be_changed_signal.emit(this->file);
794          try {          try {
795              std::string filename = dialog.get_filename();              std::string filename = dialog.get_filename();
796              if (!Glib::str_has_suffix(filename, ".gig")) {              if (!Glib::str_has_suffix(filename, ".gig")) {
# Line 543  bool MainWindow::file_save_as() Line 799  bool MainWindow::file_save_as()
799              printf("filename=%s\n", filename.c_str());              printf("filename=%s\n", filename.c_str());
800              file->Save(filename);              file->Save(filename);
801              this->filename = filename;              this->filename = filename;
802              current_dir = Glib::path_get_dirname(filename);              current_gig_dir = Glib::path_get_dirname(filename);
803              set_title(Glib::filename_display_basename(filename));              set_title(Glib::filename_display_basename(filename));
804              file_has_name = true;              file_has_name = true;
805              file_is_changed = false;              file_is_changed = false;
806          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
807              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
808                Glib::ustring txt = _("Could not save file: ") + e.Message;
809              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
810              msg.run();              msg.run();
811              return false;              return false;
812          }          }
813          __import_queued_samples();          __import_queued_samples();
814            file_structure_changed_signal.emit(this->file);
815          return true;          return true;
816      }      }
817      return false;      return false;
# Line 576  void MainWindow::__import_queued_samples Line 834  void MainWindow::__import_queued_samples
834              int bitdepth;              int bitdepth;
835              switch (info.format & 0xff) {              switch (info.format & 0xff) {
836                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
837                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
838                    case SF_FORMAT_PCM_U8:
839                      bitdepth = 16;                      bitdepth = 16;
840                      break;                      break;
841                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
842                  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;  
843                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
844                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
845                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
846                      break;                      break;
847                  default:                  default:
848                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
849                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
850              }              }
851              // allocate appropriate copy buffer (TODO: for now we copy  
852              // 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;  
853              switch (bitdepth) {              switch (bitdepth) {
854                  case 16:                  case 16: {
855                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
856                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
857                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
858                            // libsndfile does the conversion for us (if needed)
859                            int n = sf_readf_short(hFile, buffer, bufsize);
860                            // write from buffer directly (physically) into .gig file
861                            iter->gig_sample->Write(buffer, n);
862                            cnt -= n;
863                        }
864                        delete[] buffer;
865                      break;                      break;
866                  case 32:                  }
867                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
868                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
869                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
870                        sf_count_t cnt = info.frames;
871                        while (cnt) {
872                            // libsndfile returns 32 bits, convert to 24
873                            int n = sf_readf_int(hFile, srcbuf, bufsize);
874                            int j = 0;
875                            for (int i = 0 ; i < n * info.channels ; i++) {
876                                dstbuf[j++] = srcbuf[i] >> 8;
877                                dstbuf[j++] = srcbuf[i] >> 16;
878                                dstbuf[j++] = srcbuf[i] >> 24;
879                            }
880                            // write from buffer directly (physically) into .gig file
881                            iter->gig_sample->Write(dstbuf, n);
882                            cnt -= n;
883                        }
884                        delete[] srcbuf;
885                        delete[] dstbuf;
886                      break;                      break;
887                    }
888              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
889              // cleanup              // cleanup
890              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
891              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
892              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
893              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 635  void MainWindow::__import_queued_samples Line 902  void MainWindow::__import_queued_samples
902      }      }
903      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
904      if (error_files.size()) {      if (error_files.size()) {
905          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;
906          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
907          msg.run();          msg.run();
908      }      }
# Line 652  void MainWindow::on_action_help_about() Line 919  void MainWindow::on_action_help_about()
919  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
920      Gtk::AboutDialog dialog;      Gtk::AboutDialog dialog;
921      dialog.set_version(VERSION);      dialog.set_version(VERSION);
922        dialog.set_copyright("Copyright (C) 2006,2007 Andreas Persson");
923        dialog.set_comments(
924            "Released under the GNU General Public License.\n"
925            "\n"
926            "Please notice that this is still a very young instrument editor. "
927            "So better backup your Gigasampler files before editing them with "
928            "this application.\n"
929            "\n"
930            "Please report bugs to: http://bugs.linuxsampler.org"
931        );
932        dialog.set_website("http://www.linuxsampler.org");
933        dialog.set_website_label("http://www.linuxsampler.org");
934      dialog.run();      dialog.run();
935  #endif  #endif
936  }  }
937    
938  PropDialog::PropDialog()  PropDialog::PropDialog()
939      : table(2,1)      : table(2,1),
940          eName("Name"),
941          eCreationDate("Creation date"),
942          eComments("Comments"),
943          eProduct("Product"),
944          eCopyright("Copyright"),
945          eArtists("Artists"),
946          eGenre("Genre"),
947          eKeywords("Keywords"),
948          eEngineer("Engineer"),
949          eTechnician("Technician"),
950          eSoftware("Software"),
951          eMedium("Medium"),
952          eSource("Source"),
953          eSourceForm("Source form"),
954          eCommissioned("Commissioned"),
955          eSubject("Subject"),
956          quitButton(Gtk::Stock::CLOSE),
957          update_model(0)
958  {  {
959        set_title("File Properties");
960        eName.set_width_chars(50);
961    
962        connect(eName, &DLS::Info::Name);
963        connect(eCreationDate, &DLS::Info::CreationDate);
964        connect(eComments, &DLS::Info::Comments);
965        connect(eProduct, &DLS::Info::Product);
966        connect(eCopyright, &DLS::Info::Copyright);
967        connect(eArtists, &DLS::Info::Artists);
968        connect(eGenre, &DLS::Info::Genre);
969        connect(eKeywords, &DLS::Info::Keywords);
970        connect(eEngineer, &DLS::Info::Engineer);
971        connect(eTechnician, &DLS::Info::Technician);
972        connect(eSoftware, &DLS::Info::Software);
973        connect(eMedium, &DLS::Info::Medium);
974        connect(eSource, &DLS::Info::Source);
975        connect(eSourceForm, &DLS::Info::SourceForm);
976        connect(eCommissioned, &DLS::Info::Commissioned);
977        connect(eSubject, &DLS::Info::Subject);
978    
979        table.add(eName);
980        table.add(eCreationDate);
981        table.add(eComments);
982        table.add(eProduct);
983        table.add(eCopyright);
984        table.add(eArtists);
985        table.add(eGenre);
986        table.add(eKeywords);
987        table.add(eEngineer);
988        table.add(eTechnician);
989        table.add(eSoftware);
990        table.add(eMedium);
991        table.add(eSource);
992        table.add(eSourceForm);
993        table.add(eCommissioned);
994        table.add(eSubject);
995    
996      table.set_col_spacings(5);      table.set_col_spacings(5);
997      const char* propLabels[] = {      add(vbox);
998          "Name:",      table.set_border_width(5);
999          "CreationDate:",      vbox.add(table);
1000          "Comments:", // TODO: multiline      vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
1001          "Product:",      buttonBox.set_layout(Gtk::BUTTONBOX_END);
1002          "Copyright:",      buttonBox.set_border_width(5);
1003          "Artists:",      buttonBox.show();
1004          "Genre:",      buttonBox.pack_start(quitButton);
1005          "Keywords:",      quitButton.set_flags(Gtk::CAN_DEFAULT);
1006          "Engineer:",      quitButton.grab_focus();
1007          "Technician:",      quitButton.signal_clicked().connect(
1008          "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);  
     }  
1009    
1010      add(table);      quitButton.show();
1011      // add_button(Gtk::Stock::CANCEL, 0);      vbox.show();
     // add_button(Gtk::Stock::OK, 1);  
1012      show_all_children();      show_all_children();
1013  }  }
1014    
1015  void PropDialog::set_info(DLS::Info* info)  void PropDialog::set_info(DLS::Info* info)
1016  {  {
1017      entry[0].set_text(info->Name);      this->info = info;
1018      entry[1].set_text(info->CreationDate);      update_model++;
1019      entry[2].set_text(Glib::convert(info->Comments, "UTF-8", "ISO-8859-1"));      eName.set_value(info->Name);
1020      entry[3].set_text(info->Product);      eCreationDate.set_value(info->CreationDate);
1021      entry[4].set_text(info->Copyright);      eComments.set_value(info->Comments);
1022      entry[5].set_text(info->Artists);      eProduct.set_value(info->Product);
1023      entry[6].set_text(info->Genre);      eCopyright.set_value(info->Copyright);
1024      entry[7].set_text(info->Keywords);      eArtists.set_value(info->Artists);
1025      entry[8].set_text(info->Engineer);      eGenre.set_value(info->Genre);
1026      entry[9].set_text(info->Technician);      eKeywords.set_value(info->Keywords);
1027      entry[10].set_text(info->Software);      eEngineer.set_value(info->Engineer);
1028      entry[11].set_text(info->Medium);      eTechnician.set_value(info->Technician);
1029      entry[12].set_text(info->Source);      eSoftware.set_value(info->Software);
1030      entry[13].set_text(info->SourceForm);      eMedium.set_value(info->Medium);
1031      entry[14].set_text(info->Commissioned);      eSource.set_value(info->Source);
1032      entry[15].set_text(info->Subject);      eSourceForm.set_value(info->SourceForm);
1033  }      eCommissioned.set_value(info->Commissioned);
1034        eSubject.set_value(info->Subject);
1035  void InstrumentProps::add_prop(LabelWidget& prop)      update_model--;
1036  {  }
1037      table.attach(prop.label, 0, 1, rowno, rowno + 1,  
1038                   Gtk::FILL, Gtk::SHRINK);  sigc::signal<void>& PropDialog::signal_info_changed()
1039      table.attach(prop.widget, 1, 2, rowno, rowno + 1,  {
1040                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);      return info_changed;
1041      rowno++;  }
1042      prop.signal_changed_by_user().connect(instrument_changed.make_slot());  
1043    void InstrumentProps::set_IsDrum(bool value)
1044    {
1045        instrument->IsDrum = value;
1046    }
1047    
1048    void InstrumentProps::set_MIDIBank(uint16_t value)
1049    {
1050        instrument->MIDIBank = value;
1051    }
1052    
1053    void InstrumentProps::set_MIDIProgram(uint32_t value)
1054    {
1055        instrument->MIDIProgram = value;
1056    }
1057    
1058    void InstrumentProps::set_DimensionKeyRange_low(uint8_t value)
1059    {
1060        instrument->DimensionKeyRange.low = value;
1061        if (value > instrument->DimensionKeyRange.high) {
1062            eDimensionKeyRangeHigh.set_value(value);
1063        }
1064    }
1065    
1066    void InstrumentProps::set_DimensionKeyRange_high(uint8_t value)
1067    {
1068        instrument->DimensionKeyRange.high = value;
1069        if (value < instrument->DimensionKeyRange.low) {
1070            eDimensionKeyRangeLow.set_value(value);
1071        }
1072  }  }
1073    
1074  InstrumentProps::InstrumentProps()  InstrumentProps::InstrumentProps()
1075      : table(2,1),      : table(2,1),
1076        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
1077        eName("Name"),        eName("Name"),
1078        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
1079        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
1080        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
1081        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
1082        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
1083        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
1084        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
1085        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
1086        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
1087        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Keyswitching range low"),
1088        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Keyswitching range high"),
1089  {        update_model(0)
1090      set_title("Instrument properties");  {
1091        set_title("Instrument Properties");
1092    
1093        eDimensionKeyRangeLow.set_tip(
1094            _("start of the keyboard area which should switch the "
1095              "\"keyswitching\" dimension")
1096        );
1097        eDimensionKeyRangeHigh.set_tip(
1098            _("end of the keyboard area which should switch the "
1099              "\"keyswitching\" dimension")
1100        );
1101    
1102        connect(eIsDrum, &InstrumentProps::set_IsDrum);
1103        connect(eMIDIBank, &InstrumentProps::set_MIDIBank);
1104        connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram);
1105        connect(eAttenuation, &gig::Instrument::Attenuation);
1106        connect(eGainPlus6, &gig::Instrument::Attenuation);
1107        connect(eEffectSend, &gig::Instrument::EffectSend);
1108        connect(eFineTune, &gig::Instrument::FineTune);
1109        connect(ePitchbendRange, &gig::Instrument::PitchbendRange);
1110        connect(ePianoReleaseMode, &gig::Instrument::PianoReleaseMode);
1111        connect(eDimensionKeyRangeLow,
1112                &InstrumentProps::set_DimensionKeyRange_low);
1113        connect(eDimensionKeyRangeHigh,
1114                &InstrumentProps::set_DimensionKeyRange_high);
1115    
     rowno = 0;  
1116      table.set_col_spacings(5);      table.set_col_spacings(5);
1117    
1118      add_prop(eName);      table.add(eName);
1119      add_prop(eIsDrum);      table.add(eIsDrum);
1120      add_prop(eMIDIBank);      table.add(eMIDIBank);
1121      add_prop(eMIDIProgram);      table.add(eMIDIProgram);
1122      add_prop(eAttenuation);      table.add(eAttenuation);
1123      add_prop(eGainPlus6);      table.add(eGainPlus6);
1124      add_prop(eEffectSend);      table.add(eEffectSend);
1125      add_prop(eFineTune);      table.add(eFineTune);
1126      add_prop(ePitchbendRange);      table.add(ePitchbendRange);
1127      add_prop(ePianoReleaseMode);      table.add(ePianoReleaseMode);
1128      add_prop(eDimensionKeyRangeLow);      table.add(eDimensionKeyRangeLow);
1129      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));  
1130    
1131      add(vbox);      add(vbox);
1132      table.set_border_width(5);      table.set_border_width(5);
# Line 783  InstrumentProps::InstrumentProps() Line 1150  InstrumentProps::InstrumentProps()
1150    
1151  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
1152  {  {
1153      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);  
 }  
1154    
1155  void InstrumentProps::key_range_high_changed()      update_model++;
1156  {      eName.set_value(instrument->pInfo->Name);
1157      double l = eDimensionKeyRangeLow.get_value();      eIsDrum.set_value(instrument->IsDrum);
1158      double h = eDimensionKeyRangeHigh.get_value();      eMIDIBank.set_value(instrument->MIDIBank);
1159      if (h < l) eDimensionKeyRangeLow.set_value(h);      eMIDIProgram.set_value(instrument->MIDIProgram);
1160        eAttenuation.set_value(instrument->Attenuation);
1161        eGainPlus6.set_value(instrument->Attenuation);
1162        eEffectSend.set_value(instrument->EffectSend);
1163        eFineTune.set_value(instrument->FineTune);
1164        ePitchbendRange.set_value(instrument->PitchbendRange);
1165        ePianoReleaseMode.set_value(instrument->PianoReleaseMode);
1166        eDimensionKeyRangeLow.set_value(instrument->DimensionKeyRange.low);
1167        eDimensionKeyRangeHigh.set_value(instrument->DimensionKeyRange.high);
1168        update_model--;
1169  }  }
1170    
1171  sigc::signal<void> InstrumentProps::signal_instrument_changed()  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
1172  {  {
1173      return instrument_changed;      return instrument_changed;
1174  }  }
# Line 826  void MainWindow::file_changed() Line 1181  void MainWindow::file_changed()
1181      }      }
1182  }  }
1183    
1184  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
1185  {  {
1186      file = 0;      file = 0;
1187        set_file_is_shared(isSharedInstrument);
1188    
1189      this->filename = filename ? filename : _("Unsaved Gig File");      this->filename = filename ? filename : _("Unsaved Gig File");
1190      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 1247  void MainWindow::load_gig(gig::File* gig
1247    
1248  void MainWindow::show_instr_props()  void MainWindow::show_instr_props()
1249  {  {
1250      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      gig::Instrument* instrument = get_instrument();
1251      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      if (instrument)
     if (it)  
1252      {      {
1253          Gtk::TreeModel::Row row = *it;          instrumentProps.set_instrument(instrument);
1254          if (row[m_Columns.m_col_instr])          instrumentProps.show();
1255          {          instrumentProps.deiconify();
1256              instrumentProps.set_instrument(row[m_Columns.m_col_instr]);      }
1257              instrumentProps.show();  }
1258              instrumentProps.deiconify();  
1259          }  void MainWindow::on_action_view_status_bar() {
1260        Gtk::CheckMenuItem* item =
1261            dynamic_cast<Gtk::CheckMenuItem*>(uiManager->get_widget("/MenuBar/MenuView/Statusbar"));
1262        if (!item) {
1263            std::cerr << "/MenuBar/MenuView/Statusbar == NULL\n";
1264            return;
1265      }      }
1266        if (item->get_active()) m_StatusBar.show();
1267        else                    m_StatusBar.hide();
1268  }  }
1269    
1270  void MainWindow::on_button_release(GdkEventButton* button)  void MainWindow::on_button_release(GdkEventButton* button)
# Line 962  void MainWindow::on_action_add_instrumen Line 1324  void MainWindow::on_action_add_instrumen
1324    
1325  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1326      if (!file) return;      if (!file) return;
1327        if (file_is_shared) {
1328            Gtk::MessageDialog msg(
1329                *this,
1330                 _("You cannot delete an instrument from this file, since it's "
1331                   "currently used by the sampler."),
1332                 false, Gtk::MESSAGE_INFO
1333            );
1334            msg.run();
1335            return;
1336        }
1337    
1338      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1339      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1340      if (it) {      if (it) {
# Line 1027  void MainWindow::on_action_add_sample() Line 1400  void MainWindow::on_action_add_sample()
1400      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1401      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1402      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1403      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1404          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1405          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1406          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 1042  void MainWindow::on_action_add_sample() Line 1415  void MainWindow::on_action_add_sample()
1415      allpassfilter.set_name("All Files");      allpassfilter.set_name("All Files");
1416      dialog.add_filter(soundfilter);      dialog.add_filter(soundfilter);
1417      dialog.add_filter(allpassfilter);      dialog.add_filter(allpassfilter);
1418        if (current_sample_dir != "") {
1419            dialog.set_current_folder(current_sample_dir);
1420        }
1421      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
1422            current_sample_dir = dialog.get_current_folder();
1423          Glib::ustring error_files;          Glib::ustring error_files;
1424          Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames();          Glib::SListHandle<Glib::ustring> filenames = dialog.get_filenames();
1425          for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin();          for (Glib::SListHandle<Glib::ustring>::iterator iter = filenames.begin();
# Line 1057  void MainWindow::on_action_add_sample() Line 1434  void MainWindow::on_action_add_sample()
1434                  int bitdepth;                  int bitdepth;
1435                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1436                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1437                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1438                        case SF_FORMAT_PCM_U8:
1439                          bitdepth = 16;                          bitdepth = 16;
1440                          break;                          break;
1441                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1442                      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;  
1443                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1444                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1445                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1446                          break;                          break;
1447                      default:                      default:
1448                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 1084  void MainWindow::on_action_add_sample() Line 1451  void MainWindow::on_action_add_sample()
1451                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1452                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1453                  // file name without path                  // file name without path
1454                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1455                    // remove file extension if there is one
1456                    for (int i = 0; supportedFileTypes[i]; i++) {
1457                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1458                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1459                            break;
1460                        }
1461                    }
1462                    sample->pInfo->Name = filename;
1463                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1464                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1465                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1466                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1467                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1468                    sample->BlockAlign = sample->FrameSize;
1469                    sample->SamplesTotal = info.frames;
1470    
1471                    SF_INSTRUMENT instrument;
1472                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1473                                   &instrument, sizeof(instrument)) != SF_FALSE)
1474                    {
1475                        sample->MIDIUnityNote = instrument.basenote;
1476    
1477    #if HAVE_SF_INSTRUMENT_LOOPS
1478                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1479                            sample->Loops = 1;
1480    
1481                            switch (instrument.loops[0].mode) {
1482                            case SF_LOOP_FORWARD:
1483                                sample->LoopType = gig::loop_type_normal;
1484                                break;
1485                            case SF_LOOP_BACKWARD:
1486                                sample->LoopType = gig::loop_type_backward;
1487                                break;
1488                            case SF_LOOP_ALTERNATING:
1489                                sample->LoopType = gig::loop_type_bidirectional;
1490                                break;
1491                            }
1492                            sample->LoopStart = instrument.loops[0].start;
1493                            sample->LoopEnd = instrument.loops[0].end;
1494                            sample->LoopPlayCount = instrument.loops[0].count;
1495                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1496                        }
1497    #endif
1498                    }
1499    
1500                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1501                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1502                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1104  void MainWindow::on_action_add_sample() Line 1512  void MainWindow::on_action_add_sample()
1512                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1513                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1514                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1515                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1516                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1517                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1518                  // close sound file                  // close sound file
# Line 1117  void MainWindow::on_action_add_sample() Line 1525  void MainWindow::on_action_add_sample()
1525          }          }
1526          // 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
1527          if (error_files.size()) {          if (error_files.size()) {
1528              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;
1529                Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1530                msg.run();
1531            }
1532        }
1533    }
1534    
1535    void MainWindow::on_action_replace_all_samples_in_all_groups()
1536    {
1537        if (!file) return;
1538        Gtk::FileChooserDialog dialog(*this, _("Select Folder"),
1539                                      Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
1540        Gtk::Label description(
1541            _("This is a very specific function. It tries to replace all samples "
1542              "in the current gig file by samples located in the directory chosen "
1543              "by you above.\n\n"
1544              "It works like this: For each sample in the gig file it tries to "
1545              "find a sample file in the selected directory with the same name as "
1546              "the sample in the gig file. Optionally you can add a filename "
1547              "postfix below, which will be added to the filename expected to be "
1548              "found. That is, assume you have a gig file with a sample called "
1549              "'Snare', if you enter '.wav' below (like it's done by default), it "
1550              "assumes to find a sample file called 'Snare.wav' and will replace "
1551              "the sample in the gig file accordingly. If you don't need such a "
1552              "postfix, blank the field below. Any gig sample where no "
1553              "appropriate sample file could be found, will be reported and left "
1554              "untouched.\n\n")
1555        );
1556        description.set_line_wrap(true);
1557        Gtk::HBox entryArea;
1558        Gtk::Label entryLabel( _("Add Filename Extension: "), Gtk::ALIGN_RIGHT);
1559        Gtk::Entry postfixEntryBox;
1560        postfixEntryBox.set_text(".wav");
1561        entryArea.pack_start(entryLabel);
1562        entryArea.pack_start(postfixEntryBox);
1563        dialog.get_vbox()->pack_start(description, Gtk::PACK_SHRINK);
1564        dialog.get_vbox()->pack_start(entryArea, Gtk::PACK_SHRINK);
1565        description.show();
1566        entryLabel.show();
1567        postfixEntryBox.show();
1568        entryArea.show();
1569        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1570        dialog.add_button(_("Select"), Gtk::RESPONSE_OK);
1571        dialog.set_select_multiple(false);
1572        if (current_sample_dir != "") {
1573            dialog.set_current_folder(current_sample_dir);
1574        }
1575        // fix label width (because Gtk by design doesn't
1576        // know anything about the parent's size)
1577    #if 0 //FIXME: doesn't work
1578        int dialogW, dialogH, labelW, labelH;
1579        dialog.get_size_request(dialogW, dialogH);
1580        description.get_size_request(labelW, labelH);
1581        std::cout << "dialog(" << dialogW << "," << dialogH << ")\nlabel(" << labelW << "," << labelH << ")\n" << std::flush;
1582        description.set_size_request(dialogW, labelH);
1583    #endif
1584        if (dialog.run() == Gtk::RESPONSE_OK)
1585        {
1586            current_sample_dir = dialog.get_current_folder();
1587            Glib::ustring error_files;
1588            Glib::ustring folder = dialog.get_filename();
1589            for (gig::Sample* sample = file->GetFirstSample();
1590                 sample; sample = file->GetNextSample())
1591            {
1592                std::string filename =
1593                    folder + G_DIR_SEPARATOR_S + sample->pInfo->Name +
1594                    postfixEntryBox.get_text().raw();
1595                SF_INFO info;
1596                info.format = 0;
1597                SNDFILE* hFile = sf_open(filename.c_str(), SFM_READ, &info);
1598                try
1599                {
1600                    if (!hFile) throw std::string("could not open file");
1601                    int bitdepth;
1602                    switch (info.format & 0xff) {
1603                        case SF_FORMAT_PCM_S8:
1604                        case SF_FORMAT_PCM_16:
1605                        case SF_FORMAT_PCM_U8:
1606                            bitdepth = 16;
1607                            break;
1608                        case SF_FORMAT_PCM_24:
1609                        case SF_FORMAT_PCM_32:
1610                        case SF_FORMAT_FLOAT:
1611                        case SF_FORMAT_DOUBLE:
1612                            bitdepth = 24;
1613                            break;
1614                        default:
1615                            sf_close(hFile);
1616                            throw std::string("format not supported");
1617                    }
1618                    SampleImportItem sched_item;
1619                    sched_item.gig_sample  = sample;
1620                    sched_item.sample_path = filename;
1621                    m_SampleImportQueue.push_back(sched_item);
1622                    sf_close(hFile);
1623                    file_changed();
1624                }
1625                catch (std::string what)
1626                {
1627                    if (error_files.size()) error_files += "\n";
1628                        error_files += filename += " (" + what + ")";
1629                }
1630            }
1631            // show error message box when some file(s) could not be opened / added
1632            if (error_files.size()) {
1633                Glib::ustring txt =
1634                    _("Could not replace the following sample(s):\n") + error_files;
1635              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1636              msg.run();              msg.run();
1637          }          }
# Line 1143  void MainWindow::on_action_remove_sample Line 1657  void MainWindow::on_action_remove_sample
1657                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1658                      members.push_back(pSample);                      members.push_back(pSample);
1659                  }                  }
1660                    // notify everybody that we're going to remove these samples
1661                    samples_to_be_removed_signal.emit(members);
1662                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1663                  // samples that belong to the group                  // samples that belong to the group
1664                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1665                    // notify that we're done with removal
1666                    samples_removed_signal.emit();
1667                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1668                  // them from the import queue                  // them from the import queue
1669                  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 1680  void MainWindow::on_action_remove_sample
1680                  }                  }
1681                  file_changed();                  file_changed();
1682              } else if (sample) {              } else if (sample) {
1683                    // notify everybody that we're going to remove this sample
1684                    std::list<gig::Sample*> lsamples;
1685                    lsamples.push_back(sample);
1686                    samples_to_be_removed_signal.emit(lsamples);
1687                  // remove sample from the .gig file                  // remove sample from the .gig file
1688                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1689                    // notify that we're done with removal
1690                    samples_removed_signal.emit();
1691                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1692                  // the import queue                  // the import queue
1693                  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 1699  void MainWindow::on_action_remove_sample
1699                          break;                          break;
1700                      }                      }
1701                  }                  }
1702                    dimreg_changed();
1703                  file_changed();                  file_changed();
1704              }              }
1705              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1706              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1707          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1708                // pretend we're done with removal (i.e. to avoid dead locks)
1709                samples_removed_signal.emit();
1710                // show error message
1711              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1712              msg.run();              msg.run();
1713          }          }
1714      }      }
1715  }  }
1716    
1717    // For some reason drag_data_get gets called two times for each
1718    // drag'n'drop (at least when target is an Entry). This work-around
1719    // makes sure the code in drag_data_get and drop_drag_data_received is
1720    // only executed once, as drag_begin only gets called once.
1721    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1722    {
1723        first_call_to_drag_data_get = true;
1724    }
1725    
1726  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>&,
1727                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1728  {  {
1729        if (!first_call_to_drag_data_get) return;
1730        first_call_to_drag_data_get = false;
1731    
1732      // get selected sample      // get selected sample
1733      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1734      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 1746  void MainWindow::on_sample_label_drop_dr
1746      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1747      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1748  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1749      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1750    
1751      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1752          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1753              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1754              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1755              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1756                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1757              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1758              context->drop_reply(true, time);  
1759              file_changed();          // notify everybody that we're going to alter the region
1760              return;          gig::Region* region = m_RegionChooser.get_region();
1761            region_to_be_changed_signal.emit(region);
1762    
1763            // find the samplechannel dimension
1764            gig::dimension_def_t* stereo_dimension = 0;
1765            for (int i = 0 ; i < region->Dimensions ; i++) {
1766                if (region->pDimensionDefinitions[i].dimension ==
1767                    gig::dimension_samplechannel) {
1768                    stereo_dimension = &region->pDimensionDefinitions[i];
1769                    break;
1770                }
1771            }
1772            bool channels_changed = false;
1773            if (sample->Channels == 1 && stereo_dimension) {
1774                // remove the samplechannel dimension
1775                region->DeleteDimension(stereo_dimension);
1776                channels_changed = true;
1777                region_changed();
1778            }
1779            dimreg_edit.set_sample(sample);
1780    
1781            if (sample->Channels == 2 && !stereo_dimension) {
1782                // add samplechannel dimension
1783                gig::dimension_def_t dim;
1784                dim.dimension = gig::dimension_samplechannel;
1785                dim.bits = 1;
1786                dim.zones = 2;
1787                region->AddDimension(&dim);
1788                channels_changed = true;
1789                region_changed();
1790          }          }
1791            if (channels_changed) {
1792                // unmap all samples with wrong number of channels
1793                // TODO: maybe there should be a warning dialog for this
1794                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1795                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1796                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1797                        gig::Sample* oldref = d->pSample;
1798                        d->pSample = NULL;
1799                        sample_ref_changed_signal.emit(oldref, NULL);
1800                    }
1801                }
1802            }
1803    
1804            // notify we're done with altering
1805            region_changed_signal.emit(region);
1806    
1807            file_changed();
1808    
1809            return;
1810      }      }
1811      // drop failed      // drop failed
1812      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1258  void MainWindow::instrument_name_changed Line 1845  void MainWindow::instrument_name_changed
1845          file_changed();          file_changed();
1846      }      }
1847  }  }
1848    
1849    void MainWindow::set_file_is_shared(bool b) {
1850        this->file_is_shared = b;
1851    
1852        if (file_is_shared) {
1853            m_AttachedStateLabel.set_label(_("live-mode"));
1854            m_AttachedStateImage.set(
1855                Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm)
1856            );
1857        } else {
1858            m_AttachedStateLabel.set_label(_("stand-alone"));
1859            m_AttachedStateImage.set(
1860                Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm)
1861            );
1862        }
1863    }
1864    
1865    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1866        return file_structure_to_be_changed_signal;
1867    }
1868    
1869    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1870        return file_structure_changed_signal;
1871    }
1872    
1873    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1874        return samples_to_be_removed_signal;
1875    }
1876    
1877    sigc::signal<void>& MainWindow::signal_samples_removed() {
1878        return samples_removed_signal;
1879    }
1880    
1881    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1882        return region_to_be_changed_signal;
1883    }
1884    
1885    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1886        return region_changed_signal;
1887    }
1888    
1889    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1890        return sample_ref_changed_signal;
1891    }
1892    
1893    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1894        return dimreg_to_be_changed_signal;
1895    }
1896    
1897    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1898        return dimreg_changed_signal;
1899    }
1900    
1901    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_note_on() {
1902        return note_on_signal;
1903    }
1904    
1905    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_note_off() {
1906        return note_off_signal;
1907    }
1908    
1909    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_keyboard_key_hit() {
1910        return m_RegionChooser.signal_keyboard_key_hit();
1911    }
1912    
1913    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_keyboard_key_released() {
1914        return m_RegionChooser.signal_keyboard_key_released();
1915    }

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

  ViewVC Help
Powered by ViewVC