initial pass at session-renaming functionality
[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
44 }
45
46 ControlProtocolManager::~ControlProtocolManager()
47 {
48         Glib::Mutex::Lock lm (protocols_lock);
49
50         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
51                 delete (*i);
52         }
53
54         control_protocols.clear ();
55
56
57         for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
58                 delete (*p);
59         }
60
61         control_protocol_info.clear();
62 }
63
64 void
65 ControlProtocolManager::set_session (Session* s)
66 {
67         SessionHandlePtr::set_session (s);
68
69         if (_session) {
70                 Glib::Mutex::Lock lm (protocols_lock);
71
72                 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
73                         if ((*i)->requested || (*i)->mandatory) {
74                                 instantiate (**i);
75                                 (*i)->requested = false;
76
77                                 if ((*i)->protocol && (*i)->state) {
78                                         (*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
79                                 }
80                         }
81                 }
82         }
83 }
84
85 void
86 ControlProtocolManager::session_going_away()
87 {
88         SessionHandlePtr::session_going_away ();
89
90         {
91                 Glib::Mutex::Lock lm (protocols_lock);
92
93                 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
94                         delete *p;
95                 }
96
97                 control_protocols.clear ();
98
99                 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
100                         // mark existing protocols as requested
101                         // otherwise the ControlProtocol instances are not recreated in set_session
102                         if ((*p)->protocol) {
103                                 (*p)->requested = true;
104                                 (*p)->protocol = 0;
105                         }
106                 }
107         }
108 }
109
110 ControlProtocol*
111 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
112 {
113         /* CALLER MUST HOLD LOCK */
114
115         if (_session == 0) {
116                 return 0;
117         }
118
119         cpi.descriptor = get_descriptor (cpi.path);
120
121         if (cpi.descriptor == 0) {
122                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
123                 return 0;
124         }
125
126         if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
127                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
128                 return 0;
129         }
130
131         control_protocols.push_back (cpi.protocol);
132
133         return cpi.protocol;
134 }
135
136 int
137 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
138 {
139         if (!cpi.protocol) {
140                 return 0;
141         }
142
143         if (!cpi.descriptor) {
144                 return 0;
145         }
146
147         if (cpi.mandatory) {
148                 return 0;
149         }
150
151         cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
152
153         {
154                 Glib::Mutex::Lock lm (protocols_lock);
155                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
156                 if (p != control_protocols.end()) {
157                         control_protocols.erase (p);
158                 } else {
159                         cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
160                 }
161         }
162
163         cpi.protocol = 0;
164         dlclose (cpi.descriptor->module);
165         return 0;
166 }
167
168 void
169 ControlProtocolManager::load_mandatory_protocols ()
170 {
171         if (_session == 0) {
172                 return;
173         }
174
175         Glib::Mutex::Lock lm (protocols_lock);
176
177         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
178                 if ((*i)->mandatory && ((*i)->protocol == 0)) {
179                         info << string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name) << endmsg;
180                         instantiate (**i);
181                 }
182         }
183 }
184
185 void
186 ControlProtocolManager::discover_control_protocols ()
187 {
188         vector<sys::path> cp_modules;
189
190         Glib::PatternSpec so_extension_pattern("*.so");
191         Glib::PatternSpec dylib_extension_pattern("*.dylib");
192
193         find_matching_files_in_search_path (control_protocol_search_path (),
194                         so_extension_pattern, cp_modules);
195
196         find_matching_files_in_search_path (control_protocol_search_path (),
197                         dylib_extension_pattern, cp_modules);
198
199         info << string_compose (_("looking for control protocols in %1"), control_protocol_search_path().to_string()) << endmsg;
200
201         for (vector<sys::path>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
202                 control_protocol_discover ((*i).to_string());
203         }
204 }
205
206 int
207 ControlProtocolManager::control_protocol_discover (string path)
208 {
209         ControlProtocolDescriptor* descriptor;
210
211         if ((descriptor = get_descriptor (path)) != 0) {
212
213                 if (!descriptor->probe (descriptor)) {
214                         info << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
215                 } else {
216
217                         ControlProtocolInfo* cpi = new ControlProtocolInfo ();
218
219                         cpi->descriptor = descriptor;
220                         cpi->name = descriptor->name;
221                         cpi->path = path;
222                         cpi->protocol = 0;
223                         cpi->requested = false;
224                         cpi->mandatory = descriptor->mandatory;
225                         cpi->supports_feedback = descriptor->supports_feedback;
226                         cpi->state = 0;
227
228                         control_protocol_info.push_back (cpi);
229
230                         info << string_compose(_("Control surface protocol discovered: \"%1\""), cpi->name) << endmsg;
231                 }
232
233                 dlclose (descriptor->module);
234         }
235
236         return 0;
237 }
238
239 ControlProtocolDescriptor*
240 ControlProtocolManager::get_descriptor (string path)
241 {
242         void *module;
243         ControlProtocolDescriptor *descriptor = 0;
244         ControlProtocolDescriptor* (*dfunc)(void);
245         const char *errstr;
246
247         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
248                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
249                 return 0;
250         }
251
252
253         dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
254
255         if ((errstr = dlerror()) != 0) {
256                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
257                 error << errstr << endmsg;
258                 dlclose (module);
259                 return 0;
260         }
261
262         descriptor = dfunc();
263         if (descriptor) {
264                 descriptor->module = module;
265         } else {
266                 dlclose (module);
267         }
268
269         return descriptor;
270 }
271
272 void
273 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
274 {
275         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
276                 method (*i);
277         }
278 }
279
280 ControlProtocolInfo*
281 ControlProtocolManager::cpi_by_name (string name)
282 {
283         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
284                 if (name == (*i)->name) {
285                         return *i;
286                 }
287         }
288         return 0;
289 }
290
291 int
292 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
293 {
294         XMLNodeList clist;
295         XMLNodeConstIterator citer;
296         XMLProperty* prop;
297
298         Glib::Mutex::Lock lm (protocols_lock);
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 && string_is_affirmative (prop->value())) {
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 ()
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                 } else if ((*i)->state) {
346                         // keep ownership clear
347                         root->add_child_copy (*(*i)->state);
348                 } else {
349                         child = new XMLNode (X_("Protocol"));
350                         child->add_property (X_("name"), (*i)->name);
351                         child->add_property (X_("active"), "no");
352                         root->add_child_nocopy (*child);
353                 }
354         }
355
356         return *root;
357 }
358
359 void
360 ControlProtocolManager::set_protocol_states (const XMLNode& node)
361 {
362         XMLNodeList nlist;
363         XMLNodeConstIterator niter;
364         XMLProperty* prop;
365
366         nlist = node.children();
367
368         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
369
370                 XMLNode* child = (*niter);
371
372                 if ((prop = child->property ("name")) == 0) {
373                         error << _("control protocol XML node has no name property. Ignored.") << endmsg;
374                         continue;
375                 }
376
377                 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
378
379                 if (!cpi) {
380                         warning << string_compose (_("control protocol \"%1\" is not known. Ignored"), prop->value()) << endmsg;
381                         continue;
382                 }
383
384                 /* copy the node so that ownership is clear */
385
386                 cpi->state = new XMLNode (*child);
387         }
388 }
389
390 ControlProtocolManager&
391 ControlProtocolManager::instance ()
392 {
393         if (_instance == 0) {
394                 _instance = new ControlProtocolManager ();
395         }
396
397         return *_instance;
398 }