--- gigedit/trunk/src/gigedit/mainwindow.cpp 2018/12/09 20:48:18 3441 +++ gigedit/trunk/src/gigedit/mainwindow.cpp 2019/02/16 19:56:56 3472 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2017 Andreas Persson + * Copyright (C) 2006-2019 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 @@ -21,12 +21,6 @@ #include #include "compat.h" -// threads.h must be included first to be able to build with -// G_DISABLE_DEPRECATED -#if (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION == 31 && GLIBMM_MICRO_VERSION >= 2) || \ - (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION > 31) || GLIBMM_MAJOR_VERSION > 2 -#include -#endif #include #include @@ -1516,7 +1510,11 @@ sigc::hide( sigc::bind( file_structure_to_be_changed_signal.make_slot(), +#if SIGCXX_MAJOR_VERSION > 2 || (SIGCXX_MAJOR_VERSION == 2 && SIGCXX_MINOR_VERSION >= 8) + std::ref(this->file) +#else sigc::ref(this->file) +#endif ) ) ); @@ -1524,7 +1522,11 @@ sigc::hide( sigc::bind( file_structure_changed_signal.make_slot(), +#if SIGCXX_MAJOR_VERSION > 2 || (SIGCXX_MAJOR_VERSION == 2 && SIGCXX_MINOR_VERSION >= 8) + std::ref(this->file) +#else sigc::ref(this->file) +#endif ) ) ); @@ -1546,7 +1548,7 @@ sigc::mem_fun(*this, &MainWindow::update_dimregs)); m_searchText.signal_changed().connect( - sigc::mem_fun(m_refTreeModelFilter.operator->(), &Gtk::TreeModelFilter::refilter) + sigc::mem_fun(*m_refTreeModelFilter.operator->(), &Gtk::TreeModelFilter::refilter) ); file = 0; @@ -1884,16 +1886,30 @@ } } + +LoaderSaverBase::LoaderSaverBase(const Glib::ustring filename, gig::File* gig) : + filename(filename), gig(gig), +#ifdef GLIB_THREADS + thread(0), +#endif + progress(0.f) +{ +} + void loader_progress_callback(gig::progress_t* progress) { - Loader* loader = static_cast(progress->custom); + LoaderSaverBase* loader = static_cast(progress->custom); loader->progress_callback(progress->factor); } -void Loader::progress_callback(float fraction) +void LoaderSaverBase::progress_callback(float fraction) { { +#ifdef GLIB_THREADS Glib::Threads::Mutex::Lock lock(progressMutex); +#else + std::lock_guard lock(progressMutex); +#endif progress = fraction; } progress_dispatcher(); @@ -1903,19 +1919,21 @@ // make sure stack is 16-byte aligned for SSE instructions __attribute__((force_align_arg_pointer)) #endif -void Loader::thread_function() +void LoaderSaverBase::thread_function() { +#ifdef GLIB_THREADS printf("thread_function self=%p\n", static_cast(Glib::Threads::Thread::self())); +#else + std::cout << "thread_function self=" << std::this_thread::get_id() << "\n"; +#endif printf("Start %s\n", filename.c_str()); try { - RIFF::File* riff = new RIFF::File(filename); - gig = new gig::File(riff); gig::progress_t progress; progress.callback = loader_progress_callback; progress.custom = this; - gig->GetInstrument(0, &progress); + thread_function_sub(progress); printf("End\n"); finished_dispatcher(); } catch (RIFF::Exception e) { @@ -1927,159 +1945,111 @@ } } -Loader::Loader(const char* filename) - : filename(filename), gig(0), thread(0), progress(0.f) -{ -} - -void Loader::launch() +void LoaderSaverBase::launch() { +#ifdef GLIB_THREADS #ifdef OLD_THREADS - thread = Glib::Thread::create(sigc::mem_fun(*this, &Loader::thread_function), true); + thread = Glib::Thread::create(sigc::mem_fun(*this, &LoaderSaverBase::thread_function), true); #else - thread = Glib::Threads::Thread::create(sigc::mem_fun(*this, &Loader::thread_function)); + thread = Glib::Threads::Thread::create(sigc::mem_fun(*this, &LoaderSaverBase::thread_function)); #endif printf("launch thread=%p\n", static_cast(thread)); +#else + thread = std::thread([this](){ thread_function(); }); + std::cout << "launch thread=" << thread.get_id() << "\n"; +#endif } -float Loader::get_progress() +float LoaderSaverBase::get_progress() { - float res; - { - Glib::Threads::Mutex::Lock lock(progressMutex); - res = progress; - } - return res; +#ifdef GLIB_THREADS + Glib::Threads::Mutex::Lock lock(progressMutex); +#else + std::lock_guard lock(progressMutex); +#endif + return progress; } -Glib::Dispatcher& Loader::signal_progress() +Glib::Dispatcher& LoaderSaverBase::signal_progress() { return progress_dispatcher; } -Glib::Dispatcher& Loader::signal_finished() +Glib::Dispatcher& LoaderSaverBase::signal_finished() { return finished_dispatcher; } -Glib::Dispatcher& Loader::signal_error() +Glib::Dispatcher& LoaderSaverBase::signal_error() { return error_dispatcher; } -void saver_progress_callback(gig::progress_t* progress) -{ - Saver* saver = static_cast(progress->custom); - saver->progress_callback(progress->factor); +void LoaderSaverBase::join() { +#ifdef GLIB_THREADS + thread->join(); +#else + thread.join(); +#endif } -void Saver::progress_callback(float fraction) + +Loader::Loader(const char* filename) : + LoaderSaverBase(filename, 0) { - { - Glib::Threads::Mutex::Lock lock(progressMutex); - progress = fraction; - } - progress_dispatcher.emit(); } -#if defined(WIN32) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) -// make sure stack is 16-byte aligned for SSE instructions -__attribute__((force_align_arg_pointer)) -#endif -void Saver::thread_function() +void Loader::thread_function_sub(gig::progress_t& progress) { - printf("thread_function self=%p\n", - static_cast(Glib::Threads::Thread::self())); - printf("Start %s\n", filename.c_str()); - try { - gig::progress_t progress; - progress.callback = saver_progress_callback; - progress.custom = this; + RIFF::File* riff = new RIFF::File(filename); + gig = new gig::File(riff); - // if no filename was provided, that means "save", if filename was provided means "save as" - if (filename.empty()) { - if (!Settings::singleton()->saveWithTemporaryFile) { - // save directly over the existing .gig file - // (requires less disk space than solution below - // but may be slower) - gig->Save(&progress); - } else { - // save the file as separate temporary file first, - // then move the saved file over the old file - // (may result in performance speedup during save) - gig::String tmpname = filename + ".TMP"; - gig->Save(tmpname, &progress); - #if defined(WIN32) - if (!DeleteFile(filename.c_str())) { - throw RIFF::Exception("Could not replace original file with temporary file (unable to remove original file)."); - } - #else // POSIX ... - if (unlink(filename.c_str())) { - throw RIFF::Exception("Could not replace original file with temporary file (unable to remove original file): " + gig::String(strerror(errno))); - } - #endif - if (rename(tmpname.c_str(), filename.c_str())) { - #if defined(WIN32) - throw RIFF::Exception("Could not replace original file with temporary file (unable to rename temp file)."); - #else - throw RIFF::Exception("Could not replace original file with temporary file (unable to rename temp file): " + gig::String(strerror(errno))); - #endif - } - } - } else { - gig->Save(filename, &progress); - } - - printf("End\n"); - finished_dispatcher.emit(); - } catch (RIFF::Exception e) { - error_message = e.Message; - error_dispatcher.emit(); - } catch (...) { - error_message = _("Unknown exception occurred"); - error_dispatcher.emit(); - } + gig->GetInstrument(0, &progress); } -Saver::Saver(gig::File* file, Glib::ustring filename) - : gig(file), filename(filename), thread(0), progress(0.f) + +Saver::Saver(gig::File* file, Glib::ustring filename) : + LoaderSaverBase(filename, file) { } -void Saver::launch() +void Saver::thread_function_sub(gig::progress_t& progress) { -#ifdef OLD_THREADS - thread = Glib::Thread::create(sigc::mem_fun(*this, &Saver::thread_function), true); + // if no filename was provided, that means "save", if filename was provided means "save as" + if (filename.empty()) { + if (!Settings::singleton()->saveWithTemporaryFile) { + // save directly over the existing .gig file + // (requires less disk space than solution below + // but may be slower) + gig->Save(&progress); + } else { + // save the file as separate temporary file first, + // then move the saved file over the old file + // (may result in performance speedup during save) + gig::String tmpname = filename + ".TMP"; + gig->Save(tmpname, &progress); +#if defined(WIN32) + if (!DeleteFile(filename.c_str())) { + throw RIFF::Exception("Could not replace original file with temporary file (unable to remove original file)."); + } +#else // POSIX ... + if (unlink(filename.c_str())) { + throw RIFF::Exception("Could not replace original file with temporary file (unable to remove original file): " + gig::String(strerror(errno))); + } +#endif + if (rename(tmpname.c_str(), filename.c_str())) { +#if defined(WIN32) + throw RIFF::Exception("Could not replace original file with temporary file (unable to rename temp file)."); #else - thread = Glib::Threads::Thread::create(sigc::mem_fun(*this, &Saver::thread_function)); + throw RIFF::Exception("Could not replace original file with temporary file (unable to rename temp file): " + gig::String(strerror(errno))); #endif - printf("launch thread=%p\n", static_cast(thread)); -} - -float Saver::get_progress() -{ - float res; - { - Glib::Threads::Mutex::Lock lock(progressMutex); - res = progress; + } + } + } else { + gig->Save(filename, &progress); } - return res; } -Glib::Dispatcher& Saver::signal_progress() -{ - return progress_dispatcher; -} - -Glib::Dispatcher& Saver::signal_finished() -{ - return finished_dispatcher; -} - -Glib::Dispatcher& Saver::signal_error() -{ - return error_dispatcher; -} ProgressDialog::ProgressDialog(const Glib::ustring& title, Gtk::Window& parent) : Gtk::Dialog(title, parent, true) @@ -2237,8 +2207,13 @@ if (dialog.run() == Gtk::RESPONSE_OK) { std::string filename = dialog.get_filename(); printf("filename=%s\n", filename.c_str()); +#ifdef GLIB_THREADS printf("on_action_file_open self=%p\n", static_cast(Glib::Threads::Thread::self())); +#else + std::cout << "on_action_file_open self=" << + std::this_thread::get_id() << "\n"; +#endif load_file(filename.c_str()); current_gig_dir = Glib::path_get_dirname(filename); } @@ -2311,15 +2286,22 @@ void MainWindow::on_loader_finished() { + loader->join(); printf("Loader finished!\n"); +#ifdef GLIB_THREADS printf("on_loader_finished self=%p\n", static_cast(Glib::Threads::Thread::self())); +#else + std::cout << "on_loader_finished self=" << + std::this_thread::get_id() << "\n"; +#endif load_gig(loader->gig, loader->filename.c_str()); progress_dialog->hide(); } void MainWindow::on_loader_error() { + loader->join(); Glib::ustring txt = _("Could not load file: ") + loader->error_message; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); msg.run(); @@ -2390,6 +2372,7 @@ void MainWindow::on_saver_error() { + saver->join(); file_structure_changed_signal.emit(this->file); Glib::ustring txt = _("Could not save file: ") + saver->error_message; Gtk::MessageDialog msg(*this, txt, false, Gtk::MESSAGE_ERROR); @@ -2398,6 +2381,7 @@ void MainWindow::on_saver_finished() { + saver->join(); this->file = saver->gig; this->filename = saver->filename; current_gig_dir = Glib::path_get_dirname(filename); @@ -2669,7 +2653,7 @@ dialog.set_name("Gigedit"); #endif dialog.set_version(VERSION); - dialog.set_copyright("Copyright (C) 2006-2017 Andreas Persson"); + dialog.set_copyright("Copyright (C) 2006-2019 Andreas Persson"); const std::string sComment = _("Built " __DATE__ "\nUsing ") + ::gig::libraryName() + " " + ::gig::libraryVersion() + "\n\n" + @@ -2723,6 +2707,7 @@ set_title(_("File Properties")); eName.set_width_chars(50); + connect(eFileFormat, &PropDialog::set_FileFormat); connect(eName, &DLS::Info::Name); connect(eCreationDate, &DLS::Info::CreationDate); connect(eComments, &DLS::Info::Comments); @@ -2765,7 +2750,7 @@ #endif add(vbox); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) table.set_margin(5); #else table.set_border_width(5); @@ -2773,7 +2758,7 @@ vbox.add(table); vbox.pack_start(buttonBox, Gtk::PACK_SHRINK); buttonBox.set_layout(Gtk::BUTTONBOX_END); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) buttonBox.set_margin(5); #else buttonBox.set_border_width(5); @@ -2784,8 +2769,6 @@ quitButton.grab_focus(); quitButton.signal_clicked().connect( sigc::mem_fun(*this, &PropDialog::hide)); - eFileFormat.signal_value_changed().connect( - sigc::mem_fun(*this, &PropDialog::onFileFormatChanged)); quitButton.show(); vbox.show(); @@ -2797,6 +2780,7 @@ void PropDialog::set_file(gig::File* file) { m_file = file; + update(file->pInfo); // update file format version combo box const std::string sGiga = "Gigasampler/GigaStudio v"; @@ -2812,18 +2796,16 @@ std::vector texts; for (int i = 0; i < txts.size(); ++i) texts.push_back(txts[i].c_str()); texts.push_back(NULL); values.push_back(0); + + update_model++; eFileFormat.set_choices(&texts[0], &values[0]); eFileFormat.set_value(major); + update_model--; } -void PropDialog::onFileFormatChanged() { - const int major = eFileFormat.get_value(); - if (m_file) m_file->pVersion->major = major; -} - -void PropDialog::set_info(DLS::Info* info) +void PropDialog::set_FileFormat(int value) { - update(info); + m_file->pVersion->major = value; } @@ -2925,7 +2907,7 @@ table.add(eDimensionKeyRangeHigh); add(vbox); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) table.set_margin(5); #else table.set_border_width(5); @@ -2934,7 +2916,7 @@ table.show(); vbox.pack_start(buttonBox, Gtk::PACK_SHRINK); buttonBox.set_layout(Gtk::BUTTONBOX_END); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) buttonBox.set_margin(5); #else buttonBox.set_border_width(5); @@ -2998,7 +2980,9 @@ bool MainWindow::onQueryTreeViewTooltip(int x, int y, bool keyboardTip, const Glib::RefPtr& tooltip) { Gtk::TreeModel::iterator iter; - m_TreeView.get_tooltip_context_iter(x, y, keyboardTip, iter); + if (!m_TreeView.get_tooltip_context_iter(x, y, keyboardTip, iter)) { + return false; + } Gtk::TreeModel::Path path(iter); Gtk::TreeModel::Row row = *iter; Gtk::TreeViewColumn* pointedColumn = NULL; @@ -3030,12 +3014,12 @@ static Glib::ustring scriptTooltipFor(gig::Instrument* instrument, int index) { Glib::ustring name(gig_to_utf8(instrument->pInfo->Name)); const int iScriptSlots = instrument->ScriptSlotCount(); - Glib::ustring tooltip = "(" + ToString(index) + ") „" + name + "”\n\n"; + Glib::ustring tooltip = "(" + ToString(index) + ") “" + name + "”\n\n"; if (!iScriptSlots) tooltip += "No script assigned"; else { for (int i = 0; i < iScriptSlots; ++i) { - tooltip += "• " + ToString(i+1) + ". Script: „" + + tooltip += "• " + ToString(i+1) + ". Script: “" + instrument->GetScriptOfSlot(i)->Name + "”"; if (i + 1 < iScriptSlots) tooltip += "\n\n"; } @@ -3057,7 +3041,6 @@ file_is_changed = false; propDialog.set_file(gig); - propDialog.set_info(gig->pInfo); instrument_name_connection.block(); int index = 0; @@ -3453,7 +3436,7 @@ show_intruments_tab(); m_TreeView.get_selection()->unselect_all(); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) auto iterSel = model->children()[i].get_iter(); m_TreeView.get_selection()->select(iterSel); #else @@ -3483,7 +3466,7 @@ // select and show the respective instrument in the list view show_intruments_tab(); m_TreeView.get_selection()->unselect_all(); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) auto iterSel = model->children()[i].get_iter(); m_TreeView.get_selection()->select(iterSel); #else @@ -3519,7 +3502,7 @@ if (rowSample[m_SamplesModel.m_col_sample] == sample) { show_samples_tab(); m_TreeViewSamples.get_selection()->unselect_all(); -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) auto iterSel = rowGroup.children()[s].get_iter(); m_TreeViewSamples.get_selection()->select(iterSel); #else @@ -4794,7 +4777,7 @@ trim(pattern); if (pattern.empty()) return true; -#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) +#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) //HACK: on GTKMM4 development branch const_iterator cannot be easily converted to iterator, probably going to be fixed before final GTKMM4 release though. Gtk::TreeModel::Row row = **(Gtk::TreeModel::iterator*)(&iter); #else @@ -5034,8 +5017,13 @@ #endif if (dialog.run() == Gtk::RESPONSE_OK) { +#ifdef GLIB_THREADS printf("on_action_merge_files self=%p\n", static_cast(Glib::Threads::Thread::self())); +#else + std::cout << "on_action_merge_files self=" << + std::this_thread::get_id() << "\n"; +#endif std::vector filenames = dialog.get_filenames(); // merge the selected files to the currently open .gig file