Verbose plugin loading, code and minor gui cleanups - Alex
[terminatorX.git] / src / tX_ladspa.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2004  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_ladspa.cc
20  
21     Description: LADSPA_Plugin takes care of loading LADSPA plugins.
22                  Most of this code is based on the LADSPA SDK code by
23                  Richard W.E. Furse. For more information about ladspa
24                  checkout http://www.ladspa.org          
25 */
26
27 #include <tX_ladspa.h>
28 #include <tX_ladspa_class.h>
29 #include <dirent.h>
30 #include <dlfcn.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 std::list <LADSPA_Plugin *> LADSPA_Plugin :: plugin_list;
36 std::list <LADSPA_Stereo_Plugin *> LADSPA_Stereo_Plugin :: stereo_plugin_list;
37
38 void LADSPA_Plugin :: init ()
39 {
40         char *ladspa_path_ptr;
41         char ladspa_path[PATH_MAX];
42         char *start, *end, *buffer;
43
44         /* Finding the LADSPA Path */
45         ladspa_path_ptr=getenv("LADSPA_PATH");
46         
47         if (!ladspa_path_ptr)  {
48                 tX_warning("LADSPA_PATH not set. Trying /usr/lib/ladspa:/usr/local/lib/ladspa");
49                 strcpy(ladspa_path, "/usr/lib/ladspa:/usr/local/lib/ladspa");
50         }
51         else strcpy(ladspa_path, ladspa_path_ptr);
52         
53         /* Scanning every dir in path */
54         start = ladspa_path;
55         
56         while (*start != '\0')
57         {
58                 end = start;
59                 while (*end != ':' && *end != '\0') end++;
60     
61                 buffer = (char *) malloc(1 + end - start);
62                 if (end > start) strncpy(buffer, start, end - start);
63                         
64                 buffer[end - start] = '\0';
65                 LADSPA_Plugin::scandir(buffer);
66                 free (buffer); 
67     
68                 start = end;
69                 if (*start == ':') start++;
70         }       
71 }
72
73 /* This routine expects to get *valid* port descriptors.
74    There's no error checking as in the LADSPA SDK's "analyseplugin".
75 */
76
77 void LADSPA_Plugin :: handlelib(void *lib, LADSPA_Descriptor_Function desc_func, char *filename)
78 {
79         long i;
80         unsigned long port;
81         const LADSPA_Descriptor *descriptor;
82         int in_audio, out_audio, in_ctrl;       
83         
84         for (i=0; (descriptor = desc_func(i)) != NULL; i++) {           
85                 if (LADSPA_IS_INPLACE_BROKEN(descriptor->Properties)) {
86                         tX_plugin_warning("Plugin \"%s\" [%i] disabled: No in-place processing support.", descriptor->Label, descriptor->UniqueID);
87                 } else if (!LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties) && !globals.force_nonrt_plugins) {
88                         tX_plugin_warning("Plugin \"%s\" [%i] disabled: Not realtime capable.", descriptor->Label, descriptor->UniqueID);
89                 } else {
90                         if (!LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties)) {
91                                 tX_warning("Plugin \"%s\" [%i] is classified as non-rt capable: loading forced.", descriptor->Label, descriptor->UniqueID);
92                         }
93                         in_audio=0; out_audio=0; in_ctrl=0;
94                 
95                         for (port = 0; port<descriptor->PortCount; port++) {                    
96                                 if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[port])) {
97                                         if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port])) in_audio++;
98                                         else
99                                         if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[port])) out_audio++;
100                                 } else 
101                                         if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[port]) && LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port])) in_ctrl++;                    
102                         }
103                         
104                         if ((in_audio == 1) && (out_audio == 1)) {
105                                 new LADSPA_Plugin(descriptor, filename);
106                         } if ((in_audio == 2) && (out_audio == 2)) {
107                                 new LADSPA_Stereo_Plugin(descriptor, filename);
108                         }
109                         else { tX_plugin_warning("Plugin \"%s\" [%i] disabled: Neither mono nor stereo.", descriptor->Label, descriptor->UniqueID); }
110                 }
111         }
112 }
113
114 void LADSPA_Plugin :: scandir(char *dirname)
115 {
116         int dirlen=strlen(dirname);
117         int needslash=0;
118         DIR * dir;
119         struct dirent * entry;
120         char *filename;
121         void *handle;
122         LADSPA_Descriptor_Function desc_func;
123         
124         if (!dirlen) { tX_error("empty directory name?"); return; };
125
126         if (dirname[dirlen - 1] != '/') needslash=1;
127         
128         dir = opendir(dirname);
129         
130         if (!dir) { tX_error("couldn't access directory \"%s\".", dirname); return; };
131         
132         while (1) {
133                 entry=readdir(dir);             
134                 if (!entry) { closedir(dir); return; }
135                 
136                 filename = (char *) malloc (dirlen + strlen(entry->d_name) + 1 + needslash);
137                 
138                 strcpy(filename, dirname);
139                 if (needslash) strcat(filename, "/");
140                 strcat(filename, entry->d_name);
141                 
142                 handle = dlopen(filename, RTLD_LAZY);
143                 
144                 if (handle) {
145                         /* clear dlerror */
146                         dlerror();
147                         
148                         /* check wether this is a LADSPA lib */
149                         desc_func = (LADSPA_Descriptor_Function) dlsym(handle, "ladspa_descriptor");
150                         
151                         if (dlerror() == NULL && desc_func) {
152                                 LADSPA_Plugin :: handlelib(handle, desc_func, entry->d_name);
153                         } else {
154                                 tX_error("\"%s\" is not a LADSPA plugin library.", filename);
155                                 dlclose(handle);
156                         }
157                 }
158                 
159                 free (filename);
160         }
161 }
162
163 void LADSPA_Plugin :: status ()
164 {
165         debug_display();
166 }
167
168 void LADSPA_Plugin :: debug_display()
169 {
170         std::list <LADSPA_Plugin *> :: iterator plugin;
171         
172         for (plugin=plugin_list.begin(); plugin != plugin_list.end(); plugin++) {
173                 printf("plugin: %60s | id: %5li | ports: %2li\n", (*plugin)->getName(), (*plugin)->getUniqueID(), (*plugin)->getPortCount());
174         }
175 }
176
177 LADSPA_Plugin :: LADSPA_Plugin (const LADSPA_Descriptor *ld, char *filename)
178 {
179         ladspa_descriptor = ld;
180         
181         plugin_list.push_back(this);
182         strcpy(file, filename);
183         sprintf(info_string, "LADSPA-Plugin: %s\nLabel: %s\nFile: %s\nUnique ID: %li\nMaker: %s\nCopyright: %s", ld->Name, ld->Label, file, ld->UniqueID, ld->Maker, ld->Copyright);
184         LADSPA_Class::add_plugin(this);
185 }
186
187 LADSPA_Plugin * LADSPA_Plugin :: getPluginByIndex(int i)
188 {
189         std::list <LADSPA_Plugin *> :: iterator plugin;
190         int p;
191         
192         plugin = plugin_list.begin();
193         for (p=0; (p<i) && (plugin != plugin_list.end()); p++, plugin++);
194         
195         if (plugin==plugin_list.end()) return NULL;
196         
197         else return (*plugin);
198 }
199
200 LADSPA_Plugin * LADSPA_Plugin :: getPluginByUniqueID(long ID)
201 {
202         std::list <LADSPA_Plugin *> :: iterator plugin;
203         
204         for (plugin=plugin_list.begin(); plugin != plugin_list.end(); plugin++) {
205                 if ((*plugin)->getUniqueID()==ID) return (*plugin);
206         }
207
208         return NULL;
209 }
210
211 /* STEREO */
212
213 LADSPA_Stereo_Plugin :: LADSPA_Stereo_Plugin (const LADSPA_Descriptor *ld, char *filename)
214 {
215         ladspa_descriptor = ld;
216         
217         stereo_plugin_list.push_back(this);
218         strcpy(file, filename);
219         sprintf(info_string, "LADSPA-Stereo-Plugin: %s\nLabel: %s\nFile: %s\nUnique ID: %li\nMaker: %s\nCopyright: %s", ld->Name, ld->Label, file, ld->UniqueID, ld->Maker, ld->Copyright);
220         LADSPA_Class::add_stereo_plugin(this);
221 }
222
223 LADSPA_Stereo_Plugin * LADSPA_Stereo_Plugin :: getPluginByIndex(int i)
224 {
225         std::list <LADSPA_Stereo_Plugin *> :: iterator plugin;
226         int p;
227         
228         plugin = stereo_plugin_list.begin();
229         for (p=0; (p<i) && (plugin != stereo_plugin_list.end()); p++, plugin++);
230         
231         if (plugin==stereo_plugin_list.end()) return NULL;
232         
233         else return (*plugin);
234 }
235
236 LADSPA_Stereo_Plugin * LADSPA_Stereo_Plugin :: getPluginByUniqueID(long ID)
237 {
238         std::list <LADSPA_Stereo_Plugin *> :: iterator plugin;
239         
240         for (plugin=stereo_plugin_list.begin(); plugin != stereo_plugin_list.end(); plugin++) {
241                 if ((*plugin)->getUniqueID()==ID) return (*plugin);
242         }
243
244         return NULL;
245 }
246
247 bool LADSPA_Stereo_Plugin::is_stereo() { return true; }
248 bool LADSPA_Plugin::is_stereo() { return false; }