summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-03-02 16:52:40 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-03-02 16:52:40 +0000
commit9f4c7a9e9edd260a72f040b036982d4c5da89292 (patch)
tree191cc47ddda09dbd1ca5df768c04e10656804598 /libs/ardour
parentf613d3fe1478533ca770c1f3439cf1c670177210 (diff)
track templates, backported from 2.X
git-svn-id: svn://localhost/ardour2/branches/3.0@4713 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/directory_names.h1
-rw-r--r--libs/ardour/ardour/io.h2
-rw-r--r--libs/ardour/ardour/route.h2
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/ardour/template_utils.h9
-rw-r--r--libs/ardour/directory_names.cc1
-rw-r--r--libs/ardour/io.cc20
-rw-r--r--libs/ardour/route.cc13
-rw-r--r--libs/ardour/session.cc82
-rw-r--r--libs/ardour/template_utils.cc73
10 files changed, 204 insertions, 0 deletions
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<int> 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<void,void*> SelectedChanged;
int set_control_outs (const vector<std::string>& 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<RouteTemplateInfo>& 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> 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 <algorithm>
+#include <cstring>
#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 {
@@ -23,6 +28,20 @@ system_template_directory ()
}
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 ()
{
sys::path p(user_config_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<RouteTemplateInfo>& template_names)
+{
+ vector<string *> *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<string*>::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