1 /* dssi_list_plugins.c
2 *
3 * Written by Sean Bolton, with inspiration from Richard Furse's listplugins
4 * from the LADSPA SDK.
5 *
6 * This program is in the public domain.
7 *
8 * $Id: dssi_list_plugins.c,v 1.1 2010/06/27 19:30:09 smbolton Exp $
9 */
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <sys/types.h>
15 #include <dirent.h>
16 #include <errno.h>
17 #include <sys/stat.h>
18 #include <dlfcn.h>
19
20 #include <ladspa.h>
21 #include "dssi.h"
22
23 struct duplicate_list {
24 struct duplicate_list *next;
25 const char *item;
26 };
27
28 struct duplicate_list *dup_list = NULL;
29
30 int verbose = 0;
31
32 void
check_for_duplicates(const char * filename)33 check_for_duplicates(const char *filename)
34 {
35 struct duplicate_list *d;
36
37 for (d = dup_list; d; d = d->next) {
38 if (!strcmp(d->item, filename)) {
39 printf("-- warning: shared library '%s' appears more than once on DSSI_PATH\n", filename);
40 return;
41 }
42 }
43
44 /* not found, add it to the list */
45 d = (struct duplicate_list *)malloc(sizeof(struct duplicate_list));
46 d->item = strdup(filename);
47 d->next = dup_list;
48 dup_list = d;
49 }
50
51 void
free_dup_list(void)52 free_dup_list(void)
53 {
54 struct duplicate_list *d;
55
56 while (dup_list) {
57 d = dup_list;
58 dup_list = d->next;
59 free((char *)d->item);
60 free(d);
61 }
62 }
63
64 void
list_dssi_plugins(DSSI_Descriptor_Function descriptor_function)65 list_dssi_plugins(DSSI_Descriptor_Function descriptor_function)
66 {
67 int i;
68 const DSSI_Descriptor *descriptor;
69
70 for (i = 0; (descriptor = descriptor_function(i)); i++)
71 printf("\t%-16s %s\n", descriptor->LADSPA_Plugin->Label,
72 descriptor->LADSPA_Plugin->Name);
73
74 if (verbose && i == 0)
75 printf("-- odd ... no plugins found within this shared object\n");
76 }
77
78 void
list_ladspa_plugins(LADSPA_Descriptor_Function descriptor_function)79 list_ladspa_plugins(LADSPA_Descriptor_Function descriptor_function)
80 {
81 int i;
82 const LADSPA_Descriptor *descriptor;
83
84 for (i = 0; (descriptor = descriptor_function(i)); i++)
85 printf("\t%-16s (%lu) %s\n", descriptor->Label, descriptor->UniqueID, descriptor->Name);
86
87 if (verbose && i == 0)
88 printf("-- odd ... no plugins found within this shared object\n");
89 }
90
91 void
list_directory(char * directory)92 list_directory(char *directory)
93 {
94 int directory_length = strlen(directory);
95 DIR *dir;
96 struct dirent *dirent;
97 char *filename;
98 struct stat statbuf;
99 void *handle;
100 int found = 0;
101
102 if (directory_length == 0) {
103 if (verbose) printf("-- warning: skipping zero-length element in DSSI_PATH\n");
104 return;
105 }
106 if (directory[directory_length - 1] == '/')
107 directory[directory_length - 1] = 0; /* slash gets added again below */
108
109 dir = opendir(directory);
110 if (!dir) {
111 if (verbose) printf("-- warning: couldn't open DSSI_PATH directory element '%s'\n", directory);
112 return;
113 }
114
115 if (verbose) printf("-- scanning directory %s\n", directory);
116
117 while ((dirent = readdir(dir)) != NULL) {
118
119 if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
120 continue;
121
122 filename = malloc(directory_length + strlen(dirent->d_name) + 2);
123 sprintf(filename, "%s/%s", directory, dirent->d_name);
124
125 if (stat(filename, &statbuf)) {
126 if (verbose)
127 printf("-- warning: couldn't stat file '%s': %s\n", filename, strerror(errno));
128 free(filename);
129 continue;
130 }
131 if (S_ISDIR(statbuf.st_mode)) { /* silently skip subdirectories */
132 free(filename);
133 continue;
134 }
135
136 handle = dlopen(filename, RTLD_LAZY);
137 if (handle) {
138 DSSI_Descriptor_Function dssi_descriptor_function;
139 LADSPA_Descriptor_Function ladspa_descriptor_function;
140
141 if (verbose)
142 check_for_duplicates(dirent->d_name);
143
144 dssi_descriptor_function = (DSSI_Descriptor_Function)dlsym(handle, "dssi_descriptor");
145 ladspa_descriptor_function = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
146
147 if (dssi_descriptor_function) {
148 printf("%s\n", filename);
149 list_dssi_plugins(dssi_descriptor_function);
150 found++;
151 } else if (ladspa_descriptor_function) {
152 printf("%s (LADSPA-only)\n", filename);
153 list_ladspa_plugins(ladspa_descriptor_function);
154 } else {
155 if (verbose)
156 printf("-- warning: shared object '%s' is neither a LADSPA nor DSSI plugin\n", filename);
157 }
158 dlclose(handle);
159 } else { /* not a library */
160 int len = strlen(dirent->d_name);
161
162 if (len > 4 && !strcmp(dirent->d_name + len - 3, ".la")) { /* libtool *.la file */
163 /* if (verbose) printf("-- skipping file '%s'\n", filename); */
164 } else
165 if (verbose)
166 printf("-- warning: couldn't dlopen file '%s': %s\n", filename, dlerror());
167 }
168 free(filename);
169 }
170
171 closedir(dir);
172
173 if (verbose && found == 0)
174 printf("-- odd ... no DSSI plugins were found in this directory\n");
175 }
176
177 void
usage(const char * program_name)178 usage(const char *program_name)
179 {
180 fprintf(stderr, "usage: %s [-v|--verbose]\n", program_name);
181 fprintf(stderr, "Scan the directories listed in environment variable DSSI_PATH, and list\n");
182 fprintf(stderr, "the DSSI plugins found therein. Optional arguments:\n");
183 fprintf(stderr, " -v, --verbose describe the scan and error conditions more verbosely.\n");
184
185 exit(1);
186 }
187
188 int
main(int argc,char * argv[])189 main(int argc, char *argv[])
190 {
191 char *path, *pathtmp, *element;
192
193 while (argc > 1) {
194 argc--;
195 if (!strcmp(argv[argc], "-v") || !strcmp(argv[argc], "--verbose"))
196 verbose = 1;
197 else
198 usage(argv[0]); /* does not return */
199 }
200
201 path = getenv("DSSI_PATH");
202 if (!path) {
203 path = "/usr/local/lib/dssi:/usr/lib/dssi";
204 fprintf(stderr, "warning: DSSI_PATH not set, defaulting to '%s'\n", path);
205 }
206
207 path = strdup(path);
208 pathtmp = path;
209 while ((element = strtok(pathtmp, ":")) != 0) {
210 pathtmp = NULL;
211 list_directory(element);
212 }
213 free(path);
214
215 free_dup_list();
216
217 return 0;
218 }
219
220