Merge branch 'windows' of git.ardour.org:ardour/ardour into windows
[ardour.git] / libs / ardour / export_filename.cc
1 /*
2     Copyright (C) 2008 Paul Davis
3     Author: Sakari Bergen
4
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.
9
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.
14
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.
18
19 */
20
21 #include <string>
22 #include "ardour/export_filename.h"
23
24 #include <glibmm/miscutils.h>
25 #include <glibmm/fileutils.h>
26
27 #include "pbd/xml++.h"
28 #include "pbd/convert.h"
29 #include "pbd/enumwriter.h"
30
31 #include "ardour/session.h"
32 #include "ardour/session_directory.h"
33 #include "ardour/export_timespan.h"
34 #include "ardour/export_format_specification.h"
35 #include "ardour/export_channel_configuration.h"
36 #include "ardour/utils.h"
37
38 #include "i18n.h"
39
40 using namespace PBD;
41 using namespace Glib;
42 using std::string;
43
44 namespace ARDOUR
45 {
46
47 ExportFilename::ExportFilename (Session & session) :
48   include_label (false),
49   include_session (false),
50   include_revision (false),
51   include_channel_config (false),
52   include_format_name (false),
53   include_channel (false),
54   include_timespan (true), // Include timespan name always
55   include_time (false),
56   include_date (false),
57   session (session),
58   revision (1)
59 {
60         time_t rawtime;
61         std::time (&rawtime);
62         time_struct = localtime (&rawtime);
63
64         folder = session.session_directory().export_path();
65
66         XMLNode * instant_node = session.instant_xml ("ExportFilename");
67         if (instant_node) {
68                 set_state (*instant_node);
69         }
70 }
71
72 XMLNode &
73 ExportFilename::get_state ()
74 {
75         XMLNode * node = new XMLNode ("ExportFilename");
76         XMLNode * child;
77
78         FieldPair dir = analyse_folder();
79         child = node->add_child ("Folder");
80         child->add_property ("relative", dir.first ? "true" : "false");
81         child->add_property ("path", dir.second);
82
83         add_field (node, "label", include_label, label);
84         add_field (node, "session", include_session);
85         add_field (node, "revision", include_revision);
86         add_field (node, "time", include_time, enum_2_string (time_format));
87         add_field (node, "date", include_date, enum_2_string (date_format));
88
89         XMLNode * instant_node = new XMLNode ("ExportRevision");
90         instant_node->add_property ("revision", to_string (revision, std::dec));
91         session.add_instant_xml (*instant_node);
92
93         return *node;
94 }
95
96 int
97 ExportFilename::set_state (const XMLNode & node)
98 {
99         XMLNode * child;
100         XMLProperty * prop;
101         FieldPair pair;
102
103         child = node.child ("Folder");
104         if (!child) { return -1; }
105
106         folder = "";
107
108         if ((prop = child->property ("relative"))) {
109                 if (string_is_affirmative (prop->value())) {
110                         folder = session.session_directory().root_path();
111                 }
112         }
113
114         if ((prop = child->property ("path"))) {
115                 std::string tmp;
116                 tmp = Glib::build_filename (folder, prop->value());
117                 if (!Glib::file_test (tmp, Glib::FILE_TEST_EXISTS)) {
118                         warning << string_compose (_("Existing export folder for this session (%1) does not exist - ignored"), tmp) << endmsg;
119                 } else {
120                         folder = tmp;
121                 }
122         }
123         
124         if (folder.empty()) {
125                 folder = session.session_directory().export_path();
126         }
127
128         pair = get_field (node, "label");
129         include_label = pair.first;
130         label = pair.second;
131
132         pair = get_field (node, "session");
133         include_session = pair.first;
134
135         pair = get_field (node, "revision");
136         include_revision = pair.first;
137
138         pair = get_field (node, "time");
139         include_time = pair.first;
140         time_format = (TimeFormat) string_2_enum (pair.second, time_format);
141
142         pair = get_field (node, "date");
143         include_date = pair.first;
144         date_format = (DateFormat) string_2_enum (pair.second, date_format);
145
146         XMLNode * instant_node = session.instant_xml ("ExportRevision");
147         if (instant_node && (prop = instant_node->property ("revision"))) {
148                 revision = atoi (prop->value());
149         }
150
151         return 0;
152 }
153
154 string
155 ExportFilename::get_path (ExportFormatSpecPtr format) const
156 {
157         string path;
158         bool filename_empty = true;
159
160         if (include_session) {
161                 path += filename_empty ? "" : "_";
162                 path += session.name();
163                 filename_empty = false;
164         }
165
166         if (include_label) {
167                 path += filename_empty ? "" : "_";
168                 path += label;
169                 filename_empty = false;
170         }
171
172         if (include_revision) {
173                 path += filename_empty ? "" : "_";
174                 path += "r";
175                 path += to_string (revision, std::dec);
176                 filename_empty = false;
177         }
178
179         if (include_timespan && timespan) {
180                 path += filename_empty ? "" : "_";
181                 path += timespan->name();
182                 filename_empty = false;
183         }
184
185         if (include_channel_config && channel_config) {
186                 path += filename_empty ? "" : "_";
187                 path += channel_config->name();
188                 filename_empty = false;
189         }
190
191         if (include_channel) {
192                 path += filename_empty ? "" : "_";
193                 path += "channel";
194                 path += to_string (channel, std::dec);
195                 filename_empty = false;
196         }
197
198         if (include_date) {
199                 path += filename_empty ? "" : "_";
200                 path += get_date_format_str (date_format);
201                 filename_empty = false;
202         }
203
204         if (include_time) {
205                 path += filename_empty ? "" : "_";
206                 path += get_time_format_str (time_format);
207                 filename_empty = false;
208         }
209
210         if (include_format_name) {
211                 path += filename_empty ? "" : "_";
212                 path += format->name();
213                 filename_empty = false;
214         }
215
216         path += ".";
217         path += format->extension ();
218
219         path = legalize_for_universal_path (path);
220
221         return Glib::build_filename (folder, path);
222 }
223
224 string
225 ExportFilename::get_time_format_str (TimeFormat format) const
226 {
227         switch ( format ) {
228           case T_None:
229                 return _("No Time");
230
231           case T_NoDelim:
232                 return get_formatted_time ("%H%M");
233
234           case T_Delim:
235                 return get_formatted_time ("%H.%M");
236
237           default:
238                 return _("Invalid time format");
239         }
240 }
241
242 string
243 ExportFilename::get_date_format_str (DateFormat format) const
244 {
245         switch (format) {
246           case D_None:
247                 return _("No Date");
248
249           case D_BE:
250                 return get_formatted_time ("%Y%m%d");
251
252           case D_ISO:
253                 return get_formatted_time ("%Y-%m-%d");
254
255           case D_BEShortY:
256                 return get_formatted_time ("%y%m%d");
257
258           case D_ISOShortY:
259                 return get_formatted_time ("%y-%m-%d");
260
261           default:
262                 return _("Invalid date format");
263         }
264 }
265
266 void
267 ExportFilename::set_time_format (TimeFormat format)
268 {
269         time_format = format;
270
271         if (format == T_None) {
272                 include_time = false;
273         } else {
274                 include_time = true;
275         }
276 }
277
278 void
279 ExportFilename::set_date_format (DateFormat format)
280 {
281         date_format = format;
282
283         if (format == D_None) {
284                 include_date = false;
285         } else {
286                 include_date = true;
287         }
288 }
289
290 void
291 ExportFilename::set_label (string value)
292 {
293         label = value;
294         include_label = !value.compare ("");
295 }
296
297 bool
298 ExportFilename::set_folder (string path)
299 {
300         // TODO check folder existence
301         folder = path;
302         return true;
303 }
304
305 string
306 ExportFilename::get_formatted_time (string const & format) const
307 {
308         char buffer [80];
309         strftime (buffer, 80, format.c_str(), time_struct);
310
311         string return_value (buffer);
312         return return_value;
313 }
314
315 void
316 ExportFilename::add_field (XMLNode * node, string const & name, bool enabled, string const & value)
317 {
318         XMLNode * child = node->add_child ("Field");
319
320         if (!child) {
321                 std::cerr << "Error adding a field to ExportFilename XML-tree" << std::endl;
322                 return;
323         }
324
325         child->add_property ("name", name);
326         child->add_property ("enabled", enabled ? "true" : "false");
327         if (!value.empty()) {
328                 child->add_property ("value", value);
329         }
330 }
331
332 ExportFilename::FieldPair
333 ExportFilename::get_field (XMLNode const & node, string const & name)
334 {
335         FieldPair pair;
336         pair.first = false;
337
338         XMLNodeList children = node.children();
339
340         for (XMLNodeList::iterator it = children.begin(); it != children.end(); ++it) {
341                 XMLProperty * prop = (*it)->property ("name");
342                 if (prop && !prop->value().compare (name)) {
343
344                         prop = (*it)->property ("enabled");
345                         if (prop && !prop->value().compare ("true")) {
346                                 pair.first = true;
347                         } else {
348                                 pair.first = false;
349                         }
350
351                         prop = (*it)->property ("value");
352                         if (prop) {
353                                 pair.second = prop->value();
354                         }
355
356                         return pair;
357                 }
358         }
359
360         return pair;
361 }
362
363 ExportFilename::FieldPair
364 ExportFilename::analyse_folder ()
365 {
366         FieldPair pair;
367
368         string session_dir = session.session_directory().root_path();
369         string::size_type session_dir_len = session_dir.length();
370
371         string folder_beginning = folder.substr (0, session_dir_len);
372
373         if (!folder_beginning.compare (session_dir)) {
374                 pair.first = true;
375                 pair.second = folder.substr (session_dir_len);
376         } else {
377                 pair.first = false;
378                 pair.second = folder;
379         }
380
381         return pair;
382 }
383
384 } // namespace ARDOUR