track templates, backported from 2.X
git-svn-id: svn://localhost/ardour2/branches/3.0@4713 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<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
|
||||
|
||||
Reference in New Issue
Block a user