Fix mantis 2610: bad syntax in LV2 RDF files causes crash on startup.
[ardour.git] / libs / ardour / configuration.cc
1 /*
2     Copyright (C) 1999-2006 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <unistd.h>
21 #include <cstdio> /* for snprintf, grrr */
22
23 #include <glib.h>  
24 #include <glib/gstdio.h> /* for g_stat() */
25 #include <glibmm/miscutils.h>
26
27 #include <pbd/failed_constructor.h>
28 #include <pbd/xml++.h>
29
30 #include <midi++/manager.h>
31
32 #include <ardour/ardour.h>
33 #include <ardour/configuration.h>
34 #include <ardour/audio_diskstream.h>
35 #include <ardour/control_protocol_manager.h>
36
37 #include "i18n.h"
38
39 using namespace ARDOUR;
40 using namespace std;
41 using namespace PBD;
42
43 /* this is global so that we do not have to indirect through an object pointer
44    to reference it.
45 */
46
47 namespace ARDOUR {
48     float speed_quietning = 0.251189; // -12dB reduction for ffwd or rewind
49 }
50
51 Configuration::Configuration ()
52         :
53 /* construct variables */
54 #undef  CONFIG_VARIABLE
55 #undef  CONFIG_VARIABLE_SPECIAL 
56 #define CONFIG_VARIABLE(Type,var,name,value) var (name,value),
57 #define CONFIG_VARIABLE_SPECIAL(Type,var,name,value,mutator) var (name,value,mutator),
58 #include "ardour/configuration_vars.h"
59 #undef  CONFIG_VARIABLE
60 #undef  CONFIG_VARIABLE_SPECIAL 
61
62         current_owner (ConfigVariableBase::Default)
63 {
64         _control_protocol_state = 0;
65 }
66
67 Configuration::~Configuration ()
68 {
69 }
70
71 void
72 Configuration::set_current_owner (ConfigVariableBase::Owner owner)
73 {
74         current_owner = owner;
75 }
76
77 int
78 Configuration::load_state ()
79 {
80         string rcfile;
81         struct stat statbuf;
82
83         /* load system configuration first */
84
85         rcfile = find_config_file ("ardour_system.rc");
86
87         if (rcfile.length()) {
88
89                 XMLTree tree;
90
91                 /* stupid XML Parser hates empty files */
92                 
93                 if (g_stat (rcfile.c_str(), &statbuf)) {
94                         return -1;
95                 }
96
97                 if (statbuf.st_size != 0) {
98                         cerr << string_compose (_("loading system configuration file %1"), rcfile) << endl;
99                         
100                         if (!tree.read (rcfile.c_str())) {
101                                 error << string_compose(_("Ardour: cannot read system configuration file \"%1\""), rcfile) << endmsg;
102                                 return -1;
103                         }
104                         
105                         current_owner = ConfigVariableBase::System;
106                         
107                         if (set_state (*tree.root())) {
108                                 error << string_compose(_("Ardour: system configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
109                                 return -1;
110                         }
111                 } else {
112                         error << _("your system Ardour configuration file is empty. This probably means that there as an error installing Ardour") << endmsg;
113                 }
114         }
115
116
117         /* now load configuration file for user */
118         
119         rcfile = find_config_file ("ardour.rc");
120
121         if (rcfile.length()) {
122
123                 XMLTree tree;
124
125                 /* stupid XML parser hates empty files */
126
127                 if (g_stat (rcfile.c_str(), &statbuf)) {
128                         return -1;
129                 }
130
131                 if (statbuf.st_size != 0) {
132                         cerr << string_compose (_("loading user configuration file %1"), rcfile) << endl;
133                         
134                         if (!tree.read (rcfile)) {
135                                 error << string_compose(_("Ardour: cannot read configuration file \"%1\""), rcfile) << endmsg;
136                                 return -1;
137                         }
138                         
139                         current_owner = ConfigVariableBase::Config;
140                         
141                         if (set_state (*tree.root())) {
142                                 error << string_compose(_("Ardour: user configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
143                                 return -1;
144                         }
145                 } else {
146                         warning << _("your Ardour configuration file is empty. This is not normal.") << endmsg;
147                 }       
148         }
149
150         return 0;
151 }
152
153 int
154 Configuration::save_state()
155 {
156         XMLTree tree;
157         string rcfile;
158
159         rcfile = Glib::build_filename (get_user_ardour_path (), "ardour.rc");
160
161         if (rcfile.length()) {
162                 tree.set_root (&get_state());
163                 if (!tree.write (rcfile.c_str())){
164                         error << string_compose (_("Config file %1 not saved"), rcfile) << endmsg;
165                         return -1;
166                 }
167         }
168
169         return 0;
170 }
171
172 bool
173 Configuration::save_config_options_predicate (ConfigVariableBase::Owner owner)
174 {
175         /* only save things that were in the config file to start with */
176         return owner & ConfigVariableBase::Config;
177 }
178
179 XMLNode&
180 Configuration::get_state ()
181 {
182         XMLNode* root;
183         LocaleGuard lg (X_("POSIX"));
184
185         root = new XMLNode("Ardour");
186
187         MIDI::Manager::PortMap::const_iterator i;
188         const MIDI::Manager::PortMap& ports = MIDI::Manager::instance()->get_midi_ports();
189
190         for(i = ports.begin(); i != ports.end(); ++i) {
191                 root->add_child_nocopy(i->second->get_state());
192         }
193         
194         root->add_child_nocopy (get_variables (sigc::mem_fun (*this, &Configuration::save_config_options_predicate)));
195         
196         if (_extra_xml) {
197                 root->add_child_copy (*_extra_xml);
198         }
199         
200         root->add_child_nocopy (ControlProtocolManager::instance().get_state());
201         
202         return *root;
203 }
204
205 XMLNode&
206 Configuration::get_variables (sigc::slot<bool,ConfigVariableBase::Owner> predicate)
207 {
208         XMLNode* node;
209         LocaleGuard lg (X_("POSIX"));
210
211         node = new XMLNode("Config");
212
213 #undef  CONFIG_VARIABLE
214 #undef  CONFIG_VARIABLE_SPECIAL 
215 #define CONFIG_VARIABLE(type,var,name,value) \
216          if (predicate (var.owner())) { var.add_to_node (*node); }
217 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) \
218          if (predicate (var.owner())) { var.add_to_node (*node); }
219 #include "ardour/configuration_vars.h"
220 #undef  CONFIG_VARIABLE
221 #undef  CONFIG_VARIABLE_SPECIAL 
222         
223         return *node;
224 }
225
226 int
227 Configuration::set_state (const XMLNode& root)
228 {
229         if (root.name() != "Ardour") {
230                 return -1;
231         }
232
233         XMLNodeList nlist = root.children();
234         XMLNodeConstIterator niter;
235         XMLNode *node;
236
237         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
238
239                 node = *niter;
240
241                 if (node->name() == "MIDI-port") {
242
243                         try {
244                                 MIDI::Port::Descriptor desc (*node);
245                                 map<string,XMLNode>::iterator x;
246                                 if ((x = midi_ports.find (desc.tag)) != midi_ports.end()) {
247                                         midi_ports.erase (x);
248                                 }
249                                 midi_ports.insert (pair<string,XMLNode>(desc.tag,*node));
250                         }
251
252                         catch (failed_constructor& err) {
253                                 warning << _("ill-formed MIDI port specification in ardour rcfile (ignored)") << endmsg;
254                         }
255
256                 } else if (node->name() == "Config") {
257                         
258                         set_variables (*node, ConfigVariableBase::Config);
259                         
260                 } else if (node->name() == "extra") {
261                         _extra_xml = new XMLNode (*node);
262
263                 } else if (node->name() == ControlProtocolManager::state_node_name) {
264                         _control_protocol_state = new XMLNode (*node);
265                 }
266         }
267
268         Diskstream::set_disk_io_chunk_frames (minimum_disk_io_bytes.get() / sizeof (Sample));
269
270         return 0;
271 }
272
273 void
274 Configuration::set_variables (const XMLNode& node, ConfigVariableBase::Owner owner)
275 {
276 #undef  CONFIG_VARIABLE
277 #undef  CONFIG_VARIABLE_SPECIAL 
278 #define CONFIG_VARIABLE(type,var,name,value) \
279          if (var.set_from_node (node, owner)) { \
280                  ParameterChanged (name); \
281          }
282 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) \
283          if (var.set_from_node (node, owner)) { \
284                  ParameterChanged (name); \
285          }
286 #include "ardour/configuration_vars.h"
287 #undef  CONFIG_VARIABLE
288 #undef  CONFIG_VARIABLE_SPECIAL 
289
290 }
291
292 void
293 Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
294 {
295 #undef  CONFIG_VARIABLE
296 #undef  CONFIG_VARIABLE_SPECIAL 
297 #define CONFIG_VARIABLE(type,var,name,value)                 theSlot (name);
298 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) theSlot (name);
299 #include "ardour/configuration_vars.h"
300 #undef  CONFIG_VARIABLE
301 #undef  CONFIG_VARIABLE_SPECIAL 
302 }
303
304 bool ConfigVariableBase::show_stores = false;
305
306 void
307 ConfigVariableBase::set_show_stored_values (bool yn)
308 {
309         show_stores = yn;
310 }
311
312 void
313 ConfigVariableBase::show_stored_value (const string& str)
314 {
315         if (show_stores) {
316                 cerr << "Config variable " << _name << " stored as " << str << endl;
317         }
318 }
319
320 void
321 ConfigVariableBase::notify ()
322 {
323         // placeholder for any debugging desired when a config variable is modified
324 }
325
326 void
327 ConfigVariableBase::miss ()
328 {
329         // placeholder for any debugging desired when a config variable 
330         // is set but to the same value as it already has
331 }
332