Merge branch 'master' into cairocanvas
[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 <glibmm/module.h>
21
22 #include <glibmm/fileutils.h>
23
24 #include "pbd/compose.h"
25 #include "pbd/file_utils.h"
26 #include "pbd/error.h"
27
28 #include "control_protocol/control_protocol.h"
29
30 #include "ardour/debug.h"
31 #include "ardour/control_protocol_manager.h"
32
33 #include "ardour/control_protocol_search_path.h"
34
35
36 using namespace ARDOUR;
37 using namespace std;
38 using namespace PBD;
39
40 #include "i18n.h"
41
42 ControlProtocolManager* ControlProtocolManager::_instance = 0;
43 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
44
45 ControlProtocolManager::ControlProtocolManager ()
46 {
47 }
48
49 ControlProtocolManager::~ControlProtocolManager()
50 {
51         Glib::Threads::Mutex::Lock lm (protocols_lock);
52
53         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
54                 delete (*i);
55         }
56
57         control_protocols.clear ();
58
59
60         for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
61                 delete (*p);
62         }
63
64         control_protocol_info.clear();
65 }
66
67 void
68 ControlProtocolManager::set_session (Session* s)
69 {
70         SessionHandlePtr::set_session (s);
71
72         if (_session) {
73                 Glib::Threads::Mutex::Lock lm (protocols_lock);
74
75                 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
76                         if ((*i)->requested || (*i)->mandatory) {
77                                 (void) activate (**i);
78                         }
79                 }
80         }
81 }
82
83 int
84 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
85 {
86         ControlProtocol* cp;
87
88         cpi.requested = true;
89
90         if ((cp = instantiate (cpi)) == 0) {
91                 return -1;
92         }
93
94         /* we split the set_state() and set_active() operations so that
95            protocols that need state to configure themselves (e.g. "What device
96            is connected, or supposed to be connected?") can get it before
97            actually starting any interaction.
98         */
99
100         if (cpi.state) {
101                 /* force this by tweaking the internals of the state
102                  * XMLNode. Ugh.
103                  */
104                 cp->set_state (*cpi.state, Stateful::loading_state_version);
105         } else {
106                 /* guarantee a call to
107                    set_state() whether we have
108                    existing state or not
109                 */
110                 cp->set_state (XMLNode(""), Stateful::loading_state_version);
111         }
112
113         cp->set_active (true);
114
115         return 0;
116 }       
117
118 int
119 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
120 {
121         cpi.requested = false;
122         return teardown (cpi);
123 }
124
125 void
126 ControlProtocolManager::session_going_away()
127 {
128         SessionHandlePtr::session_going_away ();
129
130         {
131                 Glib::Threads::Mutex::Lock lm (protocols_lock);
132
133                 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
134                         delete *p;
135                 }
136
137                 control_protocols.clear ();
138
139                 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
140                         // mark existing protocols as requested
141                         // otherwise the ControlProtocol instances are not recreated in set_session
142                         if ((*p)->protocol) {
143                                 (*p)->requested = true;
144                                 (*p)->protocol = 0;
145                         }
146                 }
147         }
148 }
149
150 ControlProtocol*
151 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
152 {
153         /* CALLER MUST HOLD LOCK */
154
155         if (_session == 0) {
156                 return 0;
157         }
158
159         cpi.descriptor = get_descriptor (cpi.path);
160
161         DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
162
163         if (cpi.descriptor == 0) {
164                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
165                 return 0;
166         }
167
168         DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
169
170         if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
171                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
172                 return 0;
173         }
174
175         control_protocols.push_back (cpi.protocol);
176
177         ProtocolStatusChange (&cpi);
178
179         return cpi.protocol;
180 }
181
182 int
183 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
184 {
185         if (!cpi.protocol) {
186                 return 0;
187         }
188
189         if (!cpi.descriptor) {
190                 return 0;
191         }
192
193         if (cpi.mandatory) {
194                 return 0;
195         }
196         
197         /* save current state */
198
199         delete cpi.state;
200         cpi.state = new XMLNode (cpi.protocol->get_state());
201         cpi.state->add_property (X_("active"), "no");
202
203         cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
204
205         {
206                 Glib::Threads::Mutex::Lock lm (protocols_lock);
207                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
208                 if (p != control_protocols.end()) {
209                         control_protocols.erase (p);
210                 } else {
211                         cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
212                 }
213         }
214
215         cpi.protocol = 0;
216         delete cpi.state;
217         cpi.state = 0;
218         delete (Glib::Module*)cpi.descriptor->module;
219
220         ProtocolStatusChange (&cpi);
221
222         return 0;
223 }
224
225 void
226 ControlProtocolManager::load_mandatory_protocols ()
227 {
228         if (_session == 0) {
229                 return;
230         }
231
232         Glib::Threads::Mutex::Lock lm (protocols_lock);
233
234         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
235                 if ((*i)->mandatory && ((*i)->protocol == 0)) {
236                         DEBUG_TRACE (DEBUG::ControlProtocols,
237                                      string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
238                         instantiate (**i);
239                 }
240         }
241 }
242
243 void
244 ControlProtocolManager::discover_control_protocols ()
245 {
246         vector<std::string> cp_modules;
247
248         Glib::PatternSpec so_extension_pattern("*.so");
249         Glib::PatternSpec dylib_extension_pattern("*.dylib");
250
251         find_matching_files_in_search_path (control_protocol_search_path (),
252                                             so_extension_pattern, cp_modules);
253
254         find_matching_files_in_search_path (control_protocol_search_path (),
255                                             dylib_extension_pattern, cp_modules);
256
257         DEBUG_TRACE (DEBUG::ControlProtocols, 
258                      string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
259         
260         for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
261                 control_protocol_discover (*i);
262         }
263 }
264
265 int
266 ControlProtocolManager::control_protocol_discover (string path)
267 {
268         ControlProtocolDescriptor* descriptor;
269
270 #ifdef __APPLE__
271         /* don't load OS X shared objects that are just symlinks to the real thing.
272          */
273
274         if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
275                 return 0;
276         }
277 #endif
278
279         if ((descriptor = get_descriptor (path)) != 0) {
280
281                 if (!descriptor->probe (descriptor)) {
282                         DEBUG_TRACE (DEBUG::ControlProtocols,
283                                      string_compose (_("Control protocol %1 not usable"), descriptor->name));
284                 } else {
285
286                         ControlProtocolInfo* cpi = new ControlProtocolInfo ();
287
288                         cpi->descriptor = descriptor;
289                         cpi->name = descriptor->name;
290                         cpi->path = path;
291                         cpi->protocol = 0;
292                         cpi->requested = false;
293                         cpi->mandatory = descriptor->mandatory;
294                         cpi->supports_feedback = descriptor->supports_feedback;
295                         cpi->state = 0;
296
297                         control_protocol_info.push_back (cpi);
298
299                         DEBUG_TRACE (DEBUG::ControlProtocols, 
300                                      string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
301                 }
302
303                 delete (Glib::Module*)descriptor->module;
304         }
305
306         return 0;
307 }
308
309 ControlProtocolDescriptor*
310 ControlProtocolManager::get_descriptor (string path)
311 {
312         Glib::Module* module = new Glib::Module(path);
313         ControlProtocolDescriptor *descriptor = 0;
314         ControlProtocolDescriptor* (*dfunc)(void);
315         void* func = 0;
316
317         if (!(*module)) {
318                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
319                 delete module;
320                 return 0;
321         }
322
323         if (!module->get_symbol("protocol_descriptor", func)) {
324                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
325                 error << Glib::Module::get_last_error() << endmsg;
326                 delete module;
327                 return 0;
328         }
329
330         dfunc = (ControlProtocolDescriptor* (*)(void))func;
331         descriptor = dfunc();
332
333         if (descriptor) {
334                 descriptor->module = (void*)module;
335         } else {
336                 delete module;
337         }
338
339         return descriptor;
340 }
341
342 void
343 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
344 {
345         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
346                 method (*i);
347         }
348 }
349
350 ControlProtocolInfo*
351 ControlProtocolManager::cpi_by_name (string name)
352 {
353         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
354                 if (name == (*i)->name) {
355                         return *i;
356                 }
357         }
358         return 0;
359 }
360
361 int
362 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
363 {
364         XMLNodeList clist;
365         XMLNodeConstIterator citer;
366         XMLProperty* prop;
367
368         Glib::Threads::Mutex::Lock lm (protocols_lock);
369
370         clist = node.children();
371
372         for (citer = clist.begin(); citer != clist.end(); ++citer) {
373                 if ((*citer)->name() == X_("Protocol")) {
374
375                         if ((prop = (*citer)->property (X_("active"))) == 0) {
376                                 continue;
377                         }
378
379                         bool active = string_is_affirmative (prop->value());
380                         
381                         if ((prop = (*citer)->property (X_("name"))) == 0) {
382                                 continue;
383                         }
384
385                         ControlProtocolInfo* cpi = cpi_by_name (prop->value());
386                         
387                         if (cpi) {
388                                 cpi->state = new XMLNode (**citer);
389                                 
390                                 if (active) {
391                                         if (_session) {
392                                                 instantiate (*cpi);
393                                         } else {
394                                                 cpi->requested = true;
395                                         }
396                                 } else {
397                                         if (_session) {
398                                                 teardown (*cpi);
399                                         } else {
400                                                 cpi->requested = false;
401                                         }
402                                 }
403                         }
404                 }
405         }
406
407         return 0;
408 }
409
410 XMLNode&
411 ControlProtocolManager::get_state ()
412 {
413         XMLNode* root = new XMLNode (state_node_name);
414         Glib::Threads::Mutex::Lock lm (protocols_lock);
415
416         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
417
418                 if ((*i)->protocol) {
419                         XMLNode& child_state ((*i)->protocol->get_state());
420                         child_state.add_property (X_("active"), "yes");
421                         root->add_child_nocopy (child_state);
422                 } else if ((*i)->state) {
423                         XMLNode* child_state = new XMLNode (*(*i)->state);
424                         child_state->add_property (X_("active"), "no");
425                         root->add_child_nocopy (*child_state);
426                 } else {
427                         XMLNode* child_state = new XMLNode (X_("Protocol"));
428                         child_state->add_property (X_("name"), (*i)->name);
429                         child_state->add_property (X_("active"), "no");
430                         root->add_child_nocopy (*child_state);
431                 }
432
433         }
434
435         return *root;
436 }
437
438
439 ControlProtocolManager&
440 ControlProtocolManager::instance ()
441 {
442         if (_instance == 0) {
443                 _instance = new ControlProtocolManager ();
444         }
445
446         return *_instance;
447 }
448
449 void
450 ControlProtocolManager::midi_connectivity_established ()
451 {
452         Glib::Threads::Mutex::Lock lm (protocols_lock);
453
454         for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
455                 (*p)->midi_connectivity_established ();
456         }
457 }