session export starts from session start marker; add tooltips for rude solo + auditio...
[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->supports_feedback = descriptor->supports_feedback;
193                         cpi->state = 0;
194                         
195                         control_protocol_info.push_back (cpi);
196                         
197                         info << string_compose(_("Control surface protocol discovered: \"%1\""), cpi->name) << endmsg;
198                 }
199
200                 dlclose (descriptor->module);
201         }
202
203         return 0;
204 }
205
206 ControlProtocolDescriptor*
207 ControlProtocolManager::get_descriptor (string path)
208 {
209         void *module;
210         ControlProtocolDescriptor *descriptor = 0;
211         ControlProtocolDescriptor* (*dfunc)(void);
212         const char *errstr;
213
214         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
215                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
216                 return 0;
217         }
218
219
220         dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
221
222         if ((errstr = dlerror()) != 0) {
223                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
224                 error << errstr << endmsg;
225                 dlclose (module);
226                 return 0;
227         }
228
229         descriptor = dfunc();
230         if (descriptor) {
231                 descriptor->module = module;
232         } else {
233                 dlclose (module);
234         }
235
236         return descriptor;
237 }
238
239 void
240 ControlProtocolManager::foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*> method)
241 {
242         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
243                 method (*i);
244         }
245 }
246
247 ControlProtocolInfo*
248 ControlProtocolManager::cpi_by_name (string name)
249 {
250         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
251                 if (name == (*i)->name) {
252                         return *i;
253                 }
254         }
255         return 0;
256 }
257
258 int
259 ControlProtocolManager::set_state (const XMLNode& node)
260 {
261         XMLNodeList clist;
262         XMLNodeConstIterator citer;
263         XMLProperty* prop;
264
265         clist = node.children();
266
267         for (citer = clist.begin(); citer != clist.end(); ++citer) {
268                 if ((*citer)->name() == X_("Protocol")) {
269
270                         prop = (*citer)->property (X_("active"));
271
272                         if (prop && prop->value() == X_("yes")) {
273                                 if ((prop = (*citer)->property (X_("name"))) != 0) {
274                                         ControlProtocolInfo* cpi = cpi_by_name (prop->value());
275                                         if (cpi) {
276
277                                                 if (!(*citer)->children().empty()) {
278                                                         cpi->state = (*citer)->children().front ();
279                                                 } else {
280                                                         cpi->state = 0;
281                                                 }
282                                                 
283                                                 if (_session) {
284                                                         instantiate (*cpi);
285                                                 } else {
286                                                         cpi->requested = true;
287                                                 }
288                                         }
289                                 }
290                         }
291                 }    
292         }
293         return 0;
294 }
295
296 XMLNode&
297 ControlProtocolManager::get_state (void)
298 {
299         XMLNode* root = new XMLNode (state_node_name);
300         Glib::Mutex::Lock lm (protocols_lock);
301
302         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
303                 XMLNode* child = new XMLNode (X_("Protocol"));
304                 child->add_property (X_("name"), (*i)->name);
305                 child->add_property (X_("active"), (*i)->protocol ? "yes" : "no");
306                 root->add_child_nocopy (*child);
307         }
308
309         return *root;
310 }
311
312 void
313 ControlProtocolManager::set_protocol_states (const XMLNode& node)
314 {
315         XMLNodeList nlist;
316         XMLNodeConstIterator niter;
317         XMLProperty* prop;
318
319         nlist = node.children();
320
321         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
322
323                 XMLNode* child = (*niter);
324
325                 if ((prop = child->property ("name")) == 0) {
326                         error << _("control protocol XML node has no name property. Ignored.") << endmsg;
327                         continue;
328                 }
329
330                 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
331
332                 if (!cpi) {
333                         warning << string_compose (_("control protocol \"%1\" is not known. Ignored"), prop->value()) << endmsg;
334                         continue;
335                 }
336
337                 /* copy the node so that ownership is clear */
338
339                 cpi->state = new XMLNode (*child);
340         }
341 }