Adding stereo plugins, fixed LADSPA menus, ignoring NON-RT plugins - Alex
[terminatorX.git] / src / tX_ladspa.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2003  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_warning("Plugin \"%s\" disabled. No in-place processing support.", descriptor->Name);
87                 } else if (!LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties)) {
88                         tX_warning("Plugin \"%s\" disabled. Not realtime capable.", descriptor->Name);                  
89                 } else {                
90                         in_audio=0; out_audio=0; in_ctrl=0;
91                 
92                         for (port = 0; port<descriptor->PortCount; port++) {                    
93                                 if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[port])) {
94                                         if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port])) in_audio++;
95                                         else
96                                         if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[port])) out_audio++;
97                                 } else 
98                                         if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[port]) && LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port])) in_ctrl++;                    
99                         }
100                         
101                         if ((in_audio == 1) && (out_audio == 1)) {
102                                 new LADSPA_Plugin(descriptor, filename);
103                         } if ((in_audio == 2) && (out_audio == 2)) {
104                                 new LADSPA_Stereo_Plugin(descriptor, filename);
105                         }
106                         else { tX_warning("Plugin \"%s\" disabled. Neither mono nor stereo.", descriptor->Name); }
107                 }
108         }
109 }
110
111 void LADSPA_Plugin :: scandir(char *dirname)
112 {
113         int dirlen=strlen(dirname);
114         int needslash=0;
115         DIR * dir;
116         struct dirent * entry;
117         char *filename;
118         void *handle;
119         LADSPA_Descriptor_Function desc_func;
120         
121         if (!dirlen) { tX_error("tX: Error: empty directory name?"); return; };
122
123         if (dirname[dirlen - 1] != '/') needslash=1;
124         
125         dir = opendir(dirname);
126         
127         if (!dir) { tX_error("tX: Error: couldn't access directory \"%s\".", dirname); return; };
128         
129         while (1) {
130                 entry=readdir(dir);             
131                 if (!entry) { closedir(dir); return; }
132                 
133                 filename = (char *) malloc (dirlen + strlen(entry->d_name) + 1 + needslash);
134                 
135                 strcpy(filename, dirname);
136                 if (needslash) strcat(filename, "/");
137                 strcat(filename, entry->d_name);
138                 
139                 handle = dlopen(filename, RTLD_LAZY);
140                 
141                 if (handle) {
142                         /* clear dlerror */
143                         dlerror();
144                         
145                         /* check wether this is a LADSPA lib */
146                         desc_func = (LADSPA_Descriptor_Function) dlsym(handle, "ladspa_descriptor");
147                         
148                         if (dlerror() == NULL && desc_func) {
149                                 LADSPA_Plugin :: handlelib(handle, desc_func, entry->d_name);
150                         } else {
151                                 tX_error("tX: Error: %s is not a LADSPA plugin library.", filename);
152                                 dlclose(handle);
153                         }
154                 }
155                 
156                 free (filename);
157         }
158 }
159
160 void LADSPA_Plugin :: status ()
161 {
162         printf ("tX: %i LADSPA plugins available\n", plugin_list.size());
163         debug_display();
164 }
165
166 void LADSPA_Plugin :: debug_display()
167 {
168         std::list <LADSPA_Plugin *> :: iterator plugin;
169         
170         for (plugin=plugin_list.begin(); plugin != plugin_list.end(); plugin++) {
171                 printf("plugin: %60s | id: %5li | ports: %2li\n", (*plugin)->getName(), (*plugin)->getUniqueID(), (*plugin)->getPortCount());
172         }
173 }
174
175 LADSPA_Plugin :: LADSPA_Plugin (const LADSPA_Descriptor *ld, char *filename)
176 {
177         ladspa_descriptor = ld;
178         
179         plugin_list.push_back(this);
180         strcpy(file, filename);
181         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);
182         LADSPA_Class::add_plugin(this);
183 }
184
185 LADSPA_Plugin * LADSPA_Plugin :: getPluginByIndex(int i)
186 {
187         std::list <LADSPA_Plugin *> :: iterator plugin;
188         int p;
189         
190         plugin = plugin_list.begin();
191         for (p=0; (p<i) && (plugin != plugin_list.end()); p++, plugin++);
192         
193         if (plugin==plugin_list.end()) return NULL;
194         
195         else return (*plugin);
196 }
197
198 LADSPA_Plugin * LADSPA_Plugin :: getPluginByUniqueID(long ID)
199 {
200         std::list <LADSPA_Plugin *> :: iterator plugin;
201         
202         for (plugin=plugin_list.begin(); plugin != plugin_list.end(); plugin++) {
203                 if ((*plugin)->getUniqueID()==ID) return (*plugin);
204         }
205
206         return NULL;
207 }
208
209 /* STEREO */
210
211 LADSPA_Stereo_Plugin :: LADSPA_Stereo_Plugin (const LADSPA_Descriptor *ld, char *filename)
212 {
213         ladspa_descriptor = ld;
214         
215         stereo_plugin_list.push_back(this);
216         strcpy(file, filename);
217         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);
218         LADSPA_Class::add_stereo_plugin(this);
219 }
220
221 LADSPA_Stereo_Plugin * LADSPA_Stereo_Plugin :: getPluginByIndex(int i)
222 {
223         std::list <LADSPA_Stereo_Plugin *> :: iterator plugin;
224         int p;
225         
226         plugin = stereo_plugin_list.begin();
227         for (p=0; (p<i) && (plugin != stereo_plugin_list.end()); p++, plugin++);
228         
229         if (plugin==stereo_plugin_list.end()) return NULL;
230         
231         else return (*plugin);
232 }
233
234 LADSPA_Stereo_Plugin * LADSPA_Stereo_Plugin :: getPluginByUniqueID(long ID)
235 {
236         std::list <LADSPA_Stereo_Plugin *> :: iterator plugin;
237         
238         for (plugin=stereo_plugin_list.begin(); plugin != stereo_plugin_list.end(); plugin++) {
239                 if ((*plugin)->getUniqueID()==ID) return (*plugin);
240         }
241
242         return NULL;
243 }
244
245 bool LADSPA_Stereo_Plugin::is_stereo() { return true; }
246 bool LADSPA_Plugin::is_stereo() { return false; }