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 /***********************************************************/
7 /*This is largely unmodified from the original (C code) FST vstinfofile module*/
9 #include "ardour/vstfx.h"
11 #include <sys/types.h>
21 #define MAX_STRING_LEN 256
26 static char* read_string(FILE *fp)
28 char buf[MAX_STRING_LEN];
30 fgets( buf, MAX_STRING_LEN, fp );
32 if(strlen(buf) < MAX_STRING_LEN)
35 buf[strlen(buf)-1] = 0;
45 static VSTFXInfo* load_vstfx_info_file(char *filename)
47 VSTFXInfo *info = (VSTFXInfo*) malloc(sizeof(VSTFXInfo));
54 fp = fopen(filename, "r");
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;
73 if((info->ParamNames = (char **) malloc(sizeof(char*)*info->numParams)) == NULL) goto error;
74 for(i=0; i<info->numParams; i++)
76 if((info->ParamNames[i] = read_string(fp)) == NULL) goto error;
78 if((info->ParamLabels = (char **) malloc(sizeof(char*)*info->numParams)) == NULL) goto error;
80 for(i=0; i < info->numParams; i++)
82 if((info->ParamLabels[i] = read_string(fp)) == NULL) goto error;
94 static int save_vstfx_info_file(VSTFXInfo *info, char *filename)
101 vstfx_error("** ERROR ** VSTFXinfofile : info ptr is NULL\n");
105 fp = fopen(filename, "w");
109 vstfx_error("** WARNING ** VSTFX : Can't write info file %s\n", filename);
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 );
124 for(i=0; i < info->numParams; i++)
126 fprintf(fp, "%s\n", info->ParamNames[i]);
129 for(i=0; i < info->numParams; i++)
131 fprintf(fp, "%s\n", info->ParamLabels[i]);
139 static char* vstfx_dllpath_to_infopath(char *dllpath)
145 if(strstr(dllpath, ".so" ) == NULL)
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*/
151 retval = (char*)malloc(strlen(dllpath) + 3);
153 dir_path = strdup(dllpath);
154 base_name = strdup(dllpath);
156 sprintf(retval, "%s/.%s", dirname(dir_path), basename(base_name));
157 sprintf(retval + strlen(retval) - 3, ".fsi");
165 static int vstfx_info_file_is_valid(char *dllpath)
168 struct stat vstfxstat;
170 char *vstfxpath = vstfx_dllpath_to_infopath(dllpath);
175 if(stat(dllpath, &dllstat))
177 vstfx_error( "** ERROR ** VSTFXinfofile : .so path %s invalid\n", dllpath );
181 if(stat(vstfxpath, &vstfxstat))
186 if(dllstat.st_mtime > vstfxstat.st_mtime)
192 static int vstfx_can_midi(VSTFX *vstfx)
194 struct AEffect *plugin = vstfx->plugin;
196 int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
198 if (vst_version >= 2)
200 /* should we send it VST events (i.e. MIDI) */
202 if ((plugin->flags & effFlagsIsSynth) || (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
208 static VSTFXInfo* vstfx_info_from_plugin(VSTFX *vstfx)
211 VSTFXInfo* info = (VSTFXInfo*) malloc(sizeof(VSTFXInfo));
213 struct AEffect *plugin;
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*/
220 char creator[65] = "Unknown\0";
224 vstfx_error( "** ERROR ** VSTFXinfofile : vstfx ptr is NULL\n" );
231 plugin = vstfx->plugin;
233 info->name = strdup(vstfx->handle->name );
235 /*If the plugin doesn't bother to implement GetVendorString we will
236 have pre-stuffed the string with 'Unkown' */
238 plugin->dispatcher (plugin, effGetVendorString, 0, 0, creator, 0);
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' */
243 if (strlen(creator) == 0)
245 info->creator = strdup("Unknown");
249 info->creator = strdup (creator);
252 #if defined LXVST_64BIT && defined VESTIGE_HEADER
254 /*On 64Bit the data alignment in AEffect struct is
255 incorrect using vestige. see lxvst_plugin.cc*/
257 info->UniqueID = *((int32_t *) &((AEffect*)(((char*)(plugin)) + 12))->unused_id);
259 #elif defined LXVST_32BIT && defined VESTIGE_HEADER
261 info->UniqueID = *((int32_t *) &plugin->unused_id);
265 info->UniqueID = plugin->uniqueID;
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++)
283 /*Not all plugins give parameters labels as well as names*/
285 strcpy(name, "No Name");
286 strcpy(label, "No Label");
288 plugin->dispatcher (plugin, effGetParamName, i, 0, name, 0);
289 info->ParamNames[i] = strdup(name);
291 plugin->dispatcher (plugin, effGetParamLabel, i, 0, label, 0);
292 info->ParamLabels[i] = strdup(label);
297 /* A simple 'dummy' audiomaster callback which should be ok,
298 we will only be instantiating the plugin in order to get its info*/
300 static long simple_master_callback(struct AEffect *fx, long opcode, long index, long value, void *ptr, float opt)
303 if(opcode == audioMasterVersion)
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*/
313 VSTFXInfo *vstfx_get_info(char *dllpath)
315 if( vstfx_info_file_is_valid(dllpath))
318 char *vstfxpath = vstfx_dllpath_to_infopath(dllpath);
320 info = load_vstfx_info_file(vstfxpath);
333 if(!(h = vstfx_load(dllpath)))
336 if(!(vstfx = vstfx_instantiate(h, simple_master_callback, NULL)))
339 vstfx_error( "** ERROR ** VSTFXinfofile : Instantiate failed\n" );
343 vstfxpath = vstfx_dllpath_to_infopath(dllpath);
349 vstfx_error( "** ERROR ** VSTFXinfofile : get vstfx filename failed\n" );
353 info = vstfx_info_from_plugin(vstfx);
355 save_vstfx_info_file(info, vstfxpath);
366 void vstfx_free_info(VSTFXInfo *info )
370 for(i=0; i < info->numParams; i++)
372 free(info->ParamNames[i]);
373 free(info->ParamLabels[i]);
378 free(info->Category);