/[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 1661 by schoenebeck, Sun Feb 3 14:10:47 2008 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006 - 2008 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
 #include <libintl.h>  
20  #include <iostream>  #include <iostream>
21    
22  #include <gtkmm/filechooserdialog.h>  #include <gtkmm/filechooserdialog.h>
# Line 25  Line 24 
24  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
25  #include <gtkmm/targetentry.h>  #include <gtkmm/targetentry.h>
26  #include <gtkmm/main.h>  #include <gtkmm/main.h>
27    #include <gtkmm/toggleaction.h>
28    
29  #if GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6  #include "global.h"
30    
31    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
32  #define ABOUT_DIALOG  #define ABOUT_DIALOG
33  #include <gtkmm/aboutdialog.h>  #include <gtkmm/aboutdialog.h>
34  #endif  #endif
35    
36    #if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION < 6) || GLIBMM_MAJOR_VERSION < 2
37    namespace Glib {
38    Glib::ustring filename_display_basename(const std::string& filename)
39    {
40        gchar* gstr = g_path_get_basename(filename.c_str());
41        Glib::ustring str(gstr);
42        g_free(gstr);
43        return Glib::filename_to_utf8(str);
44    }
45    }
46    #endif
47    
48  #include <stdio.h>  #include <stdio.h>
49  #include <sndfile.h>  #include <sndfile.h>
50    
51  #include "mainwindow.h"  #include "mainwindow.h"
52    
53  #define _(String) gettext(String)  #include "../../gfx/status_attached.xpm"
54    #include "../../gfx/status_detached.xpm"
55    
56  template<class T> inline std::string ToString(T o) {  template<class T> inline std::string ToString(T o) {
57      std::stringstream ss;      std::stringstream ss;
# Line 44  template<class T> inline std::string ToS Line 59  template<class T> inline std::string ToS
59      return ss.str();      return ss.str();
60  }  }
61    
62  MainWindow::MainWindow()  Table::Table(int x, int y) : Gtk::Table(x, y), rowno(0) {  }
63    
64    void Table::add(BoolEntry& boolentry)
65    {
66        attach(boolentry.widget, 0, 2, rowno, rowno + 1,
67               Gtk::FILL, Gtk::SHRINK);
68        rowno++;
69    }
70    
71    void Table::add(BoolEntryPlus6& boolentry)
72    {
73        attach(boolentry.widget, 0, 2, rowno, rowno + 1,
74               Gtk::FILL, Gtk::SHRINK);
75        rowno++;
76    }
77    
78    void Table::add(LabelWidget& prop)
79    {
80        attach(prop.label, 1, 2, rowno, rowno + 1,
81               Gtk::FILL, Gtk::SHRINK);
82        attach(prop.widget, 2, 3, rowno, rowno + 1,
83               Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
84        rowno++;
85    }
86    
87    MainWindow::MainWindow() :
88        dimreg_label(_("Changes apply to:")),
89        dimreg_all_regions(_("all regions")),
90        dimreg_all_dimregs(_("all dimension splits")),
91        dimreg_stereo(_("both channels"))
92  {  {
93  //    set_border_width(5);  //    set_border_width(5);
94  //    set_default_size(400, 200);  //    set_default_size(400, 200);
# Line 74  MainWindow::MainWindow() Line 118  MainWindow::MainWindow()
118      m_TreeViewNotebook.set_size_request(300);      m_TreeViewNotebook.set_size_request(300);
119    
120      m_HPaned.add1(m_TreeViewNotebook);      m_HPaned.add1(m_TreeViewNotebook);
121      m_HPaned.add2(dimreg_edit);      dimreg_hbox.add(dimreg_label);
122        dimreg_hbox.add(dimreg_all_regions);
123        dimreg_hbox.add(dimreg_all_dimregs);
124        dimreg_stereo.set_active();
125        dimreg_hbox.add(dimreg_stereo);
126        dimreg_vbox.add(dimreg_edit);
127        dimreg_vbox.pack_start(dimreg_hbox, Gtk::PACK_SHRINK);
128        m_HPaned.add2(dimreg_vbox);
129    
130    
131      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");      m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples");
# Line 99  MainWindow::MainWindow() Line 150  MainWindow::MainWindow()
150      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);      action = Gtk::Action::create("SaveAs", Gtk::Stock::SAVE_AS);
151      action->property_label() = action->property_label() + "...";      action->property_label() = action->property_label() + "...";
152      actionGroup->add(action,      actionGroup->add(action,
153                       *(new Gtk::AccelKey("<shift><control>s")),                       Gtk::AccelKey("<shift><control>s"),
154                       sigc::mem_fun(                       sigc::mem_fun(
155                           *this, &MainWindow::on_action_file_save_as)                           *this, &MainWindow::on_action_file_save_as));
         );  
156      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
157                                           Gtk::Stock::PROPERTIES),                                           Gtk::Stock::PROPERTIES),
158                       sigc::mem_fun(                       sigc::mem_fun(
# Line 113  MainWindow::MainWindow() Line 163  MainWindow::MainWindow()
163                           *this, &MainWindow::show_instr_props));                           *this, &MainWindow::show_instr_props));
164      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),      actionGroup->add(Gtk::Action::create("Quit", Gtk::Stock::QUIT),
165                       sigc::mem_fun(                       sigc::mem_fun(
166                           *this, &MainWindow::hide));                           *this, &MainWindow::on_action_quit));
167      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));      actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument")));
168    
169        actionGroup->add(Gtk::Action::create("MenuView", _("_View")));
170        Glib::RefPtr<Gtk::ToggleAction> toggle_action =
171            Gtk::ToggleAction::create("Statusbar", _("_Statusbar"));
172        toggle_action->set_active(true);
173        actionGroup->add(toggle_action,
174                         sigc::mem_fun(
175                             *this, &MainWindow::on_action_view_status_bar));
176    
177      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);      action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP);
178      actionGroup->add(Gtk::Action::create("MenuHelp",      actionGroup->add(Gtk::Action::create("MenuHelp",
179                                           action->property_label()));                                           action->property_label()));
# Line 153  MainWindow::MainWindow() Line 211  MainWindow::MainWindow()
211    
212      uiManager = Gtk::UIManager::create();      uiManager = Gtk::UIManager::create();
213      uiManager->insert_action_group(actionGroup);      uiManager->insert_action_group(actionGroup);
214      // add_accel_group(uiManager->get_accel_group());      add_accel_group(uiManager->get_accel_group());
215    
216      Glib::ustring ui_info =      Glib::ustring ui_info =
217          "<ui>"          "<ui>"
# Line 171  MainWindow::MainWindow() Line 229  MainWindow::MainWindow()
229          "    </menu>"          "    </menu>"
230          "    <menu action='MenuInstrument'>"          "    <menu action='MenuInstrument'>"
231          "    </menu>"          "    </menu>"
232            "    <menu action='MenuView'>"
233            "      <menuitem action='Statusbar'/>"
234            "    </menu>"
235  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
236          "    <menu action='MenuHelp'>"          "    <menu action='MenuHelp'>"
237          "      <menuitem action='About'/>"          "      <menuitem action='About'/>"
# Line 199  MainWindow::MainWindow() Line 260  MainWindow::MainWindow()
260      m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);      m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);
261      m_VBox.pack_start(m_HPaned);      m_VBox.pack_start(m_HPaned);
262      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
263        m_VBox.pack_start(m_RegionChooser.m_VirtKeybPropsBox, Gtk::PACK_SHRINK);
264      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);      m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
265        m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK);
266    
267        // Status Bar:
268        m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK);
269        m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK);
270        m_StatusBar.show();
271    
272      m_RegionChooser.signal_sel_changed().connect(      m_RegionChooser.signal_region_selected().connect(
273          sigc::mem_fun(*this, &MainWindow::region_changed) );          sigc::mem_fun(*this, &MainWindow::region_changed) );
274      m_DimRegionChooser.signal_sel_changed().connect(      m_DimRegionChooser.signal_dimregion_selected().connect(
275          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );          sigc::mem_fun(*this, &MainWindow::dimreg_changed) );
276    
277    
# Line 235  MainWindow::MainWindow() Line 303  MainWindow::MainWindow()
303      std::list<Gtk::TargetEntry> drag_target_gig_sample;      std::list<Gtk::TargetEntry> drag_target_gig_sample;
304      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );      drag_target_gig_sample.push_back( Gtk::TargetEntry("gig::Sample") );
305      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);      m_TreeViewSamples.drag_source_set(drag_target_gig_sample);
306        m_TreeViewSamples.signal_drag_begin().connect(
307            sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_begin)
308        );
309      m_TreeViewSamples.signal_drag_data_get().connect(      m_TreeViewSamples.signal_drag_data_get().connect(
310          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)          sigc::mem_fun(*this, &MainWindow::on_sample_treeview_drag_data_get)
311      );      );
# Line 242  MainWindow::MainWindow() Line 313  MainWindow::MainWindow()
313      dimreg_edit.wSample->signal_drag_data_received().connect(      dimreg_edit.wSample->signal_drag_data_received().connect(
314          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)          sigc::mem_fun(*this, &MainWindow::on_sample_label_drop_drag_data_received)
315      );      );
316        dimreg_edit.signal_dimreg_changed().connect(
317            sigc::hide(sigc::mem_fun(*this, &MainWindow::file_changed)));
318        m_RegionChooser.signal_instrument_changed().connect(
319            sigc::mem_fun(*this, &MainWindow::file_changed));
320        m_DimRegionChooser.signal_region_changed().connect(
321            sigc::mem_fun(*this, &MainWindow::file_changed));
322        instrumentProps.signal_instrument_changed().connect(
323            sigc::mem_fun(*this, &MainWindow::file_changed));
324        propDialog.signal_info_changed().connect(
325            sigc::mem_fun(*this, &MainWindow::file_changed));
326    
327        dimreg_edit.signal_dimreg_to_be_changed().connect(
328            dimreg_to_be_changed_signal.make_slot());
329        dimreg_edit.signal_dimreg_changed().connect(
330            dimreg_changed_signal.make_slot());
331        dimreg_edit.signal_sample_ref_changed().connect(
332            sample_ref_changed_signal.make_slot());
333    
334        m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
335            sigc::hide(
336                sigc::bind(
337                    file_structure_to_be_changed_signal.make_slot(),
338                    sigc::ref(this->file)
339                )
340            )
341        );
342        m_RegionChooser.signal_instrument_struct_changed().connect(
343            sigc::hide(
344                sigc::bind(
345                    file_structure_changed_signal.make_slot(),
346                    sigc::ref(this->file)
347                )
348            )
349        );
350        m_RegionChooser.signal_region_to_be_changed().connect(
351            region_to_be_changed_signal.make_slot());
352        m_RegionChooser.signal_region_changed_signal().connect(
353            region_changed_signal.make_slot());
354    
355        note_on_signal.connect(
356            sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_on_event));
357        note_off_signal.connect(
358            sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_off_event));
359    
360        dimreg_all_regions.signal_toggled().connect(
361            sigc::mem_fun(*this, &MainWindow::update_dimregs));
362        dimreg_all_dimregs.signal_toggled().connect(
363            sigc::mem_fun(*this, &MainWindow::dimreg_all_dimregs_toggled));
364        dimreg_stereo.signal_toggled().connect(
365            sigc::mem_fun(*this, &MainWindow::update_dimregs));
366    
367      file = 0;      file = 0;
368        file_is_changed = false;
369        set_file_is_shared(false);
370    
371      show_all_children();      show_all_children();
372    
373        // start with a new gig file by default
374        on_action_file_new();
375  }  }
376    
377  MainWindow::~MainWindow()  MainWindow::~MainWindow()
378  {  {
379  }  }
380    
381  void MainWindow::region_changed()  bool MainWindow::on_delete_event(GdkEventAny* event)
382  {  {
383      m_DimRegionChooser.set_region(m_RegionChooser.get_region());      return !file_is_shared && file_is_changed && !close_confirmation_dialog();
384  }  }
385    
386  void MainWindow::dimreg_changed()  void MainWindow::on_action_quit()
387  {  {
388      dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());      if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
389        hide();
390  }  }
391    
392  void MainWindow::on_sel_change()  void MainWindow::region_changed()
393    {
394        m_DimRegionChooser.set_region(m_RegionChooser.get_region());
395    }
396    
397    gig::Instrument* MainWindow::get_instrument()
398  {  {
399        gig::Instrument* instrument = 0;
400      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
401    
402      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();
403      if (it) {      if (it) {
404          Gtk::TreeModel::Row row = *it;          Gtk::TreeModel::Row row = *it;
405          std::cout << row[m_Columns.m_col_name] << std::endl;          instrument = row[m_Columns.m_col_instr];
406        }
407        return instrument;
408    }
409    
410    void MainWindow::add_region_to_dimregs(gig::Region* region, bool stereo, bool all_dimregs)
411    {
412        if (all_dimregs) {
413            for (int i = 0 ; i < region->DimensionRegions ; i++) {
414                if (region->pDimensionRegions[i]) {
415                    dimreg_edit.dimregs.insert(region->pDimensionRegions[i]);
416                }
417            }
418        } else {
419            m_DimRegionChooser.get_dimregions(region, stereo, dimreg_edit.dimregs);
420        }
421    }
422    
423    void MainWindow::update_dimregs()
424    {
425        dimreg_edit.dimregs.clear();
426        bool all_regions = dimreg_all_regions.get_active();
427        bool stereo = dimreg_stereo.get_active();
428        bool all_dimregs = dimreg_all_dimregs.get_active();
429    
430          m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]);      if (all_regions) {
431            gig::Instrument* instrument = get_instrument();
432            if (instrument) {
433                for (gig::Region* region = instrument->GetFirstRegion() ;
434                     region ;
435                     region = instrument->GetNextRegion()) {
436                    add_region_to_dimregs(region, stereo, all_dimregs);
437                }
438            }
439      } else {      } else {
440          m_RegionChooser.set_instrument(0);          gig::Region* region = m_RegionChooser.get_region();
441            if (region) {
442                add_region_to_dimregs(region, stereo, all_dimregs);
443            }
444      }      }
445  }  }
446    
447    void MainWindow::dimreg_all_dimregs_toggled()
448    {
449        dimreg_stereo.set_sensitive(!dimreg_all_dimregs.get_active());
450        update_dimregs();
451    }
452    
453    void MainWindow::dimreg_changed()
454    {
455        update_dimregs();
456        dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion());
457    }
458    
459    void MainWindow::on_sel_change()
460    {
461        m_RegionChooser.set_instrument(get_instrument());
462    }
463    
464  void loader_progress_callback(gig::progress_t* progress)  void loader_progress_callback(gig::progress_t* progress)
465  {  {
466      Loader* loader = static_cast<Loader*>(progress->custom);      Loader* loader = static_cast<Loader*>(progress->custom);
# Line 362  void MainWindow::__clear() { Line 546  void MainWindow::__clear() {
546      m_refTreeModel->clear();      m_refTreeModel->clear();
547      m_refSamplesTreeModel->clear();      m_refSamplesTreeModel->clear();
548      // free libgig's gig::File instance      // free libgig's gig::File instance
549      if (file) {      if (file && !file_is_shared) delete file;
550          delete file;      file = NULL;
551          file = NULL;      set_file_is_shared(false);
     }  
552  }  }
553    
554  void MainWindow::on_action_file_new()  void MainWindow::on_action_file_new()
555  {  {
556        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
557    
558        if (file_is_shared && !leaving_shared_mode_dialog()) return;
559    
560      // clear all GUI elements      // clear all GUI elements
561      __clear();      __clear();
562      // create a new .gig file (virtually yet)      // create a new .gig file (virtually yet)
# Line 378  void MainWindow::on_action_file_new() Line 565  void MainWindow::on_action_file_new()
565      gig::Instrument* pInstrument = pFile->AddInstrument();      gig::Instrument* pInstrument = pFile->AddInstrument();
566      pInstrument->pInfo->Name = "Unnamed Instrument";      pInstrument->pInfo->Name = "Unnamed Instrument";
567      // update GUI with that new gig::File      // update GUI with that new gig::File
568      load_gig(pFile, NULL /*no file name yet*/);      load_gig(pFile, 0 /*no file name yet*/);
569    }
570    
571    bool MainWindow::close_confirmation_dialog()
572    {
573        gchar* msg = g_strdup_printf(_("Save changes to \"%s\" before closing?"),
574                                     Glib::filename_display_basename(filename).c_str());
575        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
576        g_free(msg);
577    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
578        dialog.set_secondary_text(_("If you close without saving, your changes will be lost."));
579    #endif
580        dialog.add_button(_("Close _Without Saving"), Gtk::RESPONSE_NO);
581        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
582        dialog.add_button(file_has_name ? Gtk::Stock::SAVE : Gtk::Stock::SAVE_AS, Gtk::RESPONSE_YES);
583        dialog.set_default_response(Gtk::RESPONSE_YES);
584        int response = dialog.run();
585        dialog.hide();
586        if (response == Gtk::RESPONSE_YES) return file_save();
587        return response != Gtk::RESPONSE_CANCEL;
588    }
589    
590    bool MainWindow::leaving_shared_mode_dialog() {
591        Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?");
592        Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE);
593    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2
594        dialog.set_secondary_text(
595            _("If you proceed to work on another instrument file, it won't be "
596              "used by the sampler until you tell the sampler explicitly to "
597              "load it.")
598       );
599    #endif
600        dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES);
601        dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
602        dialog.set_default_response(Gtk::RESPONSE_CANCEL);
603        int response = dialog.run();
604        dialog.hide();
605        return response == Gtk::RESPONSE_YES;
606  }  }
607    
608  void MainWindow::on_action_file_open()  void MainWindow::on_action_file_open()
609  {  {
610        if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return;
611    
612        if (file_is_shared && !leaving_shared_mode_dialog()) return;
613    
614      Gtk::FileChooserDialog dialog(*this, _("Open file"));      Gtk::FileChooserDialog dialog(*this, _("Open file"));
615      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
616      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
617        dialog.set_default_response(Gtk::RESPONSE_OK);
618      Gtk::FileFilter filter;      Gtk::FileFilter filter;
619      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
620      dialog.set_filter(filter);      dialog.set_filter(filter);
621        if (current_dir != "") {
622            dialog.set_current_folder(current_dir);
623        }
624      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
625          printf("filename=%s\n", dialog.get_filename().c_str());          std::string filename = dialog.get_filename();
626          __clear();          printf("filename=%s\n", filename.c_str());
627          printf("on_action_file_open self=%x\n", Glib::Thread::self());          printf("on_action_file_open self=%x\n", Glib::Thread::self());
628          load_file(dialog.get_filename().c_str());          load_file(filename.c_str());
629            current_dir = Glib::path_get_dirname(filename);
630      }      }
631  }  }
632    
633  void MainWindow::load_file(const char* name)  void MainWindow::load_file(const char* name)
634  {  {
635        __clear();
636      load_dialog = new LoadDialog("Loading...", *this);      load_dialog = new LoadDialog("Loading...", *this);
637      load_dialog->show_all();      load_dialog->show_all();
638      loader = new Loader(strdup(name));      loader = new Loader(strdup(name));
# Line 416  void MainWindow::load_instrument(gig::In Line 650  void MainWindow::load_instrument(gig::In
650          msg.run();          msg.run();
651          Gtk::Main::quit();          Gtk::Main::quit();
652      }      }
653        // clear all GUI elements
654        __clear();
655        // load the instrument
656      gig::File* pFile = (gig::File*) instr->GetParent();      gig::File* pFile = (gig::File*) instr->GetParent();
657      load_gig(pFile, NULL /*file name*/);      load_gig(pFile, 0 /*file name*/, true /*shared instrument*/);
658      //TODO: automatically select the given instrument      //TODO: automatically select the given instrument
659  }  }
660    
# Line 436  void MainWindow::on_loader_finished() Line 673  void MainWindow::on_loader_finished()
673    
674  void MainWindow::on_action_file_save()  void MainWindow::on_action_file_save()
675  {  {
676      if (!file) return;      file_save();
677    }
678    
679    bool MainWindow::check_if_savable()
680    {
681        if (!file) return false;
682    
683        if (!file->GetFirstSample()) {
684            Gtk::MessageDialog(*this, _("The file could not be saved "
685                                        "because it contains no samples"),
686                               false, Gtk::MESSAGE_ERROR).run();
687            return false;
688        }
689    
690        for (gig::Instrument* instrument = file->GetFirstInstrument() ; instrument ;
691             instrument = file->GetNextInstrument()) {
692            if (!instrument->GetFirstRegion()) {
693                Gtk::MessageDialog(*this, _("The file could not be saved "
694                                            "because there are instruments "
695                                            "that have no regions"),
696                                   false, Gtk::MESSAGE_ERROR).run();
697                return false;
698            }
699        }
700        return true;
701    }
702    
703    bool MainWindow::file_save()
704    {
705        if (!check_if_savable()) return false;
706        if (!file_is_shared && !file_has_name) return file_save_as();
707    
708      std::cout << "Saving file\n" << std::flush;      std::cout << "Saving file\n" << std::flush;
709        file_structure_to_be_changed_signal.emit(this->file);
710      try {      try {
711          file->Save();          file->Save();
712            if (file_is_changed) {
713                set_title(get_title().substr(1));
714                file_is_changed = false;
715            }
716      } catch (RIFF::Exception e) {      } catch (RIFF::Exception e) {
717          Glib::ustring txt = "Could not save file: " + e.Message;          file_structure_changed_signal.emit(this->file);
718            Glib::ustring txt = _("Could not save file: ") + e.Message;
719          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
720          msg.run();          msg.run();
721          return;          return false;
722      }      }
723      std::cout << "Saving file done\n" << std::flush;      std::cout << "Saving file done\n" << std::flush;
724      __import_queued_samples();      __import_queued_samples();
725        file_structure_changed_signal.emit(this->file);
726        return true;
727  }  }
728    
729  void MainWindow::on_action_file_save_as()  void MainWindow::on_action_file_save_as()
730  {  {
731      if (!file) return;      if (!check_if_savable()) return;
732      Gtk::FileChooserDialog dialog(*this, "Open", Gtk::FILE_CHOOSER_ACTION_SAVE);      file_save_as();
733    }
734    
735    bool MainWindow::file_save_as()
736    {
737        Gtk::FileChooserDialog dialog(*this, _("Save as"), Gtk::FILE_CHOOSER_ACTION_SAVE);
738      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);      dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
739      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
740        dialog.set_default_response(Gtk::RESPONSE_OK);
741    
742    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 8) || GTKMM_MAJOR_VERSION > 2
743        dialog.set_do_overwrite_confirmation();
744        // TODO: an overwrite dialog for gtkmm < 2.8
745    #endif
746      Gtk::FileFilter filter;      Gtk::FileFilter filter;
747      filter.add_pattern("*.gig");      filter.add_pattern("*.gig");
748      dialog.set_filter(filter);      dialog.set_filter(filter);
749    
750        if (Glib::path_is_absolute(filename)) {
751            dialog.set_filename(filename);
752        } else if (current_dir != "") {
753            dialog.set_current_folder(current_dir);
754        }
755        dialog.set_current_name(Glib::filename_display_basename(filename));
756    
757      if (dialog.run() == Gtk::RESPONSE_OK) {      if (dialog.run() == Gtk::RESPONSE_OK) {
758          printf("filename=%s\n", dialog.get_filename().c_str());          file_structure_to_be_changed_signal.emit(this->file);
759          try {          try {
760              file->Save(dialog.get_filename());              std::string filename = dialog.get_filename();
761                if (!Glib::str_has_suffix(filename, ".gig")) {
762                    filename += ".gig";
763                }
764                printf("filename=%s\n", filename.c_str());
765                file->Save(filename);
766                this->filename = filename;
767                current_dir = Glib::path_get_dirname(filename);
768                set_title(Glib::filename_display_basename(filename));
769                file_has_name = true;
770                file_is_changed = false;
771          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
772              Glib::ustring txt = "Could not save file: " + e.Message;              file_structure_changed_signal.emit(this->file);
773                Glib::ustring txt = _("Could not save file: ") + e.Message;
774              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
775              msg.run();              msg.run();
776              return;              return false;
777          }          }
778          __import_queued_samples();          __import_queued_samples();
779            file_structure_changed_signal.emit(this->file);
780            return true;
781      }      }
782        return false;
783  }  }
784    
785  // 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 799  void MainWindow::__import_queued_samples
799              int bitdepth;              int bitdepth;
800              switch (info.format & 0xff) {              switch (info.format & 0xff) {
801                  case SF_FORMAT_PCM_S8:                  case SF_FORMAT_PCM_S8:
                     bitdepth = 16; // we simply convert to 16 bit for now  
                     break;  
802                  case SF_FORMAT_PCM_16:                  case SF_FORMAT_PCM_16:
803                    case SF_FORMAT_PCM_U8:
804                      bitdepth = 16;                      bitdepth = 16;
805                      break;                      break;
806                  case SF_FORMAT_PCM_24:                  case SF_FORMAT_PCM_24:
                     bitdepth = 32; // we simply convert to 32 bit for now  
                     break;  
807                  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;  
808                  case SF_FORMAT_FLOAT:                  case SF_FORMAT_FLOAT:
                     bitdepth = 32;  
                     break;  
809                  case SF_FORMAT_DOUBLE:                  case SF_FORMAT_DOUBLE:
810                      bitdepth = 32; // I guess we will always truncate this to 32 bit                      bitdepth = 24;
811                      break;                      break;
812                  default:                  default:
813                      sf_close(hFile); // close sound file                      sf_close(hFile); // close sound file
814                      throw std::string("format not supported"); // unsupported subformat (yet?)                      throw std::string("format not supported"); // unsupported subformat (yet?)
815              }              }
816              // allocate appropriate copy buffer (TODO: for now we copy  
817              // 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;  
818              switch (bitdepth) {              switch (bitdepth) {
819                  case 16:                  case 16: {
820                      buffer = new int8_t[2 * info.channels * info.frames];                      short* buffer = new short[bufsize * info.channels];
821                      // libsndfile does the conversion for us (if needed)                      sf_count_t cnt = info.frames;
822                      sf_readf_short(hFile, (short*) buffer, info.frames);                      while (cnt) {
823                            // libsndfile does the conversion for us (if needed)
824                            int n = sf_readf_short(hFile, buffer, bufsize);
825                            // write from buffer directly (physically) into .gig file
826                            iter->gig_sample->Write(buffer, n);
827                            cnt -= n;
828                        }
829                        delete[] buffer;
830                      break;                      break;
831                  case 32:                  }
832                      buffer = new int8_t[4 * info.channels * info.frames];                  case 24: {
833                      // libsndfile does the conversion for us (if needed)                      int* srcbuf = new int[bufsize * info.channels];
834                      sf_readf_int(hFile, (int*) buffer, info.frames);                      uint8_t* dstbuf = new uint8_t[bufsize * 3 * info.channels];
835                        sf_count_t cnt = info.frames;
836                        while (cnt) {
837                            // libsndfile returns 32 bits, convert to 24
838                            int n = sf_readf_int(hFile, srcbuf, bufsize);
839                            int j = 0;
840                            for (int i = 0 ; i < n * info.channels ; i++) {
841                                dstbuf[j++] = srcbuf[i] >> 8;
842                                dstbuf[j++] = srcbuf[i] >> 16;
843                                dstbuf[j++] = srcbuf[i] >> 24;
844                            }
845                            // write from buffer directly (physically) into .gig file
846                            iter->gig_sample->Write(dstbuf, n);
847                            cnt -= n;
848                        }
849                        delete[] srcbuf;
850                        delete[] dstbuf;
851                      break;                      break;
852                    }
853              }              }
             // write from buffer directly (physically) into .gig file  
             (*iter).gig_sample->Write(buffer, info.frames);  
854              // cleanup              // cleanup
855              sf_close(hFile);              sf_close(hFile);
             delete[] buffer;  
856              // on success we remove the sample from the import queue,              // on success we remove the sample from the import queue,
857              // otherwise keep it, maybe it works the next time ?              // otherwise keep it, maybe it works the next time ?
858              std::list<SampleImportItem>::iterator cur = iter;              std::list<SampleImportItem>::iterator cur = iter;
# Line 549  void MainWindow::__import_queued_samples Line 867  void MainWindow::__import_queued_samples
867      }      }
868      // show error message box when some sample(s) could not be imported      // show error message box when some sample(s) could not be imported
869      if (error_files.size()) {      if (error_files.size()) {
870          Glib::ustring txt = "Could not import the following sample(s):\n" + error_files;          Glib::ustring txt = _("Could not import the following sample(s):\n") + error_files;
871          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);          Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
872          msg.run();          msg.run();
873      }      }
# Line 566  void MainWindow::on_action_help_about() Line 884  void MainWindow::on_action_help_about()
884  #ifdef ABOUT_DIALOG  #ifdef ABOUT_DIALOG
885      Gtk::AboutDialog dialog;      Gtk::AboutDialog dialog;
886      dialog.set_version(VERSION);      dialog.set_version(VERSION);
887        dialog.set_copyright("Copyright (C) 2006,2007 Andreas Persson");
888        dialog.set_comments(
889            "Released under the GNU General Public License.\n"
890            "\n"
891            "Please notice that this is still a very young instrument editor. "
892            "So better backup your Gigasampler files before editing them with "
893            "this application.\n"
894            "\n"
895            "Please report bugs to: http://bugs.linuxsampler.org"
896        );
897        dialog.set_website("http://www.linuxsampler.org");
898        dialog.set_website_label("http://www.linuxsampler.org");
899      dialog.run();      dialog.run();
900  #endif  #endif
901  }  }
902    
903  PropDialog::PropDialog()  PropDialog::PropDialog()
904      : table(2,1)      : table(2,1),
905          eName("Name"),
906          eCreationDate("Creation date"),
907          eComments("Comments"),
908          eProduct("Product"),
909          eCopyright("Copyright"),
910          eArtists("Artists"),
911          eGenre("Genre"),
912          eKeywords("Keywords"),
913          eEngineer("Engineer"),
914          eTechnician("Technician"),
915          eSoftware("Software"),
916          eMedium("Medium"),
917          eSource("Source"),
918          eSourceForm("Source form"),
919          eCommissioned("Commissioned"),
920          eSubject("Subject"),
921          quitButton(Gtk::Stock::CLOSE),
922          update_model(0)
923  {  {
924        set_title("File Properties");
925        eName.set_width_chars(50);
926    
927        connect(eName, &DLS::Info::Name);
928        connect(eCreationDate, &DLS::Info::CreationDate);
929        connect(eComments, &DLS::Info::Comments);
930        connect(eProduct, &DLS::Info::Product);
931        connect(eCopyright, &DLS::Info::Copyright);
932        connect(eArtists, &DLS::Info::Artists);
933        connect(eGenre, &DLS::Info::Genre);
934        connect(eKeywords, &DLS::Info::Keywords);
935        connect(eEngineer, &DLS::Info::Engineer);
936        connect(eTechnician, &DLS::Info::Technician);
937        connect(eSoftware, &DLS::Info::Software);
938        connect(eMedium, &DLS::Info::Medium);
939        connect(eSource, &DLS::Info::Source);
940        connect(eSourceForm, &DLS::Info::SourceForm);
941        connect(eCommissioned, &DLS::Info::Commissioned);
942        connect(eSubject, &DLS::Info::Subject);
943    
944        table.add(eName);
945        table.add(eCreationDate);
946        table.add(eComments);
947        table.add(eProduct);
948        table.add(eCopyright);
949        table.add(eArtists);
950        table.add(eGenre);
951        table.add(eKeywords);
952        table.add(eEngineer);
953        table.add(eTechnician);
954        table.add(eSoftware);
955        table.add(eMedium);
956        table.add(eSource);
957        table.add(eSourceForm);
958        table.add(eCommissioned);
959        table.add(eSubject);
960    
961      table.set_col_spacings(5);      table.set_col_spacings(5);
962      const char* propLabels[] = {      add(vbox);
963          "Name:",      table.set_border_width(5);
964          "CreationDate:",      vbox.add(table);
965          "Comments:", // TODO: multiline      vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
966          "Product:",      buttonBox.set_layout(Gtk::BUTTONBOX_END);
967          "Copyright:",      buttonBox.set_border_width(5);
968          "Artists:",      buttonBox.show();
969          "Genre:",      buttonBox.pack_start(quitButton);
970          "Keywords:",      quitButton.set_flags(Gtk::CAN_DEFAULT);
971          "Engineer:",      quitButton.grab_focus();
972          "Technician:",      quitButton.signal_clicked().connect(
973          "Software:", // TODO: readonly          sigc::mem_fun(*this, &PropDialog::hide));
         "Medium:",  
         "Source:",  
         "SourceForm:",  
         "Commissioned:",  
         "Subject:"  
     };  
     for (int i = 0 ; i < sizeof(propLabels) / sizeof(char*) ; i++) {  
         label[i].set_text(propLabels[i]);  
         label[i].set_alignment(Gtk::ALIGN_LEFT);  
         table.attach(label[i], 0, 1, i, i + 1, Gtk::FILL, Gtk::SHRINK);  
         table.attach(entry[i], 1, 2, i, i + 1, Gtk::FILL | Gtk::EXPAND,  
                      Gtk::SHRINK);  
     }  
974    
975      add(table);      quitButton.show();
976      // add_button(Gtk::Stock::CANCEL, 0);      vbox.show();
     // add_button(Gtk::Stock::OK, 1);  
977      show_all_children();      show_all_children();
978  }  }
979    
980  void PropDialog::set_info(DLS::Info* info)  void PropDialog::set_info(DLS::Info* info)
981  {  {
982      entry[0].set_text(info->Name);      this->info = info;
983      entry[1].set_text(info->CreationDate);      update_model++;
984      entry[2].set_text(Glib::convert(info->Comments, "UTF-8", "ISO-8859-1"));      eName.set_value(info->Name);
985      entry[3].set_text(info->Product);      eCreationDate.set_value(info->CreationDate);
986      entry[4].set_text(info->Copyright);      eComments.set_value(info->Comments);
987      entry[5].set_text(info->Artists);      eProduct.set_value(info->Product);
988      entry[6].set_text(info->Genre);      eCopyright.set_value(info->Copyright);
989      entry[7].set_text(info->Keywords);      eArtists.set_value(info->Artists);
990      entry[8].set_text(info->Engineer);      eGenre.set_value(info->Genre);
991      entry[9].set_text(info->Technician);      eKeywords.set_value(info->Keywords);
992      entry[10].set_text(info->Software);      eEngineer.set_value(info->Engineer);
993      entry[11].set_text(info->Medium);      eTechnician.set_value(info->Technician);
994      entry[12].set_text(info->Source);      eSoftware.set_value(info->Software);
995      entry[13].set_text(info->SourceForm);      eMedium.set_value(info->Medium);
996      entry[14].set_text(info->Commissioned);      eSource.set_value(info->Source);
997      entry[15].set_text(info->Subject);      eSourceForm.set_value(info->SourceForm);
998  }      eCommissioned.set_value(info->Commissioned);
999        eSubject.set_value(info->Subject);
1000  void InstrumentProps::add_prop(LabelWidget& prop)      update_model--;
1001  {  }
1002      table.attach(prop.label, 0, 1, rowno, rowno + 1,  
1003                   Gtk::FILL, Gtk::SHRINK);  sigc::signal<void>& PropDialog::signal_info_changed()
1004      table.attach(prop.widget, 1, 2, rowno, rowno + 1,  {
1005                   Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);      return info_changed;
1006      rowno++;  }
1007    
1008    void InstrumentProps::set_IsDrum(bool value)
1009    {
1010        instrument->IsDrum = value;
1011    }
1012    
1013    void InstrumentProps::set_MIDIBank(uint16_t value)
1014    {
1015        instrument->MIDIBank = value;
1016    }
1017    
1018    void InstrumentProps::set_MIDIProgram(uint32_t value)
1019    {
1020        instrument->MIDIProgram = value;
1021    }
1022    
1023    void InstrumentProps::set_DimensionKeyRange_low(uint8_t value)
1024    {
1025        instrument->DimensionKeyRange.low = value;
1026        if (value > instrument->DimensionKeyRange.high) {
1027            eDimensionKeyRangeHigh.set_value(value);
1028        }
1029    }
1030    
1031    void InstrumentProps::set_DimensionKeyRange_high(uint8_t value)
1032    {
1033        instrument->DimensionKeyRange.high = value;
1034        if (value < instrument->DimensionKeyRange.low) {
1035            eDimensionKeyRangeLow.set_value(value);
1036        }
1037  }  }
1038    
1039  InstrumentProps::InstrumentProps()  InstrumentProps::InstrumentProps()
1040      : table(2,1),      : table(2,1),
1041        quitButton(Gtk::Stock::CLOSE),        quitButton(Gtk::Stock::CLOSE),
1042        eName("Name"),        eName("Name"),
1043        eIsDrum("IsDrum"),        eIsDrum("Is drum"),
1044        eMIDIBank("MIDIBank", 0, 16383),        eMIDIBank("MIDI bank", 0, 16383),
1045        eMIDIProgram("MIDIProgram"),        eMIDIProgram("MIDI program"),
1046        eAttenuation("Attenuation", 0, 96, 0, 1),        eAttenuation("Attenuation", 0, 96, 0, 1),
1047        eGainPlus6("Gain +6dB", eAttenuation, -6),        eGainPlus6("Gain +6dB", eAttenuation, -6),
1048        eEffectSend("EffectSend", 0, 65535),        eEffectSend("Effect send", 0, 65535),
1049        eFineTune("FineTune", -8400, 8400),        eFineTune("Fine tune", -8400, 8400),
1050        ePitchbendRange("PitchbendRange", 0, 12),        ePitchbendRange("Pitchbend range", 0, 12),
1051        ePianoReleaseMode("PianoReleaseMode"),        ePianoReleaseMode("Piano release mode"),
1052        eDimensionKeyRangeLow("DimensionKeyRangeLow"),        eDimensionKeyRangeLow("Keyswitching range low"),
1053        eDimensionKeyRangeHigh("DimensionKeyRangeHigh")        eDimensionKeyRangeHigh("Keyswitching range high"),
1054  {        update_model(0)
1055      set_title("Instrument properties");  {
1056        set_title("Instrument Properties");
1057    
1058        eDimensionKeyRangeLow.set_tip(
1059            _("start of the keyboard area which should switch the "
1060              "\"keyswitching\" dimension")
1061        );
1062        eDimensionKeyRangeHigh.set_tip(
1063            _("end of the keyboard area which should switch the "
1064              "\"keyswitching\" dimension")
1065        );
1066    
1067        connect(eIsDrum, &InstrumentProps::set_IsDrum);
1068        connect(eMIDIBank, &InstrumentProps::set_MIDIBank);
1069        connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram);
1070        connect(eAttenuation, &gig::Instrument::Attenuation);
1071        connect(eGainPlus6, &gig::Instrument::Attenuation);
1072        connect(eEffectSend, &gig::Instrument::EffectSend);
1073        connect(eFineTune, &gig::Instrument::FineTune);
1074        connect(ePitchbendRange, &gig::Instrument::PitchbendRange);
1075        connect(ePianoReleaseMode, &gig::Instrument::PianoReleaseMode);
1076        connect(eDimensionKeyRangeLow,
1077                &InstrumentProps::set_DimensionKeyRange_low);
1078        connect(eDimensionKeyRangeHigh,
1079                &InstrumentProps::set_DimensionKeyRange_high);
1080    
     rowno = 0;  
1081      table.set_col_spacings(5);      table.set_col_spacings(5);
1082    
1083      add_prop(eName);      table.add(eName);
1084      add_prop(eIsDrum);      table.add(eIsDrum);
1085      add_prop(eMIDIBank);      table.add(eMIDIBank);
1086      add_prop(eMIDIProgram);      table.add(eMIDIProgram);
1087      add_prop(eAttenuation);      table.add(eAttenuation);
1088      add_prop(eGainPlus6);      table.add(eGainPlus6);
1089      add_prop(eEffectSend);      table.add(eEffectSend);
1090      add_prop(eFineTune);      table.add(eFineTune);
1091      add_prop(ePitchbendRange);      table.add(ePitchbendRange);
1092      add_prop(ePianoReleaseMode);      table.add(ePianoReleaseMode);
1093      add_prop(eDimensionKeyRangeLow);      table.add(eDimensionKeyRangeLow);
1094      add_prop(eDimensionKeyRangeHigh);      table.add(eDimensionKeyRangeHigh);
   
     eDimensionKeyRangeLow.signal_value_changed().connect(  
         sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed));  
     eDimensionKeyRangeHigh.signal_value_changed().connect(  
         sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed));  
1095    
1096      add(vbox);      add(vbox);
1097      table.set_border_width(5);      table.set_border_width(5);
# Line 696  InstrumentProps::InstrumentProps() Line 1115  InstrumentProps::InstrumentProps()
1115    
1116  void InstrumentProps::set_instrument(gig::Instrument* instrument)  void InstrumentProps::set_instrument(gig::Instrument* instrument)
1117  {  {
1118      update_gui = false;      this->instrument = instrument;
1119      eName.set_ptr(&instrument->pInfo->Name);  
1120      eIsDrum.set_ptr(&instrument->IsDrum);      update_model++;
1121      eMIDIBank.set_ptr(&instrument->MIDIBank);      eName.set_value(instrument->pInfo->Name);
1122      eMIDIProgram.set_ptr(&instrument->MIDIProgram);      eIsDrum.set_value(instrument->IsDrum);
1123      eAttenuation.set_ptr(&instrument->Attenuation);      eMIDIBank.set_value(instrument->MIDIBank);
1124      eGainPlus6.set_ptr(&instrument->Attenuation);      eMIDIProgram.set_value(instrument->MIDIProgram);
1125      eEffectSend.set_ptr(&instrument->EffectSend);      eAttenuation.set_value(instrument->Attenuation);
1126      eFineTune.set_ptr(&instrument->FineTune);      eGainPlus6.set_value(instrument->Attenuation);
1127      ePitchbendRange.set_ptr(&instrument->PitchbendRange);      eEffectSend.set_value(instrument->EffectSend);
1128      ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode);      eFineTune.set_value(instrument->FineTune);
1129      eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low);      ePitchbendRange.set_value(instrument->PitchbendRange);
1130      eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high);      ePianoReleaseMode.set_value(instrument->PianoReleaseMode);
1131      update_gui = true;      eDimensionKeyRangeLow.set_value(instrument->DimensionKeyRange.low);
1132        eDimensionKeyRangeHigh.set_value(instrument->DimensionKeyRange.high);
1133        update_model--;
1134  }  }
1135    
1136  void InstrumentProps::key_range_low_changed()  sigc::signal<void>& InstrumentProps::signal_instrument_changed()
1137  {  {
1138      double l = eDimensionKeyRangeLow.get_value();      return instrument_changed;
     double h = eDimensionKeyRangeHigh.get_value();  
     if (h < l) eDimensionKeyRangeHigh.set_value(l);  
1139  }  }
1140    
1141  void InstrumentProps::key_range_high_changed()  void MainWindow::file_changed()
1142  {  {
1143      double l = eDimensionKeyRangeLow.get_value();      if (file && !file_is_changed) {
1144      double h = eDimensionKeyRangeHigh.get_value();          set_title("*" + get_title());
1145      if (h < l) eDimensionKeyRangeLow.set_value(h);          file_is_changed = true;
1146        }
1147  }  }
1148    
1149  void MainWindow::load_gig(gig::File* gig, const char* filename)  void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument)
1150  {  {
1151      file = gig;      file = 0;
1152        set_file_is_shared(isSharedInstrument);
1153    
1154      if (filename) {      this->filename = filename ? filename : _("Unsaved Gig File");
1155          const char *basename = strrchr(filename, '/');      set_title(Glib::filename_display_basename(this->filename));
1156          basename = basename ? basename + 1 : filename;      file_has_name = filename;
1157          set_title(basename);      file_is_changed = false;
     } else {  
         set_title("unnamed");  
     }  
1158    
1159      propDialog.set_info(gig->pInfo);      propDialog.set_info(gig->pInfo);
1160    
# Line 785  void MainWindow::load_gig(gig::File* gig Line 1203  void MainWindow::load_gig(gig::File* gig
1203          }          }
1204      }      }
1205    
1206        file = gig;
1207    
1208      // select the first instrument      // select the first instrument
1209      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();
1210      tree_sel_ref->select(Gtk::TreePath("0"));      tree_sel_ref->select(Gtk::TreePath("0"));
# Line 792  void MainWindow::load_gig(gig::File* gig Line 1212  void MainWindow::load_gig(gig::File* gig
1212    
1213  void MainWindow::show_instr_props()  void MainWindow::show_instr_props()
1214  {  {
1215      Glib::RefPtr<Gtk::TreeSelection> tree_sel_ref = m_TreeView.get_selection();      gig::Instrument* instrument = get_instrument();
1216      Gtk::TreeModel::iterator it = tree_sel_ref->get_selected();      if (instrument)
     if (it)  
1217      {      {
1218          Gtk::TreeModel::Row row = *it;          instrumentProps.set_instrument(instrument);
1219          if (row[m_Columns.m_col_instr])          instrumentProps.show();
1220          {          instrumentProps.deiconify();
1221              instrumentProps.set_instrument(row[m_Columns.m_col_instr]);      }
1222              instrumentProps.show();  }
1223              instrumentProps.deiconify();  
1224          }  void MainWindow::on_action_view_status_bar() {
1225        Gtk::CheckMenuItem* item =
1226            dynamic_cast<Gtk::CheckMenuItem*>(uiManager->get_widget("/MenuBar/MenuView/Statusbar"));
1227        if (!item) {
1228            std::cerr << "/MenuBar/MenuView/Statusbar == NULL\n";
1229            return;
1230      }      }
1231        if (item->get_active()) m_StatusBar.show();
1232        else                    m_StatusBar.hide();
1233  }  }
1234    
1235  void MainWindow::on_button_release(GdkEventButton* button)  void MainWindow::on_button_release(GdkEventButton* button)
# Line 858  void MainWindow::on_action_add_instrumen Line 1284  void MainWindow::on_action_add_instrumen
1284      Gtk::TreeModel::Row rowInstr = *iterInstr;      Gtk::TreeModel::Row rowInstr = *iterInstr;
1285      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();      rowInstr[m_Columns.m_col_name] = instrument->pInfo->Name.c_str();
1286      rowInstr[m_Columns.m_col_instr] = instrument;      rowInstr[m_Columns.m_col_instr] = instrument;
1287        file_changed();
1288  }  }
1289    
1290  void MainWindow::on_action_remove_instrument() {  void MainWindow::on_action_remove_instrument() {
1291      if (!file) return;      if (!file) return;
1292        if (file_is_shared) {
1293            Gtk::MessageDialog msg(
1294                *this,
1295                 _("You cannot delete an instrument from this file, since it's "
1296                   "currently used by the sampler."),
1297                 false, Gtk::MESSAGE_INFO
1298            );
1299            msg.run();
1300            return;
1301        }
1302    
1303      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();      Glib::RefPtr<Gtk::TreeSelection> sel = m_TreeView.get_selection();
1304      Gtk::TreeModel::iterator it = sel->get_selected();      Gtk::TreeModel::iterator it = sel->get_selected();
1305      if (it) {      if (it) {
# Line 872  void MainWindow::on_action_remove_instru Line 1310  void MainWindow::on_action_remove_instru
1310              if (instr) file->DeleteInstrument(instr);              if (instr) file->DeleteInstrument(instr);
1311              // remove respective row from instruments tree view              // remove respective row from instruments tree view
1312              m_refTreeModel->erase(it);              m_refTreeModel->erase(it);
1313                file_changed();
1314          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1315              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1316              msg.run();              msg.run();
# Line 900  void MainWindow::on_action_add_group() { Line 1339  void MainWindow::on_action_add_group() {
1339      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();      rowGroup[m_SamplesModel.m_col_name] = group->Name.c_str();
1340      rowGroup[m_SamplesModel.m_col_sample] = NULL;      rowGroup[m_SamplesModel.m_col_sample] = NULL;
1341      rowGroup[m_SamplesModel.m_col_group] = group;      rowGroup[m_SamplesModel.m_col_group] = group;
1342        file_changed();
1343  }  }
1344    
1345  void MainWindow::on_action_add_sample() {  void MainWindow::on_action_add_sample() {
# Line 925  void MainWindow::on_action_add_sample() Line 1365  void MainWindow::on_action_add_sample()
1365      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);      dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1366      dialog.set_select_multiple(true);      dialog.set_select_multiple(true);
1367      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile      Gtk::FileFilter soundfilter; // matches all file types supported by libsndfile
1368      const char* supportedFileTypes[] = {      const char* const supportedFileTypes[] = {
1369          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",          "*.wav", "*.WAV", "*.aiff", "*.AIFF", "*.aifc", "*.AIFC", "*.snd",
1370          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",          "*.SND", "*.au", "*.AU", "*.paf", "*.PAF", "*.iff", "*.IFF",
1371          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",          "*.svx", "*.SVX", "*.sf", "*.SF", "*.voc", "*.VOC", "*.w64",
# Line 955  void MainWindow::on_action_add_sample() Line 1395  void MainWindow::on_action_add_sample()
1395                  int bitdepth;                  int bitdepth;
1396                  switch (info.format & 0xff) {                  switch (info.format & 0xff) {
1397                      case SF_FORMAT_PCM_S8:                      case SF_FORMAT_PCM_S8:
                         bitdepth = 16; // we simply convert to 16 bit for now  
                         break;  
1398                      case SF_FORMAT_PCM_16:                      case SF_FORMAT_PCM_16:
1399                        case SF_FORMAT_PCM_U8:
1400                          bitdepth = 16;                          bitdepth = 16;
1401                          break;                          break;
1402                      case SF_FORMAT_PCM_24:                      case SF_FORMAT_PCM_24:
                         bitdepth = 32; // we simply convert to 32 bit for now  
                         break;  
1403                      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;  
1404                      case SF_FORMAT_FLOAT:                      case SF_FORMAT_FLOAT:
                         bitdepth = 32;  
                         break;  
1405                      case SF_FORMAT_DOUBLE:                      case SF_FORMAT_DOUBLE:
1406                          bitdepth = 32; // I guess we will always truncate this to 32 bit                          bitdepth = 24;
1407                          break;                          break;
1408                      default:                      default:
1409                          sf_close(hFile); // close sound file                          sf_close(hFile); // close sound file
# Line 982  void MainWindow::on_action_add_sample() Line 1412  void MainWindow::on_action_add_sample()
1412                  // add a new sample to the .gig file                  // add a new sample to the .gig file
1413                  gig::Sample* sample = file->AddSample();                  gig::Sample* sample = file->AddSample();
1414                  // file name without path                  // file name without path
1415                  sample->pInfo->Name = (*iter).substr((*iter).rfind('/') + 1).raw();                  Glib::ustring filename = Glib::filename_display_basename(*iter);
1416                    // remove file extension if there is one
1417                    for (int i = 0; supportedFileTypes[i]; i++) {
1418                        if (Glib::str_has_suffix(filename, supportedFileTypes[i] + 1)) {
1419                            filename.erase(filename.length() - strlen(supportedFileTypes[i] + 1));
1420                            break;
1421                        }
1422                    }
1423                    sample->pInfo->Name = filename;
1424                  sample->Channels = info.channels;                  sample->Channels = info.channels;
1425                  sample->BitDepth = bitdepth;                  sample->BitDepth = bitdepth;
1426                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;                  sample->FrameSize = bitdepth / 8/*1 byte are 8 bits*/ * info.channels;
1427                  sample->SamplesPerSecond = info.samplerate;                  sample->SamplesPerSecond = info.samplerate;
1428                    sample->AverageBytesPerSecond = sample->FrameSize * sample->SamplesPerSecond;
1429                    sample->BlockAlign = sample->FrameSize;
1430                    sample->SamplesTotal = info.frames;
1431    
1432                    SF_INSTRUMENT instrument;
1433                    if (sf_command(hFile, SFC_GET_INSTRUMENT,
1434                                   &instrument, sizeof(instrument)) != SF_FALSE)
1435                    {
1436                        sample->MIDIUnityNote = instrument.basenote;
1437    
1438    #if HAVE_SF_INSTRUMENT_LOOPS
1439                        if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
1440                            sample->Loops = 1;
1441    
1442                            switch (instrument.loops[0].mode) {
1443                            case SF_LOOP_FORWARD:
1444                                sample->LoopType = gig::loop_type_normal;
1445                                break;
1446                            case SF_LOOP_BACKWARD:
1447                                sample->LoopType = gig::loop_type_backward;
1448                                break;
1449                            case SF_LOOP_ALTERNATING:
1450                                sample->LoopType = gig::loop_type_bidirectional;
1451                                break;
1452                            }
1453                            sample->LoopStart = instrument.loops[0].start;
1454                            sample->LoopEnd = instrument.loops[0].end;
1455                            sample->LoopPlayCount = instrument.loops[0].count;
1456                            sample->LoopSize = sample->LoopEnd - sample->LoopStart + 1;
1457                        }
1458    #endif
1459                    }
1460    
1461                  // schedule resizing the sample (which will be done                  // schedule resizing the sample (which will be done
1462                  // physically when File::Save() is called)                  // physically when File::Save() is called)
1463                  sample->Resize(info.frames);                  sample->Resize(info.frames);
# Line 1002  void MainWindow::on_action_add_sample() Line 1473  void MainWindow::on_action_add_sample()
1473                  Gtk::TreeModel::iterator iterSample =                  Gtk::TreeModel::iterator iterSample =
1474                      m_refSamplesTreeModel->append(row.children());                      m_refSamplesTreeModel->append(row.children());
1475                  Gtk::TreeModel::Row rowSample = *iterSample;                  Gtk::TreeModel::Row rowSample = *iterSample;
1476                  rowSample[m_SamplesModel.m_col_name]   = sample->pInfo->Name.c_str();                  rowSample[m_SamplesModel.m_col_name]   = filename;
1477                  rowSample[m_SamplesModel.m_col_sample] = sample;                  rowSample[m_SamplesModel.m_col_sample] = sample;
1478                  rowSample[m_SamplesModel.m_col_group]  = NULL;                  rowSample[m_SamplesModel.m_col_group]  = NULL;
1479                  // close sound file                  // close sound file
1480                  sf_close(hFile);                  sf_close(hFile);
1481                    file_changed();
1482              } 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)
1483                  if (error_files.size()) error_files += "\n";                  if (error_files.size()) error_files += "\n";
1484                  error_files += *iter += " (" + what + ")";                  error_files += *iter += " (" + what + ")";
# Line 1014  void MainWindow::on_action_add_sample() Line 1486  void MainWindow::on_action_add_sample()
1486          }          }
1487          // show error message box when some file(s) could not be opened / added          // show error message box when some file(s) could not be opened / added
1488          if (error_files.size()) {          if (error_files.size()) {
1489              Glib::ustring txt = "Could not add the following sample(s):\n" + error_files;              Glib::ustring txt = _("Could not add the following sample(s):\n") + error_files;
1490              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
1491              msg.run();              msg.run();
1492          }          }
# Line 1040  void MainWindow::on_action_remove_sample Line 1512  void MainWindow::on_action_remove_sample
1512                       pSample; pSample = group->GetNextSample()) {                       pSample; pSample = group->GetNextSample()) {
1513                      members.push_back(pSample);                      members.push_back(pSample);
1514                  }                  }
1515                    // notify everybody that we're going to remove these samples
1516                    samples_to_be_removed_signal.emit(members);
1517                  // delete the group in the .gig file including the                  // delete the group in the .gig file including the
1518                  // samples that belong to the group                  // samples that belong to the group
1519                  file->DeleteGroup(group);                  file->DeleteGroup(group);
1520                    // notify that we're done with removal
1521                    samples_removed_signal.emit();
1522                  // if sample(s) were just previously added, remove                  // if sample(s) were just previously added, remove
1523                  // them from the import queue                  // them from the import queue
1524                  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 1533  void MainWindow::on_action_remove_sample
1533                          }                          }
1534                      }                      }
1535                  }                  }
1536                    file_changed();
1537              } else if (sample) {              } else if (sample) {
1538                    // notify everybody that we're going to remove this sample
1539                    std::list<gig::Sample*> lsamples;
1540                    lsamples.push_back(sample);
1541                    samples_to_be_removed_signal.emit(lsamples);
1542                  // remove sample from the .gig file                  // remove sample from the .gig file
1543                  file->DeleteSample(sample);                  file->DeleteSample(sample);
1544                    // notify that we're done with removal
1545                    samples_removed_signal.emit();
1546                  // if sample was just previously added, remove it from                  // if sample was just previously added, remove it from
1547                  // the import queue                  // the import queue
1548                  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 1554  void MainWindow::on_action_remove_sample
1554                          break;                          break;
1555                      }                      }
1556                  }                  }
1557                    dimreg_changed();
1558                    file_changed();
1559              }              }
1560              // remove respective row(s) from samples tree view              // remove respective row(s) from samples tree view
1561              m_refSamplesTreeModel->erase(it);              m_refSamplesTreeModel->erase(it);
1562          } catch (RIFF::Exception e) {          } catch (RIFF::Exception e) {
1563                // pretend we're done with removal (i.e. to avoid dead locks)
1564                samples_removed_signal.emit();
1565                // show error message
1566              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);              Gtk::MessageDialog msg(*this, e.Message.c_str(), false, Gtk::MESSAGE_ERROR);
1567              msg.run();              msg.run();
1568          }          }
1569      }      }
1570  }  }
1571    
1572    // For some reason drag_data_get gets called two times for each
1573    // drag'n'drop (at least when target is an Entry). This work-around
1574    // makes sure the code in drag_data_get and drop_drag_data_received is
1575    // only executed once, as drag_begin only gets called once.
1576    void MainWindow::on_sample_treeview_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context)
1577    {
1578        first_call_to_drag_data_get = true;
1579    }
1580    
1581  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>&,
1582                                                    Gtk::SelectionData& selection_data, guint, guint)                                                    Gtk::SelectionData& selection_data, guint, guint)
1583  {  {
1584        if (!first_call_to_drag_data_get) return;
1585        first_call_to_drag_data_get = false;
1586    
1587      // get selected sample      // get selected sample
1588      gig::Sample* sample = NULL;      gig::Sample* sample = NULL;
1589      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 1601  void MainWindow::on_sample_label_drop_dr
1601      const Glib::RefPtr<Gdk::DragContext>& context, int, int,      const Glib::RefPtr<Gdk::DragContext>& context, int, int,
1602      const Gtk::SelectionData& selection_data, guint, guint time)      const Gtk::SelectionData& selection_data, guint, guint time)
1603  {  {
     gig::DimensionRegion* dimregion = m_DimRegionChooser.get_dimregion();  
1604      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());      gig::Sample* sample = *((gig::Sample**) selection_data.get_data());
1605    
1606      if (sample && dimregion && selection_data.get_length() == sizeof(gig::Sample*)) {      if (sample && selection_data.get_length() == sizeof(gig::Sample*)) {
1607          if (sample != dimregion->pSample) {          std::cout << "Drop received sample \"" <<
1608              dimregion->pSample = sample;              sample->pInfo->Name << "\"" << std::endl;
1609              dimreg_edit.wSample->set_text(dimregion->pSample->pInfo->Name.c_str());          // drop success
1610              std::cout << "Drop received sample \"" <<          context->drop_reply(true, time);
1611                  dimregion->pSample->pInfo->Name.c_str() << "\"" << std::endl;  
1612              // drop success          //TODO: we should better move most of the following code to DimRegionEdit::set_sample()
1613              context->drop_reply(true, time);  
1614              return;          // notify everybody that we're going to alter the region
1615            gig::Region* region = m_RegionChooser.get_region();
1616            region_to_be_changed_signal.emit(region);
1617    
1618            // find the samplechannel dimension
1619            gig::dimension_def_t* stereo_dimension = 0;
1620            for (int i = 0 ; i < region->Dimensions ; i++) {
1621                if (region->pDimensionDefinitions[i].dimension ==
1622                    gig::dimension_samplechannel) {
1623                    stereo_dimension = &region->pDimensionDefinitions[i];
1624                    break;
1625                }
1626            }
1627            bool channels_changed = false;
1628            if (sample->Channels == 1 && stereo_dimension) {
1629                // remove the samplechannel dimension
1630                region->DeleteDimension(stereo_dimension);
1631                channels_changed = true;
1632                region_changed();
1633            }
1634            dimreg_edit.set_sample(sample);
1635    
1636            if (sample->Channels == 2 && !stereo_dimension) {
1637                // add samplechannel dimension
1638                gig::dimension_def_t dim;
1639                dim.dimension = gig::dimension_samplechannel;
1640                dim.bits = 1;
1641                dim.zones = 2;
1642                region->AddDimension(&dim);
1643                channels_changed = true;
1644                region_changed();
1645            }
1646            if (channels_changed) {
1647                // unmap all samples with wrong number of channels
1648                // TODO: maybe there should be a warning dialog for this
1649                for (int i = 0 ; i < region->DimensionRegions ; i++) {
1650                    gig::DimensionRegion* d = region->pDimensionRegions[i];
1651                    if (d->pSample && d->pSample->Channels != sample->Channels) {
1652                        gig::Sample* oldref = d->pSample;
1653                        d->pSample = NULL;
1654                        sample_ref_changed_signal.emit(oldref, NULL);
1655                    }
1656                }
1657          }          }
1658    
1659            // notify we're done with altering
1660            region_changed_signal.emit(region);
1661    
1662            file_changed();
1663    
1664            return;
1665      }      }
1666      // drop failed      // drop failed
1667      context->drop_reply(false, time);      context->drop_reply(false, time);
# Line 1127  void MainWindow::sample_name_changed(con Line 1675  void MainWindow::sample_name_changed(con
1675      gig::Group* group   = row[m_SamplesModel.m_col_group];      gig::Group* group   = row[m_SamplesModel.m_col_group];
1676      gig::Sample* sample = row[m_SamplesModel.m_col_sample];      gig::Sample* sample = row[m_SamplesModel.m_col_sample];
1677      if (group) {      if (group) {
1678          group->Name = name;          if (group->Name != name) {
1679                group->Name = name;
1680                printf("group name changed\n");
1681                file_changed();
1682            }
1683      } else if (sample) {      } else if (sample) {
1684          sample->pInfo->Name = name.raw();          if (sample->pInfo->Name != name.raw()) {
1685                sample->pInfo->Name = name.raw();
1686                printf("sample name changed\n");
1687                file_changed();
1688            }
1689      }      }
1690  }  }
1691    
# Line 1139  void MainWindow::instrument_name_changed Line 1695  void MainWindow::instrument_name_changed
1695      Gtk::TreeModel::Row row = *iter;      Gtk::TreeModel::Row row = *iter;
1696      Glib::ustring name = row[m_Columns.m_col_name];      Glib::ustring name = row[m_Columns.m_col_name];
1697      gig::Instrument* instrument = row[m_Columns.m_col_instr];      gig::Instrument* instrument = row[m_Columns.m_col_instr];
1698      if (instrument) instrument->pInfo->Name = name.raw();      if (instrument && instrument->pInfo->Name != name.raw()) {
1699            instrument->pInfo->Name = name.raw();
1700            file_changed();
1701        }
1702    }
1703    
1704    void MainWindow::set_file_is_shared(bool b) {
1705        this->file_is_shared = b;
1706    
1707        if (file_is_shared) {
1708            m_AttachedStateLabel.set_label(_("live-mode"));
1709            m_AttachedStateImage.set(
1710                Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm)
1711            );
1712        } else {
1713            m_AttachedStateLabel.set_label(_("stand-alone"));
1714            m_AttachedStateImage.set(
1715                Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm)
1716            );
1717        }
1718    }
1719    
1720    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_to_be_changed() {
1721        return file_structure_to_be_changed_signal;
1722    }
1723    
1724    sigc::signal<void, gig::File*>& MainWindow::signal_file_structure_changed() {
1725        return file_structure_changed_signal;
1726    }
1727    
1728    sigc::signal<void, std::list<gig::Sample*> >& MainWindow::signal_samples_to_be_removed() {
1729        return samples_to_be_removed_signal;
1730    }
1731    
1732    sigc::signal<void>& MainWindow::signal_samples_removed() {
1733        return samples_removed_signal;
1734    }
1735    
1736    sigc::signal<void, gig::Region*>& MainWindow::signal_region_to_be_changed() {
1737        return region_to_be_changed_signal;
1738    }
1739    
1740    sigc::signal<void, gig::Region*>& MainWindow::signal_region_changed() {
1741        return region_changed_signal;
1742    }
1743    
1744    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& MainWindow::signal_sample_ref_changed() {
1745        return sample_ref_changed_signal;
1746    }
1747    
1748    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_to_be_changed() {
1749        return dimreg_to_be_changed_signal;
1750    }
1751    
1752    sigc::signal<void, gig::DimensionRegion*>& MainWindow::signal_dimreg_changed() {
1753        return dimreg_changed_signal;
1754    }
1755    
1756    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_note_on() {
1757        return note_on_signal;
1758    }
1759    
1760    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_note_off() {
1761        return note_off_signal;
1762    }
1763    
1764    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_keyboard_key_hit() {
1765        return m_RegionChooser.signal_keyboard_key_hit();
1766    }
1767    
1768    sigc::signal<void, int/*key*/, int/*velocity*/>& MainWindow::signal_keyboard_key_released() {
1769        return m_RegionChooser.signal_keyboard_key_released();
1770  }  }

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

  ViewVC Help
Powered by ViewVC