fix C99 compliance issue for winegcc
[ardour.git] / libs / fst / fstinfofile.c
1 #include "fst.h"
2
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <unistd.h>
6
7 #include <stdlib.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #define MAX_STRING_LEN 256
13
14 #define FALSE 0
15 #define TRUE !FALSE
16
17 extern char * strdup (const char *);
18
19 static char *read_string( FILE *fp ) {
20     char buf[MAX_STRING_LEN];
21
22     fgets( buf, MAX_STRING_LEN, fp );
23     if( strlen( buf ) < MAX_STRING_LEN ) {
24         
25         if( strlen(buf) )
26             buf[strlen(buf)-1] = 0;
27
28         return strdup( buf );
29     } else {
30         return NULL;
31     }
32 }
33
34 static FSTInfo *load_fst_info_file( char *filename ) {
35
36     FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
37     FILE *fp;
38     int i;
39
40
41     if( info == NULL )
42         return NULL;
43
44     fp = fopen( filename, "r" );
45     
46     if( fp == NULL ) {
47         free( info );
48         return NULL;
49     }
50
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;
61
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;
65     }
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;
69     }
70         
71
72     fclose( fp );
73     return info;
74
75 error:
76     fclose( fp );
77     free( info );
78     return NULL;
79 }
80
81 static int save_fst_info_file( FSTInfo *info, char *filename ) {
82
83     FILE *fp;
84     int i;
85
86
87     if( info == NULL ) {
88         fst_error( "info is NULL\n" );
89         return TRUE;
90     }
91
92     fp = fopen( filename, "w" );
93     
94     if( fp == NULL ) {
95         fst_error( "Cant write info file %s\n", filename );
96         return TRUE;
97     }
98
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 );
109
110     for( i=0; i<info->numParams; i++ ) {
111         fprintf( fp, "%s\n", info->ParamNames[i] );
112     }
113     for( i=0; i<info->numParams; i++ ) {
114         fprintf( fp, "%s\n", info->ParamLabels[i] );
115     }
116         
117
118     fclose( fp );
119
120     return FALSE;
121 }
122
123 static char *fst_dllpath_to_infopath( char *dllpath ) {
124     char *retval;
125     if( strstr( dllpath, ".dll" ) == NULL ) return NULL;
126     
127     retval = strdup( dllpath );
128     sprintf( retval + strlen(retval) - 4, ".fsi" );
129     return retval;
130 }
131
132 static int fst_info_file_is_valid( char *dllpath ) {
133     struct stat dllstat, fststat;
134     char *fstpath = fst_dllpath_to_infopath( dllpath );
135
136     if( !fstpath ) return FALSE;
137     
138     if( stat( dllpath, &dllstat ) ){ fst_error( "dll path %s invalid\n", dllpath );  return TRUE; }
139     if( stat( fstpath, &fststat ) ) return FALSE;
140
141     free( fstpath );
142     if( dllstat.st_mtime > fststat.st_mtime )
143         return FALSE;
144     else 
145         return TRUE;
146 }
147
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);
151
152         if (vst_version >= 2) {
153                 
154                 /* should we send it VST events (i.e. MIDI) */
155                 
156                 if ((plugin->flags & effFlagsIsSynth) ||
157                     (plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
158                     return TRUE;
159         }
160         return FALSE;
161
162 }
163 static FSTInfo *fst_info_from_plugin( FST *fst ) {
164     FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
165     struct AEffect *plugin;
166     int i;
167     char creator[65];
168
169     if( ! fst ) {
170         fst_error( "fst is NULL\n" );
171         return NULL;
172     }
173
174     if( ! info ) return NULL;
175     
176     plugin = fst->plugin;
177     
178
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");
183     } else {
184       info->creator = strdup (creator);
185     }
186
187 #ifdef VESTIGE_HEADER
188     info->UniqueID = *((int32_t *) &plugin->unused_id);
189 #else
190     info->UniqueID = plugin->uniqueID;
191 #endif
192
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;
200
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++ ) {
204         char name[20];
205         char label[9];
206         plugin->dispatcher (plugin,
207                             effGetParamName,
208                             i, 0, name, 0);
209         info->ParamNames[i] = strdup( name );
210         plugin->dispatcher (plugin,
211                             6 /* effGetParamLabel */,
212                             i, 0, label, 0);
213         info->ParamLabels[i] = strdup( label );
214     }
215     return info;
216 }
217
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 )
221         return 2;
222     else
223         return 0;
224 }
225
226 FSTInfo *fst_get_info( char *dllpath ) {
227
228     if( fst_info_file_is_valid( dllpath ) ) {
229         FSTInfo *info;
230         char *fstpath = fst_dllpath_to_infopath( dllpath );
231
232         info = load_fst_info_file( fstpath );
233         free( fstpath );
234         return info;
235
236     } else {
237
238         FSTHandle *h;
239         FST *fst;
240         FSTInfo *info;
241         char *fstpath;
242
243         if( !(h = fst_load( dllpath )) ) return NULL;
244         if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) {
245             fst_unload( h );
246             fst_error( "instantiate failed\n" );
247             return NULL;
248         }
249         fstpath = fst_dllpath_to_infopath( dllpath );
250         if( !fstpath ) {
251             fst_close( fst );
252             fst_unload( h );
253             fst_error( "get fst filename failed\n" );
254             return NULL;
255         }
256         info = fst_info_from_plugin( fst );
257         save_fst_info_file( info, fstpath );
258
259         free( fstpath );
260         fst_close( fst );
261         fst_unload( h );
262         return info;
263     }
264 }
265
266 void fst_free_info( FSTInfo *info ) {
267
268     int i;
269
270     for( i=0; i<info->numParams; i++ ) {
271         free( info->ParamNames[i] );
272         free( info->ParamLabels[i] );
273     }
274     free( info->name );
275     free( info->creator );
276     free( info->Category );
277     free( info );
278 }
279
280