ardour/libs/fst/fstinfofile.c
Carl Hetherington 16aece1d47 Share main VSTFX / FST struct between windows / linux VSTs.
git-svn-id: svn://localhost/ardour2/branches/3.0@10762 d708f5d6-7413-0410-9779-e7cbd77b26cf
2011-11-22 02:27:26 +00:00

288 lines
6.8 KiB
C

#include "fst.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#define MAX_STRING_LEN 256
#define FALSE 0
#define TRUE !FALSE
extern char * strdup (const char *);
static char *read_string( FILE *fp ) {
char buf[MAX_STRING_LEN];
fgets( buf, MAX_STRING_LEN, fp );
if( strlen( buf ) < MAX_STRING_LEN ) {
if( strlen(buf) )
buf[strlen(buf)-1] = 0;
return strdup( buf );
} else {
return NULL;
}
}
static VSTInfo *
load_fst_info_file (char* filename)
{
VSTInfo *info = (VSTInfo *) malloc (sizeof (VSTInfo));
FILE *fp;
int i;
if (info == NULL) {
return NULL;
}
fp = fopen( filename, "r" );
if (fp == NULL) {
free (info);
return NULL;
}
if( (info->name = read_string( fp )) == NULL ) goto error;
if( (info->creator = read_string( fp )) == NULL ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->UniqueID ) ) goto error;
if( (info->Category = read_string( fp )) == NULL ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->numInputs ) ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->numOutputs ) ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->numParams ) ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->wantMidi ) ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->hasEditor ) ) goto error;
if( 1 != fscanf( fp, "%d\n", &info->canProcessReplacing ) ) goto error;
if( (info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
for( i=0; i<info->numParams; i++ ) {
if( (info->ParamNames[i] = read_string( fp )) == NULL ) goto error;
}
if( (info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams )) == NULL ) goto error;
for( i=0; i<info->numParams; i++ ) {
if( (info->ParamLabels[i] = read_string( fp )) == NULL ) goto error;
}
fclose( fp );
return info;
error:
fclose( fp );
free( info );
return NULL;
}
static int
save_fst_info_file (VSTInfo* info, char* filename)
{
FILE *fp;
int i;
if( info == NULL ) {
fst_error( "info is NULL\n" );
return TRUE;
}
fp = fopen( filename, "w" );
if( fp == NULL ) {
fst_error( "Cant write info file %s\n", filename );
return TRUE;
}
fprintf( fp, "%s\n", info->name );
fprintf( fp, "%s\n", info->creator );
fprintf( fp, "%d\n", info->UniqueID );
fprintf( fp, "%s\n", info->Category );
fprintf( fp, "%d\n", info->numInputs );
fprintf( fp, "%d\n", info->numOutputs );
fprintf( fp, "%d\n", info->numParams );
fprintf( fp, "%d\n", info->wantMidi );
fprintf( fp, "%d\n", info->hasEditor );
fprintf( fp, "%d\n", info->canProcessReplacing );
for( i=0; i<info->numParams; i++ ) {
fprintf( fp, "%s\n", info->ParamNames[i] );
}
for( i=0; i<info->numParams; i++ ) {
fprintf( fp, "%s\n", info->ParamLabels[i] );
}
fclose( fp );
return FALSE;
}
static char *fst_dllpath_to_infopath( char *dllpath ) {
char *retval;
if( strstr( dllpath, ".dll" ) == NULL ) return NULL;
retval = strdup( dllpath );
sprintf( retval + strlen(retval) - 4, ".fsi" );
return retval;
}
static int fst_info_file_is_valid( char *dllpath ) {
struct stat dllstat, fststat;
char *fstpath = fst_dllpath_to_infopath( dllpath );
if( !fstpath ) return FALSE;
if( stat( dllpath, &dllstat ) ){ fst_error( "dll path %s invalid\n", dllpath ); return TRUE; }
if( stat( fstpath, &fststat ) ) return FALSE;
free( fstpath );
if( dllstat.st_mtime > fststat.st_mtime )
return FALSE;
else
return TRUE;
}
static int
fst_can_midi (VSTState* fst)
{
AEffect* plugin = fst->plugin;
int vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
if (vst_version >= 2) {
/* should we send it VST events (i.e. MIDI) */
if ((plugin->flags & effFlagsIsSynth) ||
(plugin->dispatcher (plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0))
return TRUE;
}
return FALSE;
}
static VSTInfo *
fst_info_from_plugin (VSTState* fst)
{
VSTInfo* info = (VSTInfo *) malloc (sizeof (VSTInfo));
AEffect* plugin;
int i;
char creator[65];
if( ! fst ) {
fst_error( "fst is NULL\n" );
return NULL;
}
if( ! info ) return NULL;
plugin = fst->plugin;
info->name = strdup(fst->handle->name );
plugin->dispatcher (plugin, 47 /* effGetVendorString */, 0, 0, creator, 0);
if (strlen (creator) == 0) {
info->creator = strdup ("Unknown");
} else {
info->creator = strdup (creator);
}
info->UniqueID = *((int32_t *) &plugin->uniqueID);
info->Category = strdup( "None" ); // FIXME:
info->numInputs = plugin->numInputs;
info->numOutputs = plugin->numOutputs;
info->numParams = plugin->numParams;
info->wantMidi = fst_can_midi( fst );
info->hasEditor = plugin->flags & effFlagsHasEditor ? TRUE : FALSE;
info->canProcessReplacing = plugin->flags & effFlagsCanReplacing ? TRUE : FALSE;
info->ParamNames = (char **) malloc( sizeof( char * ) * info->numParams );
info->ParamLabels = (char **) malloc( sizeof( char * ) * info->numParams );
for( i=0; i<info->numParams; i++ ) {
char name[20];
char label[9];
plugin->dispatcher (plugin,
effGetParamName,
i, 0, name, 0);
info->ParamNames[i] = strdup( name );
plugin->dispatcher (plugin,
6 /* effGetParamLabel */,
i, 0, label, 0);
info->ParamLabels[i] = strdup( label );
}
return info;
}
// most simple one :) could be sufficient....
static intptr_t
simple_master_callback (AEffect *fx, int32_t opcode, int32_t index, intptr_t value, void *ptr, float opt)
{
if (opcode == audioMasterVersion) {
return 2;
} else {
return 0;
}
}
VSTInfo *
fst_get_info (char* dllpath)
{
if( fst_info_file_is_valid( dllpath ) ) {
VSTInfo *info;
char *fstpath = fst_dllpath_to_infopath( dllpath );
info = load_fst_info_file( fstpath );
free( fstpath );
return info;
} else {
VSTHandle* h;
VSTState* fst;
VSTInfo* info;
char* fstpath;
if( !(h = fst_load( dllpath )) ) return NULL;
if( !(fst = fst_instantiate( h, simple_master_callback, NULL )) ) {
fst_unload( h );
fst_error( "instantiate failed\n" );
return NULL;
}
fstpath = fst_dllpath_to_infopath( dllpath );
if( !fstpath ) {
fst_close( fst );
fst_unload( h );
fst_error( "get fst filename failed\n" );
return NULL;
}
info = fst_info_from_plugin( fst );
save_fst_info_file( info, fstpath );
free( fstpath );
fst_close( fst );
fst_unload( h );
return info;
}
}
void
fst_free_info (VSTInfo *info)
{
int i;
for( i=0; i<info->numParams; i++ ) {
free( info->ParamNames[i] );
free( info->ParamLabels[i] );
}
free( info->name );
free( info->creator );
free( info->Category );
free( info );
}