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

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

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

revision 1261 by persson, Thu Jul 5 17:12:20 2007 UTC revision 1382 by schoenebeck, Thu Oct 4 23:29:22 2007 UTC
# Line 31  Line 31 
31  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
32  #endif  #endif
33    
34    #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION < 6) || GLIBMM_MAJOR_VERSION < 2
35    namespace Glib {
36    Glib::ustring filename_display_basename(const std::string& filename)
37    {
38        gchar* gstr = g_path_get_basename(filename.c_str());
39        Glib::ustring str(gstr);
40        g_free(gstr);
41        return Glib::filename_to_utf8(str);
42    }
43    }
44    #endif
45    
46  #include <stdio.h>  #include <stdio.h>
47  #include <sndfile.h>  #include <sndfile.h>
48    
# Line 234  MainWindow::MainWindow() Line 246  MainWindow::MainWindow()
246      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
247      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
248      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
249        m_TreeViewSamples.signal_drag_begin().connect(
250            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
251        );
252      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
253          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
254      );      );
# Line 242  MainWindow::MainWindow() Line 257  MainWindow::MainWindow()
257          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
258      );      );
259      dimreg_edit.signal_dimreg_changed().connect(      dimreg_edit.signal_dimreg_changed().connect(
260          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
261      m_RegionChooser.signal_instrument_changed().connect(      m_RegionChooser.signal_instrument_changed().connect(
262          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
263      m_DimRegionChooser.signal_region_changed().connect(      m_DimRegionChooser.signal_region_changed().connect(
264          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
265      instrumentProps.signal_instrument_changed().connect(      instrumentProps.signal_instrument_changed().connect(
266          sigc::mem_fun(*this, &MainWindow::file_changed));          sigc::mem_fun(*this, &MainWindow::file_changed));
267    
268        dimreg_edit.signal_dimreg_to_be_changed().connect(
269            dimreg_to_be_changed_signal.make_slot());
270        dimreg_edit.signal_dimreg_changed().connect(
271            dimreg_changed_signal.make_slot());
272        dimreg_edit.signal_sample_ref_changed().connect(
273            sample_ref_changed_signal.make_slot());
274    
275        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
276            sigc::hide(
277                sigc::bind(
278                    file_structure_to_be_changed_signal.make_slot(),
279                    sigc::ref(this->file)
280                )
281            )
282        );
283        m_RegionChooser.signal_instrument_struct_changed().connect(
284            sigc::hide(
285                sigc::bind(
286                    file_structure_changed_signal.make_slot(),
287                    sigc::ref(this->file)
288                )
289            )
290        );
291        m_RegionChooser.signal_region_to_be_changed().connect(
292            region_to_be_changed_signal.make_slot());
293        m_RegionChooser.signal_region_changed_signal().connect(
294            region_changed_signal.make_slot());
295    
296      file = 0;      file = 0;
297      file_is_changed = false;      file_is_changed = false;
298        file_is_shared  = false;
299    
300      show_all_children();      show_all_children();
301    
302        // start with a new gig file by default
303        on_action_file_new();
304  }  }
305    
306  MainWindow::~MainWindow()  MainWindow::~MainWindow()
# Line 261  MainWindow::~MainWindow() Line 309  MainWindow::~MainWindow()
309    
310  bool MainWindow::on_delete_event(GdkEventAny* event)  bool MainWindow::on_delete_event(GdkEventAny* event)
311  {  {
312      return file_is_changed && !close_confirmation_dialog();      return !file_is_shared && file_is_changed && !close_confirmation_dialog();
313  }  }
314    
315  void MainWindow::on_action_quit()  void MainWindow::on_action_quit()
316  {  {
317      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
318      hide();      hide();
319  }  }
320    
# Line 380  void MainWindow::__clear() { Line 428  void MainWindow::__clear() {
428      m_refTreeModel->clear();      m_refTreeModel->clear();
429      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
430      // free libgig's gig::File instance      // free libgig's gig::File instance
431      if (file) {      if (file && !file_is_shared) delete file;
432          delete file;      file = NULL;
433          file = NULL;      file_is_shared = false;
     }  
434  }  }
435    
436  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
437  {  {
438      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
439    
440        if (file_is_shared && !leaving_shared_mode_dialog()) return;
441    
442      // clear all GUI elements      // clear all GUI elements
443      __clear();      __clear();
# Line 407  bool MainWindow::close_confirmation_dial Line 456  bool MainWindow::close_confirmation_dial
456                                   Glib::filename_display_basename(filename).c_str());                                   Glib::filename_display_basename(filename).c_str());
457      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);      Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
458      g_free(msg);      g_free(msg);
459    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
460      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."));
461    #endif
462      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);      dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
463      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
464      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);
465      dialog.set_default_response(Gtk::RESPONSE_YES);      dialog.set_default_response(Gtk::RESPONSE_YES);
466      int response = dialog.run();      int response = dialog.run();
467        dialog.hide();
468      if (response == Gtk::RESPONSE_YES) return file_save();      if (response == Gtk::RESPONSE_YES) return file_save();
469      return response != Gtk::RESPONSE_CANCEL;      return response != Gtk::RESPONSE_CANCEL;
470  }  }
471    
472    bool MainWindow::leaving_shared_mode_dialog() {
473        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
474        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
475    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
476        dialog.set_secondary_text(
477            _("If you proceed to work on another instrument file, it won't be "
478              "used by the sampler until you tell the sampler explicitly to "
479              "load it.")
480       );
481    #endif
482        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
483        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
484        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
485        int response = dialog.run();
486        dialog.hide();
487        return response == Gtk::RESPONSE_YES;
488    }
489    
490  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
491  {  {
492      if (file_is_changed && !close_confirmation_dialog()) return;      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
493    
494        if (file_is_shared && !leaving_shared_mode_dialog()) return;
495    
496      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
497      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 506  void MainWindow::on_action_file_open()
506      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
507          std::string filename = dialog.get_filename();          std::string filename = dialog.get_filename();
508          printf("filename=%s\n", filename.c_str());          printf("filename=%s\n", filename.c_str());
         __clear();  
509          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
510          load_file(filename.c_str());          load_file(filename.c_str());
511          current_dir = Glib::path_get_dirname(filename);          current_dir = Glib::path_get_dirname(filename);
# Line 443  void MainWindow::on_action_file_open() Line 514  void MainWindow::on_action_file_open()
514    
515  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
516  {  {
517        __clear();
518      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
519      load_dialog->show_all();      load_dialog->show_all();
520      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 460  void MainWindow::load_instrument(gig::In Line 532  void MainWindow::load_instrument(gig::In
532          msg.run();          msg.run();
533          Gtk::Main::quit();          Gtk::Main::quit();
534      }      }
535        // clear all GUI elements
536        __clear();
537        // load the instrument
538      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
539      load_gig(pFile, 0 /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
540      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
541  }  }
542    
# Line 483  void MainWindow::on_action_file_save() Line 558  void MainWindow::on_action_file_save()
558      file_save();      file_save();
559  }  }
560    
561  bool MainWindow::file_save()  bool MainWindow::check_if_savable()
562  {  {
563      if (!file) return false;      if (!file) return false;
564      if (!file_has_name) return file_save_as();  
565        if (!file->GetFirstSample()) {
566            Gtk::MessageDialog(*this, _("The file could not be saved "
567                                        "because it contains no samples"),
568                               false, Gtk::MESSAGE_ERROR).run();
569            return false;
570        }
571    
572        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
573             instrument = file->GetNextInstrument()) {
574            if (!instrument->GetFirstRegion()) {
575                Gtk::MessageDialog(*this, _("The file could not be saved "
576                                            "because there are instruments "
577                                            "that have no regions"),
578                                   false, Gtk::MESSAGE_ERROR).run();
579                return false;
580            }
581        }
582        return true;
583    }
584    
585    bool MainWindow::file_save()
586    {
587        if (!check_if_savable()) return false;
588        if (!file_is_shared && !file_has_name) return file_save_as();
589    
590      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
591        file_structure_to_be_changed_signal.emit(this->file);
592      try {      try {
593          file->Save();          file->Save();
594          if (file_is_changed) {          if (file_is_changed) {
# Line 496  bool MainWindow::file_save() Line 596  bool MainWindow::file_save()
596              file_is_changed = false;              file_is_changed = false;
597          }          }
598      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
599          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
600            Glib::ustring txt = _("Could not save file: ") + e.Message;
601          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
602          msg.run();          msg.run();
603          return false;          return false;
604      }      }
605      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
606      __import_queued_samples();      __import_queued_samples();
607        file_structure_changed_signal.emit(this->file);
608      return true;      return true;
609  }  }
610    
611  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
612  {  {
613        if (!check_if_savable()) return;
614      file_save_as();      file_save_as();
615  }  }
616    
617  bool MainWindow::file_save_as()  bool MainWindow::file_save_as()
618  {  {
     if (!file) return false;  
619      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);      Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
620      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
621      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 637  bool MainWindow::file_save_as()
637      dialog.set_current_name(Glib::filename_display_basename(filename));      dialog.set_current_name(Glib::filename_display_basename(filename));
638    
639      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
640            file_structure_to_be_changed_signal.emit(this->file);
641          try {          try {
642              std::string filename = dialog.get_filename();              std::string filename = dialog.get_filename();
643              if (!Glib::str_has_suffix(filename, ".gig")) {              if (!Glib::str_has_suffix(filename, ".gig")) {
# Line 548  bool MainWindow::file_save_as() Line 651  bool MainWindow::file_save_as()
651              file_has_name = true;              file_has_name = true;
652              file_is_changed = false;              file_is_changed = false;
653          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
654              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
655                Glib::ustring txt = _("Could not save file: ") + e.Message;
656              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
657              msg.run();              msg.run();
658              return false;              return false;
659          }          }
660          __import_queued_samples();          __import_queued_samples();
661            file_structure_changed_signal.emit(this->file);
662          return true;          return true;
663      }      }
664      return false;      return false;
# Line 576  void MainWindow::__import_queued_samples Line 681  void MainWindow::__import_queued_samples
681              int bitdepth;              int bitdepth;
682              switch (info.format & 0xff) {              switch (info.format & 0xff) {
683                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
684                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
685                    case SF_FORMAT_PCM_U8:
686                      bitdepth = 16;                      bitdepth = 16;
687                      break;                      break;
688                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
689                  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;  
690                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
691                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
692                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
693                      break;                      break;
694                  default:                  default:
695                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
696                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
697              }              }
698              // allocate appropriate copy buffer (TODO: for now we copy  
699              // 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;  
700              switch (bitdepth) {              switch (bitdepth) {
701                  case 16:                  case 16: {
702                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
703                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
704                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
705                            // libsndfile does the conversion for us (if needed)
706                            int n = sf_readf_short(hFile, buffer, bufsize);
707                            // write from buffer directly (physically) into .gig file
708                            iter->gig_sample->Write(buffer, n);
709                            cnt -= n;
710                        }
711                        delete[] buffer;
712                      break;                      break;
713                  case 32:                  }
714                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
715                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
716                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
717                        sf_count_t cnt = info.frames;
718                        while (cnt) {
719                            // libsndfile returns 32 bits, convert to 24
720                            int n = sf_readf_int(hFile, srcbuf, bufsize);
721                            int j = 0;
722                            for (int i = 0 ; i < n * info.channels ; i++) {
723                                dstbuf[j++] = srcbuf[i] >> 8;
724                                dstbuf[j++] = srcbuf[i] >> 16;
725                                dstbuf[j++] = srcbuf[i] >> 24;
726                            }
727                            // write from buffer directly (physically) into .gig file
728                            iter->gig_sample->Write(dstbuf, n);
729                            cnt -= n;
730                        }
731                        delete[] srcbuf;
732                        delete[] dstbuf;
733                      break;                      break;
734                    }
735              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
736              // cleanup              // cleanup
737              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
738              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
739              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
740              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 635  void MainWindow::__import_queued_samples Line 749  void MainWindow::__import_queued_samples
749      }      }
750      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
751      if (error_files.size()) {      if (error_files.size()) {
752          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;
753          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
754          msg.run();          msg.run();
755      }      }
# Line 712  void PropDialog::set_info(DLS::Info* inf Line 826  void PropDialog::set_info(DLS::Info* inf
826      entry[15].set_text(info->Subject);      entry[15].set_text(info->Subject);
827  }  }
828    
829    void InstrumentProps::add_prop(BoolEntry& boolentry)
830    {
831        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
832                     Gtk::FILL, Gtk::SHRINK);
833        rowno++;
834        boolentry.signal_changed_by_user().connect(instrument_changed.make_slot());
835    }
836    
837    void InstrumentProps::add_prop(BoolEntryPlus6& boolentry)
838    {
839        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
840                     Gtk::FILL, Gtk::SHRINK);
841        rowno++;
842        boolentry.signal_changed_by_user().connect(instrument_changed.make_slot());
843    }
844    
845  void InstrumentProps::add_prop(LabelWidget& prop)  void InstrumentProps::add_prop(LabelWidget& prop)
846  {  {
847      table.attach(prop.label, 0, 1, rowno, rowno + 1,      table.attach(prop.label, 0, 1, rowno, rowno + 1,
# Line 726  InstrumentProps::InstrumentProps() Line 856  InstrumentProps::InstrumentProps()
856      : table(2,1),      : table(2,1),
857        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
858        eName("Name"),        eName("Name"),
859        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
860        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
861        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
862        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
863        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
864        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
865        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
866        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
867        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
868        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Dimension key range low"),
869        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Dimension key range high")
870  {  {
871      set_title("Instrument properties");      set_title("Instrument properties");
872    
# Line 813  void InstrumentProps::key_range_high_cha Line 943  void InstrumentProps::key_range_high_cha
943      if (h < l) eDimensionKeyRangeLow.set_value(h);      if (h < l) eDimensionKeyRangeLow.set_value(h);
944  }  }
945    
946  sigc::signal<void> InstrumentProps::signal_instrument_changed()  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
947  {  {
948      return instrument_changed;      return instrument_changed;
949  }  }
# Line 826  void MainWindow::file_changed() Line 956  void MainWindow::file_changed()
956      }      }
957  }  }
958    
959  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
960  {  {
961      file = 0;      file = 0;
962        file_is_shared = isSharedInstrument;
963    
964      this->filename = filename ? filename : _("Unsaved Gig File");      this->filename = filename ? filename : _("Unsaved Gig File");
965      set_title(Glib::filename_display_basename(this->filename));      set_title(Glib::filename_display_basename(this->filename));
# Line 962  void MainWindow::on_action_add_instrumen Line 1093  void MainWindow::on_action_add_instrumen
1093    
1094  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1095      if (!file) return;      if (!file) return;
1096        if (file_is_shared) {
1097            Gtk::MessageDialog msg(
1098                *this,
1099                 _("You cannot delete an instrument from this file, since it's "
1100                   "currently used by the sampler."),
1101                 false, Gtk::MESSAGE_INFO
1102            );
1103            msg.run();
1104            return;
1105        }
1106    
1107      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1108      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1109      if (it) {      if (it) {
# Line 1027  void MainWindow::on_action_add_sample() Line 1169  void MainWindow::on_action_add_sample()
1169      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1170      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1171      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1172      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1173          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1174          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1175          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 1057  void MainWindow::on_action_add_sample() Line 1199  void MainWindow::on_action_add_sample()
1199                  int bitdepth;                  int bitdepth;
1200                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1201                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1202                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1203                        case SF_FORMAT_PCM_U8:
1204                          bitdepth = 16;                          bitdepth = 16;
1205                          break;                          break;
1206                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1207                      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;  
1208                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1209                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1210                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1211                          break;                          break;
1212                      default:                      default:
1213                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 1084  void MainWindow::on_action_add_sample() Line 1216  void MainWindow::on_action_add_sample()
1216                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1217                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1218                  // file name without path                  // file name without path
1219                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1220                    // remove file extension if there is one
1221                    for (int i = 0; supportedFileTypes[i]; i++) {
1222                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1223                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1224                            break;
1225                        }
1226                    }
1227                    sample->pInfo->Name = filename;
1228                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1229                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1230                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1231                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1232                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1233                    sample->BlockAlign = sample->FrameSize;
1234                    sample->SamplesTotal = info.frames;
1235    
1236                    SF_INSTRUMENT instrument;
1237                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1238                                   &instrument, sizeof(instrument)) != SF_FALSE)
1239                    {
1240                        sample->MIDIUnityNote = instrument.basenote;
1241    
1242    #if HAVE_SF_INSTRUMENT_LOOPS
1243                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1244                            sample->Loops = 1;
1245    
1246                            switch (instrument.loops[0].mode) {
1247                            case SF_LOOP_FORWARD:
1248                                sample->LoopType = gig::loop_type_normal;
1249                                break;
1250                            case SF_LOOP_BACKWARD:
1251                                sample->LoopType = gig::loop_type_backward;
1252                                break;
1253                            case SF_LOOP_ALTERNATING:
1254                                sample->LoopType = gig::loop_type_bidirectional;
1255                                break;
1256                            }
1257                            sample->LoopStart = instrument.loops[0].start;
1258                            sample->LoopEnd = instrument.loops[0].end;
1259                            sample->LoopPlayCount = instrument.loops[0].count;
1260                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1261                        }
1262    #endif
1263                    }
1264    
1265                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1266                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1267                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1104  void MainWindow::on_action_add_sample() Line 1277  void MainWindow::on_action_add_sample()
1277                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1278                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1279                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1280                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1281                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1282                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1283                  // close sound file                  // close sound file
# Line 1117  void MainWindow::on_action_add_sample() Line 1290  void MainWindow::on_action_add_sample()
1290          }          }
1291          // 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
1292          if (error_files.size()) {          if (error_files.size()) {
1293              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;
1294              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1295              msg.run();              msg.run();
1296          }          }
# Line 1143  void MainWindow::on_action_remove_sample Line 1316  void MainWindow::on_action_remove_sample
1316                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1317                      members.push_back(pSample);                      members.push_back(pSample);
1318                  }                  }
1319                    // notify everybody that we're going to remove these samples
1320                    samples_to_be_removed_signal.emit(members);
1321                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1322                  // samples that belong to the group                  // samples that belong to the group
1323                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1324                    // notify that we're done with removal
1325                    samples_removed_signal.emit();
1326                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1327                  // them from the import queue                  // them from the import queue
1328                  for (std::list<gig::Sample*>::iterator member = members.begin();                  for (std::list<gig::Sample*>::iterator member = members.begin();
# Line 1162  void MainWindow::on_action_remove_sample Line 1339  void MainWindow::on_action_remove_sample
1339                  }                  }
1340                  file_changed();                  file_changed();
1341              } else if (sample) {              } else if (sample) {
1342                    // notify everybody that we're going to remove this sample
1343                    std::list<gig::Sample*> lsamples;
1344                    lsamples.push_back(sample);
1345                    samples_to_be_removed_signal.emit(lsamples);
1346                  // remove sample from the .gig file                  // remove sample from the .gig file
1347                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1348                    // notify that we're done with removal
1349                    samples_removed_signal.emit();
1350                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1351                  // the import queue                  // the import queue
1352                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();                  for (std::list<SampleImportItem>::iterator iter = m_SampleImportQueue.begin();
# Line 1175  void MainWindow::on_action_remove_sample Line 1358  void MainWindow::on_action_remove_sample
1358                          break;                          break;
1359                      }                      }
1360                  }                  }
1361                    dimreg_changed();
1362                  file_changed();                  file_changed();
1363              }              }
1364              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1365              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1366          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1367                // pretend we're done with removal (i.e. to avoid dead locks)
1368                samples_removed_signal.emit();
1369                // show error message
1370              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1371              msg.run();              msg.run();
1372          }          }
1373      }      }
1374  }  }
1375    
1376    // For some reason drag_data_get gets called two times for each
1377    // drag'n'drop (at least when target is an Entry). This work-around
1378    // makes sure the code in drag_data_get and drop_drag_data_received is
1379    // only executed once, as drag_begin only gets called once.
1380    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1381    {
1382        first_call_to_drag_data_get = true;
1383    }
1384    
1385  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>&,
1386                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1387  {  {
1388        if (!first_call_to_drag_data_get) return;
1389        first_call_to_drag_data_get = false;
1390    
1391      // get selected sample      // get selected sample
1392      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1393      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeViewSamples.get_selection();
# Line 1206  void MainWindow::on_sample_label_drop_dr Line 1405  void MainWindow::on_sample_label_drop_dr
1405      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1406      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1407  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1408      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1409    
1410      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1411          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1412              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1413              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1414              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1415                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1416              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1417              context->drop_reply(true, time);  
1418              file_changed();          // notify everybody that we're going to alter the region
1419              return;          gig::Region* region = m_RegionChooser.get_region();
1420            region_to_be_changed_signal.emit(region);
1421    
1422            // find the samplechannel dimension
1423            gig::dimension_def_t* stereo_dimension = 0;
1424            for (int i = 0 ; i < region->Dimensions ; i++) {
1425                if (region->pDimensionDefinitions[i].dimension ==
1426                    gig::dimension_samplechannel) {
1427                    stereo_dimension = &region->pDimensionDefinitions[i];
1428                    break;
1429                }
1430          }          }
1431            bool channels_changed = false;
1432            if (sample->Channels == 1 && stereo_dimension) {
1433                // remove the samplechannel dimension
1434                region->DeleteDimension(stereo_dimension);
1435                channels_changed = true;
1436                region_changed();
1437            }
1438            dimreg_edit.set_sample(sample);
1439    
1440            if (sample->Channels == 2 && !stereo_dimension) {
1441                // add samplechannel dimension
1442                gig::dimension_def_t dim;
1443                dim.dimension = gig::dimension_samplechannel;
1444                dim.bits = 1;
1445                dim.zones = 2;
1446                region->AddDimension(&dim);
1447                channels_changed = true;
1448                region_changed();
1449            }
1450            if (channels_changed) {
1451                // unmap all samples with wrong number of channels
1452                // TODO: maybe there should be a warning dialog for this
1453                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1454                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1455                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1456                        gig::Sample* oldref = d->pSample;
1457                        d->pSample = NULL;
1458                        sample_ref_changed_signal.emit(oldref, NULL);
1459                    }
1460                }
1461            }
1462    
1463            // notify we're done with altering
1464            region_changed_signal.emit(region);
1465    
1466            return;
1467      }      }
1468      // drop failed      // drop failed
1469      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1258  void MainWindow::instrument_name_changed Line 1502  void MainWindow::instrument_name_changed
1502          file_changed();          file_changed();
1503      }      }
1504  }  }
1505    
1506    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1507        return file_structure_to_be_changed_signal;
1508    }
1509    
1510    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1511        return file_structure_changed_signal;
1512    }
1513    
1514    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1515        return samples_to_be_removed_signal;
1516    }
1517    
1518    sigc::signal<void>& MainWindow::signal_samples_removed() {
1519        return samples_removed_signal;
1520    }
1521    
1522    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1523        return region_to_be_changed_signal;
1524    }
1525    
1526    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1527        return region_changed_signal;
1528    }
1529    
1530    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1531        return sample_ref_changed_signal;
1532    }
1533    
1534    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1535        return dimreg_to_be_changed_signal;
1536    }
1537    
1538    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1539        return dimreg_changed_signal;
1540    }

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

  ViewVC Help
Powered by ViewVC