Forget about the canvas patchbay, I'll work that later
[klaudia.git] / fst / fstinfofile.c
blob1e79f8e949a15857cfc758d5820fdea5d8e2b5e2
2 #include "fst.h"
3 #include "vestige/aeffectx.h"
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
9 #include <stddef.h>
10 #include <stdio.h>
11 #include <string.h>
14 #define MAX_STRING_LEN 256
16 //#define FALSE 0
17 //#define TRUE !FALSE
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 ) {
25 if( strlen(buf) )
26 buf[strlen(buf)-1] = 0;
28 return strdup( buf );
29 } else {
30 return NULL;
34 static FSTInfo *load_fst_info_file( char *filename ) {
36 FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
37 FILE *fp;
38 int i;
41 if( info == NULL )
42 return NULL;
44 fp = fopen( filename, "r" );
46 if( fp == NULL ) {
47 free( info );
48 return NULL;
51 if( (info->name = read_string( fp )) == NULL ) goto error;
52 if( 1 != fscanf( fp, "%d\n", &info->UniqueID ) ) goto error;
53 if( (info->Category = read_string( fp )) == NULL ) goto error;
54 if( 1 != fscanf( fp, "%d\n", &info->numInputs ) ) goto error;
55 if( 1 != fscanf( fp, "%d\n", &info->numOutputs ) ) goto error;
56 if( 1 != fscanf( fp, "%d\n", &info->numParams ) ) goto error;
57 if( 1 != fscanf( fp, "%d\n", &info->wantMidi ) ) goto error;
58 if( 1 != fscanf( fp, "%d\n", &info->hasEditor ) ) goto error;
59 if( 1 != fscanf( fp, "%d\n", &info->canProcessReplacing ) ) goto error;
61 if( (info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
62 for( i=0; i<info->numParams; i++ ) {
63 if( (info->ParamNames[i] = read_string( fp )) == NULL ) goto error;
65 if( (info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
66 for( i=0; i<info->numParams; i++ ) {
67 if( (info->ParamLabels[i] = read_string( fp )) == NULL ) goto error;
71 fclose( fp );
72 return info;
74 error:
75 fclose( fp );
76 free( info );
77 return NULL;
80 static int save_fst_info_file( FSTInfo *info, char *filename ) {
82 FILE *fp;
83 int i;
86 if( info == NULL ) {
87 fst_error( "info is NULL\n" );
88 return TRUE;
91 fp = fopen( filename, "w" );
93 if( fp == NULL ) {
94 fst_error( "Cant write info file %s\n", filename );
95 return TRUE;
98 fprintf( fp, "%s\n", info->name );
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] );
116 fclose( fp );
118 return FALSE;
121 static char *fst_dllpath_to_infopath( char *dllpath ) {
122 char *retval;
123 if( strstr( dllpath, ".dll" ) == NULL ) return NULL;
125 retval = strdup( dllpath );
126 sprintf( retval + strlen(retval) - 4, ".fst" );
127 return retval;
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;
139 free( fstpath );
140 if( dllstat.st_mtime > fststat.st_mtime )
141 return FALSE;
142 else
143 return TRUE;
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))
156 return TRUE;
158 return FALSE;
161 static FSTInfo *fst_info_from_plugin( FST *fst ) {
162 FSTInfo *info = (FSTInfo *) malloc( sizeof( FSTInfo ) );
163 struct AEffect *plugin;
164 int i;
166 if( ! fst ) {
167 fst_error( "fst is NULL\n" );
168 return NULL;
171 if( ! info ) return NULL;
173 plugin = fst->plugin;
176 info->name = strdup(fst->handle->name );
177 //info->UniqueID = plugin->uniqueID;
178 info->Category = strdup( "None" ); // FIXME:
179 info->numInputs = plugin->numInputs;
180 info->numOutputs = plugin->numOutputs;
181 info->numParams = plugin->numParams;
182 info->wantMidi = fst_can_midi( fst );
183 info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
184 info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
186 info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams );
187 info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams );
188 for( i=0; i<info->numParams; i++ ) {
189 char name[20];
190 char label[9];
191 plugin->dispatcher (plugin,
192 effGetParamName,
193 i, 0, name, 0);
194 info->ParamNames[i] = strdup( name );
195 #if 0
196 plugin->dispatcher (plugin,
197 effGetParamLabel,
198 i, 0, label, 0);
200 info->ParamLabels[i] = strdup( label );
201 #else
202 info->ParamLabels[i] = strdup( name );
203 #endif
205 return info;
208 // most simple one :) could be sufficient....
209 static long simple_master_callback( struct AEffect *fx, long opcode, long index, long value, void *ptr, float opt ) {
210 if( opcode == audioMasterVersion )
211 return 2;
212 else
213 return 0;
216 FSTInfo *fst_get_info( char *dllpath ) {
218 if( fst_info_file_is_valid( dllpath ) ) {
219 FSTInfo *info;
220 char *fstpath = fst_dllpath_to_infopath( dllpath );
222 info = load_fst_info_file( fstpath );
223 free( fstpath );
224 return info;
226 } else {
228 FSTHandle *h;
229 FST *fst;
230 FSTInfo *info;
231 char *fstpath;
233 if( !(h = fst_load( dllpath )) ) return NULL;
234 if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) {
235 fst_unload( h );
236 fst_error( "instantiate failed\n" );
237 return NULL;
239 fstpath = fst_dllpath_to_infopath( dllpath );
240 if( !fstpath ) {
241 fst_close( fst );
242 fst_unload( h );
243 fst_error( "get fst filename failed\n" );
244 return NULL;
246 info = fst_info_from_plugin( fst );
247 save_fst_info_file( info, fstpath );
249 free( fstpath );
250 fst_close( fst );
251 fst_unload( h );
252 return info;
256 void fst_free_info( FSTInfo *info ) {
258 int i;
260 for( i=0; i<info->numParams; i++ ) {
261 free( info->ParamNames[i] );
262 free( info->ParamLabels[i] );
264 free( info->name );
265 free( info->Category );
266 free( info );