diff options
Diffstat (limited to 'externals/grill/vst/src/vsthost.cpp')
-rw-r--r-- | externals/grill/vst/src/vsthost.cpp | 938 |
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 |