From cdc8807728ff57ba3df56aa5a9e00255f9e81b0b Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 22 Feb 2017 10:38:17 +0100 Subject: [PATCH] Prepare re-locating missing external files. --- libs/ardour/ardour/session.h | 6 ++++++ libs/ardour/session_state.cc | 37 +++++++++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index dac899db5c..8ce31630f0 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1145,6 +1145,10 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop */ static PBD::Signal3 MissingFile; + void set_missing_file_replacement (const std::string& mfr) { + _missing_file_replacement = mfr; + } + /** Emitted when the session wants Ardour to quit */ static PBD::Signal0 Quit; @@ -1260,6 +1264,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop bool _under_nsm_control; unsigned int _xrun_count; + std::string _missing_file_replacement; + void mtc_status_changed (bool); PBD::ScopedConnection mtc_status_connection; void ltc_status_changed (bool); diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 5e63e0c357..0c2fa42073 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -2198,19 +2198,23 @@ Session::load_sources (const XMLNode& node) nlist = node.children(); set_dirty(); + std::map relocation; for (niter = nlist.begin(); niter != nlist.end(); ++niter) { #ifdef PLATFORM_WINDOWS int old_mode = 0; #endif + XMLNode srcnode (**niter); + bool try_replace_abspath = true; + retry: try { #ifdef PLATFORM_WINDOWS // do not show "insert media" popups (files embedded from removable media). old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); #endif - if ((source = XMLSourceFactory (**niter)) == 0) { + if ((source = XMLSourceFactory (srcnode)) == 0) { error << _("Session: cannot create Source from XML description.") << endmsg; } #ifdef PLATFORM_WINDOWS @@ -2222,10 +2226,25 @@ retry: SetErrorMode(old_mode); #endif + /* try previous abs path replacements first */ + if (try_replace_abspath && Glib::path_is_absolute (err.path)) { + std::string dir = Glib::path_get_dirname (err.path); + std::map::const_iterator rl = relocation.find (dir); + if (rl != relocation.end ()) { + std::string newpath = Glib::build_filename (rl->second, Glib::path_get_basename (err.path)); + if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) { + srcnode.add_property ("origin", newpath); + try_replace_abspath = false; + goto retry; + } + } + } + int user_choice; + _missing_file_replacement = ""; if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) { - error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"), + error << string_compose (_("An external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"), PROGRAM_NAME) << endmsg; return -1; } @@ -2238,7 +2257,19 @@ retry: switch (user_choice) { case 0: - /* user added a new search location, so try again */ + /* user added a new search location + * or selected a new absolute path, + * so try again */ + if (Glib::path_is_absolute (err.path)) { + if (!_missing_file_replacement.empty ()) { + /* replace origin, in XML */ + std::string newpath = Glib::build_filename ( + _missing_file_replacement, Glib::path_get_basename (err.path)); + srcnode.add_property ("origin", newpath); + relocation[Glib::path_get_dirname (err.path)] = _missing_file_replacement; + _missing_file_replacement = ""; + } + } goto retry;