the return of VST support
[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     $Id$
19 */
20
21 #include <unistd.h>
22 #include <cstdio> /* for snprintf, grrr */
23
24 #include <pbd/failed_constructor.h>
25 #include <pbd/xml++.h>
26
27 #include <ardour/ardour.h>
28 #include <ardour/configuration.h>
29 #include <ardour/audio_diskstream.h>
30 #include <ardour/destructive_filesource.h>
31 #include <ardour/control_protocol_manager.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         user_configuration (false)
59 {
60         _control_protocol_state = 0;
61 }
62
63 Configuration::~Configuration ()
64 {
65 }
66
67 int
68 Configuration::load_state ()
69 {
70         string rcfile;
71         
72         /* load system configuration first */
73
74         rcfile = find_config_file ("ardour_system.rc");
75
76         if (rcfile.length()) {
77
78                 XMLTree tree;
79
80                 cerr << string_compose (_("loading system configuration file %1"), rcfile) << endl;
81                 
82                 if (!tree.read (rcfile.c_str())) {
83                         error << string_compose(_("Ardour: cannot read system configuration file \"%1\""), rcfile) << endmsg;
84                         return -1;
85                 }
86
87                 if (set_state (*tree.root())) {
88                         error << string_compose(_("Ardour: system configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
89                         return -1;
90                 }
91         }
92
93         /* from this point on, all configuration changes are user driven */
94
95         user_configuration = true;
96
97         /* now load configuration file for user */
98         
99         rcfile = find_config_file ("ardour.rc");
100
101         if (rcfile.length()) {
102
103                 XMLTree tree;
104                 
105                 cerr << string_compose (_("loading user configuration file %1"), rcfile) << endl;
106
107                 if (!tree.read (rcfile)) {
108                         error << string_compose(_("Ardour: cannot read configuration file \"%1\""), rcfile) << endmsg;
109                         return -1;
110                 }
111
112                 if (set_state (*tree.root())) {
113                         error << string_compose(_("Ardour: user configuration file \"%1\" not loaded successfully."), rcfile) << endmsg;
114                         return -1;
115                 }
116         }
117
118         return 0;
119 }
120
121 int
122 Configuration::save_state()
123 {
124         XMLTree tree;
125         string rcfile;
126
127         /* Note: this only writes the per-user file, and therefore
128            only saves variables marked as user-set or modified
129         */
130
131         rcfile = get_user_ardour_path ();
132         rcfile += "ardour.rc";
133
134         if (rcfile.length()) {
135                 tree.set_root (&state (true));
136                 if (!tree.write (rcfile.c_str())){
137                         error << string_compose (_("Config file %1 not saved"), rcfile) << endmsg;
138                         return -1;
139                 }
140         }
141
142         return 0;
143 }
144
145 XMLNode&
146 Configuration::get_state ()
147 {
148         return state (false);
149 }
150
151 XMLNode&
152 Configuration::state (bool user_only)
153 {
154         XMLNode* root = new XMLNode("Ardour");
155         LocaleGuard lg (X_("POSIX"));
156
157         typedef map<string, MidiPortDescriptor*>::const_iterator CI;
158         for(CI m = midi_ports.begin(); m != midi_ports.end(); ++m){
159                 root->add_child_nocopy(m->second->get_state());
160         }
161
162         XMLNode* node = new XMLNode("Config");
163         
164 #undef  CONFIG_VARIABLE
165 #undef  CONFIG_VARIABLE_SPECIAL 
166 #define CONFIG_VARIABLE(type,var,name,value) \
167          if (!user_only || var.is_user()) var.add_to_node (*node);
168 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) \
169          if (!user_only || var.is_user()) var.add_to_node (*node);
170 #include "ardour/configuration_vars.h"
171 #undef  CONFIG_VARIABLE
172 #undef  CONFIG_VARIABLE_SPECIAL 
173
174         root->add_child_nocopy (*node);
175
176         if (_extra_xml) {
177                 root->add_child_copy (*_extra_xml);
178         }
179
180         root->add_child_nocopy (ControlProtocolManager::instance().get_state());
181
182         return *root;
183 }
184
185 int
186 Configuration::set_state (const XMLNode& root)
187 {
188         if (root.name() != "Ardour") {
189                 return -1;
190         }
191
192         XMLNodeList nlist = root.children();
193         XMLNodeConstIterator niter;
194         XMLNode *node;
195
196         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
197
198                 node = *niter;
199
200                 if (node->name() == "MIDI-port") {
201
202                         try {
203                                 pair<string,MidiPortDescriptor*> newpair;
204                                 newpair.second = new MidiPortDescriptor (*node);
205                                 newpair.first = newpair.second->tag;
206                                 midi_ports.insert (newpair);
207                         }
208
209                         catch (failed_constructor& err) {
210                                 warning << _("ill-formed MIDI port specification in ardour rcfile (ignored)") << endmsg;
211                         }
212
213                 } else if (node->name() == "Config") {
214
215 #undef  CONFIG_VARIABLE
216 #undef  CONFIG_VARIABLE_SPECIAL 
217 #define CONFIG_VARIABLE(type,var,name,value) \
218          var.set_from_node (*node); \
219          var.set_is_user (user_configuration);
220 #define CONFIG_VARIABLE_SPECIAL(type,var,name,value,mutator) \
221          var.set_from_node (*node); \
222          var.set_is_user (user_configuration);
223 #include "ardour/configuration_vars.h"
224 #undef  CONFIG_VARIABLE
225 #undef  CONFIG_VARIABLE_SPECIAL 
226                         
227                 } else if (node->name() == "extra") {
228                         _extra_xml = new XMLNode (*node);
229
230                 } else if (node->name() == ControlProtocolManager::state_node_name) {
231                         _control_protocol_state = new XMLNode (*node);
232                 }
233         }
234
235         AudioDiskstream::set_disk_io_chunk_frames (minimum_disk_io_bytes.get() / sizeof (Sample));
236
237         return 0;
238 }
239
240 Configuration::MidiPortDescriptor::MidiPortDescriptor (const XMLNode& node)
241 {
242         const XMLProperty *prop;
243         bool have_tag = false;
244         bool have_device = false;
245         bool have_type = false;
246         bool have_mode = false;
247
248         if ((prop = node.property ("tag")) != 0) {
249                 tag = prop->value();
250                 have_tag = true;
251         }
252
253         if ((prop = node.property ("device")) != 0) {
254                 device = prop->value();
255                 have_device = true;
256         }
257
258         if ((prop = node.property ("type")) != 0) {
259                 type = prop->value();
260                 have_type = true;
261         }
262
263         if ((prop = node.property ("mode")) != 0) {
264                 mode = prop->value();
265                 have_mode = true;
266         }
267
268         if (!have_tag || !have_device || !have_type || !have_mode) {
269                 throw failed_constructor();
270         }
271 }
272
273 XMLNode&
274 Configuration::MidiPortDescriptor::get_state()
275 {
276         XMLNode* root = new XMLNode("MIDI-port");
277
278         root->add_property("tag", tag);
279         root->add_property("device", device);
280         root->add_property("type", type);
281         root->add_property("mode", mode);
282
283         return *root;
284 }
285