summaryrefslogtreecommitdiff
path: root/session_utils
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-06-02 22:25:18 +0200
committerRobin Gareus <robin@gareus.org>2016-06-02 22:25:41 +0200
commitfe0ad00e7f690951f12c247bcb54e0859e84920f (patch)
tree170cfabc2ba93636bff9af5a3b3c869a3d27c34d /session_utils
parentea8521743717a0027f497c416ab3f08fc407a406 (diff)
copy mixer utility evolution
Diffstat (limited to 'session_utils')
-rw-r--r--session_utils/copy-mixer.cc275
-rw-r--r--session_utils/copy_mix.cc159
2 files changed, 275 insertions, 159 deletions
diff --git a/session_utils/copy-mixer.cc b/session_utils/copy-mixer.cc
new file mode 100644
index 0000000000..e95c077618
--- /dev/null
+++ b/session_utils/copy-mixer.cc
@@ -0,0 +1,275 @@
+#include <iostream>
+#include <cstdlib>
+#include <getopt.h>
+
+#include "pbd/stateful.h"
+#include "ardour/send.h"
+#include "ardour/track.h"
+
+#include "common.h"
+
+#define X_(Text) Text
+
+using namespace std;
+using namespace ARDOUR;
+using namespace SessionUtils;
+
+/* this is copied from Session::new_route_from_template */
+static void
+trim_state_for_mixer_copy (Session*s, XMLNode& node)
+{
+ /* trim bitslots from listen sends so that new ones are used */
+ XMLNodeList children = node.children ();
+ for (XMLNodeList::iterator i = children.begin (); i != children.end (); ++i) {
+ if ((*i)->name() == X_("Processor")) {
+ /* ForceIDRegeneration does not catch the following */
+ XMLProperty const * role = (*i)->property (X_("role"));
+ XMLProperty const * type = (*i)->property (X_("type"));
+ if (role && role->value () == X_("Aux")) {
+ /* check if the target bus exists,
+ * HERE: we use the bus-name (not target-id)
+ */
+ XMLProperty const * target = (*i)->property (X_("name"));
+ if (!target) {
+ (*i)->add_property ("type", "dangling-aux-send");
+ continue;
+ }
+ boost::shared_ptr<Route> r = s->route_by_name (target->value ());
+ if (!r || boost::dynamic_pointer_cast<Track> (r)) {
+ (*i)->add_property ("type", "dangling-aux-send");
+ continue;
+ }
+ (*i)->add_property ("target", r->id ().to_s ());
+ }
+ if (role && role->value () == X_("Listen")) {
+ (*i)->remove_property (X_("bitslot"));
+ }
+ else if (role && (role->value () == X_("Send") || role->value () == X_("Aux"))) {
+ char buf[32];
+ Delivery::Role xrole;
+ uint32_t bitslot = 0;
+ xrole = Delivery::Role (string_2_enum (role->value (), xrole));
+ std::string name = Send::name_and_id_new_send (*s, xrole, bitslot, false);
+ snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
+ (*i)->remove_property (X_("bitslot"));
+ (*i)->remove_property (X_("name"));
+ (*i)->add_property ("bitslot", buf);
+ (*i)->add_property ("name", name);
+ }
+ else if (type && type->value () == X_("intreturn")) {
+ // ignore, in case bus existed in old session,
+ // tracks in old session may be connected to it.
+ // if the bus is new, new_route_from_template()
+ // will have re-created an ID.
+ (*i)->add_property ("type", "ignore-aux-return");
+ }
+ else if (type && type->value () == X_("return")) {
+ // Return::set_state() generates a new one
+ (*i)->remove_property (X_("bitslot"));
+ }
+ else if (type && type->value () == X_("port")) {
+ // PortInsert::set_state() handles the bitslot
+ (*i)->remove_property (X_("bitslot"));
+ (*i)->add_property ("ignore-name", "1");
+ }
+ }
+ }
+}
+
+static void
+copy_mixer_settings (Session*s, boost::shared_ptr<Route> dst, XMLNode& state)
+{
+ PBD::Stateful::ForceIDRegeneration force_ids;
+
+ trim_state_for_mixer_copy (s, state);
+ state.remove_nodes_and_delete ("Diskstream");
+ state.remove_nodes_and_delete ("Automation");
+ state.dump (cerr);
+
+ dst->set_state (state, PBD::Stateful::loading_state_version);
+}
+
+static int
+copy_session_routes (
+ const std::string& src_path, const std::string& src_name,
+ const std::string& dst_path, const std::string& dst_load, const std::string& dst_save)
+{
+ SessionUtils::init (false);
+ Session* s = 0;
+
+ typedef std::map<std::string,XMLNode*> StateMap;
+ StateMap routestate;
+ StateMap buslist;
+
+ s = SessionUtils::load_session (src_path, src_name);
+
+ if (!s) {
+ printf ("Cannot load source session %s/%s.\n", src_path.c_str (), src_name.c_str ());
+ SessionUtils::cleanup ();
+ return -1;
+ }
+
+ /* get route state from first session */
+ boost::shared_ptr<RouteList> rl = s->get_routes ();
+ for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
+ boost::shared_ptr<Route> r = *i;
+ if (r->is_master () || r->is_monitor () || r->is_auditioner ()) {
+ continue;
+ }
+ XMLNode& state (r->get_state ());
+ routestate[r->name ()] = &state;
+ if (boost::dynamic_pointer_cast<Track> (r)) {
+ continue;
+ }
+ buslist[r->name ()] = &state;
+ }
+ rl.reset ();
+ SessionUtils::unload_session (s);
+
+
+ /* open target session */
+ s = SessionUtils::load_session (dst_path, dst_load);
+ if (!s) {
+ printf ("Cannot load target session %s/%s.\n", dst_path.c_str (), dst_load.c_str ());
+ SessionUtils::cleanup ();
+ return -1;
+ }
+
+ /* iterate over all busses in the src session, add missing ones to target */
+ // TODO: make optional
+ rl = s->get_routes ();
+ for (StateMap::const_iterator i = buslist.begin (); i != buslist.end (); ++i) {
+ if (s->route_by_name (i->first)) {
+ continue;
+ }
+ XMLNode& rs (*(i->second));
+ s->new_route_from_template (1, rs, rs.property (X_("name"))->value (), NewPlaylist);
+ }
+
+ /* iterate over all *busses* in the target session.
+ * setup internal return targets.
+ */
+ rl = s->get_routes ();
+ for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
+ boost::shared_ptr<Route> r = *i;
+ /* skip special busses */
+ if (r->is_master () || r->is_monitor () || r->is_auditioner ()) {
+ continue;
+ }
+ if (boost::dynamic_pointer_cast<Track> (r)) {
+ continue;
+ }
+ /* find matching route by name */
+ std::map<std::string,XMLNode*>::iterator it = routestate.find (r->name ());
+ if (it == routestate.end ()) {
+ printf (" -- no match for '%s'\n", (*i)->name ().c_str ());
+ continue;
+ }
+ printf ("-- found match '%s'\n", (*i)->name ().c_str ());
+ XMLNode *state = it->second;
+ // copy state
+ copy_mixer_settings (s, r, *state);
+ }
+
+ /* iterate over all tracks in the target session.. */
+ rl = s->get_routes ();
+ for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
+ boost::shared_ptr<Route> r = *i;
+ /* skip special busses */
+ if (r->is_master () || r->is_monitor () || r->is_auditioner ()) {
+ continue;
+ }
+ if (!boost::dynamic_pointer_cast<Track> (r)) {
+ continue;
+ }
+
+ /* find matching route by name */
+ std::map<std::string,XMLNode*>::iterator it = routestate.find (r->name ());
+ if (it == routestate.end ()) {
+ printf (" -- no match for '%s'\n", (*i)->name ().c_str ());
+ continue;
+ }
+ printf ("-- found match '%s'\n", (*i)->name ().c_str ());
+ XMLNode *state = it->second;
+ /* copy state */
+ copy_mixer_settings (s, r, *state);
+ }
+
+ s->save_state (dst_save);
+
+ rl.reset ();
+ SessionUtils::unload_session (s);
+
+ // clean up.
+ for (StateMap::iterator i = routestate.begin (); i != routestate.end (); ++i) {
+ XMLNode *state = i->second;
+ delete state;
+ }
+
+ SessionUtils::cleanup ();
+ return 0;
+}
+
+
+static void usage (int status) {
+ // help2man compatible format (standard GNU help-text)
+ printf ("copy-mixer - copy mixer settings from one session to another.\n\n");
+ printf ("Usage: copy-mixer [ OPTIONS ] <src-path> <name> <dst-path> <name> [name]\n\n");
+ printf ("Options:\n\
+ -h, --help display this help and exit\n\
+ -V, --version print version information and exit\n\
+\n");
+ printf ("\n\
+.. not yet documented..\n\
+\n");
+
+ printf ("Report bugs to <http://tracker.ardour.org/>\n"
+ "Website: <http://ardour.org/>\n");
+ ::exit (status);
+}
+
+
+int main (int argc, char* argv[])
+{
+ const char *optstring = "hV";
+
+ // TODO add some arguments. (save snapshot, copy busses...)
+
+ const struct option longopts[] = {
+ { "help", 0, 0, 'h' },
+ { "version", 0, 0, 'V' },
+ };
+
+ int c = 0;
+
+ while (EOF != (c = getopt_long (argc, argv,
+ optstring, longopts, (int *) 0))) {
+ switch (c) {
+
+ case 'V':
+ printf ("ardour-utils version %s\n\n", VERSIONSTRING);
+ printf ("Copyright (C) GPL 2015 Robin Gareus <robin@gareus.org>\n");
+ exit (0);
+ break;
+
+ case 'h':
+ usage (0);
+ break;
+
+ default:
+ usage (EXIT_FAILURE);
+ break;
+ }
+ }
+
+ // TODO parse path/name from a single argument.
+
+ if (optind + 4 > argc) {
+ usage (EXIT_FAILURE);
+ }
+
+ return copy_session_routes (
+ argv[optind], argv[optind + 1],
+ argv[optind + 2], argv[optind + 3],
+ (optind + 4 < argc) ? argv[optind + 4] : "");
+}
diff --git a/session_utils/copy_mix.cc b/session_utils/copy_mix.cc
deleted file mode 100644
index 8163c47253..0000000000
--- a/session_utils/copy_mix.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-#include <iostream>
-#include <cstdlib>
-
-#include "pbd/stateful.h"
-#include "ardour/send.h"
-#include "ardour/track.h"
-
-#include "common.h"
-
-#define X_(Text) Text
-
-using namespace std;
-using namespace ARDOUR;
-using namespace SessionUtils;
-
-/* this is copied from Session::new_route_from_template */
-void trim_state_for_mixer_copy (Session*s, XMLNode& node)
-{
- /* trim bitslots from listen sends so that new ones are used */
- XMLNodeList children = node.children ();
- for (XMLNodeList::iterator i = children.begin(); i != children.end(); ++i) {
- if ((*i)->name() == X_("Processor")) {
- /* ForceIDRegeneration does not catch the following */
- XMLProperty const * role = (*i)->property (X_("role"));
- XMLProperty const * type = (*i)->property (X_("type"));
- if (role && role->value() == X_("Aux")) {
- /* check if the target bus exists.
- * we should not save aux-sends in templates.
- */
- XMLProperty const * target = (*i)->property (X_("target"));
- if (!target) {
- (*i)->add_property ("type", "dangling-aux-send");
- continue;
- }
- boost::shared_ptr<Route> r = s->route_by_id (target->value());
- if (!r || boost::dynamic_pointer_cast<Track>(r)) {
- (*i)->add_property ("type", "dangling-aux-send");
- continue;
- }
- }
- if (role && role->value() == X_("Listen")) {
- (*i)->remove_property (X_("bitslot"));
- }
- else if (role && (role->value() == X_("Send") || role->value() == X_("Aux"))) {
- char buf[32];
- Delivery::Role xrole;
- uint32_t bitslot = 0;
- xrole = Delivery::Role (string_2_enum (role->value(), xrole));
- std::string name = Send::name_and_id_new_send(*s, xrole, bitslot, false);
- snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
- (*i)->remove_property (X_("bitslot"));
- (*i)->remove_property (X_("name"));
- (*i)->add_property ("bitslot", buf);
- (*i)->add_property ("name", name);
- }
- else if (type && type->value() == X_("return")) {
- // Return::set_state() generates a new one
- (*i)->remove_property (X_("bitslot"));
- }
- else if (type && type->value() == X_("port")) {
- // PortInsert::set_state() handles the bitslot
- (*i)->remove_property (X_("bitslot"));
- (*i)->add_property ("ignore-name", "1");
- }
- }
- }
-}
-
-
-static void copy_mixer_settings (Session*s, boost::shared_ptr<Route> dst, XMLNode& state)
-{
- PBD::Stateful::ForceIDRegeneration force_ids;
-
- trim_state_for_mixer_copy (s, state);
- state.remove_nodes_and_delete ("Diskstream");
- state.remove_nodes_and_delete ("Automation");
- //state.dump (cerr);
-
- dst->set_state (state, PBD::Stateful::loading_state_version);
-}
-
-int main (int argc, char* argv[])
-{
- if (argc < 5) {
- printf ("Usage: copy-mix <session1-dir> <session1-name> <session2-dir> <session2-name>\n");
- return -1;
- }
-
- std::string session1_dir (argv[1]);
- std::string session1_name (argv[2]);
-
- std::string session2_dir = (argv[3]);
- std::string session2_name = (argv[4]);
-
-
- SessionUtils::init();
- Session* s = 0;
- std::map<std::string,XMLNode*> routestate;
-
- s = SessionUtils::load_session ( session1_dir, session1_name);
-
- if (!s) {
- printf("Cannot load source session.\n");
- SessionUtils::cleanup();
- return 0;
- }
-
- // get route state from first session
- boost::shared_ptr<RouteList> rl = s->get_routes ();
- for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
- XMLNode& state ((*i)->get_state());
- routestate[(*i)->name()] = &state;
- }
- rl.reset();
- SessionUtils::unload_session(s);
-
-
- // open target session
- s = SessionUtils::load_session (session2_dir, session2_name);
- if (!s) {
- printf("Cannot load target session.\n");
- SessionUtils::cleanup();
- return 0;
- }
-
- // iterate over all routes in the target session..
- rl = s->get_routes ();
- for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
- boost::shared_ptr<Route> r = *i;
- // skip special busses
- if (r->is_master() || r->is_monitor() || r->is_auditioner()) {
- continue;
- }
- // find matching route by name
- std::map<std::string,XMLNode*>::iterator it = routestate.find (r->name ());
- if (it == routestate.end()) {
- printf (" -- no match for '%s'\n", (*i)->name().c_str());
- continue;
- }
- printf ("-- found match '%s'\n", (*i)->name().c_str());
- XMLNode *state = it->second;
- // copy state
- copy_mixer_settings (s, r, *state);
- }
-
- s->save_state ("");
-
- rl.reset();
- SessionUtils::unload_session(s);
-
- // clean up.
- for (std::map<std::string,XMLNode*>::iterator i = routestate.begin(); i != routestate.end(); ++i) {
- XMLNode *state = i->second;
- delete state;
- }
-
- SessionUtils::cleanup();
- return 0;
-}