/[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 1396 by schoenebeck, Wed Oct 10 15:48:54 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  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6  #include "global.h"
29    
30    #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    
 #define _(String) gettext(String)  
   
52  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
53      std::stringstream ss;      std::stringstream ss;
54      ss << o;      ss << o;
# Line 99  MainWindow::MainWindow() Line 110  MainWindow::MainWindow()
110      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);
111      action->property_label() = action->property_label() + "...";      action->property_label() = action->property_label() + "...";
112      actionGroup->add(action,      actionGroup->add(action,
113                       *(new Gtk::AccelKey("<shift><control>s")),                       Gtk::AccelKey("<shift><control>s"),
114                       sigc::mem_fun(                       sigc::mem_fun(
115                           *this, &MainWindow::on_action_file_save_as)                           *this, &MainWindow::on_action_file_save_as));
         );  
116      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
117                                           Gtk::Stock::PROPERTIES),                                           Gtk::Stock::PROPERTIES),
118                       sigc::mem_fun(                       sigc::mem_fun(
# Line 113  MainWindow::MainWindow() Line 123  MainWindow::MainWindow()
123                           *this, &MainWindow::show_instr_props));                           *this, &MainWindow::show_instr_props));
124      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
125                       sigc::mem_fun(                       sigc::mem_fun(
126                           *this, &MainWindow::hide));                           *this, &MainWindow::on_action_quit));
127      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
128    
129      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
# Line 153  MainWindow::MainWindow() Line 163  MainWindow::MainWindow()
163    
164      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
165      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
166      // add_accel_group(uiManager->get_accel_group());      add_accel_group(uiManager->get_accel_group());
167    
168      Glib::ustring ui_info =      Glib::ustring ui_info =
169          "<ui>"          "<ui>"
# Line 201  MainWindow::MainWindow() Line 211  MainWindow::MainWindow()
211      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
212      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
213    
214      m_RegionChooser.signal_sel_changed().connect(      m_RegionChooser.signal_region_selected().connect(
215          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
216      m_DimRegionChooser.signal_sel_changed().connect(      m_DimRegionChooser.signal_dimregion_selected().connect(
217          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );
218    
219    
# Line 235  MainWindow::MainWindow() Line 245  MainWindow::MainWindow()
245      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
246      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
247      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
248        m_TreeViewSamples.signal_drag_begin().connect(
249            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
250        );
251      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
252          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
253      );      );
# Line 242  MainWindow::MainWindow() Line 255  MainWindow::MainWindow()
255      dimreg_edit.wSample->signal_drag_data_received().connect(      dimreg_edit.wSample->signal_drag_data_received().connect(
256          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
257      );      );
258        dimreg_edit.signal_dimreg_changed().connect(
259            sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
260        m_RegionChooser.signal_instrument_changed().connect(
261            sigc::mem_fun(*this, &MainWindow::file_changed));
262        m_DimRegionChooser.signal_region_changed().connect(
263            sigc::mem_fun(*this, &MainWindow::file_changed));
264        instrumentProps.signal_instrument_changed().connect(
265            sigc::mem_fun(*this, &MainWindow::file_changed));
266    
267        dimreg_edit.signal_dimreg_to_be_changed().connect(
268            dimreg_to_be_changed_signal.make_slot());
269        dimreg_edit.signal_dimreg_changed().connect(
270            dimreg_changed_signal.make_slot());
271        dimreg_edit.signal_sample_ref_changed().connect(
272            sample_ref_changed_signal.make_slot());
273    
274        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
275            sigc::hide(
276                sigc::bind(
277                    file_structure_to_be_changed_signal.make_slot(),
278                    sigc::ref(this->file)
279                )
280            )
281        );
282        m_RegionChooser.signal_instrument_struct_changed().connect(
283            sigc::hide(
284                sigc::bind(
285                    file_structure_changed_signal.make_slot(),
286                    sigc::ref(this->file)
287                )
288            )
289        );
290        m_RegionChooser.signal_region_to_be_changed().connect(
291            region_to_be_changed_signal.make_slot());
292        m_RegionChooser.signal_region_changed_signal().connect(
293            region_changed_signal.make_slot());
294    
295      file = 0;      file = 0;
296        file_is_changed = false;
297        file_is_shared  = false;
298    
299      show_all_children();      show_all_children();
300    
301        // start with a new gig file by default
302        on_action_file_new();
303  }  }
304    
305  MainWindow::~MainWindow()  MainWindow::~MainWindow()
306  {  {
307  }  }
308    
309    bool MainWindow::on_delete_event(GdkEventAny* event)
310    {
311        return !file_is_shared && file_is_changed && !close_confirmation_dialog();
312    }
313    
314    void MainWindow::on_action_quit()
315    {
316        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
317        hide();
318    }
319    
320  void MainWindow::region_changed()  void MainWindow::region_changed()
321  {  {
322      m_DimRegionChooser.set_region(m_RegionChooser.get_region());      m_DimRegionChooser.set_region(m_RegionChooser.get_region());
# Line 362  void MainWindow::__clear() { Line 427  void MainWindow::__clear() {
427      m_refTreeModel->clear();      m_refTreeModel->clear();
428      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
429      // free libgig's gig::File instance      // free libgig's gig::File instance
430      if (file) {      if (file && !file_is_shared) delete file;
431          delete file;      file = NULL;
432          file = NULL;      file_is_shared = false;
     }  
433  }  }
434    
435  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
436  {  {
437        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
438    
439        if (file_is_shared && !leaving_shared_mode_dialog()) return;
440    
441      // clear all GUI elements      // clear all GUI elements
442      __clear();      __clear();
443      // create a new .gig file (virtually yet)      // create a new .gig file (virtually yet)
# Line 378  void MainWindow::on_action_file_new() Line 446  void MainWindow::on_action_file_new()
446      gig::Instrument* pInstrument = pFile->AddInstrument();      gig::Instrument* pInstrument = pFile->AddInstrument();
447      pInstrument->pInfo->Name = "Unnamed Instrument";      pInstrument->pInfo->Name = "Unnamed Instrument";
448      // update GUI with that new gig::File      // update GUI with that new gig::File
449      load_gig(pFile, NULL /*no file name yet*/);      load_gig(pFile, 0 /*no file name yet*/);
450    }
451    
452    bool MainWindow::close_confirmation_dialog()
453    {
454        gchar* msg = g_strdup_printf(_("Save changes to \"%s\" before closing?"),
455                                     Glib::filename_display_basename(filename).c_str());
456        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
457        g_free(msg);
458    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
459        dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));
460    #endif
461        dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
462        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
463        dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);
464        dialog.set_default_response(Gtk::RESPONSE_YES);
465        int response = dialog.run();
466        dialog.hide();
467        if (response == Gtk::RESPONSE_YES) return file_save();
468        return response != Gtk::RESPONSE_CANCEL;
469    }
470    
471    bool MainWindow::leaving_shared_mode_dialog() {
472        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
473        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
474    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
475        dialog.set_secondary_text(
476            _("If you proceed to work on another instrument file, it won't be "
477              "used by the sampler until you tell the sampler explicitly to "
478              "load it.")
479       );
480    #endif
481        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
482        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
483        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
484        int response = dialog.run();
485        dialog.hide();
486        return response == Gtk::RESPONSE_YES;
487  }  }
488    
489  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
490  {  {
491        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
492    
493        if (file_is_shared && !leaving_shared_mode_dialog()) return;
494    
495      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
496      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
497      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
498        dialog.set_default_response(Gtk::RESPONSE_OK);
499      Gtk::FileFilter filter;      Gtk::FileFilter filter;
500      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
501      dialog.set_filter(filter);      dialog.set_filter(filter);
502        if (current_dir != "") {
503            dialog.set_current_folder(current_dir);
504        }
505      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
506          printf("filename=%s\n", dialog.get_filename().c_str());          std::string filename = dialog.get_filename();
507          __clear();          printf("filename=%s\n", filename.c_str());
508          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
509          load_file(dialog.get_filename().c_str());          load_file(filename.c_str());
510            current_dir = Glib::path_get_dirname(filename);
511      }      }
512  }  }
513    
514  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
515  {  {
516        __clear();
517      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
518      load_dialog->show_all();      load_dialog->show_all();
519      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 416  void MainWindow::load_instrument(gig::In Line 531  void MainWindow::load_instrument(gig::In
531          msg.run();          msg.run();
532          Gtk::Main::quit();          Gtk::Main::quit();
533      }      }
534        // clear all GUI elements
535        __clear();
536        // load the instrument
537      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
538      load_gig(pFile, NULL /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
539      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
540  }  }
541    
# Line 436  void MainWindow::on_loader_finished() Line 554  void MainWindow::on_loader_finished()
554    
555  void MainWindow::on_action_file_save()  void MainWindow::on_action_file_save()
556  {  {
557      if (!file) return;      file_save();
558    }
559    
560    bool MainWindow::check_if_savable()
561    {
562        if (!file) return false;
563    
564        if (!file->GetFirstSample()) {
565            Gtk::MessageDialog(*this, _("The file could not be saved "
566                                        "because it contains no samples"),
567                               false, Gtk::MESSAGE_ERROR).run();
568            return false;
569        }
570    
571        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
572             instrument = file->GetNextInstrument()) {
573            if (!instrument->GetFirstRegion()) {
574                Gtk::MessageDialog(*this, _("The file could not be saved "
575                                            "because there are instruments "
576                                            "that have no regions"),
577                                   false, Gtk::MESSAGE_ERROR).run();
578                return false;
579            }
580        }
581        return true;
582    }
583    
584    bool MainWindow::file_save()
585    {
586        if (!check_if_savable()) return false;
587        if (!file_is_shared && !file_has_name) return file_save_as();
588    
589      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
590        file_structure_to_be_changed_signal.emit(this->file);
591      try {      try {
592          file->Save();          file->Save();
593            if (file_is_changed) {
594                set_title(get_title().substr(1));
595                file_is_changed = false;
596            }
597      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
598          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
599            Glib::ustring txt = _("Could not save file: ") + e.Message;
600          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
601          msg.run();          msg.run();
602          return;          return false;
603      }      }
604      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
605      __import_queued_samples();      __import_queued_samples();
606        file_structure_changed_signal.emit(this->file);
607        return true;
608  }  }
609    
610  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
611  {  {
612      if (!file) return;      if (!check_if_savable()) return;
613      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);      file_save_as();
614    }
615    
616    bool MainWindow::file_save_as()
617    {
618        Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
619      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
620      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
621        dialog.set_default_response(Gtk::RESPONSE_OK);
622    
623    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 2
624        dialog.set_do_overwrite_confirmation();
625        // TODO: an overwrite dialog for gtkmm < 2.8
626    #endif
627      Gtk::FileFilter filter;      Gtk::FileFilter filter;
628      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
629      dialog.set_filter(filter);      dialog.set_filter(filter);
630    
631        if (Glib::path_is_absolute(filename)) {
632            dialog.set_filename(filename);
633        } else if (current_dir != "") {
634            dialog.set_current_folder(current_dir);
635        }
636        dialog.set_current_name(Glib::filename_display_basename(filename));
637    
638      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
639          printf("filename=%s\n", dialog.get_filename().c_str());          file_structure_to_be_changed_signal.emit(this->file);
640          try {          try {
641              file->Save(dialog.get_filename());              std::string filename = dialog.get_filename();
642                if (!Glib::str_has_suffix(filename, ".gig")) {
643                    filename += ".gig";
644                }
645                printf("filename=%s\n", filename.c_str());
646                file->Save(filename);
647                this->filename = filename;
648                current_dir = Glib::path_get_dirname(filename);
649                set_title(Glib::filename_display_basename(filename));
650                file_has_name = true;
651                file_is_changed = false;
652          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
653              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
654                Glib::ustring txt = _("Could not save file: ") + e.Message;
655              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
656              msg.run();              msg.run();
657              return;              return false;
658          }          }
659          __import_queued_samples();          __import_queued_samples();
660            file_structure_changed_signal.emit(this->file);
661            return true;
662      }      }
663        return false;
664  }  }
665    
666  // 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 680  void MainWindow::__import_queued_samples
680              int bitdepth;              int bitdepth;
681              switch (info.format & 0xff) {              switch (info.format & 0xff) {
682                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
683                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
684                    case SF_FORMAT_PCM_U8:
685                      bitdepth = 16;                      bitdepth = 16;
686                      break;                      break;
687                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
688                  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;  
689                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
690                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
691                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
692                      break;                      break;
693                  default:                  default:
694                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
695                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
696              }              }
697              // allocate appropriate copy buffer (TODO: for now we copy  
698              // 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;  
699              switch (bitdepth) {              switch (bitdepth) {
700                  case 16:                  case 16: {
701                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
702                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
703                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
704                            // libsndfile does the conversion for us (if needed)
705                            int n = sf_readf_short(hFile, buffer, bufsize);
706                            // write from buffer directly (physically) into .gig file
707                            iter->gig_sample->Write(buffer, n);
708                            cnt -= n;
709                        }
710                        delete[] buffer;
711                      break;                      break;
712                  case 32:                  }
713                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
714                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
715                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
716                        sf_count_t cnt = info.frames;
717                        while (cnt) {
718                            // libsndfile returns 32 bits, convert to 24
719                            int n = sf_readf_int(hFile, srcbuf, bufsize);
720                            int j = 0;
721                            for (int i = 0 ; i < n * info.channels ; i++) {
722                                dstbuf[j++] = srcbuf[i] >> 8;
723                                dstbuf[j++] = srcbuf[i] >> 16;
724                                dstbuf[j++] = srcbuf[i] >> 24;
725                            }
726                            // write from buffer directly (physically) into .gig file
727                            iter->gig_sample->Write(dstbuf, n);
728                            cnt -= n;
729                        }
730                        delete[] srcbuf;
731                        delete[] dstbuf;
732                      break;                      break;
733                    }
734              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
735              // cleanup              // cleanup
736              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
737              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
738              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
739              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 549  void MainWindow::__import_queued_samples Line 748  void MainWindow::__import_queued_samples
748      }      }
749      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
750      if (error_files.size()) {      if (error_files.size()) {
751          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;
752          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
753          msg.run();          msg.run();
754      }      }
# Line 626  void PropDialog::set_info(DLS::Info* inf Line 825  void PropDialog::set_info(DLS::Info* inf
825      entry[15].set_text(info->Subject);      entry[15].set_text(info->Subject);
826  }  }
827    
828    void InstrumentProps::add_prop(BoolEntry& boolentry)
829    {
830        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
831                     Gtk::FILL, Gtk::SHRINK);
832        rowno++;
833        boolentry.signal_changed_by_user().connect(instrument_changed.make_slot());
834    }
835    
836    void InstrumentProps::add_prop(BoolEntryPlus6& boolentry)
837    {
838        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
839                     Gtk::FILL, Gtk::SHRINK);
840        rowno++;
841        boolentry.signal_changed_by_user().connect(instrument_changed.make_slot());
842    }
843    
844  void InstrumentProps::add_prop(LabelWidget& prop)  void InstrumentProps::add_prop(LabelWidget& prop)
845  {  {
846      table.attach(prop.label, 0, 1, rowno, rowno + 1,      table.attach(prop.label, 0, 1, rowno, rowno + 1,
# Line 633  void InstrumentProps::add_prop(LabelWidg Line 848  void InstrumentProps::add_prop(LabelWidg
848      table.attach(prop.widget, 1, 2, rowno, rowno + 1,      table.attach(prop.widget, 1, 2, rowno, rowno + 1,
849                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
850      rowno++;      rowno++;
851        prop.signal_changed_by_user().connect(instrument_changed.make_slot());
852  }  }
853    
854  InstrumentProps::InstrumentProps()  InstrumentProps::InstrumentProps()
855      : table(2,1),      : table(2,1),
856        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
857        eName("Name"),        eName("Name"),
858        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
859        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
860        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
861        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
862        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
863        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
864        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
865        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
866        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
867        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Dimension key range low"),
868        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Dimension key range high")
869  {  {
870      set_title("Instrument properties");      set_title("Instrument properties");
871    
# Line 669  InstrumentProps::InstrumentProps() Line 885  InstrumentProps::InstrumentProps()
885      add_prop(eDimensionKeyRangeLow);      add_prop(eDimensionKeyRangeLow);
886      add_prop(eDimensionKeyRangeHigh);      add_prop(eDimensionKeyRangeHigh);
887    
888      eDimensionKeyRangeLow.signal_value_changed().connect(      eDimensionKeyRangeLow.signal_changed_by_user().connect(
889          sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));          sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));
890      eDimensionKeyRangeHigh.signal_value_changed().connect(      eDimensionKeyRangeHigh.signal_changed_by_user().connect(
891          sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));          sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));
892    
893      add(vbox);      add(vbox);
# Line 696  InstrumentProps::InstrumentProps() Line 912  InstrumentProps::InstrumentProps()
912    
913  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
914  {  {
     update_gui = false;  
915      eName.set_ptr(&instrument->pInfo->Name);      eName.set_ptr(&instrument->pInfo->Name);
916      eIsDrum.set_ptr(&instrument->IsDrum);      eIsDrum.set_ptr(&instrument->IsDrum);
917      eMIDIBank.set_ptr(&instrument->MIDIBank);      eMIDIBank.set_ptr(&instrument->MIDIBank);
# Line 707  void InstrumentProps::set_instrument(gig Line 922  void InstrumentProps::set_instrument(gig
922      eFineTune.set_ptr(&instrument->FineTune);      eFineTune.set_ptr(&instrument->FineTune);
923      ePitchbendRange.set_ptr(&instrument->PitchbendRange);      ePitchbendRange.set_ptr(&instrument->PitchbendRange);
924      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);
925        eDimensionKeyRangeLow.set_ptr(0);
926        eDimensionKeyRangeHigh.set_ptr(0);
927      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);
928      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);
     update_gui = true;  
929  }  }
930    
931  void InstrumentProps::key_range_low_changed()  void InstrumentProps::key_range_low_changed()
# Line 726  void InstrumentProps::key_range_high_cha Line 942  void InstrumentProps::key_range_high_cha
942      if (h < l) eDimensionKeyRangeLow.set_value(h);      if (h < l) eDimensionKeyRangeLow.set_value(h);
943  }  }
944    
945  void MainWindow::load_gig(gig::File* gig, const char* filename)  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
946  {  {
947      file = gig;      return instrument_changed;
948    }
949    
950      if (filename) {  void MainWindow::file_changed()
951          const char *basename = strrchr(filename, '/');  {
952          basename = basename ? basename + 1 : filename;      if (file && !file_is_changed) {
953          set_title(basename);          set_title("*" + get_title());
954      } else {          file_is_changed = true;
         set_title("unnamed");  
955      }      }
956    }
957    
958    void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
959    {
960        file = 0;
961        file_is_shared = isSharedInstrument;
962    
963        this->filename = filename ? filename : _("Unsaved Gig File");
964        set_title(Glib::filename_display_basename(this->filename));
965        file_has_name = filename;
966        file_is_changed = false;
967    
968      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
969    
# Line 785  void MainWindow::load_gig(gig::File* gig Line 1012  void MainWindow::load_gig(gig::File* gig
1012          }          }
1013      }      }
1014    
1015        file = gig;
1016    
1017      // select the first instrument      // select the first instrument
1018      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
1019      tree_sel_ref->select(Gtk::TreePath("0"));      tree_sel_ref->select(Gtk::TreePath("0"));
# Line 858  void MainWindow::on_action_add_instrumen Line 1087  void MainWindow::on_action_add_instrumen
1087      Gtk::TreeModel::Row rowInstr = *iterInstr;      Gtk::TreeModel::Row rowInstr = *iterInstr;
1088      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
1089      rowInstr[m_Columns.m_col_instr] = instrument;      rowInstr[m_Columns.m_col_instr] = instrument;
1090        file_changed();
1091  }  }
1092    
1093  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1094      if (!file) return;      if (!file) return;
1095        if (file_is_shared) {
1096            Gtk::MessageDialog msg(
1097                *this,
1098                 _("You cannot delete an instrument from this file, since it's "
1099                   "currently used by the sampler."),
1100                 false, Gtk::MESSAGE_INFO
1101            );
1102            msg.run();
1103            return;
1104        }
1105    
1106      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1107      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1108      if (it) {      if (it) {
# Line 872  void MainWindow::on_action_remove_instru Line 1113  void MainWindow::on_action_remove_instru
1113              if (instr) file->DeleteInstrument(instr);              if (instr) file->DeleteInstrument(instr);
1114              // remove respective row from instruments tree view              // remove respective row from instruments tree view
1115              m_refTreeModel->erase(it);              m_refTreeModel->erase(it);
1116                file_changed();
1117          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1118              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1119              msg.run();              msg.run();
# Line 900  void MainWindow::on_action_add_group() { Line 1142  void MainWindow::on_action_add_group() {
1142      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1143      rowGroup[m_SamplesModel.m_col_sample] = NULL;      rowGroup[m_SamplesModel.m_col_sample] = NULL;
1144      rowGroup[m_SamplesModel.m_col_group] = group;      rowGroup[m_SamplesModel.m_col_group] = group;
1145        file_changed();
1146  }  }
1147    
1148  void MainWindow::on_action_add_sample() {  void MainWindow::on_action_add_sample() {
# Line 925  void MainWindow::on_action_add_sample() Line 1168  void MainWindow::on_action_add_sample()
1168      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1169      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1170      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1171      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1172          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1173          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1174          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 955  void MainWindow::on_action_add_sample() Line 1198  void MainWindow::on_action_add_sample()
1198                  int bitdepth;                  int bitdepth;
1199                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1200                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1201                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1202                        case SF_FORMAT_PCM_U8:
1203                          bitdepth = 16;                          bitdepth = 16;
1204                          break;                          break;
1205                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1206                      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;  
1207                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1208                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1209                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1210                          break;                          break;
1211                      default:                      default:
1212                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 982  void MainWindow::on_action_add_sample() Line 1215  void MainWindow::on_action_add_sample()
1215                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1216                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1217                  // file name without path                  // file name without path
1218                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1219                    // remove file extension if there is one
1220                    for (int i = 0; supportedFileTypes[i]; i++) {
1221                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1222                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1223                            break;
1224                        }
1225                    }
1226                    sample->pInfo->Name = filename;
1227                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1228                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1229                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1230                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1231                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1232                    sample->BlockAlign = sample->FrameSize;
1233                    sample->SamplesTotal = info.frames;
1234    
1235                    SF_INSTRUMENT instrument;
1236                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1237                                   &instrument, sizeof(instrument)) != SF_FALSE)
1238                    {
1239                        sample->MIDIUnityNote = instrument.basenote;
1240    
1241    #if HAVE_SF_INSTRUMENT_LOOPS
1242                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1243                            sample->Loops = 1;
1244    
1245                            switch (instrument.loops[0].mode) {
1246                            case SF_LOOP_FORWARD:
1247                                sample->LoopType = gig::loop_type_normal;
1248                                break;
1249                            case SF_LOOP_BACKWARD:
1250                                sample->LoopType = gig::loop_type_backward;
1251                                break;
1252                            case SF_LOOP_ALTERNATING:
1253                                sample->LoopType = gig::loop_type_bidirectional;
1254                                break;
1255                            }
1256                            sample->LoopStart = instrument.loops[0].start;
1257                            sample->LoopEnd = instrument.loops[0].end;
1258                            sample->LoopPlayCount = instrument.loops[0].count;
1259                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1260                        }
1261    #endif
1262                    }
1263    
1264                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1265                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1266                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1002  void MainWindow::on_action_add_sample() Line 1276  void MainWindow::on_action_add_sample()
1276                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1277                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1278                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1279                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1280                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1281                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1282                  // close sound file                  // close sound file
1283                  sf_close(hFile);                  sf_close(hFile);
1284                    file_changed();
1285              } 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)
1286                  if (error_files.size()) error_files += "\n";                  if (error_files.size()) error_files += "\n";
1287                  error_files += *iter += " (" + what + ")";                  error_files += *iter += " (" + what + ")";
# Line 1014  void MainWindow::on_action_add_sample() Line 1289  void MainWindow::on_action_add_sample()
1289          }          }
1290          // 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
1291          if (error_files.size()) {          if (error_files.size()) {
1292              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;
1293              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1294              msg.run();              msg.run();
1295          }          }
# Line 1040  void MainWindow::on_action_remove_sample Line 1315  void MainWindow::on_action_remove_sample
1315                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1316                      members.push_back(pSample);                      members.push_back(pSample);
1317                  }                  }
1318                    // notify everybody that we're going to remove these samples
1319                    samples_to_be_removed_signal.emit(members);
1320                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1321                  // samples that belong to the group                  // samples that belong to the group
1322                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1323                    // notify that we're done with removal
1324                    samples_removed_signal.emit();
1325                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1326                  // them from the import queue                  // them from the import queue
1327                  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 1336  void MainWindow::on_action_remove_sample
1336                          }                          }
1337                      }                      }
1338                  }                  }
1339                    file_changed();
1340              } else if (sample) {              } else if (sample) {
1341                    // notify everybody that we're going to remove this sample
1342                    std::list<gig::Sample*> lsamples;
1343                    lsamples.push_back(sample);
1344                    samples_to_be_removed_signal.emit(lsamples);
1345                  // remove sample from the .gig file                  // remove sample from the .gig file
1346                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1347                    // notify that we're done with removal
1348                    samples_removed_signal.emit();
1349                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1350                  // the import queue                  // the import queue
1351                  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 1357  void MainWindow::on_action_remove_sample
1357                          break;                          break;
1358                      }                      }
1359                  }                  }
1360                    dimreg_changed();
1361                    file_changed();
1362              }              }
1363              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1364              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1365          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1366                // pretend we're done with removal (i.e. to avoid dead locks)
1367                samples_removed_signal.emit();
1368                // show error message
1369              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1370              msg.run();              msg.run();
1371          }          }
1372      }      }
1373  }  }
1374    
1375    // For some reason drag_data_get gets called two times for each
1376    // drag'n'drop (at least when target is an Entry). This work-around
1377    // makes sure the code in drag_data_get and drop_drag_data_received is
1378    // only executed once, as drag_begin only gets called once.
1379    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1380    {
1381        first_call_to_drag_data_get = true;
1382    }
1383    
1384  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>&,
1385                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1386  {  {
1387        if (!first_call_to_drag_data_get) return;
1388        first_call_to_drag_data_get = false;
1389    
1390      // get selected sample      // get selected sample
1391      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1392      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 1404  void MainWindow::on_sample_label_drop_dr
1404      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1405      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1406  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1407      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1408    
1409      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1410          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1411              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1412              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1413              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1414                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1415              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1416              context->drop_reply(true, time);  
1417              return;          // notify everybody that we're going to alter the region
1418            gig::Region* region = m_RegionChooser.get_region();
1419            region_to_be_changed_signal.emit(region);
1420    
1421            // find the samplechannel dimension
1422            gig::dimension_def_t* stereo_dimension = 0;
1423            for (int i = 0 ; i < region->Dimensions ; i++) {
1424                if (region->pDimensionDefinitions[i].dimension ==
1425                    gig::dimension_samplechannel) {
1426                    stereo_dimension = &region->pDimensionDefinitions[i];
1427                    break;
1428                }
1429            }
1430            bool channels_changed = false;
1431            if (sample->Channels == 1 && stereo_dimension) {
1432                // remove the samplechannel dimension
1433                region->DeleteDimension(stereo_dimension);
1434                channels_changed = true;
1435                region_changed();
1436            }
1437            dimreg_edit.set_sample(sample);
1438    
1439            if (sample->Channels == 2 && !stereo_dimension) {
1440                // add samplechannel dimension
1441                gig::dimension_def_t dim;
1442                dim.dimension = gig::dimension_samplechannel;
1443                dim.bits = 1;
1444                dim.zones = 2;
1445                region->AddDimension(&dim);
1446                channels_changed = true;
1447                region_changed();
1448            }
1449            if (channels_changed) {
1450                // unmap all samples with wrong number of channels
1451                // TODO: maybe there should be a warning dialog for this
1452                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1453                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1454                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1455                        gig::Sample* oldref = d->pSample;
1456                        d->pSample = NULL;
1457                        sample_ref_changed_signal.emit(oldref, NULL);
1458                    }
1459                }
1460          }          }
1461    
1462            // notify we're done with altering
1463            region_changed_signal.emit(region);
1464    
1465            return;
1466      }      }
1467      // drop failed      // drop failed
1468      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1127  void MainWindow::sample_name_changed(con Line 1476  void MainWindow::sample_name_changed(con
1476      gig::Group* group   = row[m_SamplesModel.m_col_group];      gig::Group* group   = row[m_SamplesModel.m_col_group];
1477      gig::Sample* sample = row[m_SamplesModel.m_col_sample];      gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1478      if (group) {      if (group) {
1479          group->Name = name;          if (group->Name != name) {
1480                group->Name = name;
1481                printf("group name changed\n");
1482                file_changed();
1483            }
1484      } else if (sample) {      } else if (sample) {
1485          sample->pInfo->Name = name.raw();          if (sample->pInfo->Name != name.raw()) {
1486                sample->pInfo->Name = name.raw();
1487                printf("sample name changed\n");
1488                file_changed();
1489            }
1490      }      }
1491  }  }
1492    
# Line 1139  void MainWindow::instrument_name_changed Line 1496  void MainWindow::instrument_name_changed
1496      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1497      Glib::ustring name = row[m_Columns.m_col_name];      Glib::ustring name = row[m_Columns.m_col_name];
1498      gig::Instrument* instrument = row[m_Columns.m_col_instr];      gig::Instrument* instrument = row[m_Columns.m_col_instr];
1499      if (instrument) instrument->pInfo->Name = name.raw();      if (instrument && instrument->pInfo->Name != name.raw()) {
1500            instrument->pInfo->Name = name.raw();
1501            file_changed();
1502        }
1503    }
1504    
1505    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1506        return file_structure_to_be_changed_signal;
1507    }
1508    
1509    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1510        return file_structure_changed_signal;
1511    }
1512    
1513    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1514        return samples_to_be_removed_signal;
1515    }
1516    
1517    sigc::signal<void>& MainWindow::signal_samples_removed() {
1518        return samples_removed_signal;
1519    }
1520    
1521    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1522        return region_to_be_changed_signal;
1523    }
1524    
1525    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1526        return region_changed_signal;
1527    }
1528    
1529    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1530        return sample_ref_changed_signal;
1531    }
1532    
1533    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1534        return dimreg_to_be_changed_signal;
1535    }
1536    
1537    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1538        return dimreg_changed_signal;
1539  }  }

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

  ViewVC Help
Powered by ViewVC