12 #define MAX_STRING_LEN 256
17 static char *read_string( FILE *fp ) {
18 char buf[MAX_STRING_LEN];
20 fgets( buf, MAX_STRING_LEN, fp );
21 if( strlen( buf ) < MAX_STRING_LEN ) {
24 buf[strlen(buf)-1] = 0;
32 static FSTInfo *load_fst_info_file( char *filename ) {
34 FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
42 fp = fopen( filename, "r" );
49 if( (info->name = read_string( fp )) == NULL ) goto error;
50 if( (info->creator = read_string( fp )) == NULL ) goto error;
51 if( 1 != fscanf( fp, "%d\n", &info->UniqueID ) ) goto error;
52 if( (info->Category = read_string( fp )) == NULL ) goto error;
53 if( 1 != fscanf( fp, "%d\n", &info->numInputs ) ) goto error;
54 if( 1 != fscanf( fp, "%d\n", &info->numOutputs ) ) goto error;
55 if( 1 != fscanf( fp, "%d\n", &info->numParams ) ) goto error;
56 if( 1 != fscanf( fp, "%d\n", &info->wantMidi ) ) goto error;
57 if( 1 != fscanf( fp, "%d\n", &info->hasEditor ) ) goto error;
58 if( 1 != fscanf( fp, "%d\n", &info->canProcessReplacing ) ) goto error;
60 if( (info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
61 for( i=0; i<info->numParams; i++ ) {
62 if( (info->ParamNames[i] = read_string( fp )) == NULL ) goto error;
64 if( (info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
65 for( i=0; i<info->numParams; i++ ) {
66 if( (info->ParamLabels[i] = read_string( fp )) == NULL ) goto error;
79 static int save_fst_info_file( FSTInfo *info, char *filename ) {
86 fst_error( "info is NULL\n" );
90 fp = fopen( filename, "w" );
93 fst_error( "Cant write info file %s\n", filename );
97 fprintf( fp, "%s\n", info->name );
98 fprintf( fp, "%s\n", info->creator );
99 fprintf( fp, "%d\n", info->UniqueID );
100 fprintf( fp, "%s\n", info->Category );
101 fprintf( fp, "%d\n", info->numInputs );
102 fprintf( fp, "%d\n", info->numOutputs );
103 fprintf( fp, "%d\n", info->numParams );
104 fprintf( fp, "%d\n", info->wantMidi );
105 fprintf( fp, "%d\n", info->hasEditor );
106 fprintf( fp, "%d\n", info->canProcessReplacing );
108 for( i=0; i<info->numParams; i++ ) {
109 fprintf( fp, "%s\n", info->ParamNames[i] );
111 for( i=0; i<info->numParams; i++ ) {
112 fprintf( fp, "%s\n", info->ParamLabels[i] );
121 static char *fst_dllpath_to_infopath( char *dllpath ) {
123 if( strstr( dllpath, ".dll" ) == NULL ) return NULL;
125 retval = strdup( dllpath );
126 sprintf( retval + strlen(retval) - 4, ".fsi" );
130 static int fst_info_file_is_valid( char *dllpath ) {
131 struct stat dllstat, fststat;
132 char *fstpath = fst_dllpath_to_infopath( dllpath );
134 if( !fstpath ) return FALSE;
136 if( stat( dllpath, &dllstat ) ){ fst_error( "dll path %s invalid\n", dllpath ); return TRUE; }
137 if( stat( fstpath, &fststat ) ) return FALSE;
140 if( dllstat.st_mtime > fststat.st_mtime )
146 static int fst_can_midi( FST *fst ) {
147 struct AEffect *plugin = fst->plugin;
148 int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
150 if (vst_version >= 2) {
152 /* should we send it VST events (i.e. MIDI) */
154 if ((plugin->flags & effFlagsIsSynth) ||
155 (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
161 static FSTInfo *fst_info_from_plugin( FST *fst ) {
162 FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
163 struct AEffect *plugin;
168 fst_error( "fst is NULL\n" );
172 if( ! info ) return NULL;
174 plugin = fst->plugin;
177 info->name = strdup(fst->handle->name );
178 plugin->dispatcher (plugin, 47 /* effGetVendorString */, 0, 0, creator, 0);
179 if (strlen (creator) == 0) {
180 info->creator = strdup ("Unknown");
182 info->creator = strdup (creator);
185 #ifdef VESTIGE_HEADER
186 info->UniqueID = *((int32_t *) &plugin->unused_id);
188 info->UniqueID = plugin->uniqueID;
191 info->Category = strdup( "None" ); // FIXME:
192 info->numInputs = plugin->numInputs;
193 info->numOutputs = plugin->numOutputs;
194 info->numParams = plugin->numParams;
195 info->wantMidi = fst_can_midi( fst );
196 info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
197 info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
199 info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams );
200 info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams );
201 for( i=0; i<info->numParams; i++ ) {
204 plugin->dispatcher (plugin,
207 info->ParamNames[i] = strdup( name );
208 plugin->dispatcher (plugin,
209 6 /* effGetParamLabel */,
211 info->ParamLabels[i] = strdup( label );
216 // most simple one :) could be sufficient....
217 static long simple_master_callback( struct AEffect *fx, long opcode, long index, long value, void *ptr, float opt ) {
218 if( opcode == audioMasterVersion )
224 FSTInfo *fst_get_info( char *dllpath ) {
226 if( fst_info_file_is_valid( dllpath ) ) {
228 char *fstpath = fst_dllpath_to_infopath( dllpath );
230 info = load_fst_info_file( fstpath );
241 if( !(h = fst_load( dllpath )) ) return NULL;
242 if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) {
244 fst_error( "instantiate failed\n" );
247 fstpath = fst_dllpath_to_infopath( dllpath );
251 fst_error( "get fst filename failed\n" );
254 info = fst_info_from_plugin( fst );
255 save_fst_info_file( info, fstpath );
264 void fst_free_info( FSTInfo *info ) {
268 for( i=0; i<info->numParams; i++ ) {
269 free( info->ParamNames[i] );
270 free( info->ParamLabels[i] );
273 free( info->creator );
274 free( info->Category );