]> git.sesse.net Git - mlt/blob - src/modules/jackrack/plugin_mgr.c
b666e354031821f0b47513d0cce780293b77d0f8
[mlt] / src / modules / jackrack / plugin_mgr.c
1 /*
2  *   jack-ladspa-host
3  *    
4  *   Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
5  *    
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <sys/stat.h>
27 #include <dlfcn.h>
28 #include <math.h>
29 #include <strings.h>
30 #include <ctype.h>
31 #include <ladspa.h>
32
33 #include "plugin_mgr.h"
34 #include "plugin_desc.h"
35 #include "ui.h"
36
37
38 static gboolean
39 plugin_is_valid (const LADSPA_Descriptor * descriptor)
40 {
41   unsigned long i;
42   unsigned long icount = 0;
43   unsigned long ocount = 0;
44   
45   for (i = 0; i < descriptor->PortCount; i++)
46     {
47       if (!LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[i]))
48         continue;
49       
50       if (LADSPA_IS_PORT_INPUT (descriptor->PortDescriptors[i]))
51         icount++;
52       else
53         ocount++;
54     }
55   
56   if (icount == 0 || ocount == 0)
57     return FALSE;
58   
59   return TRUE;
60 }
61
62 static void
63 plugin_mgr_get_object_file_plugins (ui_t * ui, plugin_mgr_t * plugin_mgr, const char * filename)
64 {
65   const char * dlerr;
66   void * dl_handle;
67   LADSPA_Descriptor_Function get_descriptor;
68   const LADSPA_Descriptor * descriptor;
69   unsigned long plugin_index;
70   plugin_desc_t * desc, * other_desc = NULL;
71   GSList * list;
72   gboolean exists;
73   int err;
74   
75   /* open the object file */
76   dl_handle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL);
77   if (!dl_handle)
78     {
79       fprintf (stderr, "%s: error opening shared object file '%s': %s\n",
80                __FUNCTION__, filename, dlerror());
81       return;
82     }
83   
84   
85   /* get the get_descriptor function */
86   dlerror (); /* clear the error report */
87   
88   get_descriptor = (LADSPA_Descriptor_Function)
89     dlsym (dl_handle, "ladspa_descriptor");
90   
91   dlerr = dlerror();
92   if (dlerr) {
93     fprintf (stderr, "%s: error finding ladspa_descriptor symbol in object file '%s': %s\n",
94              __FUNCTION__, filename, dlerr);
95     dlclose (dl_handle);
96     return;
97   }
98   
99   plugin_index = 0;
100   while ( (descriptor = get_descriptor (plugin_index)) )
101     {
102       if (!plugin_is_valid (descriptor))
103         {
104           plugin_index++;
105           continue;
106         }
107
108       
109       /* check it doesn't already exist */
110       exists = FALSE;
111       for (list = plugin_mgr->all_plugins; list; list = g_slist_next (list))
112         {
113           other_desc = (plugin_desc_t *) list->data;
114           
115           if (other_desc->id == descriptor->UniqueID)
116             {
117               exists = TRUE;
118               break;
119             }
120         }
121       
122       if (exists)
123         {
124           printf ("Plugin %ld exists in both '%s' and '%s'; using version in '%s'\n",
125                   descriptor->UniqueID, other_desc->object_file, filename, other_desc->object_file);
126           plugin_index++;
127           continue;
128         }
129
130       
131       desc = plugin_desc_new_with_descriptor (filename, plugin_index, descriptor);
132       plugin_mgr->all_plugins = g_slist_append (plugin_mgr->all_plugins, desc);
133       plugin_index++;
134       plugin_mgr->plugin_count++;
135       
136       /* print in the splash screen */
137       /* printf ("Loaded plugin '%s'\n", desc->name); */
138     }
139   
140   err = dlclose (dl_handle);
141   if (err)
142     {
143       fprintf (stderr, "%s: error closing object file '%s': %s\n",
144                __FUNCTION__, filename, dlerror ());
145     }
146 }
147
148 static void
149 plugin_mgr_get_dir_plugins (ui_t * ui, plugin_mgr_t * plugin_mgr, const char * dir)
150 {
151   DIR * dir_stream;
152   struct dirent * dir_entry;
153   char * file_name;
154   int err;
155   size_t dirlen;
156   
157   dir_stream = opendir (dir);
158   if (!dir_stream)
159     {
160 /*      fprintf (stderr, "%s: error opening directory '%s': %s\n",
161                __FUNCTION__, dir, strerror (errno)); */
162       return;
163     }
164   
165   dirlen = strlen (dir);
166   
167   while ( (dir_entry = readdir (dir_stream)) )
168     {
169       if (strcmp (dir_entry->d_name, ".") == 0 ||
170           strcmp (dir_entry->d_name, "..") == 0)
171         continue;
172   
173       file_name = g_malloc (dirlen + 1 + strlen (dir_entry->d_name) + 1);
174     
175       strcpy (file_name, dir);
176       if (file_name[dirlen - 1] == '/')
177         strcpy (file_name + dirlen, dir_entry->d_name);
178       else
179         {
180           file_name[dirlen] = '/';
181           strcpy (file_name + dirlen + 1, dir_entry->d_name);
182         }
183     
184       plugin_mgr_get_object_file_plugins (ui, plugin_mgr, file_name);
185       
186       g_free (file_name);
187     }
188
189   err = closedir (dir_stream);
190   if (err)
191     fprintf (stderr, "%s: error closing directory '%s': %s\n",
192              __FUNCTION__, dir, strerror (errno));
193 }
194
195 static void
196 plugin_mgr_get_path_plugins (ui_t * ui, plugin_mgr_t * plugin_mgr)
197 {
198   char * ladspa_path, * dir;
199   
200   ladspa_path = g_strdup (getenv ("LADSPA_PATH"));
201   if (!ladspa_path)
202     ladspa_path = g_strdup ("/usr/local/lib/ladspa:/usr/lib/ladspa");
203   
204   dir = strtok (ladspa_path, ":");
205   do
206     plugin_mgr_get_dir_plugins (ui, plugin_mgr, dir);
207   while ((dir = strtok (NULL, ":")));
208
209   g_free (ladspa_path);
210 }
211
212 static gint
213 plugin_mgr_sort (gconstpointer a, gconstpointer b)
214 {
215   const plugin_desc_t * da;
216   const plugin_desc_t * db;
217   da = (const plugin_desc_t *) a;
218   db = (const plugin_desc_t *) b;
219   
220   return strcasecmp (da->name, db->name);
221 }
222
223 plugin_mgr_t *
224 plugin_mgr_new (ui_t * ui)
225 {
226   plugin_mgr_t * pm;
227   
228   pm = g_malloc (sizeof (plugin_mgr_t));
229   pm->all_plugins = NULL;  
230   pm->plugins = NULL;
231   pm->plugin_count = 0;
232   
233   plugin_mgr_get_path_plugins (ui, pm);
234   
235   if (!pm->all_plugins)
236     {
237       fprintf (stderr, "No LADSPA plugins were found!\n\nCheck your LADSPA_PATH environment variable.\n");
238       abort ();
239     }
240   
241   pm->all_plugins = g_slist_sort (pm->all_plugins, plugin_mgr_sort);
242   
243   return pm;
244 }
245
246 void
247 plugin_mgr_destroy (plugin_mgr_t * plugin_mgr)
248 {
249   GSList * list;
250   
251   for (list = plugin_mgr->all_plugins; list; list = g_slist_next (list))
252     plugin_desc_destroy ((plugin_desc_t *) list->data);
253   
254   g_slist_free (plugin_mgr->plugins);
255   g_slist_free (plugin_mgr->all_plugins);
256   free (plugin_mgr);
257 }
258
259
260 void
261 plugin_mgr_set_plugins (plugin_mgr_t * plugin_mgr, unsigned long rack_channels)
262 {
263   GSList * list;
264   plugin_desc_t * desc;
265
266   /* clear the current plugins */
267   g_slist_free (plugin_mgr->plugins);
268   plugin_mgr->plugins = NULL;
269   
270   for (list = plugin_mgr->all_plugins; list; list = g_slist_next (list))
271     {
272       desc = (plugin_desc_t *) list->data;
273       
274       if (plugin_desc_get_copies (desc, rack_channels) != 0)
275         plugin_mgr->plugins = g_slist_append (plugin_mgr->plugins, desc);
276     }
277 }
278
279 static plugin_desc_t *
280 plugin_mgr_find_desc (plugin_mgr_t * plugin_mgr, GSList * plugins, unsigned long id)
281 {
282   GSList * list;
283   plugin_desc_t * desc;
284   
285   for (list = plugins; list; list = g_slist_next (list))
286     {
287       desc = (plugin_desc_t *) list->data;
288       
289       if (desc->id == id)
290         return desc;
291     }
292   
293   return NULL;
294 }
295
296 plugin_desc_t *
297 plugin_mgr_get_desc (plugin_mgr_t * plugin_mgr, unsigned long id)
298 {
299   return plugin_mgr_find_desc (plugin_mgr, plugin_mgr->plugins, id);
300 }
301
302 plugin_desc_t *
303 plugin_mgr_get_any_desc (plugin_mgr_t * plugin_mgr, unsigned long id)
304 {
305   return plugin_mgr_find_desc (plugin_mgr, plugin_mgr->all_plugins, id);
306 }
307
308
309 /* EOF */