second (and hopefully) final part of changes to respond to header format changes...
[ArdourMidi.git] / libs / ardour / location_importer.cc
blob8d6af300ca597d746dc2a7f0a4a9067323f988a7
1 /*
2 Copyright (C) 2008 Paul Davis
3 Author: Sakari Bergen
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/location_importer.h"
23 #include <sstream>
24 #include <stdexcept>
26 #include "ardour/session.h"
27 #include "pbd/convert.h"
28 #include "pbd/failed_constructor.h"
30 #include "i18n.h"
32 using namespace std;
33 using namespace PBD;
34 using namespace ARDOUR;
36 /**** Handler ***/
37 LocationImportHandler::LocationImportHandler (XMLTree const & source, Session & session) :
38 ElementImportHandler (source, session)
40 XMLNode const *root = source.root();
41 XMLNode const * location_node;
43 if (!(location_node = root->child ("Locations"))) {
44 throw failed_constructor();
47 // Construct importable locations
48 XMLNodeList const & locations = location_node->children();
49 for (XMLNodeList::const_iterator it = locations.begin(); it != locations.end(); ++it) {
50 try {
51 elements.push_back (ElementPtr ( new LocationImporter (source, session, *this, **it)));
52 } catch (failed_constructor err) {
53 _dirty = true;
58 string
59 LocationImportHandler::get_info () const
61 return _("Locations");
64 /*** LocationImporter ***/
65 LocationImporter::LocationImporter (XMLTree const & source, Session & session, LocationImportHandler & handler, XMLNode const & node) :
66 ElementImporter (source, session),
67 handler (handler),
68 xml_location (node),
69 location (0)
71 // Parse XML
72 bool name_ok = false;
73 XMLPropertyList props = xml_location.properties();
75 for (XMLPropertyIterator it = props.begin(); it != props.end(); ++it) {
76 string prop = (*it)->name();
77 if (!prop.compare ("id") || !prop.compare ("flags") || !prop.compare ("locked")) {
78 // All ok
79 } else if (!prop.compare ("start") || !prop.compare ("end")) {
80 // Sample rate conversion
81 (*it)->set_value (rate_convert_samples ((*it)->value()));
82 } else if (!prop.compare ("name")) {
83 // rename region if necessary
84 name = (*it)->value();
85 name_ok = true;
86 } else {
87 std::cerr << string_compose (X_("LocationImporter did not recognise XML-property \"%1\""), prop) << endmsg;
91 if (!name_ok) {
92 error << X_("LocationImporter did not find necessary XML-property \"name\"") << endmsg;
93 throw failed_constructor();
97 LocationImporter::~LocationImporter ()
99 if (!queued()) {
100 delete location;
104 string
105 LocationImporter::get_info () const
107 nframes_t start, end;
108 Timecode::Time start_time, end_time;
110 // Get sample positions
111 std::istringstream iss_start (xml_location.property ("start")->value());
112 iss_start >> start;
113 std::istringstream iss_end (xml_location.property ("end")->value());
114 iss_end >> end;
116 // Convert to timecode
117 session.sample_to_timecode (start, start_time, true, false);
118 session.sample_to_timecode (end, end_time, true, false);
120 // return info
121 std::ostringstream oss;
122 if (start == end) {
123 oss << _("Location: ") << timecode_to_string (start_time);
124 } else {
125 oss << _("Range\nstart: ") << timecode_to_string (start_time) <<
126 _("\nend: ") << timecode_to_string (end_time);
129 return oss.str();
132 bool
133 LocationImporter::_prepare_move ()
135 try {
136 Location const original (xml_location);
137 location = new Location (original); // Updates id
138 } catch (failed_constructor& err) {
139 throw std::runtime_error (X_("Error in session file!"));
140 return false;
143 std::pair<bool, string> rename_pair;
145 if (location->is_auto_punch()) {
146 rename_pair = *Rename (_("The location is the Punch range. It will be imported as a normal range.\nYou may rename the imported location:"), name);
147 if (!rename_pair.first) {
148 return false;
151 name = rename_pair.second;
152 location->set_auto_punch (false, this);
153 location->set_is_range_marker (true, this);
156 if (location->is_auto_loop()) {
157 rename_pair = *Rename (_("The location is a Loop range. It will be imported as a normal range.\nYou may rename the imported location:"), name);
158 if (!rename_pair.first) { return false; }
160 location->set_auto_loop (false, this);
161 location->set_is_range_marker (true, this);
164 // duplicate name checking
165 Locations::LocationList const & locations(session.locations()->list());
166 for (Locations::LocationList::const_iterator it = locations.begin(); it != locations.end(); ++it) {
167 if (!((*it)->name().compare (location->name())) || !handler.check_name (location->name())) {
168 rename_pair = *Rename (_("A location with that name already exists.\nYou may rename the imported location:"), name);
169 if (!rename_pair.first) { return false; }
170 name = rename_pair.second;
174 location->set_name (name);
176 return true;
179 void
180 LocationImporter::_cancel_move ()
182 delete location;
183 location = 0;
186 void
187 LocationImporter::_move ()
189 session.locations()->add (location);