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