aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/vst/src/vsthost.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill/vst/src/vsthost.cpp')
-rw-r--r--externals/grill/vst/src/vsthost.cpp938
1 files changed, 222 insertions, 716 deletions
diff --git a/externals/grill/vst/src/vsthost.cpp b/externals/grill/vst/src/vsthost.cpp
index 0d883cd9..2c4f0643 100644
--- a/externals/grill/vst/src/vsthost.cpp
+++ b/externals/grill/vst/src/vsthost.cpp
@@ -2,94 +2,113 @@
vst~ - VST plugin object for PD
based on the work of Jarno Seppänen and Mark Williamson
-Copyright (c)2003-2004 Thomas Grill (xovo@gmx.net)
+Copyright (c)2003-2005 Thomas Grill (gr@grrrr.org)
For information on usage and redistribution, and for a DISCLAIMER OF ALL
WARRANTIES, see the file, "license.txt," in this distribution.
*/
-#include "editor.h"
#include "vsthost.h"
-#include "AEffectx.h"
-#include <ctype.h>
-typedef AEffect *(VSTCALLBACK *PVSTMAIN)(audioMasterCallback audioMaster);
-
-
-
-VSTPlugin::VSTPlugin():
- h_dll(NULL),hwnd(NULL),_pEffect(NULL),
- posx(0),posy(0),caption(true),
- _midichannel(0),queue_size(0),
- paramnamecnt(0)
+const t_symbol
+ *VSTPlugin::sym_event,
+ *VSTPlugin::sym_evmidi,
+ *VSTPlugin::sym_evaudio,
+ *VSTPlugin::sym_evvideo,
+ *VSTPlugin::sym_evparam,
+ *VSTPlugin::sym_evtrigger,
+ *VSTPlugin::sym_evsysex,
+ *VSTPlugin::sym_ev_,
+ *VSTPlugin::sym_midi[8];
+
+void VSTPlugin::Setup()
+{
+ sym_event = flext::MakeSymbol("event");
+ sym_evmidi = flext::MakeSymbol("midi");
+ sym_evaudio = flext::MakeSymbol("audio");
+ sym_evvideo = flext::MakeSymbol("video");
+ sym_evparam = flext::MakeSymbol("param");
+ sym_evtrigger = flext::MakeSymbol("trigger");
+ 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[4] = flext::MakeSymbol("progchg");
+ sym_midi[5] = flext::MakeSymbol("chnafter");
+ sym_midi[6] = flext::MakeSymbol("pitchbend");
+ sym_midi[7] = sym__;
+}
+
+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)
+ , paramnamecnt(0)
+ , transchg(true)
+ , playing(false),looping(false)
+ , samplerate(0)
+ , samplepos(0),ppqpos(0)
+ , tempo(120)
+ , timesignom(4),timesigden(4)
+ , barstartpos(0)
+ , cyclestartpos(0),cycleendpos(0)
+ , smpteoffset(0),smpterate(0)
{}
VSTPlugin::~VSTPlugin()
{
- Free(); // Call free
+ Free();
}
-
-void VSTPlugin::FreeVST(MHandle handle)
-{
-#if FLEXT_OS == FLEXT_OS_WIN
- FreeLibrary(handle);
-#elif FLEXT_OS == FLEXT_OS_MAC
-#else
-#error Platform not supported
-#endif
-}
+
#if FLEXT_OS == FLEXT_OS_MAC
-OSStatus FSPathMakeFSSpec(
- const UInt8 *path,
- FSSpec *spec,
- Boolean *isDirectory) /* can be NULL */
+OSStatus FSPathMakeFSSpec(const UInt8 *path,FSSpec *spec,Boolean *isDirectory) /* can be NULL */
{
- OSStatus result;
- FSRef ref;
-
- /* check parameters */
- require_action(NULL != spec, BadParameter, result = paramErr);
-
- /* convert the POSIX path to an FSRef */
- result = FSPathMakeRef(path, &ref, isDirectory);
- require_noerr(result, FSPathMakeRef);
-
- /* and then convert the FSRef to an FSSpec */
- result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
- require_noerr(result, FSGetCatalogInfo);
+ OSStatus result;
+ FSRef ref;
+
+ /* check parameters */
+ require_action(NULL != spec, BadParameter, result = paramErr);
+
+ /* convert the POSIX path to an FSRef */
+ result = FSPathMakeRef(path, &ref, isDirectory);
+ require_noerr(result, FSPathMakeRef);
+
+ /* and then convert the FSRef to an FSSpec */
+ result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+ require_noerr(result, FSGetCatalogInfo);
FSGetCatalogInfo:
FSPathMakeRef:
BadParameter:
-
- return ( result );
+ return result;
}
#endif
-static long uniqueid = 0;
-
-int VSTPlugin::Instance(const char *dllname,const char *subname)
+// hdll, pluginmain and audiomaster are set here
+// must be NULL beforehand!
+bool VSTPlugin::NewPlugin(const char *plugname)
{
-#ifdef FLEXT_DEBUG
- flext::post("New Plugin 1 - %x",this);
-#endif
+ FLEXT_ASSERT(!hdll && !pluginmain && !audiomaster);
+
+ dllname = plugname;
- PVSTMAIN pluginmain;
#if FLEXT_OS == FLEXT_OS_WIN
- h_dll = LoadLibrary(dllname);
- if(!h_dll)
- return VSTINSTANCE_ERR_NO_VALID_FILE;
+ hdll = LoadLibrary(dllname.c_str());
+ if(hdll) pluginmain = (PVSTMAIN)GetProcAddress(hdll,"main");
+ audiomaster = Master;
- pluginmain = (PVSTMAIN)GetProcAddress(h_dll,"main");
- void *audioMasterFPtr = Master;
-
#elif FLEXT_OS == FLEXT_OS_MAC
short resFileID;
FSSpec spec;
OSErr err;
- err = FSPathMakeFSSpec(dllname,&spec,NULL);
+ err = FSPathMakeFSSpec(dllname.c_str(),&spec,NULL);
resFileID = FSpOpenResFile(&spec, fsRdPerm);
short cResCB = Count1Resources('aEff');
@@ -104,7 +123,7 @@ int VSTPlugin::Instance(const char *dllname,const char *subname)
OSType resType;
codeH = Get1IndResource('aEff', short(i+1));
- if (!codeH) continue;
+ if(!codeH) continue;
GetResInfo(codeH, &resID, &resType, fragName);
DetachResource(codeH);
@@ -116,7 +135,7 @@ int VSTPlugin::Instance(const char *dllname,const char *subname)
kPrivateCFragCopy,
&connID, (Ptr *) & mainAddr, errName);
- if (!err) {
+ if(!err) {
#ifdef __CFM__
pluginmain = (PVSTMAIN)NewMachOFromCFM(mainAddr);
#else
@@ -124,10 +143,9 @@ int VSTPlugin::Instance(const char *dllname,const char *subname)
#endif
}
}
-
CloseResFile(resFileID);
- void *audioMasterFPtr =
+ audiomaster =
#ifdef __CFM__
NewCFMFromMachO(Master);
#else
@@ -138,702 +156,190 @@ int VSTPlugin::Instance(const char *dllname,const char *subname)
#error Platform not supported
#endif
- if(!pluginmain) {
- FreeVST(h_dll);
- _pEffect = NULL;
- return VSTINSTANCE_ERR_NO_VST_PLUGIN;
- }
-
-
- uniqueid = 0;
-
- //This calls the "main" function and receives the pointer to the AEffect structure.
- _pEffect = pluginmain((audioMasterCallback)audioMasterFPtr);
- if(!_pEffect || _pEffect->magic != kEffectMagic) {
- post("VST plugin : Unable to create effect");
-
- _pEffect = NULL;
- FreeVST(h_dll);
- h_dll = NULL;
- return VSTINSTANCE_ERR_REJECTED;
- }
-
- if(subname && *subname && Dispatch(effGetPlugCategory) == kPlugCategShell) {
- // scan shell for subplugins
- char tempName[64];
- char idname[5]; idname[4] = 0;
- while((uniqueid = Dispatch(effShellGetNextPlugin,0,0,tempName))) {
- // subplug needs a name
- *(long *)idname = uniqueid;
- post("plug %s - %s",idname,tempName);
- if(!strcmp(subname,tempName) || !strcmp(subname,idname)) break;
- }
- }
-
- if(uniqueid) {
- // re-init with uniqueID set
- _pEffect = pluginmain((audioMasterCallback)audioMasterFPtr);
- if(!_pEffect || _pEffect->magic != kEffectMagic) {
- post("VST plugin : Unable to create effect");
-
- _pEffect = NULL;
- FreeVST(h_dll);
- h_dll = NULL;
- return VSTINSTANCE_ERR_REJECTED;
- }
+ if(hdll && pluginmain && audiomaster)
+ return true;
+ else {
+ FreePlugin();
+ return false;
}
+}
+void VSTPlugin::FreePlugin()
+{
+#if FLEXT_OS == FLEXT_OS_WIN
+ if(hdll) FreeLibrary(hdll);
+#elif FLEXT_OS == FLEXT_OS_MAC
+
#ifdef __MACOSX__
#ifdef __CFM__
- DisposeCFMFromMachO(audioMasterFPtr);
- DisposeMachOFromCFM(pluginmain);
-#endif
+ if(audiomaster) DisposeCFMFromMachO(audiomaster);
+ if(pluginmain) DisposeMachOFromCFM(pluginmain);
#endif
-
-
- //init plugin
- _pEffect->user = this;
-
- long ret = Dispatch( effOpen );
- FLEXT_ASSERT(!ret);
-
- ret = Dispatch( effIdentify);
- FLEXT_ASSERT(ret == 'NvEf');
-
- *_sProductName = 0;
- ret = Dispatch( effGetProductString, 0, 0, _sProductName, 0.0f);
- if(!*_sProductName) {
- // no product name given by plugin -> extract it from the filename
-
- std::string str1(dllname);
- std::string::size_type slpos = str1.rfind('\\');
- if(slpos == std::string::npos) {
- slpos = str1.rfind('/');
- if(slpos == std::string::npos)
- slpos = 0;
- else
- ++slpos;
- }
- else
- ++slpos;
- std::string str2 = str1.substr(slpos);
- int snip = str2.find('.');
- if( snip != std::string::npos )
- str1 = str2.substr(0,snip);
- else
- str1 = str2;
- strcpy(_sProductName,str1.c_str());
- }
-
- if(*_sProductName) {
- char tmp[512];
- sprintf(tmp,"vst~ - %s",_sProductName);
- title = tmp;
- }
- else
- title = "vst~";
-
- *_sVendorName = 0;
- Dispatch( effGetVendorString, 0, 0,_sVendorName, 0.0f);
-
- _sDllName = dllname;
-
-#ifdef FLEXT_DEBUG
- flext::post("New Plugin 2 - %x",this);
#endif
- return VSTINSTANCE_NO_ERROR;
-}
+#else
+#error Platform not supported
+#endif
+ effect = NULL;
+ audiomaster = NULL;
+ pluginmain = NULL;
+ hdll = NULL;
+}
/*
-void VSTPlugin::Create(VSTPlugin *plug)
-{
- h_dll = plug->h_dll;
- _pEffect = plug->_pEffect;
- _pEffect->user = this;
-
- Dispatch( effMainsChanged, 0, 1);
-// strcpy(_editName,plug->_editName); On current implementation, this replaces the right one.
- strcpy(_sProductName,plug->_sProductName);
- strcpy(_sVendorName,plug->_sVendorName);
-
- _sDllName = new char[strlen(plug->_sDllName)+1];
- strcpy(_sDllName,plug->_sDllName);
-
- _isSynth=plug->_isSynth;
- _version=plug->_version;
-
- plug->instantiated=false; // We are "stoling" the plugin from the "plug" object so this
- // is just a "trick" so that when destructing the "plug", it
- // doesn't unload the Dll.
- instantiated=true;
-}
+This is static to be able to communicate between the plugin methods
+and the static Audiomaster function
+the this (plugin->user) pointer has not been initialized at the point it is needed
+static should not be a problem, as we are single-threaded and it is immediately
+queried in a called function
*/
+long VSTPlugin::uniqueid = 0;
-void VSTPlugin::Free() // Called also in destruction
-{
- if(Is()) {
- if(IsEdited()) StopEditor(this);
-
- // shut down plugin
- Dispatch(effMainsChanged, 0, 0);
- Dispatch(effClose);
-
-#ifdef FLEXT_DEBUG
- flext::post("Free Plugin 1 - %x",this);
-#endif
-
- _pEffect = NULL;
-
- // \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
-
- if(h_dll) {
- FreeVST(h_dll);
- h_dll = NULL;
- }
-
-#ifdef FLEXT_DEBUG
- flext::post("Free Plugin 2 - %x",this);
-#endif
- }
-}
-
-void VSTPlugin::DspInit(float samplerate,int blocksize)
-{
- // sample rate and block size must _first_ be set
- Dispatch(effSetSampleRate, 0, 0,NULL,samplerate);
- Dispatch(effSetBlockSize, 0, blocksize);
- // than signal that mains have changed!
- Dispatch(effMainsChanged, 0, 1);
-}
+std::string VSTPlugin::dllloading;
-static void striptrail(char *txt)
+bool VSTPlugin::InstPlugin(long plugid)
{
- // strip trailing whitespace
- for(int i = strlen(txt)-1; i >= 0; --i)
- // cast to unsigned char since isspace functions don't want characters like 0x80 = -128
- if(isspace(((unsigned char *)txt)[i])) txt[i] = 0;
-}
+ uniqueid = plugid;
+ dllloading = dllname;
-void VSTPlugin::GetParamName(int numparam,char *name) const
-{
- if(numparam < GetNumParams()) {
- name[0] = 0;
- Dispatch(effGetParamName,numparam,0,name,0.0f);
- striptrail(name);
- }
- else
- name[0] = 0;
-}
+ FLEXT_ASSERT(pluginmain && audiomaster);
-bool VSTPlugin::SetParamFloat(int parameter,float value)
-{
- if(Is() && parameter >= 0 && parameter < GetNumParams()) {
- _pEffect->setParameter(_pEffect,parameter,value);
- return true;
- }
- else
+ //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");
+ effect = NULL;
return false;
-}
-
-void VSTPlugin::GetParamValue(int numparam,char *parval) const
-{
- if(Is()) {
- if(numparam < GetNumParams()) {
- // how many chars needed?
- char par_display[64]; par_display[0] = 0;
- Dispatch(effGetParamDisplay,numparam,0,par_display,0.0f);
-// if(par_display[7]) par_display[8] = 0; // set trailing zero
-
- // how many chars needed?
- char par_label[64]; par_label[0] = 0;
- Dispatch(effGetParamLabel,numparam,0,par_label,0.0f);
- striptrail(par_label);
-// if(par_label[7]) par_label[8] = 0; // set trailing zero
-
- sprintf(parval,"%s%s",par_display,par_label);
- }
- else
- strcpy(parval,"Index out of range");
}
- else
- strcpy(parval,"Plugin not loaded");
-}
-
-float VSTPlugin::GetParamValue(int numparam) const
-{
- if(Is() && numparam < GetNumParams())
- return _pEffect->getParameter(_pEffect, numparam);
- else
- return -1.0;
+ return true;
}
-void VSTPlugin::ScanParams(int cnt)
+bool VSTPlugin::Instance(const char *name,const char *subname)
{
- if(cnt < 0) cnt = GetNumParams();
- if(paramnamecnt >= cnt) return;
- if(cnt >= GetNumParams()) cnt = GetNumParams();
-
- char name[64];
- for(int i = paramnamecnt; i < cnt; ++i) {
- GetParamName(i,name);
- if(*name) paramnames[std::string(name)] = i;
+ bool ok = effect != NULL;
+
+ if(!ok && dllname != name) {
+ FreePlugin();
+ // freshly load plugin
+ ok = NewPlugin(name) && InstPlugin();
}
- paramnamecnt = cnt;
-}
-
-int VSTPlugin::GetParamIx(const char *p) const
-{
- NameMap::const_iterator it = paramnames.find(std::string(p));
- return it == paramnames.end()?-1:it->second;
-}
-void VSTPlugin::Edit(bool open)
-{
- if(Is()) {
- if(open) {
- if(HasEditor() && !IsEdited())
- StartEditor(this);
- }
- else if(IsEdited())
- StopEditor(this);
- }
-}
+ if(ok && subname && *subname && Dispatch(effGetPlugCategory) == kPlugCategShell) {
+ // sub plugin-name given -> scan plugs
-void VSTPlugin::StartEditing(WHandle h)
-{
- FLEXT_ASSERT(h != NULL);
- Dispatch(effEditOpen,0,0,hwnd = h);
-// Dispatch(effEditTop);
-
- TitleEditor(this,title.c_str());
-}
+ long plugid;
+ char tmp[64];
+ // scan shell for subplugins
+ while((plugid = Dispatch(effShellGetNextPlugin,0,0,tmp))) {
+ // subplug needs a name
+ FLEXT_LOG1("subplug %s",tmp);
+ if(!strcmp(subname,tmp))
+ // found
+ break;
+ }
-void VSTPlugin::StopEditing()
-{
- if(Is()) {
- Dispatch(effEditClose);
- hwnd = NULL;
+ // re-init with plugid set
+ if(plugid) ok = InstPlugin(plugid);
}
-}
-
-void VSTPlugin::Visible(bool vis)
-{
- if(Is() && IsEdited()) ShowEditor(this,vis);
-}
-
-bool VSTPlugin::IsVisible() const
-{
- return Is() && IsEdited() && IsEditorShown(this);
-}
-
-bool VSTPlugin::AddMIDI(unsigned char data0,unsigned char data1,unsigned char data2)
-{
- if(Is()) {
- VstMidiEvent* pevent = &midievent[queue_size];
-
- pevent->type = kVstMidiType;
- pevent->byteSize = 24;
- pevent->deltaFrames = 0;
- pevent->flags = 0;
- pevent->detune = 0;
- pevent->noteLength = 0;
- pevent->noteOffset = 0;
- pevent->reserved1 = 0;
- pevent->reserved2 = 0;
- pevent->noteOffVelocity = 0;
- pevent->midiData[0] = data0;
- pevent->midiData[1] = data1;
- pevent->midiData[2] = data2;
- pevent->midiData[3] = 0;
-
- if ( queue_size < MAX_EVENTS ) queue_size++;
- SendMidi();
- return true;
- }
- else return false;
-}
-
-
-void VSTPlugin::SendMidi()
-{
- if(Is() && queue_size > 0) {
- // Prepare MIDI events and free queue dispatching all events
- events.numEvents = queue_size;
- events.reserved = 0;
- for(int q = 0; q < queue_size; q++)
- events.events[q] = (VstEvent*)&midievent[q];
-
- Dispatch(effProcessEvents, 0, 0, &events, 0.0f);
- queue_size = 0;
- }
-}
-
-static int range(int value,int mn = 0,int mx = 127)
-{
- return value < mn?mn:(value > mx?mx:value);
-}
-
-bool VSTPlugin::AddNoteOn( unsigned char note,unsigned char speed,unsigned char midichannel)
-{
- return AddMIDI((char)MIDI_NOTEON | midichannel,note,speed);
-}
-
-bool VSTPlugin::AddNoteOff( unsigned char note,unsigned char midichannel)
-{
- return AddMIDI((char)MIDI_NOTEOFF | midichannel,note,0);
-}
-void VSTPlugin::AddAftertouch(int value)
-{
- AddMIDI( (char)MIDI_NOTEOFF | _midichannel , range(value) );
-}
-
-void VSTPlugin::AddPitchBend(int value)
-{
- AddMIDI( MIDI_PITCHBEND + (_midichannel & 0xf) , ((value>>7) & 127), (value & 127));
-}
-
-void VSTPlugin::AddProgramChange(int value)
-{
- AddMIDI( MIDI_PROGRAMCHANGE + (_midichannel & 0xf), range(value), 0);
-}
-
-void VSTPlugin::AddControlChange(int control, int value)
-{
- AddMIDI( MIDI_CONTROLCHANGE + (_midichannel & 0xf), range(control), range(value));
-}
-
-
-bool VSTPlugin::GetProgramName( int cat , int p, char *buf) const
-{
- buf[0] = 0;
- int parameter = p;
- if(parameter < GetNumPrograms() && cat < GetNumCategories()) {
- Dispatch(effGetProgramNameIndexed,parameter,cat,buf,0.0f);
- striptrail(buf);
- return true;
- }
- else
- return false;
-}
-
-void VSTPlugin::SetPos(int x,int y,bool upd)
-{
- if(Is()) {
- posx = x; posy = y;
- if(upd && IsEdited()) MoveEditor(this,posx,posy);
+ if(ok) {
+ //init plugin
+ effect->user = this;
+ ok = Dispatch(effOpen) == 0;
}
-}
-void VSTPlugin::SetCaption(bool c)
-{
- if(Is()) {
- caption = c;
- if(IsEdited()) CaptionEditor(this,c);
+ if(ok) {
+ ok = Dispatch(effIdentify) == 'NvEf';
}
-}
-void VSTPlugin::SetTitle(const char *t)
-{
- if(Is()) {
- title = t;
- if(IsEdited()) TitleEditor(this,t);
- }
-}
+ if(ok) {
+ *productname = 0;
+ long ret = Dispatch(effGetProductString,0,0,productname);
+
+ if(!*productname) {
+ // no product name given by plugin -> extract it from the filename
+
+ std::string str1(dllname);
+ std::string::size_type slpos = str1.rfind('\\');
+ if(slpos == std::string::npos) {
+ slpos = str1.rfind('/');
+ if(slpos == std::string::npos)
+ slpos = 0;
+ else
+ ++slpos;
+ }
+ else
+ ++slpos;
+ std::string str2 = str1.substr(slpos);
+ int snip = str2.find('.');
+ if( snip != std::string::npos )
+ str1 = str2.substr(0,snip);
+ else
+ str1 = str2;
+ strcpy(productname,str1.c_str());
+ }
+
+ if(*productname) {
+ char tmp[512];
+ sprintf(tmp,"vst~ - %s",productname);
+ title = tmp;
+ }
+ else
+ title = "vst~";
-void VSTPlugin::processReplacing( float **inputs, float **outputs, long sampleframes )
-{
- _pEffect->processReplacing( _pEffect , inputs , outputs , sampleframes );
-}
+ *vendorname = 0;
+ Dispatch(effGetVendorString,0,0,vendorname);
+ }
-void VSTPlugin::process( float **inputs, float **outputs, long sampleframes )
-{
- _pEffect->process( _pEffect , inputs , outputs , sampleframes );
+ if(!ok) Free();
+ return ok;
}
-#if 1
-
-// Host callback dispatcher
-long VSTPlugin::Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt)
+void VSTPlugin::Free() // Called also in destruction
{
-#if 0
- audioMasterEnum op = (audioMasterEnum)opcode;
- audioMasterEnumx opx = (audioMasterEnumx)opcode;
-#endif
-
-#ifdef FLEXT_DEBUG
- post("VST -> host: Eff = 0x%.8X, Opcode = %d, Index = %d, Value = %d, PTR = %.8X, OPT = %.3f\n",(int)effect, opcode,index,value,(int)ptr,opt);
-#endif
-
-// VSTPlugin *th = effect?(VSTPlugin *)effect->user:NULL;
+ if(effect) {
+ Edit(false);
- switch (opcode) {
- case audioMasterAutomate: // 0
-#ifdef FLEXT_DEBUG
- post("Automate index=%li value=%li opt=%f",index,value,opt);
-#endif
- // index, value given
- //! \todo set effect parameter
- return 0;
- case audioMasterVersion: // 1
- // support VST 2.3
- return 2300;
-// return 2;
- case audioMasterCurrentId: { // 2
- return uniqueid;
+ // shut down plugin
+ Dispatch(effMainsChanged, 0, 0);
+ Dispatch(effClose);
}
- case audioMasterIdle: // 3
- effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
- return 0;
- case audioMasterPinConnected: // 4
- //! \todo set connection state correctly (if possible..)
- // index=pin, value=0..input, else..output
-#ifdef FLEXT_DEBUG
- post("Pin connected pin=%li conn=%li",index,value);
-#endif
- return 0; // 0 means connected
- case audioMasterWantMidi: // 6
-#ifdef FLEXT_DEBUG
- post("Want MIDI = %li",value);
-#endif
- return 0; // VST header says: "currently ignored"
- case audioMasterGetTime: // 7
- return 0; // not supported
- case audioMasterProcessEvents: { // 8
- // VST event data from plugin
- VstEvent *ev = static_cast<VstEvent *>(ptr);
- if(ev->type == kVstMidiType) {
- VstMidiEvent *mev = static_cast<VstMidiEvent *>(ptr);
-#ifdef FLEXT_DEBUG
- if(mev->byteSize == 24)
- post("MIDI event delta=%li len=%li offs=%li detune=%i offvel=%i",mev->deltaFrames,mev->noteLength,mev->noteOffset,(int)mev->detune,(int)mev->noteOffVelocity);
- else
- // has incorrect size
- post("MIDI event");
-#endif
- }
- else {
-#ifdef FLEXT_DEBUG
- post("VST event type=%li",ev->type);
-#endif
- }
- return 1;
- }
- case audioMasterSetTime: { // 9
- VstTimeInfo *tminfo = static_cast<VstTimeInfo *>(ptr);
-#ifdef FLEXT_DEBUG
- post("TimeInfo pos=%lf rate=%lf filter=%li",tminfo->samplePos,tminfo->sampleRate,value);
-#endif
- return 0; // not supported
- }
- case audioMasterTempoAt: // 10
- return 0; // not supported
- case audioMasterGetNumAutomatableParameters: // 11
- return 0; // not supported
- case audioMasterSizeWindow: // 15
- return 0;
-// case audioMasterGetSampleRate: // 16
-// case audioMasterGetBlockSize: // 17
- case audioMasterGetCurrentProcessLevel: // 23
- // return thread state
- return flext::GetThreadId() == flext::GetSysThreadId()?2:1;
- case audioMasterGetVendorString: // 32
- strcpy((char*)ptr,"grrrr.org");
- return 0;
- case audioMasterGetProductString: // 33
- strcpy((char *)ptr,"vst~ host external");
- return 0;
- case audioMasterGetVendorVersion: // 34
- return 100;
- case audioMasterCanDo: // 37
-#ifdef FLEXT_DEBUG
- post("\taudioMasterCanDo PTR = %s",ptr);
-#endif
- if(!strcmp((char *)ptr,"sendVstEvents"))
- return 1;
- else if(!strcmp((char *)ptr,"sendVstMidiEvent"))
- return 1;
- else if(!strcmp((char *)ptr,"sendVstTimeInfo"))
- return 1; // NOT YET
- else if(!strcmp((char *)ptr,"receiveVstEvents"))
- return 1;
- else if(!strcmp((char *)ptr,"receiveVstMidiEvent"))
- return 1;
- else if(!strcmp((char *)ptr,"receiveVstTimeInfo"))
- return 1; // NOT YET
- else if(!strcmp((char *)ptr,"reportConnectionChanges"))
- return 0; // \TODO PD has hard times supporting that...
- else if(!strcmp((char *)ptr,"acceptIOChanges"))
- return 0; // \TODO what does this means exactly?
- else if(!strcmp((char *)ptr,"supplyIdle"))
- return 1;
- else if(!strcmp((char *)ptr,"sizeWindow"))
- return 1;
- else if(!strcmp((char *)ptr,"supportShell"))
- return 0; // deprecated - new one is shellCategory
- else if(!strcmp((char *)ptr,"offline"))
- return 0; // not supported
- else if(!strcmp((char *)ptr,"asyncProcessing"))
- return 0; // not supported
- else if(!strcmp((char *)ptr,"shellCategory"))
- return 1; // supported!
-
- return 0; // not supported
- case audioMasterGetLanguage: // 38
- return kVstLangEnglish;
- case audioMasterGetDirectory: // 41
- // return full path of plugin
- return 0; // not supported
- case audioMasterUpdateDisplay: // 42
-#ifdef FLEXT_DEBUG
- post("UPDATE DISPLAY");
-#endif
- return 0;
- default:
-#ifdef FLEXT_DEBUG
- post("Unknown opcode %li",opcode);
-#endif
- return 0;
- }
-}
+ // \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
-#else
+ FreePlugin();
+}
-// Host callback dispatcher
-long VSTPlugin::Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt)
+void VSTPlugin::DspInit(float sr,int blsz)
{
- VSTPlugin *th = effect?(VSTPlugin *)effect->user:NULL;
- if(!th) FLEXT_LOG("No this");
-
-#ifdef FLEXT_DEBUG
- if(opcode != audioMasterGetTime)
- post("VST plugin call to host dispatcher: Eff: 0x%.8X, Opcode = %d, Index = %d, Value = %d, PTR = %.8X, OPT = %.3f\n",(int)effect, opcode,index,value,(int)ptr,opt);
- //st( "audioMasterWantMidi %d " , audioMasterWantMidi);
-#endif
-
- // Support opcodes
- switch(opcode)
- {
- case audioMasterAutomate:
- return 0; // index, value, returns 0
-
- case audioMasterVersion:
- return 2; // vst version, currently 7 (0 for older)
-
- case audioMasterCurrentId:
- return subplugid;
-
- case audioMasterIdle:
- effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
- return 0; // call application idle routine (this will call effEditIdle for all open editors too)
-
- case audioMasterPinConnected:
- if(value == 0)
- return index < 2?0:1; //input
- else
- return index < 2?0:1; //output
-
-/*
- case audioMasterWantMidi:
- return 0;
-
- case audioMasterProcessEvents:
- return 0; // Support of vst events to host is not available
-*/
- case audioMasterGetTime:
- memset(&_timeInfo, 0, sizeof(_timeInfo));
- _timeInfo.samplePos = 0;
- _timeInfo.sampleRate = th?th->sample_rate:0;
- return (long)&_timeInfo;
-
-
- case audioMasterTempoAt:
- return 0;
-
- case audioMasterNeedIdle:
-// effect->dispatcher(effect, effIdle, 0, 0, NULL, 0.0f);
- return 1;
-
- case audioMasterGetSampleRate:
- return th?(long)th->sample_rate:0;
-
- case audioMasterGetVendorString: // Just fooling version string
- strcpy((char*)ptr,"Steinberg");
- return 0;
-
- case audioMasterGetVendorVersion:
- return 5000; // HOST version 5000
-
- case audioMasterGetProductString: // Just fooling product string
- strcpy((char *)ptr,"Cubase 5.0");
- return 0;
-
- case audioMasterVendorSpecific:
- return 0;
+ // 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);
+}
+
+void VSTPlugin::ListPlugs(const t_symbol *sym) const
+{
+ if(responder) {
+ if(Is() && Dispatch(effGetPlugCategory) == kPlugCategShell) {
+ t_atom at;
+ // sub plugin-name given -> scan plugs
+ char tmp[64];
+ // scan shell for subplugins
+ while(Dispatch(effShellGetNextPlugin,0,0,tmp)) {
+ SetString(at,tmp);
+ responder->Respond(sym,1,&at);
+ }
+ }
- case audioMasterGetLanguage:
- return kVstLangEnglish;
-
- case audioMasterUpdateDisplay:
- FLEXT_LOG("audioMasterUpdateDisplay");
- effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
- return 0;
-
- case audioMasterCanDo:
- if (!strcmp((char *)ptr,"sendVstEvents")) return 1;
- else if (!strcmp((char *)ptr,"sendVstMidiEvent")) return 1;
- else if (!strcmp((char *)ptr,"sendVstTimeInfo")) return 1;
-// "receiveVstEvents",
-// "receiveVstMidiEvent",
-// "receiveVstTimeInfo",
-
-// "reportConnectionChanges",
-// "acceptIOChanges",
-// else if (!strcmp((char*)ptr,"sizeWindow")) return 1;
- else if (!strcmp((char*)ptr,"supplyIdle")) return 1;
- return -1;
-
- case audioMasterSetTime: FLEXT_LOG("VST master dispatcher: Set Time");break;
- case audioMasterGetNumAutomatableParameters: FLEXT_LOG("VST master dispatcher: GetNumAutPar");break;
- case audioMasterGetParameterQuantization: FLEXT_LOG("VST master dispatcher: ParamQuant");break;
- case audioMasterIOChanged: FLEXT_LOG("VST master dispatcher: IOchanged");break;
- case audioMasterSizeWindow: FLEXT_LOG("VST master dispatcher: Size Window");break;
- case audioMasterGetBlockSize: FLEXT_LOG("VST master dispatcher: GetBlockSize");break;
- case audioMasterGetInputLatency: FLEXT_LOG("VST master dispatcher: GetInLatency");break;
- case audioMasterGetOutputLatency: FLEXT_LOG("VST master dispatcher: GetOutLatency");break;
- case audioMasterGetPreviousPlug: FLEXT_LOG("VST master dispatcher: PrevPlug");break;
- case audioMasterGetNextPlug: FLEXT_LOG("VST master dispatcher: NextPlug");break;
- case audioMasterWillReplaceOrAccumulate: FLEXT_LOG("VST master dispatcher: WillReplace"); break;
- case audioMasterGetCurrentProcessLevel: return 0; break;
- case audioMasterGetAutomationState: FLEXT_LOG("VST master dispatcher: GetAutState");break;
- case audioMasterOfflineStart: FLEXT_LOG("VST master dispatcher: Offlinestart");break;
- case audioMasterOfflineRead: FLEXT_LOG("VST master dispatcher: Offlineread");break;
- case audioMasterOfflineWrite: FLEXT_LOG("VST master dispatcher: Offlinewrite");break;
- case audioMasterOfflineGetCurrentPass: FLEXT_LOG("VST master dispatcher: OfflineGetcurrentpass");break;
- case audioMasterOfflineGetCurrentMetaPass: FLEXT_LOG("VST master dispatcher: GetGetCurrentMetapass");break;
- case audioMasterSetOutputSampleRate: FLEXT_LOG("VST master dispatcher: Setsamplerate");break;
- case audioMasterGetSpeakerArrangement: FLEXT_LOG("VST master dispatcher: Getspeaker");break;
- case audioMasterSetIcon: FLEXT_LOG("VST master dispatcher: seticon");break;
- case audioMasterOpenWindow: FLEXT_LOG("VST master dispatcher: OpenWindow");break;
- case audioMasterCloseWindow: FLEXT_LOG("VST master dispatcher: CloseWindow");break;
- case audioMasterGetDirectory: FLEXT_LOG("VST master dispatcher: GetDirectory");break;
-// case audioMasterUpdateDisplay: post("VST master dispatcher: audioMasterUpdateDisplay");break;
-
-#ifdef FLEXT_DEBUG
- default:
- post("VST master dispatcher: undefed: %d , %d",opcode , effKeysRequired );
-#endif
- }
-
- return 0;
+ // bang
+ responder->Respond(sym);
+ }
}
-
-#endif