prototype tool to copy mixer/route settings between sessions
authorRobin Gareus <robin@gareus.org>
Thu, 2 Jun 2016 12:07:00 +0000 (14:07 +0200)
committerRobin Gareus <robin@gareus.org>
Thu, 2 Jun 2016 12:07:25 +0000 (14:07 +0200)
session_utils/copy_mix.cc [new file with mode: 0644]

diff --git a/session_utils/copy_mix.cc b/session_utils/copy_mix.cc
new file mode 100644 (file)
index 0000000..8163c47
--- /dev/null
@@ -0,0 +1,159 @@
+#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;
+}