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