1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2020 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer 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 GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/plugin/ags_ladspa_manager.h>
21 
22 #include <ags/plugin/ags_base_plugin.h>
23 
24 #if defined(AGS_W32API)
25 #include <windows.h>
26 #else
27 #include <dlfcn.h>
28 #endif
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 
36 #include <string.h>
37 #include <strings.h>
38 
39 #include <ladspa.h>
40 
41 #include <ags/config.h>
42 
43 void ags_ladspa_manager_class_init(AgsLadspaManagerClass *ladspa_manager);
44 void ags_ladspa_manager_init (AgsLadspaManager *ladspa_manager);
45 void ags_ladspa_manager_dispose(GObject *gobject);
46 void ags_ladspa_manager_finalize(GObject *gobject);
47 
48 /**
49  * SECTION:ags_ladspa_manager
50  * @short_description: Singleton pattern to organize LADSPA
51  * @title: AgsLadspaManager
52  * @section_id:
53  * @include: ags/plugin/ags_ladspa_manager.h
54  *
55  * The #AgsLadspaManager loads/unloads LADSPA plugins.
56  */
57 enum{
58   ADD,
59   CREATE,
60   LAST_SIGNAL,
61 };
62 
63 static gpointer ags_ladspa_manager_parent_class = NULL;
64 
65 AgsLadspaManager *ags_ladspa_manager = NULL;
66 gchar **ags_ladspa_default_path = NULL;
67 
68 GType
ags_ladspa_manager_get_type(void)69 ags_ladspa_manager_get_type (void)
70 {
71   static volatile gsize g_define_type_id__volatile = 0;
72 
73   if(g_once_init_enter (&g_define_type_id__volatile)){
74     GType ags_type_ladspa_manager = 0;
75 
76     static const GTypeInfo ags_ladspa_manager_info = {
77       sizeof (AgsLadspaManagerClass),
78       NULL, /* base_init */
79       NULL, /* base_finalize */
80       (GClassInitFunc) ags_ladspa_manager_class_init,
81       NULL, /* class_finalize */
82       NULL, /* class_data */
83       sizeof (AgsLadspaManager),
84       0,    /* n_preallocs */
85       (GInstanceInitFunc) ags_ladspa_manager_init,
86     };
87 
88     ags_type_ladspa_manager = g_type_register_static(G_TYPE_OBJECT,
89 						     "AgsLadspaManager",
90 						     &ags_ladspa_manager_info,
91 						     0);
92 
93     g_once_init_leave(&g_define_type_id__volatile, ags_type_ladspa_manager);
94   }
95 
96   return g_define_type_id__volatile;
97 }
98 
99 void
ags_ladspa_manager_class_init(AgsLadspaManagerClass * ladspa_manager)100 ags_ladspa_manager_class_init(AgsLadspaManagerClass *ladspa_manager)
101 {
102   GObjectClass *gobject;
103 
104   ags_ladspa_manager_parent_class = g_type_class_peek_parent(ladspa_manager);
105 
106   /* GObjectClass */
107   gobject = (GObjectClass *) ladspa_manager;
108 
109   gobject->dispose = ags_ladspa_manager_dispose;
110   gobject->finalize = ags_ladspa_manager_finalize;
111 }
112 
113 void
ags_ladspa_manager_init(AgsLadspaManager * ladspa_manager)114 ags_ladspa_manager_init(AgsLadspaManager *ladspa_manager)
115 {
116   /* ladspa manager mutex */
117   g_rec_mutex_init(&(ladspa_manager->obj_mutex));
118 
119   /* ladspa plugin and path */
120   ladspa_manager->ladspa_plugin = NULL;
121 
122   if(ags_ladspa_default_path == NULL){
123     gchar *ladspa_env;
124 
125     if((ladspa_env = getenv("LADSPA_PATH")) != NULL){
126       gchar *iter, *next;
127       guint i;
128 
129       ags_ladspa_default_path = (gchar **) malloc(sizeof(gchar *));
130 
131       iter = ladspa_env;
132       i = 0;
133 
134       while((next = strchr(iter, G_SEARCHPATH_SEPARATOR)) != NULL){
135 	ags_ladspa_default_path = (gchar **) realloc(ags_ladspa_default_path,
136 						     (i + 2) * sizeof(gchar *));
137 	ags_ladspa_default_path[i] = g_strndup(iter,
138 					       next - iter);
139 
140 	iter = next + 1;
141 	i++;
142       }
143 
144       if(*iter != '\0'){
145 	ags_ladspa_default_path = (gchar **) realloc(ags_ladspa_default_path,
146 						     (i + 2) * sizeof(gchar *));
147 	ags_ladspa_default_path[i] = g_strdup(iter);
148 
149 	i++;
150       }
151 
152       ags_ladspa_default_path[i] = NULL;
153     }else{
154 #if defined(AGS_W32API)
155       AgsApplicationContext *application_context;
156 
157       gchar *app_dir;
158       gchar *path;
159 
160       guint i;
161 
162       i = 0;
163 
164       application_context = ags_application_context_get_instance();
165 
166       app_dir = NULL;
167 
168       if(strlen(application_context->argv[0]) > strlen("\\gsequencer.exe")){
169 	app_dir = g_strndup(application_context->argv[0],
170 			    strlen(application_context->argv[0]) - strlen("\\gsequencer.exe"));
171       }
172 
173       ags_ladspa_default_path = (gchar **) malloc(2 * sizeof(gchar *));
174 
175       path = g_strdup_printf("%s\\ladspa",
176 			     g_get_current_dir());
177 
178       if(g_file_test(path,
179 		     G_FILE_TEST_IS_DIR)){
180 	ags_ladspa_default_path[i++] = path;
181       }else{
182 	g_free(path);
183 
184 	if(g_path_is_absolute(app_dir)){
185 	  ags_ladspa_default_path[i++] = g_strdup_printf("%s\\ladspa",
186 							 app_dir);
187 	}else{
188 	  ags_ladspa_default_path[i++] = g_strdup_printf("%s\\%s\\ladspa",
189 							 g_get_current_dir(),
190 							 app_dir);
191 	}
192       }
193 
194       ags_ladspa_default_path[i++] = NULL;
195 
196       g_free(app_dir);
197 #else
198       gchar *home_dir;
199       guint i;
200 
201 #ifdef AGS_MAC_BUNDLE
202       if((home_dir = getenv("HOME")) != NULL){
203 	ags_ladspa_default_path = (gchar **) malloc(7 * sizeof(gchar *));
204       }else{
205 	ags_ladspa_default_path = (gchar **) malloc(6 * sizeof(gchar *));
206       }
207 #else
208       if((home_dir = getenv("HOME")) != NULL){
209 	ags_ladspa_default_path = (gchar **) malloc(6 * sizeof(gchar *));
210       }else{
211 	ags_ladspa_default_path = (gchar **) malloc(5 * sizeof(gchar *));
212       }
213 #endif
214 
215       i = 0;
216 
217 #ifdef AGS_MAC_BUNDLE
218       ags_ladspa_default_path[i++] = g_strdup_printf("%s/ladspa",
219 						     getenv("GSEQUENCER_PLUGIN_DIR"));
220 #endif
221 
222       ags_ladspa_default_path[i++] = g_strdup("/usr/lib64/ladspa");
223       ags_ladspa_default_path[i++] = g_strdup("/usr/local/lib64/ladspa");
224       ags_ladspa_default_path[i++] = g_strdup("/usr/lib/ladspa");
225       ags_ladspa_default_path[i++] = g_strdup("/usr/local/lib/ladspa");
226 
227       if(home_dir != NULL){
228 	ags_ladspa_default_path[i++] = g_strdup_printf("%s/.ladspa",
229 						       home_dir);
230       }
231 
232       ags_ladspa_default_path[i++] = NULL;
233 #endif
234     }
235   }
236 }
237 
238 void
ags_ladspa_manager_dispose(GObject * gobject)239 ags_ladspa_manager_dispose(GObject *gobject)
240 {
241   AgsLadspaManager *ladspa_manager;
242 
243   ladspa_manager = AGS_LADSPA_MANAGER(gobject);
244 
245   if(ladspa_manager->ladspa_plugin != NULL){
246     g_list_free_full(ladspa_manager->ladspa_plugin,
247 		     (GDestroyNotify) g_object_unref);
248 
249     ladspa_manager->ladspa_plugin = NULL;
250   }
251 
252   /* call parent */
253   G_OBJECT_CLASS(ags_ladspa_manager_parent_class)->dispose(gobject);
254 }
255 
256 void
ags_ladspa_manager_finalize(GObject * gobject)257 ags_ladspa_manager_finalize(GObject *gobject)
258 {
259   AgsLadspaManager *ladspa_manager;
260 
261   GList *ladspa_plugin;
262 
263   ladspa_manager = AGS_LADSPA_MANAGER(gobject);
264 
265   ladspa_plugin = ladspa_manager->ladspa_plugin;
266 
267   g_list_free_full(ladspa_plugin,
268 		   (GDestroyNotify) g_object_unref);
269 
270   if(ladspa_manager == ags_ladspa_manager){
271     ags_ladspa_manager = NULL;
272   }
273 
274   /* call parent */
275   G_OBJECT_CLASS(ags_ladspa_manager_parent_class)->finalize(gobject);
276 }
277 
278 /**
279  * ags_ladspa_manager_get_default_path:
280  *
281  * Get ladspa manager default plugin path.
282  *
283  * Returns: (element-type utf8) (array zero-terminated=1) (transfer none): the plugin default search path as a string vector
284  *
285  * Since: 3.0.0
286  */
287 gchar**
ags_ladspa_manager_get_default_path()288 ags_ladspa_manager_get_default_path()
289 {
290   return(ags_ladspa_default_path);
291 }
292 
293 /**
294  * ags_ladspa_manager_set_default_path:
295  * @default_path: (element-type utf8) (array zero-terminated=1) (transfer full): the string vector array to use as default path
296  *
297  * Set ladspa manager default plugin path.
298  *
299  * Since: 3.0.0
300  */
301 void
ags_ladspa_manager_set_default_path(gchar ** default_path)302 ags_ladspa_manager_set_default_path(gchar** default_path)
303 {
304   ags_ladspa_default_path = default_path;
305 }
306 
307 /**
308  * ags_ladspa_manager_get_filenames:
309  * @ladspa_manager: the #AgsLadspaManager
310  *
311  * Retrieve all filenames
312  *
313  * Returns: (element-type utf8) (array zero-terminated=1) (transfer full): a %NULL-terminated array of filenames
314  *
315  * Since: 3.0.0
316  */
317 gchar**
ags_ladspa_manager_get_filenames(AgsLadspaManager * ladspa_manager)318 ags_ladspa_manager_get_filenames(AgsLadspaManager *ladspa_manager)
319 {
320   GList *start_ladspa_plugin, *ladspa_plugin;
321 
322   gchar **filenames;
323 
324   guint i;
325   gboolean contains_filename;
326 
327   GRecMutex *ladspa_manager_mutex;
328   GRecMutex *base_plugin_mutex;
329 
330   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager)){
331     return(NULL);
332   }
333 
334   /* get ladspa manager mutex */
335   ladspa_manager_mutex = AGS_LADSPA_MANAGER_GET_OBJ_MUTEX(ladspa_manager);
336 
337   /* collect */
338   g_rec_mutex_lock(ladspa_manager_mutex);
339 
340   ladspa_plugin =
341     start_ladspa_plugin = g_list_copy(ladspa_manager->ladspa_plugin);
342 
343   g_rec_mutex_unlock(ladspa_manager_mutex);
344 
345   filenames = NULL;
346 
347   for(i = 0; ladspa_plugin != NULL;){
348     gchar *filename;
349 
350     /* get base plugin mutex */
351     base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(ladspa_plugin->data);
352 
353     /* duplicate filename */
354     g_rec_mutex_lock(base_plugin_mutex);
355 
356     filename = g_strdup(AGS_BASE_PLUGIN(ladspa_plugin->data)->filename);
357 
358     g_rec_mutex_unlock(base_plugin_mutex);
359 
360     if(filenames == NULL){
361       filenames = (gchar **) malloc(2 * sizeof(gchar *));
362 
363       /* set filename */
364       filenames[i] = filename;
365 
366       /* terminate */
367       filenames[i + 1] = NULL;
368 
369       i++;
370     }else{
371 #ifdef HAVE_GLIB_2_44
372       contains_filename = g_strv_contains(filenames,
373 					  AGS_BASE_PLUGIN(ladspa_plugin->data)->filename);
374 #else
375       contains_filename = ags_strv_contains(filenames,
376 					    AGS_BASE_PLUGIN(ladspa_plugin->data)->filename);
377 #endif
378 
379       if(!contains_filename){
380 	filenames = (gchar **) realloc(filenames,
381 				       (i + 2) * sizeof(gchar *));
382 	filenames[i] = filename;
383 	filenames[i + 1] = NULL;
384 
385 	i++;
386       }else{
387 	g_free(filename);
388       }
389     }
390 
391     ladspa_plugin = ladspa_plugin->next;
392   }
393 
394   g_list_free(start_ladspa_plugin);
395 
396   return(filenames);
397 }
398 
399 /**
400  * ags_ladspa_manager_find_ladspa_plugin:
401  * @ladspa_manager: the #AgsLadspaManager
402  * @filename: the filename of the plugin
403  * @effect: the effect's name
404  *
405  * Lookup filename in loaded plugins.
406  *
407  * Returns: (transfer none): the #AgsLadspaPlugin
408  *
409  * Since: 3.0.0
410  */
411 AgsLadspaPlugin*
ags_ladspa_manager_find_ladspa_plugin(AgsLadspaManager * ladspa_manager,gchar * filename,gchar * effect)412 ags_ladspa_manager_find_ladspa_plugin(AgsLadspaManager *ladspa_manager,
413 				      gchar *filename, gchar *effect)
414 {
415   AgsLadspaPlugin *ladspa_plugin;
416 
417   GList *start_list, *list;
418 
419   gboolean success;
420 
421   GRecMutex *ladspa_manager_mutex;
422   GRecMutex *base_plugin_mutex;
423 
424   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager)){
425     return(NULL);
426   }
427 
428   /* get ladspa manager mutex */
429   ladspa_manager_mutex = AGS_LADSPA_MANAGER_GET_OBJ_MUTEX(ladspa_manager);
430 
431   /* collect */
432   g_rec_mutex_lock(ladspa_manager_mutex);
433 
434   list =
435     start_list = g_list_copy(ladspa_manager->ladspa_plugin);
436 
437   g_rec_mutex_unlock(ladspa_manager_mutex);
438 
439   success = FALSE;
440 
441   while(list != NULL){
442     ladspa_plugin = AGS_LADSPA_PLUGIN(list->data);
443 
444     /* get base plugin mutex */
445     base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(ladspa_plugin);
446 
447     /* check filename and effect */
448     g_rec_mutex_lock(base_plugin_mutex);
449 
450     success = (!g_strcmp0(AGS_BASE_PLUGIN(ladspa_plugin)->filename,
451 			  filename) &&
452 	       !g_strcmp0(AGS_BASE_PLUGIN(ladspa_plugin)->effect,
453 			  effect)) ? TRUE: FALSE;
454 
455     g_rec_mutex_unlock(base_plugin_mutex);
456 
457     if(success){
458       break;
459     }
460 
461     list = list->next;
462   }
463 
464   g_list_free(start_list);
465 
466   if(!success){
467     ladspa_plugin = NULL;
468   }
469 
470   return(ladspa_plugin);
471 }
472 
473 /**
474  * ags_ladspa_manager_find_ladspa_plugin_with_fallback:
475  * @ladspa_manager: the #AgsLadspaManager
476  * @filename: the filename of the plugin
477  * @effect: the effect's name
478  *
479  * Lookup filename in loaded plugins.
480  *
481  * Returns: (transfer none): the #AgsLadspaPlugin
482  *
483  * Since: 3.5.10
484  */
485 AgsLadspaPlugin*
ags_ladspa_manager_find_ladspa_plugin_with_fallback(AgsLadspaManager * ladspa_manager,gchar * filename,gchar * effect)486 ags_ladspa_manager_find_ladspa_plugin_with_fallback(AgsLadspaManager *ladspa_manager,
487 						    gchar *filename, gchar *effect)
488 {
489   AgsLadspaPlugin *ladspa_plugin;
490 
491   GList *start_list, *list;
492 
493   gchar *filename_suffix;
494 
495   gboolean success;
496 
497   GRecMutex *ladspa_manager_mutex;
498   GRecMutex *base_plugin_mutex;
499 
500   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager) ||
501      filename == NULL ||
502      effect == NULL){
503     return(NULL);
504   }
505 
506   /* get ladspa manager mutex */
507   ladspa_manager_mutex = AGS_LADSPA_MANAGER_GET_OBJ_MUTEX(ladspa_manager);
508 
509   ladspa_plugin = ags_ladspa_manager_find_ladspa_plugin(ladspa_manager,
510 							filename, effect);
511 
512   if(ladspa_plugin == NULL){
513     filename_suffix = strrchr(filename, "/");
514 
515     /* collect */
516     g_rec_mutex_lock(ladspa_manager_mutex);
517 
518     list =
519       start_list = g_list_copy(ladspa_manager->ladspa_plugin);
520 
521     g_rec_mutex_unlock(ladspa_manager_mutex);
522 
523     success = FALSE;
524 
525     while(list != NULL){
526       ladspa_plugin = AGS_LADSPA_PLUGIN(list->data);
527 
528       /* get base plugin mutex */
529       base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(ladspa_plugin);
530 
531       /* check filename and effect */
532       g_rec_mutex_lock(base_plugin_mutex);
533 
534       success = (g_str_has_suffix(AGS_BASE_PLUGIN(ladspa_plugin)->filename,
535 				  filename_suffix) &&
536 		 !g_strcmp0(AGS_BASE_PLUGIN(ladspa_plugin)->effect,
537 			    effect)) ? TRUE: FALSE;
538 
539       g_rec_mutex_unlock(base_plugin_mutex);
540 
541       if(success){
542 	break;
543       }
544 
545       list = list->next;
546     }
547 
548     g_list_free(start_list);
549 
550     if(!success){
551       ladspa_plugin = NULL;
552     }
553   }
554 
555   return(ladspa_plugin);
556 }
557 
558 /**
559  * ags_ladspa_manager_load_blacklist:
560  * @ladspa_manager: the #AgsLadspaManager
561  * @blacklist_filename: the filename as string
562  *
563  * Load blacklisted plugin filenames.
564  *
565  * Since: 3.0.0
566  */
567 void
ags_ladspa_manager_load_blacklist(AgsLadspaManager * ladspa_manager,gchar * blacklist_filename)568 ags_ladspa_manager_load_blacklist(AgsLadspaManager *ladspa_manager,
569 				  gchar *blacklist_filename)
570 {
571   GRecMutex *ladspa_manager_mutex;
572 
573   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager) ||
574      blacklist_filename == NULL){
575     return;
576   }
577 
578   /* get ladspa manager mutex */
579   ladspa_manager_mutex = AGS_LADSPA_MANAGER_GET_OBJ_MUTEX(ladspa_manager);
580 
581   /* fill in */
582   g_rec_mutex_lock(ladspa_manager_mutex);
583 
584   if(g_file_test(blacklist_filename,
585 		 (G_FILE_TEST_EXISTS |
586 		  G_FILE_TEST_IS_REGULAR))){
587     FILE *file;
588 
589     gchar *str;
590 
591     file = fopen(blacklist_filename,
592 		 "r");
593 
594 #ifndef AGS_W32API
595     while(getline(&str, NULL, file) != -1){
596       ladspa_manager->ladspa_plugin_blacklist = g_list_prepend(ladspa_manager->ladspa_plugin_blacklist,
597 							       str);
598     }
599 #endif
600   }
601 
602   g_rec_mutex_unlock(ladspa_manager_mutex);
603 }
604 
605 /**
606  * ags_ladspa_manager_load_file:
607  * @ladspa_manager: the #AgsLadspaManager
608  * @ladspa_path: the LADSPA path
609  * @filename: the filename of the plugin
610  *
611  * Load @filename specified plugin.
612  *
613  * Since: 3.0.0
614  */
615 void
ags_ladspa_manager_load_file(AgsLadspaManager * ladspa_manager,gchar * ladspa_path,gchar * filename)616 ags_ladspa_manager_load_file(AgsLadspaManager *ladspa_manager,
617 			     gchar *ladspa_path,
618 			     gchar *filename)
619 {
620   AgsLadspaPlugin *ladspa_plugin;
621 
622   gchar *path;
623   gchar *effect;
624 
625   void *plugin_so;
626   LADSPA_Descriptor_Function ladspa_descriptor;
627   LADSPA_Descriptor *plugin_descriptor;
628   unsigned long i;
629   gboolean success;
630 
631   GRecMutex *ladspa_manager_mutex;
632 
633   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager) ||
634      ladspa_path == NULL ||
635      filename == NULL){
636     return;
637   }
638 
639   /* get ladspa manager mutex */
640   ladspa_manager_mutex = AGS_LADSPA_MANAGER_GET_OBJ_MUTEX(ladspa_manager);
641 
642   /* load */
643   g_rec_mutex_lock(ladspa_manager_mutex);
644 
645   path = g_strdup_printf("%s%c%s",
646 			 ladspa_path,
647 			 G_DIR_SEPARATOR,
648 			 filename);
649 
650   g_message("ags_ladspa_manager.c loading - %s", path);
651 
652 #ifdef AGS_W32API
653   plugin_so = LoadLibrary(path);
654 #else
655   plugin_so = dlopen(path,
656 		     RTLD_NOW);
657 #endif
658 
659   if(plugin_so == NULL){
660     g_warning("ags_ladspa_manager.c - failed to load static object file");
661 
662 #ifndef AGS_W32API
663     dlerror();
664 #endif
665 
666     g_rec_mutex_unlock(ladspa_manager_mutex);
667 
668     return;
669   }
670 
671   success = FALSE;
672 
673 #ifdef AGS_W32API
674   ladspa_descriptor = (LADSPA_Descriptor_Function) GetProcAddress((void *) plugin_so,
675 								  "ladspa_descriptor");
676 
677   success = (!ladspa_descriptor) ? FALSE: TRUE;
678 #else
679   ladspa_descriptor = (LADSPA_Descriptor_Function) dlsym((void *) plugin_so,
680 							 "ladspa_descriptor");
681 
682   success = (dlerror() == NULL) ? TRUE: FALSE;
683 #endif
684 
685   if(success && ladspa_descriptor){
686     for(i = 0; (plugin_descriptor = ladspa_descriptor(i)) != NULL; i++){
687       if(ags_base_plugin_find_effect(ladspa_manager->ladspa_plugin,
688 				     path,
689 				     plugin_descriptor->Name) == NULL){
690 	ladspa_plugin = ags_ladspa_plugin_new(path,
691 					      plugin_descriptor->Name,
692 					      i);
693 	ags_base_plugin_load_plugin((AgsBasePlugin *) ladspa_plugin);
694 	ladspa_manager->ladspa_plugin = g_list_prepend(ladspa_manager->ladspa_plugin,
695 						       ladspa_plugin);
696       }
697     }
698   }
699 
700   g_rec_mutex_unlock(ladspa_manager_mutex);
701 
702   g_free(path);
703 }
704 
705 /**
706  * ags_ladspa_manager_load_default_directory:
707  * @ladspa_manager: the #AgsLadspaManager
708  *
709  * Loads all available plugins.
710  *
711  * Since: 3.0.0
712  */
713 void
ags_ladspa_manager_load_default_directory(AgsLadspaManager * ladspa_manager)714 ags_ladspa_manager_load_default_directory(AgsLadspaManager *ladspa_manager)
715 {
716   AgsLadspaPlugin *ladspa_plugin;
717 
718   GDir *dir;
719 
720   gchar **ladspa_path;
721   gchar *filename;
722 
723   GError *error;
724 
725   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager)){
726     return;
727   }
728 
729   ladspa_path = ags_ladspa_default_path;
730 
731   while(*ladspa_path != NULL){
732     if(!g_file_test(*ladspa_path,
733 		    G_FILE_TEST_EXISTS)){
734       ladspa_path++;
735 
736       continue;
737     }
738 
739     error = NULL;
740     dir = g_dir_open(*ladspa_path,
741 		     0,
742 		     &error);
743 
744     if(error != NULL){
745       g_warning("%s", error->message);
746 
747       ladspa_path++;
748 
749       g_error_free(error);
750 
751       continue;
752     }
753 
754     while((filename = g_dir_read_name(dir)) != NULL){
755       if(g_str_has_suffix(filename,
756 			  AGS_LIBRARY_SUFFIX) &&
757 	 !g_list_find_custom(ladspa_manager->ladspa_plugin_blacklist,
758 			     filename,
759 			     strcmp)){
760 	ags_ladspa_manager_load_file(ladspa_manager,
761 				     *ladspa_path,
762 				     filename);
763       }
764     }
765 
766     ladspa_path++;
767   }
768 }
769 
770 /**
771  * ags_ladspa_manager_get_ladspa_plugin:
772  * @ladspa_manager: the #AgsLadspaManager
773  *
774  * Get ladspa plugin.
775  *
776  * Returns: (transfer full): the #GList-struct containing #AgsLadspaPlugin
777  *
778  * Since: 3.5.15
779  */
780 GList*
ags_ladspa_manager_get_ladspa_plugin(AgsLadspaManager * ladspa_manager)781 ags_ladspa_manager_get_ladspa_plugin(AgsLadspaManager *ladspa_manager)
782 {
783   GList *ladspa_plugin;
784 
785   GRecMutex *ladspa_manager_mutex;
786 
787   if(!AGS_IS_LADSPA_MANAGER(ladspa_manager)){
788     return(NULL);
789   }
790 
791   /* get ladspa manager mutex */
792   ladspa_manager_mutex = AGS_LADSPA_MANAGER_GET_OBJ_MUTEX(ladspa_manager);
793 
794   g_rec_mutex_lock(ladspa_manager_mutex);
795 
796   ladspa_plugin = g_list_copy_deep(ladspa_manager->ladspa_plugin,
797 				   (GCopyFunc) g_object_ref,
798 				   NULL);
799 
800   g_rec_mutex_unlock(ladspa_manager_mutex);
801 
802   return(ladspa_plugin);
803 }
804 
805 /**
806  * ags_ladspa_manager_get_instance:
807  *
808  * Get instance.
809  *
810  * Returns: (transfer none): the #AgsLadspaManager
811  *
812  * Since: 3.0.0
813  */
814 AgsLadspaManager*
ags_ladspa_manager_get_instance()815 ags_ladspa_manager_get_instance()
816 {
817   static GMutex mutex;
818 
819   g_mutex_lock(&mutex);
820 
821   if(ags_ladspa_manager == NULL){
822     ags_ladspa_manager = ags_ladspa_manager_new();
823   }
824 
825   g_mutex_unlock(&mutex);
826 
827   return(ags_ladspa_manager);
828 }
829 
830 /**
831  * ags_ladspa_manager_new:
832  *
833  * Create a new instance of #AgsLadspaManager
834  *
835  * Returns: the new #AgsLadspaManager
836  *
837  * Since: 3.0.0
838  */
839 AgsLadspaManager*
ags_ladspa_manager_new()840 ags_ladspa_manager_new()
841 {
842   AgsLadspaManager *ladspa_manager;
843 
844   ladspa_manager = (AgsLadspaManager *) g_object_new(AGS_TYPE_LADSPA_MANAGER,
845 						     NULL);
846 
847   return(ladspa_manager);
848 }
849