/[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 1382 by schoenebeck, Thu Oct 4 23:29:22 2007 UTC
# Line 26  Line 26 
26  #include <gtkmm/targetentry.h>  #include <gtkmm/targetentry.h>
27  #include <gtkmm/main.h>  #include <gtkmm/main.h>
28    
29  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
30  #define ABOUT_DIALOG  #define ABOUT_DIALOG
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 99  MainWindow::MainWindow() Line 111  MainWindow::MainWindow()
111      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);
112      action->property_label() = action->property_label() + "...";      action->property_label() = action->property_label() + "...";
113      actionGroup->add(action,      actionGroup->add(action,
114                       *(new Gtk::AccelKey("<shift><control>s")),                       Gtk::AccelKey("<shift><control>s"),
115                       sigc::mem_fun(                       sigc::mem_fun(
116                           *this, &MainWindow::on_action_file_save_as)                           *this, &MainWindow::on_action_file_save_as));
         );  
117      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
118                                           Gtk::Stock::PROPERTIES),                                           Gtk::Stock::PROPERTIES),
119                       sigc::mem_fun(                       sigc::mem_fun(
# Line 113  MainWindow::MainWindow() Line 124  MainWindow::MainWindow()
124                           *this, &MainWindow::show_instr_props));                           *this, &MainWindow::show_instr_props));
125      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
126                       sigc::mem_fun(                       sigc::mem_fun(
127                           *this, &MainWindow::hide));                           *this, &MainWindow::on_action_quit));
128      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
129    
130      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
# Line 153  MainWindow::MainWindow() Line 164  MainWindow::MainWindow()
164    
165      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
166      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
167      // add_accel_group(uiManager->get_accel_group());      add_accel_group(uiManager->get_accel_group());
168    
169      Glib::ustring ui_info =      Glib::ustring ui_info =
170          "<ui>"          "<ui>"
# Line 201  MainWindow::MainWindow() Line 212  MainWindow::MainWindow()
212      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
213      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
214    
215      m_RegionChooser.signal_sel_changed().connect(      m_RegionChooser.signal_region_selected().connect(
216          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
217      m_DimRegionChooser.signal_sel_changed().connect(      m_DimRegionChooser.signal_dimregion_selected().connect(
218          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );
219    
220    
# Line 235  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 256  MainWindow::MainWindow()
256      dimreg_edit.wSample->signal_drag_data_received().connect(      dimreg_edit.wSample->signal_drag_data_received().connect(
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(
260            sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
261        m_RegionChooser.signal_instrument_changed().connect(
262            sigc::mem_fun(*this, &MainWindow::file_changed));
263        m_DimRegionChooser.signal_region_changed().connect(
264            sigc::mem_fun(*this, &MainWindow::file_changed));
265        instrumentProps.signal_instrument_changed().connect(
266            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;
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()
307  {  {
308  }  }
309    
310    bool MainWindow::on_delete_event(GdkEventAny* event)
311    {
312        return !file_is_shared && file_is_changed && !close_confirmation_dialog();
313    }
314    
315    void MainWindow::on_action_quit()
316    {
317        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
318        hide();
319    }
320    
321  void MainWindow::region_changed()  void MainWindow::region_changed()
322  {  {
323      m_DimRegionChooser.set_region(m_RegionChooser.get_region());      m_DimRegionChooser.set_region(m_RegionChooser.get_region());
# Line 362  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_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();
444      // create a new .gig file (virtually yet)      // create a new .gig file (virtually yet)
# Line 378  void MainWindow::on_action_file_new() Line 447  void MainWindow::on_action_file_new()
447      gig::Instrument* pInstrument = pFile->AddInstrument();      gig::Instrument* pInstrument = pFile->AddInstrument();
448      pInstrument->pInfo->Name = "Unnamed Instrument";      pInstrument->pInfo->Name = "Unnamed Instrument";
449      // update GUI with that new gig::File      // update GUI with that new gig::File
450      load_gig(pFile, NULL /*no file name yet*/);      load_gig(pFile, 0 /*no file name yet*/);
451    }
452    
453    bool MainWindow::close_confirmation_dialog()
454    {
455        gchar* msg = g_strdup_printf(_("Save changes to \"%s\" before closing?"),
456                                     Glib::filename_display_basename(filename).c_str());
457        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
458        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."));
461    #endif
462        dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
463        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);
465        dialog.set_default_response(Gtk::RESPONSE_YES);
466        int response = dialog.run();
467        dialog.hide();
468        if (response == Gtk::RESPONSE_YES) return file_save();
469        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_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);
498      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
499        dialog.set_default_response(Gtk::RESPONSE_OK);
500      Gtk::FileFilter filter;      Gtk::FileFilter filter;
501      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
502      dialog.set_filter(filter);      dialog.set_filter(filter);
503        if (current_dir != "") {
504            dialog.set_current_folder(current_dir);
505        }
506      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
507          printf("filename=%s\n", dialog.get_filename().c_str());          std::string filename = dialog.get_filename();
508          __clear();          printf("filename=%s\n", filename.c_str());
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(dialog.get_filename().c_str());          load_file(filename.c_str());
511            current_dir = Glib::path_get_dirname(filename);
512      }      }
513  }  }
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 416  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, NULL /*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 436  void MainWindow::on_loader_finished() Line 555  void MainWindow::on_loader_finished()
555    
556  void MainWindow::on_action_file_save()  void MainWindow::on_action_file_save()
557  {  {
558      if (!file) return;      file_save();
559    }
560    
561    bool MainWindow::check_if_savable()
562    {
563        if (!file) return false;
564    
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) {
595                set_title(get_title().substr(1));
596                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;          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;
609  }  }
610    
611  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
612  {  {
613      if (!file) return;      if (!check_if_savable()) return;
614      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);      file_save_as();
615    }
616    
617    bool MainWindow::file_save_as()
618    {
619        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);
622        dialog.set_default_response(Gtk::RESPONSE_OK);
623    
624    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 2
625        dialog.set_do_overwrite_confirmation();
626        // TODO: an overwrite dialog for gtkmm < 2.8
627    #endif
628      Gtk::FileFilter filter;      Gtk::FileFilter filter;
629      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
630      dialog.set_filter(filter);      dialog.set_filter(filter);
631    
632        if (Glib::path_is_absolute(filename)) {
633            dialog.set_filename(filename);
634        } else if (current_dir != "") {
635            dialog.set_current_folder(current_dir);
636        }
637        dialog.set_current_name(Glib::filename_display_basename(filename));
638    
639      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
640          printf("filename=%s\n", dialog.get_filename().c_str());          file_structure_to_be_changed_signal.emit(this->file);
641          try {          try {
642              file->Save(dialog.get_filename());              std::string filename = dialog.get_filename();
643                if (!Glib::str_has_suffix(filename, ".gig")) {
644                    filename += ".gig";
645                }
646                printf("filename=%s\n", filename.c_str());
647                file->Save(filename);
648                this->filename = filename;
649                current_dir = Glib::path_get_dirname(filename);
650                set_title(Glib::filename_display_basename(filename));
651                file_has_name = true;
652                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;              return false;
659          }          }
660          __import_queued_samples();          __import_queued_samples();
661            file_structure_changed_signal.emit(this->file);
662            return true;
663      }      }
664        return false;
665  }  }
666    
667  // 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 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 549  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 626  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 633  void InstrumentProps::add_prop(LabelWidg Line 849  void InstrumentProps::add_prop(LabelWidg
849      table.attach(prop.widget, 1, 2, rowno, rowno + 1,      table.attach(prop.widget, 1, 2, rowno, rowno + 1,
850                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
851      rowno++;      rowno++;
852        prop.signal_changed_by_user().connect(instrument_changed.make_slot());
853  }  }
854    
855  InstrumentProps::InstrumentProps()  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 669  InstrumentProps::InstrumentProps() Line 886  InstrumentProps::InstrumentProps()
886      add_prop(eDimensionKeyRangeLow);      add_prop(eDimensionKeyRangeLow);
887      add_prop(eDimensionKeyRangeHigh);      add_prop(eDimensionKeyRangeHigh);
888    
889      eDimensionKeyRangeLow.signal_value_changed().connect(      eDimensionKeyRangeLow.signal_changed_by_user().connect(
890          sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));          sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));
891      eDimensionKeyRangeHigh.signal_value_changed().connect(      eDimensionKeyRangeHigh.signal_changed_by_user().connect(
892          sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));          sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));
893    
894      add(vbox);      add(vbox);
# Line 696  InstrumentProps::InstrumentProps() Line 913  InstrumentProps::InstrumentProps()
913    
914  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
915  {  {
     update_gui = false;  
916      eName.set_ptr(&instrument->pInfo->Name);      eName.set_ptr(&instrument->pInfo->Name);
917      eIsDrum.set_ptr(&instrument->IsDrum);      eIsDrum.set_ptr(&instrument->IsDrum);
918      eMIDIBank.set_ptr(&instrument->MIDIBank);      eMIDIBank.set_ptr(&instrument->MIDIBank);
# Line 707  void InstrumentProps::set_instrument(gig Line 923  void InstrumentProps::set_instrument(gig
923      eFineTune.set_ptr(&instrument->FineTune);      eFineTune.set_ptr(&instrument->FineTune);
924      ePitchbendRange.set_ptr(&instrument->PitchbendRange);      ePitchbendRange.set_ptr(&instrument->PitchbendRange);
925      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);
926        eDimensionKeyRangeLow.set_ptr(0);
927        eDimensionKeyRangeHigh.set_ptr(0);
928      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);
929      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);
     update_gui = true;  
930  }  }
931    
932  void InstrumentProps::key_range_low_changed()  void InstrumentProps::key_range_low_changed()
# Line 726  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  void MainWindow::load_gig(gig::File* gig, const char* filename)  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
947  {  {
948      file = gig;      return instrument_changed;
949    }
950    
951      if (filename) {  void MainWindow::file_changed()
952          const char *basename = strrchr(filename, '/');  {
953          basename = basename ? basename + 1 : filename;      if (file && !file_is_changed) {
954          set_title(basename);          set_title("*" + get_title());
955      } else {          file_is_changed = true;
         set_title("unnamed");  
956      }      }
957    }
958    
959    void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
960    {
961        file = 0;
962        file_is_shared = isSharedInstrument;
963    
964        this->filename = filename ? filename : _("Unsaved Gig File");
965        set_title(Glib::filename_display_basename(this->filename));
966        file_has_name = filename;
967        file_is_changed = false;
968    
969      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
970    
# Line 785  void MainWindow::load_gig(gig::File* gig Line 1013  void MainWindow::load_gig(gig::File* gig
1013          }          }
1014      }      }
1015    
1016        file = gig;
1017    
1018      // select the first instrument      // select the first instrument
1019      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
1020      tree_sel_ref->select(Gtk::TreePath("0"));      tree_sel_ref->select(Gtk::TreePath("0"));
# Line 858  void MainWindow::on_action_add_instrumen Line 1088  void MainWindow::on_action_add_instrumen
1088      Gtk::TreeModel::Row rowInstr = *iterInstr;      Gtk::TreeModel::Row rowInstr = *iterInstr;
1089      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
1090      rowInstr[m_Columns.m_col_instr] = instrument;      rowInstr[m_Columns.m_col_instr] = instrument;
1091        file_changed();
1092  }  }
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 872  void MainWindow::on_action_remove_instru Line 1114  void MainWindow::on_action_remove_instru
1114              if (instr) file->DeleteInstrument(instr);              if (instr) file->DeleteInstrument(instr);
1115              // remove respective row from instruments tree view              // remove respective row from instruments tree view
1116              m_refTreeModel->erase(it);              m_refTreeModel->erase(it);
1117                file_changed();
1118          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1119              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1120              msg.run();              msg.run();
# Line 900  void MainWindow::on_action_add_group() { Line 1143  void MainWindow::on_action_add_group() {
1143      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1144      rowGroup[m_SamplesModel.m_col_sample] = NULL;      rowGroup[m_SamplesModel.m_col_sample] = NULL;
1145      rowGroup[m_SamplesModel.m_col_group] = group;      rowGroup[m_SamplesModel.m_col_group] = group;
1146        file_changed();
1147  }  }
1148    
1149  void MainWindow::on_action_add_sample() {  void MainWindow::on_action_add_sample() {
# Line 925  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 955  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 982  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 1002  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
1284                  sf_close(hFile);                  sf_close(hFile);
1285                    file_changed();
1286              } 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)
1287                  if (error_files.size()) error_files += "\n";                  if (error_files.size()) error_files += "\n";
1288                  error_files += *iter += " (" + what + ")";                  error_files += *iter += " (" + what + ")";
# Line 1014  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 1040  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 1057  void MainWindow::on_action_remove_sample Line 1337  void MainWindow::on_action_remove_sample
1337                          }                          }
1338                      }                      }
1339                  }                  }
1340                    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 1071  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();
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 1101  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              return;          // notify everybody that we're going to alter the region
1419            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 1127  void MainWindow::sample_name_changed(con Line 1477  void MainWindow::sample_name_changed(con
1477      gig::Group* group   = row[m_SamplesModel.m_col_group];      gig::Group* group   = row[m_SamplesModel.m_col_group];
1478      gig::Sample* sample = row[m_SamplesModel.m_col_sample];      gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1479      if (group) {      if (group) {
1480          group->Name = name;          if (group->Name != name) {
1481                group->Name = name;
1482                printf("group name changed\n");
1483                file_changed();
1484            }
1485      } else if (sample) {      } else if (sample) {
1486          sample->pInfo->Name = name.raw();          if (sample->pInfo->Name != name.raw()) {
1487                sample->pInfo->Name = name.raw();
1488                printf("sample name changed\n");
1489                file_changed();
1490            }
1491      }      }
1492  }  }
1493    
# Line 1139  void MainWindow::instrument_name_changed Line 1497  void MainWindow::instrument_name_changed
1497      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1498      Glib::ustring name = row[m_Columns.m_col_name];      Glib::ustring name = row[m_Columns.m_col_name];
1499      gig::Instrument* instrument = row[m_Columns.m_col_instr];      gig::Instrument* instrument = row[m_Columns.m_col_instr];
1500      if (instrument) instrument->pInfo->Name = name.raw();      if (instrument && instrument->pInfo->Name != name.raw()) {
1501            instrument->pInfo->Name = name.raw();
1502            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.1225  
changed lines
  Added in v.1382

  ViewVC Help
Powered by ViewVC