fixes for 98% of all the warnings/errors reported by OS X gcc on tiger
[ardour.git] / libs / ardour / vstfxinfofile.cc
1 /***********************************************************/
2 /*vstfx infofile - module to manage info files             */
3 /*containing cached information about a plugin. e.g. its   */
4 /*name, creator etc etc                                    */
5 /***********************************************************/
6
7 /*This is largely unmodified from the original (C code) FST vstinfofile module*/
8
9 #include "ardour/vstfx.h"
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14
15 #include <stdlib.h>
16 #include <stddef.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <libgen.h>
20
21 #define MAX_STRING_LEN 256
22
23 #define FALSE 0
24 #define TRUE !FALSE
25
26 static char* read_string(FILE *fp)
27 {
28     char buf[MAX_STRING_LEN];
29
30     fgets( buf, MAX_STRING_LEN, fp );
31         
32     if(strlen(buf) < MAX_STRING_LEN)
33         {
34                 if(strlen(buf))
35                 buf[strlen(buf)-1] = 0;
36
37                 return strdup(buf);
38     }
39         else
40         {
41                 return NULL;
42     }
43 }
44
45 static VSTFXInfo* load_vstfx_info_file(char *filename)
46 {
47         VSTFXInfo *info = (VSTFXInfo*) malloc(sizeof(VSTFXInfo));
48     FILE *fp;
49     int i;
50         
51     if(info == NULL)
52                 return NULL;
53
54     fp = fopen(filename, "r");
55     
56     if(fp == NULL)
57         {
58                 free( info );
59                 return NULL;
60     }
61
62     if((info->name = read_string(fp)) == NULL) goto error;
63     if((info->creator = read_string(fp)) == NULL) goto error;
64     if(1 != fscanf(fp, "%d\n", &info->UniqueID)) goto error;
65     if((info->Category = read_string(fp)) == NULL) goto error;
66     if(1 != fscanf(fp, "%d\n", &info->numInputs)) goto error;
67     if(1 != fscanf(fp, "%d\n", &info->numOutputs)) goto error;
68     if(1 != fscanf(fp, "%d\n", &info->numParams)) goto error;
69     if(1 != fscanf(fp, "%d\n", &info->wantMidi)) goto error;
70     if(1 != fscanf(fp, "%d\n", &info->hasEditor)) goto error;
71     if(1 != fscanf(fp, "%d\n", &info->canProcessReplacing)) goto error;
72
73     if((info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams)) == NULL) goto error;
74     for(i=0; i<info->numParams; i++)
75         {
76                 if((info->ParamNames[i] = read_string(fp)) == NULL) goto error;
77     }
78     if((info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams)) == NULL) goto error;
79     
80         for(i=0; i < info->numParams; i++)
81         {
82                 if((info->ParamLabels[i] = read_string(fp)) == NULL) goto error;
83     }
84         
85     fclose( fp );
86     return info;
87
88 error:
89     fclose( fp );
90     free( info );
91     return NULL;
92 }
93
94 static int save_vstfx_info_file(VSTFXInfo *info, char *filename)
95 {
96     FILE *fp;
97     int i;
98
99     if(info == NULL)
100         {
101                 vstfx_error("** ERROR ** VSTFXinfofile : info ptr is NULL\n");
102                 return TRUE;
103     }
104
105     fp = fopen(filename, "w");
106     
107     if(fp == NULL)
108         {
109                 vstfx_error("** WARNING ** VSTFX : Can't write info file %s\n", filename);
110                 return TRUE;
111     }
112
113     fprintf( fp, "%s\n", info->name );
114     fprintf( fp, "%s\n", info->creator );
115     fprintf( fp, "%d\n", info->UniqueID );
116     fprintf( fp, "%s\n", info->Category );
117     fprintf( fp, "%d\n", info->numInputs );
118     fprintf( fp, "%d\n", info->numOutputs );
119     fprintf( fp, "%d\n", info->numParams );
120     fprintf( fp, "%d\n", info->wantMidi );
121     fprintf( fp, "%d\n", info->hasEditor );
122     fprintf( fp, "%d\n", info->canProcessReplacing );
123
124     for(i=0; i < info->numParams; i++)
125         {
126                 fprintf(fp, "%s\n", info->ParamNames[i]);
127     }
128         
129     for(i=0; i < info->numParams; i++)
130         {
131                 fprintf(fp, "%s\n", info->ParamLabels[i]);
132     }
133         
134     fclose( fp );
135
136     return FALSE;
137 }
138
139 static char* vstfx_dllpath_to_infopath(char *dllpath)
140 {
141     char* retval;
142         char* dir_path;
143         char* base_name;
144         
145     if(strstr(dllpath, ".so" ) == NULL)
146                 return NULL;
147     
148         /*Allocate space for the filename - need strlen + 1 for the terminating'0', +1 because .so is three
149         chars, and .fsi is four chars and +1 because we have a '.' at the beginning*/
150         
151         retval = (char*)malloc(strlen(dllpath) + 3);
152         
153         dir_path = strdup(dllpath);
154         base_name = strdup(dllpath);
155         
156         sprintf(retval, "%s/.%s", dirname(dir_path), basename(base_name));
157         sprintf(retval + strlen(retval) - 3, ".fsi");
158         
159         free(dir_path);
160         free(base_name);
161         
162     return retval;
163 }
164
165 static int vstfx_info_file_is_valid(char *dllpath)
166 {
167     struct stat dllstat;
168         struct stat vstfxstat;
169         
170     char *vstfxpath = vstfx_dllpath_to_infopath(dllpath);
171         
172     if(!vstfxpath)
173                 return FALSE;
174     
175     if(stat(dllpath, &dllstat))
176         {
177                 vstfx_error( "** ERROR ** VSTFXinfofile : .so path %s invalid\n", dllpath );
178                         return TRUE;
179         }
180         
181     if(stat(vstfxpath, &vstfxstat))
182                 return FALSE;
183
184     free(vstfxpath);
185         
186     if(dllstat.st_mtime > vstfxstat.st_mtime)
187                 return FALSE;
188     else 
189                 return TRUE;
190 }
191
192 static int vstfx_can_midi(VSTFX *vstfx)
193 {
194         struct AEffect *plugin = vstfx->plugin;
195         
196         int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
197
198         if (vst_version >= 2)
199         {
200                 /* should we send it VST events (i.e. MIDI) */
201                 
202                 if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
203                     return TRUE;
204         }
205         return FALSE;
206 }
207
208 static VSTFXInfo* vstfx_info_from_plugin(VSTFX *vstfx)
209 {
210
211         VSTFXInfo* info = (VSTFXInfo*) malloc(sizeof(VSTFXInfo));
212         
213     struct AEffect *plugin;
214     int i;
215
216         /*We need to init the creator because some plugins
217         fail to implement getVendorString, and so won't stuff the
218         string with any name*/
219         
220     char creator[65] = "Unknown\0";
221
222     if(!vstfx)
223         {
224                 vstfx_error( "** ERROR ** VSTFXinfofile : vstfx ptr is NULL\n" );
225                 return NULL;
226     }
227
228     if(!info)
229                 return NULL;
230     
231     plugin = vstfx->plugin;
232         
233     info->name = strdup(vstfx->handle->name ); 
234         
235         /*If the plugin doesn't bother to implement GetVendorString we will
236         have pre-stuffed the string with 'Unkown' */
237         
238     plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0);
239         
240         /*Some plugins DO implement GetVendorString, but DON'T put a name in it
241         so if its just a zero length string we replace it with 'Unknown' */
242         
243     if (strlen(creator) == 0)
244         {
245       info->creator = strdup("Unknown");
246     }
247         else
248         {
249       info->creator = strdup (creator);
250     }
251
252 #if defined LXVST_64BIT && defined VESTIGE_HEADER
253
254         /*On 64Bit the data alignment in AEffect struct is
255         incorrect using vestige.  see lxvst_plugin.cc*/
256         
257         info->UniqueID = *((int32_t *) &((AEffect*)(((char*)(plugin)) + 12))->unused_id);
258         
259 #elif defined LXVST_32BIT && defined VESTIGE_HEADER
260
261     info->UniqueID = *((int32_t *) &plugin->unused_id);
262
263 #else
264
265     info->UniqueID = plugin->uniqueID;
266
267 #endif
268
269     info->Category = strdup("None");          // FIXME:  
270     info->numInputs = plugin->numInputs;
271     info->numOutputs = plugin->numOutputs;
272     info->numParams = plugin->numParams;
273     info->wantMidi = vstfx_can_midi(vstfx); 
274         info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
275     info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
276     info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams);
277     info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams);
278     for(i=0; i < info->numParams; i++)
279         {
280                 char name[64];
281                 char label[64];
282                 
283                 /*Not all plugins give parameters labels as well as names*/
284                 
285                 strcpy(name, "No Name");
286                 strcpy(label, "No Label");
287                 
288                 plugin->dispatcher (plugin, effGetParamName, i, 0, name, 0);
289                 info->ParamNames[i] = strdup(name);
290                 
291                 plugin->dispatcher (plugin, effGetParamLabel, i, 0, label, 0);
292                 info->ParamLabels[i] = strdup(label);
293     }
294     return info;
295 }
296
297 /* A simple 'dummy' audiomaster callback which should be ok,
298 we will only be instantiating the plugin in order to get its info*/
299
300 static long simple_master_callback(struct AEffect *, long opcode, long, long, void *, float)
301 {
302
303         if (opcode == audioMasterVersion)
304                 return 2;
305         else
306                 return 0;
307 }
308
309 /*Try to get plugin info - first by looking for a .fsi cache of the
310 data, and if that doesn't exist, load the plugin, get its data and
311 then cache it for future ref*/
312
313 VSTFXInfo *vstfx_get_info(char *dllpath)
314 {
315         if( vstfx_info_file_is_valid(dllpath))
316         {
317                 VSTFXInfo *info;
318                 char *vstfxpath = vstfx_dllpath_to_infopath(dllpath);
319
320                 info = load_vstfx_info_file(vstfxpath);
321                 free(vstfxpath);
322                 
323                 return info;
324     }
325         else
326         {
327                 VSTFXHandle *h;
328                 VSTFX *vstfx;
329                 VSTFXInfo *info;
330                 
331                 char *vstfxpath;
332                 
333                 if(!(h = vstfx_load(dllpath)))
334                         return NULL;
335                                                         
336                 if(!(vstfx = vstfx_instantiate(h, simple_master_callback, NULL)))
337                 {
338                 vstfx_unload(h);
339                 vstfx_error( "** ERROR ** VSTFXinfofile : Instantiate failed\n" );
340                 return NULL;
341                 }
342                 
343                 vstfxpath = vstfx_dllpath_to_infopath(dllpath);
344                 
345                 if(!vstfxpath)
346                 {
347                 vstfx_close(vstfx);
348                 vstfx_unload(h);
349                 vstfx_error( "** ERROR ** VSTFXinfofile : get vstfx filename failed\n" );
350                 return NULL;
351                 }
352                 
353                 info = vstfx_info_from_plugin(vstfx);
354                 
355                 save_vstfx_info_file(info, vstfxpath);
356
357                 free(vstfxpath);
358                 
359                 vstfx_close(vstfx);
360                 vstfx_unload(h);
361                 
362                 return info;
363     }
364 }
365
366 void vstfx_free_info(VSTFXInfo *info )
367 {
368     int i;
369
370     for(i=0; i < info->numParams; i++)
371         {
372                 free(info->ParamNames[i]);
373                 free(info->ParamLabels[i]);
374     }
375         
376     free(info->name);
377     free(info->creator);
378     free(info->Category);
379     free(info);
380 }
381
382