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