summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2010-11-09 06:03:51 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2010-11-09 06:03:51 +0000
commit5c6ba165f684fbd45be33c83d41083567d4dd88f (patch)
treeb3108d53b3a82fb1ea522038fe4500e0c38349bb /libs/ardour
parentd29f14bf33bc807be7b95015e4f011f4ad741cc6 (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.h28
-rw-r--r--libs/ardour/ardour/session.h15
-rw-r--r--libs/ardour/ardour/session_configuration_vars.h2
-rw-r--r--libs/ardour/file_source.cc116
-rw-r--r--libs/ardour/session.cc57
-rw-r--r--libs/ardour/session_state.cc45
-rw-r--r--libs/ardour/source_factory.cc1
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);