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

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

  ViewVC Help
Powered by ViewVC