--- gigedit/trunk/src/gigedit/mainwindow.cpp 2007/09/07 21:18:31 1328 +++ gigedit/trunk/src/gigedit/mainwindow.cpp 2007/12/01 10:21:07 1533 @@ -17,7 +17,6 @@ * 02110-1301 USA. */ -#include #include #include @@ -25,6 +24,9 @@ #include #include #include +#include + +#include "global.h" #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2 #define ABOUT_DIALOG @@ -48,7 +50,8 @@ #include "mainwindow.h" -#define _(String) gettext(String) +#include "../../gfx/status_attached.xpm" +#include "../../gfx/status_detached.xpm" template inline std::string ToString(T o) { std::stringstream ss; @@ -56,7 +59,11 @@ return ss.str(); } -MainWindow::MainWindow() +MainWindow::MainWindow() : + dimreg_label(_("Changes apply to:")), + dimreg_all_regions(_("all regions")), + dimreg_all_dimregs(_("all dimension splits")), + dimreg_stereo(_("both channels")) { // set_border_width(5); // set_default_size(400, 200); @@ -86,7 +93,14 @@ m_TreeViewNotebook.set_size_request(300); m_HPaned.add1(m_TreeViewNotebook); - m_HPaned.add2(dimreg_edit); + dimreg_hbox.add(dimreg_label); + dimreg_hbox.add(dimreg_all_regions); + dimreg_hbox.add(dimreg_all_dimregs); + dimreg_stereo.set_active(); + dimreg_hbox.add(dimreg_stereo); + dimreg_vbox.add(dimreg_edit); + dimreg_vbox.add(dimreg_hbox); + m_HPaned.add2(dimreg_vbox); m_TreeViewNotebook.append_page(m_ScrolledWindowSamples, "Samples"); @@ -127,6 +141,14 @@ *this, &MainWindow::on_action_quit)); actionGroup->add(Gtk::Action::create("MenuInstrument", _("_Instrument"))); + actionGroup->add(Gtk::Action::create("MenuView", _("_View"))); + Glib::RefPtr toggle_action = + Gtk::ToggleAction::create("Statusbar", _("_Statusbar")); + toggle_action->set_active(true); + actionGroup->add(toggle_action, + sigc::mem_fun( + *this, &MainWindow::on_action_view_status_bar)); + action = Gtk::Action::create("MenuHelp", Gtk::Stock::HELP); actionGroup->add(Gtk::Action::create("MenuHelp", action->property_label())); @@ -182,6 +204,9 @@ " " " " " " + " " + " " + " " #ifdef ABOUT_DIALOG " " " " @@ -211,6 +236,12 @@ m_VBox.pack_start(m_HPaned); m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK); m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK); + m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK); + + // Status Bar: + m_StatusBar.pack_start(m_AttachedStateLabel, Gtk::PACK_SHRINK); + m_StatusBar.pack_start(m_AttachedStateImage, Gtk::PACK_SHRINK); + m_StatusBar.show(); m_RegionChooser.signal_region_selected().connect( sigc::mem_fun(*this, &MainWindow::region_changed) ); @@ -293,8 +324,16 @@ m_RegionChooser.signal_region_changed_signal().connect( region_changed_signal.make_slot()); + dimreg_all_regions.signal_toggled().connect( + sigc::mem_fun(*this, &MainWindow::update_dimregs)); + dimreg_all_dimregs.signal_toggled().connect( + sigc::mem_fun(*this, &MainWindow::dimreg_all_dimregs_toggled)); + dimreg_stereo.signal_toggled().connect( + sigc::mem_fun(*this, &MainWindow::update_dimregs)); + file = 0; file_is_changed = false; + set_file_is_shared(false); show_all_children(); @@ -308,12 +347,12 @@ bool MainWindow::on_delete_event(GdkEventAny* event) { - return file_is_changed && !close_confirmation_dialog(); + return !file_is_shared && file_is_changed && !close_confirmation_dialog(); } void MainWindow::on_action_quit() { - if (file_is_changed && !close_confirmation_dialog()) return; + if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return; hide(); } @@ -322,26 +361,73 @@ m_DimRegionChooser.set_region(m_RegionChooser.get_region()); } -void MainWindow::dimreg_changed() -{ - dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion()); -} - -void MainWindow::on_sel_change() +gig::Instrument* MainWindow::get_instrument() { + gig::Instrument* instrument = 0; Glib::RefPtr tree_sel_ref = m_TreeView.get_selection(); Gtk::TreeModel::iterator it = tree_sel_ref->get_selected(); if (it) { Gtk::TreeModel::Row row = *it; - std::cout << row[m_Columns.m_col_name] << std::endl; + instrument = row[m_Columns.m_col_instr]; + } + return instrument; +} + +void MainWindow::add_region_to_dimregs(gig::Region* region, bool stereo, bool all_dimregs) +{ + if (all_dimregs) { + for (int i = 0 ; i < region->DimensionRegions ; i++) { + if (region->pDimensionRegions[i]) { + dimreg_edit.dimregs.insert(region->pDimensionRegions[i]); + } + } + } else { + m_DimRegionChooser.get_dimregions(region, stereo, dimreg_edit.dimregs); + } +} + +void MainWindow::update_dimregs() +{ + dimreg_edit.dimregs.clear(); + bool all_regions = dimreg_all_regions.get_active(); + bool stereo = dimreg_stereo.get_active(); + bool all_dimregs = dimreg_all_dimregs.get_active(); - m_RegionChooser.set_instrument(row[m_Columns.m_col_instr]); + if (all_regions) { + gig::Instrument* instrument = get_instrument(); + if (instrument) { + for (gig::Region* region = instrument->GetFirstRegion() ; + region ; + region = instrument->GetNextRegion()) { + add_region_to_dimregs(region, stereo, all_dimregs); + } + } } else { - m_RegionChooser.set_instrument(0); + gig::Region* region = m_RegionChooser.get_region(); + if (region) { + add_region_to_dimregs(region, stereo, all_dimregs); + } } } +void MainWindow::dimreg_all_dimregs_toggled() +{ + dimreg_stereo.set_sensitive(!dimreg_all_dimregs.get_active()); + update_dimregs(); +} + +void MainWindow::dimreg_changed() +{ + update_dimregs(); + dimreg_edit.set_dim_region(m_DimRegionChooser.get_dimregion()); +} + +void MainWindow::on_sel_change() +{ + m_RegionChooser.set_instrument(get_instrument()); +} + void loader_progress_callback(gig::progress_t* progress) { Loader* loader = static_cast(progress->custom); @@ -427,15 +513,16 @@ m_refTreeModel->clear(); m_refSamplesTreeModel->clear(); // free libgig's gig::File instance - if (file) { - delete file; - file = NULL; - } + if (file && !file_is_shared) delete file; + file = NULL; + set_file_is_shared(false); } void MainWindow::on_action_file_new() { - if (file_is_changed && !close_confirmation_dialog()) return; + if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return; + + if (file_is_shared && !leaving_shared_mode_dialog()) return; // clear all GUI elements __clear(); @@ -467,9 +554,29 @@ return response != Gtk::RESPONSE_CANCEL; } +bool MainWindow::leaving_shared_mode_dialog() { + Glib::ustring msg = _("Detach from sampler and proceed working stand-alone?"); + Gtk::MessageDialog dialog(*this, msg, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE); +#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 6) || GTKMM_MAJOR_VERSION > 2 + dialog.set_secondary_text( + _("If you proceed to work on another instrument file, it won't be " + "used by the sampler until you tell the sampler explicitly to " + "load it.") + ); +#endif + dialog.add_button(_("_Yes, Detach"), Gtk::RESPONSE_YES); + dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dialog.set_default_response(Gtk::RESPONSE_CANCEL); + int response = dialog.run(); + dialog.hide(); + return response == Gtk::RESPONSE_YES; +} + void MainWindow::on_action_file_open() { - if (file_is_changed && !close_confirmation_dialog()) return; + if (!file_is_shared && file_is_changed && !close_confirmation_dialog()) return; + + if (file_is_shared && !leaving_shared_mode_dialog()) return; Gtk::FileChooserDialog dialog(*this, _("Open file")); dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); @@ -514,7 +621,7 @@ __clear(); // load the instrument gig::File* pFile = (gig::File*) instr->GetParent(); - load_gig(pFile, 0 /*file name*/); + load_gig(pFile, 0 /*file name*/, true /*shared instrument*/); //TODO: automatically select the given instrument } @@ -563,7 +670,7 @@ bool MainWindow::file_save() { if (!check_if_savable()) return false; - if (!file_has_name) return file_save_as(); + if (!file_is_shared && !file_has_name) return file_save_as(); std::cout << "Saving file\n" << std::flush; file_structure_to_be_changed_signal.emit(this->file); @@ -575,7 +682,7 @@ } } catch (RIFF::Exception e) { file_structure_changed_signal.emit(this->file); - Glib::ustring txt = "Could not save file: " + e.Message; + Glib::ustring txt = _("Could not save file: ") + e.Message; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); return false; @@ -630,7 +737,7 @@ file_is_changed = false; } catch (RIFF::Exception e) { file_structure_changed_signal.emit(this->file); - Glib::ustring txt = "Could not save file: " + e.Message; + Glib::ustring txt = _("Could not save file: ") + e.Message; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); return false; @@ -727,7 +834,7 @@ } // show error message box when some sample(s) could not be imported if (error_files.size()) { - 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; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); } @@ -744,6 +851,18 @@ #ifdef ABOUT_DIALOG Gtk::AboutDialog dialog; dialog.set_version(VERSION); + dialog.set_copyright("Copyright (C) 2006,2007 Andreas Persson"); + dialog.set_comments( + "Released under the GNU General Public License.\n" + "\n" + "Please notice that this is still a very young instrument editor. " + "So better backup your Gigasampler files before editing them with " + "this application.\n" + "\n" + "Please report bugs to: http://bugs.linuxsampler.org" + ); + dialog.set_website("http://www.linuxsampler.org"); + dialog.set_website_label("http://www.linuxsampler.org"); dialog.run(); #endif } @@ -804,12 +923,42 @@ entry[15].set_text(info->Subject); } +void InstrumentProps::set_IsDrum(bool value) +{ + instrument->IsDrum = value; +} + +void InstrumentProps::set_MIDIBank(uint16_t value) +{ + instrument->MIDIBank = value; +} + +void InstrumentProps::set_MIDIProgram(uint32_t value) +{ + instrument->MIDIProgram = value; +} + +void InstrumentProps::set_DimensionKeyRange_low(uint8_t value) +{ + instrument->DimensionKeyRange.low = value; + if (value > instrument->DimensionKeyRange.high) { + eDimensionKeyRangeHigh.set_value(value); + } +} + +void InstrumentProps::set_DimensionKeyRange_high(uint8_t value) +{ + instrument->DimensionKeyRange.high = value; + if (value < instrument->DimensionKeyRange.low) { + eDimensionKeyRangeLow.set_value(value); + } +} + void InstrumentProps::add_prop(BoolEntry& boolentry) { table.attach(boolentry.widget, 0, 2, rowno, rowno + 1, Gtk::FILL, Gtk::SHRINK); rowno++; - boolentry.signal_changed_by_user().connect(instrument_changed.make_slot()); } void InstrumentProps::add_prop(BoolEntryPlus6& boolentry) @@ -817,7 +966,6 @@ table.attach(boolentry.widget, 0, 2, rowno, rowno + 1, Gtk::FILL, Gtk::SHRINK); rowno++; - boolentry.signal_changed_by_user().connect(instrument_changed.make_slot()); } void InstrumentProps::add_prop(LabelWidget& prop) @@ -827,7 +975,6 @@ table.attach(prop.widget, 1, 2, rowno, rowno + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK); rowno++; - prop.signal_changed_by_user().connect(instrument_changed.make_slot()); } InstrumentProps::InstrumentProps() @@ -844,10 +991,25 @@ ePitchbendRange("Pitchbend range", 0, 12), ePianoReleaseMode("Piano release mode"), eDimensionKeyRangeLow("Dimension key range low"), - eDimensionKeyRangeHigh("Dimension key range high") + eDimensionKeyRangeHigh("Dimension key range high"), + update_model(0) { set_title("Instrument properties"); + connect(eIsDrum, &InstrumentProps::set_IsDrum); + connect(eMIDIBank, &InstrumentProps::set_MIDIBank); + connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram); + connect(eAttenuation, &gig::Instrument::Attenuation); + connect(eGainPlus6, &gig::Instrument::Attenuation); + connect(eEffectSend, &gig::Instrument::EffectSend); + connect(eFineTune, &gig::Instrument::FineTune); + connect(ePitchbendRange, &gig::Instrument::PitchbendRange); + connect(ePianoReleaseMode, &gig::Instrument::PianoReleaseMode); + connect(eDimensionKeyRangeLow, + &InstrumentProps::set_DimensionKeyRange_low); + connect(eDimensionKeyRangeHigh, + &InstrumentProps::set_DimensionKeyRange_high); + rowno = 0; table.set_col_spacings(5); @@ -864,11 +1026,6 @@ add_prop(eDimensionKeyRangeLow); add_prop(eDimensionKeyRangeHigh); - eDimensionKeyRangeLow.signal_changed_by_user().connect( - sigc::mem_fun(*this, &InstrumentProps::key_range_low_changed)); - eDimensionKeyRangeHigh.signal_changed_by_user().connect( - sigc::mem_fun(*this, &InstrumentProps::key_range_high_changed)); - add(vbox); table.set_border_width(5); vbox.pack_start(table); @@ -891,37 +1048,25 @@ void InstrumentProps::set_instrument(gig::Instrument* instrument) { - eName.set_ptr(&instrument->pInfo->Name); - eIsDrum.set_ptr(&instrument->IsDrum); - eMIDIBank.set_ptr(&instrument->MIDIBank); - eMIDIProgram.set_ptr(&instrument->MIDIProgram); - eAttenuation.set_ptr(&instrument->Attenuation); - eGainPlus6.set_ptr(&instrument->Attenuation); - eEffectSend.set_ptr(&instrument->EffectSend); - eFineTune.set_ptr(&instrument->FineTune); - ePitchbendRange.set_ptr(&instrument->PitchbendRange); - ePianoReleaseMode.set_ptr(&instrument->PianoReleaseMode); - eDimensionKeyRangeLow.set_ptr(0); - eDimensionKeyRangeHigh.set_ptr(0); - eDimensionKeyRangeLow.set_ptr(&instrument->DimensionKeyRange.low); - eDimensionKeyRangeHigh.set_ptr(&instrument->DimensionKeyRange.high); -} - -void InstrumentProps::key_range_low_changed() -{ - double l = eDimensionKeyRangeLow.get_value(); - double h = eDimensionKeyRangeHigh.get_value(); - if (h < l) eDimensionKeyRangeHigh.set_value(l); -} + this->instrument = instrument; -void InstrumentProps::key_range_high_changed() -{ - double l = eDimensionKeyRangeLow.get_value(); - double h = eDimensionKeyRangeHigh.get_value(); - if (h < l) eDimensionKeyRangeLow.set_value(h); + update_model++; + eName.set_ptr(&instrument->pInfo->Name); + eIsDrum.set_value(instrument->IsDrum); + eMIDIBank.set_value(instrument->MIDIBank); + eMIDIProgram.set_value(instrument->MIDIProgram); + eAttenuation.set_value(instrument->Attenuation); + eGainPlus6.set_value(instrument->Attenuation); + eEffectSend.set_value(instrument->EffectSend); + eFineTune.set_value(instrument->FineTune); + ePitchbendRange.set_value(instrument->PitchbendRange); + ePianoReleaseMode.set_value(instrument->PianoReleaseMode); + eDimensionKeyRangeLow.set_value(instrument->DimensionKeyRange.low); + eDimensionKeyRangeHigh.set_value(instrument->DimensionKeyRange.high); + update_model--; } -sigc::signal InstrumentProps::signal_instrument_changed() +sigc::signal& InstrumentProps::signal_instrument_changed() { return instrument_changed; } @@ -934,9 +1079,10 @@ } } -void MainWindow::load_gig(gig::File* gig, const char* filename) +void MainWindow::load_gig(gig::File* gig, const char* filename, bool isSharedInstrument) { file = 0; + set_file_is_shared(isSharedInstrument); this->filename = filename ? filename : _("Unsaved Gig File"); set_title(Glib::filename_display_basename(this->filename)); @@ -999,20 +1145,26 @@ void MainWindow::show_instr_props() { - Glib::RefPtr tree_sel_ref = m_TreeView.get_selection(); - Gtk::TreeModel::iterator it = tree_sel_ref->get_selected(); - if (it) + gig::Instrument* instrument = get_instrument(); + if (instrument) { - Gtk::TreeModel::Row row = *it; - if (row[m_Columns.m_col_instr]) - { - instrumentProps.set_instrument(row[m_Columns.m_col_instr]); - instrumentProps.show(); - instrumentProps.deiconify(); - } + instrumentProps.set_instrument(instrument); + instrumentProps.show(); + instrumentProps.deiconify(); } } +void MainWindow::on_action_view_status_bar() { + Gtk::CheckMenuItem* item = + dynamic_cast(uiManager->get_widget("/MenuBar/MenuView/Statusbar")); + if (!item) { + std::cerr << "/MenuBar/MenuView/Statusbar == NULL\n"; + return; + } + if (item->get_active()) m_StatusBar.show(); + else m_StatusBar.hide(); +} + void MainWindow::on_button_release(GdkEventButton* button) { if (button->type == GDK_2BUTTON_PRESS) { @@ -1070,6 +1222,17 @@ void MainWindow::on_action_remove_instrument() { if (!file) return; + if (file_is_shared) { + Gtk::MessageDialog msg( + *this, + _("You cannot delete an instrument from this file, since it's " + "currently used by the sampler."), + false, Gtk::MESSAGE_INFO + ); + msg.run(); + return; + } + Glib::RefPtr sel = m_TreeView.get_selection(); Gtk::TreeModel::iterator it = sel->get_selected(); if (it) { @@ -1256,7 +1419,7 @@ } // show error message box when some file(s) could not be opened / added if (error_files.size()) { - 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; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); } @@ -1429,6 +1592,8 @@ // notify we're done with altering region_changed_signal.emit(region); + file_changed(); + return; } // drop failed @@ -1469,38 +1634,54 @@ } } -sigc::signal MainWindow::signal_file_structure_to_be_changed() { +void MainWindow::set_file_is_shared(bool b) { + this->file_is_shared = b; + + if (file_is_shared) { + m_AttachedStateLabel.set_label(_("live-mode")); + m_AttachedStateImage.set( + Gdk::Pixbuf::create_from_xpm_data(status_attached_xpm) + ); + } else { + m_AttachedStateLabel.set_label(_("stand-alone")); + m_AttachedStateImage.set( + Gdk::Pixbuf::create_from_xpm_data(status_detached_xpm) + ); + } +} + +sigc::signal& MainWindow::signal_file_structure_to_be_changed() { return file_structure_to_be_changed_signal; } -sigc::signal MainWindow::signal_file_structure_changed() { +sigc::signal& MainWindow::signal_file_structure_changed() { return file_structure_changed_signal; } -sigc::signal > MainWindow::signal_samples_to_be_removed() { +sigc::signal >& MainWindow::signal_samples_to_be_removed() { return samples_to_be_removed_signal; } -sigc::signal MainWindow::signal_samples_removed() { +sigc::signal& MainWindow::signal_samples_removed() { return samples_removed_signal; } -sigc::signal MainWindow::signal_region_to_be_changed() { +sigc::signal& MainWindow::signal_region_to_be_changed() { return region_to_be_changed_signal; } -sigc::signal MainWindow::signal_region_changed() { +sigc::signal& MainWindow::signal_region_changed() { return region_changed_signal; } -sigc::signal MainWindow::signal_sample_ref_changed() { +sigc::signal& MainWindow::signal_sample_ref_changed() { return sample_ref_changed_signal; } -sigc::signal MainWindow::signal_dimreg_to_be_changed() { +sigc::signal& MainWindow::signal_dimreg_to_be_changed() { return dimreg_to_be_changed_signal; } -sigc::signal MainWindow::signal_dimreg_changed() { +sigc::signal& MainWindow::signal_dimreg_changed() { return dimreg_changed_signal; }