12 #define MAX_STRING_LEN 256
17 extern char * strdup (const char *);
19 static char *read_string( FILE *fp ) {
20 char buf[MAX_STRING_LEN];
22 fgets( buf, MAX_STRING_LEN, fp );
23 if( strlen( buf ) < MAX_STRING_LEN ) {
26 buf[strlen(buf)-1] = 0;
34 static FSTInfo *load_fst_info_file( char *filename ) {
36 FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
44 fp = fopen( filename, "r" );
51 if( (info->name = read_string( fp )) == NULL ) goto error;
52 if( (info->creator = read_string( fp )) == NULL ) goto error;
53 if( 1 != fscanf( fp, "%d\n", &info->UniqueID ) ) goto error;
54 if( (info->Category = read_string( fp )) == NULL ) goto error;
55 if( 1 != fscanf( fp, "%d\n", &info->numInputs ) ) goto error;
56 if( 1 != fscanf( fp, "%d\n", &info->numOutputs ) ) goto error;
57 if( 1 != fscanf( fp, "%d\n", &info->numParams ) ) goto error;
58 if( 1 != fscanf( fp, "%d\n", &info->wantMidi ) ) goto error;
59 if( 1 != fscanf( fp, "%d\n", &info->hasEditor ) ) goto error;
60 if( 1 != fscanf( fp, "%d\n", &info->canProcessReplacing ) ) goto error;
62 if( (info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
63 for( i=0; i<info->numParams; i++ ) {
64 if( (info->ParamNames[i] = read_string( fp )) == NULL ) goto error;
66 if( (info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
67 for( i=0; i<info->numParams; i++ ) {
68 if( (info->ParamLabels[i] = read_string( fp )) == NULL ) goto error;
81 static int save_fst_info_file( FSTInfo *info, char *filename ) {
88 fst_error( "info is NULL\n" );
92 fp = fopen( filename, "w" );
95 fst_error( "Cant write info file %s\n", filename );
99 fprintf( fp, "%s\n", info->name );
100 fprintf( fp, "%s\n", info->creator );
101 fprintf( fp, "%d\n", info->UniqueID );
102 fprintf( fp, "%s\n", info->Category );
103 fprintf( fp, "%d\n", info->numInputs );
104 fprintf( fp, "%d\n", info->numOutputs );
105 fprintf( fp, "%d\n", info->numParams );
106 fprintf( fp, "%d\n", info->wantMidi );
107 fprintf( fp, "%d\n", info->hasEditor );
108 fprintf( fp, "%d\n", info->canProcessReplacing );
110 for( i=0; i<info->numParams; i++ ) {
111 fprintf( fp, "%s\n", info->ParamNames[i] );
113 for( i=0; i<info->numParams; i++ ) {
114 fprintf( fp, "%s\n", info->ParamLabels[i] );
123 static char *fst_dllpath_to_infopath( char *dllpath ) {
125 if( strstr( dllpath, ".dll" ) == NULL ) return NULL;
127 retval = strdup( dllpath );
128 sprintf( retval + strlen(retval) - 4, ".fsi" );
132 static int fst_info_file_is_valid( char *dllpath ) {
133 struct stat dllstat, fststat;
134 char *fstpath = fst_dllpath_to_infopath( dllpath );
136 if( !fstpath ) return FALSE;
138 if( stat( dllpath, &dllstat ) ){ fst_error( "dll path %s invalid\n", dllpath ); return TRUE; }
139 if( stat( fstpath, &fststat ) ) return FALSE;
142 if( dllstat.st_mtime > fststat.st_mtime )
148 static int fst_can_midi( FST *fst ) {
149 struct AEffect *plugin = fst->plugin;
150 int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
152 if (vst_version >= 2) {
154 /* should we send it VST events (i.e. MIDI) */
156 if ((plugin->flags & effFlagsIsSynth) ||
157 (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
163 static FSTInfo *fst_info_from_plugin( FST *fst ) {
164 FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
165 struct AEffect *plugin;
170 fst_error( "fst is NULL\n" );
174 if( ! info ) return NULL;
176 plugin = fst->plugin;
179 info->name = strdup(fst->handle->name );
180 plugin->dispatcher (plugin, 47 /* effGetVendorString */, 0, 0, creator, 0);
181 if (strlen (creator) == 0) {
182 info->creator = strdup ("Unknown");
184 info->creator = strdup (creator);
187 #ifdef VESTIGE_HEADER
188 info->UniqueID = *((int32_t *) &plugin->unused_id);
190 info->UniqueID = plugin->uniqueID;
193 info->Category = strdup( "None" ); // FIXME:
194 info->numInputs = plugin->numInputs;
195 info->numOutputs = plugin->numOutputs;
196 info->numParams = plugin->numParams;
197 info->wantMidi = fst_can_midi( fst );
198 info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
199 info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
201 info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams );
202 info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams );
203 for( i=0; i<info->numParams; i++ ) {
206 plugin->dispatcher (plugin,
209 info->ParamNames[i] = strdup( name );
210 plugin->dispatcher (plugin,
211 6 /* effGetParamLabel */,
213 info->ParamLabels[i] = strdup( label );
218 // most simple one :) could be sufficient....
219 static long simple_master_callback( struct AEffect *fx, long opcode, long index, long value, void *ptr, float opt ) {
220 if( opcode == audioMasterVersion )
226 FSTInfo *fst_get_info( char *dllpath ) {
228 if( fst_info_file_is_valid( dllpath ) ) {
230 char *fstpath = fst_dllpath_to_infopath( dllpath );
232 info = load_fst_info_file( fstpath );
243 if( !(h = fst_load( dllpath )) ) return NULL;
244 if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) {
246 fst_error( "instantiate failed\n" );
249 fstpath = fst_dllpath_to_infopath( dllpath );
253 fst_error( "get fst filename failed\n" );
256 info = fst_info_from_plugin( fst );
257 save_fst_info_file( info, fstpath );
266 void fst_free_info( FSTInfo *info ) {
270 for( i=0; i<info->numParams; i++ ) {
271 free( info->ParamNames[i] );
272 free( info->ParamLabels[i] );
275 free( info->creator );
276 free( info->Category );