/[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 1262 by persson, Sun Jul 22 15:07:08 2007 UTC revision 1411 by schoenebeck, Fri Oct 12 17:46:29 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 26  Line 25 
25  #include <gtkmm/targetentry.h>  #include <gtkmm/targetentry.h>
26  #include <gtkmm/main.h>  #include <gtkmm/main.h>
27    
28    #include "global.h"
29    
30  #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
31  #define ABOUT_DIALOG  #define ABOUT_DIALOG
32  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
33  #endif  #endif
34    
35    #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION < 6) || GLIBMM_MAJOR_VERSION < 2
36    namespace Glib {
37    Glib::ustring filename_display_basename(const std::string& filename)
38    {
39        gchar* gstr = g_path_get_basename(filename.c_str());
40        Glib::ustring str(gstr);
41        g_free(gstr);
42        return Glib::filename_to_utf8(str);
43    }
44    }
45    #endif
46    
47  #include <stdio.h>  #include <stdio.h>
48  #include <sndfile.h>  #include <sndfile.h>
49    
50  #include "mainwindow.h"  #include "mainwindow.h"
51    
52  #define _(String) gettext(String)  #include "../../gfx/status_attached.xpm"
53    #include "../../gfx/status_detached.xpm"
54    
55  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
56      std::stringstream ss;      std::stringstream ss;
# Line 199  MainWindow::MainWindow() Line 213  MainWindow::MainWindow()
213      m_VBox.pack_start(m_HPaned);      m_VBox.pack_start(m_HPaned);
214      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
215      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
216        m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK);
217    
218        // Status Bar:
219        m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK);
220        m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK);
221        m_StatusBar.show();
222    
223      m_RegionChooser.signal_region_selected().connect(      m_RegionChooser.signal_region_selected().connect(
224          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
# Line 234  MainWindow::MainWindow() Line 254  MainWindow::MainWindow()
254      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
255      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
256      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
257        m_TreeViewSamples.signal_drag_begin().connect(
258            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
259        );
260      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
261          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
262      );      );
# Line 242  MainWindow::MainWindow() Line 265  MainWindow::MainWindow()
265          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
266      );      );
267      dimreg_edit.signal_dimreg_changed().connect(      dimreg_edit.signal_dimreg_changed().connect(
268          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
269      m_RegionChooser.signal_instrument_changed().connect(      m_RegionChooser.signal_instrument_changed().connect(
270          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
271      m_DimRegionChooser.signal_region_changed().connect(      m_DimRegionChooser.signal_region_changed().connect(
272          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
273      instrumentProps.signal_instrument_changed().connect(      instrumentProps.signal_instrument_changed().connect(
274          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
275    
276        dimreg_edit.signal_dimreg_to_be_changed().connect(
277            dimreg_to_be_changed_signal.make_slot());
278        dimreg_edit.signal_dimreg_changed().connect(
279            dimreg_changed_signal.make_slot());
280        dimreg_edit.signal_sample_ref_changed().connect(
281            sample_ref_changed_signal.make_slot());
282    
283        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
284            sigc::hide(
285                sigc::bind(
286                    file_structure_to_be_changed_signal.make_slot(),
287                    sigc::ref(this->file)
288                )
289            )
290        );
291        m_RegionChooser.signal_instrument_struct_changed().connect(
292            sigc::hide(
293                sigc::bind(
294                    file_structure_changed_signal.make_slot(),
295                    sigc::ref(this->file)
296                )
297            )
298        );
299        m_RegionChooser.signal_region_to_be_changed().connect(
300            region_to_be_changed_signal.make_slot());
301        m_RegionChooser.signal_region_changed_signal().connect(
302            region_changed_signal.make_slot());
303    
304      file = 0;      file = 0;
305      file_is_changed = false;      file_is_changed = false;
306        set_file_is_shared(false);
307    
308      show_all_children();      show_all_children();
309    
310        // start with a new gig file by default
311        on_action_file_new();
312  }  }
313    
314  MainWindow::~MainWindow()  MainWindow::~MainWindow()
# Line 261  MainWindow::~MainWindow() Line 317  MainWindow::~MainWindow()
317    
318  bool MainWindow::on_delete_event(GdkEventAny* event)  bool MainWindow::on_delete_event(GdkEventAny* event)
319  {  {
320      return file_is_changed && !close_confirmation_dialog();      return !file_is_shared && file_is_changed && !close_confirmation_dialog();
321  }  }
322    
323  void MainWindow::on_action_quit()  void MainWindow::on_action_quit()
324  {  {
325      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
326      hide();      hide();
327  }  }
328    
# Line 380  void MainWindow::__clear() { Line 436  void MainWindow::__clear() {
436      m_refTreeModel->clear();      m_refTreeModel->clear();
437      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
438      // free libgig's gig::File instance      // free libgig's gig::File instance
439      if (file) {      if (file && !file_is_shared) delete file;
440          delete file;      file = NULL;
441          file = NULL;      set_file_is_shared(false);
     }  
442  }  }
443    
444  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
445  {  {
446      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
447    
448        if (file_is_shared && !leaving_shared_mode_dialog()) return;
449    
450      // clear all GUI elements      // clear all GUI elements
451      __clear();      __clear();
# Line 407  bool MainWindow::close_confirmation_dial Line 464  bool MainWindow::close_confirmation_dial
464                                   Glib::filename_display_basename(filename).c_str());                                   Glib::filename_display_basename(filename).c_str());
465      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
466      g_free(msg);      g_free(msg);
467    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
468      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."));
469    #endif
470      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
471      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
472      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);
473      dialog.set_default_response(Gtk::RESPONSE_YES);      dialog.set_default_response(Gtk::RESPONSE_YES);
474      int response = dialog.run();      int response = dialog.run();
475        dialog.hide();
476      if (response == Gtk::RESPONSE_YES) return file_save();      if (response == Gtk::RESPONSE_YES) return file_save();
477      return response != Gtk::RESPONSE_CANCEL;      return response != Gtk::RESPONSE_CANCEL;
478  }  }
479    
480    bool MainWindow::leaving_shared_mode_dialog() {
481        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
482        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
483    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
484        dialog.set_secondary_text(
485            _("If you proceed to work on another instrument file, it won't be "
486              "used by the sampler until you tell the sampler explicitly to "
487              "load it.")
488       );
489    #endif
490        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
491        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
492        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
493        int response = dialog.run();
494        dialog.hide();
495        return response == Gtk::RESPONSE_YES;
496    }
497    
498  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
499  {  {
500      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
501    
502        if (file_is_shared && !leaving_shared_mode_dialog()) return;
503    
504      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
505      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
# Line 434  void MainWindow::on_action_file_open() Line 514  void MainWindow::on_action_file_open()
514      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
515          std::string filename = dialog.get_filename();          std::string filename = dialog.get_filename();
516          printf("filename=%s\n", filename.c_str());          printf("filename=%s\n", filename.c_str());
         __clear();  
517          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
518          load_file(filename.c_str());          load_file(filename.c_str());
519          current_dir = Glib::path_get_dirname(filename);          current_dir = Glib::path_get_dirname(filename);
# Line 443  void MainWindow::on_action_file_open() Line 522  void MainWindow::on_action_file_open()
522    
523  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
524  {  {
525        __clear();
526      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
527      load_dialog->show_all();      load_dialog->show_all();
528      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 460  void MainWindow::load_instrument(gig::In Line 540  void MainWindow::load_instrument(gig::In
540          msg.run();          msg.run();
541          Gtk::Main::quit();          Gtk::Main::quit();
542      }      }
543        // clear all GUI elements
544        __clear();
545        // load the instrument
546      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
547      load_gig(pFile, 0 /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
548      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
549  }  }
550    
# Line 483  void MainWindow::on_action_file_save() Line 566  void MainWindow::on_action_file_save()
566      file_save();      file_save();
567  }  }
568    
569  bool MainWindow::file_save()  bool MainWindow::check_if_savable()
570  {  {
571      if (!file) return false;      if (!file) return false;
572      if (!file_has_name) return file_save_as();  
573        if (!file->GetFirstSample()) {
574            Gtk::MessageDialog(*this, _("The file could not be saved "
575                                        "because it contains no samples"),
576                               false, Gtk::MESSAGE_ERROR).run();
577            return false;
578        }
579    
580        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
581             instrument = file->GetNextInstrument()) {
582            if (!instrument->GetFirstRegion()) {
583                Gtk::MessageDialog(*this, _("The file could not be saved "
584                                            "because there are instruments "
585                                            "that have no regions"),
586                                   false, Gtk::MESSAGE_ERROR).run();
587                return false;
588            }
589        }
590        return true;
591    }
592    
593    bool MainWindow::file_save()
594    {
595        if (!check_if_savable()) return false;
596        if (!file_is_shared && !file_has_name) return file_save_as();
597    
598      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
599        file_structure_to_be_changed_signal.emit(this->file);
600      try {      try {
601          file->Save();          file->Save();
602          if (file_is_changed) {          if (file_is_changed) {
# Line 496  bool MainWindow::file_save() Line 604  bool MainWindow::file_save()
604              file_is_changed = false;              file_is_changed = false;
605          }          }
606      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
607          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
608            Glib::ustring txt = _("Could not save file: ") + e.Message;
609          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
610          msg.run();          msg.run();
611          return false;          return false;
612      }      }
613      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
614      __import_queued_samples();      __import_queued_samples();
615        file_structure_changed_signal.emit(this->file);
616      return true;      return true;
617  }  }
618    
619  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
620  {  {
621        if (!check_if_savable()) return;
622      file_save_as();      file_save_as();
623  }  }
624    
625  bool MainWindow::file_save_as()  bool MainWindow::file_save_as()
626  {  {
     if (!file) return false;  
627      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
628      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
629      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
# Line 535  bool MainWindow::file_save_as() Line 645  bool MainWindow::file_save_as()
645      dialog.set_current_name(Glib::filename_display_basename(filename));      dialog.set_current_name(Glib::filename_display_basename(filename));
646    
647      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
648            file_structure_to_be_changed_signal.emit(this->file);
649          try {          try {
650              std::string filename = dialog.get_filename();              std::string filename = dialog.get_filename();
651              if (!Glib::str_has_suffix(filename, ".gig")) {              if (!Glib::str_has_suffix(filename, ".gig")) {
# Line 548  bool MainWindow::file_save_as() Line 659  bool MainWindow::file_save_as()
659              file_has_name = true;              file_has_name = true;
660              file_is_changed = false;              file_is_changed = false;
661          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
662              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
663                Glib::ustring txt = _("Could not save file: ") + e.Message;
664              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
665              msg.run();              msg.run();
666              return false;              return false;
667          }          }
668          __import_queued_samples();          __import_queued_samples();
669            file_structure_changed_signal.emit(this->file);
670          return true;          return true;
671      }      }
672      return false;      return false;
# Line 576  void MainWindow::__import_queued_samples Line 689  void MainWindow::__import_queued_samples
689              int bitdepth;              int bitdepth;
690              switch (info.format & 0xff) {              switch (info.format & 0xff) {
691                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
692                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
693                    case SF_FORMAT_PCM_U8:
694                      bitdepth = 16;                      bitdepth = 16;
695                      break;                      break;
696                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
697                  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;  
698                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
699                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
700                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
701                      break;                      break;
702                  default:                  default:
703                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
704                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
705              }              }
706              // allocate appropriate copy buffer (TODO: for now we copy  
707              // 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;  
708              switch (bitdepth) {              switch (bitdepth) {
709                  case 16:                  case 16: {
710                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
711                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
712                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
713                            // libsndfile does the conversion for us (if needed)
714                            int n = sf_readf_short(hFile, buffer, bufsize);
715                            // write from buffer directly (physically) into .gig file
716                            iter->gig_sample->Write(buffer, n);
717                            cnt -= n;
718                        }
719                        delete[] buffer;
720                      break;                      break;
721                  case 32:                  }
722                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
723                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
724                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
725                        sf_count_t cnt = info.frames;
726                        while (cnt) {
727                            // libsndfile returns 32 bits, convert to 24
728                            int n = sf_readf_int(hFile, srcbuf, bufsize);
729                            int j = 0;
730                            for (int i = 0 ; i < n * info.channels ; i++) {
731                                dstbuf[j++] = srcbuf[i] >> 8;
732                                dstbuf[j++] = srcbuf[i] >> 16;
733                                dstbuf[j++] = srcbuf[i] >> 24;
734                            }
735                            // write from buffer directly (physically) into .gig file
736                            iter->gig_sample->Write(dstbuf, n);
737                            cnt -= n;
738                        }
739                        delete[] srcbuf;
740                        delete[] dstbuf;
741                      break;                      break;
742                    }
743              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
744              // cleanup              // cleanup
745              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
746              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
747              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
748              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 635  void MainWindow::__import_queued_samples Line 757  void MainWindow::__import_queued_samples
757      }      }
758      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
759      if (error_files.size()) {      if (error_files.size()) {
760          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;
761          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
762          msg.run();          msg.run();
763      }      }
# Line 829  void InstrumentProps::key_range_high_cha Line 951  void InstrumentProps::key_range_high_cha
951      if (h < l) eDimensionKeyRangeLow.set_value(h);      if (h < l) eDimensionKeyRangeLow.set_value(h);
952  }  }
953    
954  sigc::signal<void> InstrumentProps::signal_instrument_changed()  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
955  {  {
956      return instrument_changed;      return instrument_changed;
957  }  }
# Line 842  void MainWindow::file_changed() Line 964  void MainWindow::file_changed()
964      }      }
965  }  }
966    
967  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
968  {  {
969      file = 0;      file = 0;
970        set_file_is_shared(isSharedInstrument);
971    
972      this->filename = filename ? filename : _("Unsaved Gig File");      this->filename = filename ? filename : _("Unsaved Gig File");
973      set_title(Glib::filename_display_basename(this->filename));      set_title(Glib::filename_display_basename(this->filename));
# Line 978  void MainWindow::on_action_add_instrumen Line 1101  void MainWindow::on_action_add_instrumen
1101    
1102  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1103      if (!file) return;      if (!file) return;
1104        if (file_is_shared) {
1105            Gtk::MessageDialog msg(
1106                *this,
1107                 _("You cannot delete an instrument from this file, since it's "
1108                   "currently used by the sampler."),
1109                 false, Gtk::MESSAGE_INFO
1110            );
1111            msg.run();
1112            return;
1113        }
1114    
1115      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1116      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1117      if (it) {      if (it) {
# Line 1073  void MainWindow::on_action_add_sample() Line 1207  void MainWindow::on_action_add_sample()
1207                  int bitdepth;                  int bitdepth;
1208                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1209                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1210                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1211                        case SF_FORMAT_PCM_U8:
1212                          bitdepth = 16;                          bitdepth = 16;
1213                          break;                          break;
1214                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1215                      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;  
1216                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1217                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1218                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1219                          break;                          break;
1220                      default:                      default:
1221                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 1113  void MainWindow::on_action_add_sample() Line 1237  void MainWindow::on_action_add_sample()
1237                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1238                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1239                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1240                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1241                    sample->BlockAlign = sample->FrameSize;
1242                    sample->SamplesTotal = info.frames;
1243    
1244                    SF_INSTRUMENT instrument;
1245                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1246                                   &instrument, sizeof(instrument)) != SF_FALSE)
1247                    {
1248                        sample->MIDIUnityNote = instrument.basenote;
1249    
1250    #if HAVE_SF_INSTRUMENT_LOOPS
1251                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1252                            sample->Loops = 1;
1253    
1254                            switch (instrument.loops[0].mode) {
1255                            case SF_LOOP_FORWARD:
1256                                sample->LoopType = gig::loop_type_normal;
1257                                break;
1258                            case SF_LOOP_BACKWARD:
1259                                sample->LoopType = gig::loop_type_backward;
1260                                break;
1261                            case SF_LOOP_ALTERNATING:
1262                                sample->LoopType = gig::loop_type_bidirectional;
1263                                break;
1264                            }
1265                            sample->LoopStart = instrument.loops[0].start;
1266                            sample->LoopEnd = instrument.loops[0].end;
1267                            sample->LoopPlayCount = instrument.loops[0].count;
1268                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1269                        }
1270    #endif
1271                    }
1272    
1273                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1274                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1275                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1141  void MainWindow::on_action_add_sample() Line 1298  void MainWindow::on_action_add_sample()
1298          }          }
1299          // 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
1300          if (error_files.size()) {          if (error_files.size()) {
1301              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;
1302              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1303              msg.run();              msg.run();
1304          }          }
# Line 1167  void MainWindow::on_action_remove_sample Line 1324  void MainWindow::on_action_remove_sample
1324                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1325                      members.push_back(pSample);                      members.push_back(pSample);
1326                  }                  }
1327                    // notify everybody that we're going to remove these samples
1328                    samples_to_be_removed_signal.emit(members);
1329                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1330                  // samples that belong to the group                  // samples that belong to the group
1331                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1332                    // notify that we're done with removal
1333                    samples_removed_signal.emit();
1334                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1335                  // them from the import queue                  // them from the import queue
1336                  for (std::list<gig::Sample*>::iterator member = members.begin();                  for (std::list<gig::Sample*>::iterator member = members.begin();
# Line 1186  void MainWindow::on_action_remove_sample Line 1347  void MainWindow::on_action_remove_sample
1347                  }                  }
1348                  file_changed();                  file_changed();
1349              } else if (sample) {              } else if (sample) {
1350                    // notify everybody that we're going to remove this sample
1351                    std::list<gig::Sample*> lsamples;
1352                    lsamples.push_back(sample);
1353                    samples_to_be_removed_signal.emit(lsamples);
1354                  // remove sample from the .gig file                  // remove sample from the .gig file
1355                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1356                    // notify that we're done with removal
1357                    samples_removed_signal.emit();
1358                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1359                  // the import queue                  // the import queue
1360                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
# Line 1199  void MainWindow::on_action_remove_sample Line 1366  void MainWindow::on_action_remove_sample
1366                          break;                          break;
1367                      }                      }
1368                  }                  }
1369                    dimreg_changed();
1370                  file_changed();                  file_changed();
1371              }              }
1372              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1373              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1374          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1375                // pretend we're done with removal (i.e. to avoid dead locks)
1376                samples_removed_signal.emit();
1377                // show error message
1378              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1379              msg.run();              msg.run();
1380          }          }
1381      }      }
1382  }  }
1383    
1384    // For some reason drag_data_get gets called two times for each
1385    // drag'n'drop (at least when target is an Entry). This work-around
1386    // makes sure the code in drag_data_get and drop_drag_data_received is
1387    // only executed once, as drag_begin only gets called once.
1388    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1389    {
1390        first_call_to_drag_data_get = true;
1391    }
1392    
1393  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>&,
1394                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1395  {  {
1396        if (!first_call_to_drag_data_get) return;
1397        first_call_to_drag_data_get = false;
1398    
1399      // get selected sample      // get selected sample
1400      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1401      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
# Line 1230  void MainWindow::on_sample_label_drop_dr Line 1413  void MainWindow::on_sample_label_drop_dr
1413      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1414      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1415  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1416      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1417    
1418      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1419          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1420              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1421              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1422              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1423                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1424              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1425              context->drop_reply(true, time);  
1426              file_changed();          // notify everybody that we're going to alter the region
1427              return;          gig::Region* region = m_RegionChooser.get_region();
1428            region_to_be_changed_signal.emit(region);
1429    
1430            // find the samplechannel dimension
1431            gig::dimension_def_t* stereo_dimension = 0;
1432            for (int i = 0 ; i < region->Dimensions ; i++) {
1433                if (region->pDimensionDefinitions[i].dimension ==
1434                    gig::dimension_samplechannel) {
1435                    stereo_dimension = &region->pDimensionDefinitions[i];
1436                    break;
1437                }
1438            }
1439            bool channels_changed = false;
1440            if (sample->Channels == 1 && stereo_dimension) {
1441                // remove the samplechannel dimension
1442                region->DeleteDimension(stereo_dimension);
1443                channels_changed = true;
1444                region_changed();
1445          }          }
1446            dimreg_edit.set_sample(sample);
1447    
1448            if (sample->Channels == 2 && !stereo_dimension) {
1449                // add samplechannel dimension
1450                gig::dimension_def_t dim;
1451                dim.dimension = gig::dimension_samplechannel;
1452                dim.bits = 1;
1453                dim.zones = 2;
1454                region->AddDimension(&dim);
1455                channels_changed = true;
1456                region_changed();
1457            }
1458            if (channels_changed) {
1459                // unmap all samples with wrong number of channels
1460                // TODO: maybe there should be a warning dialog for this
1461                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1462                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1463                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1464                        gig::Sample* oldref = d->pSample;
1465                        d->pSample = NULL;
1466                        sample_ref_changed_signal.emit(oldref, NULL);
1467                    }
1468                }
1469            }
1470    
1471            // notify we're done with altering
1472            region_changed_signal.emit(region);
1473    
1474            return;
1475      }      }
1476      // drop failed      // drop failed
1477      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1282  void MainWindow::instrument_name_changed Line 1510  void MainWindow::instrument_name_changed
1510          file_changed();          file_changed();
1511      }      }
1512  }  }
1513    
1514    void MainWindow::set_file_is_shared(bool b) {
1515        this->file_is_shared = b;
1516    
1517        if (file_is_shared) {
1518            m_AttachedStateLabel.set_label(_("live-mode"));
1519            m_AttachedStateImage.set(
1520                Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm)
1521            );
1522        } else {
1523            m_AttachedStateLabel.set_label(_("stand-alone"));
1524            m_AttachedStateImage.set(
1525                Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm)
1526            );
1527        }
1528    }
1529    
1530    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1531        return file_structure_to_be_changed_signal;
1532    }
1533    
1534    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1535        return file_structure_changed_signal;
1536    }
1537    
1538    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1539        return samples_to_be_removed_signal;
1540    }
1541    
1542    sigc::signal<void>& MainWindow::signal_samples_removed() {
1543        return samples_removed_signal;
1544    }
1545    
1546    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1547        return region_to_be_changed_signal;
1548    }
1549    
1550    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1551        return region_changed_signal;
1552    }
1553    
1554    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1555        return sample_ref_changed_signal;
1556    }
1557    
1558    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1559        return dimreg_to_be_changed_signal;
1560    }
1561    
1562    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1563        return dimreg_changed_signal;
1564    }

Legend:
Removed from v.1262  
changed lines
  Added in v.1411

  ViewVC Help
Powered by ViewVC