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