2 * Copyright (C) 2008-2010 Carl Hetherington <carl@carlh.net>
3 * Copyright (C) 2008 Sakari Bergen <sakari.bergen@beatwaves.net>
4 * Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
5 * Copyright (C) 2009-2017 Paul Davis <paul@linuxaudiosystems.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "ardour/location_importer.h"
27 #include "ardour/session.h"
28 #include "pbd/convert.h"
29 #include "pbd/failed_constructor.h"
35 using namespace ARDOUR;
38 LocationImportHandler::LocationImportHandler (XMLTree const & source, Session & session) :
39 ElementImportHandler (source, session)
41 XMLNode const *root = source.root();
42 XMLNode const * location_node;
44 if (!(location_node = root->child ("Locations"))) {
45 throw failed_constructor();
48 // Construct importable locations
49 XMLNodeList const & locations = location_node->children();
50 for (XMLNodeList::const_iterator it = locations.begin(); it != locations.end(); ++it) {
52 elements.push_back (ElementPtr ( new LocationImporter (source, session, *this, **it)));
53 } catch (failed_constructor const&) {
60 LocationImportHandler::get_info () const
62 return _("Locations");
65 /*** LocationImporter ***/
66 LocationImporter::LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node) :
67 ElementImporter (source, session),
74 XMLPropertyList props = xml_location.properties();
76 for (XMLPropertyIterator it = props.begin(); it != props.end(); ++it) {
77 string prop = (*it)->name();
78 if (!prop.compare ("id") || !prop.compare ("flags") || !prop.compare ("locked")) {
80 } else if (!prop.compare ("start") || !prop.compare ("end")) {
81 // Sample rate conversion
82 (*it)->set_value (rate_convert_samples ((*it)->value()));
83 } else if (!prop.compare ("name")) {
84 // rename region if necessary
85 name = (*it)->value();
88 std::cerr << string_compose (X_("LocationImporter did not recognise XML-property \"%1\""), prop) << endmsg;
93 error << X_("LocationImporter did not find necessary XML-property \"name\"") << endmsg;
94 throw failed_constructor();
98 LocationImporter::~LocationImporter ()
106 LocationImporter::get_info () const
108 samplepos_t start, end;
109 Timecode::Time start_time, end_time;
111 // Get sample positions
112 std::istringstream iss_start (xml_location.property ("start")->value());
114 std::istringstream iss_end (xml_location.property ("end")->value());
117 // Convert to timecode
118 session.sample_to_timecode (start, start_time, true, false);
119 session.sample_to_timecode (end, end_time, true, false);
122 std::ostringstream oss;
124 oss << _("Location: ") << timecode_to_string (start_time);
126 oss << _("Range\nstart: ") << timecode_to_string (start_time) <<
127 _("\nend: ") << timecode_to_string (end_time);
134 LocationImporter::_prepare_move ()
137 Location const original (session, xml_location);
138 location = new Location (original); // Updates id
139 } catch (failed_constructor& err) {
140 throw std::runtime_error (X_("Error in session file!"));
144 std::pair<bool, string> rename_pair;
146 if (location->is_auto_punch()) {
147 rename_pair = *Rename (_("The location is the Punch range. It will be imported as a normal range.\nYou may rename the imported location:"), name);
148 if (!rename_pair.first) {
152 name = rename_pair.second;
153 location->set_auto_punch (false, this);
154 location->set_is_range_marker (true, this);
157 if (location->is_auto_loop()) {
158 rename_pair = *Rename (_("The location is a Loop range. It will be imported as a normal range.\nYou may rename the imported location:"), name);
159 if (!rename_pair.first) { return false; }
161 location->set_auto_loop (false, this);
162 location->set_is_range_marker (true, this);
165 // duplicate name checking
166 Locations::LocationList const & locations(session.locations()->list());
167 for (Locations::LocationList::const_iterator it = locations.begin(); it != locations.end(); ++it) {
168 if (!((*it)->name().compare (location->name())) || !handler.check_name (location->name())) {
169 rename_pair = *Rename (_("A location with that name already exists.\nYou may rename the imported location:"), name);
170 if (!rename_pair.first) { return false; }
171 name = rename_pair.second;
175 location->set_name (name);
181 LocationImporter::_cancel_move ()
188 LocationImporter::_move ()
190 session.locations()->add (location);