2 Copyright (C) 2008 Paul Davis
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <ardour/audio_track_importer.h>
23 #include <ardour/audio_playlist_importer.h>
24 #include <ardour/session.h>
26 #include <pbd/failed_constructor.h>
27 #include <pbd/convert.h>
34 using namespace ARDOUR;
36 /*** AudioTrackImportHandler ***/
38 AudioTrackImportHandler::AudioTrackImportHandler (XMLTree const & source, Session & session, AudioPlaylistImportHandler & pl_handler) :
39 ElementImportHandler (source, session),
40 pl_handler (pl_handler)
42 XMLNode const * root = source.root();
43 XMLNode const * routes;
45 if (!(routes = root->child ("Routes"))) {
46 throw failed_constructor();
49 XMLNodeList const & route_list = routes->children();
50 for (XMLNodeList::const_iterator it = route_list.begin(); it != route_list.end(); ++it) {
51 const XMLProperty* type = (*it)->property("default-type");
52 if ( (!type || type->value() == "audio") && ((*it)->property ("diskstream") != 0 || (*it)->property ("diskstream-id") != 0)) {
54 elements.push_back (ElementPtr ( new AudioTrackImporter (source, session, *this, **it, pl_handler)));
55 } catch (failed_constructor err) {
63 AudioTrackImportHandler::get_info () const
65 return _("Audio Tracks");
69 /*** AudioTrackImporter ***/
71 AudioTrackImporter::AudioTrackImporter (XMLTree const & source,
73 AudioTrackImportHandler & handler,
75 AudioPlaylistImportHandler & pl_handler) :
76 ElementImporter (source, session),
77 track_handler (track_handler),
79 pl_handler (pl_handler)
83 if (!parse_route_xml ()) {
84 throw failed_constructor();
88 throw failed_constructor();
91 XMLNodeList const & controllables = node.children ("controllable");
92 for (XMLNodeList::const_iterator it = controllables.begin(); it != controllables.end(); ++it) {
93 parse_controllable (**it);
96 XMLNode * remote_control = xml_track.child ("remote_control");
97 if (remote_control && (prop = remote_control->property ("id"))) {
98 uint32_t control_id = session.ntracks() + session.nbusses() + 1;
99 prop->set_value (to_string (control_id, std::dec));
102 xml_track.remove_nodes_and_delete ("extra");
106 AudioTrackImporter::parse_route_xml ()
110 // Remove order keys, new ones will be generated
111 xml_track.remove_property ("order-keys");
113 XMLPropertyList const & props = xml_track.properties();
114 for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) {
115 string prop = (*it)->name();
116 if (!prop.compare ("default-type") || !prop.compare ("flags") ||
117 !prop.compare ("active") || !prop.compare ("muted") ||
118 !prop.compare ("soloed") || !prop.compare ("phase-invert") ||
119 !prop.compare ("denormal-protection") || !prop.compare("mute-affects-pre-fader") ||
120 !prop.compare ("mute-affects-post-fader") || !prop.compare("mute-affects-control-outs") ||
121 !prop.compare ("mute-affects-main-outs") || !prop.compare("mode")) {
123 } else if (!prop.compare("diskstream-id")) {
124 old_ds_id = (*it)->value();
125 (*it)->set_value (new_ds_id.to_s());
128 std::cerr << string_compose (X_("AudioTrackImporter: did not recognise XML-property \"%1\""), prop) << endmsg;
133 error << X_("AudioTrackImporter: did not find necessary XML-property \"diskstream-id\"") << endmsg;
141 AudioTrackImporter::parse_io ()
144 bool name_ok = false;
147 if (!(io = xml_track.child ("IO"))) {
151 XMLPropertyList const & props = io->properties();
153 for (XMLPropertyList::const_iterator it = props.begin(); it != props.end(); ++it) {
154 string prop = (*it)->name();
155 if (!prop.compare ("gain") || !prop.compare ("iolimits")) {
157 } else if (!prop.compare("name")) {
158 name = (*it)->value();
160 } else if (!prop.compare("id")) {
162 (*it)->set_value (id.to_s());
164 } else if (!prop.compare("inputs")) {
165 // TODO Let the IO class do it's thing for now...
166 } else if (!prop.compare("outputs")) {
167 // TODO Let the IO class do it's thing for now...
169 std::cerr << string_compose (X_("AudioTrackImporter: did not recognise XML-property \"%1\""), prop) << endmsg;
174 error << X_("AudioTrackImporter: did not find necessary XML-property \"name\"") << endmsg;
179 error << X_("AudioTrackImporter: did not find necessary XML-property \"id\"") << endmsg;
183 XMLNodeList const & controllables = io->children ("controllable");
184 for (XMLNodeList::const_iterator it = controllables.begin(); it != controllables.end(); ++it) {
185 parse_controllable (**it);
188 XMLNodeList const & processors = io->children ("Processor");
189 for (XMLNodeList::const_iterator it = processors.begin(); it != processors.end(); ++it) {
190 parse_processor (**it);
193 XMLNodeList const & automations = io->children ("Automation");
194 for (XMLNodeList::const_iterator it = automations.begin(); it != automations.end(); ++it) {
195 parse_automation (**it);
202 AudioTrackImporter::get_info () const
209 AudioTrackImporter::_prepare_move ()
211 /* Copy dependent playlists */
213 pl_handler.playlists_by_diskstream (old_ds_id, playlists);
215 for (PlaylistList::iterator it = playlists.begin(); it != playlists.end(); ++it) {
216 if (!(*it)->prepare_move ()) {
220 (*it)->set_diskstream (new_ds_id);
225 while (session.route_by_name (name) || !track_handler.check_name (name)) {
226 std::pair<bool, string> rename_pair = Rename (_("A playlist with this name already exists, please rename it."), name);
227 if (!rename_pair.first) {
230 name = rename_pair.second;
232 xml_track.child ("IO")->property ("name")->set_value (name);
233 track_handler.add_name (name);
240 AudioTrackImporter::_cancel_move ()
242 track_handler.remove_name (name);
248 AudioTrackImporter::_move ()
254 AudioTrackImporter::parse_processor (XMLNode & node)
256 XMLNode * automation = node.child ("Automation");
258 parse_automation (*automation);
265 AudioTrackImporter::parse_controllable (XMLNode & node)
269 if ((prop = node.property ("id"))) {
271 prop->set_value (new_id.to_s());
280 AudioTrackImporter::parse_automation (XMLNode & node)
283 XMLNodeList const & lists = node.children ("AutomationList");
284 for (XMLNodeList::const_iterator it = lists.begin(); it != lists.end(); ++it) {
287 if ((prop = (*it)->property ("id"))) {
289 prop->set_value (id.to_s());
292 if (!(*it)->name().compare ("events")) {
293 rate_convert_events (**it);
301 AudioTrackImporter::rate_convert_events (XMLNode & node)
303 if (node.children().empty()) {
307 XMLNode* content_node = node.children().front();
309 if (content_node->content().empty()) {
313 std::stringstream str (content_node->content());
314 std::ostringstream new_content;
331 new_content << rate_convert_samples (x) << ' ' << y;
335 error << X_("AudioTrackImporter: error in rate converting automation events") << endmsg;
339 content_node->set_content (new_content.str());