diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc index 8dd52a2194..58ad5b03ff 100644 --- a/gtk2_ardour/session_option_editor.cc +++ b/gtk2_ardour/session_option_editor.cc @@ -18,6 +18,7 @@ */ #include "ardour/session.h" +#include "ardour/session_directory.h" #include "gui_thread.h" #include "session_option_editor.h" @@ -198,6 +199,21 @@ SessionOptionEditor::SessionOptionEditor (Session* s) add_option (_("Media"), hf); + add_option (_("Locations"), new OptionEditorHeading (_("Record Folders"))); + + add_option (_("Locations"), new DirectoryOption ("session-root-hack", + _("Audio:"), + sigc::mem_fun (*this, &SessionOptionEditor::get_audio_source_dir), + sigc::mem_fun (*this, &SessionOptionEditor::set_audio_source_dir) + )); + + add_option (_("Locations"), new DirectoryOption ("session-root-hack", + _("Midi:"), + sigc::mem_fun (*this, &SessionOptionEditor::get_midi_source_dir), + sigc::mem_fun (*this, &SessionOptionEditor::set_midi_source_dir) + )); + + add_option (_("Locations"), new OptionEditorHeading (_("File locations"))); SearchPathOption* spo = new SearchPathOption ("audio-search-path", _("Search for audio files in:"), @@ -213,6 +229,7 @@ SessionOptionEditor::SessionOptionEditor (Session* s) add_option (_("Locations"), spo); + /* File Naming */ add_option (_("Filenames"), new OptionEditorHeading (_("File Naming"))); @@ -421,3 +438,35 @@ SessionOptionEditor::get_use_monitor_section () { return _session->monitor_out() != 0; } + +bool +SessionOptionEditor::set_audio_source_dir (std::string s) +{ + _session->set_audio_source_dir(s); + return true; +} + +std::string SessionOptionEditor::get_audio_source_dir () +{ + std::string s = _session->custom_audio_source_dir(); + if (s.empty()) { + s =_session->session_directory().sound_path(); + } + return s; +} + +bool +SessionOptionEditor::set_midi_source_dir (std::string s) +{ + _session->set_midi_source_dir(s); + return true; +} + +std::string SessionOptionEditor::get_midi_source_dir () +{ + std::string s = _session->custom_midi_source_dir(); + if (s.empty()) { + s =_session->session_directory().midi_path(); + } + return s; +} diff --git a/gtk2_ardour/session_option_editor.h b/gtk2_ardour/session_option_editor.h index d2053b46c4..a80bbedbfd 100644 --- a/gtk2_ardour/session_option_editor.h +++ b/gtk2_ardour/session_option_editor.h @@ -42,6 +42,11 @@ private: ComboOption* _vpu; EntryOption* _take_name; + + std::string get_audio_source_dir(); + bool set_audio_source_dir(std::string); + std::string get_midi_source_dir(); + bool set_midi_source_dir(std::string); }; #endif /* __gtk_ardour_session_option_editor_h__ */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 788d4d9fcb..1ed9566712 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -43,6 +43,7 @@ #include "pbd/rcu.h" #include "pbd/statefuldestructible.h" #include "pbd/signals.h" +#include "pbd/search_path.h" #include "pbd/undo.h" #include "evoral/types.hpp" @@ -184,6 +185,11 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop const SessionDirectory& session_directory () const { return *(_session_dir.get()); } + bool set_audio_source_dir (std::string); + bool set_midi_source_dir (std::string); + std::string custom_audio_source_dir () const { return _custom_audio_source_dir; } + std::string custom_midi_source_dir () const { return _custom_midi_source_dir; } + static PBD::Signal1 Dialog; int ensure_subdirs (); @@ -1486,6 +1492,9 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop std::string get_best_session_directory_for_new_source (); + std::string _custom_audio_source_dir; + std::string _custom_midi_source_dir; + mutable gint _playback_load; mutable gint _capture_load; diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 3123b59c2c..16197d869a 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -3427,13 +3427,21 @@ Session::new_source_path_from_name (DataType type, const string& name) { assert(name.find("/") == string::npos); - SessionDirectory sdir(get_best_session_directory_for_new_source()); - std::string p; if (type == DataType::AUDIO) { - p = sdir.sound_path(); + if (_custom_audio_source_dir.empty()) { + SessionDirectory sdir(get_best_session_directory_for_new_source()); + p = sdir.sound_path(); + } else { + p = _custom_audio_source_dir; + } } else if (type == DataType::MIDI) { - p = sdir.midi_path(); + if (_custom_midi_source_dir.empty()) { + SessionDirectory sdir(get_best_session_directory_for_new_source()); + p = sdir.midi_path(); + } else { + p = _custom_midi_source_dir; + } } else { error << "Unknown source type, unable to create file path" << endmsg; return ""; @@ -3442,6 +3450,94 @@ Session::new_source_path_from_name (DataType type, const string& name) return Glib::build_filename (p, name); } +bool +Session::set_audio_source_dir (std::string dir) +{ + bool changed = true; + if (get_record_enabled() && actively_recording()) { + /* this messes things up if done while recording */ + return false; + } + if (dir == _custom_audio_source_dir) { + return true; + } + SessionDirectory sdir(get_best_session_directory_for_new_source ()); + if (dir == sdir.sound_path() || dir.empty()) { + if (_custom_audio_source_dir.empty()) { + changed = false; + } else { + _custom_audio_source_dir = ""; + } + } else { + if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create new media location \"%1\" (%2)"), dir, strerror (errno)) << endmsg; + return false; + } + _custom_audio_source_dir = dir; + Searchpath asp (config.get_audio_search_path()); + asp += dir; + config.set_audio_search_path(asp.to_string()); + } + + if (changed) { + StateProtector sp (this); + + RouteList r (*(routes.reader ())); + for (RouteList::iterator i = r.begin(); i != r.end(); ++i) { + boost::shared_ptr t = boost::dynamic_pointer_cast (*i); + if (t) { + t->reset_write_sources(false, true); + } + } + } + return true; +} + +bool +Session::set_midi_source_dir (std::string dir) +{ + bool changed = true; + if (get_record_enabled() && actively_recording()) { + /* this messes things up if done while recording */ + return false; + } + if (dir == _custom_midi_source_dir) { + return true; + } + + SessionDirectory sdir(get_best_session_directory_for_new_source ()); + if (dir == sdir.midi_path() || dir.empty()) { + if (_custom_midi_source_dir.empty()) { + changed = false; + } else { + _custom_midi_source_dir = ""; + } + } else { + if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { + error << string_compose(_("Session: cannot create new media location \"%1\" (%2)"), dir, strerror (errno)) << endmsg; + return false; + } + + _custom_midi_source_dir = dir; + Searchpath msp (config.get_midi_search_path()); + msp += dir; + config.set_midi_search_path(msp.to_string()); + } + + if (changed) { + StateProtector sp (this); + + RouteList r (*(routes.reader ())); + for (RouteList::iterator i = r.begin(); i != r.end(); ++i) { + boost::shared_ptr t = boost::dynamic_pointer_cast (*i); + if (t) { + t->reset_write_sources(false, true); + } + } + } + return true; +} + string Session::peak_path (string base) const { @@ -3461,13 +3557,23 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha buf[0] = '\0'; legalized = legalize_for_path (base); + std::vector sdirs; + vector::iterator i; + + for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { + SessionDirectory sdir((*i).path); + sdirs.push_back(sdir.sound_path()); + } + if (!_custom_audio_source_dir.empty()) { + sdirs.push_back(_custom_audio_source_dir); + } + // Find a "version" of the base name that doesn't exist in any of the possible directories. for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) { - vector::iterator i; uint32_t existing = 0; - for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { + for (vector::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) { if (destructive) { @@ -3507,9 +3613,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha } } - SessionDirectory sdir((*i).path); - - string spath = sdir.sound_path(); + string spath = (*i); /* note that we search *without* the extension so that we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf" @@ -3579,21 +3683,29 @@ Session::new_midi_source_name (const string& owner_name) buf[0] = '\0'; legalized = legalize_for_path (owner_name); + std::vector sdirs; + vector::iterator i; + + for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { + SessionDirectory sdir((*i).path); + sdirs.push_back(sdir.midi_path()); + } + if (!_custom_midi_source_dir.empty()) { + sdirs.push_back(_custom_midi_source_dir); + } + // Find a "version" of the file name that doesn't exist in any of the possible directories. for (cnt = 1; cnt <= limit; ++cnt) { - vector::iterator i; uint32_t existing = 0; - for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { + for (vector::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) { - SessionDirectory sdir((*i).path); - snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt); possible_name = buf; - std::string possible_path = Glib::build_filename (sdir.midi_path(), possible_name); + std::string possible_path = Glib::build_filename (*i, possible_name); if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) { existing++; @@ -4182,7 +4294,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, framepos_t to_do; framepos_t latency_skip; BufferSet buffers; - SessionDirectory sdir(get_best_session_directory_for_new_source ()); + SessionDirectory sdir(get_best_session_directory_for_new_source ()); // XXX use _custom_audio_source_dir ?? const string sound_dir = sdir.sound_path(); framepos_t len = end - start; bool need_block_size_reset = false; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 6979f88dcb..da6b12270b 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -2123,7 +2123,7 @@ Session::get_best_session_directory_for_new_source () /* handle common case without system calls */ if (session_dirs.size() == 1) { - return result; + return session_dirs[0].path; } /* OK, here's the algorithm we're following here: