From aeccb137fda8845ead04419a15f2821de6ab4560 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 13 Sep 2022 13:53:39 -0600 Subject: [PATCH] threaded archive inflation for library mgmt --- gtk2_ardour/library_download_dialog.cc | 89 ++++++++++++++++++++++---- gtk2_ardour/library_download_dialog.h | 24 +++++-- libs/pbd/file_archive.cc | 4 -- 3 files changed, 97 insertions(+), 20 deletions(-) diff --git a/gtk2_ardour/library_download_dialog.cc b/gtk2_ardour/library_download_dialog.cc index eab855a519..5bfcbf7fbc 100644 --- a/gtk2_ardour/library_download_dialog.cc +++ b/gtk2_ardour/library_download_dialog.cc @@ -21,6 +21,8 @@ #include +#include "pbd/downloader.h" +#include "pbd/inflater.h" #include "pbd/i18n.h" #include @@ -28,13 +30,16 @@ #include "ardour/rc_configuration.h" #include "ardour/library.h" +#include "gui_thread.h" #include "library_download_dialog.h" +using namespace PBD; using namespace ARDOUR; using std::string; LibraryDownloadDialog::LibraryDownloadDialog () : ArdourDialog (_("Loop Library Manager"), true) /* modal */ + , inflater(0) { _model = Gtk::ListStore::create (_columns); _display.set_model (_model); @@ -44,7 +49,8 @@ LibraryDownloadDialog::LibraryDownloadDialog () _display.append_column (_("License"), _columns.license); _display.append_column (_("Size"), _columns.size); _display.append_column (_("Installed"), _columns.installed); - _display.append_column_editable ("", _columns.install); + + append_install_column (); append_progress_column (); _display.set_headers_visible (true); @@ -66,6 +72,11 @@ LibraryDownloadDialog::LibraryDownloadDialog () lf.foreach_description (boost::bind (&LibraryDownloadDialog::add_library, this, _1)); } +LibraryDownloadDialog::~LibraryDownloadDialog () +{ + delete inflater; +} + void LibraryDownloadDialog::append_progress_column () { @@ -76,6 +87,16 @@ LibraryDownloadDialog::append_progress_column () _display.append_column (*tvc); } +void +LibraryDownloadDialog::append_install_column () +{ + install_renderer = new Gtk::CellRendererText(); + Gtk::TreeViewColumn* tvc = manage (new Gtk::TreeViewColumn ("", *install_renderer)); + tvc->set_data (X_("index"), (void*) (intptr_t (_columns.install.index()))); + tvc->add_attribute (*install_renderer, "text", _columns.install); + _display.append_column (*tvc); +} + void LibraryDownloadDialog::add_library (ARDOUR::LibraryDescription const & ld) @@ -87,10 +108,8 @@ LibraryDownloadDialog::add_library (ARDOUR::LibraryDescription const & ld) (*i)[_columns.license] = ld.license(); (*i)[_columns.size] = ld.size(); (*i)[_columns.installed] = ld.installed(); - if (ld.installed()) { - std::cerr << ld.name() << " should be installed\n"; - } (*i)[_columns.url] = ld.url(); + (*i)[_columns.toplevel] = ld.toplevel_dir(); if (ld.installed()) { (*i)[_columns.install] = string(); @@ -98,8 +117,7 @@ LibraryDownloadDialog::add_library (ARDOUR::LibraryDescription const & ld) (*i)[_columns.install] = string (_("Install")); } - /* tooltip must be escape for pango markup, and we should strip all - * duplicate spaces + /* tooltip must be escape for pango markup */ (*i)[_columns.description] = Glib::Markup::escape_text (ld.description()); @@ -108,20 +126,60 @@ LibraryDownloadDialog::add_library (ARDOUR::LibraryDescription const & ld) void LibraryDownloadDialog::install (std::string const & path, Gtk::TreePath const & treepath) { - Gtk::TreeModel::iterator row = _model->get_iter (treepath); - LibraryFetcher lf; + std::string destdir = Glib::path_get_dirname (path); + + inflater = new Inflater (path, destdir); + inflater->progress.connect (install_connection, invalidator(*this), boost::bind (&LibraryDownloadDialog::install_progress, this, _1, _2, path, treepath), gui_context()); + inflater->start (); /* starts unpacking in a thread */ +} + +void +LibraryDownloadDialog::install_progress (size_t nread, size_t total, std::string path, Gtk::TreePath treepath) +{ + Gtk::TreeModel::iterator row = _model->get_iter (treepath); + + if (!inflater) { + return; + } + + if (inflater->status() >= 0) { + LibraryDownloadDialog::install_finished (row, path, inflater->status()); + return; + } + + (*row)[_columns.progress] = (int) round ((double) nread / total); +} + +void +LibraryDownloadDialog::install_finished (Gtk::TreeModel::iterator row, std::string path, int status) +{ + if (status == 0) { + + std::string toplevel = (*row)[_columns.toplevel]; + toplevel = Glib::build_filename (Glib::path_get_dirname (path), toplevel); + + LibraryFetcher lf; + + lf.add (toplevel); - if (lf.add (path) == 0) { (*row)[_columns.installed] = true; - (*row)[_columns.install] = string();; + (*row)[_columns.install] = string(); + (*row)[_columns.progress] = 100; } else { (*row)[_columns.installed] = false; (*row)[_columns.install] = _("Install"); + (*row)[_columns.progress] = 0; } /* Always unlink (remove) the downloaded archive */ - // ::g_unlink (path.c_str()); + ::g_unlink (path.c_str()); + + /* reap thread */ + + install_connection.disconnect (); + delete inflater; + inflater = 0; } @@ -131,7 +189,7 @@ LibraryDownloadDialog::download (Gtk::TreePath const & path) Gtk::TreeModel::iterator row = _model->get_iter (path); std::string url = (*row)[_columns.url]; - ARDOUR::Downloader* downloader = new ARDOUR::Downloader (url, ARDOUR::Config->get_clip_library_dir()); + PBD::Downloader* downloader = new PBD::Downloader (url, ARDOUR::Config->get_clip_library_dir()); /* setup timer callback to update progressbar */ @@ -188,6 +246,13 @@ LibraryDownloadDialog::display_button_press (GdkEventButton* ev) return false; } + int col = (intptr_t) column->get_data (X_("index")); + + if (col != _columns.install.index()) { + std::cerr << "not install\n"; + return false; + } + Gtk::TreeIter iter = _model->get_iter (path); string cur = (*iter)[_columns.install]; diff --git a/gtk2_ardour/library_download_dialog.h b/gtk2_ardour/library_download_dialog.h index 725b2e4ee5..926c53dc3c 100644 --- a/gtk2_ardour/library_download_dialog.h +++ b/gtk2_ardour/library_download_dialog.h @@ -22,21 +22,28 @@ #include #include +#include #include #include #include #include "ardour_dialog.h" +namespace PBD { + class Inflater; + class Downloader; +} + namespace ARDOUR { class LibraryDescription; - class Downloader; + class LibraryFetcher; } class LibraryDownloadDialog : public ArdourDialog { public: LibraryDownloadDialog (); + ~LibraryDownloadDialog (); void add_library (ARDOUR::LibraryDescription const &); @@ -51,6 +58,7 @@ class LibraryDownloadDialog : public ArdourDialog add (installed); add (description); add (url); + add (toplevel); add (install); add (progress); add (downloader); @@ -64,7 +72,8 @@ class LibraryDownloadDialog : public ArdourDialog Gtk::TreeModelColumn installed; /* these are not displayed */ Gtk::TreeModelColumn url; - Gtk::TreeModelColumn downloader; + Gtk::TreeModelColumn toplevel; + Gtk::TreeModelColumn downloader; Gtk::TreeModelColumn progress; /* used as tooltip */ Gtk::TreeModelColumn description; @@ -87,14 +96,21 @@ class LibraryDownloadDialog : public ArdourDialog } Gtk::CellRendererProgress* progress_renderer; + Gtk::CellRendererText* install_renderer; void append_progress_column (); + void append_install_column (); void download (Gtk::TreePath const &); - void install (std::string const & path, Gtk::TreePath const & treepath); - bool dl_timer_callback (ARDOUR::Downloader*, Gtk::TreePath); + bool dl_timer_callback (PBD::Downloader*, Gtk::TreePath); bool display_button_press (GdkEventButton* ev); + + PBD::Inflater* inflater; + void install (std::string const & path, Gtk::TreePath const & treepath); + void install_progress (size_t, size_t, std::string, Gtk::TreePath); + void install_finished (Gtk::TreeModel::iterator row, std::string path, int status); + PBD::ScopedConnection install_connection; }; diff --git a/libs/pbd/file_archive.cc b/libs/pbd/file_archive.cc index bf01bf0214..07149a1d87 100644 --- a/libs/pbd/file_archive.cc +++ b/libs/pbd/file_archive.cc @@ -467,10 +467,6 @@ FileArchive::do_extract (struct archive* a) } } } - if (_req.mp.progress && rv == 0) { - // file i/o -- not URL - progress (_req.mp.length, _req.mp.length); - } archive_read_close (a); archive_read_free (a);