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