summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-04-16 00:43:41 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-04-16 00:43:41 +0000
commitc2b12f05f4c40319c7fd41ca18d48cee1119826e (patch)
tree7886cb55dd31308cbce24d0338f82a3865d42f08 /libs
parent54d9f2f2d83af1f0f44579fe2ebf090e68259938 (diff)
FST code from 2.X branch
git-svn-id: svn://localhost/ardour2/branches/3.0@4981 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/fst/SConscript58
-rw-r--r--libs/fst/fst.h6
-rw-r--r--libs/fst/vestige/aeffectx.h108
-rw-r--r--libs/fst/vstwin.c269
4 files changed, 254 insertions, 187 deletions
diff --git a/libs/fst/SConscript b/libs/fst/SConscript
index 92c7504257..a543d72a50 100644
--- a/libs/fst/SConscript
+++ b/libs/fst/SConscript
@@ -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])
+vestige_headers = glob.glob ('vestige/*.h')
+
env.Alias('tarball', env.Distribute (env['DISTTREE'],
- fst_src + ['SConscript',
- 'fst.h',
- 'jackvst.h'
- ] ))
+ fst_src + vestige_headers +
+ ['SConscript',
+ 'fst.h',
+ 'jackvst.h',
+ ]
+ ))
diff --git a/libs/fst/fst.h b/libs/fst/fst.h
index 2a0130667a..6ef5acf794 100644
--- a/libs/fst/fst.h
+++ b/libs/fst/fst.h
@@ -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
diff --git a/libs/fst/vestige/aeffectx.h b/libs/fst/vestige/aeffectx.h
index 790c93e6dc..dda128f45e 100644
--- a/libs/fst/vestige/aeffectx.h
+++ b/libs/fst/vestige/aeffectx.h
@@ -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
diff --git a/libs/fst/vstwin.c b/libs/fst/vstwin.c
index fc9ac0c999..09ca8f18d3 100644
--- a/libs/fst/vstwin.c
+++ b/libs/fst/vstwin.c
@@ -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);
- 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);
- }
- }
+ /* we don't care about windows closing ... */
+ return 0;
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);
+ case WM_DESTROY:
+ case WM_NCDESTROY:
+ /* 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);
-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) {
+ if (msg.message == WM_TIMER) {
+ pthread_mutex_lock (&plugin_mutex);
+
+again:
+ 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);
- 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);
+ 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_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;
- }
- 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);
+ 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;
+ 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
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" );