display results of a bounce in the region list
[ardour.git] / libs / ardour / control_protocol_manager.cc
1 #include <dlfcn.h>
2
3 #include <pbd/compose.h>
4 #include <pbd/error.h>
5 #include <pbd/pathscanner.h>
6
7 #include <control_protocol/control_protocol.h>
8
9 #include <ardour/session.h>
10 #include <ardour/control_protocol_manager.h>
11
12 using namespace ARDOUR;
13 using namespace std;
14 using namespace PBD;
15
16 #include "i18n.h"
17
18 ControlProtocolManager* ControlProtocolManager::_instance = 0;
19 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
20
21 ControlProtocolManager::ControlProtocolManager ()
22 {
23         if (_instance == 0) {
24                 _instance = this;
25         }
26
27         _session = 0;
28 }
29
30 ControlProtocolManager::~ControlProtocolManager()
31 {
32         Glib::Mutex::Lock lm (protocols_lock);
33
34         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
35                 delete (*i);
36         }
37
38         control_protocols.clear ();
39                 
40 }
41
42 void
43 ControlProtocolManager::set_session (Session& s)
44 {
45         _session = &s;
46         _session->GoingAway.connect (mem_fun (*this, &ControlProtocolManager::drop_session));
47
48         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
49                 if ((*i)->requested || (*i)->mandatory) {
50                         instantiate (**i);
51                         (*i)->requested = false;
52
53                         if ((*i)->protocol && (*i)->state) {
54                                 (*i)->protocol->set_state (*(*i)->state);
55                         }
56                 }
57         }
58 }
59
60 void
61 ControlProtocolManager::drop_session ()
62 {
63         _session = 0;
64
65         {
66                 Glib::Mutex::Lock lm (protocols_lock);
67                 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
68                         delete *p;
69                 }
70                 control_protocols.clear ();
71         }
72 }
73
74 ControlProtocol*
75 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
76 {
77         if (_session == 0) {
78                 return 0;
79         }
80
81         cpi.descriptor = get_descriptor (cpi.path);
82
83         if (cpi.descriptor == 0) {
84                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
85                 return 0;
86         }
87
88         if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
89                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
90                 return 0;
91         }
92
93         Glib::Mutex::Lock lm (protocols_lock);
94         control_protocols.push_back (cpi.protocol);
95
96         if (cpi.state) {
97                 cpi.protocol->set_state (*cpi.state);
98         }
99
100         return cpi.protocol;
101 }
102
103 int
104 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
105 {
106         if (!cpi.protocol) {
107                 return 0;
108         }
109
110         if (!cpi.descriptor) {
111                 return 0;
112         }
113
114         if (cpi.mandatory) {
115                 return 0;
116         }
117
118         cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
119         
120         {
121                 Glib::Mutex::Lock lm (protocols_lock);
122                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
123                 if (p != control_protocols.end()) {
124                         control_protocols.erase (p);
125                 }
126         }
127         
128         cpi.protocol = 0;
129         dlclose (cpi.descriptor->module);
130         return 0;
131 }
132
133 static bool protocol_filter (const string& str, void *arg)
134 {
135         /* Not a dotfile, has a prefix before a period, suffix is "so" */
136         
137         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
138 }
139
140 void
141 ControlProtocolManager::load_mandatory_protocols ()
142 {
143         if (_session == 0) {
144                 return;
145         }
146
147         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
148                 if ((*i)->mandatory && ((*i)->protocol == 0)) {
149                         info << string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name) << endmsg;
150                         instantiate (**i);
151                 }
152         }
153 }
154
155 void
156 ControlProtocolManager::discover_control_protocols (string path)
157 {
158         vector<string *> *found;
159         PathScanner scanner;
160
161         info << string_compose (_("looking for control protocols in %1"), path) << endmsg;
162
163         found = scanner (path, protocol_filter, 0, false, true);
164
165         for (vector<string*>::iterator i = found->begin(); i != found->end(); ++i) {
166                 control_protocol_discover (**i);
167                 delete *i;
168         }
169
170         delete found;
171 }
172
173 int
174 ControlProtocolManager::control_protocol_discover (string path)
175 {
176         ControlProtocolDescriptor* descriptor;
177
178         if ((descriptor = get_descriptor (path)) != 0) {
179
180                 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
181
182                 if (!descriptor->probe (descriptor)) {
183                         info << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
184                 } else {
185
186                         cpi->descriptor = descriptor;
187                         cpi->name = descriptor->name;
188                         cpi->path = path;
189                         cpi->protocol = 0;
190                         cpi->requested = false;
191                         cpi->mandatory = descriptor->mandatory;
192                         cpi->state = 0;
193                         
194                         control_protocol_info.push_back (cpi);
195                         
196                         info << string_compose(_("Control surface protocol discovered: \"%1\""), cpi->name) << endmsg;
197                 }
198
199                 dlclose (descriptor->module);
200         }
201
202         return 0;
203 }
204
205 ControlProtocolDescriptor*
206 ControlProtocolManager::get_descriptor (string path)
207 {
208         void *module;
209         ControlProtocolDescriptor *descriptor = 0;
210         ControlProtocolDescriptor* (*dfunc)(void);
211         const char *errstr;
212
213         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
214                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
215                 return 0;
216         }
217
218
219         dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
220
221         if ((errstr = dlerror()) != 0) {
222                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
223                 error << errstr << endmsg;
224                 dlclose (module);
225                 return 0;
226         }
227
228         descriptor = dfunc();
229         if (descriptor) {
230                 descriptor->module = module;
231         } else {
232                 dlclose (module);
233         }
234
235         return descriptor;
236 }
237
238 void
239 ControlProtocolManager::foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*> method)
240 {
241         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
242                 method (*i);
243         }
244 }
245
246 ControlProtocolInfo*
247 ControlProtocolManager::cpi_by_name (string name)
248 {
249         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
250                 if (name == (*i)->name) {
251                         return *i;
252                 }
253         }
254         return 0;
255 }
256
257 int
258 ControlProtocolManager::set_state (const XMLNode& node)
259 {
260         XMLNodeList clist;
261         XMLNodeConstIterator citer;
262         XMLProperty* prop;
263
264         clist = node.children();
265
266         for (citer = clist.begin(); citer != clist.end(); ++citer) {
267                 if ((*citer)->name() == X_("Protocol")) {
268
269                         prop = (*citer)->property (X_("active"));
270
271                         if (prop && prop->value() == X_("yes")) {
272                                 if ((prop = (*citer)->property (X_("name"))) != 0) {
273                                         ControlProtocolInfo* cpi = cpi_by_name (prop->value());
274                                         if (cpi) {
275
276                                                 if (!(*citer)->children().empty()) {
277                                                         cpi->state = (*citer)->children().front ();
278                                                 } else {
279                                                         cpi->state = 0;
280                                                 }
281                                                 
282                                                 if (_session) {
283                                                         instantiate (*cpi);
284                                                 } else {
285                                                         cpi->requested = true;
286                                                 }
287                                         }
288                                 }
289                         }
290                 }    
291         }
292         return 0;
293 }
294
295 XMLNode&
296 ControlProtocolManager::get_state (void)
297 {
298         XMLNode* root = new XMLNode (state_node_name);
299         Glib::Mutex::Lock lm (protocols_lock);
300
301         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
302                 XMLNode* child = new XMLNode (X_("Protocol"));
303                 child->add_property (X_("name"), (*i)->name);
304                 child->add_property (X_("active"), (*i)->protocol ? "yes" : "no");
305                 root->add_child_nocopy (*child);
306         }
307
308         return *root;
309 }
310
311 void
312 ControlProtocolManager::set_protocol_states (const XMLNode& node)
313 {
314         XMLNodeList nlist;
315         XMLNodeConstIterator niter;
316         XMLProperty* prop;
317
318         nlist = node.children();
319
320         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
321
322                 XMLNode* child = (*niter);
323
324                 if ((prop = child->property ("name")) == 0) {
325                         error << _("control protocol XML node has no name property. Ignored.") << endmsg;
326                         continue;
327                 }
328
329                 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
330
331                 if (!cpi) {
332                         warning << string_compose (_("control protocol \"%1\" is not known. Ignored"), prop->value()) << endmsg;
333                         continue;
334                 }
335
336                 /* copy the node so that ownership is clear */
337
338                 cpi->state = new XMLNode (*child);
339         }
340 }