From 4fe8863a1176f7fe4057d82b2844dd7127b13bca Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 16 Mar 2005 04:59:36 +0000 Subject: much cleaner Window GUI code fixed bug with param method updated build system minimal feedback attribute for parameter reporting clean handling of plugin deletion (potentially open editor window etc.) updated for new flext function naming names containing spaces are now correctly dumped added event processing (like Midi in) more consistent MIDI functionality trying to catch crashing plugins svn path=/trunk/; revision=2630 --- externals/grill/vst/src/vsthost.cpp | 159 ++++++++++++++++++++++++++++-------- 1 file changed, 127 insertions(+), 32 deletions(-) (limited to 'externals/grill/vst/src/vsthost.cpp') diff --git a/externals/grill/vst/src/vsthost.cpp b/externals/grill/vst/src/vsthost.cpp index 3b9d6241..5f2443fc 100644 --- a/externals/grill/vst/src/vsthost.cpp +++ b/externals/grill/vst/src/vsthost.cpp @@ -8,7 +8,9 @@ WARRANTIES, see the file, "license.txt," in this distribution. */ #include "vsthost.h" - +#include "editor.h" +#include +#include "flcontainers.h" const t_symbol *VSTPlugin::sym_param, @@ -22,8 +24,22 @@ const t_symbol *VSTPlugin::sym_ev_, *VSTPlugin::sym_midi[8]; + +class DelPlugin + : public Fifo::Cell +{ +public: + DelPlugin(VSTPlugin *p): plug(p) {} + VSTPlugin *plug; +}; + +static TypedLifo todel; +flext::ThrCond VSTPlugin::thrcond; + void VSTPlugin::Setup() { + LaunchThread(worker); + sym_param = flext::MakeSymbol("param"); sym_event = flext::MakeSymbol("event"); sym_evmidi = flext::MakeSymbol("midi"); @@ -34,22 +50,23 @@ void VSTPlugin::Setup() sym_evsysex = flext::MakeSymbol("sysex"); sym_ev_ = flext::MakeSymbol("???"); - sym_midi[0] = flext::MakeSymbol("noteon"); - sym_midi[1] = flext::MakeSymbol("noteoff"); - sym_midi[2] = flext::MakeSymbol("polyafter"); - sym_midi[3] = flext::MakeSymbol("cntl"); + sym_midi[0] = flext::MakeSymbol("noteoff"); + sym_midi[1] = flext::MakeSymbol("note"); + sym_midi[2] = flext::MakeSymbol("atouch"); + sym_midi[3] = flext::MakeSymbol("ctlchg"); sym_midi[4] = flext::MakeSymbol("progchg"); - sym_midi[5] = flext::MakeSymbol("chnafter"); - sym_midi[6] = flext::MakeSymbol("pitchbend"); - sym_midi[7] = sym__; + sym_midi[5] = flext::MakeSymbol("atouch"); + sym_midi[6] = flext::MakeSymbol("pbend"); + sym_midi[7] = flext::MakeSymbol("sysex"); } VSTPlugin::VSTPlugin(Responder *resp) : hdll(NULL),hwnd(NULL) , effect(NULL),pluginmain(NULL),audiomaster(NULL) , responder(resp) - , posx(0),posy(0),caption(true) - , midichannel(0),eventqusz(0) + , posx(0),posy(0),sizex(0),sizey(0) + , visible(true),caption(true),handle(false) + , midichannel(0),eventqusz(0),dumpevents(false) , paramnamecnt(0) , transchg(true) , playing(false),looping(false),feedback(false) @@ -67,7 +84,55 @@ VSTPlugin::~VSTPlugin() Free(); } +VSTPlugin *VSTPlugin::New(Responder *resp) +{ + FLEXT_ASSERT(resp); + return new VSTPlugin(resp); +} + +void VSTPlugin::Delete(VSTPlugin *p) +{ + FLEXT_ASSERT(p); + + // tell plugin to close editor! + StopEditor(p); + // transfer to deletion thread + todel.Push(new DelPlugin(p)); + thrcond.Signal(); +} + +void VSTPlugin::worker(thr_params *) +{ + TypedLifo tmp; + bool again = false; + for(;;) { + // wait for signal + if(again) { + thrcond.TimedWait(0.01); + again = false; + } + else + thrcond.Wait(); + + DelPlugin *p; + while((p = todel.Pop()) != NULL) { + // see if editing has stopped + if(p && p->plug->hwnd == NULL) { + // yes, it is now safe to delete the plug + delete p->plug; + delete p; + } + else { + tmp.Push(p); + again = true; + } + } + // put back remaining entries + while((p = tmp.Pop()) != NULL) todel.Push(p); + } +} + #if FLEXT_OS == FLEXT_OS_MAC OSStatus FSPathMakeFSSpec(const UInt8 *path,FSSpec *spec,Boolean *isDirectory) /* can be NULL */ { @@ -208,9 +273,17 @@ bool VSTPlugin::InstPlugin(long plugid) FLEXT_ASSERT(pluginmain && audiomaster); //This calls the "main" function and receives the pointer to the AEffect structure. - effect = pluginmain(audiomaster); - if(!effect || effect->magic != kEffectMagic) { - post("VST plugin : Unable to create effect"); + try { effect = pluginmain(audiomaster); } + catch(exception &e) { + flext::post("vst~ - caught exception while instantiating plugin: %s",e.what()); + } + catch(...) { + flext::post("vst~ - caught exception while instantiating plugin"); + } + + if(!effect) + return false; + else if(effect->magic != kEffectMagic) { effect = NULL; return false; } @@ -219,13 +292,19 @@ bool VSTPlugin::InstPlugin(long plugid) bool VSTPlugin::Instance(const char *name,const char *subname) { - bool ok = effect != NULL; + bool ok = false; + FLEXT_ASSERT(effect == NULL); + try { + +/* if(!ok && dllname != name) { FreePlugin(); // freshly load plugin ok = NewPlugin(name) && InstPlugin(); } +*/ + ok = NewPlugin(name) && InstPlugin(); if(ok && subname && *subname && Dispatch(effGetPlugCategory) == kPlugCategShell) { // sub plugin-name given -> scan plugs @@ -294,37 +373,53 @@ bool VSTPlugin::Instance(const char *name,const char *subname) Dispatch(effGetVendorString,0,0,vendorname); } + } + catch(exception &e) { + flext::post("vst~ - caught exception while loading plugin: %s",e.what()); + ok = false; + } + catch(...) { + flext::post("vst~ - Caught exception while loading plugin"); + ok = false; + } + if(!ok) Free(); return ok; } -void VSTPlugin::Free() // Called also in destruction +void VSTPlugin::Free() { - if(effect) { - Edit(false); + // This should only also in destruction - // shut down plugin - Dispatch(effMainsChanged, 0, 0); - Dispatch(effClose); - } + try { + if(effect) { + FLEXT_ASSERT(!IsEdited()); - // \TODO - // Here, we really have to wait until the editor thread has terminated - // otherwise WM_DESTROY etc. messages may still be pending - // in other words: this is a design flaw - // There should be a data stub accessible from the plugin object and the thread - // holding the necessary data, so that both can operate independently + // shut down plugin + Dispatch(effMainsChanged, 0, 0); + Dispatch(effClose); + } + } + catch(...) {} FreePlugin(); } void VSTPlugin::DspInit(float sr,int blsz) { - // sample rate and block size must _first_ be set - Dispatch(effSetSampleRate,0,0,NULL,samplerate = sr); - Dispatch(effSetBlockSize, 0,blsz); - // then signal that mains have changed! - Dispatch(effMainsChanged,0,1); + try { + // sample rate and block size must _first_ be set + Dispatch(effSetSampleRate,0,0,NULL,samplerate = sr); + Dispatch(effSetBlockSize, 0,blsz); + // then signal that mains have changed! + Dispatch(effMainsChanged,0,1); + } + catch(exception &e) { + flext::post("vst~ - caught exception while initializing dsp: %s",e.what()); + } + catch(...) { + flext::post("vst~ - caught exception while initializing dsp"); + } } void VSTPlugin::ListPlugs(const t_symbol *sym) const -- cgit v1.2.1