5 #include "pbd/stateful.h"
6 #include "ardour/send.h"
7 #include "ardour/track.h"
14 using namespace ARDOUR;
15 using namespace SessionUtils;
17 /* this is copied from Session::new_route_from_template */
19 trim_state_for_mixer_copy (Session*s, XMLNode& node)
21 /* trim bitslots from listen sends so that new ones are used */
22 XMLNodeList children = node.children ();
23 for (XMLNodeList::iterator i = children.begin (); i != children.end (); ++i) {
24 if ((*i)->name() == X_("Processor")) {
25 /* ForceIDRegeneration does not catch the following */
26 XMLProperty const * role = (*i)->property (X_("role"));
27 XMLProperty const * type = (*i)->property (X_("type"));
28 if (role && role->value () == X_("Aux")) {
29 /* check if the target bus exists,
30 * HERE: we use the bus-name (not target-id)
32 XMLProperty const * target = (*i)->property (X_("name"));
34 (*i)->add_property ("type", "dangling-aux-send");
37 boost::shared_ptr<Route> r = s->route_by_name (target->value ());
38 if (!r || boost::dynamic_pointer_cast<Track> (r)) {
39 (*i)->add_property ("type", "dangling-aux-send");
42 (*i)->add_property ("target", r->id ().to_s ());
44 if (role && role->value () == X_("Listen")) {
45 (*i)->remove_property (X_("bitslot"));
47 else if (role && (role->value () == X_("Send") || role->value () == X_("Aux"))) {
51 xrole = Delivery::Role (string_2_enum (role->value (), xrole));
52 std::string name = Send::name_and_id_new_send (*s, xrole, bitslot, false);
53 snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
54 (*i)->remove_property (X_("bitslot"));
55 (*i)->remove_property (X_("name"));
56 (*i)->add_property ("bitslot", buf);
57 (*i)->add_property ("name", name);
59 else if (type && type->value () == X_("intreturn")) {
60 // ignore, in case bus existed in old session,
61 // tracks in old session may be connected to it.
62 // if the bus is new, new_route_from_template()
63 // will have re-created an ID.
64 (*i)->add_property ("type", "ignore-aux-return");
66 else if (type && type->value () == X_("return")) {
67 // Return::set_state() generates a new one
68 (*i)->remove_property (X_("bitslot"));
70 else if (type && type->value () == X_("port")) {
71 // PortInsert::set_state() handles the bitslot
72 (*i)->remove_property (X_("bitslot"));
73 (*i)->add_property ("ignore-name", "1");
80 copy_mixer_settings (Session*s, boost::shared_ptr<Route> dst, XMLNode& state)
82 PBD::Stateful::ForceIDRegeneration force_ids;
84 trim_state_for_mixer_copy (s, state);
85 state.remove_nodes_and_delete ("Diskstream");
86 state.remove_nodes_and_delete ("Automation");
89 dst->set_state (state, PBD::Stateful::loading_state_version);
94 const std::string& src_path, const std::string& src_name,
95 const std::string& dst_path, const std::string& dst_load, const std::string& dst_save)
97 SessionUtils::init (false);
100 typedef std::map<std::string,XMLNode*> StateMap;
104 s = SessionUtils::load_session (src_path, src_name);
107 printf ("Cannot load source session %s/%s.\n", src_path.c_str (), src_name.c_str ());
108 SessionUtils::cleanup ();
112 /* get route state from first session */
113 boost::shared_ptr<RouteList> rl = s->get_routes ();
114 for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
115 boost::shared_ptr<Route> r = *i;
116 if (r->is_master () || r->is_monitor () || r->is_auditioner ()) {
119 XMLNode& state (r->get_state ());
120 routestate[r->name ()] = &state;
121 if (boost::dynamic_pointer_cast<Track> (r)) {
124 buslist[r->name ()] = &state;
127 SessionUtils::unload_session (s);
130 /* open target session */
131 s = SessionUtils::load_session (dst_path, dst_load);
133 printf ("Cannot load target session %s/%s.\n", dst_path.c_str (), dst_load.c_str ());
134 SessionUtils::cleanup ();
138 /* iterate over all busses in the src session, add missing ones to target */
139 // TODO: make optional
140 rl = s->get_routes ();
141 for (StateMap::const_iterator i = buslist.begin (); i != buslist.end (); ++i) {
142 if (s->route_by_name (i->first)) {
145 XMLNode& rs (*(i->second));
146 s->new_route_from_template (1, rs, rs.property (X_("name"))->value (), NewPlaylist);
149 /* iterate over all *busses* in the target session.
150 * setup internal return targets.
152 rl = s->get_routes ();
153 for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
154 boost::shared_ptr<Route> r = *i;
155 /* skip special busses */
156 if (r->is_master () || r->is_monitor () || r->is_auditioner ()) {
159 if (boost::dynamic_pointer_cast<Track> (r)) {
162 /* find matching route by name */
163 std::map<std::string,XMLNode*>::iterator it = routestate.find (r->name ());
164 if (it == routestate.end ()) {
165 printf (" -- no match for '%s'\n", (*i)->name ().c_str ());
168 printf ("-- found match '%s'\n", (*i)->name ().c_str ());
169 XMLNode *state = it->second;
171 copy_mixer_settings (s, r, *state);
174 /* iterate over all tracks in the target session.. */
175 rl = s->get_routes ();
176 for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) {
177 boost::shared_ptr<Route> r = *i;
178 /* skip special busses */
179 if (r->is_master () || r->is_monitor () || r->is_auditioner ()) {
182 if (!boost::dynamic_pointer_cast<Track> (r)) {
186 /* find matching route by name */
187 std::map<std::string,XMLNode*>::iterator it = routestate.find (r->name ());
188 if (it == routestate.end ()) {
189 printf (" -- no match for '%s'\n", (*i)->name ().c_str ());
192 printf ("-- found match '%s'\n", (*i)->name ().c_str ());
193 XMLNode *state = it->second;
195 copy_mixer_settings (s, r, *state);
198 s->save_state (dst_save);
201 SessionUtils::unload_session (s);
204 for (StateMap::iterator i = routestate.begin (); i != routestate.end (); ++i) {
205 XMLNode *state = i->second;
209 SessionUtils::cleanup ();
214 static void usage (int status) {
215 // help2man compatible format (standard GNU help-text)
216 printf ("copy-mixer - copy mixer settings from one session to another.\n\n");
217 printf ("Usage: copy-mixer [ OPTIONS ] <src-path> <name> <dst-path> <name> [name]\n\n");
219 -h, --help display this help and exit\n\
220 -V, --version print version information and exit\n\
223 .. not yet documented..\n\
226 printf ("Report bugs to <http://tracker.ardour.org/>\n"
227 "Website: <http://ardour.org/>\n");
232 int main (int argc, char* argv[])
234 const char *optstring = "hV";
236 // TODO add some arguments. (save snapshot, copy busses...)
238 const struct option longopts[] = {
239 { "help", 0, 0, 'h' },
240 { "version", 0, 0, 'V' },
245 while (EOF != (c = getopt_long (argc, argv,
246 optstring, longopts, (int *) 0))) {
250 printf ("ardour-utils version %s\n\n", VERSIONSTRING);
251 printf ("Copyright (C) GPL 2015 Robin Gareus <robin@gareus.org>\n");
260 usage (EXIT_FAILURE);
265 // TODO parse path/name from a single argument.
267 if (optind + 4 > argc) {
268 usage (EXIT_FAILURE);
271 return copy_session_routes (
272 argv[optind], argv[optind + 1],
273 argv[optind + 2], argv[optind + 3],
274 (optind + 4 < argc) ? argv[optind + 4] : "");