+Session::RouteList
+Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
+{
+ char name[32];
+ RouteList ret;
+ uint32_t control_id;
+ XMLTree tree;
+ uint32_t number = 1;
+
+ if (!tree.read (template_path.c_str())) {
+ return ret;
+ }
+
+ XMLNode* node = tree.root();
+
+ control_id = ntracks() + nbusses() + 1;
+
+ while (how_many) {
+
+ XMLNode node_copy (*node); // make a copy so we can change the name if we need to
+
+ std::string node_name = IO::name_from_state (*node_copy.children().front());
+
+ /* generate a new name by adding a number to the end of the template name */
+
+ do {
+ snprintf (name, sizeof (name), "%s %" PRIu32, node_name.c_str(), number);
+
+ number++;
+
+ if (route_by_name (name) == 0) {
+ break;
+ }
+
+ } while (number < UINT_MAX);
+
+ if (number == UINT_MAX) {
+ fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ IO::set_name_in_state (*node_copy.children().front(), name);
+
+ Track::zero_diskstream_id_in_xml (node_copy);
+
+ try {
+ shared_ptr<Route> route (XMLRouteFactory (node_copy));
+
+ if (route == 0) {
+ error << _("Session: cannot create track/bus from template description") << endmsg;
+ goto out;
+ }
+
+ if (boost::dynamic_pointer_cast<Track>(route)) {
+ /* force input/output change signals so that the new diskstream
+ picks up the configuration of the route. During session
+ loading this normally happens in a different way.
+ */
+ route->input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
+ route->output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
+ }
+
+ route->set_remote_control_id (control_id);
+ ++control_id;
+
+ ret.push_back (route);
+ }
+
+ catch (failed_constructor &err) {
+ error << _("Session: could not create new route from template") << endmsg;
+ goto out;
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& pfe) {
+ error << pfe.what() << endmsg;
+ goto out;
+ }
+
+ --how_many;
+ }
+
+ out:
+ if (!ret.empty()) {
+ add_routes (ret, true);
+ }
+
+ return ret;
+}
+
+boost::shared_ptr<Route>
+Session::new_video_track (string name)
+{
+ uint32_t control_id = ntracks() + nbusses() + 1;
+ shared_ptr<Route> new_route (
+ new Route ( *this, name, -1, -1, -1, -1, Route::Flag(0), ARDOUR::DataType::NIL));
+ new_route->set_remote_control_id (control_id);
+
+ RouteList rl;
+ rl.push_back (new_route);
+ {
+ RCUWriter<RouteList> writer (routes);
+ shared_ptr<RouteList> r = writer.get_copy ();
+ r->insert (r->end(), rl.begin(), rl.end());
+ resort_routes_using (r);
+ }
+ return new_route;
+}
+