b89b83a29ffe51492de740d912b308d5e4cd0e0e
[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 <ardour/control_protocol.h>
8 #include <ardour/control_protocol_manager.h>
9
10 using namespace ARDOUR;
11 using namespace PBD;
12 using namespace std;
13
14 #include "i18n.h"
15
16 ControlProtocolManager* ControlProtocolManager::_instance = 0;
17
18 ControlProtocolManager::ControlProtocolManager ()
19 {
20         if (_instance == 0) {
21                 _instance = this;
22         }
23 }
24
25 ControlProtocolManager::~ControlProtocolManager()
26 {
27         LockMonitor lm (protocols_lock, __LINE__, __FILE__);
28
29         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
30                 delete (*i);
31         }
32
33         control_protocols.clear ();
34                 
35 }
36
37 void
38 ControlProtocolManager::startup (Session& s)
39 {
40         list<ControlProtocolInfo *>::iterator i;
41         
42         for (i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
43
44                 ControlProtocolInfo* cpi = (*i);
45
46                 if (cpi->name == "Tranzport") {
47                 
48                         cpi->descriptor = get_descriptor ((*i)->path);
49                         
50                         if (cpi->descriptor == 0) {
51                                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi->name) << endmsg;
52                                 continue;
53                         }
54                         
55                         if ((cpi->protocol = cpi->descriptor->initialize (cpi->descriptor, &s)) == 0) {
56                                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi->name) << endmsg;
57                                 continue;
58                         }
59                         
60                         {
61                                 LockMonitor lm (protocols_lock, __LINE__, __FILE__);
62                                 control_protocols.push_back (cpi->protocol);
63                         }
64                         
65                         cpi->protocol->init ();
66                         cpi->protocol->set_active (true);
67                 }
68         }
69 }
70
71 ControlProtocol*
72 ControlProtocolManager::instantiate (Session& session, string name)
73 {
74         list<ControlProtocolInfo *>::iterator i;
75
76         for (i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
77                 if ((*i)->name == name) {
78                         break;
79                 }
80         }
81
82         if (i == control_protocol_info.end()) {
83                 error << string_compose (_("control protocol name \"%1\" is unknown"), name) << endmsg;
84                 return 0;
85         }
86
87         ControlProtocolInfo* cpi = (*i);
88
89         cpi->descriptor = get_descriptor ((*i)->path);
90
91         if (cpi->descriptor == 0) {
92                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), name) << endmsg;
93                 return 0;
94         }
95
96         if ((cpi->protocol = cpi->descriptor->initialize (cpi->descriptor, &session)) == 0) {
97                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), name) << endmsg;
98                 return 0;
99         }
100
101         LockMonitor lm (protocols_lock, __LINE__, __FILE__);
102         control_protocols.push_back (cpi->protocol);
103         return cpi->protocol;
104 }
105
106 int
107 ControlProtocolManager::teardown (string name)
108 {
109         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
110                 ControlProtocolInfo* cpi = *i;
111
112                 if (cpi->name == name && cpi->descriptor && cpi->protocol) {
113                         cpi->descriptor->destroy (cpi->descriptor, cpi->protocol);
114                         
115                         {
116                                 LockMonitor lm (protocols_lock, __LINE__, __FILE__);
117                                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi->protocol);
118                                 if (p != control_protocols.end()) {
119                                         control_protocols.erase (p);
120                                 }
121                         }
122
123                         cpi->protocol = 0;
124                         return 0;
125                 }
126         }
127
128         return -1;
129 }
130
131 static bool protocol_filter (const string& str, void *arg)
132 {
133         /* Not a dotfile, has a prefix before a period, suffix is "so" */
134         
135         return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
136 }
137
138 void
139 ControlProtocolManager::discover_control_protocols (string path)
140 {
141         vector<string *> *found;
142         PathScanner scanner;
143
144         cerr << "CP Manager looking for surfaces\n";
145
146         found = scanner (path, protocol_filter, 0, false, true);
147
148         for (vector<string*>::iterator i = found->begin(); i != found->end(); ++i) {
149                 cerr << "CP Manager looking at " << **i << endl;
150                 control_protocol_discover (**i);
151                 delete *i;
152         }
153
154         delete found;
155 }
156
157 int
158 ControlProtocolManager::control_protocol_discover (string path)
159 {
160         ControlProtocolDescriptor* descriptor;
161
162         if ((descriptor = get_descriptor (path)) != 0) {
163
164                 ControlProtocolInfo* info = new ControlProtocolInfo ();
165
166                 info->descriptor = descriptor;
167                 info->name = descriptor->name;
168                 info->path = path;
169                 
170                 control_protocol_info.push_back (info);
171
172                 cerr << "Found \"" << info->name << "\"\n";
173
174                 dlclose (descriptor->module);
175
176         } else {
177                 cerr << "no descriptor\n";
178         }
179
180         return 0;
181 }
182
183 ControlProtocolDescriptor*
184 ControlProtocolManager::get_descriptor (string path)
185 {
186         void *module;
187         ControlProtocolDescriptor *descriptor = 0;
188         ControlProtocolDescriptor* (*dfunc)(void);
189         const char *errstr;
190
191         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
192                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
193                 return 0;
194         }
195
196
197         dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
198
199         if ((errstr = dlerror()) != 0) {
200                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
201                 error << errstr << endmsg;
202                 dlclose (module);
203                 return 0;
204         }
205
206         descriptor = dfunc();
207         if (descriptor) {
208                 descriptor->module = module;
209         } else {
210                 dlclose (module);
211         }
212
213         return descriptor;
214 }