From 9f4c7a9e9edd260a72f040b036982d4c5da89292 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 2 Mar 2009 16:52:40 +0000 Subject: track templates, backported from 2.X git-svn-id: svn://localhost/ardour2/branches/3.0@4713 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/directory_names.h | 1 + libs/ardour/ardour/io.h | 2 + libs/ardour/ardour/route.h | 2 + libs/ardour/ardour/session.h | 1 + libs/ardour/ardour/template_utils.h | 9 ++++ libs/ardour/directory_names.cc | 1 + libs/ardour/io.cc | 20 +++++++++ libs/ardour/route.cc | 13 ++++++ libs/ardour/session.cc | 82 ++++++++++++++++++++++++++++++++++++ libs/ardour/template_utils.cc | 73 ++++++++++++++++++++++++++++++++ 10 files changed, 204 insertions(+) diff --git a/libs/ardour/ardour/directory_names.h b/libs/ardour/ardour/directory_names.h index 2f9991fd65..b0023bba5a 100644 --- a/libs/ardour/ardour/directory_names.h +++ b/libs/ardour/ardour/directory_names.h @@ -16,6 +16,7 @@ extern const char* const interchange_dir_name; extern const char* const peak_dir_name; extern const char* const export_dir_name; extern const char* const templates_dir_name; +extern const char* const route_templates_dir_name; extern const char* const surfaces_dir_name; extern const char* const user_config_dir_name; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 2058e2e079..709a5368db 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -215,6 +215,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent static sigc::signal PortsCreated; static void update_meters(); + static std::string name_from_state (const XMLNode&); + static void set_name_in_state (XMLNode&, const std::string&); private: diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index a5bd751d22..2319cadb57 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -221,6 +221,8 @@ class Route : public IO XMLNode& get_processor_state (); int set_processor_state (const XMLNode&); + int save_as_template (const std::string& path, const std::string& name); + sigc::signal SelectedChanged; int set_control_outs (const vector& ports); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 6e09bbd4ed..082e05a9bd 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -281,6 +281,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable string new_audio_source_name (const string&, uint32_t nchans, uint32_t chan, bool destructive); string new_midi_source_name (const string&); string new_source_path_from_name (DataType type, const string&); + RouteList new_route_from_template (uint32_t how_many, const std::string& template_path); void process (nframes_t nframes); diff --git a/libs/ardour/ardour/template_utils.h b/libs/ardour/ardour/template_utils.h index 6ba0683e1e..5542e8420f 100644 --- a/libs/ardour/ardour/template_utils.h +++ b/libs/ardour/ardour/template_utils.h @@ -12,8 +12,17 @@ namespace ARDOUR { using namespace PBD; sys::path system_template_directory (); + sys::path system_route_template_directory (); sys::path user_template_directory (); + sys::path user_route_template_directory (); + + struct RouteTemplateInfo { + std::string name; + std::string path; + }; + + void find_route_templates (std::vector& template_names); } // namespace ARDOUR diff --git a/libs/ardour/directory_names.cc b/libs/ardour/directory_names.cc index 6afcfb4353..266147eb2e 100644 --- a/libs/ardour/directory_names.cc +++ b/libs/ardour/directory_names.cc @@ -14,6 +14,7 @@ const char* const dead_midi_dir_name = X_("dead_midi"); const char* const interchange_dir_name = X_("interchange"); const char* const export_dir_name = X_("export"); const char* const templates_dir_name = X_("templates"); +const char* const route_templates_dir_name = X_("route_templates"); const char* const surfaces_dir_name = X_("surfaces"); const char* const user_config_dir_name = X_(".ardour3"); diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index f1c1bb1dab..e6dff6158a 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -2778,4 +2778,24 @@ IO::bundle_channel_name (uint32_t c, uint32_t n) const return ""; } +string +IO::name_from_state (const XMLNode& node) +{ + const XMLProperty* prop; + + if ((prop = node.property ("name")) != 0) { + return prop->value(); + } + + return string(); +} +void +IO::set_name_in_state (XMLNode& node, const string& new_name) +{ + const XMLProperty* prop; + + if ((prop = node.property ("name")) != 0) { + node.add_property ("name", new_name); + } +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 0111ca8e10..c1f7d97d5c 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -3099,3 +3099,16 @@ Route::shift (nframes64_t pos, nframes64_t frames) #endif } + + +int +Route::save_as_template (const string& path, const string& name) +{ + XMLNode& node (state (false)); + XMLTree tree; + + IO::set_name_in_state (*node.children().front(), name); + + tree.set_root (&node); + return tree.write (path.c_str()); +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 51f55cb6b9..d2938f666f 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1980,6 +1980,88 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ } +RouteList +Session::new_route_from_template (uint32_t how_many, const std::string& template_path) +{ + char name[32]; + RouteList ret; + uint32_t control_id; + XMLTree tree; + + if (!tree.read (template_path.c_str())) { + return ret; + } + + XMLNode* node = tree.root(); + + control_id = ntracks() + nbusses() + 1; + + while (how_many) { + + XMLNode node_copy (*node); // make a copy so we can change the name if we need to + + std::string node_name = IO::name_from_state (*node_copy.children().front()); + + if (route_by_name (node_name) != 0) { + + /* generate a new name by adding a number to the end of the template name */ + + uint32_t number = 1; + + do { + snprintf (name, sizeof (name), "%s %" PRIu32, node_name.c_str(), number); + + number++; + + if (route_by_name (name) == 0) { + break; + } + + } while (number < UINT_MAX); + + if (number == UINT_MAX) { + fatal << _("Session: UINT_MAX routes? impossible!") << endmsg; + /*NOTREACHED*/ + } + + IO::set_name_in_state (node_copy, name); + } + + try { + shared_ptr route (XMLRouteFactory (node_copy)); + + if (route == 0) { + error << _("Session: cannot create track/bus from template description") << endmsg; + goto out; + } + + route->set_remote_control_id (control_id); + ++control_id; + + ret.push_back (route); + } + + catch (failed_constructor &err) { + error << _("Session: could not create new route from template") << endmsg; + goto out; + } + + catch (AudioEngine::PortRegistrationFailure& pfe) { + error << _("No more JACK ports are available. You will need to stop Ardour and restart JACK with ports if you need this many tracks.") << endmsg; + goto out; + } + + --how_many; + } + + out: + if (!ret.empty()) { + add_routes (ret, true); + } + + return ret; +} + void Session::add_routes (RouteList& new_routes, bool save) { diff --git a/libs/ardour/template_utils.cc b/libs/ardour/template_utils.cc index 7c25b59db8..93bfd46972 100644 --- a/libs/ardour/template_utils.cc +++ b/libs/ardour/template_utils.cc @@ -1,10 +1,15 @@ #include +#include #include "pbd/filesystem.h" +#include "pbd/pathscanner.h" +#include "pbd/xml++.h" #include "ardour/template_utils.h" #include "ardour/directory_names.h" #include "ardour/filesystem_paths.h" +#include "ardour/filename_extensions.h" +#include "ardour/io.h" namespace ARDOUR { @@ -22,6 +27,20 @@ system_template_directory () return *i; } +sys::path +system_route_template_directory () +{ + SearchPath spath(system_data_search_path()); + spath.add_subdirectory_to_paths(route_templates_dir_name); + + // just return the first directory in the search path that exists + SearchPath::const_iterator i = std::find_if(spath.begin(), spath.end(), sys::exists); + + if (i == spath.end()) return sys::path(); + + return *i; +} + sys::path user_template_directory () { @@ -31,4 +50,58 @@ user_template_directory () return p; } +sys::path +user_route_template_directory () +{ + sys::path p(user_config_directory()); + p /= route_templates_dir_name; + + return p; +} + +static bool +template_filter (const string &str, void *arg) +{ + return (str.length() > strlen(temp_suffix) && + str.find (temp_suffix) == (str.length() - strlen (temp_suffix))); +} + +void +find_route_templates (vector& template_names) +{ + vector *templates; + PathScanner scanner; + SearchPath spath (system_data_search_path()); + + spath += user_config_directory(); + spath.add_subdirectory_to_paths(route_templates_dir_name); + + templates = scanner (spath.to_string(), template_filter, 0, false, true); + + if (!templates) { + return; + } + + for (vector::iterator i = templates->begin(); i != templates->end(); ++i) { + string fullpath = *(*i); + + XMLTree tree; + + if (!tree.read (fullpath.c_str())) { + continue; + } + + XMLNode* root = tree.root(); + + RouteTemplateInfo rti; + + rti.name = IO::name_from_state (*root->children().front()); + rti.path = fullpath; + + template_names.push_back (rti); + } + + free (templates); +} + } // namespace ARDOUR -- cgit v1.2.3