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