diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2010-11-09 06:03:51 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2010-11-09 06:03:51 +0000 |
commit | 5c6ba165f684fbd45be33c83d41083567d4dd88f (patch) | |
tree | b3108d53b3a82fb1ea522038fe4500e0c38349bb /libs/ardour | |
parent | d29f14bf33bc807be7b95015e4f011f4ad741cc6 (diff) |
initial pass at a missing file dialog and "relocatable" source files. lots more to do here
git-svn-id: svn://localhost/ardour2/branches/3.0@7983 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/file_source.h | 28 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 15 | ||||
-rw-r--r-- | libs/ardour/ardour/session_configuration_vars.h | 2 | ||||
-rw-r--r-- | libs/ardour/file_source.cc | 116 | ||||
-rw-r--r-- | libs/ardour/session.cc | 57 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 45 | ||||
-rw-r--r-- | libs/ardour/source_factory.cc | 1 |
7 files changed, 234 insertions, 30 deletions
diff --git a/libs/ardour/ardour/file_source.h b/libs/ardour/ardour/file_source.h index aa4fe973b1..78210916f0 100644 --- a/libs/ardour/ardour/file_source.h +++ b/libs/ardour/ardour/file_source.h @@ -20,15 +20,25 @@ #ifndef __ardour_filesource_h__ #define __ardour_filesource_h__ +#include <list> +#include <string> #include <exception> #include <time.h> #include "ardour/source.h" namespace ARDOUR { -class MissingSource : public std::exception { -public: +class MissingSource : public std::exception +{ + public: + MissingSource (const std::string& p, DataType t) throw () + : path (p), type (t) {} + ~MissingSource() throw() {} + virtual const char *what() const throw() { return "source file does not exist"; } + + std::string path; + DataType type; }; /** A source associated with a file on disk somewhere */ @@ -54,15 +64,19 @@ public: int set_source_name (const std::string& newname, bool destructive); - static void set_search_path (DataType type, const std::string& path); + static bool find (Session&, DataType type, const std::string& path, + bool must_exist, bool& is_new, uint16_t& chan, + std::string& found_path); - static bool find (DataType type, const std::string& path, - bool must_exist, bool& is_new, uint16_t& chan, - std::string& found_path); + static bool find_2X (Session&, DataType type, const std::string& path, + bool must_exist, bool& is_new, uint16_t& chan, + std::string& found_path); void inc_use_count (); bool removable () const; + static PBD::Signal3<int,std::string,std::string,std::vector<std::string> > AmbiguousFileName; + protected: FileSource (Session& session, DataType type, const std::string& path, @@ -81,8 +95,6 @@ protected: bool _file_is_new; uint16_t _channel; bool _within_session; - - static std::map<DataType, std::string> search_paths; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 7c7ff820e9..d0fe89ee52 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -785,6 +785,19 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void request_resume_timecode_transmission (); bool timecode_transmission_suspended () const; + std::string source_search_path(DataType) const; + + /* handlers can return an integer value: + 0: config.set_audio_search_path() or config.set_midi_search_path() was used + to modify the search path and we should try to find it again. + 1: quit entire session load + 2: as 0, but don't ask about other missing files + 3: don't ask about other missing files, and just mark this one missing + -1: just mark this one missing + any other value: as -1 + */ + static PBD::Signal3<int,Session*,std::string,DataType> MissingFile; + /** Emitted when the session wants Ardour to quit */ static PBD::Signal0<void> Quit; @@ -1310,6 +1323,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi uint32_t _total_free_4k_blocks; Glib::Mutex space_lock; + bool no_questions_about_missing_files; + std::string get_best_session_directory_for_new_source (); mutable gint _playback_load; diff --git a/libs/ardour/ardour/session_configuration_vars.h b/libs/ardour/ardour/session_configuration_vars.h index 828b2cbfcf..057cff01fe 100644 --- a/libs/ardour/ardour/session_configuration_vars.h +++ b/libs/ardour/ardour/session_configuration_vars.h @@ -35,6 +35,8 @@ CONFIG_VARIABLE (bool, punch_out, "punch-out", false) CONFIG_VARIABLE (uint32_t, subframes_per_frame, "subframes-per-frame", 100) CONFIG_VARIABLE (TimecodeFormat, timecode_format, "timecode-format", timecode_30) CONFIG_VARIABLE_SPECIAL(std::string, raid_path, "raid-path", "", path_expand) +CONFIG_VARIABLE_SPECIAL(std::string, audio_search_path, "audio-search-path", "", path_expand) +CONFIG_VARIABLE_SPECIAL(std::string, midi_search_path, "midi-search-path", "", path_expand) CONFIG_VARIABLE (std::string, bwf_country_code, "bwf-country-code", "US") CONFIG_VARIABLE (std::string, bwf_organization_code, "bwf-organization-code", "US") CONFIG_VARIABLE (LayerModel, layer_model, "layer-model", MoveAddHigher) diff --git a/libs/ardour/file_source.cc b/libs/ardour/file_source.cc index 5e52d7739a..95ab3e9f3d 100644 --- a/libs/ardour/file_source.cc +++ b/libs/ardour/file_source.cc @@ -52,7 +52,7 @@ using namespace ARDOUR; using namespace PBD; using namespace Glib; -map<DataType, string> FileSource::search_paths; +PBD::Signal3<int,std::string,std::string,std::vector<std::string> > FileSource::AmbiguousFileName; FileSource::FileSource (Session& session, DataType type, const string& path, Source::Flag flag) : Source(session, type, path, flag) @@ -84,8 +84,6 @@ FileSource::removable () const && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && empty() == 0))); - cerr << "is " << _path << " removable ? " << r << endl; - return r; } @@ -94,9 +92,15 @@ FileSource::init (const string& pathstr, bool must_exist) { _timeline_position = 0; - if (!find (_type, pathstr, must_exist, _file_is_new, _channel, _path)) { - throw MissingSource (); - } + if (Stateful::loading_state_version < 3000) { + if (!find_2X (_session, _type, pathstr, must_exist, _file_is_new, _channel, _path)) { + throw MissingSource (pathstr, _type); + } + } else { + if (!find (_session, _type, pathstr, must_exist, _file_is_new, _channel, _path)) { + throw MissingSource (pathstr, _type); + } + } set_within_session_from_path (pathstr); @@ -204,10 +208,100 @@ FileSource::move_to_trash (const string& trash_dir_name) * \return true iff the file was found. */ bool -FileSource::find (DataType type, const string& path, bool must_exist, +FileSource::find (Session& s, DataType type, const string& path, bool must_exist, bool& isnew, uint16_t& chan, string& found_path) { - string search_path = search_paths[type]; + string search_path = s.source_search_path (type); + + string pathstr = path; + bool ret = false; + + cerr << "Searching along " << search_path << endl; + + isnew = false; + + vector<string> dirs; + vector<string> hits; + int cnt; + string fullpath; + string keeppath; + + if (search_path.length() == 0) { + error << _("FileSource: search path not set") << endmsg; + goto out; + } + + split (search_path, dirs, ':'); + + cnt = 0; + hits.clear (); + + for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) { + + cerr << "Searching in " << *i << " for " << pathstr << endl; + + fullpath = Glib::build_filename (*i, pathstr); + + if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) { + keeppath = fullpath; + hits.push_back (fullpath); + ++cnt; + } + } + + if (cnt > 1) { + + int which = FileSource::AmbiguousFileName (pathstr, search_path, hits).get_value_or (-1); + + if (which < 0) { + goto out; + } else { + keeppath = hits[which]; + } + + } else if (cnt == 0) { + + if (must_exist) { + error << string_compose( + _("Filesource: cannot find required file (%1): while searching %2"), + pathstr, search_path) << endmsg; + goto out; + } else { + isnew = true; + } + } + + /* Current find() is unable to parse relative path names to yet non-existant + sources. QuickFix(tm) + */ + if (keeppath == "") { + if (must_exist) { + error << "FileSource::find(), keeppath = \"\", but the file must exist" << endl; + } else { + keeppath = pathstr; + } + } + + found_path = keeppath; + + ret = true; + + out: + return ret; +} + +/** Find the actual source file based on \a filename. + * + * If the source is within the session tree, \a filename should be a simple filename (no slashes). + * If the source is external, \a filename should be a full path. + * In either case, found_path is set to the complete absolute path of the source file. + * \return true iff the file was found. + */ +bool +FileSource::find_2X (Session& s, DataType type, const string& path, bool must_exist, + bool& isnew, uint16_t& chan, string& found_path) +{ + string search_path = s.source_search_path (type); string pathstr = path; string::size_type pos; @@ -398,12 +492,6 @@ FileSource::set_source_name (const string& newname, bool destructive) } void -FileSource::set_search_path (DataType type, const string& p) -{ - search_paths[type] = p; -} - -void FileSource::mark_immutable () { /* destructive sources stay writable, and their other flags don't change. */ diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 2392d45ca1..f870fd9b11 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -44,6 +44,7 @@ #include "pbd/stacktrace.h" #include "pbd/file_utils.h" #include "pbd/convert.h" +#include "pbd/strsplit.h" #include "ardour/amp.h" #include "ardour/analyser.h" @@ -117,6 +118,7 @@ PBD::Signal1<void,std::string> Session::Dialog; PBD::Signal0<int> Session::AskAboutPendingState; PBD::Signal2<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch; PBD::Signal0<void> Session::SendFeedback; +PBD::Signal3<int,Session*,std::string,DataType> Session::MissingFile; PBD::Signal0<void> Session::TimecodeOffsetChanged; PBD::Signal1<void, framepos_t> Session::StartTimeChanged; @@ -4060,3 +4062,58 @@ Session::end_time_changed (framepos_t old) l->set_end (s->end(), true); } } + +string +Session::source_search_path (DataType type) const +{ + string search_path; + + if (session_dirs.size() == 1) { + switch (type) { + case DataType::AUDIO: + search_path = _session_dir->sound_path().to_string(); + break; + case DataType::MIDI: + search_path = _session_dir->midi_path().to_string(); + break; + } + } else { + for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) { + SessionDirectory sdir (i->path); + if (!search_path.empty()) { + search_path += ':'; + } + switch (type) { + case DataType::AUDIO: + search_path += sdir.sound_path().to_string(); + break; + case DataType::MIDI: + search_path += sdir.midi_path().to_string(); + break; + } + } + } + + /* now add user-specified locations + */ + + vector<string> dirs; + + switch (type) { + case DataType::AUDIO: + split (config.get_audio_search_path (), dirs, ':'); + break; + case DataType::MIDI: + split (config.get_midi_search_path (), dirs, ':'); + break; + } + + for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) { + search_path += ':'; + search_path += *i; + + } + + return search_path; +} + diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 4ae4065329..e9feed4e1f 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -217,6 +217,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) post_export_sync = false; midi_control_ui = 0; _step_editors = 0; + no_questions_about_missing_files = false; AudioDiskstream::allocate_working_buffers(); @@ -423,10 +424,6 @@ Session::setup_raid_path (string path) midi_search_path += sdir.midi_path (); } - // set the search path for each data type - FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ()); - SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ()); - // reset the round-robin soundfile path thingie last_rr_session_dir = session_dirs.begin(); } @@ -1871,13 +1868,47 @@ Session::load_sources (const XMLNode& node) set_dirty(); for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + retry: try { if ((source = XMLSourceFactory (**niter)) == 0) { error << _("Session: cannot create Source from XML description.") << endmsg; } + } catch (MissingSource& err) { - warning << _("A sound file is missing. It will be replaced by silence.") << endmsg; - source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate); + + int user_choice; + + if (!no_questions_about_missing_files) { + user_choice = MissingFile (this, err.path, err.type).get_value_or (-1); + } else { + user_choice = -2; + } + + switch (user_choice) { + case 0: + /* user added a new search location, so try again */ + goto retry; + + + case 1: + /* user asked to quit the entire session load + */ + return -1; + + case 2: + no_questions_about_missing_files = true; + goto retry; + + case 3: + no_questions_about_missing_files = true; + /* fallthru */ + + case -1: + default: + warning << _("A sound file is missing. It will be replaced by silence.") << endmsg; + source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate); + break; + } } } @@ -2421,7 +2452,7 @@ Session::find_all_sources (string path, set<string>& result) bool is_new; uint16_t chan; - if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) { + if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) { result.insert (found_path); } } diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index d09bf05c6e..ca1dc3b354 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -144,7 +144,6 @@ SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks) if (type == DataType::AUDIO) { try { - Source* src = new SndFileSource (s, node); // boost_debug_shared_ptr_mark_interesting (src, "Source"); boost::shared_ptr<Source> ret (src); |