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

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

  ViewVC Help
Powered by ViewVC