session-utils tweaks
[ardour.git] / session_utils / copy_mix.cc
1 #include <iostream>
2 #include <cstdlib>
3
4 #include "pbd/stateful.h"
5 #include "ardour/send.h"
6 #include "ardour/track.h"
7
8 #include "common.h"
9
10 #define X_(Text) Text
11
12 using namespace std;
13 using namespace ARDOUR;
14 using namespace SessionUtils;
15
16 /* this is copied from  Session::new_route_from_template */
17 void trim_state_for_mixer_copy (Session*s, XMLNode& node)
18 {
19         /* trim bitslots from listen sends so that new ones are used */
20         XMLNodeList children = node.children ();
21         for (XMLNodeList::iterator i = children.begin(); i != children.end(); ++i) {
22                 if ((*i)->name() == X_("Processor")) {
23                         /* ForceIDRegeneration does not catch the following */
24                         XMLProperty const * role = (*i)->property (X_("role"));
25                         XMLProperty const * type = (*i)->property (X_("type"));
26                         if (role && role->value() == X_("Aux")) {
27                                 /* check if the target bus exists.
28                                  * we should not save aux-sends in templates.
29                                  */
30                                 XMLProperty const * target = (*i)->property (X_("target"));
31                                 if (!target) {
32                                         (*i)->add_property ("type", "dangling-aux-send");
33                                         continue;
34                                 }
35                                 boost::shared_ptr<Route> r = s->route_by_id (target->value());
36                                 if (!r || boost::dynamic_pointer_cast<Track>(r)) {
37                                         (*i)->add_property ("type", "dangling-aux-send");
38                                         continue;
39                                 }
40                         }
41                         if (role && role->value() == X_("Listen")) {
42                                 (*i)->remove_property (X_("bitslot"));
43                         }
44                         else if (role && (role->value() == X_("Send") || role->value() == X_("Aux"))) {
45                                 char buf[32];
46                                 Delivery::Role xrole;
47                                 uint32_t bitslot = 0;
48                                 xrole = Delivery::Role (string_2_enum (role->value(), xrole));
49                                 std::string name = Send::name_and_id_new_send(*s, xrole, bitslot, false);
50                                 snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
51                                 (*i)->remove_property (X_("bitslot"));
52                                 (*i)->remove_property (X_("name"));
53                                 (*i)->add_property ("bitslot", buf);
54                                 (*i)->add_property ("name", name);
55                         }
56                         else if (type && type->value() == X_("return")) {
57                                 // Return::set_state() generates a new one
58                                 (*i)->remove_property (X_("bitslot"));
59                         }
60                         else if (type && type->value() == X_("port")) {
61                                 // PortInsert::set_state() handles the bitslot
62                                 (*i)->remove_property (X_("bitslot"));
63                                 (*i)->add_property ("ignore-name", "1");
64                         }
65                 }
66         }
67 }
68
69
70 static void copy_mixer_settings (Session*s, boost::shared_ptr<Route> dst, XMLNode& state)
71 {
72         PBD::Stateful::ForceIDRegeneration force_ids;
73
74         trim_state_for_mixer_copy (s, state);
75         state.remove_nodes_and_delete ("Diskstream");
76         state.remove_nodes_and_delete ("Automation");
77         //state.dump (cerr);
78
79         dst->set_state (state, PBD::Stateful::loading_state_version);
80 }
81
82 int main (int argc, char* argv[])
83 {
84         if (argc < 5) {
85                 printf ("Usage: copy-mix <session1-dir> <session1-name> <session2-dir> <session2-name>\n");
86                 return -1;
87         }
88
89         std::string session1_dir (argv[1]);
90         std::string session1_name (argv[2]);
91
92         std::string session2_dir = (argv[3]);
93         std::string session2_name = (argv[4]);
94
95
96         SessionUtils::init();
97         Session* s = 0;
98         std::map<std::string,XMLNode*> routestate;
99
100         s = SessionUtils::load_session ( session1_dir, session1_name);
101
102         if (!s) {
103                 printf("Cannot load source session.\n");
104                 SessionUtils::cleanup();
105                 return 0;
106         }
107
108         // get route state from first session
109         boost::shared_ptr<RouteList> rl = s->get_routes ();
110         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
111                 XMLNode& state ((*i)->get_state());
112                 routestate[(*i)->name()] = &state;
113         }
114         rl.reset();
115         SessionUtils::unload_session(s);
116
117
118         // open target session
119         s = SessionUtils::load_session (session2_dir, session2_name);
120         if (!s) {
121                 printf("Cannot load target session.\n");
122                 SessionUtils::cleanup();
123                 return 0;
124         }
125
126         // iterate over all routes in the target session..
127         rl = s->get_routes ();
128         for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
129                 boost::shared_ptr<Route> r = *i;
130                 // skip special busses
131                 if (r->is_master() || r->is_monitor() || r->is_auditioner()) {
132                         continue;
133                 }
134                 // find matching route by name
135                 std::map<std::string,XMLNode*>::iterator it = routestate.find (r->name ());
136                 if (it == routestate.end()) {
137                         printf (" -- no match for '%s'\n", (*i)->name().c_str());
138                         continue;
139                 }
140                 printf ("-- found match '%s'\n", (*i)->name().c_str());
141                 XMLNode *state = it->second;
142                 // copy state
143                 copy_mixer_settings (s, r, *state);
144         }
145
146         s->save_state ("");
147
148         rl.reset();
149         SessionUtils::unload_session(s);
150
151         // clean up.
152         for (std::map<std::string,XMLNode*>::iterator i = routestate.begin(); i != routestate.end(); ++i) {
153                 XMLNode *state = i->second;
154                 delete state;
155         }
156
157         SessionUtils::cleanup();
158         return 0;
159 }