/[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 1225 by schoenebeck, Sun Jun 10 10:56:11 2007 UTC revision 1460 by persson, Sat Oct 27 12:28:33 2007 UTC
# 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  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6  #include "global.h"
30    
31    #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 99  MainWindow::MainWindow() Line 114  MainWindow::MainWindow()
114      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);
115      action->property_label() = action->property_label() + "...";      action->property_label() = action->property_label() + "...";
116      actionGroup->add(action,      actionGroup->add(action,
117                       *(new Gtk::AccelKey("<shift><control>s")),                       Gtk::AccelKey("<shift><control>s"),
118                       sigc::mem_fun(                       sigc::mem_fun(
119                           *this, &MainWindow::on_action_file_save_as)                           *this, &MainWindow::on_action_file_save_as));
         );  
120      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
121                                           Gtk::Stock::PROPERTIES),                                           Gtk::Stock::PROPERTIES),
122                       sigc::mem_fun(                       sigc::mem_fun(
# Line 113  MainWindow::MainWindow() Line 127  MainWindow::MainWindow()
127                           *this, &MainWindow::show_instr_props));                           *this, &MainWindow::show_instr_props));
128      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
129                       sigc::mem_fun(                       sigc::mem_fun(
130                           *this, &MainWindow::hide));                           *this, &MainWindow::on_action_quit));
131      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
132    
133        actionGroup->add(Gtk::Action::create("MenuView", _("_View")));
134        Glib::RefPtr<Gtk::ToggleAction> toggle_action =
135            Gtk::ToggleAction::create("Statusbar", _("_Statusbar"));
136        toggle_action->set_active(true);
137        actionGroup->add(toggle_action,
138                         sigc::mem_fun(
139                             *this, &MainWindow::on_action_view_status_bar));
140    
141      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
142      actionGroup->add(Gtk::Action::create("MenuHelp",      actionGroup->add(Gtk::Action::create("MenuHelp",
143                                           action->property_label()));                                           action->property_label()));
# Line 153  MainWindow::MainWindow() Line 175  MainWindow::MainWindow()
175    
176      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
177      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
178      // add_accel_group(uiManager->get_accel_group());      add_accel_group(uiManager->get_accel_group());
179    
180      Glib::ustring ui_info =      Glib::ustring ui_info =
181          "<ui>"          "<ui>"
# Line 171  MainWindow::MainWindow() Line 193  MainWindow::MainWindow()
193          "    </menu>"          "    </menu>"
194          "    <menu action='MenuInstrument'>"          "    <menu action='MenuInstrument'>"
195          "    </menu>"          "    </menu>"
196            "    <menu action='MenuView'>"
197            "      <menuitem action='Statusbar'/>"
198            "    </menu>"
199  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
200          "    <menu action='MenuHelp'>"          "    <menu action='MenuHelp'>"
201          "      <menuitem action='About'/>"          "      <menuitem action='About'/>"
# Line 200  MainWindow::MainWindow() Line 225  MainWindow::MainWindow()
225      m_VBox.pack_start(m_HPaned);      m_VBox.pack_start(m_HPaned);
226      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
227      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
228        m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK);
229    
230      m_RegionChooser.signal_sel_changed().connect(      // Status Bar:
231        m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK);
232        m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK);
233        m_StatusBar.show();
234    
235        m_RegionChooser.signal_region_selected().connect(
236          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
237      m_DimRegionChooser.signal_sel_changed().connect(      m_DimRegionChooser.signal_dimregion_selected().connect(
238          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );
239    
240    
# Line 235  MainWindow::MainWindow() Line 266  MainWindow::MainWindow()
266      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
267      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
268      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
269        m_TreeViewSamples.signal_drag_begin().connect(
270            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
271        );
272      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
273          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
274      );      );
# Line 242  MainWindow::MainWindow() Line 276  MainWindow::MainWindow()
276      dimreg_edit.wSample->signal_drag_data_received().connect(      dimreg_edit.wSample->signal_drag_data_received().connect(
277          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
278      );      );
279        dimreg_edit.signal_dimreg_changed().connect(
280            sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
281        m_RegionChooser.signal_instrument_changed().connect(
282            sigc::mem_fun(*this, &MainWindow::file_changed));
283        m_DimRegionChooser.signal_region_changed().connect(
284            sigc::mem_fun(*this, &MainWindow::file_changed));
285        instrumentProps.signal_instrument_changed().connect(
286            sigc::mem_fun(*this, &MainWindow::file_changed));
287    
288        dimreg_edit.signal_dimreg_to_be_changed().connect(
289            dimreg_to_be_changed_signal.make_slot());
290        dimreg_edit.signal_dimreg_changed().connect(
291            dimreg_changed_signal.make_slot());
292        dimreg_edit.signal_sample_ref_changed().connect(
293            sample_ref_changed_signal.make_slot());
294    
295        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
296            sigc::hide(
297                sigc::bind(
298                    file_structure_to_be_changed_signal.make_slot(),
299                    sigc::ref(this->file)
300                )
301            )
302        );
303        m_RegionChooser.signal_instrument_struct_changed().connect(
304            sigc::hide(
305                sigc::bind(
306                    file_structure_changed_signal.make_slot(),
307                    sigc::ref(this->file)
308                )
309            )
310        );
311        m_RegionChooser.signal_region_to_be_changed().connect(
312            region_to_be_changed_signal.make_slot());
313        m_RegionChooser.signal_region_changed_signal().connect(
314            region_changed_signal.make_slot());
315    
316      file = 0;      file = 0;
317        file_is_changed = false;
318        set_file_is_shared(false);
319    
320      show_all_children();      show_all_children();
321    
322        // start with a new gig file by default
323        on_action_file_new();
324  }  }
325    
326  MainWindow::~MainWindow()  MainWindow::~MainWindow()
327  {  {
328  }  }
329    
330    bool MainWindow::on_delete_event(GdkEventAny* event)
331    {
332        return !file_is_shared && file_is_changed && !close_confirmation_dialog();
333    }
334    
335    void MainWindow::on_action_quit()
336    {
337        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
338        hide();
339    }
340    
341  void MainWindow::region_changed()  void MainWindow::region_changed()
342  {  {
343      m_DimRegionChooser.set_region(m_RegionChooser.get_region());      m_DimRegionChooser.set_region(m_RegionChooser.get_region());
# Line 362  void MainWindow::__clear() { Line 448  void MainWindow::__clear() {
448      m_refTreeModel->clear();      m_refTreeModel->clear();
449      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
450      // free libgig's gig::File instance      // free libgig's gig::File instance
451      if (file) {      if (file && !file_is_shared) delete file;
452          delete file;      file = NULL;
453          file = NULL;      set_file_is_shared(false);
     }  
454  }  }
455    
456  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
457  {  {
458        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
459    
460        if (file_is_shared && !leaving_shared_mode_dialog()) return;
461    
462      // clear all GUI elements      // clear all GUI elements
463      __clear();      __clear();
464      // create a new .gig file (virtually yet)      // create a new .gig file (virtually yet)
# Line 378  void MainWindow::on_action_file_new() Line 467  void MainWindow::on_action_file_new()
467      gig::Instrument* pInstrument = pFile->AddInstrument();      gig::Instrument* pInstrument = pFile->AddInstrument();
468      pInstrument->pInfo->Name = "Unnamed Instrument";      pInstrument->pInfo->Name = "Unnamed Instrument";
469      // update GUI with that new gig::File      // update GUI with that new gig::File
470      load_gig(pFile, NULL /*no file name yet*/);      load_gig(pFile, 0 /*no file name yet*/);
471    }
472    
473    bool MainWindow::close_confirmation_dialog()
474    {
475        gchar* msg = g_strdup_printf(_("Save changes to \"%s\" before closing?"),
476                                     Glib::filename_display_basename(filename).c_str());
477        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
478        g_free(msg);
479    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
480        dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));
481    #endif
482        dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
483        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
484        dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);
485        dialog.set_default_response(Gtk::RESPONSE_YES);
486        int response = dialog.run();
487        dialog.hide();
488        if (response == Gtk::RESPONSE_YES) return file_save();
489        return response != Gtk::RESPONSE_CANCEL;
490    }
491    
492    bool MainWindow::leaving_shared_mode_dialog() {
493        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
494        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
495    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
496        dialog.set_secondary_text(
497            _("If you proceed to work on another instrument file, it won't be "
498              "used by the sampler until you tell the sampler explicitly to "
499              "load it.")
500       );
501    #endif
502        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
503        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
504        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
505        int response = dialog.run();
506        dialog.hide();
507        return response == Gtk::RESPONSE_YES;
508  }  }
509    
510  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
511  {  {
512        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
513    
514        if (file_is_shared && !leaving_shared_mode_dialog()) return;
515    
516      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
517      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
518      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
519        dialog.set_default_response(Gtk::RESPONSE_OK);
520      Gtk::FileFilter filter;      Gtk::FileFilter filter;
521      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
522      dialog.set_filter(filter);      dialog.set_filter(filter);
523        if (current_dir != "") {
524            dialog.set_current_folder(current_dir);
525        }
526      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
527          printf("filename=%s\n", dialog.get_filename().c_str());          std::string filename = dialog.get_filename();
528          __clear();          printf("filename=%s\n", filename.c_str());
529          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
530          load_file(dialog.get_filename().c_str());          load_file(filename.c_str());
531            current_dir = Glib::path_get_dirname(filename);
532      }      }
533  }  }
534    
535  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
536  {  {
537        __clear();
538      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
539      load_dialog->show_all();      load_dialog->show_all();
540      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 416  void MainWindow::load_instrument(gig::In Line 552  void MainWindow::load_instrument(gig::In
552          msg.run();          msg.run();
553          Gtk::Main::quit();          Gtk::Main::quit();
554      }      }
555        // clear all GUI elements
556        __clear();
557        // load the instrument
558      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
559      load_gig(pFile, NULL /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
560      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
561  }  }
562    
# Line 436  void MainWindow::on_loader_finished() Line 575  void MainWindow::on_loader_finished()
575    
576  void MainWindow::on_action_file_save()  void MainWindow::on_action_file_save()
577  {  {
578      if (!file) return;      file_save();
579    }
580    
581    bool MainWindow::check_if_savable()
582    {
583        if (!file) return false;
584    
585        if (!file->GetFirstSample()) {
586            Gtk::MessageDialog(*this, _("The file could not be saved "
587                                        "because it contains no samples"),
588                               false, Gtk::MESSAGE_ERROR).run();
589            return false;
590        }
591    
592        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
593             instrument = file->GetNextInstrument()) {
594            if (!instrument->GetFirstRegion()) {
595                Gtk::MessageDialog(*this, _("The file could not be saved "
596                                            "because there are instruments "
597                                            "that have no regions"),
598                                   false, Gtk::MESSAGE_ERROR).run();
599                return false;
600            }
601        }
602        return true;
603    }
604    
605    bool MainWindow::file_save()
606    {
607        if (!check_if_savable()) return false;
608        if (!file_is_shared && !file_has_name) return file_save_as();
609    
610      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
611        file_structure_to_be_changed_signal.emit(this->file);
612      try {      try {
613          file->Save();          file->Save();
614            if (file_is_changed) {
615                set_title(get_title().substr(1));
616                file_is_changed = false;
617            }
618      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
619          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
620            Glib::ustring txt = _("Could not save file: ") + e.Message;
621          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
622          msg.run();          msg.run();
623          return;          return false;
624      }      }
625      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
626      __import_queued_samples();      __import_queued_samples();
627        file_structure_changed_signal.emit(this->file);
628        return true;
629  }  }
630    
631  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
632  {  {
633      if (!file) return;      if (!check_if_savable()) return;
634      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);      file_save_as();
635    }
636    
637    bool MainWindow::file_save_as()
638    {
639        Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
640      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
641      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
642        dialog.set_default_response(Gtk::RESPONSE_OK);
643    
644    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 2
645        dialog.set_do_overwrite_confirmation();
646        // TODO: an overwrite dialog for gtkmm < 2.8
647    #endif
648      Gtk::FileFilter filter;      Gtk::FileFilter filter;
649      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
650      dialog.set_filter(filter);      dialog.set_filter(filter);
651    
652        if (Glib::path_is_absolute(filename)) {
653            dialog.set_filename(filename);
654        } else if (current_dir != "") {
655            dialog.set_current_folder(current_dir);
656        }
657        dialog.set_current_name(Glib::filename_display_basename(filename));
658    
659      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
660          printf("filename=%s\n", dialog.get_filename().c_str());          file_structure_to_be_changed_signal.emit(this->file);
661          try {          try {
662              file->Save(dialog.get_filename());              std::string filename = dialog.get_filename();
663                if (!Glib::str_has_suffix(filename, ".gig")) {
664                    filename += ".gig";
665                }
666                printf("filename=%s\n", filename.c_str());
667                file->Save(filename);
668                this->filename = filename;
669                current_dir = Glib::path_get_dirname(filename);
670                set_title(Glib::filename_display_basename(filename));
671                file_has_name = true;
672                file_is_changed = false;
673          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
674              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
675                Glib::ustring txt = _("Could not save file: ") + e.Message;
676              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
677              msg.run();              msg.run();
678              return;              return false;
679          }          }
680          __import_queued_samples();          __import_queued_samples();
681            file_structure_changed_signal.emit(this->file);
682            return true;
683      }      }
684        return false;
685  }  }
686    
687  // actually write the sample(s)' data to the gig file  // actually write the sample(s)' data to the gig file
# Line 490  void MainWindow::__import_queued_samples Line 701  void MainWindow::__import_queued_samples
701              int bitdepth;              int bitdepth;
702              switch (info.format & 0xff) {              switch (info.format & 0xff) {
703                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
704                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
705                    case SF_FORMAT_PCM_U8:
706                      bitdepth = 16;                      bitdepth = 16;
707                      break;                      break;
708                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
709                  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;  
710                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
711                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
712                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
713                      break;                      break;
714                  default:                  default:
715                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
716                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
717              }              }
718              // allocate appropriate copy buffer (TODO: for now we copy  
719              // 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;  
720              switch (bitdepth) {              switch (bitdepth) {
721                  case 16:                  case 16: {
722                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
723                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
724                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
725                            // libsndfile does the conversion for us (if needed)
726                            int n = sf_readf_short(hFile, buffer, bufsize);
727                            // write from buffer directly (physically) into .gig file
728                            iter->gig_sample->Write(buffer, n);
729                            cnt -= n;
730                        }
731                        delete[] buffer;
732                      break;                      break;
733                  case 32:                  }
734                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
735                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
736                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
737                        sf_count_t cnt = info.frames;
738                        while (cnt) {
739                            // libsndfile returns 32 bits, convert to 24
740                            int n = sf_readf_int(hFile, srcbuf, bufsize);
741                            int j = 0;
742                            for (int i = 0 ; i < n * info.channels ; i++) {
743                                dstbuf[j++] = srcbuf[i] >> 8;
744                                dstbuf[j++] = srcbuf[i] >> 16;
745                                dstbuf[j++] = srcbuf[i] >> 24;
746                            }
747                            // write from buffer directly (physically) into .gig file
748                            iter->gig_sample->Write(dstbuf, n);
749                            cnt -= n;
750                        }
751                        delete[] srcbuf;
752                        delete[] dstbuf;
753                      break;                      break;
754                    }
755              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
756              // cleanup              // cleanup
757              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
758              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
759              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
760              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 549  void MainWindow::__import_queued_samples Line 769  void MainWindow::__import_queued_samples
769      }      }
770      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
771      if (error_files.size()) {      if (error_files.size()) {
772          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;
773          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
774          msg.run();          msg.run();
775      }      }
# Line 566  void MainWindow::on_action_help_about() Line 786  void MainWindow::on_action_help_about()
786  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
787      Gtk::AboutDialog dialog;      Gtk::AboutDialog dialog;
788      dialog.set_version(VERSION);      dialog.set_version(VERSION);
789        dialog.set_copyright("Copyright (C) 2006,2007 Andreas Persson");
790        dialog.set_comments(
791            "Released under the GNU General Public License.\n"
792            "\n"
793            "Please notice that this is still a very young instrument editor. "
794            "So better backup your Gigasampler files before editing them with "
795            "this application.\n"
796            "\n"
797            "Please report bugs to: http://bugs.linuxsampler.org"
798        );
799        dialog.set_website("http://www.linuxsampler.org");
800        dialog.set_website_label("http://www.linuxsampler.org");
801      dialog.run();      dialog.run();
802  #endif  #endif
803  }  }
# Line 626  void PropDialog::set_info(DLS::Info* inf Line 858  void PropDialog::set_info(DLS::Info* inf
858      entry[15].set_text(info->Subject);      entry[15].set_text(info->Subject);
859  }  }
860    
861    void InstrumentProps::set_IsDrum(bool value)
862    {
863        instrument->IsDrum = value;
864    }
865    
866    void InstrumentProps::set_MIDIBank(uint16_t value)
867    {
868        instrument->MIDIBank = value;
869    }
870    
871    void InstrumentProps::set_MIDIProgram(uint32_t value)
872    {
873        instrument->MIDIProgram = value;
874    }
875    
876    void InstrumentProps::set_DimensionKeyRange_low(uint8_t value)
877    {
878        instrument->DimensionKeyRange.low = value;
879        if (value > instrument->DimensionKeyRange.high) {
880            eDimensionKeyRangeHigh.set_value(value);
881        }
882    }
883    
884    void InstrumentProps::set_DimensionKeyRange_high(uint8_t value)
885    {
886        instrument->DimensionKeyRange.high = value;
887        if (value < instrument->DimensionKeyRange.low) {
888            eDimensionKeyRangeLow.set_value(value);
889        }
890    }
891    
892    void InstrumentProps::add_prop(BoolEntry& boolentry)
893    {
894        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
895                     Gtk::FILL, Gtk::SHRINK);
896        rowno++;
897    }
898    
899    void InstrumentProps::add_prop(BoolEntryPlus6& boolentry)
900    {
901        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
902                     Gtk::FILL, Gtk::SHRINK);
903        rowno++;
904    }
905    
906  void InstrumentProps::add_prop(LabelWidget& prop)  void InstrumentProps::add_prop(LabelWidget& prop)
907  {  {
908      table.attach(prop.label, 0, 1, rowno, rowno + 1,      table.attach(prop.label, 0, 1, rowno, rowno + 1,
# Line 639  InstrumentProps::InstrumentProps() Line 916  InstrumentProps::InstrumentProps()
916      : table(2,1),      : table(2,1),
917        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
918        eName("Name"),        eName("Name"),
919        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
920        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
921        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
922        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
923        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
924        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
925        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
926        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
927        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
928        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Dimension key range low"),
929        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Dimension key range high"),
930          update_model(0)
931  {  {
932      set_title("Instrument properties");      set_title("Instrument properties");
933    
934        connect(eIsDrum, &InstrumentProps::set_IsDrum);
935        connect(eMIDIBank, &InstrumentProps::set_MIDIBank);
936        connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram);
937        connect(eAttenuation, &gig::Instrument::Attenuation);
938        connect(eGainPlus6, &gig::Instrument::Attenuation);
939        connect(eEffectSend, &gig::Instrument::EffectSend);
940        connect(eFineTune, &gig::Instrument::FineTune);
941        connect(ePitchbendRange, &gig::Instrument::PitchbendRange);
942        connect(ePianoReleaseMode, &gig::Instrument::PianoReleaseMode);
943        connect(eDimensionKeyRangeLow,
944                &InstrumentProps::set_DimensionKeyRange_low);
945        connect(eDimensionKeyRangeHigh,
946                &InstrumentProps::set_DimensionKeyRange_high);
947    
948      rowno = 0;      rowno = 0;
949      table.set_col_spacings(5);      table.set_col_spacings(5);
950    
# Line 669  InstrumentProps::InstrumentProps() Line 961  InstrumentProps::InstrumentProps()
961      add_prop(eDimensionKeyRangeLow);      add_prop(eDimensionKeyRangeLow);
962      add_prop(eDimensionKeyRangeHigh);      add_prop(eDimensionKeyRangeHigh);
963    
     eDimensionKeyRangeLow.signal_value_changed().connect(  
         sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));  
     eDimensionKeyRangeHigh.signal_value_changed().connect(  
         sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));  
   
964      add(vbox);      add(vbox);
965      table.set_border_width(5);      table.set_border_width(5);
966      vbox.pack_start(table);      vbox.pack_start(table);
# Line 696  InstrumentProps::InstrumentProps() Line 983  InstrumentProps::InstrumentProps()
983    
984  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
985  {  {
986      update_gui = false;      this->instrument = instrument;
987    
988        update_model++;
989      eName.set_ptr(&instrument->pInfo->Name);      eName.set_ptr(&instrument->pInfo->Name);
990      eIsDrum.set_ptr(&instrument->IsDrum);      eIsDrum.set_value(instrument->IsDrum);
991      eMIDIBank.set_ptr(&instrument->MIDIBank);      eMIDIBank.set_value(instrument->MIDIBank);
992      eMIDIProgram.set_ptr(&instrument->MIDIProgram);      eMIDIProgram.set_value(instrument->MIDIProgram);
993      eAttenuation.set_ptr(&instrument->Attenuation);      eAttenuation.set_value(instrument->Attenuation);
994      eGainPlus6.set_ptr(&instrument->Attenuation);      eGainPlus6.set_value(instrument->Attenuation);
995      eEffectSend.set_ptr(&instrument->EffectSend);      eEffectSend.set_value(instrument->EffectSend);
996      eFineTune.set_ptr(&instrument->FineTune);      eFineTune.set_value(instrument->FineTune);
997      ePitchbendRange.set_ptr(&instrument->PitchbendRange);      ePitchbendRange.set_value(instrument->PitchbendRange);
998      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);      ePianoReleaseMode.set_value(instrument->PianoReleaseMode);
999      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);      eDimensionKeyRangeLow.set_value(instrument->DimensionKeyRange.low);
1000      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);      eDimensionKeyRangeHigh.set_value(instrument->DimensionKeyRange.high);
1001      update_gui = true;      update_model--;
1002  }  }
1003    
1004  void InstrumentProps::key_range_low_changed()  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
1005  {  {
1006      double l = eDimensionKeyRangeLow.get_value();      return instrument_changed;
     double h = eDimensionKeyRangeHigh.get_value();  
     if (h < l) eDimensionKeyRangeHigh.set_value(l);  
1007  }  }
1008    
1009  void InstrumentProps::key_range_high_changed()  void MainWindow::file_changed()
1010  {  {
1011      double l = eDimensionKeyRangeLow.get_value();      if (file && !file_is_changed) {
1012      double h = eDimensionKeyRangeHigh.get_value();          set_title("*" + get_title());
1013      if (h < l) eDimensionKeyRangeLow.set_value(h);          file_is_changed = true;
1014        }
1015  }  }
1016    
1017  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
1018  {  {
1019      file = gig;      file = 0;
1020        set_file_is_shared(isSharedInstrument);
1021    
1022      if (filename) {      this->filename = filename ? filename : _("Unsaved Gig File");
1023          const char *basename = strrchr(filename, '/');      set_title(Glib::filename_display_basename(this->filename));
1024          basename = basename ? basename + 1 : filename;      file_has_name = filename;
1025          set_title(basename);      file_is_changed = false;
     } else {  
         set_title("unnamed");  
     }  
1026    
1027      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
1028    
# Line 785  void MainWindow::load_gig(gig::File* gig Line 1071  void MainWindow::load_gig(gig::File* gig
1071          }          }
1072      }      }
1073    
1074        file = gig;
1075    
1076      // select the first instrument      // select the first instrument
1077      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
1078      tree_sel_ref->select(Gtk::TreePath("0"));      tree_sel_ref->select(Gtk::TreePath("0"));
# Line 806  void MainWindow::show_instr_props() Line 1094  void MainWindow::show_instr_props()
1094      }      }
1095  }  }
1096    
1097    void MainWindow::on_action_view_status_bar() {
1098        Gtk::CheckMenuItem* item =
1099            dynamic_cast<Gtk::CheckMenuItem*>(uiManager->get_widget("/MenuBar/MenuView/Statusbar"));
1100        if (!item) {
1101            std::cerr << "/MenuBar/MenuView/Statusbar == NULL\n";
1102            return;
1103        }
1104        if (item->get_active()) m_StatusBar.show();
1105        else                    m_StatusBar.hide();
1106    }
1107    
1108  void MainWindow::on_button_release(GdkEventButton* button)  void MainWindow::on_button_release(GdkEventButton* button)
1109  {  {
1110      if (button->type == GDK_2BUTTON_PRESS) {      if (button->type == GDK_2BUTTON_PRESS) {
# Line 858  void MainWindow::on_action_add_instrumen Line 1157  void MainWindow::on_action_add_instrumen
1157      Gtk::TreeModel::Row rowInstr = *iterInstr;      Gtk::TreeModel::Row rowInstr = *iterInstr;
1158      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
1159      rowInstr[m_Columns.m_col_instr] = instrument;      rowInstr[m_Columns.m_col_instr] = instrument;
1160        file_changed();
1161  }  }
1162    
1163  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1164      if (!file) return;      if (!file) return;
1165        if (file_is_shared) {
1166            Gtk::MessageDialog msg(
1167                *this,
1168                 _("You cannot delete an instrument from this file, since it's "
1169                   "currently used by the sampler."),
1170                 false, Gtk::MESSAGE_INFO
1171            );
1172            msg.run();
1173            return;
1174        }
1175    
1176      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1177      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1178      if (it) {      if (it) {
# Line 872  void MainWindow::on_action_remove_instru Line 1183  void MainWindow::on_action_remove_instru
1183              if (instr) file->DeleteInstrument(instr);              if (instr) file->DeleteInstrument(instr);
1184              // remove respective row from instruments tree view              // remove respective row from instruments tree view
1185              m_refTreeModel->erase(it);              m_refTreeModel->erase(it);
1186                file_changed();
1187          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1188              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1189              msg.run();              msg.run();
# Line 900  void MainWindow::on_action_add_group() { Line 1212  void MainWindow::on_action_add_group() {
1212      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1213      rowGroup[m_SamplesModel.m_col_sample] = NULL;      rowGroup[m_SamplesModel.m_col_sample] = NULL;
1214      rowGroup[m_SamplesModel.m_col_group] = group;      rowGroup[m_SamplesModel.m_col_group] = group;
1215        file_changed();
1216  }  }
1217    
1218  void MainWindow::on_action_add_sample() {  void MainWindow::on_action_add_sample() {
# Line 925  void MainWindow::on_action_add_sample() Line 1238  void MainWindow::on_action_add_sample()
1238      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1239      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1240      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1241      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1242          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1243          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1244          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 955  void MainWindow::on_action_add_sample() Line 1268  void MainWindow::on_action_add_sample()
1268                  int bitdepth;                  int bitdepth;
1269                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1270                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1271                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1272                        case SF_FORMAT_PCM_U8:
1273                          bitdepth = 16;                          bitdepth = 16;
1274                          break;                          break;
1275                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1276                      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;  
1277                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1278                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1279                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1280                          break;                          break;
1281                      default:                      default:
1282                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 982  void MainWindow::on_action_add_sample() Line 1285  void MainWindow::on_action_add_sample()
1285                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1286                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1287                  // file name without path                  // file name without path
1288                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1289                    // remove file extension if there is one
1290                    for (int i = 0; supportedFileTypes[i]; i++) {
1291                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1292                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1293                            break;
1294                        }
1295                    }
1296                    sample->pInfo->Name = filename;
1297                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1298                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1299                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1300                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1301                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1302                    sample->BlockAlign = sample->FrameSize;
1303                    sample->SamplesTotal = info.frames;
1304    
1305                    SF_INSTRUMENT instrument;
1306                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1307                                   &instrument, sizeof(instrument)) != SF_FALSE)
1308                    {
1309                        sample->MIDIUnityNote = instrument.basenote;
1310    
1311    #if HAVE_SF_INSTRUMENT_LOOPS
1312                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1313                            sample->Loops = 1;
1314    
1315                            switch (instrument.loops[0].mode) {
1316                            case SF_LOOP_FORWARD:
1317                                sample->LoopType = gig::loop_type_normal;
1318                                break;
1319                            case SF_LOOP_BACKWARD:
1320                                sample->LoopType = gig::loop_type_backward;
1321                                break;
1322                            case SF_LOOP_ALTERNATING:
1323                                sample->LoopType = gig::loop_type_bidirectional;
1324                                break;
1325                            }
1326                            sample->LoopStart = instrument.loops[0].start;
1327                            sample->LoopEnd = instrument.loops[0].end;
1328                            sample->LoopPlayCount = instrument.loops[0].count;
1329                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1330                        }
1331    #endif
1332                    }
1333    
1334                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1335                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1336                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1002  void MainWindow::on_action_add_sample() Line 1346  void MainWindow::on_action_add_sample()
1346                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1347                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1348                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1349                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1350                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1351                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1352                  // close sound file                  // close sound file
1353                  sf_close(hFile);                  sf_close(hFile);
1354                    file_changed();
1355              } catch (std::string what) { // remember the files that made trouble (and their cause)              } catch (std::string what) { // remember the files that made trouble (and their cause)
1356                  if (error_files.size()) error_files += "\n";                  if (error_files.size()) error_files += "\n";
1357                  error_files += *iter += " (" + what + ")";                  error_files += *iter += " (" + what + ")";
# Line 1014  void MainWindow::on_action_add_sample() Line 1359  void MainWindow::on_action_add_sample()
1359          }          }
1360          // 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
1361          if (error_files.size()) {          if (error_files.size()) {
1362              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;
1363              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1364              msg.run();              msg.run();
1365          }          }
# Line 1040  void MainWindow::on_action_remove_sample Line 1385  void MainWindow::on_action_remove_sample
1385                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1386                      members.push_back(pSample);                      members.push_back(pSample);
1387                  }                  }
1388                    // notify everybody that we're going to remove these samples
1389                    samples_to_be_removed_signal.emit(members);
1390                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1391                  // samples that belong to the group                  // samples that belong to the group
1392                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1393                    // notify that we're done with removal
1394                    samples_removed_signal.emit();
1395                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1396                  // them from the import queue                  // them from the import queue
1397                  for (std::list<gig::Sample*>::iterator member = members.begin();                  for (std::list<gig::Sample*>::iterator member = members.begin();
# Line 1057  void MainWindow::on_action_remove_sample Line 1406  void MainWindow::on_action_remove_sample
1406                          }                          }
1407                      }                      }
1408                  }                  }
1409                    file_changed();
1410              } else if (sample) {              } else if (sample) {
1411                    // notify everybody that we're going to remove this sample
1412                    std::list<gig::Sample*> lsamples;
1413                    lsamples.push_back(sample);
1414                    samples_to_be_removed_signal.emit(lsamples);
1415                  // remove sample from the .gig file                  // remove sample from the .gig file
1416                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1417                    // notify that we're done with removal
1418                    samples_removed_signal.emit();
1419                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1420                  // the import queue                  // the import queue
1421                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
# Line 1071  void MainWindow::on_action_remove_sample Line 1427  void MainWindow::on_action_remove_sample
1427                          break;                          break;
1428                      }                      }
1429                  }                  }
1430                    dimreg_changed();
1431                    file_changed();
1432              }              }
1433              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1434              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1435          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1436                // pretend we're done with removal (i.e. to avoid dead locks)
1437                samples_removed_signal.emit();
1438                // show error message
1439              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1440              msg.run();              msg.run();
1441          }          }
1442      }      }
1443  }  }
1444    
1445    // For some reason drag_data_get gets called two times for each
1446    // drag'n'drop (at least when target is an Entry). This work-around
1447    // makes sure the code in drag_data_get and drop_drag_data_received is
1448    // only executed once, as drag_begin only gets called once.
1449    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1450    {
1451        first_call_to_drag_data_get = true;
1452    }
1453    
1454  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>&,
1455                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1456  {  {
1457        if (!first_call_to_drag_data_get) return;
1458        first_call_to_drag_data_get = false;
1459    
1460      // get selected sample      // get selected sample
1461      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1462      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
# Line 1101  void MainWindow::on_sample_label_drop_dr Line 1474  void MainWindow::on_sample_label_drop_dr
1474      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1475      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1476  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1477      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1478    
1479      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1480          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1481              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1482              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1483              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1484                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1485              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1486              context->drop_reply(true, time);  
1487              return;          // notify everybody that we're going to alter the region
1488            gig::Region* region = m_RegionChooser.get_region();
1489            region_to_be_changed_signal.emit(region);
1490    
1491            // find the samplechannel dimension
1492            gig::dimension_def_t* stereo_dimension = 0;
1493            for (int i = 0 ; i < region->Dimensions ; i++) {
1494                if (region->pDimensionDefinitions[i].dimension ==
1495                    gig::dimension_samplechannel) {
1496                    stereo_dimension = &region->pDimensionDefinitions[i];
1497                    break;
1498                }
1499            }
1500            bool channels_changed = false;
1501            if (sample->Channels == 1 && stereo_dimension) {
1502                // remove the samplechannel dimension
1503                region->DeleteDimension(stereo_dimension);
1504                channels_changed = true;
1505                region_changed();
1506            }
1507            dimreg_edit.set_sample(sample);
1508    
1509            if (sample->Channels == 2 && !stereo_dimension) {
1510                // add samplechannel dimension
1511                gig::dimension_def_t dim;
1512                dim.dimension = gig::dimension_samplechannel;
1513                dim.bits = 1;
1514                dim.zones = 2;
1515                region->AddDimension(&dim);
1516                channels_changed = true;
1517                region_changed();
1518          }          }
1519            if (channels_changed) {
1520                // unmap all samples with wrong number of channels
1521                // TODO: maybe there should be a warning dialog for this
1522                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1523                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1524                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1525                        gig::Sample* oldref = d->pSample;
1526                        d->pSample = NULL;
1527                        sample_ref_changed_signal.emit(oldref, NULL);
1528                    }
1529                }
1530            }
1531    
1532            // notify we're done with altering
1533            region_changed_signal.emit(region);
1534    
1535            file_changed();
1536    
1537            return;
1538      }      }
1539      // drop failed      // drop failed
1540      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1127  void MainWindow::sample_name_changed(con Line 1548  void MainWindow::sample_name_changed(con
1548      gig::Group* group   = row[m_SamplesModel.m_col_group];      gig::Group* group   = row[m_SamplesModel.m_col_group];
1549      gig::Sample* sample = row[m_SamplesModel.m_col_sample];      gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1550      if (group) {      if (group) {
1551          group->Name = name;          if (group->Name != name) {
1552                group->Name = name;
1553                printf("group name changed\n");
1554                file_changed();
1555            }
1556      } else if (sample) {      } else if (sample) {
1557          sample->pInfo->Name = name.raw();          if (sample->pInfo->Name != name.raw()) {
1558                sample->pInfo->Name = name.raw();
1559                printf("sample name changed\n");
1560                file_changed();
1561            }
1562      }      }
1563  }  }
1564    
# Line 1139  void MainWindow::instrument_name_changed Line 1568  void MainWindow::instrument_name_changed
1568      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1569      Glib::ustring name = row[m_Columns.m_col_name];      Glib::ustring name = row[m_Columns.m_col_name];
1570      gig::Instrument* instrument = row[m_Columns.m_col_instr];      gig::Instrument* instrument = row[m_Columns.m_col_instr];
1571      if (instrument) instrument->pInfo->Name = name.raw();      if (instrument && instrument->pInfo->Name != name.raw()) {
1572            instrument->pInfo->Name = name.raw();
1573            file_changed();
1574        }
1575    }
1576    
1577    void MainWindow::set_file_is_shared(bool b) {
1578        this->file_is_shared = b;
1579    
1580        if (file_is_shared) {
1581            m_AttachedStateLabel.set_label(_("live-mode"));
1582            m_AttachedStateImage.set(
1583                Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm)
1584            );
1585        } else {
1586            m_AttachedStateLabel.set_label(_("stand-alone"));
1587            m_AttachedStateImage.set(
1588                Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm)
1589            );
1590        }
1591    }
1592    
1593    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1594        return file_structure_to_be_changed_signal;
1595    }
1596    
1597    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1598        return file_structure_changed_signal;
1599    }
1600    
1601    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1602        return samples_to_be_removed_signal;
1603    }
1604    
1605    sigc::signal<void>& MainWindow::signal_samples_removed() {
1606        return samples_removed_signal;
1607    }
1608    
1609    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1610        return region_to_be_changed_signal;
1611    }
1612    
1613    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1614        return region_changed_signal;
1615    }
1616    
1617    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1618        return sample_ref_changed_signal;
1619    }
1620    
1621    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1622        return dimreg_to_be_changed_signal;
1623    }
1624    
1625    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1626        return dimreg_changed_signal;
1627  }  }

Legend:
Removed from v.1225  
changed lines
  Added in v.1460

  ViewVC Help
Powered by ViewVC