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