remove MidiPlaylist::read() API
[ardour.git] / libs / ardour / template_utils.cc
1 /*
2  * Copyright (C) 2007-2014 Tim Mayberry <mojofunk@gmail.com>
3  * Copyright (C) 2008-2015 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2009 David Robillard <d@drobilla.net>
6  * Copyright (C) 2013-2014 John Emmas <john@creativepost.co.uk>
7  * Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
8  * Copyright (C) 2017 Ben Loftis <ben@harrisonconsoles.com>
9  * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include <algorithm>
27 #include <cstring>
28
29 #include <glibmm.h>
30
31 #include "pbd/file_utils.h"
32 #include "pbd/stl_delete.h"
33 #include "pbd/xml++.h"
34
35 #include "ardour/template_utils.h"
36 #include "ardour/directory_names.h"
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/filename_extensions.h"
39 #include "ardour/search_paths.h"
40 #include "ardour/io.h"
41
42 #include "pbd/i18n.h"
43
44 using namespace std;
45 using namespace PBD;
46
47 namespace ARDOUR {
48
49 std::string
50 user_template_directory ()
51 {
52         return Glib::build_filename (user_config_directory(), templates_dir_name);
53 }
54
55 std::string
56 user_route_template_directory ()
57 {
58         return Glib::build_filename (user_config_directory(), route_templates_dir_name);
59 }
60
61 static bool
62 template_filter (const string &str, void* /*arg*/)
63 {
64         if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) {
65                 return false;
66         }
67
68         return true;
69 }
70
71 static bool
72 route_template_filter (const string &str, void* /*arg*/)
73 {
74         if (str.find (template_suffix) == str.length() - strlen (template_suffix)) {
75                 return true;
76         }
77
78         return false;
79 }
80
81 string
82 session_template_dir_to_file (string const & dir)
83 {
84         return Glib::build_filename (dir, Glib::path_get_basename(dir) + template_suffix);
85 }
86
87
88 void
89 find_session_templates (vector<TemplateInfo>& template_names, bool read_xml)
90 {
91         vector<string> templates;
92
93         find_paths_matching_filter (templates, template_search_path(), template_filter, 0, true, true);
94
95         if (templates.empty()) {
96                 cerr << "Found nothing along " << template_search_path().to_string() << endl;
97                 return;
98         }
99
100         for (vector<string>::iterator i = templates.begin(); i != templates.end(); ++i) {
101                 string file = session_template_dir_to_file (*i);
102
103                 TemplateInfo rti;
104                 rti.name = Glib::path_get_basename (*i);
105                 rti.path = *i;
106
107                 if (read_xml) {
108
109                         XMLTree tree;
110                         if (!tree.read (file.c_str())) {
111                                 cerr << "Failed to parse Route-template XML file: " << file << endl;
112                                 continue;
113                         }
114
115                         XMLNode* root = tree.root();
116                         
117                         rti.modified_with = _("(unknown)");
118                         try {
119                                 XMLNode *pv = root->child("ProgramVersion");
120                                 string modified_with;
121                                 if (pv != 0) {
122                                         pv->get_property (X_("modified-with"), modified_with);
123                                 }
124                                 rti.modified_with = modified_with;
125                         } catch (XMLException &e) {}
126
127                         rti.description = _("No Description");
128                         try {
129                                 XMLNode *desc = root->child("description");
130                                 if (desc != 0) {
131                                         rti.description = desc->attribute_value();
132                                 }
133                         } catch (XMLException &e) {}
134                 }
135
136                 template_names.push_back (rti);
137         }
138         std::sort(template_names.begin(), template_names.end());
139 }
140
141 struct TemplateInfoSorter {
142         bool operator () (TemplateInfo const& a, TemplateInfo const& b) {
143                 return a.name < b.name;
144         }
145 };
146
147 void
148 find_route_templates (vector<TemplateInfo>& template_names)
149 {
150         vector<string> templates;
151
152         find_files_matching_filter (templates, route_template_search_path(), route_template_filter, 0, false, true);
153
154         if (templates.empty()) {
155                 return;
156         }
157
158         for (vector<string>::iterator i = templates.begin(); i != templates.end(); ++i) {
159                 string fullpath = *i;
160
161                 XMLTree tree;
162
163                 if (!tree.read (fullpath.c_str())) {
164                         cerr << "Failed to parse Route-template XML file: " << fullpath << endl;
165                         continue;
166                 }
167
168                 XMLNode* root = tree.root();
169
170                 TemplateInfo rti;
171
172                 rti.modified_with = _("(unknown)");
173                 try {
174                         XMLNode *pv = root->child("ProgramVersion");
175                         string modified_with;
176                         if (pv != 0) {
177                                 pv->get_property (X_("modified-with"), modified_with);
178                         }
179                         rti.modified_with = modified_with;
180                 } catch (XMLException &e) {}
181
182                 rti.description = _("No Description");
183                 try {
184                         XMLNode *desc = root->child("description");
185                         if (desc != 0) {
186                                 rti.description = desc->attribute_value();
187                         }
188                 } catch (XMLException &e) {}
189
190                 rti.name = IO::name_from_state (*root->children().front());
191                 rti.path = fullpath;
192
193                 template_names.push_back (rti);
194         }
195
196         std::sort (template_names.begin(), template_names.end (), TemplateInfoSorter ());
197 }
198
199 }