#include #include #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 r = s->route_by_id (target->value()); if (!r || boost::dynamic_pointer_cast(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 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 \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 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 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 r = *i; // skip special busses if (r->is_master() || r->is_monitor() || r->is_auditioner()) { continue; } // find matching route by name std::map::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::iterator i = routestate.begin(); i != routestate.end(); ++i) { XMLNode *state = i->second; delete state; } SessionUtils::cleanup(); return 0; }