--- gigedit/trunk/src/gigedit/mainwindow.cpp 2007/12/01 10:21:07 1533
+++ gigedit/trunk/src/gigedit/mainwindow.cpp 2008/02/12 14:13:46 1679
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Andreas Persson
+ * Copyright (C) 2006 - 2008 Andreas Persson
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -59,6 +59,31 @@
return ss.str();
}
+Table::Table(int x, int y) : Gtk::Table(x, y), rowno(0) { }
+
+void Table::add(BoolEntry& boolentry)
+{
+ attach(boolentry.widget, 0, 2, rowno, rowno + 1,
+ Gtk::FILL, Gtk::SHRINK);
+ rowno++;
+}
+
+void Table::add(BoolEntryPlus6& boolentry)
+{
+ attach(boolentry.widget, 0, 2, rowno, rowno + 1,
+ Gtk::FILL, Gtk::SHRINK);
+ rowno++;
+}
+
+void Table::add(LabelWidget& prop)
+{
+ attach(prop.label, 1, 2, rowno, rowno + 1,
+ Gtk::FILL, Gtk::SHRINK);
+ attach(prop.widget, 2, 3, rowno, rowno + 1,
+ Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
+ rowno++;
+}
+
MainWindow::MainWindow() :
dimreg_label(_("Changes apply to:")),
dimreg_all_regions(_("all regions")),
@@ -99,7 +124,7 @@
dimreg_stereo.set_active();
dimreg_hbox.add(dimreg_stereo);
dimreg_vbox.add(dimreg_edit);
- dimreg_vbox.add(dimreg_hbox);
+ dimreg_vbox.pack_start(dimreg_hbox, Gtk::PACK_SHRINK);
m_HPaned.add2(dimreg_vbox);
@@ -183,6 +208,10 @@
Gtk::Action::create("RemoveSample", Gtk::Stock::REMOVE),
sigc::mem_fun(*this, &MainWindow::on_action_remove_sample)
);
+ actionGroup->add(
+ Gtk::Action::create("ReplaceAllSamplesInAllGroups", _("Replace All Samples In All Groups")),
+ sigc::mem_fun(*this, &MainWindow::on_action_replace_all_samples_in_all_groups)
+ );
uiManager = Gtk::UIManager::create();
uiManager->insert_action_group(actionGroup);
@@ -223,6 +252,7 @@
" "
" "
" "
+ " "
" "
" "
" "
@@ -235,6 +265,7 @@
m_VBox.pack_start(*menuBar, Gtk::PACK_SHRINK);
m_VBox.pack_start(m_HPaned);
m_VBox.pack_start(m_RegionChooser, Gtk::PACK_SHRINK);
+ m_VBox.pack_start(m_RegionChooser.m_VirtKeybPropsBox, Gtk::PACK_SHRINK);
m_VBox.pack_start(m_DimRegionChooser, Gtk::PACK_SHRINK);
m_VBox.pack_start(m_StatusBar, Gtk::PACK_SHRINK);
@@ -295,6 +326,8 @@
sigc::mem_fun(*this, &MainWindow::file_changed));
instrumentProps.signal_instrument_changed().connect(
sigc::mem_fun(*this, &MainWindow::file_changed));
+ propDialog.signal_info_changed().connect(
+ sigc::mem_fun(*this, &MainWindow::file_changed));
dimreg_edit.signal_dimreg_to_be_changed().connect(
dimreg_to_be_changed_signal.make_slot());
@@ -324,6 +357,11 @@
m_RegionChooser.signal_region_changed_signal().connect(
region_changed_signal.make_slot());
+ note_on_signal.connect(
+ sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_on_event));
+ note_off_signal.connect(
+ sigc::mem_fun(m_RegionChooser, &RegionChooser::on_note_off_event));
+
dimreg_all_regions.signal_toggled().connect(
sigc::mem_fun(*this, &MainWindow::update_dimregs));
dimreg_all_dimregs.signal_toggled().connect(
@@ -714,12 +752,41 @@
filter.add_pattern("*.gig");
dialog.set_filter(filter);
- if (Glib::path_is_absolute(filename)) {
- dialog.set_filename(filename);
- } else if (current_dir != "") {
- dialog.set_current_folder(current_dir);
+ // set initial dir and filename of the Save As dialog
+ // and prepare that initial filename as a copy of the gig
+ {
+ std::string basename = Glib::path_get_basename(filename);
+ std::string dir = Glib::path_get_dirname(filename);
+ basename = std::string("copy_of_") + basename;
+ Glib::ustring copyFileName = Glib::build_filename(dir, basename);
+ if (Glib::path_is_absolute(filename)) {
+ dialog.set_filename(copyFileName);
+ } else {
+ if (current_dir != "") dialog.set_current_folder(current_dir);
+ }
+ dialog.set_current_name(Glib::filename_display_basename(copyFileName));
}
- dialog.set_current_name(Glib::filename_display_basename(filename));
+
+ // show warning in the dialog
+ Gtk::HBox descriptionArea;
+ descriptionArea.set_spacing(15);
+ Gtk::Image warningIcon(Gtk::Stock::DIALOG_WARNING, Gtk::IconSize(Gtk::ICON_SIZE_DIALOG));
+ descriptionArea.pack_start(warningIcon, Gtk::PACK_SHRINK);
+ warningIcon.show();
+ Gtk::Label description;
+ description.set_markup(
+ _("\nCAUTION: You MUST use the "
+ "\"Save\" dialog instead of "
+ "\"Save As...\" if you want to save "
+ "to the same .gig file. Using "
+ "\"Save As...\" for writing to the "
+ "same .gig file will end up in corrupted sample wave data!\n")
+ );
+ description.set_line_wrap(true);
+ descriptionArea.pack_start(description, Gtk::PACK_SHRINK);
+ description.show();
+ dialog.get_vbox()->pack_start(descriptionArea, Gtk::PACK_SHRINK);
+ descriptionArea.show();
if (dialog.run() == Gtk::RESPONSE_OK) {
file_structure_to_be_changed_signal.emit(this->file);
@@ -868,59 +935,108 @@
}
PropDialog::PropDialog()
- : table(2,1)
+ : table(2,1),
+ eName("Name"),
+ eCreationDate("Creation date"),
+ eComments("Comments"),
+ eProduct("Product"),
+ eCopyright("Copyright"),
+ eArtists("Artists"),
+ eGenre("Genre"),
+ eKeywords("Keywords"),
+ eEngineer("Engineer"),
+ eTechnician("Technician"),
+ eSoftware("Software"),
+ eMedium("Medium"),
+ eSource("Source"),
+ eSourceForm("Source form"),
+ eCommissioned("Commissioned"),
+ eSubject("Subject"),
+ quitButton(Gtk::Stock::CLOSE),
+ update_model(0)
{
+ set_title("File Properties");
+ eName.set_width_chars(50);
+
+ connect(eName, &DLS::Info::Name);
+ connect(eCreationDate, &DLS::Info::CreationDate);
+ connect(eComments, &DLS::Info::Comments);
+ connect(eProduct, &DLS::Info::Product);
+ connect(eCopyright, &DLS::Info::Copyright);
+ connect(eArtists, &DLS::Info::Artists);
+ connect(eGenre, &DLS::Info::Genre);
+ connect(eKeywords, &DLS::Info::Keywords);
+ connect(eEngineer, &DLS::Info::Engineer);
+ connect(eTechnician, &DLS::Info::Technician);
+ connect(eSoftware, &DLS::Info::Software);
+ connect(eMedium, &DLS::Info::Medium);
+ connect(eSource, &DLS::Info::Source);
+ connect(eSourceForm, &DLS::Info::SourceForm);
+ connect(eCommissioned, &DLS::Info::Commissioned);
+ connect(eSubject, &DLS::Info::Subject);
+
+ table.add(eName);
+ table.add(eCreationDate);
+ table.add(eComments);
+ table.add(eProduct);
+ table.add(eCopyright);
+ table.add(eArtists);
+ table.add(eGenre);
+ table.add(eKeywords);
+ table.add(eEngineer);
+ table.add(eTechnician);
+ table.add(eSoftware);
+ table.add(eMedium);
+ table.add(eSource);
+ table.add(eSourceForm);
+ table.add(eCommissioned);
+ table.add(eSubject);
+
table.set_col_spacings(5);
- const char* propLabels[] = {
- "Name:",
- "CreationDate:",
- "Comments:", // TODO: multiline
- "Product:",
- "Copyright:",
- "Artists:",
- "Genre:",
- "Keywords:",
- "Engineer:",
- "Technician:",
- "Software:", // TODO: readonly
- "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);
- }
+ add(vbox);
+ table.set_border_width(5);
+ vbox.add(table);
+ vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
+ buttonBox.set_layout(Gtk::BUTTONBOX_END);
+ buttonBox.set_border_width(5);
+ buttonBox.show();
+ buttonBox.pack_start(quitButton);
+ quitButton.set_flags(Gtk::CAN_DEFAULT);
+ quitButton.grab_focus();
+ quitButton.signal_clicked().connect(
+ sigc::mem_fun(*this, &PropDialog::hide));
- add(table);
- // add_button(Gtk::Stock::CANCEL, 0);
- // add_button(Gtk::Stock::OK, 1);
+ quitButton.show();
+ vbox.show();
show_all_children();
}
void PropDialog::set_info(DLS::Info* info)
{
- entry[0].set_text(info->Name);
- entry[1].set_text(info->CreationDate);
- entry[2].set_text(Glib::convert(info->Comments, "UTF-8", "ISO-8859-1"));
- entry[3].set_text(info->Product);
- entry[4].set_text(info->Copyright);
- entry[5].set_text(info->Artists);
- entry[6].set_text(info->Genre);
- entry[7].set_text(info->Keywords);
- entry[8].set_text(info->Engineer);
- entry[9].set_text(info->Technician);
- entry[10].set_text(info->Software);
- entry[11].set_text(info->Medium);
- entry[12].set_text(info->Source);
- entry[13].set_text(info->SourceForm);
- entry[14].set_text(info->Commissioned);
- entry[15].set_text(info->Subject);
+ this->info = info;
+ update_model++;
+ eName.set_value(info->Name);
+ eCreationDate.set_value(info->CreationDate);
+ eComments.set_value(info->Comments);
+ eProduct.set_value(info->Product);
+ eCopyright.set_value(info->Copyright);
+ eArtists.set_value(info->Artists);
+ eGenre.set_value(info->Genre);
+ eKeywords.set_value(info->Keywords);
+ eEngineer.set_value(info->Engineer);
+ eTechnician.set_value(info->Technician);
+ eSoftware.set_value(info->Software);
+ eMedium.set_value(info->Medium);
+ eSource.set_value(info->Source);
+ eSourceForm.set_value(info->SourceForm);
+ eCommissioned.set_value(info->Commissioned);
+ eSubject.set_value(info->Subject);
+ update_model--;
+}
+
+sigc::signal& PropDialog::signal_info_changed()
+{
+ return info_changed;
}
void InstrumentProps::set_IsDrum(bool value)
@@ -954,29 +1070,6 @@
}
}
-void InstrumentProps::add_prop(BoolEntry& boolentry)
-{
- table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
- Gtk::FILL, Gtk::SHRINK);
- rowno++;
-}
-
-void InstrumentProps::add_prop(BoolEntryPlus6& boolentry)
-{
- table.attach(boolentry.widget, 0, 2, rowno, rowno + 1,
- Gtk::FILL, Gtk::SHRINK);
- rowno++;
-}
-
-void InstrumentProps::add_prop(LabelWidget& prop)
-{
- table.attach(prop.label, 0, 1, rowno, rowno + 1,
- Gtk::FILL, Gtk::SHRINK);
- table.attach(prop.widget, 1, 2, rowno, rowno + 1,
- Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
- rowno++;
-}
-
InstrumentProps::InstrumentProps()
: table(2,1),
quitButton(Gtk::Stock::CLOSE),
@@ -990,11 +1083,20 @@
eFineTune("Fine tune", -8400, 8400),
ePitchbendRange("Pitchbend range", 0, 12),
ePianoReleaseMode("Piano release mode"),
- eDimensionKeyRangeLow("Dimension key range low"),
- eDimensionKeyRangeHigh("Dimension key range high"),
+ eDimensionKeyRangeLow("Keyswitching range low"),
+ eDimensionKeyRangeHigh("Keyswitching range high"),
update_model(0)
{
- set_title("Instrument properties");
+ set_title("Instrument Properties");
+
+ eDimensionKeyRangeLow.set_tip(
+ _("start of the keyboard area which should switch the "
+ "\"keyswitching\" dimension")
+ );
+ eDimensionKeyRangeHigh.set_tip(
+ _("end of the keyboard area which should switch the "
+ "\"keyswitching\" dimension")
+ );
connect(eIsDrum, &InstrumentProps::set_IsDrum);
connect(eMIDIBank, &InstrumentProps::set_MIDIBank);
@@ -1010,21 +1112,20 @@
connect(eDimensionKeyRangeHigh,
&InstrumentProps::set_DimensionKeyRange_high);
- rowno = 0;
table.set_col_spacings(5);
- add_prop(eName);
- add_prop(eIsDrum);
- add_prop(eMIDIBank);
- add_prop(eMIDIProgram);
- add_prop(eAttenuation);
- add_prop(eGainPlus6);
- add_prop(eEffectSend);
- add_prop(eFineTune);
- add_prop(ePitchbendRange);
- add_prop(ePianoReleaseMode);
- add_prop(eDimensionKeyRangeLow);
- add_prop(eDimensionKeyRangeHigh);
+ table.add(eName);
+ table.add(eIsDrum);
+ table.add(eMIDIBank);
+ table.add(eMIDIProgram);
+ table.add(eAttenuation);
+ table.add(eGainPlus6);
+ table.add(eEffectSend);
+ table.add(eFineTune);
+ table.add(ePitchbendRange);
+ table.add(ePianoReleaseMode);
+ table.add(eDimensionKeyRangeLow);
+ table.add(eDimensionKeyRangeHigh);
add(vbox);
table.set_border_width(5);
@@ -1051,7 +1152,7 @@
this->instrument = instrument;
update_model++;
- eName.set_ptr(&instrument->pInfo->Name);
+ eName.set_value(instrument->pInfo->Name);
eIsDrum.set_value(instrument->IsDrum);
eMIDIBank.set_value(instrument->MIDIBank);
eMIDIProgram.set_value(instrument->MIDIProgram);
@@ -1426,6 +1527,108 @@
}
}
+void MainWindow::on_action_replace_all_samples_in_all_groups()
+{
+ if (!file) return;
+ Gtk::FileChooserDialog dialog(*this, _("Select Folder"),
+ Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ Gtk::Label description(
+ _("This is a very specific function. It tries to replace all samples "
+ "in the current gig file by samples located in the directory chosen "
+ "by you above.\n\n"
+ "It works like this: For each sample in the gig file it tries to "
+ "find a sample file in the selected directory with the same name as "
+ "the sample in the gig file. Optionally you can add a filename "
+ "postfix below, which will be added to the filename expected to be "
+ "found. That is, assume you have a gig file with a sample called "
+ "'Snare', if you enter '.wav' below (like it's done by default), it "
+ "assumes to find a sample file called 'Snare.wav' and will replace "
+ "the sample in the gig file accordingly. If you don't need such a "
+ "postfix, blank the field below. Any gig sample where no "
+ "appropriate sample file could be found, will be reported and left "
+ "untouched.\n\n")
+ );
+ description.set_line_wrap(true);
+ Gtk::HBox entryArea;
+ Gtk::Label entryLabel( _("Add Filename Extension: "), Gtk::ALIGN_RIGHT);
+ Gtk::Entry postfixEntryBox;
+ postfixEntryBox.set_text(".wav");
+ entryArea.pack_start(entryLabel);
+ entryArea.pack_start(postfixEntryBox);
+ dialog.get_vbox()->pack_start(description, Gtk::PACK_SHRINK);
+ dialog.get_vbox()->pack_start(entryArea, Gtk::PACK_SHRINK);
+ description.show();
+ entryLabel.show();
+ postfixEntryBox.show();
+ entryArea.show();
+ dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ dialog.add_button(_("Select"), Gtk::RESPONSE_OK);
+ dialog.set_select_multiple(false);
+ // fix label width (because Gtk by design doesn't
+ // know anything about the parent's size)
+#if 0 //FIXME: doesn't work
+ int dialogW, dialogH, labelW, labelH;
+ dialog.get_size_request(dialogW, dialogH);
+ description.get_size_request(labelW, labelH);
+ std::cout << "dialog(" << dialogW << "," << dialogH << ")\nlabel(" << labelW << "," << labelH << ")\n" << std::flush;
+ description.set_size_request(dialogW, labelH);
+#endif
+ if (dialog.run() == Gtk::RESPONSE_OK)
+ {
+ Glib::ustring error_files;
+ Glib::ustring folder = dialog.get_filename();
+ for (gig::Sample* sample = file->GetFirstSample();
+ sample; sample = file->GetNextSample())
+ {
+ std::string filename =
+ folder + G_DIR_SEPARATOR_S + sample->pInfo->Name +
+ postfixEntryBox.get_text().raw();
+ SF_INFO info;
+ info.format = 0;
+ SNDFILE* hFile = sf_open(filename.c_str(), SFM_READ, &info);
+ try
+ {
+ if (!hFile) throw std::string("could not open file");
+ int bitdepth;
+ switch (info.format & 0xff) {
+ case SF_FORMAT_PCM_S8:
+ case SF_FORMAT_PCM_16:
+ case SF_FORMAT_PCM_U8:
+ bitdepth = 16;
+ break;
+ case SF_FORMAT_PCM_24:
+ case SF_FORMAT_PCM_32:
+ case SF_FORMAT_FLOAT:
+ case SF_FORMAT_DOUBLE:
+ bitdepth = 24;
+ break;
+ default:
+ sf_close(hFile);
+ throw std::string("format not supported");
+ }
+ SampleImportItem sched_item;
+ sched_item.gig_sample = sample;
+ sched_item.sample_path = filename;
+ m_SampleImportQueue.push_back(sched_item);
+ sf_close(hFile);
+ file_changed();
+ }
+ catch (std::string what)
+ {
+ if (error_files.size()) error_files += "\n";
+ error_files += filename += " (" + what + ")";
+ }
+ }
+ // show error message box when some file(s) could not be opened / added
+ if (error_files.size()) {
+ Glib::ustring txt =
+ _("Could not replace the following sample(s):\n") + error_files;
+ Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR);
+ msg.run();
+ }
+ }
+}
+
void MainWindow::on_action_remove_sample() {
if (!file) return;
Glib::RefPtr sel = m_TreeViewSamples.get_selection();
@@ -1685,3 +1888,19 @@
sigc::signal& MainWindow::signal_dimreg_changed() {
return dimreg_changed_signal;
}
+
+sigc::signal& MainWindow::signal_note_on() {
+ return note_on_signal;
+}
+
+sigc::signal& MainWindow::signal_note_off() {
+ return note_off_signal;
+}
+
+sigc::signal& MainWindow::signal_keyboard_key_hit() {
+ return m_RegionChooser.signal_keyboard_key_hit();
+}
+
+sigc::signal& MainWindow::signal_keyboard_key_released() {
+ return m_RegionChooser.signal_keyboard_key_released();
+}