change several startup messages to be triggered only by -D (debug) options
[ardour.git] / libs / ardour / control_protocol_manager.cc
1 /*
2     Copyright (C) 2000-2007 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 <dlfcn.h>
21
22 #include "pbd/compose.h"
23 #include "pbd/file_utils.h"
24 #include "pbd/error.h"
25
26 #include "control_protocol/control_protocol.h"
27
28 #include "ardour/debug.h"
29 #include "ardour/session.h"
30 #include "ardour/control_protocol_manager.h"
31 #include "ardour/control_protocol_search_path.h"
32
33 using namespace ARDOUR;
34 using namespace std;
35 using namespace PBD;
36
37 #include "i18n.h"
38
39 ControlProtocolManager* ControlProtocolManager::_instance = 0;
40 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
41
42 ControlProtocolManager::ControlProtocolManager ()
43 {
44
45 }
46
47 ControlProtocolManager::~ControlProtocolManager()
48 {
49         Glib::Mutex::Lock lm (protocols_lock);
50
51         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
52                 delete (*i);
53         }
54
55         control_protocols.clear ();
56
57
58         for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
59                 delete (*p);
60         }
61
62         control_protocol_info.clear();
63 }
64
65 void
66 ControlProtocolManager::set_session (Session* s)
67 {
68         SessionHandlePtr::set_session (s);
69
70         if (_session) {
71                 Glib::Mutex::Lock lm (protocols_lock);
72
73                 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
74                         if ((*i)->requested || (*i)->mandatory) {
75                                 instantiate (**i);
76                                 (*i)->requested = false;
77
78                                 if ((*i)->protocol && (*i)->state) {
79                                         (*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
80                                 }
81                         }
82                 }
83         }
84 }
85
86 void
87 ControlProtocolManager::session_going_away()
88 {
89         SessionHandlePtr::session_going_away ();
90
91         {
92                 Glib::Mutex::Lock lm (protocols_lock);
93
94                 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
95                         delete *p;
96                 }
97
98                 control_protocols.clear ();
99
100                 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
101                         // mark existing protocols as requested
102                         // otherwise the ControlProtocol instances are not recreated in set_session
103                         if ((*p)->protocol) {
104                                 (*p)->requested = true;
105                                 (*p)->protocol = 0;
106                         }
107                 }
108         }
109 }
110
111 ControlProtocol*
112 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
113 {
114         /* CALLER MUST HOLD LOCK */
115
116         if (_session == 0) {
117                 return 0;
118         }
119
120         cpi.descriptor = get_descriptor (cpi.path);
121
122         if (cpi.descriptor == 0) {
123                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
124                 return 0;
125         }
126
127         if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
128                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
129                 return 0;
130         }
131
132         control_protocols.push_back (cpi.protocol);
133
134         return cpi.protocol;
135 }
136
137 int
138 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
139 {
140         if (!cpi.protocol) {
141                 return 0;
142         }
143
144         if (!cpi.descriptor) {
145                 return 0;
146         }
147
148         if (cpi.mandatory) {
149                 return 0;
150         }
151
152         cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
153
154         {
155                 Glib::Mutex::Lock lm (protocols_lock);
156                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
157                 if (p != control_protocols.end()) {
158                         control_protocols.erase (p);
159                 } else {
160                         cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
161                 }
162         }
163
164         cpi.protocol = 0;
165         dlclose (cpi.descriptor->module);
166         return 0;
167 }
168
169 void
170 ControlProtocolManager::load_mandatory_protocols ()
171 {
172         if (_session == 0) {
173                 return;
174         }
175
176         Glib::Mutex::Lock lm (protocols_lock);
177
178         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
179                 if ((*i)->mandatory && ((*i)->protocol == 0)) {
180                         DEBUG_TRACE (DEBUG::ControlProtocols,
181                                      string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
182                         instantiate (**i);
183                 }
184         }
185 }
186
187 void
188 ControlProtocolManager::discover_control_protocols ()
189 {
190         vector<sys::path> cp_modules;
191
192         Glib::PatternSpec so_extension_pattern("*.so");
193         Glib::PatternSpec dylib_extension_pattern("*.dylib");
194
195         find_matching_files_in_search_path (control_protocol_search_path (),
196                         so_extension_pattern, cp_modules);
197
198         find_matching_files_in_search_path (control_protocol_search_path (),
199                         dylib_extension_pattern, cp_modules);
200
201         DEBUG_TRACE (DEBUG::ControlProtocols, 
202                      string_compose (_("looking for control protocols in %1"), control_protocol_search_path().to_string()));
203         
204         for (vector<sys::path>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
205                 control_protocol_discover ((*i).to_string());
206         }
207 }
208
209 int
210 ControlProtocolManager::control_protocol_discover (string path)
211 {
212         ControlProtocolDescriptor* descriptor;
213
214         if ((descriptor = get_descriptor (path)) != 0) {
215
216                 if (!descriptor->probe (descriptor)) {
217                         DEBUG_TRACE (DEBUG::ControlProtocols,
218                                      string_compose (_("Control protocol %1 not usable"), descriptor->name));
219                 } else {
220
221                         ControlProtocolInfo* cpi = new ControlProtocolInfo ();
222
223                         cpi->descriptor = descriptor;
224                         cpi->name = descriptor->name;
225                         cpi->path = path;
226                         cpi->protocol = 0;
227                         cpi->requested = false;
228                         cpi->mandatory = descriptor->mandatory;
229                         cpi->supports_feedback = descriptor->supports_feedback;
230                         cpi->state = 0;
231
232                         control_protocol_info.push_back (cpi);
233
234                         DEBUG_TRACE (DEBUG::ControlProtocols, 
235                                      string_compose(_("Control surface protocol discovered: \"%1\""), cpi->name));
236                 }
237
238                 dlclose (descriptor->module);
239         }
240
241         return 0;
242 }
243
244 ControlProtocolDescriptor*
245 ControlProtocolManager::get_descriptor (string path)
246 {
247         void *module;
248         ControlProtocolDescriptor *descriptor = 0;
249         ControlProtocolDescriptor* (*dfunc)(void);
250         const char *errstr;
251
252         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
253                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
254                 return 0;
255         }
256
257
258         dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
259
260         if ((errstr = dlerror()) != 0) {
261                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
262                 error << errstr << endmsg;
263                 dlclose (module);
264                 return 0;
265         }
266
267         descriptor = dfunc();
268         if (descriptor) {
269                 descriptor->module = module;
270         } else {
271                 dlclose (module);
272         }
273
274         return descriptor;
275 }
276
277 void
278 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
279 {
280         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
281                 method (*i);
282         }
283 }
284
285 ControlProtocolInfo*
286 ControlProtocolManager::cpi_by_name (string name)
287 {
288         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
289                 if (name == (*i)->name) {
290                         return *i;
291                 }
292         }
293         return 0;
294 }
295
296 int
297 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
298 {
299         XMLNodeList clist;
300         XMLNodeConstIterator citer;
301         XMLProperty* prop;
302
303         Glib::Mutex::Lock lm (protocols_lock);
304
305         clist = node.children();
306
307         for (citer = clist.begin(); citer != clist.end(); ++citer) {
308                 if ((*citer)->name() == X_("Protocol")) {
309
310                         prop = (*citer)->property (X_("active"));
311
312                         if (prop && string_is_affirmative (prop->value())) {
313                                 if ((prop = (*citer)->property (X_("name"))) != 0) {
314                                         ControlProtocolInfo* cpi = cpi_by_name (prop->value());
315                                         if (cpi) {
316                                                 if (!(*citer)->children().empty()) {
317                                                         cpi->state = (*citer)->children().front ();
318                                                 } else {
319                                                         cpi->state = 0;
320                                                 }
321
322                                                 if (_session) {
323                                                         instantiate (*cpi);
324                                                 } else {
325                                                         cpi->requested = true;
326                                                 }
327                                         }
328                                 }
329                         }
330                 }
331         }
332         return 0;
333 }
334
335 XMLNode&
336 ControlProtocolManager::get_state ()
337 {
338         XMLNode* root = new XMLNode (state_node_name);
339         Glib::Mutex::Lock lm (protocols_lock);
340
341         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
342
343                 XMLNode * child;
344
345                 if ((*i)->protocol) {
346                         child = &((*i)->protocol->get_state());
347                         child->add_property (X_("active"), "yes");
348                         // should we update (*i)->state here?  probably.
349                         root->add_child_nocopy (*child);
350                 } else if ((*i)->state) {
351                         // keep ownership clear
352                         root->add_child_copy (*(*i)->state);
353                 } else {
354                         child = new XMLNode (X_("Protocol"));
355                         child->add_property (X_("name"), (*i)->name);
356                         child->add_property (X_("active"), "no");
357                         root->add_child_nocopy (*child);
358                 }
359         }
360
361         return *root;
362 }
363
364 void
365 ControlProtocolManager::set_protocol_states (const XMLNode& node)
366 {
367         XMLNodeList nlist;
368         XMLNodeConstIterator niter;
369         XMLProperty* prop;
370
371         nlist = node.children();
372
373         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
374
375                 XMLNode* child = (*niter);
376
377                 if ((prop = child->property ("name")) == 0) {
378                         error << _("control protocol XML node has no name property. Ignored.") << endmsg;
379                         continue;
380                 }
381
382                 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
383
384                 if (!cpi) {
385                         warning << string_compose (_("control protocol \"%1\" is not known. Ignored"), prop->value()) << endmsg;
386                         continue;
387                 }
388
389                 /* copy the node so that ownership is clear */
390
391                 cpi->state = new XMLNode (*child);
392         }
393 }
394
395 ControlProtocolManager&
396 ControlProtocolManager::instance ()
397 {
398         if (_instance == 0) {
399                 _instance = new ControlProtocolManager ();
400         }
401
402         return *_instance;
403 }