/[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 1322 by schoenebeck, Tue Sep 4 11:04:56 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    
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_changed && !close_confirmation_dialog();
312    }
313    
314    void MainWindow::on_action_quit()
315    {
316        if (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 370  void MainWindow::__clear() { Line 435  void MainWindow::__clear() {
435    
436  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
437  {  {
438        if (file_is_changed && !close_confirmation_dialog()) return;
439    
440      // clear all GUI elements      // clear all GUI elements
441      __clear();      __clear();
442      // create a new .gig file (virtually yet)      // create a new .gig file (virtually yet)
# Line 378  void MainWindow::on_action_file_new() Line 445  void MainWindow::on_action_file_new()
445      gig::Instrument* pInstrument = pFile->AddInstrument();      gig::Instrument* pInstrument = pFile->AddInstrument();
446      pInstrument->pInfo->Name = "Unnamed Instrument";      pInstrument->pInfo->Name = "Unnamed Instrument";
447      // update GUI with that new gig::File      // update GUI with that new gig::File
448      load_gig(pFile, NULL /*no file name yet*/);      load_gig(pFile, 0 /*no file name yet*/);
449    }
450    
451    bool MainWindow::close_confirmation_dialog()
452    {
453        gchar* msg = g_strdup_printf(_("Save changes to \"%s\" before closing?"),
454                                     Glib::filename_display_basename(filename).c_str());
455        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
456        g_free(msg);
457    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
458        dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));
459    #endif
460        dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
461        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
462        dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);
463        dialog.set_default_response(Gtk::RESPONSE_YES);
464        int response = dialog.run();
465        dialog.hide();
466        if (response == Gtk::RESPONSE_YES) return file_save();
467        return response != Gtk::RESPONSE_CANCEL;
468  }  }
469    
470  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
471  {  {
472        if (file_is_changed && !close_confirmation_dialog()) return;
473    
474      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
475      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
476      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
477        dialog.set_default_response(Gtk::RESPONSE_OK);
478      Gtk::FileFilter filter;      Gtk::FileFilter filter;
479      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
480      dialog.set_filter(filter);      dialog.set_filter(filter);
481        if (current_dir != "") {
482            dialog.set_current_folder(current_dir);
483        }
484      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
485          printf("filename=%s\n", dialog.get_filename().c_str());          std::string filename = dialog.get_filename();
486          __clear();          printf("filename=%s\n", filename.c_str());
487          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
488          load_file(dialog.get_filename().c_str());          load_file(filename.c_str());
489            current_dir = Glib::path_get_dirname(filename);
490      }      }
491  }  }
492    
493  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
494  {  {
495        __clear();
496      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
497      load_dialog->show_all();      load_dialog->show_all();
498      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 417  void MainWindow::load_instrument(gig::In Line 511  void MainWindow::load_instrument(gig::In
511          Gtk::Main::quit();          Gtk::Main::quit();
512      }      }
513      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
514      load_gig(pFile, NULL /*file name*/);      load_gig(pFile, 0 /*file name*/);
515      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
516  }  }
517    
# Line 436  void MainWindow::on_loader_finished() Line 530  void MainWindow::on_loader_finished()
530    
531  void MainWindow::on_action_file_save()  void MainWindow::on_action_file_save()
532  {  {
533      if (!file) return;      file_save();
534    }
535    
536    bool MainWindow::check_if_savable()
537    {
538        if (!file) return false;
539    
540        if (!file->GetFirstSample()) {
541            Gtk::MessageDialog(*this, _("The file could not be saved "
542                                        "because it contains no samples"),
543                               false, Gtk::MESSAGE_ERROR).run();
544            return false;
545        }
546    
547        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
548             instrument = file->GetNextInstrument()) {
549            if (!instrument->GetFirstRegion()) {
550                Gtk::MessageDialog(*this, _("The file could not be saved "
551                                            "because there are instruments "
552                                            "that have no regions"),
553                                   false, Gtk::MESSAGE_ERROR).run();
554                return false;
555            }
556        }
557        return true;
558    }
559    
560    bool MainWindow::file_save()
561    {
562        if (!check_if_savable()) return false;
563        if (!file_has_name) return file_save_as();
564    
565      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
566        file_structure_to_be_changed_signal.emit(this->file);
567      try {      try {
568          file->Save();          file->Save();
569            if (file_is_changed) {
570                set_title(get_title().substr(1));
571                file_is_changed = false;
572            }
573      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
574            file_structure_changed_signal.emit(this->file);
575          Glib::ustring txt = "Could not save file: " + e.Message;          Glib::ustring txt = "Could not save file: " + e.Message;
576          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
577          msg.run();          msg.run();
578          return;          return false;
579      }      }
580      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
581      __import_queued_samples();      __import_queued_samples();
582        file_structure_changed_signal.emit(this->file);
583        return true;
584  }  }
585    
586  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
587  {  {
588      if (!file) return;      if (!check_if_savable()) return;
589      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);      file_save_as();
590    }
591    
592    bool MainWindow::file_save_as()
593    {
594        Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
595      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
596      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
597        dialog.set_default_response(Gtk::RESPONSE_OK);
598    
599    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 2
600        dialog.set_do_overwrite_confirmation();
601        // TODO: an overwrite dialog for gtkmm < 2.8
602    #endif
603      Gtk::FileFilter filter;      Gtk::FileFilter filter;
604      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
605      dialog.set_filter(filter);      dialog.set_filter(filter);
606    
607        if (Glib::path_is_absolute(filename)) {
608            dialog.set_filename(filename);
609        } else if (current_dir != "") {
610            dialog.set_current_folder(current_dir);
611        }
612        dialog.set_current_name(Glib::filename_display_basename(filename));
613    
614      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
615          printf("filename=%s\n", dialog.get_filename().c_str());          file_structure_to_be_changed_signal.emit(this->file);
616          try {          try {
617              file->Save(dialog.get_filename());              std::string filename = dialog.get_filename();
618                if (!Glib::str_has_suffix(filename, ".gig")) {
619                    filename += ".gig";
620                }
621                printf("filename=%s\n", filename.c_str());
622                file->Save(filename);
623                this->filename = filename;
624                current_dir = Glib::path_get_dirname(filename);
625                set_title(Glib::filename_display_basename(filename));
626                file_has_name = true;
627                file_is_changed = false;
628          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
629                file_structure_changed_signal.emit(this->file);
630              Glib::ustring txt = "Could not save file: " + e.Message;              Glib::ustring txt = "Could not save file: " + e.Message;
631              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
632              msg.run();              msg.run();
633              return;              return false;
634          }          }
635          __import_queued_samples();          __import_queued_samples();
636            file_structure_changed_signal.emit(this->file);
637            return true;
638      }      }
639        return false;
640  }  }
641    
642  // 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 656  void MainWindow::__import_queued_samples
656              int bitdepth;              int bitdepth;
657              switch (info.format & 0xff) {              switch (info.format & 0xff) {
658                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
659                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
660                    case SF_FORMAT_PCM_U8:
661                      bitdepth = 16;                      bitdepth = 16;
662                      break;                      break;
663                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
664                  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;  
665                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
666                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
667                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
668                      break;                      break;
669                  default:                  default:
670                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
671                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
672              }              }
673              // allocate appropriate copy buffer (TODO: for now we copy  
674              // 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;  
675              switch (bitdepth) {              switch (bitdepth) {
676                  case 16:                  case 16: {
677                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
678                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
679                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
680                            // libsndfile does the conversion for us (if needed)
681                            int n = sf_readf_short(hFile, buffer, bufsize);
682                            // write from buffer directly (physically) into .gig file
683                            iter->gig_sample->Write(buffer, n);
684                            cnt -= n;
685                        }
686                        delete[] buffer;
687                      break;                      break;
688                  case 32:                  }
689                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
690                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
691                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
692                        sf_count_t cnt = info.frames;
693                        while (cnt) {
694                            // libsndfile returns 32 bits, convert to 24
695                            int n = sf_readf_int(hFile, srcbuf, bufsize);
696                            int j = 0;
697                            for (int i = 0 ; i < n * info.channels ; i++) {
698                                dstbuf[j++] = srcbuf[i] >> 8;
699                                dstbuf[j++] = srcbuf[i] >> 16;
700                                dstbuf[j++] = srcbuf[i] >> 24;
701                            }
702                            // write from buffer directly (physically) into .gig file
703                            iter->gig_sample->Write(dstbuf, n);
704                            cnt -= n;
705                        }
706                        delete[] srcbuf;
707                        delete[] dstbuf;
708                      break;                      break;
709                    }
710              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
711              // cleanup              // cleanup
712              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
713              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
714              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
715              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 626  void PropDialog::set_info(DLS::Info* inf Line 801  void PropDialog::set_info(DLS::Info* inf
801      entry[15].set_text(info->Subject);      entry[15].set_text(info->Subject);
802  }  }
803    
804    void InstrumentProps::add_prop(BoolEntry& boolentry)
805    {
806        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
807                     Gtk::FILL, Gtk::SHRINK);
808        rowno++;
809        boolentry.signal_changed_by_user().connect(instrument_changed.make_slot());
810    }
811    
812    void InstrumentProps::add_prop(BoolEntryPlus6& boolentry)
813    {
814        table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
815                     Gtk::FILL, Gtk::SHRINK);
816        rowno++;
817        boolentry.signal_changed_by_user().connect(instrument_changed.make_slot());
818    }
819    
820  void InstrumentProps::add_prop(LabelWidget& prop)  void InstrumentProps::add_prop(LabelWidget& prop)
821  {  {
822      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 824  void InstrumentProps::add_prop(LabelWidg
824      table.attach(prop.widget, 1, 2, rowno, rowno + 1,      table.attach(prop.widget, 1, 2, rowno, rowno + 1,
825                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
826      rowno++;      rowno++;
827        prop.signal_changed_by_user().connect(instrument_changed.make_slot());
828  }  }
829    
830  InstrumentProps::InstrumentProps()  InstrumentProps::InstrumentProps()
831      : table(2,1),      : table(2,1),
832        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
833        eName("Name"),        eName("Name"),
834        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
835        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
836        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
837        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
838        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
839        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
840        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
841        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
842        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
843        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Dimension key range low"),
844        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Dimension key range high")
845  {  {
846      set_title("Instrument properties");      set_title("Instrument properties");
847    
# Line 669  InstrumentProps::InstrumentProps() Line 861  InstrumentProps::InstrumentProps()
861      add_prop(eDimensionKeyRangeLow);      add_prop(eDimensionKeyRangeLow);
862      add_prop(eDimensionKeyRangeHigh);      add_prop(eDimensionKeyRangeHigh);
863    
864      eDimensionKeyRangeLow.signal_value_changed().connect(      eDimensionKeyRangeLow.signal_changed_by_user().connect(
865          sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));          sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));
866      eDimensionKeyRangeHigh.signal_value_changed().connect(      eDimensionKeyRangeHigh.signal_changed_by_user().connect(
867          sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));          sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));
868    
869      add(vbox);      add(vbox);
# Line 696  InstrumentProps::InstrumentProps() Line 888  InstrumentProps::InstrumentProps()
888    
889  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
890  {  {
     update_gui = false;  
891      eName.set_ptr(&instrument->pInfo->Name);      eName.set_ptr(&instrument->pInfo->Name);
892      eIsDrum.set_ptr(&instrument->IsDrum);      eIsDrum.set_ptr(&instrument->IsDrum);
893      eMIDIBank.set_ptr(&instrument->MIDIBank);      eMIDIBank.set_ptr(&instrument->MIDIBank);
# Line 707  void InstrumentProps::set_instrument(gig Line 898  void InstrumentProps::set_instrument(gig
898      eFineTune.set_ptr(&instrument->FineTune);      eFineTune.set_ptr(&instrument->FineTune);
899      ePitchbendRange.set_ptr(&instrument->PitchbendRange);      ePitchbendRange.set_ptr(&instrument->PitchbendRange);
900      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);
901        eDimensionKeyRangeLow.set_ptr(0);
902        eDimensionKeyRangeHigh.set_ptr(0);
903      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);
904      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);
     update_gui = true;  
905  }  }
906    
907  void InstrumentProps::key_range_low_changed()  void InstrumentProps::key_range_low_changed()
# Line 726  void InstrumentProps::key_range_high_cha Line 918  void InstrumentProps::key_range_high_cha
918      if (h < l) eDimensionKeyRangeLow.set_value(h);      if (h < l) eDimensionKeyRangeLow.set_value(h);
919  }  }
920    
921  void MainWindow::load_gig(gig::File* gig, const char* filename)  sigc::signal<void> InstrumentProps::signal_instrument_changed()
922  {  {
923      file = gig;      return instrument_changed;
924    }
925    
926      if (filename) {  void MainWindow::file_changed()
927          const char *basename = strrchr(filename, '/');  {
928          basename = basename ? basename + 1 : filename;      if (file && !file_is_changed) {
929          set_title(basename);          set_title("*" + get_title());
930      } else {          file_is_changed = true;
         set_title("unnamed");  
931      }      }
932    }
933    
934    void MainWindow::load_gig(gig::File* gig, const char* filename)
935    {
936        file = 0;
937    
938        this->filename = filename ? filename : _("Unsaved Gig File");
939        set_title(Glib::filename_display_basename(this->filename));
940        file_has_name = filename;
941        file_is_changed = false;
942    
943      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
944    
# Line 785  void MainWindow::load_gig(gig::File* gig Line 987  void MainWindow::load_gig(gig::File* gig
987          }          }
988      }      }
989    
990        file = gig;
991    
992      // select the first instrument      // select the first instrument
993      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
994      tree_sel_ref->select(Gtk::TreePath("0"));      tree_sel_ref->select(Gtk::TreePath("0"));
# Line 858  void MainWindow::on_action_add_instrumen Line 1062  void MainWindow::on_action_add_instrumen
1062      Gtk::TreeModel::Row rowInstr = *iterInstr;      Gtk::TreeModel::Row rowInstr = *iterInstr;
1063      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
1064      rowInstr[m_Columns.m_col_instr] = instrument;      rowInstr[m_Columns.m_col_instr] = instrument;
1065        file_changed();
1066  }  }
1067    
1068  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
# Line 872  void MainWindow::on_action_remove_instru Line 1077  void MainWindow::on_action_remove_instru
1077              if (instr) file->DeleteInstrument(instr);              if (instr) file->DeleteInstrument(instr);
1078              // remove respective row from instruments tree view              // remove respective row from instruments tree view
1079              m_refTreeModel->erase(it);              m_refTreeModel->erase(it);
1080                file_changed();
1081          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1082              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1083              msg.run();              msg.run();
# Line 900  void MainWindow::on_action_add_group() { Line 1106  void MainWindow::on_action_add_group() {
1106      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1107      rowGroup[m_SamplesModel.m_col_sample] = NULL;      rowGroup[m_SamplesModel.m_col_sample] = NULL;
1108      rowGroup[m_SamplesModel.m_col_group] = group;      rowGroup[m_SamplesModel.m_col_group] = group;
1109        file_changed();
1110  }  }
1111    
1112  void MainWindow::on_action_add_sample() {  void MainWindow::on_action_add_sample() {
# Line 925  void MainWindow::on_action_add_sample() Line 1132  void MainWindow::on_action_add_sample()
1132      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1133      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1134      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1135      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1136          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1137          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1138          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 955  void MainWindow::on_action_add_sample() Line 1162  void MainWindow::on_action_add_sample()
1162                  int bitdepth;                  int bitdepth;
1163                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1164                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1165                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1166                        case SF_FORMAT_PCM_U8:
1167                          bitdepth = 16;                          bitdepth = 16;
1168                          break;                          break;
1169                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1170                      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;  
1171                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1172                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1173                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1174                          break;                          break;
1175                      default:                      default:
1176                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 982  void MainWindow::on_action_add_sample() Line 1179  void MainWindow::on_action_add_sample()
1179                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1180                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1181                  // file name without path                  // file name without path
1182                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1183                    // remove file extension if there is one
1184                    for (int i = 0; supportedFileTypes[i]; i++) {
1185                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1186                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1187                            break;
1188                        }
1189                    }
1190                    sample->pInfo->Name = filename;
1191                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1192                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1193                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1194                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1195                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1196                    sample->BlockAlign = sample->FrameSize;
1197                    sample->SamplesTotal = info.frames;
1198    
1199                    SF_INSTRUMENT instrument;
1200                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1201                                   &instrument, sizeof(instrument)) != SF_FALSE)
1202                    {
1203                        sample->MIDIUnityNote = instrument.basenote;
1204    
1205    #if HAVE_SF_INSTRUMENT_LOOPS
1206                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1207                            sample->Loops = 1;
1208    
1209                            switch (instrument.loops[0].mode) {
1210                            case SF_LOOP_FORWARD:
1211                                sample->LoopType = gig::loop_type_normal;
1212                                break;
1213                            case SF_LOOP_BACKWARD:
1214                                sample->LoopType = gig::loop_type_backward;
1215                                break;
1216                            case SF_LOOP_ALTERNATING:
1217                                sample->LoopType = gig::loop_type_bidirectional;
1218                                break;
1219                            }
1220                            sample->LoopStart = instrument.loops[0].start;
1221                            sample->LoopEnd = instrument.loops[0].end;
1222                            sample->LoopPlayCount = instrument.loops[0].count;
1223                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1224                        }
1225    #endif
1226                    }
1227    
1228                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1229                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1230                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1002  void MainWindow::on_action_add_sample() Line 1240  void MainWindow::on_action_add_sample()
1240                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1241                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1242                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1243                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1244                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1245                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1246                  // close sound file                  // close sound file
1247                  sf_close(hFile);                  sf_close(hFile);
1248                    file_changed();
1249              } 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)
1250                  if (error_files.size()) error_files += "\n";                  if (error_files.size()) error_files += "\n";
1251                  error_files += *iter += " (" + what + ")";                  error_files += *iter += " (" + what + ")";
# Line 1040  void MainWindow::on_action_remove_sample Line 1279  void MainWindow::on_action_remove_sample
1279                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1280                      members.push_back(pSample);                      members.push_back(pSample);
1281                  }                  }
1282                    // notify everybody that we're going to remove these samples
1283                    samples_to_be_removed_signal.emit(members);
1284                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1285                  // samples that belong to the group                  // samples that belong to the group
1286                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1287                    // notify that we're done with removal
1288                    samples_removed_signal.emit();
1289                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1290                  // them from the import queue                  // them from the import queue
1291                  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 1300  void MainWindow::on_action_remove_sample
1300                          }                          }
1301                      }                      }
1302                  }                  }
1303                    file_changed();
1304              } else if (sample) {              } else if (sample) {
1305                    // notify everybody that we're going to remove this sample
1306                    std::list<gig::Sample*> lsamples;
1307                    lsamples.push_back(sample);
1308                    samples_to_be_removed_signal.emit(lsamples);
1309                  // remove sample from the .gig file                  // remove sample from the .gig file
1310                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1311                    // notify that we're done with removal
1312                    samples_removed_signal.emit();
1313                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1314                  // the import queue                  // the import queue
1315                  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 1321  void MainWindow::on_action_remove_sample
1321                          break;                          break;
1322                      }                      }
1323                  }                  }
1324                    dimreg_changed();
1325                    file_changed();
1326              }              }
1327              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1328              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1329          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1330                // pretend we're done with removal (i.e. to avoid dead locks)
1331                samples_removed_signal.emit();
1332                // show error message
1333              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1334              msg.run();              msg.run();
1335          }          }
1336      }      }
1337  }  }
1338    
1339    // For some reason drag_data_get gets called two times for each
1340    // drag'n'drop (at least when target is an Entry). This work-around
1341    // makes sure the code in drag_data_get and drop_drag_data_received is
1342    // only executed once, as drag_begin only gets called once.
1343    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1344    {
1345        first_call_to_drag_data_get = true;
1346    }
1347    
1348  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>&,
1349                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1350  {  {
1351        if (!first_call_to_drag_data_get) return;
1352        first_call_to_drag_data_get = false;
1353    
1354      // get selected sample      // get selected sample
1355      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1356      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 1368  void MainWindow::on_sample_label_drop_dr
1368      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1369      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1370  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1371      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1372    
1373      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1374          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1375              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1376              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1377              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1378                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1379              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1380              context->drop_reply(true, time);  
1381              return;          // notify everybody that we're going to alter the region
1382            gig::Region* region = m_RegionChooser.get_region();
1383            region_to_be_changed_signal.emit(region);
1384    
1385            // find the samplechannel dimension
1386            gig::dimension_def_t* stereo_dimension = 0;
1387            for (int i = 0 ; i < region->Dimensions ; i++) {
1388                if (region->pDimensionDefinitions[i].dimension ==
1389                    gig::dimension_samplechannel) {
1390                    stereo_dimension = &region->pDimensionDefinitions[i];
1391                    break;
1392                }
1393            }
1394            bool channels_changed = false;
1395            if (sample->Channels == 1 && stereo_dimension) {
1396                // remove the samplechannel dimension
1397                region->DeleteDimension(stereo_dimension);
1398                channels_changed = true;
1399                region_changed();
1400            }
1401            dimreg_edit.set_sample(sample);
1402    
1403            if (sample->Channels == 2 && !stereo_dimension) {
1404                // add samplechannel dimension
1405                gig::dimension_def_t dim;
1406                dim.dimension = gig::dimension_samplechannel;
1407                dim.bits = 1;
1408                dim.zones = 2;
1409                region->AddDimension(&dim);
1410                channels_changed = true;
1411                region_changed();
1412          }          }
1413            if (channels_changed) {
1414                // unmap all samples with wrong number of channels
1415                // TODO: maybe there should be a warning dialog for this
1416                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1417                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1418                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1419                        gig::Sample* oldref = d->pSample;
1420                        d->pSample = NULL;
1421                        sample_ref_changed_signal.emit(oldref, NULL);
1422                    }
1423                }
1424            }
1425    
1426            // notify we're done with altering
1427            region_changed_signal.emit(region);
1428    
1429            return;
1430      }      }
1431      // drop failed      // drop failed
1432      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1127  void MainWindow::sample_name_changed(con Line 1440  void MainWindow::sample_name_changed(con
1440      gig::Group* group   = row[m_SamplesModel.m_col_group];      gig::Group* group   = row[m_SamplesModel.m_col_group];
1441      gig::Sample* sample = row[m_SamplesModel.m_col_sample];      gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1442      if (group) {      if (group) {
1443          group->Name = name;          if (group->Name != name) {
1444                group->Name = name;
1445                printf("group name changed\n");
1446                file_changed();
1447            }
1448      } else if (sample) {      } else if (sample) {
1449          sample->pInfo->Name = name.raw();          if (sample->pInfo->Name != name.raw()) {
1450                sample->pInfo->Name = name.raw();
1451                printf("sample name changed\n");
1452                file_changed();
1453            }
1454      }      }
1455  }  }
1456    
# Line 1139  void MainWindow::instrument_name_changed Line 1460  void MainWindow::instrument_name_changed
1460      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1461      Glib::ustring name = row[m_Columns.m_col_name];      Glib::ustring name = row[m_Columns.m_col_name];
1462      gig::Instrument* instrument = row[m_Columns.m_col_instr];      gig::Instrument* instrument = row[m_Columns.m_col_instr];
1463      if (instrument) instrument->pInfo->Name = name.raw();      if (instrument && instrument->pInfo->Name != name.raw()) {
1464            instrument->pInfo->Name = name.raw();
1465            file_changed();
1466        }
1467    }
1468    
1469    sigc::signal<void, gig::File*> MainWindow::signal_file_structure_to_be_changed() {
1470        return file_structure_to_be_changed_signal;
1471    }
1472    
1473    sigc::signal<void, gig::File*> MainWindow::signal_file_structure_changed() {
1474        return file_structure_changed_signal;
1475    }
1476    
1477    sigc::signal<void, std::list<gig::Sample*> > MainWindow::signal_samples_to_be_removed() {
1478        return samples_to_be_removed_signal;
1479    }
1480    
1481    sigc::signal<void> MainWindow::signal_samples_removed() {
1482        return samples_removed_signal;
1483    }
1484    
1485    sigc::signal<void, gig::Region*> MainWindow::signal_region_to_be_changed() {
1486        return region_to_be_changed_signal;
1487    }
1488    
1489    sigc::signal<void, gig::Region*> MainWindow::signal_region_changed() {
1490        return region_changed_signal;
1491    }
1492    
1493    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/> MainWindow::signal_sample_ref_changed() {
1494        return sample_ref_changed_signal;
1495    }
1496    
1497    sigc::signal<void, gig::DimensionRegion*> MainWindow::signal_dimreg_to_be_changed() {
1498        return dimreg_to_be_changed_signal;
1499    }
1500    
1501    sigc::signal<void, gig::DimensionRegion*> MainWindow::signal_dimreg_changed() {
1502        return dimreg_changed_signal;
1503  }  }

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

  ViewVC Help
Powered by ViewVC