13
0

FST code from 2.X branch

git-svn-id: svn://localhost/ardour2/branches/3.0@4981 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-04-16 00:43:41 +00:00
parent 54d9f2f2d8
commit c2b12f05f4
4 changed files with 253 additions and 186 deletions

View File

@ -8,21 +8,63 @@ import glob
fst_src = glob.glob('*.c')
Import('env install_prefix libraries')
fst = env.Clone(CC="winegcc")
fst = env.Clone()
fst.Append (CPPPATH=".")
fst.Merge ([libraries['glib2']])
fst.Merge ([
libraries['jack'],
libraries['glib2']
])
#
# See if JACK supports jack_set_thread_creator()
#
jack_test_source_file = """
#include <jack/jack.h>
#include <pthread.h>
int
my_pthread_create (pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg)
{
return 0;
}
int main(int argc, char **argv)
{
jack_set_thread_creator (my_pthread_create);
return 0;
}
"""
def CheckJackSetThreadCreator(context):
context.Message('Checking for jack_set_thread_creator()...')
result = context.TryLink(jack_test_source_file, '.c')
context.Result(result)
return result
conf = Configure(fst, custom_tests = {
'CheckJackSetThreadCreator' : CheckJackSetThreadCreator,
})
if conf.CheckJackSetThreadCreator():
fst.Append(CCFLAGS="-DHAVE_JACK_SET_THREAD_CREATOR")
fst = conf.Finish ()
if fst['VST']:
fst.Replace(CC = ("winegcc"))
a = fst.Object ('fst', 'fst.c')
b = fst.Object ('fstinfofile', 'fstinfofile.c')
c = fst.Object ('vstwin', 'vstwin.c')
d = fst.Object ('vsti', 'vsti.c')
Default([a,b,c,d])
e = fst.Object ('thread', 'thread.c')
Default([a,b,c,d,e])
env.Alias('tarball', env.Distribute (env['DISTTREE'],
fst_src + ['SConscript',
'fst.h',
'jackvst.h'
] ))
vestige_headers = glob.glob ('vestige/*.h')
env.Alias('tarball', env.Distribute (env['DISTTREE'],
fst_src + vestige_headers +
['SConscript',
'fst.h',
'jackvst.h',
]
))

View File

@ -80,8 +80,10 @@ struct _FST
int height;
int wantIdle;
int destroy;
int vst_version;
int want_program;
int current_program;
float *want_params;
float *set_params;
@ -105,6 +107,7 @@ extern "C" {
#endif
extern int fst_init (void* possible_hmodule);
extern void fst_exit ();
extern FSTHandle* fst_load (const char*);
extern int fst_unload (FSTHandle*);
@ -133,6 +136,9 @@ extern int fst_load_state (FST * fst, char * filename);
*/
extern int fst_save_state (FST * fst, char * filename);
extern int wine_pthread_create (pthread_t* thread_id, const pthread_attr_t* attr, void *(*function)(void*), void* arg);
#ifdef __cplusplus
}
#endif

View File

@ -26,6 +26,7 @@
#ifndef _AEFFECTX_H
#define _AEFFECTX_H
#include <stdint.h>
#define audioMasterAutomate 0
#define audioMasterVersion 1
@ -128,9 +129,18 @@
#define kVstLangEnglish 1
#define kVstMidiType 1
#define kVstTransportPlaying (1 << 1)
#define kVstParameterUsesFloatStep (1 << 2)
/* validity flags for a VstTimeINfo structure this info comes from the web */
#define kVstNanosValid (1 << 8)
#define kVstPpqPosValid (1 << 9)
#define kVstTempoValid (1 << 10)
#define kVstBarsValid (1 << 11)
#define kVstCyclePosValid (1 << 12)
#define kVstTimeSigValid (1 << 13)
#define kVstSmpteValid (1 << 14)
#define kVstClockValid (1 << 15)
#define kVstTransportChanged 1
typedef struct VstMidiEvent
@ -182,27 +192,49 @@ typedef struct VstEvents
VstEvent * events[];
} VstEvents;
/* constants from http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=3740&sid=183f74631fee71a493316735e2b9f28b */
// Not finished, neither really used
typedef struct VstParameterProperties
enum Vestige2StringConstants
{
float stepFloat;
char label[64];
int flags;
int minInteger;
int maxInteger;
int stepInteger;
char shortLabel[8];
int category;
char categoryLabel[24];
char empty[128];
} VstParameterProperties;
VestigeMaxNameLen = 64,
VestigeMaxLabelLen = 64,
VestigeMaxShortLabelLen = 8,
VestigeMaxCategLabelLen = 24,
VestigeMaxFileNameLen = 100
};
/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
struct VstParameterProperties
{
float stepFloat; /* float step */
float smallStepFloat; /* small float step */
float largeStepFloat; /* large float step */
char label[VestigeMaxLabelLen]; /* parameter label */
int32_t flags; /* @see VstParameterFlags */
int32_t minInteger; /* integer minimum */
int32_t maxInteger; /* integer maximum */
int32_t stepInteger; /* integer step */
int32_t largeStepInteger; /* large integer step */
char shortLabel[VestigeMaxShortLabelLen]; /* short label, recommended: 6 + delimiter */
int16_t displayIndex; /* index where this parameter should be displayed (starting with 0) */
int16_t category; /* 0: no category, else group index + 1 */
int16_t numParametersInCategory; /* number of parameters in category */
int16_t reserved; /* zero */
char categoryLabel[VestigeMaxCategLabelLen]; /* category label, e.g. "Osc 1" */
char future[16]; /* reserved for future use */
};
/* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */
enum VstParameterFlags
{
kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */
kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */
kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */
kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */
kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */
kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */
kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */
};
typedef struct AEffect
{
@ -253,30 +285,26 @@ typedef struct AEffect
typedef struct VstTimeInfo
{
// 00
double samplePos;
// 08
double sampleRate;
// unconfirmed 10 18
char empty1[8 + 8];
// 20?
double tempo;
// unconfirmed 28 30 38
char empty2[8 + 8 + 8];
// 40?
int timeSigNumerator;
// 44?
int timeSigDenominator;
// unconfirmed 48 4c 50
char empty3[4 + 4 + 4];
// 54
int flags;
/* info from online documentation of VST provided by Steinberg */
double samplePos;
double sampleRate;
double nanoSeconds;
double ppqPos;
double tempo;
double barStartPos;
double cycleStartPos;
double cycleEndPos;
double timeSigNumerator;
double timeSigDenominator;
long smpteOffset;
long smpteFrameRate;
long samplesToNextClock;
long flags;
} VstTimeInfo;
typedef long int (* audioMasterCallback)( AEffect * , long int , long int ,
long int , void * , float );
// we don't use it, may be noise

View File

@ -1,4 +1,6 @@
#include <stdio.h>
#include <jack/jack.h>
#include <jack/thread.h>
#include <libgen.h>
#include <windows.h>
#include <winnt.h>
@ -24,11 +26,7 @@ static FST* fst_first = NULL;
const char magic[] = "FST Plugin State v002";
DWORD gui_thread_id = 0;
extern boolean g_quit;
static int gui_quit = 0;
#define DELAYED_WINDOW 1
@ -36,12 +34,11 @@ extern boolean g_quit;
static LRESULT WINAPI
my_window_proc (HWND w, UINT msg, WPARAM wp, LPARAM lp)
{
FST* fst=NULL;
LRESULT result;
// if (msg != WM_TIMER) {
// fst_error ("window callback handler, msg = 0x%x win=%p\n", msg, w);
// }
#if 0
if (msg != WM_TIMER) {
fst_error ("window callback handler, msg = 0x%x win=%p\n", msg, w);
}
#endif
switch (msg) {
case WM_KEYUP:
@ -49,47 +46,21 @@ my_window_proc (HWND w, UINT msg, WPARAM wp, LPARAM lp)
break;
case WM_CLOSE:
//printf("wtf.\n" );
PostQuitMessage (0);
/* we don't care about windows closing ... */
return 0;
break;
case WM_DESTROY:
case WM_NCDESTROY:
/* we should never get these */
//return 0;
break;
#if 0
case WM_PAINT:
if ((fst = GetPropA (w, "fst_ptr")) != NULL) {
if (fst->window && !fst->been_activated) {
fst->been_activated = TRUE;
pthread_cond_signal (&fst->window_status_change);
pthread_mutex_unlock (&fst->lock);
}
}
break;
#endif
#if 0
case WM_TIMER:
fst = GetPropA( w, "fst_ptr" );
if( !fst ) {
printf( "Timer without fst_ptr Prop :(\n" );
return 0;
}
fst->plugin->dispatcher(fst->plugin, effEditIdle, 0, 0, NULL, 0.0f);
if( fst->wantIdle )
fst->plugin->dispatcher(fst->plugin, 53, 0, 0, NULL, 0.0f);
/* we don't care about windows being destroyed ... */
return 0;
#endif
break;
default:
break;
}
return DefWindowProcA (w, msg, wp, lp );
//return 0;
}
static FST*
@ -100,6 +71,7 @@ fst_new ()
pthread_cond_init (&fst->window_status_change, NULL);
pthread_cond_init (&fst->plugin_dispatcher_called, NULL);
fst->want_program = -1;
fst->current_program = -1;
return fst;
}
@ -114,7 +86,6 @@ DWORD WINAPI gui_event_loop (LPVOID param)
{
MSG msg;
FST* fst;
char c;
HMODULE hInst;
HWND window;
@ -141,75 +112,98 @@ DWORD WINAPI gui_event_loop (LPVOID param)
fst_error ("cannot set timer on dummy window");
}
while (GetMessageA (&msg, NULL, 0,0)) {
while (!gui_quit) {
if (!GetMessageA (&msg, NULL, 0,0)) {
if (!gui_quit) {
fprintf (stderr, "QUIT message received by Windows GUI thread - ignored\n");
continue;
} else {
break;
}
}
TranslateMessage( &msg );
DispatchMessageA (&msg);
/* handle window creation requests, destroy requests,
and run idle callbacks
*/
if( msg.message == WM_TIMER ) {
pthread_mutex_lock (&plugin_mutex);
if (msg.message == WM_TIMER) {
pthread_mutex_lock (&plugin_mutex);
again:
for (fst = fst_first; fst; fst = fst->next) {
if (fst->destroy) {
if (fst->window) {
fst->plugin->dispatcher( fst->plugin, effEditClose, 0, 0, NULL, 0.0 );
CloseWindow (fst->window);
fst->window = NULL;
fst->destroy = FALSE;
}
fst_event_loop_remove_plugin (fst);
fst->been_activated = FALSE;
pthread_mutex_lock (&fst->lock);
pthread_cond_signal (&fst->window_status_change);
pthread_mutex_unlock (&fst->lock);
goto again;
}
if (fst->window == NULL) {
pthread_mutex_lock (&fst->lock);
fst_error ("Creating window for FST plugin %s", fst->handle->name);
if (fst_create_editor (fst)) {
fst_error ("cannot create editor for plugin %s", fst->handle->name);
fst_event_loop_remove_plugin (fst);
pthread_cond_signal (&fst->window_status_change);
pthread_mutex_unlock (&fst->lock);
goto again;
}
/* condition/unlock: it was signalled & unlocked in fst_create_editor() */
}
if(fst->want_program != -1 ) {
fst->plugin->dispatcher (fst->plugin, effSetProgram, 0, fst->want_program, NULL, 0);
fst->want_program = -1;
}
if(fst->dispatcher_wantcall) {
for (fst = fst_first; fst; fst = fst->next) {
pthread_mutex_lock (&fst->lock);
fst->dispatcher_retval = fst->plugin->dispatcher( fst->plugin, fst->dispatcher_opcode,
fst->dispatcher_index,
fst->dispatcher_val,
fst->dispatcher_ptr,
fst->dispatcher_opt );
fst->dispatcher_wantcall = 0;
pthread_cond_signal (&fst->plugin_dispatcher_called);
if (fst->destroy) {
fprintf (stderr, "%s scheduled for destroy\n", fst->handle->name);
if (fst->window) {
fst->plugin->dispatcher( fst->plugin, effEditClose, 0, 0, NULL, 0.0 );
CloseWindow (fst->window);
fst->window = NULL;
fst->destroy = FALSE;
}
fst_event_loop_remove_plugin (fst);
fst->been_activated = FALSE;
pthread_cond_signal (&fst->window_status_change);
pthread_mutex_unlock (&fst->lock);
goto again;
}
if (fst->window == NULL) {
if (fst_create_editor (fst)) {
fst_error ("cannot create editor for plugin %s", fst->handle->name);
fst_event_loop_remove_plugin (fst);
pthread_cond_signal (&fst->window_status_change);
pthread_mutex_unlock (&fst->lock);
goto again;
} else {
/* condition/unlock: it was signalled & unlocked in fst_create_editor() */
}
}
if (fst->want_program != -1 ) {
if (fst->vst_version >= 2) {
fst->plugin->dispatcher (fst->plugin, 67 /* effBeginSetProgram */, 0, 0, NULL, 0);
}
fst->plugin->dispatcher (fst->plugin, effSetProgram, 0, fst->want_program, NULL, 0);
if (fst->vst_version >= 2) {
fst->plugin->dispatcher (fst->plugin, 68 /* effEndSetProgram */, 0, 0, NULL, 0);
}
/* did it work? */
fst->current_program = fst->plugin->dispatcher (fst->plugin, 3, /* effGetProgram */ 0, 0, NULL, 0);
fst->want_program = -1;
}
if(fst->dispatcher_wantcall) {
fst->dispatcher_retval = fst->plugin->dispatcher( fst->plugin,
fst->dispatcher_opcode,
fst->dispatcher_index,
fst->dispatcher_val,
fst->dispatcher_ptr,
fst->dispatcher_opt );
fst->dispatcher_wantcall = 0;
pthread_cond_signal (&fst->plugin_dispatcher_called);
}
fst->plugin->dispatcher (fst->plugin, effEditIdle, 0, 0, NULL, 0);
if( fst->wantIdle ) {
fst->plugin->dispatcher (fst->plugin, 53, 0, 0, NULL, 0);
}
pthread_mutex_unlock (&fst->lock);
}
pthread_mutex_lock (&fst->lock);
fst->plugin->dispatcher (fst->plugin, effEditIdle, 0, 0, NULL, 0);
if( fst->wantIdle ) {
fst->plugin->dispatcher (fst->plugin, 53, 0, 0, NULL, 0);
}
pthread_mutex_unlock (&fst->lock);
}
pthread_mutex_unlock (&plugin_mutex);
pthread_mutex_unlock (&plugin_mutex);
}
}
fprintf (stderr, "VST GUI EVENT LOOP THREAD EXIT\n");
return 0;
}
@ -220,37 +214,25 @@ fst_init (void* possible_hmodule)
HMODULE hInst;
if (possible_hmodule) {
hInst = (HMODULE) possible_hmodule;
hInst = (HMODULE) possible_hmodule;
} else if ((hInst = GetModuleHandleA (NULL)) == NULL) {
fst_error ("can't get module handle");
return -1;
fst_error ("can't get module handle");
return -1;
}
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.style = 0;
wclass.lpfnWndProc = my_window_proc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInst;
wclass.hIcon = LoadIcon(hInst, "FST");
wclass.hCursor = LoadCursor(0, IDI_APPLICATION);
// wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wclass.lpszMenuName = "MENU_FST";
wclass.lpszClassName = "FST";
wclass.hIconSm = 0;
#if 0
wc.style = 0;
wc.lpfnWndProc = my_window_proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIconA( hInst, "FST");
wc.hCursor = LoadCursorA( NULL, IDI_APPLICATION );
wc.hbrBackground = GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = "FSTMENU";
wc.lpszClassName = "FST";
//wc.hIconSm = 0;
#endif
wclass.cbSize = sizeof(WNDCLASSEX);
wclass.style = 0;
wclass.lpfnWndProc = my_window_proc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInst;
wclass.hIcon = LoadIcon(hInst, "FST");
wclass.hCursor = LoadCursor(0, IDI_APPLICATION);
// wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wclass.lpszMenuName = "MENU_FST";
wclass.lpszClassName = "FST";
wclass.hIconSm = 0;
if (!RegisterClassExA(&wclass)){
printf( "Class register failed :(\n" );
@ -263,9 +245,21 @@ fst_init (void* possible_hmodule)
fst_error ("could not create new thread proxy");
return -1;
}
#ifdef HAVE_JACK_SET_THREAD_CREATOR
jack_set_thread_creator (wine_pthread_create);
#endif
return 0;
}
void
fst_exit ()
{
gui_quit = 1;
PostQuitMessage (0);
}
int
fst_run_editor (FST* fst)
{
@ -319,7 +313,6 @@ int
fst_create_editor (FST* fst)
{
HMODULE hInst;
char class[20];
HWND window;
struct ERect* er;
@ -372,9 +365,7 @@ fst_create_editor (FST* fst)
//SetWindowPos (fst->window, 0, 0, 0, er->right-er->left+8, er->bottom-er->top+26, SWP_NOMOVE|SWP_NOZORDER);
fst->xid = (int) GetPropA (window, "__wine_x11_whole_window");
printf( "And xid = %x\n", fst->xid );
fst->been_activated = TRUE;
printf ("Signalling window ready\n");
pthread_cond_signal (&fst->window_status_change);
pthread_mutex_unlock (&fst->lock);
@ -385,25 +376,24 @@ void
fst_move_window_into_view (FST* fst)
{
if (fst->window) {
SetWindowPos (fst->window, 0, 0, 0, fst->width, fst->height+24, 0);
ShowWindow (fst->window, SW_SHOWNA);
SetWindowPos (fst->window, 0, 0, 0, fst->width, fst->height+24, 0);
ShowWindow (fst->window, SW_SHOWNA);
}
}
void
fst_destroy_editor (FST* fst)
{
FST* p;
FST* prev;
pthread_mutex_lock (&fst->lock);
if (fst->window) {
fprintf (stderr, "mark %s for destroy\n", fst->handle->name);
fst->destroy = TRUE;
//if (!PostThreadMessageA (gui_thread_id, WM_USER, 0, 0)) {
//if (!PostThreadMessageA (gui_thread_id, WM_QUIT, 0, 0)) {
// fst_error ("could not post message to gui thread");
//}
pthread_cond_wait (&fst->window_status_change, &fst->lock);
fprintf (stderr, "%s editor destroyed\n", fst->handle->name);
}
pthread_mutex_unlock (&fst->lock);
@ -481,7 +471,7 @@ fst_load_vst_library(const char * path)
FSTHandle*
fst_load (const char *path)
{
char* buf, *buf2;
char* buf;
FSTHandle* fhandle;
char* period;
@ -585,6 +575,8 @@ fst_instantiate (FSTHandle* fhandle, audioMasterCallback amc, void* userptr)
fst->plugin->dispatcher (fst->plugin, effOpen, 0, 0, 0, 0);
//fst->plugin->dispatcher (fst->plugin, effMainsChanged, 0, 0, NULL, 0);
fst->vst_version = fst->plugin->dispatcher (fst->plugin, effGetVstVersion, 0, 0, 0, 0);
fst->handle->plugincnt++;
fst->wantIdle = 0;
@ -742,7 +734,6 @@ int fst_save_state (FST * fst, char * filename)
char effectName[64];
char vendorString[64];
int success;
unsigned length;
// write header
fprintf( f, "<plugin_state>\n" );