From 27da08004c5f024a0f35e3cb4c2b3942548ebcfa Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Fri, 11 Mar 2005 04:58:01 +0000 Subject: restructured VSThost code better shell support fix for build system update for flext build systemcleanups VSTTime info added event processing (like Midi in) svn path=/trunk/; revision=2617 --- externals/grill/vst/src/editorwin.hpp | 20 +- externals/grill/vst/src/main.cpp | 489 ++++++++++-------- externals/grill/vst/src/main.h | 12 - externals/grill/vst/src/vst.rc | 2 +- externals/grill/vst/src/vstedit.cpp | 76 +++ externals/grill/vst/src/vsthost.cpp | 938 ++++++++-------------------------- externals/grill/vst/src/vsthost.h | 293 ++++++++--- externals/grill/vst/src/vstmaster.cpp | 288 +++++++++++ externals/grill/vst/src/vstmidi.cpp | 52 ++ externals/grill/vst/src/vstparam.cpp | 105 ++++ 10 files changed, 1233 insertions(+), 1042 deletions(-) create mode 100644 externals/grill/vst/src/vstedit.cpp create mode 100644 externals/grill/vst/src/vstmaster.cpp create mode 100644 externals/grill/vst/src/vstmidi.cpp create mode 100644 externals/grill/vst/src/vstparam.cpp (limited to 'externals/grill/vst/src') diff --git a/externals/grill/vst/src/editorwin.hpp b/externals/grill/vst/src/editorwin.hpp index f29313d4..29e63db6 100644 --- a/externals/grill/vst/src/editorwin.hpp +++ b/externals/grill/vst/src/editorwin.hpp @@ -38,7 +38,7 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) plug->StartEditing(hwnd); break; case WM_CLOSE: -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("WM_CLOSE"); #endif // plug could already have been unloaded... @@ -46,7 +46,7 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) DestroyWindow(hwnd); break; case WM_DESTROY: -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("WM_DESTROY"); #endif // stop editor thread @@ -66,7 +66,7 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) short x = reinterpret_cast(wx),y = reinterpret_cast(wy); // x and y are the coordinates of the client rect (= actual VST interface) plug->SetPos(x,y,false); -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("WM_MOVE x/y=%i/%i",x,y); #endif break; @@ -87,7 +87,7 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) } #endif -#if 0 //def FLEXT_DEBUG +#if 0 //def FLEXT_LOGGING case WM_SIZE: { WORD wx = LOWORD(lp),wy = HIWORD(lp); short x = reinterpret_cast(wx),y = reinterpret_cast(wy); @@ -98,7 +98,7 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) #endif default: - #ifdef FLEXT_DEBUG + #ifdef FLEXT_LOGGING flext::post("WND MSG %i, WP=%i, lp=%i",msg,wp,lp); #endif @@ -169,7 +169,7 @@ static void threadfun(flext::thr_params *p) ERect r; plug->GetEditorRect(r); windowsize(wnd,plug->GetX(),plug->GetY(),r.right-r.left,r.bottom-r.top,plug->GetCaption(),SWP_SHOWWINDOW); -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("Editor rect left/top=%i/%i, right/bottom=%i/%i",r.left,r.top,r.right,r.bottom); #endif @@ -220,23 +220,23 @@ void SetupEditor() void StartEditor(VSTPlugin *p) { -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("Start editor 1"); #endif flext::LaunchThread(threadfun,reinterpret_cast(p)); -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("Start editor 2"); #endif } void StopEditor(VSTPlugin *p) { -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("Stop editor 1"); #endif PostMessage(p->EditorHandle(),WM_CLOSE,0,0); flext::StopThread(threadfun,reinterpret_cast(p)); -#ifdef FLEXT_DEBUG +#ifdef FLEXT_LOGGING flext::post("Stop editor 2"); #endif } diff --git a/externals/grill/vst/src/main.cpp b/externals/grill/vst/src/main.cpp index 75b5feda..1292a746 100644 --- a/externals/grill/vst/src/main.cpp +++ b/externals/grill/vst/src/main.cpp @@ -26,109 +26,142 @@ WARRANTIES, see the file, "license.txt," in this distribution. #endif -#define VST_VERSION "0.1.0pre18" +#define VST_VERSION "0.1.0pre19" -class vst: - public flext_dsp +class vst + : public flext_dsp + , public Responder { FLEXT_HEADER_S(vst,flext_dsp,Setup) public: - vst(I argc,const A *argv); + vst(int argc,const t_atom *argv); ~vst(); protected: - virtual V m_dsp(I n,t_signalvec const *insigs,t_signalvec const *outsigs); - virtual V m_signal(I n,R *const *insigs,R *const *outsigs); + virtual void m_dsp(int n,t_signalvec const *insigs,t_signalvec const *outsigs); + virtual void m_signal(int n,t_sample *const *insigs,t_sample *const *outsigs); virtual void m_click() { ms_edit(true); } - BL ms_plug(I argc,const A *argv); - BL ms_plug(const AtomList &args) { return ms_plug(args.Count(),args.Atoms()); } - V mg_plug(AtomList &sym) const { sym(1); SetString(sym[0],plugname.c_str()); } + bool ms_plug(int argc,const t_atom *argv); + bool ms_plug(const AtomList &args) { return ms_plug(args.Count(),args.Atoms()); } + void mg_plug(AtomList &sym) const { sym(1); SetString(sym[0],plugname.c_str()); } - void ms_subplug(I argc,const A *argv); + void ms_subplug(int argc,const t_atom *argv); void ms_subplug(const AtomList &args) { ms_subplug(args.Count(),args.Atoms()); } void mg_subplug(AtomList &sym) const { sym(1); SetString(sym[0],subplug.c_str()); } - V mg_editor(BL &ed) { ed = plug && plug->HasEditor(); } - - V ms_edit(BL on) { if(plug) plug->Edit(on); } - V mg_edit(BL &ed) { ed = plug && plug->IsEdited(); } - V ms_vis(BL vis) { if(plug) plug->Visible(vis); } - V mg_vis(BL &vis) { vis = plug && plug->IsVisible(); } - - V mg_winx(I &x) const { x = plug?plug->GetX():0; } - V mg_winy(I &y) const { y = plug?plug->GetY():0; } - V ms_winx(I x) { if(plug) plug->SetX(x); } - V ms_winy(I y) { if(plug) plug->SetY(y); } - V ms_wincaption(bool c) { if(plug) plug->SetCaption(c); } - V mg_wincaption(bool &c) const { c = plug && plug->GetCaption(); } - V ms_wintitle(const AtomList &t); - V mg_wintitle(AtomList &t) const { if(plug) { t(1); SetString(t[0],plug->GetTitle()); } } - - V mg_chnsin(I &c) const { c = plug?plug->GetNumInputs():0; } - V mg_chnsout(I &c) const { c = plug?plug->GetNumOutputs():0; } - V mg_params(I &p) const { p = plug?plug->GetNumParams():0; } - V mg_programs(I &p) const { p = plug?plug->GetNumPrograms():0; } - V mg_progcats(I &p) const { p = plug?plug->GetNumCategories():0; } - V mg_plugname(const S *&s) const { s = plug?MakeSymbol(plug->GetName()):sym__; } - V mg_plugvendor(const S *&s) const { s = plug?MakeSymbol(plug->GetVendorName()):sym__; } - V mg_plugdll(const S *&s) const { s = plug?MakeSymbol(plug->GetDllName()):sym__; } - V mg_plugversion(I &v) const { v = plug?plug->GetVersion():0; } - V mg_issynth(BL &s) const { s = plug && plug->IsSynth(); } - - V m_print(I ac,const A *av); - - V ms_program(I p); - V mg_program(I &p) const { p = plug?plug->GetCurrentProgram():0; } - V mg_progname(int argc,const t_atom *argv) const; + void m_pluglist() { if(plug) plug->ListPlugs(sym_pluglist); } + + void mg_editor(bool &ed) { ed = plug && plug->HasEditor(); } + + void ms_edit(bool on) { if(plug) plug->Edit(on); } + void mg_edit(bool &ed) { ed = plug && plug->IsEdited(); } + void ms_vis(bool vis) { if(plug) plug->Visible(vis); } + void mg_vis(bool &vis) { vis = plug && plug->IsVisible(); } + + void mg_winx(int &x) const { x = plug?plug->GetX():0; } + void mg_winy(int &y) const { y = plug?plug->GetY():0; } + void ms_winx(int x) { if(plug) plug->SetX(x); } + void ms_winy(int y) { if(plug) plug->SetY(y); } + void ms_wincaption(bool c) { if(plug) plug->SetCaption(c); } + void mg_wincaption(bool &c) const { c = plug && plug->GetCaption(); } + void ms_wintitle(const AtomList &t); + void mg_wintitle(AtomList &t) const { if(plug) { t(1); SetString(t[0],plug->GetTitle()); } } + + void mg_chnsin(int &c) const { c = plug?plug->GetNumInputs():0; } + void mg_chnsout(int &c) const { c = plug?plug->GetNumOutputs():0; } + void mg_params(int &p) const { p = plug?plug->GetNumParams():0; } + void mg_programs(int &p) const { p = plug?plug->GetNumPrograms():0; } + void mg_progcats(int &p) const { p = plug?plug->GetNumCategories():0; } + void mg_plugname(const t_symbol *&s) const { s = plug?MakeSymbol(plug->GetName()):sym__; } + void mg_plugvendor(const t_symbol *&s) const { s = plug?MakeSymbol(plug->GetVendorName()):sym__; } + void mg_plugdll(const t_symbol *&s) const { s = plug?MakeSymbol(plug->GetDllName()):sym__; } + void mg_plugversion(int &v) const { v = plug?plug->GetVersion():0; } + void mg_issynth(bool &s) const { s = plug && plug->IsSynth(); } + + void m_print(int ac,const t_atom *av); + + void ms_program(int p) { if(plug && p >= 0) plug->SetCurrentProgram(p); } + void mg_program(int &p) const { p = plug?plug->GetCurrentProgram():0; } + void mg_progname(int argc,const t_atom *argv) const; - V m_pname(I pnum); - V ms_paramnames(int cnt) { paramnames = cnt; if(plug) plug->ScanParams(cnt); } - - V ms_param(I pnum,F val); - V ms_params(int argc,const t_atom *argv); - V mg_param(I pnum); - V mg_params(int argc,const t_atom *argv); - V m_ptext(I pnum); - V m_ptexts(int argc,const t_atom *argv); - -// V m_control(const S *ctrl_name,I ctrl_value); - V m_pitchbend(I ctrl_value); - V m_programchange(I ctrl_value); - V m_aftertouch(I ctrl_value); - V m_ctrlchange(I control,I ctrl_value); - V m_note(I note,I vel); - inline V m_noteoff(I note) { m_note(note,0); } + void m_pname(int pnum); + void ms_paramnames(int cnt) { paramnames = cnt; if(plug) plug->ScanParams(cnt); } + + void ms_param(int pnum,float val); + void ms_params(int argc,const t_atom *argv); + void mg_param(int pnum); + void mg_params(int argc,const t_atom *argv); + void m_ptext(int pnum); + void m_ptexts(int argc,const t_atom *argv); + +// void m_control(const t_symbol *ctrl_name,int ctrl_value); + void m_pitchbend(int ctrl_value) { if(plug) plug->AddPitchBend(ctrl_value ); } + void m_programchange(int ctrl_value) { if(plug) plug->AddProgramChange(ctrl_value ); } + void m_aftertouch(int ctrl_value) { if(plug) plug->AddAftertouch(ctrl_value ); } + void m_ctrlchange(int control,int ctrl_value) { if(plug) plug->AddControlChange(control,ctrl_value ); } + void m_note(int note,int vel); + void m_noteoff(int note) { m_note(note,0); } + + void mg_playing(bool &p) { p = plug && plug->GetPlaying(); } + void ms_playing(bool p) { if(plug) plug->SetPlaying(p); } + void mg_looping(bool &p) { p = plug && plug->GetLooping(); } + void ms_looping(bool p) { if(plug) plug->SetLooping(p); } + void mg_samplepos(float &p) { p = plug?(float)plug->GetSamplePos():0; } + void ms_samplepos(float p) { if(plug) plug->SetSamplePos(p); } + void mg_ppqpos(float &p) { p = plug?(float)plug->GetPPQPos():0; } + void ms_ppqpos(float p) { if(plug) plug->SetPPQPos(p); } + void mg_tempo(float &p) { p = plug?(float)plug->GetTempo():0; } + void ms_tempo(float p) { if(plug) plug->SetTempo(p); } + void mg_barstart(float &p) { p = plug?(float)plug->GetBarStart():0; } + void ms_barstart(float p) { if(plug) plug->SetBarStart(p); } + void mg_cyclestart(float &p) { p = plug?(float)plug->GetCycleStart():0; } + void ms_cyclestart(float p) { if(plug) plug->SetCycleStart(p); } + void mg_cycleend(float &p) { p = plug?(float)plug->GetCycleEnd():0; } + void ms_cycleend(float p) { if(plug) plug->SetCycleEnd(p); } + void mg_cyclelength(float &p) { p = plug?(float)(plug->GetCycleEnd()-plug->GetCycleStart()):0; } + void ms_cyclelength(float p) { if(p) plug->SetCycleEnd(plug->GetCycleStart()+p); } + void mg_timesignom(int &p) { p = plug?plug->GetTimesigNom():0; } + void ms_timesignom(int p) { if(plug) plug->SetTimesigNom(p); } + void mg_timesigden(int &p) { p = plug?plug->GetTimesigDen():0; } + void ms_timesigden(int p) { if(plug) plug->SetTimesigDen(p); } + void mg_smpteoffset(int &p) { p = plug?plug->GetSmpteOffset():0; } + void ms_smpteoffset(int p) { if(plug) plug->SetSmpteOffset(p); } + void mg_smpterate(int &p) { p = plug?plug->GetSmpteRate():0; } + void ms_smpterate(int p) { if(plug) plug->SetSmpteRate(p); } private: - V display_parameter(I param,BL showparams); + void display_parameter(int param,bool showparams); VSTPlugin *plug; std::string plugname,subplug; bool echoparam,visible,bypass,mute; int paramnames; - I blsz; - V (VSTPlugin::*vstfun)(R **insigs,R **outsigs,L n); - BL sigmatch; - R **vstin,**vstout,**tmpin,**tmpout; + int blsz; + void (VSTPlugin::*vstfun)(t_sample **insigs,t_sample **outsigs,long n); + bool sigmatch; + t_sample **vstin,**vstout,**tmpin,**tmpout; - V InitPlug(); - V ClearPlug(); - V InitPlugDSP(); - V InitBuf(); - V ClearBuf(); + void InitPlug(); + void ClearPlug(); + bool LoadPlug(); + void InitPlugDSP(); + void InitBuf(); + void ClearBuf(); - static V Setup(t_classid); + static void Setup(t_classid); + virtual void Respond(const t_symbol *sym,int argc = 0,const t_atom *argv = NULL); FLEXT_CALLBACK_V(m_print) FLEXT_CALLVAR_V(mg_plug,ms_plug) FLEXT_CALLVAR_V(mg_subplug,ms_subplug) + FLEXT_CALLBACK(m_pluglist) FLEXT_CALLVAR_B(mg_edit,ms_edit) FLEXT_CALLGET_B(mg_editor) @@ -175,15 +208,29 @@ private: FLEXT_CALLGET_I(mg_plugversion) FLEXT_CALLGET_B(mg_issynth) - static const t_symbol *sym_progname,*sym_pname,*sym_param,*sym_ptext; + FLEXT_CALLVAR_B(mg_playing,ms_playing) + FLEXT_CALLVAR_B(mg_looping,ms_looping) + FLEXT_CALLVAR_F(mg_samplepos,ms_samplepos) + FLEXT_CALLVAR_F(mg_ppqpos,ms_ppqpos) + FLEXT_CALLVAR_F(mg_tempo,ms_tempo) + FLEXT_CALLVAR_F(mg_barstart,ms_barstart) + FLEXT_CALLVAR_F(mg_cyclestart,ms_cyclestart) + FLEXT_CALLVAR_F(mg_cycleend,ms_cycleend) + FLEXT_CALLVAR_F(mg_cyclelength,ms_cyclelength) + FLEXT_CALLVAR_I(mg_timesignom,ms_timesignom) + FLEXT_CALLVAR_I(mg_timesigden,ms_timesigden) + FLEXT_CALLVAR_I(mg_smpteoffset,ms_smpteoffset) + FLEXT_CALLVAR_I(mg_smpterate,ms_smpterate) + + static const t_symbol *sym_progname,*sym_pname,*sym_param,*sym_ptext,*sym_pluglist; }; FLEXT_NEW_DSP_V("vst~",vst); -const t_symbol *vst::sym_progname,*vst::sym_pname,*vst::sym_param,*vst::sym_ptext; +const t_symbol *vst::sym_progname,*vst::sym_pname,*vst::sym_param,*vst::sym_ptext,*vst::sym_pluglist; -V vst::Setup(t_classid c) +void vst::Setup(t_classid c) { post(""); post("vst~ %s - VST plugin object, (C)2003-05 Thomas Grill",VST_VERSION); @@ -192,6 +239,7 @@ V vst::Setup(t_classid c) FLEXT_CADDATTR_VAR(c,"plug",mg_plug,ms_plug); FLEXT_CADDATTR_VAR(c,"subplug",mg_subplug,ms_subplug); + FLEXT_CADDMETHOD_(c,0,"getpluglist",m_pluglist); FLEXT_CADDATTR_VAR(c,"edit",mg_edit,ms_edit); FLEXT_CADDATTR_GET(c,"editor",mg_editor); FLEXT_CADDATTR_VAR(c,"vis",mg_vis,ms_vis); @@ -236,34 +284,50 @@ V vst::Setup(t_classid c) FLEXT_CADDATTR_GET(c,"version",mg_plugversion); FLEXT_CADDATTR_GET(c,"synth",mg_issynth); + FLEXT_CADDATTR_VAR(c,"playing",mg_playing,ms_playing); + FLEXT_CADDATTR_VAR(c,"looping",mg_looping,ms_looping); + FLEXT_CADDATTR_VAR(c,"samplepos",mg_samplepos,ms_samplepos); + FLEXT_CADDATTR_VAR(c,"ppqpos",mg_ppqpos,ms_ppqpos); + FLEXT_CADDATTR_VAR(c,"tempo",mg_tempo,ms_tempo); + FLEXT_CADDATTR_VAR(c,"barstart",mg_barstart,ms_barstart); + FLEXT_CADDATTR_VAR(c,"loopstart",mg_cyclestart,ms_cyclestart); + FLEXT_CADDATTR_VAR(c,"loopend",mg_cycleend,ms_cycleend); + FLEXT_CADDATTR_VAR(c,"looplength",mg_cyclelength,ms_cyclelength); + FLEXT_CADDATTR_VAR(c,"timenom",mg_timesignom,ms_timesignom); + FLEXT_CADDATTR_VAR(c,"timeden",mg_timesigden,ms_timesigden); + FLEXT_CADDATTR_VAR(c,"smpteoffset",mg_smpteoffset,ms_smpteoffset); + FLEXT_CADDATTR_VAR(c,"smpterate",mg_smpterate,ms_smpterate); + sym_progname = MakeSymbol("progname"); sym_pname = MakeSymbol("pname"); sym_param = MakeSymbol("param"); sym_ptext = MakeSymbol("ptext"); + sym_pluglist = MakeSymbol("pluglist"); + VSTPlugin::Setup(); SetupEditor(); } -vst::vst(I argc,const A *argv): +vst::vst(int argc,const t_atom *argv): plug(NULL),visible(false), blsz(0), vstfun(NULL),vstin(NULL),vstout(NULL),tmpin(NULL),tmpout(NULL), echoparam(false),bypass(false),mute(false),paramnames(0) { - if(argc >= 2 && CanbeInt(argv[0]) && CanbeInt(argv[1])) { - AddInSignal(GetAInt(argv[0])); - AddOutSignal(GetAInt(argv[1])); - - if(argc >= 3 && !ms_plug(argc-2,argv+2)) InitProblem(); - } - else - throw "syntax: vst~ inputs outputs [plug]"; - #if FLEXT_OS == FLEXT_OS_WIN // this is necessary for Waveshell CoInitializeEx(NULL,COINIT_MULTITHREADED+COINIT_SPEED_OVER_MEMORY); #endif + + int ins = 1,outs = 1; + if(argc >= 1 && CanbeInt(argv[0])) { ins = GetAInt(argv[0]); argc--,argv++; } + if(argc >= 1 && CanbeInt(argv[0])) { outs = GetAInt(argv[0]); argc--,argv++; } + + AddInSignal(ins); + AddOutSignal(outs); + + if(argc >= 1 && !ms_plug(argc,argv)) InitProblem(); } vst::~vst() @@ -274,7 +338,7 @@ vst::~vst() #endif } -V vst::ClearPlug() +void vst::ClearPlug() { if(plug) { plug->Edit(false); @@ -283,7 +347,7 @@ V vst::ClearPlug() } } -V vst::InitPlug() +void vst::InitPlug() { FLEXT_ASSERT(plug); @@ -296,7 +360,7 @@ V vst::InitPlug() plug->ScanParams(paramnames); } -V vst::InitPlugDSP() +void vst::InitPlugDSP() { FLEXT_ASSERT(plug); // this might be invalid if DSP is switched off, @@ -304,36 +368,36 @@ V vst::InitPlugDSP() plug->DspInit(Samplerate(),Blocksize()); } -V vst::ClearBuf() +void vst::ClearBuf() { if(!plug) return; if(vstin) { - for(I i = 0; i < plug->GetNumInputs(); ++i) FreeAligned(vstin[i]); + for(int i = 0; i < plug->GetNumInputs(); ++i) FreeAligned(vstin[i]); delete[] vstin; vstin = NULL; delete[] tmpin; tmpin = NULL; } if(vstout) { - for(I i = 0; i < plug->GetNumOutputs(); ++i) FreeAligned(vstout[i]); + for(int i = 0; i < plug->GetNumOutputs(); ++i) FreeAligned(vstout[i]); delete[] vstout; vstout = NULL; delete[] tmpout; tmpout = NULL; } } -V vst::InitBuf() +void vst::InitBuf() { FLEXT_ASSERT(!vstin && !tmpin && !vstout && !tmpout); const int inputs = plug->GetNumInputs(),outputs = plug->GetNumOutputs(); - I i; + int i; - vstin = new R *[inputs]; - tmpin = new R *[inputs]; - for(i = 0; i < inputs; ++i) vstin[i] = (R *)NewAligned(Blocksize()*sizeof(R)); + vstin = new t_sample *[inputs]; + tmpin = new t_sample *[inputs]; + for(i = 0; i < inputs; ++i) vstin[i] = (t_sample *)NewAligned(Blocksize()*sizeof(t_sample)); - vstout = new R *[outputs]; - tmpout = new R *[outputs]; - for(i = 0; i < outputs; ++i) vstout[i] = (R *)NewAligned(Blocksize()*sizeof(R)); + vstout = new t_sample *[outputs]; + tmpout = new t_sample *[outputs]; + for(i = 0; i < outputs; ++i) vstout[i] = (t_sample *)NewAligned(Blocksize()*sizeof(t_sample)); } static std::string findFilePath(const std::string &path,const std::string &dllname) @@ -372,52 +436,21 @@ static std::string findFilePath(const std::string &path,const std::string &dllna } -BL vst::ms_plug(I argc,const A *argv) +bool vst::LoadPlug() { - ClearPlug(); - - plugname.clear(); - C buf[255]; - for(I i = 0; i < argc; i++) { - if(i > 0) plugname += ' '; - GetAString(argv[i],buf,sizeof buf); -#if FLEXT_OS == FLEXT_OS_WIN - strlwr(buf); -#endif - -#if FLEXT_SYS == FLEXT_SYS_PD - // strip char escapes (only in newer/devel PD version) - char *cs = buf,*cd = cs; - while(*cs) { - if(*cs != '\\') *(cd++) = *cs; - ++cs; - } - *cd = 0; -#endif - - plugname += buf; - } - - if(!plugname.length()) return false; + if(plug) ClearPlug(); - plug = new VSTPlugin; - - // now try to load plugin - - // to help deal with spaces we assume ALL of the args make - // up the filename - bool lf = false; - int loaderr = VSTINSTANCE_NO_ERROR; + plug = new VSTPlugin(this); // try loading the dll from the raw filename - if ((loaderr = plug->Instance(plugname.c_str(),subplug.c_str())) == VSTINSTANCE_NO_ERROR) { - FLEXT_LOG("raw filename loaded fine"); - lf = true; - } - - if(!lf) { // try finding it on the PD path - C *name,dir[1024]; - I fd = open_via_path("",plugname.c_str(),".dll",dir,&name,sizeof(dir)-1,0); + bool ok = plug->Instance(plugname.c_str(),subplug.c_str()); + if(ok) + FLEXT_LOG("raw filename loaded fine"); + else { +#if FLEXT_SYS == FLEXT_SYS_PD + // try finding it on the PD path + char *name,dir[1024]; + int fd = open_via_path("",plugname.c_str(),".dll",dir,&name,sizeof(dir)-1,0); if(fd > 0) close(fd); else name = NULL; @@ -430,35 +463,38 @@ BL vst::ms_plug(I argc,const A *argv) dllname += "\\"; dllname += name; - lf = (loaderr = plug->Instance(dllname.c_str())) == VSTINSTANCE_NO_ERROR; + ok = plug->Instance(dllname.c_str()); } +#endif } - if(!lf) { // try finding it on the VST path - C *vst_path = getenv("VST_PATH"); + if(!ok) { + // try finding it on the VST path + char *vst_path = getenv("VST_PATH"); std::string dllname(plugname); if(dllname.find(".dll") == -1) dllname += ".dll"; if(vst_path) { FLEXT_LOG("found VST_PATH env variable"); - char* tok_path = new C[strlen( vst_path)+1]; + char* tok_path = new char[strlen( vst_path)+1]; strcpy( tok_path , vst_path); char *tok = strtok( tok_path , ";" ); while( tok != NULL ) { std::string abpath( tok ); if( abpath[abpath.length()-1] != '\\' ) abpath += "\\"; - FLEXT_LOG1("trying VST_PATH %s",(const C *)abpath.c_str()); + FLEXT_LOG1("trying VST_PATH %s",(const char *)abpath.c_str()); std::string realpath = findFilePath( abpath , dllname ); //post( "findFilePath( %s , %s ) = %s\n" , abpath , dllname , realpath ); if ( realpath.length() ) { realpath += plugname; - FLEXT_LOG1("trying %s",(const C *)realpath.c_str()); - if((loaderr = plug->Instance( realpath.c_str() )) == VSTINSTANCE_NO_ERROR ) { + FLEXT_LOG1("trying %s",(const char *)realpath.c_str()); + + ok = plug->Instance(realpath.c_str()); + if(ok) { FLEXT_LOG("plugin loaded via VST_PATH"); - lf = true; break; } } @@ -471,39 +507,65 @@ BL vst::ms_plug(I argc,const A *argv) } } - if(!lf) { // failed - don't make any ins or outs - post("%s - unable to load plugin '%s', load error %i",thisName(),plugname.c_str(),loaderr); + if(!ok) { + post("%s - unable to load plugin '%s'",thisName(),plugname.c_str()); ClearPlug(); - } + } + else + InitPlug(); + + return ok; +} + +static char *stripesc(char *buf) +{ +#if FLEXT_SYS == FLEXT_SYS_PD + // strip char escapes (only in newer/devel PD version) + char *cs = buf,*cd = cs; + while(*cs) { + if(*cs != '\\') *(cd++) = *cs; + ++cs; + } + *cd = 0; +#endif + return buf; +} - // re-init dsp stuff - if(plug) InitPlug(); +bool vst::ms_plug(int argc,const t_atom *argv) +{ + ClearPlug(); - return lf; + plugname.clear(); + char buf[255]; + for(int i = 0; i < argc; i++) { + if(i > 0) plugname += ' '; + GetAString(argv[i],buf,sizeof buf); +#if FLEXT_OS == FLEXT_OS_WIN + strlwr(buf); +#endif + plugname += stripesc(buf); + } + + if(!plugname.length()) + return false; + else + return LoadPlug(); } -void vst::ms_subplug(I argc,const A *argv) +void vst::ms_subplug(int argc,const t_atom *argv) { subplug.clear(); - C buf[255]; - for(I i = 0; i < argc; i++) { + char buf[255]; + for(int i = 0; i < argc; i++) { if(i > 0) subplug += ' '; GetAString(argv[i],buf,sizeof buf); - -#if FLEXT_SYS == FLEXT_SYS_PD - // strip char escapes (only in newer/devel PD version) - char *cs = buf,*cd = cs; - while(*cs) { - if(*cs != '\\') *(cd++) = *cs; - ++cs; - } - *cd = 0; -#endif - subplug += buf; + subplug += stripesc(buf); } + + LoadPlug(); } -V vst::m_dsp(I n,t_signalvec const *,t_signalvec const *) +void vst::m_dsp(int n,t_signalvec const *,t_signalvec const *) { if(plug) { FLEXT_ASSERT(vstfun); @@ -518,7 +580,7 @@ V vst::m_dsp(I n,t_signalvec const *,t_signalvec const *) } } -V vst::m_signal(I n,R *const *insigs,R *const *outsigs) +void vst::m_signal(int n,t_sample *const *insigs,t_sample *const *outsigs) { if(mute) flext_dsp::m_signal(n,insigs,outsigs); @@ -532,10 +594,10 @@ V vst::m_signal(I n,R *const *insigs,R *const *outsigs) i = 1; } else if(mx == 2) { - R *o1 = outsigs[0],*o2 = outsigs[1]; - const R *i1 = insigs[0],*i2 = insigs[1]; + t_sample *o1 = outsigs[0],*o2 = outsigs[1]; + const t_sample *i1 = insigs[0],*i2 = insigs[1]; for(int s = 0; s < n; ++s) { - const R f = *(i1++); + const t_sample f = *(i1++); *(o2++) = *(i2++); *(o1++) = f; } @@ -555,16 +617,16 @@ V vst::m_signal(I n,R *const *insigs,R *const *outsigs) const int inputs = plug->GetNumInputs(),outputs = plug->GetNumOutputs(); if(sigmatch) - (plug->*vstfun)(const_cast(insigs),const_cast(outsigs),n); + (plug->*vstfun)(const_cast(insigs),const_cast(outsigs),n); else { const int cntin = CntInSig(),cntout = CntOutSig(); - R **inv,**outv; + t_sample **inv,**outv; if(inputs <= cntin) - inv = const_cast(insigs); + inv = const_cast(insigs); else { // more plug inputs than inlets - I i; - for(i = 0; i < cntin; ++i) tmpin[i] = const_cast(insigs[i]); + int i; + for(i = 0; i < cntin; ++i) tmpin[i] = const_cast(insigs[i]); // set dangling inputs to zero // according to mode... (e.g. set zero) @@ -573,11 +635,11 @@ V vst::m_signal(I n,R *const *insigs,R *const *outsigs) inv = tmpin; } - const BL more = outputs <= cntout; + const bool more = outputs <= cntout; if(more) // more outlets than plug outputs - outv = const_cast(outsigs); + outv = const_cast(outsigs); else { - I i; + int i; for(i = 0; i < cntout; ++i) tmpout[i] = outsigs[i]; for(; i < outputs; ++i) tmpout[i] = vstout[i]; @@ -603,11 +665,11 @@ V vst::m_signal(I n,R *const *insigs,R *const *outsigs) #if 0 -V vst::m_control(const S *ctrl_name,I ctrl_value) +void vst::m_control(const t_symbol *ctrl_name,int ctrl_value) { if(!plug) return; - I parm_num = 0; + int parm_num = 0; if (!*GetString(ctrl_name) || !strlen(GetString(ctrl_name))) { error ("plugin~: control messages must have a name and a value"); @@ -626,26 +688,6 @@ V vst::m_control(const S *ctrl_name,I ctrl_value) #endif -V vst::m_pitchbend(I ctrl_value) -{ - if(plug) plug->AddPitchBend(ctrl_value ); -} - -V vst::m_aftertouch(I ctrl_value) -{ - if(plug) plug->AddAftertouch(ctrl_value ); -} - -V vst::m_programchange(I ctrl_value) -{ - if(plug) plug->AddProgramChange(ctrl_value ); -} - -V vst::ms_program(I p) -{ - if(plug && p >= 0) plug->SetCurrentProgram(p); -} - void vst::mg_progname(int argc,const t_atom *argv) const { if(plug) { @@ -662,7 +704,7 @@ void vst::mg_progname(int argc,const t_atom *argv) const char str[256]; plug->GetProgramName(cat,pnum,str); - A at[3]; + t_atom at[3]; SetInt(at[0],cat); SetInt(at[1],pnum); SetString(at[2],str); @@ -673,12 +715,7 @@ void vst::mg_progname(int argc,const t_atom *argv) const } } -V vst::m_ctrlchange(I control,I ctrl_value) -{ - if(plug) plug->AddControlChange(control,ctrl_value ); -} - -V vst::ms_wintitle(const AtomList &t) +void vst::ms_wintitle(const AtomList &t) { if(plug) { char txt[256]; @@ -692,7 +729,7 @@ V vst::ms_wintitle(const AtomList &t) * may be of use */ -V vst::m_print(I ac,const A *av) +void vst::m_print(int ac,const t_atom *av) { if(!plug) return; @@ -705,7 +742,7 @@ V vst::m_print(I ac,const A *av) if( ac > 0 ) { for( i = 0 ; i < ac ; i++) { if(IsString(av[i])) { - const C *buf = GetString(av[i]); + const char *buf = GetString(av[i]); if ( strcmp( buf , "-params" ) == 0 ) { params = true; } @@ -773,7 +810,7 @@ V vst::m_print(I ac,const A *av) } -V vst::display_parameter(I param,BL showparams) +void vst::display_parameter(int param,bool showparams) { int j = param; /* the Steinberg(tm) way... */ @@ -801,25 +838,25 @@ V vst::display_parameter(I param,BL showparams) } } -V vst::m_pname(I pnum) +void vst::m_pname(int pnum) { if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; char name[256]; // how many chars needed? plug->GetParamName(pnum,name); - A at[2]; + t_atom at[2]; SetInt(at[0],pnum); SetString(at[1],name); ToOutAnything(GetOutAttr(),sym_pname,2,at); } // set the value of a parameter -V vst::ms_param(I pnum,F val) +void vst::ms_param(int pnum,float val) { if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; - F xval = plug->GetParamValue( pnum ); + float xval = plug->GetParamValue( pnum ); // if(xval <= 1.0f) // What's that???? if(true) { @@ -849,17 +886,17 @@ void vst::ms_params(int argc,const t_atom *argv) } } -V vst::mg_param(I pnum) +void vst::mg_param(int pnum) { if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; - A at[2]; + t_atom at[2]; SetInt(at[0],pnum); SetFloat(at[1],plug->GetParamValue(pnum)); ToOutAnything(GetOutAttr(),sym_param,2,at); } -V vst::mg_params(int argc,const t_atom *argv) +void vst::mg_params(int argc,const t_atom *argv) { if(plug) { char str[255]; @@ -877,7 +914,7 @@ V vst::mg_params(int argc,const t_atom *argv) } } -V vst::m_ptext(I pnum) +void vst::m_ptext(int pnum) { if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; @@ -885,13 +922,13 @@ V vst::m_ptext(I pnum) memset(display,0,sizeof(display)); plug->GetParamValue(pnum,display); - A at[2]; + t_atom at[2]; SetInt(at[0],pnum); SetString(at[1],display); ToOutAnything(GetOutAttr(),sym_ptext,2,at); } -V vst::m_ptexts(int argc,const t_atom *argv) +void vst::m_ptexts(int argc,const t_atom *argv) { if(plug) { char str[255]; @@ -909,7 +946,7 @@ V vst::m_ptexts(int argc,const t_atom *argv) } } -V vst::m_note(I note,I velocity) +void vst::m_note(int note,int velocity) { if(!plug) return; @@ -918,3 +955,9 @@ V vst::m_note(I note,I velocity) else plug->AddNoteOff(note); } + +void vst::Respond(const t_symbol *sym,int argc,const t_atom *argv) +{ + FLEXT_ASSERT(sym); + ToOutAnything(GetOutAttr(),sym,argc,argv); +} diff --git a/externals/grill/vst/src/main.h b/externals/grill/vst/src/main.h index fab6b622..ffd138ec 100644 --- a/externals/grill/vst/src/main.h +++ b/externals/grill/vst/src/main.h @@ -24,17 +24,5 @@ WARRANTIES, see the file, "license.txt," in this distribution. #error Platform not supported! #endif -typedef void V; -typedef int I; -typedef long L; -typedef unsigned long UL; -typedef float F; -typedef t_sample R; -typedef char C; -typedef bool BL; -typedef t_atom A; -typedef t_symbol S; - - #endif diff --git a/externals/grill/vst/src/vst.rc b/externals/grill/vst/src/vst.rc index bc1a1b94..8f8e368b 100644 --- a/externals/grill/vst/src/vst.rc +++ b/externals/grill/vst/src/vst.rc @@ -46,7 +46,7 @@ BEGIN VALUE "FileDescription", "vst~ external" VALUE "FileVersion", "0,1, 0, 8" VALUE "InternalName", "vst~" - VALUE "LegalCopyright", "Copyright (C) 2003-2004 Thomas Grill" + VALUE "LegalCopyright", "Copyright (C) 2003-2005 Thomas Grill" VALUE "OriginalFilename", "vst~.DLL" VALUE "ProductName", "VST plugin object" VALUE "ProductVersion", "0, 1, 0, 8" diff --git a/externals/grill/vst/src/vstedit.cpp b/externals/grill/vst/src/vstedit.cpp new file mode 100644 index 00000000..804e83ca --- /dev/null +++ b/externals/grill/vst/src/vstedit.cpp @@ -0,0 +1,76 @@ +/* +vst~ - VST plugin object for PD +based on the work of Jarno Seppänen and Mark Williamson + +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 "vsthost.h" +#include "editor.h" + + +void VSTPlugin::Edit(bool open) +{ + if(Is()) { + if(open) { + if(HasEditor() && !IsEdited()) + StartEditor(this); + } + else if(IsEdited()) + StopEditor(this); + } +} + +void VSTPlugin::StartEditing(WHandle h) +{ + FLEXT_ASSERT(h != NULL); + Dispatch(effEditOpen,0,0,hwnd = h); +// Dispatch(effEditTop); + + TitleEditor(this,title.c_str()); +} + +void VSTPlugin::StopEditing() +{ + if(Is()) { + Dispatch(effEditClose); + hwnd = NULL; + } +} + +void VSTPlugin::Visible(bool vis) +{ + if(Is() && IsEdited()) ShowEditor(this,vis); +} + +bool VSTPlugin::IsVisible() const +{ + return Is() && IsEdited() && IsEditorShown(this); +} + + +void VSTPlugin::SetPos(int x,int y,bool upd) +{ + if(Is()) { + posx = x; posy = y; + if(upd && IsEdited()) MoveEditor(this,posx,posy); + } +} + +void VSTPlugin::SetCaption(bool c) +{ + if(Is()) { + caption = c; + if(IsEdited()) CaptionEditor(this,c); + } +} + +void VSTPlugin::SetTitle(const char *t) +{ + if(Is()) { + title = t; + if(IsEdited()) TitleEditor(this,t); + } +} 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 -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(ptr); - if(ev->type == kVstMidiType) { - VstMidiEvent *mev = static_cast(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(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 diff --git a/externals/grill/vst/src/vsthost.h b/externals/grill/vst/src/vsthost.h index 185a7113..8dc20394 100644 --- a/externals/grill/vst/src/vsthost.h +++ b/externals/grill/vst/src/vsthost.h @@ -2,7 +2,7 @@ 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. */ @@ -11,9 +11,13 @@ WARRANTIES, see the file, "license.txt," in this distribution. #define __VSTHOST_H #include +#include +#include +#include + #include "AEffectx.h" #include "AEffEditor.hpp" -#include + #if FLEXT_OS == FLEXT_OS_WIN #include @@ -28,51 +32,57 @@ typedef void *MHandle; #endif -#define MAX_EVENTS 64 -#define MAX_INOUTS 8 - -#define VSTINSTANCE_ERR_NO_VALID_FILE -1 -#define VSTINSTANCE_ERR_NO_VST_PLUGIN -2 -#define VSTINSTANCE_ERR_REJECTED -3 -#define VSTINSTANCE_NO_ERROR 0 - -#define MIDI_NOTEON 144 -#define MIDI_NOTEOFF 128 -#define MIDI_POLYAFTERTOUCH 160 -#define MIDI_CONTROLCHANGE 176 -#define MIDI_PROGRAMCHANGE 192 -#define MIDI_AFTERTOUCH 208 -#define MIDI_PITCHBEND 224 +#define MIDI_MAX_EVENTS 64 +class Responder +{ +public: + virtual void Respond(const t_symbol *sym,int argc = 0,const t_atom *argv = NULL) = 0; +}; class VSTPlugin: public flext { public: - VSTPlugin(); + static void Setup(); + + VSTPlugin(Responder *resp); ~VSTPlugin(); - int Instance(const char *dllname,const char *subplug = NULL); + bool Instance(const char *plug,const char *subplug = NULL); void Free(); void DspInit(float samplerate,int blocksize); - bool Is() const { return _pEffect != NULL; } + ////////////////////////////////////////////////////////////////////////////// + +public: + bool Is() const { return effect != NULL; } - long GetVersion() const { return _pEffect?_pEffect->version:0; } + long GetVersion() const { return effect?effect->version:0; } bool IsSynth() const { return HasFlags(effFlagsIsSynth); } bool IsReplacing() const { return HasFlags(effFlagsCanReplacing); } bool HasEditor() const { return HasFlags(effFlagsHasEditor); } - const char *GetName() const { return _sProductName; } - const char *GetVendorName() const { return _sVendorName; } - const char *GetDllName() const { return _sDllName.c_str(); } + const char *GetName() const { return productname; } + const char *GetVendorName() const { return vendorname; } + const char *GetDllName() const { return dllname.c_str(); } - int GetNumInputs() const { return _pEffect?_pEffect->numInputs:0; } - int GetNumOutputs() const { return _pEffect?_pEffect->numOutputs:0; } + int GetNumInputs() const { return effect?effect->numInputs:0; } + int GetNumOutputs() const { return effect?effect->numOutputs:0; } - int GetNumParams() const { return _pEffect?_pEffect->numParams:0; } + void ListPlugs(const t_symbol *sym) const; + +private: + char productname[300]; + char vendorname[300]; + std::string dllname; // Contains dll name + + ////////////////////////////////////////////////////////////////////////////// + +public: + int GetNumParams() const { return effect?effect->numParams:0; } void GetParamName(int numparam,char *name) const; void GetParamValue(int numparam,char *parval) const; float GetParamValue(int numparam) const; @@ -89,21 +99,35 @@ public: void SetCurrentProgram(int prg) { Dispatch(effSetProgram,0,prg); } int GetCurrentProgram() const { return Dispatch(effGetProgram); } - int GetNumPrograms() const { return _pEffect->numPrograms; } + int GetNumPrograms() const { return effect->numPrograms; } int GetNumCategories() const { return Dispatch(effGetNumProgramCategories); } - bool GetProgramName( int cat, int p , char* buf) const; + bool GetProgramName(int cat,int p,char* buf) const; + +private: + struct NameCmp: + std::less + { + bool operator()(const std::string &a,const std::string &b) const { return a.compare(b) < 0; } + }; + + typedef std::map NameMap; + int paramnamecnt; + NameMap paramnames; + ////////////////////////////////////////////////////////////////////////////// - bool AddMIDI(unsigned char data0,unsigned char data1=0,unsigned char data2=0); +public: + void SetPos(int x,int y,bool upd = true); + void SetX(int x,bool upd = true) { SetPos(x,posy,upd); } + void SetY(int y,bool upd = true) { SetPos(posx,y,upd); } + int GetX() const { return posx; } + int GetY() const { return posy; } + void SetCaption(bool b); + bool GetCaption() const { return caption; } + void SetTitle(const char *t); + const char *GetTitle() const { return title.c_str(); } - bool AddNoteOn( unsigned char note,unsigned char speed,unsigned char midichannel=0); - bool AddNoteOff( unsigned char note,unsigned char midichannel=0); - - void AddControlChange( int control , int value ); - void AddProgramChange( int value ); - void AddPitchBend( int value ); - void AddAftertouch( int value ); void Edit(bool open); @@ -120,64 +144,173 @@ public: void Paint(ERect &r) const { Dispatch(effEditDraw,0,0,&r); } - void processReplacing( float **inputs, float **outputs, long sampleframes ); - void process( float **inputs, float **outputs, long sampleframes ); +private: + int posx,posy; // Window position + bool caption; // Window border + std::string title; // Window title - long Dispatch(long opCode, long index = 0, long value = 0, void *ptr = NULL, float opt = 0) const - { - return Is()?_pEffect->dispatcher(_pEffect, opCode, index, value, ptr, opt):0; - } + ////////////////////////////////////////////////////////////////////////////// - static long VSTCALLBACK Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt); +public: + enum { + MIDI_NOTEON = 144, + MIDI_NOTEOFF = 128, + MIDI_POLYAFTERTOUCH = 160, + MIDI_CONTROLCHANGE = 176, + MIDI_PROGRAMCHANGE = 192, + MIDI_AFTERTOUCH = 208, + MIDI_PITCHBEND = 224 + }; + + bool AddMIDI(unsigned char data0,unsigned char data1 = 0,unsigned char data2 = 0); - void SetPos(int x,int y,bool upd = true); - void SetX(int x,bool upd = true) { SetPos(x,posy,upd); } - void SetY(int y,bool upd = true) { SetPos(posx,y,upd); } - int GetX() const { return posx; } - int GetY() const { return posy; } - void SetCaption(bool b); - bool GetCaption() const { return caption; } - void SetTitle(const char *t); - const char *GetTitle() const { return title.c_str(); } + static int range(int value,int mn = 0,int mx = 127) { return value < mn?mn:(value > mx?mx:value); } -protected: + bool AddNoteOn(unsigned char note,unsigned char speed,unsigned char midichannel = 0) + { + return AddMIDI((char)MIDI_NOTEON|midichannel,note,speed); + } - MHandle h_dll; - WHandle hwnd; + bool AddNoteOff(unsigned char note,unsigned char midichannel = 0) + { + return AddMIDI((char)MIDI_NOTEOFF|midichannel,note,0); + } + + void AddControlChange(int control,int value) + { + AddMIDI(MIDI_CONTROLCHANGE+(midichannel&0xf),range(control),range(value)); + } + + void AddProgramChange(int value) + { + AddMIDI(MIDI_PROGRAMCHANGE+(midichannel&0xf),range(value),0); + } - AEffect *_pEffect; + void AddPitchBend(int value) + { + AddMIDI(MIDI_PITCHBEND+(midichannel&0xf),((value>>7)&127),(value&127)); + } - static void FreeVST(MHandle handle); + void AddAftertouch(int value) + { + AddMIDI((char)MIDI_AFTERTOUCH|midichannel,range(value)); + } - inline long GetFlags() const { return _pEffect?_pEffect->flags:0; } - inline bool HasFlags(long msk) const { return _pEffect && (_pEffect->flags&msk); } +private: + void SendMidi(); - char _sProductName[300]; - char _sVendorName[300]; - std::string _sDllName; // Contains dll name + // static VstTimeInfo _timeInfo; + VstMidiEvent midievent[MIDI_MAX_EVENTS]; + VstEvents events; + int eventqusz; - struct NameCmp: - std::less + char midichannel; + + ////////////////////////////////////////////////////////////////////////////// + +public: + + void SetPlaying(bool p) { if(playing != p) transchg = true,playing = p; } + bool GetPlaying() const { return playing; } + void SetLooping(bool p) { if(looping != p) transchg = true,looping = p; } + bool GetLooping() const { return looping; } + + void SetSamplePos(double p) { if(samplepos != p) transchg = true,samplepos = p; } + double GetSamplePos() const { return samplepos; } + void SetTempo(double p) { if(tempo != p) transchg = true,tempo = p; } + double GetTempo() const { return tempo; } + void SetPPQPos(double p) { if(ppqpos != p) transchg = true,ppqpos = p; } + double GetPPQPos() const { return ppqpos; } + + void SetTimesigNom(int p) { if(timesignom != p) transchg = true,timesignom = p; } + int GetTimesigNom() const { return timesignom; } + void SetTimesigDen(int p) { if(timesigden != p) transchg = true,timesigden = p; } + int GetTimesigDen() const { return timesigden; } + void SetBarStart(double p) { if(barstartpos != p) transchg = true,barstartpos = p; } + double GetBarStart() const { return barstartpos; } + void SetCycleStart(double p) { if(cyclestartpos != p) transchg = true,cyclestartpos = p; } + double GetCycleStart() const { return cyclestartpos; } + void SetCycleEnd(double p) { if(cycleendpos != p) transchg = true,cycleendpos = p; } + double GetCycleEnd() const { return cycleendpos; } + + void SetSmpteOffset(int p) { if(smpteoffset != p) transchg = true,smpteoffset = p; } + int GetSmpteOffset() const { return smpteoffset; } + void SetSmpteRate(int p) { if(smpterate != p) transchg = true,smpterate = p; } + int GetSmpteRate() const { return smpterate; } + +private: + + bool playing,looping; + float samplerate; + bool transchg; + + double samplepos,tempo; + double ppqpos; + + int timesignom,timesigden; + double barstartpos; + double cyclestartpos,cycleendpos; + int smpteoffset,smpterate; + + ////////////////////////////////////////////////////////////////////////////// + +public: + void processReplacing(float **inputs,float **outputs,long sampleframes ) { - bool operator()(const std::string &a,const std::string &b) const { return a.compare(b) < 0; } - }; + FLEXT_ASSERT(effect); + effect->processReplacing(effect,inputs,outputs,sampleframes); + if(playing) updatepos(sampleframes); + } - typedef std::map NameMap; - int paramnamecnt; - NameMap paramnames; - + void process(float **inputs,float **outputs,long sampleframes ) + { + FLEXT_ASSERT(effect); + effect->process(effect,inputs,outputs,sampleframes); + if(playing) updatepos(sampleframes); + } -// static VstTimeInfo _timeInfo; - VstMidiEvent midievent[MAX_EVENTS]; - VstEvents events; - int queue_size; +private: + void updatepos(long frames); - void SendMidi(); - char _midichannel; + ////////////////////////////////////////////////////////////////////////////// - int posx,posy; // Window position - bool caption; // Window border - std::string title; // Window title +private: + Responder *responder; + + bool NewPlugin(const char *plugname); + void FreePlugin(); + bool InstPlugin(long plugid = 0); + + static long uniqueid; + static std::string dllloading; + + inline long GetFlags() const { return effect?effect->flags:0; } + inline bool HasFlags(long msk) const { return effect && (effect->flags&msk); } + + + // the handle to the shared library + MHandle hdll; + // the handle to the plugin editor window + WHandle hwnd; + // the VST plugin instance + AEffect *effect; + + typedef AEffect *(VSTCALLBACK *PVSTMAIN)(audioMasterCallback audioMaster); + PVSTMAIN pluginmain; + audioMasterCallback audiomaster; + + long Dispatch(long opCode,long index = 0,long value = 0,void *ptr = NULL,float opt = 0) const + { + FLEXT_ASSERT(effect); + return effect->dispatcher(effect,opCode,index,value,ptr,opt); + } + + static long VSTCALLBACK Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt); + + static const t_symbol *sym_event,*sym_evmidi,*sym_evaudio,*sym_evvideo,*sym_evparam,*sym_evtrigger,*sym_evsysex,*sym_ev_; + static const t_symbol *sym_midi[8]; + + void ProcessEvent(const VstEvent &ev); }; #endif diff --git a/externals/grill/vst/src/vstmaster.cpp b/externals/grill/vst/src/vstmaster.cpp new file mode 100644 index 00000000..0395fb65 --- /dev/null +++ b/externals/grill/vst/src/vstmaster.cpp @@ -0,0 +1,288 @@ +/* +vst~ - VST plugin object for PD +based on the work of Jarno Seppänen and Mark Williamson + +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 "vsthost.h" + +static const int VST_VERSION = 100; +static const char *vendor = "grrrr.org"; +static const char *product = "vst~"; + + +void VSTPlugin::ProcessEvent(const VstEvent &ev) +{ + if(!responder) return; + + if(ev.type == kVstMidiType) { + const VstMidiEvent &mev = (const VstMidiEvent &)ev; + t_atom lst[10]; + SetSymbol(lst[0],sym_evmidi); + int midi = ((unsigned char)mev.midiData[0]>>4)-8; + FLEXT_ASSERT(midi >= 0 && midi < 8); + SetSymbol(lst[1],sym_midi[midi]); + SetInt(lst[2],(unsigned char)mev.midiData[0]&0x0f); + SetInt(lst[3],(unsigned char)mev.midiData[1]); + SetInt(lst[4],(unsigned char)mev.midiData[2]); + // what about running status? (obviously not possible) + SetInt(lst[5],mev.deltaFrames); + SetInt(lst[6],mev.noteLength); + SetInt(lst[7],mev.noteOffset); + SetInt(lst[8],(int)mev.detune); + SetInt(lst[9],(int)mev.noteOffVelocity); + responder->Respond(sym_event,9,lst); + } + else { + const t_symbol *sym; + if(ev.type == kVstAudioType) + sym = sym_evaudio; + else if(ev.type == kVstVideoType) + sym = sym_evvideo; + else if(ev.type == kVstParameterType) + sym = sym_evparam; + else if(ev.type == kVstTriggerType) + sym = sym_evtrigger; + else if(ev.type == kVstSysExType) + sym = sym_evsysex; + else + sym = sym_ev_; + + int data = ev.byteSize-sizeof(ev.deltaFrames)-sizeof(ev.flags); + const int stsize = 16; + t_atom stlst[stsize]; + t_atom *lst = data+3 > stsize?new t_atom[data+3]:stlst; + + SetSymbol(lst[0],sym); + SetInt(lst[1],ev.deltaFrames); + SetInt(lst[2],ev.flags); + for(int i = 0; i < data; ++i) SetInt(lst[3],(unsigned char)ev.data[i]); + + responder->Respond(sym_event,data+3,lst); + + if(lst != stlst) delete[] lst; + } +} + +// Host callback dispatcher +long VSTPlugin::Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt) +{ +#ifdef FLEXT_LOGGING + 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; + + switch (opcode) { + case audioMasterAutomate: // 0 +#ifdef FLEXT_LOGGING + 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; + + case audioMasterCurrentId: // 2 + // set to subplugin id (default 0) + return uniqueid; + + 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_LOGGING + post("Pin connected pin=%li conn=%li",index,value); +#endif + return 0; // 0 means connected + + case audioMasterWantMidi: // 6 +#ifdef FLEXT_LOGGING + post("Want MIDI = %li",value); +#endif + return 0; // VST header says: "currently ignored" + + case audioMasterGetTime: { // 7 + if(!th) return 0; + + static VstTimeInfo time; + memset(&time,0,sizeof(time)); + + // flags + time.flags = kVstTempoValid|kVstBarsValid|kVstCyclePosValid|kVstPpqPosValid|kVstSmpteValid|kVstTimeSigValid; + + if(th->transchg) { time.flags |= kVstTransportChanged; th->transchg = false; } + if(th->playing) time.flags |= kVstTransportPlaying; + if(th->looping) time.flags |= kVstTransportCycleActive; + + time.sampleRate = th->samplerate; + time.samplePos = th->samplepos; + time.ppqPos = th->ppqpos; + + time.tempo = th->tempo; + time.barStartPos = th->barstartpos; + time.cycleStartPos = th->cyclestartpos; + time.cycleEndPos = th->cycleendpos; + + time.timeSigNumerator = th->timesignom; + time.timeSigDenominator = th->timesigden; + + // SMPTE data + time.smpteOffset = th->smpteoffset; + time.smpteFrameRate = th->smpterate; + +// time.samplesToNextClock = 0; + + if(value&kVstNanosValid) { + time.nanoSeconds = flext::GetOSTime()*1.e9; + time.flags |= kVstNanosValid; + } + + return (long)&time; + } + + case audioMasterProcessEvents: { // 8 + // VST event data from plugin + VstEvents *evs = static_cast(ptr); + if(th) { + for(int i = 0; i < evs->numEvents; ++i) + th->ProcessEvent(*evs->events[i]); + return 1; + } + else + return 0; + } + + case audioMasterSetTime: { // 9 + VstTimeInfo *tminfo = static_cast(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 + return 0; // not supported + case audioMasterGetBlockSize: // 17 + return 0; // not supported + + case audioMasterGetCurrentProcessLevel: // 23 + // return thread state + return flext::GetThreadId() == flext::GetSysThreadId()?2:1; + + case audioMasterGetVendorString: // 32 + strcpy((char*)ptr,vendor); + return 0; + + case audioMasterGetProductString: // 33 + strcpy((char *)ptr,product); + return 0; + + case audioMasterGetVendorVersion: // 34 + return VST_VERSION; + + case audioMasterCanDo: // 37 +#ifdef FLEXT_LOGGING + 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! + else if(!strcmp((char *)ptr,"editFile")) + return 0; // not supported + else if(!strcmp((char *)ptr,"openFileSelector")) + return 0; // not supported + else if(!strcmp((char *)ptr,"closeFileSelector")) + return 0; // not supported + else if(!strcmp((char *)ptr,"startStopProcess")) + return 0; // not supported +#ifdef FLEXT_DEBUG + else + post("Unknown audioMasterCanDo PTR = %s",ptr); +#endif + + return 0; // not supported + + case audioMasterGetLanguage: // 38 + return kVstLangEnglish; + + case audioMasterGetDirectory: // 41 + return (long)(th?th->dllname.c_str():dllloading.c_str()); + + case audioMasterUpdateDisplay: // 42 +#ifdef FLEXT_LOGGING + post("UPDATE DISPLAY"); +#endif + return 0; + + default: +#ifdef FLEXT_DEBUG + post("Unknown opcode %li",opcode); +#endif + return 0; + } +} + +void VSTPlugin::updatepos(long frames) +{ + bool inloop = ppqpos < cycleendpos; + + // \todo should the sample position also jump back when cycling? + // and if, how? + samplepos += frames; + + ppqpos += frames*tempo/(samplerate*60); + + if(looping) { + double cyclelen = cycleendpos-cyclestartpos; + if(cyclelen > 0) { + if(inloop && ppqpos >= cycleendpos) + ppqpos = cyclestartpos+fmod(ppqpos-cyclestartpos,cyclelen); + } + else + ppqpos = cyclestartpos; + } +} diff --git a/externals/grill/vst/src/vstmidi.cpp b/externals/grill/vst/src/vstmidi.cpp new file mode 100644 index 00000000..8bddba98 --- /dev/null +++ b/externals/grill/vst/src/vstmidi.cpp @@ -0,0 +1,52 @@ +/* +vst~ - VST plugin object for PD +based on the work of Jarno Seppänen and Mark Williamson + +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 "vsthost.h" + +bool VSTPlugin::AddMIDI(unsigned char data0,unsigned char data1,unsigned char data2) +{ + if(Is()) { + VstMidiEvent *pevent = &midievent[eventqusz]; + + 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(eventqusz < MIDI_MAX_EVENTS) ++eventqusz; + SendMidi(); + return true; + } + else return false; +} + + +void VSTPlugin::SendMidi() +{ + if(Is() && eventqusz > 0) { + // Prepare MIDI events and free queue dispatching all events + events.numEvents = eventqusz; + events.reserved = 0; + for(int q = 0; q < eventqusz; q++) + events.events[q] = (VstEvent*)&midievent[q]; + + Dispatch(effProcessEvents, 0, 0, &events, 0.0f); + eventqusz = 0; + } +} diff --git a/externals/grill/vst/src/vstparam.cpp b/externals/grill/vst/src/vstparam.cpp new file mode 100644 index 00000000..30515b23 --- /dev/null +++ b/externals/grill/vst/src/vstparam.cpp @@ -0,0 +1,105 @@ +/* +vst~ - VST plugin object for PD +based on the work of Jarno Seppänen and Mark Williamson + +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 "vsthost.h" +#include + +static void striptrail(char *txt) +{ + // 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; +} + +void VSTPlugin::GetParamName(int numparam,char *name) const +{ + if(numparam < GetNumParams()) { + name[0] = 0; + Dispatch(effGetParamName,numparam,0,name); + striptrail(name); + } + else + name[0] = 0; +} + +bool VSTPlugin::SetParamFloat(int parameter,float value) +{ + if(Is() && parameter >= 0 && parameter < GetNumParams()) { + effect->setParameter(effect,parameter,value); + return true; + } + else + 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); +// 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); + 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 effect->getParameter(effect,numparam); + else + return -1.0; +} + +void VSTPlugin::ScanParams(int cnt) +{ + 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; + } + 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; +} + +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); + striptrail(buf); + return true; + } + else + return false; +} -- cgit v1.2.1