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
This commit is contained in:
Paul Davis 2010-11-09 06:03:51 +00:00
parent d29f14bf33
commit 5c6ba165f6
16 changed files with 701 additions and 38 deletions

View File

@ -102,6 +102,7 @@ typedef uint64_t microseconds_t;
#include "window_proxy.h"
#include "global_port_matrix.h"
#include "location_ui.h"
#include "missing_file_dialog.h"
#include "i18n.h"
@ -264,6 +265,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::finish, this), gui_context ());
/* handle requests to deal with missing files */
ARDOUR::Session::MissingFile.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::missing_file, this, _1, _2, _3));
/* lets get this party started */
try {
@ -3689,3 +3694,26 @@ ARDOUR_UI::remove_window_proxy (WindowProxyBase* p)
{
_window_proxies.remove (p);
}
int
ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
{
MissingFileDialog dialog (s, str, type);
dialog.show ();
dialog.present ();
int result = dialog.run ();
dialog.hide ();
switch (result) {
case RESPONSE_OK:
break;
default:
return 1; // quit entire session load
}
result = dialog.get_action ();
return result;
}

View File

@ -716,6 +716,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void queue_finish ();
std::list<WindowProxyBase*> _window_proxies;
int missing_file (ARDOUR::Session*s, std::string str, ARDOUR::DataType type);
};
#endif /* __ardour_gui_h__ */

View File

@ -0,0 +1,166 @@
/*
Copyright (C) 2010 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "pbd/compose.h"
#include "pbd/replace_all.h"
#include "pbd/strsplit.h"
#include "ardour/session.h"
#include "missing_file_dialog.h"
using namespace Gtk;
using namespace std;
using namespace ARDOUR;
using namespace PBD;
MissingFileDialog::MissingFileDialog (Session* s, const std::string& path, DataType type)
: ArdourDialog (_("Missing File!"), true, false)
, filetype (type)
, chooser (FILE_CHOOSER_ACTION_SELECT_FOLDER)
, use_chosen (_("Add chosen folder to search path, and try again"))
, choice_group (use_chosen.get_group())
, use_chosen_and_no_more_questions (choice_group, _("Add chosen folder to search path, try again but don't ask me again"), false)
, stop_loading_button (choice_group, _("Stop loading this session"), false)
, all_missing_ok (choice_group, _("This and all other missing files are OK"), false)
, this_missing_ok (choice_group, _("This missing file is OK"), false)
{
set_session (s);
add_button (_("Done"), RESPONSE_OK);
string typestr;
switch (type) {
case DataType::AUDIO:
typestr = _("An audio");
break;
case DataType::MIDI:
typestr = _("A MIDI");
break;
}
string dirstr;
dirstr = s->source_search_path (type);
replace_all (dirstr, ":", "\n");
msg.set_markup (string_compose (_("%1 file (\"%2\") cannot be found.\n\n\
Currently, Ardour has searched in the following folders for this file:\n\n\
<tt>%3</tt>\n\n\
The following options are available:"), typestr, path, dirstr));
VBox* button_packer_box = manage (new VBox);
button_packer_box->set_spacing (6);
button_packer_box->set_border_width (12);
button_packer_box->pack_start (use_chosen, false, false);
button_packer_box->pack_start (use_chosen_and_no_more_questions, false, false);
button_packer_box->pack_start (this_missing_ok, false, false);
button_packer_box->pack_start (all_missing_ok, false, false);
button_packer_box->pack_start (stop_loading_button, false, false);
button_packer_box->show_all ();
get_vbox()->set_spacing (6);
get_vbox()->set_border_width (12);
get_vbox()->set_homogeneous (false);
get_vbox()->pack_start (msg, false, false);
HBox* hbox = manage (new HBox);
hbox->pack_start (*button_packer_box, false, true);
hbox->show ();
get_vbox()->pack_start (*hbox, false, false);
get_vbox()->pack_start (chooser, true, true);
msg.show ();
chooser.set_size_request (-1, 300);
chooser.show ();
chooser.set_current_folder (Glib::get_home_dir());
chooser.set_create_folders (false);
}
void
MissingFileDialog::add_chosen ()
{
string str;
string newdir;
vector<string> dirs;
switch (filetype) {
case DataType::AUDIO:
str = _session->config.get_audio_search_path();
break;
case DataType::MIDI:
str = _session->config.get_midi_search_path();
break;
}
split (str, dirs, ':');
newdir = chooser.get_filename ();
for (vector<string>::iterator d = dirs.begin(); d != dirs.end(); d++) {
if (*d == newdir) {
return;
}
}
if (!str.empty()) {
str += ':';
}
str += newdir;
switch (filetype) {
case DataType::AUDIO:
_session->config.set_audio_search_path (str);
break;
case DataType::MIDI:
_session->config.set_midi_search_path (str);
break;
}
}
int
MissingFileDialog::get_action ()
{
if (use_chosen.get_active ()) {
add_chosen ();
return 0;
}
if (use_chosen_and_no_more_questions.get_active()) {
add_chosen ();
return 2;
}
if (this_missing_ok.get_active()) {
return -1;
}
if (all_missing_ok.get_active ()) {
return 3;
}
return 1;
}

View File

@ -0,0 +1,39 @@
#ifndef __gtk_ardour_missing_file_dialog_h__
#define __gtk_ardour_missing_file_dialog_h__
#include <string>
#include <gtkmm/label.h>
#include <gtkmm/filechooserwidget.h>
#include <gtkmm/radiobutton.h>
#include "ardour/types.h"
#include "ardour_dialog.h"
namespace ARDOUR {
class Session;
}
class MissingFileDialog : public ArdourDialog
{
public:
MissingFileDialog (ARDOUR::Session*, const std::string& path, ARDOUR::DataType type);
int get_action();
private:
ARDOUR::DataType filetype;
Gtk::FileChooserWidget chooser;
Gtk::RadioButton use_chosen;
Gtk::RadioButton::Group choice_group;
Gtk::RadioButton use_chosen_and_no_more_questions;
Gtk::RadioButton stop_loading_button;
Gtk::RadioButton all_missing_ok;
Gtk::RadioButton this_missing_ok;
Gtk::Label msg;
void add_chosen ();
};
#endif /* __gtk_ardour_missing_file_dialog_h__ */

View File

@ -136,7 +136,7 @@ public:
return _id;
}
private:
protected:
std::string _id;
std::string _name;

View File

@ -0,0 +1,156 @@
/*
Copyright (C) 2010 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "pbd/strsplit.h"
#include "search_path_option.h"
using namespace std;
using namespace Gtk;
SearchPathOption::SearchPathOption (const string& pathname, const string& label,
sigc::slot<std::string> get, sigc::slot<bool, std::string> set)
: Option (pathname, label)
, _get (get)
, _set (set)
, add_chooser (_("Select folder to search for media"), FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
add_chooser.signal_file_set().connect (sigc::mem_fun (*this, &SearchPathOption::path_chosen));
HBox* hbox = manage (new HBox);
hbox->set_border_width (12);
hbox->set_spacing (6);
hbox->pack_end (add_chooser, false, false);
hbox->pack_end (*manage (new Label ("Click to add a new location")), false, false);
hbox->show_all ();
vbox.pack_start (path_box);
vbox.pack_end (*hbox);
session_label.set_use_markup (true);
session_label.set_markup (string_compose ("<i>%1</i>", _("the session folder")));
session_label.set_alignment (0.0, 0.5);
session_label.show ();
}
SearchPathOption::~SearchPathOption()
{
}
void
SearchPathOption::path_chosen ()
{
string path = add_chooser.get_filename ();
add_path (path);
}
void
SearchPathOption::add_to_page (OptionEditorPage* p)
{
int const n = p->table.property_n_rows();
p->table.resize (n + 2, 3);
Label* label = manage (new Label);
label->set_alignment (0.0, 0.5);
label->set_markup (string_compose ("<b>%1</b>", _name));
p->table.attach (*label, 0, 1, n, n + 1, FILL | EXPAND);
p->table.attach (vbox, 0, 3, n + 1, n + 2, FILL | EXPAND);
}
void
SearchPathOption::clear ()
{
path_box.remove (session_label);
for (list<PathEntry*>::iterator p = paths.begin(); p != paths.end(); ++p) {
path_box.remove ((*p)->box);
delete *p;
}
paths.clear ();
}
void
SearchPathOption::set_state_from_config ()
{
string str = _get ();
vector<string> dirs;
clear ();
path_box.pack_start (session_label);
split (str, dirs, ':');
for (vector<string>::iterator d = dirs.begin(); d != dirs.end(); ++d) {
add_path (*d);
}
}
void
SearchPathOption::changed ()
{
string str;
for (list<PathEntry*>::iterator p = paths.begin(); p != paths.end(); ++p) {
if (p == paths.begin()) {
/* skip first entry, its always "the session"
*/
continue;
}
if (!str.empty()) {
str += ':';
}
str += (*p)->entry.get_text ();
}
_set (str);
}
void
SearchPathOption::add_path (const string& path, bool removable)
{
PathEntry* pe = new PathEntry (path, removable);
paths.push_back (pe);
path_box.pack_start (pe->box, false, false);
}
void
SearchPathOption::remove_path (const string& path)
{
}
SearchPathOption::PathEntry::PathEntry (const std::string& path, bool removable)
: remove_button (Stock::REMOVE)
{
entry.set_text (path);
entry.show ();
box.set_spacing (6);
box.set_homogeneous (false);
box.pack_start (entry, true, true);
if (removable) {
box.pack_start (remove_button, false, false);
remove_button.show ();
}
box.show ();
}

View File

@ -0,0 +1,50 @@
#ifndef __gtk_ardour_search_path_option_h__
#define __gtk_ardour_search_path_option_h__
#include <string>
#include <gtkmm/filechooserbutton.h>
#include <gtkmm/entry.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
#include "option_editor.h"
class SearchPathOption : public Option
{
public:
SearchPathOption (const std::string& pathname, const std::string& label,
sigc::slot<std::string>, sigc::slot<bool, std::string>);
~SearchPathOption ();
void set_state_from_config ();
void add_to_page (OptionEditorPage*);
void clear ();
protected:
sigc::slot<std::string> _get; ///< slot to get the configuration variable's value
sigc::slot<bool, std::string> _set; ///< slot to set the configuration variable's value
struct PathEntry {
PathEntry (const std::string& path, bool removable=true);
Gtk::Entry entry;
Gtk::Button remove_button;
Gtk::HBox box;
std::string path;
};
std::list<PathEntry*> paths;
Gtk::FileChooserButton add_chooser;
Gtk::VBox vbox;
Gtk::VBox path_box;
Gtk::Label session_label;
void add_path (const std::string& path, bool removable=true);
void remove_path (const std::string& path);
void changed ();
void path_chosen ();
};
#endif /* __gtk_ardour_search_path_option_h__ */

View File

@ -25,6 +25,7 @@
#include "gui_thread.h"
#include "session_option_editor.h"
#include "search_path_option.h"
#include "i18n.h"
using namespace std;
@ -177,9 +178,9 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
sigc::mem_fun (*_session_config, &SessionConfiguration::set_show_region_fades)
));
/* MISC */
/* Media */
add_option (_("Misc"), new OptionEditorHeading (_("Audio file format")));
add_option (_("Media"), new OptionEditorHeading (_("Audio file format")));
ComboOption<SampleFormat>* sf = new ComboOption<SampleFormat> (
"native-file-data-format",
@ -192,7 +193,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
sf->add (FormatInt24, _("24-bit integer"));
sf->add (FormatInt16, _("16-bit integer"));
add_option (_("Misc"), sf);
add_option (_("Media"), sf);
ComboOption<HeaderFormat>* hf = new ComboOption<HeaderFormat> (
"native-file-header-format",
@ -206,13 +207,28 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
hf->add (WAVE64, _("WAVE-64"));
hf->add (CAF, _("CAF"));
add_option (_("Misc"), hf);
add_option (_("Media"), hf);
add_option (_("Media"), new OptionEditorHeading (_("Media Locations")));
add_option (_("Misc"), new OptionEditorHeading (_("Layering")));
SearchPathOption* spo = new SearchPathOption ("audio-search-path", _("Search for audio files in:"),
sigc::mem_fun (*_session_config, &SessionConfiguration::get_audio_search_path),
sigc::mem_fun (*_session_config, &SessionConfiguration::set_audio_search_path));
add_option (_("Media"), spo);
spo = new SearchPathOption ("midi-search-path", _("Search for MIDI files in:"),
sigc::mem_fun (*_session_config, &SessionConfiguration::get_midi_search_path),
sigc::mem_fun (*_session_config, &SessionConfiguration::set_midi_search_path));
add_option (_("Media"), spo);
/* Misc */
add_option (_("Misc"), new OptionEditorHeading (_("Layering (in overlaid mode)")));
ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
"layer-model",
_("Layering model in overlaid mode"),
_("Layering model"),
sigc::mem_fun (*_session_config, &SessionConfiguration::get_layer_model),
sigc::mem_fun (*_session_config, &SessionConfiguration::set_layer_model)
);
@ -227,7 +243,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
ComboOption<InsertMergePolicy>* li = new ComboOption<InsertMergePolicy> (
"insert-merge-policy",
_("Policy for handling same note and channel overlaps"),
_("Policy for handling same note\nand channel overlaps"),
sigc::mem_fun (*_session_config, &SessionConfiguration::get_insert_merge_policy),
sigc::mem_fun (*_session_config, &SessionConfiguration::set_insert_merge_policy)
);

View File

@ -141,6 +141,7 @@ gtk2_ardour_sources = [
'midi_streamview.cc',
'midi_time_axis.cc',
'midi_tracer.cc',
'missing_file_dialog.cc',
'mixer_group_tabs.cc',
'mixer_strip.cc',
'mixer_ui.cc',
@ -186,6 +187,7 @@ gtk2_ardour_sources = [
'route_processor_selection.cc',
'route_time_axis.cc',
'route_ui.cc',
'search_path_option.cc',
'selection.cc',
'send_ui.cc',
'session_import_dialog.cc',

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;
@ -397,12 +491,6 @@ FileSource::set_source_name (const string& newname, bool destructive)
return 0;
}
void
FileSource::set_search_path (DataType type, const string& p)
{
search_paths[type] = p;
}
void
FileSource::mark_immutable ()
{

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);