Use PBD::sys::path and SessionDirectory in Session::remove_pending_capture_state...
[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 <pbd/failed_constructor.h>
24 #include <pbd/xml++.h>
25 #include <pbd/filesystem.h>
26 #include <pbd/file_utils.h>
27
28 #include <ardour/configuration.h>
29 #include <ardour/audio_diskstream.h>
30 #include <ardour/control_protocol_manager.h>
31 #include <ardour/filesystem_paths.h>
32
33 #include "i18n.h"
34
35 using namespace ARDOUR;
36 using namespace std;
37 using namespace PBD;
38
39 /* this is global so that we do not have to indirect through an object pointer
40    to reference it.
41 */
42
43 namespace ARDOUR {
44     float speed_quietning = 0.251189; // -12dB reduction for ffwd or rewind
45 }
46
47 Configuration::Configuration ()
48         :
49 /* construct variables */
50 #undef  CONFIG_VARIABLE
51 #undef  CONFIG_VARIABLE_SPECIAL 
52 #define CONFIG_VARIABLE(Type,var,name,value) var (name,value),
53 #define CONFIG_VARIABLE_SPECIAL(Type,var,name,value,mutator) var (name,value,mutator),
54 #include "ardour/configuration_vars.h"
55 #undef  CONFIG_VARIABLE
56 #undef  CONFIG_VARIABLE_SPECIAL
57
58
59         current_owner (ConfigVariableBase::Default)
60 {
61         _control_protocol_state = 0;
62 }
63
64 Configuration::~Configuration ()
65 {
66 }
67
68 void
69 Configuration::set_current_owner (ConfigVariableBase::Owner owner)
70 {
71         current_owner = owner;
72 }
73
74 int
75 Configuration::load_state ()
76 {
77         bool found = false;
78
79         sys::path system_rc_file;
80         
81         /* load system configuration first */
82         
83         if ( find_file_in_search_path (ardour_search_path() + system_config_search_path(),
84                         "ardour_system.rc", system_rc_file) )
85         {
86                 XMLTree tree;
87                 found = true;
88
89                 string rcfile = system_rc_file.to_string();
90
91                 cerr << string_compose (_("loading system configuration file %1"), rcfile) << endl;
92                 
93                 if (!tree.read (rcfile.c_str())) {
94                         error << string_compose(_("Ardour: cannot read system configuration file \"%1\""), rcfile) << endmsg;
95                         return -1;
96                 }
97
98                 current_owner = ConfigVariableBase::System;
99
100                 if (set_state (*tree.root())) {
101                         error << string_compose(_("Ardour: system configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
102                         return -1;
103                 }
104         }
105
106         /* now load configuration file for user */
107
108         sys::path user_rc_file;
109
110         if (find_file_in_search_path (ardour_search_path() + user_config_directory(),
111                         "ardour.rc", user_rc_file))
112         {
113                 XMLTree tree;
114                 found = true;
115         
116                 string rcfile = user_rc_file.to_string();
117
118                 cerr << string_compose (_("loading user configuration file %1"), rcfile) << endl;
119
120                 if (!tree.read (rcfile)) {
121                         error << string_compose(_("Ardour: cannot read configuration file \"%1\""), rcfile) << endmsg;
122                         return -1;
123                 }
124
125                 current_owner = ConfigVariableBase::Config;
126
127                 if (set_state (*tree.root())) {
128                         error << string_compose(_("Ardour: user configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
129                         return -1;
130                 }
131         }
132
133         if (!found)
134                 error << "Ardour: could not find configuration file (ardour.rc), canvas will look broken." << endmsg;
135
136         return 0;
137 }
138
139 int
140 Configuration::save_state()
141 {
142         XMLTree tree;
143
144         try
145         {
146                 sys::create_directories (user_config_directory ());
147         }
148         catch (const sys::filesystem_error& ex)
149         {
150                 error << "Could not create user configuration directory" << endmsg;
151                 return -1;
152         }
153         
154         sys::path rcfile_path(user_config_directory());
155
156         rcfile_path /= "ardour.rc";
157         const string rcfile = rcfile_path.to_string();
158
159         // this test seems bogus?
160         if (rcfile.length()) {
161                 tree.set_root (&get_state());
162                 if (!tree.write (rcfile.c_str())){
163                         error << string_compose (_("Config file %1 not saved"), rcfile) << endmsg;
164                         return -1;
165                 }
166         }
167
168         return 0;
169 }
170
171 void
172 Configuration::add_instant_xml(XMLNode& node)
173 {
174         Stateful::add_instant_xml (node, user_config_directory ());
175 }
176
177 XMLNode*
178 Configuration::instant_xml(const string& node_name)
179 {
180         return Stateful::instant_xml (node_name, user_config_directory ());
181 }
182
183
184 bool
185 Configuration::save_config_options_predicate (ConfigVariableBase::Owner owner)
186 {
187         /* only save things that were in the config file to start with */
188         return owner & ConfigVariableBase::Config;
189 }
190
191 XMLNode&
192 Configuration::get_state ()
193 {
194         XMLNode* root;
195         LocaleGuard lg (X_("POSIX"));
196
197         root = new XMLNode("Ardour");
198         typedef map<string, MidiPortDescriptor*>::const_iterator CI;
199         for(CI m = midi_ports.begin(); m != midi_ports.end(); ++m){
200                 root->add_child_nocopy(m->second->get_state());
201         }
202         
203         root->add_child_nocopy (get_variables (sigc::mem_fun (*this, &Configuration::save_config_options_predicate), "Config"));
204         
205         if (_extra_xml) {
206                 root->add_child_copy (*_extra_xml);
207         }
208         
209         root->add_child_nocopy (ControlProtocolManager::instance().get_state());
210         
211         return *root;
212 }
213
214 XMLNode&
215 Configuration::get_variables (sigc::slot<bool,ConfigVariableBase::Owner> predicate, std::string which_node)
216 {
217         XMLNode* node;
218         LocaleGuard lg (X_("POSIX"));
219
220         node = new XMLNode(which_node);
221
222 #undef  CONFIG_VARIABLE
223 #undef  CONFIG_VARIABLE_SPECIAL 
224 #define CONFIG_VARIABLE(type,var,Name,value) \
225          if (node->name() == "Config") { if (predicate (var.owner())) { var.add_to_node (*node); }}
226 #define CONFIG_VARIABLE_SPECIAL(type,var,Name,value,mutator) \
227          if (node->name() == "Config") { if (predicate (var.owner())) { var.add_to_node (*node); }}
228 #include "ardour/configuration_vars.h"
229 #undef  CONFIG_VARIABLE
230 #undef  CONFIG_VARIABLE_SPECIAL 
231
232         return *node;
233 }
234
235 int
236 Configuration::set_state (const XMLNode& root)
237 {
238         if (root.name() != "Ardour") {
239                 return -1;
240         }
241
242         XMLNodeList nlist = root.children();
243         XMLNodeConstIterator niter;
244         XMLNode *node;
245
246         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
247
248                 node = *niter;
249
250                 if (node->name() == "MIDI-port") {
251
252                         try {
253                                 pair<string,MidiPortDescriptor*> newpair;
254                                 newpair.second = new MidiPortDescriptor (*node);
255                                 newpair.first = newpair.second->tag;
256                                 midi_ports.insert (newpair);
257                         }
258
259                         catch (failed_constructor& err) {
260                                 warning << _("ill-formed MIDI port specification in ardour rcfile (ignored)") << endmsg;
261                         }
262
263                 } else if (node->name() == "Config") {
264                         
265                         set_variables (*node, ConfigVariableBase::Config);
266                         
267                 } else if (node->name() == "extra") {
268                         _extra_xml = new XMLNode (*node);
269
270                 } else if (node->name() == ControlProtocolManager::state_node_name) {
271                         _control_protocol_state = new XMLNode (*node);
272                 }
273         }
274
275         Diskstream::set_disk_io_chunk_frames (minimum_disk_io_bytes.get() / sizeof (Sample));
276
277         return 0;
278 }
279
280 void
281 Configuration::set_variables (const XMLNode& node, ConfigVariableBase::Owner owner)
282 {
283 #undef  CONFIG_VARIABLE
284 #undef  CONFIG_VARIABLE_SPECIAL 
285 #define CONFIG_VARIABLE(type,var,name,value) \
286          if (var.set_from_node (node, owner)) { \
287                  ParameterChanged (name); \
288          }
289 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) \
290          if (var.set_from_node (node, owner)) { \
291                  ParameterChanged (name); \
292          }
293
294 #include "ardour/configuration_vars.h"
295 #undef  CONFIG_VARIABLE
296 #undef  CONFIG_VARIABLE_SPECIAL
297         
298 }
299
300 Configuration::MidiPortDescriptor::MidiPortDescriptor (const XMLNode& node)
301 {
302         const XMLProperty *prop;
303         bool have_tag = false;
304         bool have_device = false;
305         bool have_type = false;
306         bool have_mode = false;
307
308         if ((prop = node.property ("tag")) != 0) {
309                 tag = prop->value();
310                 have_tag = true;
311         }
312
313         if ((prop = node.property ("device")) != 0) {
314                 device = prop->value();
315                 have_device = true;
316         }
317
318         if ((prop = node.property ("type")) != 0) {
319                 type = prop->value();
320                 have_type = true;
321         }
322
323         if ((prop = node.property ("mode")) != 0) {
324                 mode = prop->value();
325                 have_mode = true;
326         }
327
328         if (!have_tag || !have_device || !have_type || !have_mode) {
329                 throw failed_constructor();
330         }
331 }
332
333 XMLNode&
334 Configuration::MidiPortDescriptor::get_state()
335 {
336         XMLNode* root = new XMLNode("MIDI-port");
337
338         root->add_property("tag", tag);
339         root->add_property("device", device);
340         root->add_property("type", type);
341         root->add_property("mode", mode);
342
343         return *root;
344 }
345
346 void
347 Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
348 {
349 #undef  CONFIG_VARIABLE
350 #undef  CONFIG_VARIABLE_SPECIAL 
351 #define CONFIG_VARIABLE(type,var,name,value)                 theSlot (name);
352 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) theSlot (name);
353 #include "ardour/configuration_vars.h"
354 #undef  CONFIG_VARIABLE
355 #undef  CONFIG_VARIABLE_SPECIAL 
356 }
357
358 bool ConfigVariableBase::show_stores = false;
359
360 void
361 ConfigVariableBase::set_show_stored_values (bool yn)
362 {
363         show_stores = yn;
364 }
365
366 void
367 ConfigVariableBase::show_stored_value (const string& str)
368 {
369         if (show_stores) {
370                 cerr << "Config variable " << _name << " stored as " << str << endl;
371         }
372 }
373
374 void
375 ConfigVariableBase::notify ()
376 {
377         // placeholder for any debugging desired when a config variable is modified
378 }
379
380 void
381 ConfigVariableBase::miss ()
382 {
383         // placeholder for any debugging desired when a config variable 
384         // is set but to the same value as it already has
385 }
386