From 4fe8863a1176f7fe4057d82b2844dd7127b13bca Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 16 Mar 2005 04:59:36 +0000 Subject: much cleaner Window GUI code fixed bug with param method updated build system minimal feedback attribute for parameter reporting clean handling of plugin deletion (potentially open editor window etc.) updated for new flext function naming names containing spaces are now correctly dumped added event processing (like Midi in) more consistent MIDI functionality trying to catch crashing plugins svn path=/trunk/; revision=2630 --- externals/grill/vst/src/editor.h | 5 +- externals/grill/vst/src/editorwin.hpp | 197 ++++++++++++++++++++++------------ externals/grill/vst/src/main.cpp | 126 +++++++++++----------- externals/grill/vst/src/vstedit.cpp | 52 +++++---- externals/grill/vst/src/vsthost.cpp | 159 +++++++++++++++++++++------ externals/grill/vst/src/vsthost.h | 74 +++++++++---- externals/grill/vst/src/vstmaster.cpp | 2 +- externals/grill/vst/src/vstparam.cpp | 1 + 8 files changed, 404 insertions(+), 212 deletions(-) (limited to 'externals/grill/vst/src') diff --git a/externals/grill/vst/src/editor.h b/externals/grill/vst/src/editor.h index ad03f59c..7c5831e7 100644 --- a/externals/grill/vst/src/editor.h +++ b/externals/grill/vst/src/editor.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. */ @@ -20,6 +20,7 @@ void MoveEditor(VSTPlugin *p,int x,int y); void SizeEditor(VSTPlugin *p,int x,int y); void TitleEditor(VSTPlugin *p,const char *t); void CaptionEditor(VSTPlugin *p,bool c); -bool IsEditorShown(const VSTPlugin *p); +void HandleEditor(VSTPlugin *p,bool h); +void FrontEditor(VSTPlugin *p); #endif // __EDITOR_H diff --git a/externals/grill/vst/src/editorwin.hpp b/externals/grill/vst/src/editorwin.hpp index 29e63db6..9d97771b 100644 --- a/externals/grill/vst/src/editorwin.hpp +++ b/externals/grill/vst/src/editorwin.hpp @@ -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. */ @@ -37,12 +37,13 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) // Initialize the window. plug->StartEditing(hwnd); break; + case WM_CLOSE: #ifdef FLEXT_LOGGING flext::post("WM_CLOSE"); #endif - // plug could already have been unloaded... - plug->StopEditing(); // this sets plug->hwnd = NULL + plug->StopEditing(); + DestroyWindow(hwnd); break; case WM_DESTROY: @@ -57,7 +58,26 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) case WM_ENTERIDLE: plug->EditorIdle(); break; +#if 0 + case WM_WINDOWPOSCHANGED: { + // ignore after WM_CLOSE so that x,y positions are preserved + if(!plug->IsEdited()) break; + WINDOWPOS *w = (WINDOWPOS *)lp; + + WINDOWINFO winfo; + winfo.cbSize = sizeof(winfo); + GetWindowInfo(hwnd,&winfo); + int cpx = winfo.rcWindow.left-winfo.rcClient.left; + int cpy = winfo.rcWindow.top-winfo.rcClient.top; + int csx = winfo.rcWindow.right-winfo.rcClient.right-cpx; + int csy = winfo.rcWindow.bottom-winfo.rcClient.bottom-cpy; + // send normalized coordinates to plugin + plug->SetPos(w->x+cpx,w->y+cpy,false); + plug->SetSize(w->cx+csx,w->cy+csy,false); + return 0; + } +#else case WM_MOVE: { // ignore after WM_CLOSE so that x,y positions are preserved if(!plug->IsEdited()) break; @@ -65,12 +85,36 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) WORD wx = LOWORD(lp),wy = HIWORD(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_LOGGING - flext::post("WM_MOVE x/y=%i/%i",x,y); -#endif + + WINDOWINFO winfo; + winfo.cbSize = sizeof(winfo); + GetWindowInfo(hwnd,&winfo); + int px = winfo.rcWindow.left-winfo.rcClient.left; + int py = winfo.rcWindow.top-winfo.rcClient.top; + // send normalized coordinates to plugin + plug->SetPos(x+px,y+py,false); + break; + } + + case WM_SIZE: { + if(!plug->IsEdited()) break; + + WORD wx = LOWORD(lp),wy = HIWORD(lp); + short x = reinterpret_cast(wx),y = reinterpret_cast(wy); + // x and y are the coordinates of the client rect (= actual VST interface) + + WINDOWINFO winfo; + winfo.cbSize = sizeof(winfo); + GetWindowInfo(hwnd,&winfo); + int px = winfo.rcWindow.left-winfo.rcClient.left; + int py = winfo.rcWindow.top-winfo.rcClient.top; + int sx = winfo.rcWindow.right-winfo.rcClient.right-px; + int sy = winfo.rcWindow.bottom-winfo.rcClient.bottom-py; + // send normalized coordinates to plugin + plug->SetSize(x+sx,y+sy,false); break; } +#endif #if 0 // NOT needed for Windows case WM_PAINT: { @@ -86,16 +130,9 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) break; } #endif - -#if 0 //def FLEXT_LOGGING - case WM_SIZE: { - WORD wx = LOWORD(lp),wy = HIWORD(lp); - short x = reinterpret_cast(wx),y = reinterpret_cast(wy); - // x and y are the coordinates of the client rect (= actual VST interface) - flext::post("WM_SIZE x/y=%i/%i",x,y); - break; - } -#endif + case WM_SHOWWINDOW: + plug->Visible(wp != FALSE,false); + break; default: #ifdef FLEXT_LOGGING @@ -107,22 +144,25 @@ static LRESULT CALLBACK wndproc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp) return res; } -static void windowsize(HWND wnd,int x,int y,int w,int h,bool caption,LONG flags = 0) +static void windowsize(HWND wnd,int x,int y,int w,int h) { - WINDOWINFO winfo; + // pre correction + WINDOWINFO winfo; winfo.cbSize = sizeof(winfo); GetWindowInfo(wnd,&winfo); + int sx1 = (winfo.rcWindow.right-winfo.rcClient.right)-(winfo.rcWindow.left-winfo.rcClient.left); + int sy1 = (winfo.rcWindow.bottom-winfo.rcClient.bottom)-(winfo.rcWindow.top-winfo.rcClient.top); - int cy = caption?GetSystemMetrics(SM_CYCAPTION):0; + // First reflect new state in flags + SetWindowPos(wnd,NULL,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); - SetWindowPos(wnd,HWND_TOP, - x-(winfo.rcClient.left-winfo.rcWindow.left), - y-(winfo.rcClient.top-winfo.rcWindow.top), - w+winfo.cxWindowBorders*2, - h+cy+winfo.cyWindowBorders*2, - flags - ); + // post correction + GetWindowInfo(wnd,&winfo); + int sx2 = (winfo.rcWindow.right-winfo.rcClient.right)-(winfo.rcWindow.left-winfo.rcClient.left); + int sy2 = (winfo.rcWindow.bottom-winfo.rcClient.bottom)-(winfo.rcWindow.top-winfo.rcClient.top); + // set pos, size and flags + SetWindowPos(wnd,NULL,x,y,w+sx2-sx1,h+sy2-sy1,SWP_NOZORDER); } static void threadfun(flext::thr_params *p) @@ -137,14 +177,18 @@ static void threadfun(flext::thr_params *p) wndmap[thrid] = plug; mapmutex.Unlock(); - char tmp[256]; sprintf(tmp,"vst~ - %s",plug->GetName()); - HWND wnd = CreateWindow( + // Get size from plugin + ERect r; + plug->GetEditorRect(r); + + HWND wnd = CreateWindowEx( + plug->GetHandle()?WS_EX_APPWINDOW:WS_EX_TOOLWINDOW, WCLNAME,tmp, - (plug->GetCaption()?WS_BORDER|WS_CAPTION:0)|WS_POPUP|WS_SYSMENU|WS_MINIMIZEBOX, - CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, + WS_POPUP|WS_SYSMENU|WS_MINIMIZEBOX, // no border for the beginning to set proper coordinates + plug->GetX(),plug->GetY(),r.right-r.left,r.bottom-r.top, NULL,NULL, hinstance,NULL ); @@ -152,34 +196,30 @@ static void threadfun(flext::thr_params *p) if(!wnd) FLEXT_LOG1("wnd == NULL: %i",GetLastError()); else { -// plug->Dispatch(effEditOpen , 0 , 0 , wnd, 0.0f ); // Done in WNDPROC!! - /* - CString str = theApp->GetProfileString( "VSTPos" , plug->GetName() , "10,10"); - int idx = str.Find(","); - CString x = str.Left( idx ); - CString y = str.Right( idx ); - printf(" index is %d left is %s and right is %s" , idx , x , y); - */ - -// plug->Dispatch(effEditTop,0,0, 0,0.0f); - // printf("Dispatched to the top\n"); - - SetTimer(wnd,0,TIMER_INTERVAL,NULL); - - 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_LOGGING - flext::post("Editor rect left/top=%i/%i, right/bottom=%i/%i",r.left,r.top,r.right,r.bottom); -#endif + // idle timer + SetTimer(wnd,0,TIMER_INTERVAL,NULL); + + // set caption style + CaptionEditor(plug,plug->GetCaption()); + + if(plug->IsVisible()) { + SetForegroundWindow(wnd); + ShowWindow(wnd,1); + + // notify plugin + // plug->Dispatch(effEditTop,0,0,0,0); + } + else + ShowWindow(wnd,0); - // SetFocus(); + try + { - // Message pump + // Message loop MSG msg; BOOL bRet; while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) { - if (bRet == -1) { + if(bRet == -1) { // handle the error and possibly exit FLEXT_LOG1("GetMessage error: %i",GetLastError()); } @@ -188,9 +228,18 @@ static void threadfun(flext::thr_params *p) DispatchMessage(&msg); } } - } -// UnregisterClass(wcx.lpszClassName,hinstance); + } + + catch(exception &e) { + flext::post("vst~ - exception caught, exiting: %s",e.what()); + } + catch(...) { + flext::post("vst~ - exception caught, exiting"); + } + + if(plug) plug->EditingEnded(); + } mapmutex.Lock(); wndmap.erase(thrid); @@ -235,7 +284,7 @@ void StopEditor(VSTPlugin *p) flext::post("Stop editor 1"); #endif PostMessage(p->EditorHandle(),WM_CLOSE,0,0); - flext::StopThread(threadfun,reinterpret_cast(p)); +// flext::StopThread(threadfun,reinterpret_cast(p)); #ifdef FLEXT_LOGGING flext::post("Stop editor 2"); #endif @@ -249,21 +298,18 @@ void ShowEditor(VSTPlugin *p,bool show) void MoveEditor(VSTPlugin *p,int x,int y) { HWND wnd = p->EditorHandle(); - - WINDOWINFO winfo; - winfo.cbSize = sizeof(winfo); - GetWindowInfo(wnd,&winfo); - - SetWindowPos(wnd,NULL, - x-(winfo.rcClient.left-winfo.rcWindow.left),y-(winfo.rcClient.top-winfo.rcWindow.top), - 0,0, - SWP_NOSIZE|SWP_NOZORDER - ); + SetWindowPos(wnd,NULL,x,y,0,0,SWP_NOSIZE|SWP_NOZORDER); } void SizeEditor(VSTPlugin *p,int x,int y) { - SetWindowPos(p->EditorHandle(),NULL,0,0,x,y,SWP_NOMOVE|SWP_NOZORDER); + HWND wnd = p->EditorHandle(); + SetWindowPos(wnd,NULL,0,0,x,y,SWP_NOMOVE|SWP_NOZORDER); +} + +void FrontEditor(VSTPlugin *p) +{ + SetForegroundWindow(p->EditorHandle()); } void CaptionEditor(VSTPlugin *plug,bool c) @@ -274,18 +320,27 @@ void CaptionEditor(VSTPlugin *plug,bool c) else ns = style&~(WS_BORDER|WS_CAPTION); if(ns != style) { SetWindowLong(wnd,GWL_STYLE,ns); - - ERect r; plug->GetEditorRect(r); - windowsize(wnd,plug->GetX(),plug->GetY(),r.right-r.left,r.bottom-r.top,c,SWP_FRAMECHANGED); + windowsize(wnd,plug->GetX(),plug->GetY(),plug->GetW(),plug->GetH()); } } +void HandleEditor(VSTPlugin *plug,bool h) +{ + HWND wnd = plug->EditorHandle(); + bool v = plug->IsVisible(); + if(v) ShowWindow(wnd,FALSE); + SetWindowLong(wnd,GWL_EXSTYLE,h?WS_EX_APPWINDOW:WS_EX_TOOLWINDOW); + if(v) ShowWindow(wnd,TRUE); +} + void TitleEditor(VSTPlugin *p,const char *t) { SetWindowText(p->EditorHandle(),t); } +/* bool IsEditorShown(const VSTPlugin *p) { return IsWindowVisible(p->EditorHandle()) != FALSE; } +*/ \ No newline at end of file diff --git a/externals/grill/vst/src/main.cpp b/externals/grill/vst/src/main.cpp index 9a4b3a6c..d1c369c3 100644 --- a/externals/grill/vst/src/main.cpp +++ b/externals/grill/vst/src/main.cpp @@ -26,7 +26,7 @@ WARRANTIES, see the file, "license.txt," in this distribution. #endif -#define VST_VERSION "0.1.0pre21" +#define VST_VERSION "0.1.0pre23" class vst @@ -64,12 +64,19 @@ protected: void mg_winx(int &x) const { x = plug?plug->GetX():0; } void mg_winy(int &y) const { y = plug?plug->GetY():0; } + void mg_winw(int &x) const { x = plug?plug->GetW():0; } + void mg_winh(int &y) const { y = plug?plug->GetH():0; } void ms_winx(int x) { if(plug) plug->SetX(x); } void ms_winy(int y) { if(plug) plug->SetY(y); } + void ms_winw(int x) { if(plug) plug->SetW(x); } + void ms_winh(int y) { if(plug) plug->SetH(y); } void ms_wincaption(bool c) { if(plug) plug->SetCaption(c); } void mg_wincaption(bool &c) const { c = plug && plug->GetCaption(); } + void ms_winhandle(bool c) { if(plug) plug->SetHandle(c); } + void mg_winhandle(bool &c) const { c = plug && plug->GetHandle(); } void ms_wintitle(const AtomList &t); void mg_wintitle(AtomList &t) const { if(plug) { t(1); SetString(t[0],plug->GetTitle()); } } + void m_winfront() const { if(plug) plug->ToFront(); } void mg_chnsin(int &c) const { c = plug?plug->GetNumInputs():0; } void mg_chnsout(int &c) const { c = plug?plug->GetNumOutputs():0; } @@ -98,13 +105,19 @@ protected: 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 mg_channel(int &chn) const { chn = plug?plug->GetChannel():0; } + void ms_channel(int chn) { if(plug) plug->SetChannel(chn); } + void m_note(int note,int vel); void m_noteoff(int note) { m_note(note,0); } + void m_programchange(int ctrl_value) { if(plug) plug->AddProgramChange(ctrl_value); } + void m_ctrlchange(int control,int ctrl_value) { if(plug) plug->AddControlChange(control,ctrl_value); } + void m_aftertouch(int ctrl_value) { if(plug) plug->AddAftertouch(ctrl_value); } + void m_polyaftertouch(int note,int ctrl_value) { if(plug) plug->AddPolyAftertouch(note,ctrl_value); } + void m_pitchbend(int ctrl_value) { if(plug) plug->AddPitchBend(ctrl_value); } + + void mg_dumpevents(bool &ev) const { ev = plug?plug->GetEvents():false; } + void ms_dumpevents(bool ev) { if(plug) plug->SetEvents(ev); } void mg_playing(bool &p) { p = plug && plug->GetPlaying(); } void ms_playing(bool p) { if(plug) plug->SetPlaying(p); } @@ -140,7 +153,7 @@ private: VSTPlugin *plug; std::string plugname,subplug; - bool echoparam,visible,bypass,mute; + bool visible,bypass,mute; int paramnames; int blsz; @@ -171,12 +184,17 @@ private: FLEXT_ATTRVAR_B(bypass) FLEXT_ATTRVAR_B(mute) -// FLEXT_CALLBACK_2(m_control,t_symptr,int) - FLEXT_CALLBACK_I(m_pitchbend) - FLEXT_CALLBACK_I(m_aftertouch) - FLEXT_CALLBACK_I(m_programchange) + FLEXT_CALLVAR_I(mg_channel,ms_channel) + FLEXT_CALLBACK_II(m_note) + FLEXT_CALLBACK_I(m_noteoff) FLEXT_CALLBACK_II(m_ctrlchange) + FLEXT_CALLBACK_I(m_aftertouch) + FLEXT_CALLBACK_II(m_polyaftertouch) + FLEXT_CALLBACK_I(m_pitchbend) + + FLEXT_CALLVAR_B(mg_dumpevents,ms_dumpevents) + FLEXT_CALLBACK_I(m_programchange) FLEXT_CALLVAR_I(mg_program,ms_program) FLEXT_CALLBACK_V(mg_progname) @@ -190,14 +208,14 @@ private: FLEXT_CALLBACK_I(m_ptext) FLEXT_CALLBACK_V(m_ptexts) - FLEXT_CALLBACK_II(m_note) - FLEXT_CALLBACK_I(m_noteoff) - - FLEXT_ATTRVAR_B(echoparam) FLEXT_CALLVAR_I(mg_winx,ms_winx) FLEXT_CALLVAR_I(mg_winy,ms_winy) + FLEXT_CALLVAR_I(mg_winw,ms_winw) + FLEXT_CALLVAR_I(mg_winh,ms_winh) FLEXT_CALLVAR_B(mg_wincaption,ms_wincaption) + FLEXT_CALLVAR_B(mg_winhandle,ms_winhandle) FLEXT_CALLVAR_V(mg_wintitle,ms_wintitle) + FLEXT_CALLBACK(m_winfront) FLEXT_CALLGET_I(mg_chnsin) FLEXT_CALLGET_I(mg_chnsout) @@ -250,12 +268,15 @@ void vst::Setup(t_classid c) FLEXT_CADDATTR_VAR1(c,"mute",mute); FLEXT_CADDMETHOD_(c,0,"print",m_print); - FLEXT_CADDMETHOD_II(c,0,"note",m_note); + FLEXT_CADDATTR_VAR(c,"channel",mg_channel,ms_channel); FLEXT_CADDMETHOD_I(c,0,"noteoff",m_noteoff); -// FLEXT_CADDMETHOD_2(c,0,"control",m_control,t_symptr,int); - FLEXT_CADDMETHOD_(c,0,"pbend",m_pitchbend); - FLEXT_CADDMETHOD_(c,0,"atouch",m_aftertouch); + FLEXT_CADDMETHOD_II(c,0,"note",m_note); + FLEXT_CADDMETHOD_II(c,0,"patouch",m_polyaftertouch); FLEXT_CADDMETHOD_II(c,0,"ctlchg",m_ctrlchange); + FLEXT_CADDMETHOD_(c,0,"atouch",m_aftertouch); + FLEXT_CADDMETHOD_(c,0,"pbend",m_pitchbend); + + FLEXT_CADDATTR_VAR(c,"events",mg_dumpevents,ms_dumpevents); FLEXT_CADDMETHOD_(c,0,"progchg",m_programchange); FLEXT_CADDATTR_VAR(c,"program",mg_program,ms_program); @@ -270,11 +291,14 @@ void vst::Setup(t_classid c) FLEXT_CADDMETHOD_(c,0,"getptext",m_ptext); FLEXT_CADDMETHOD_(c,0,"getptext",m_ptexts); - FLEXT_CADDATTR_VAR1(c,"echo",echoparam); FLEXT_CADDATTR_VAR(c,"x",mg_winx,ms_winx); FLEXT_CADDATTR_VAR(c,"y",mg_winy,ms_winy); - FLEXT_CADDATTR_VAR(c,"caption",mg_wincaption,ms_wincaption); + FLEXT_CADDATTR_VAR(c,"w",mg_winw,ms_winw); + FLEXT_CADDATTR_VAR(c,"h",mg_winh,ms_winh); FLEXT_CADDATTR_VAR(c,"title",mg_wintitle,ms_wintitle); + FLEXT_CADDATTR_VAR(c,"caption",mg_wincaption,ms_wincaption); + FLEXT_CADDATTR_VAR(c,"handle",mg_winhandle,ms_winhandle); + FLEXT_CADDMETHOD_(c,0,"front",m_winfront); FLEXT_CADDATTR_GET(c,"ins",mg_chnsin); FLEXT_CADDATTR_GET(c,"outs",mg_chnsout); @@ -318,7 +342,7 @@ 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) + bypass(false),mute(false),paramnames(0) { #if FLEXT_OS == FLEXT_OS_WIN // this is necessary for Waveshell @@ -346,9 +370,9 @@ vst::~vst() void vst::ClearPlug() { if(plug) { - plug->Edit(false); ClearBuf(); // needs valid plug - delete plug; plug = NULL; + VSTPlugin::Delete(plug); + plug = NULL; } } @@ -440,15 +464,17 @@ static std::string findFilePath(const std::string &path,const std::string &dllna return std::string(); } - +// \todo this should be in the background, because it can take some time +// ideally vst would get a response from VSTPlugin when readily, loaded and +// vst would dump out a respective signal to the patcher bool vst::LoadPlug() { if(plug) ClearPlug(); - plug = new VSTPlugin(this); + VSTPlugin *p = VSTPlugin::New(this); // try loading the dll from the raw filename - bool ok = plug->Instance(plugname.c_str(),subplug.c_str()); + bool ok = p->Instance(plugname.c_str(),subplug.c_str()); if(ok) FLEXT_LOG("raw filename loaded fine"); else { @@ -468,7 +494,7 @@ bool vst::LoadPlug() dllname += "\\"; dllname += name; - ok = plug->Instance(dllname.c_str()); + ok = p->Instance(dllname.c_str()); } #endif } @@ -497,7 +523,7 @@ bool vst::LoadPlug() realpath += plugname; FLEXT_LOG1("trying %s",(const char *)realpath.c_str()); - ok = plug->Instance(realpath.c_str()); + ok = p->Instance(realpath.c_str()); if(ok) { FLEXT_LOG("plugin loaded via VST_PATH"); break; @@ -505,7 +531,7 @@ bool vst::LoadPlug() } tok = strtok( NULL , ";" ); - if(!tok) post("%s - couldn't find plugin",thisName()); +// if(!tok) post("%s - couldn't find plugin",thisName()); } delete[] tok_path; @@ -514,10 +540,12 @@ bool vst::LoadPlug() if(!ok) { post("%s - unable to load plugin '%s'",thisName(),plugname.c_str()); - ClearPlug(); + VSTPlugin::Delete(p); } - else + else { + plug = p; InitPlug(); + } return ok; } @@ -674,32 +702,6 @@ void vst::CbSignal() flext_dsp::CbSignal(); } - -#if 0 - -void vst::m_control(const t_symbol *ctrl_name,int ctrl_value) -{ - if(!plug) return; - - int parm_num = 0; - - if (!*GetString(ctrl_name) || !strlen(GetString(ctrl_name))) { - error ("plugin~: control messages must have a name and a value"); - return; - } - //parm_num = vst_tilde_get_parm_number (x, ctrl_name->s_name); - //if (parm_num) - //{ - //vst_tilde_set_control_input_by_index (x, parm_num - 1, ctrl_value); - //} - //else - //{ - //vst_tilde_set_control_input_by_name (x, ctrl_name->s_name, ctrl_value); - //} -} - -#endif - void vst::mg_progname(int argc,const t_atom *argv) const { if(plug) { @@ -788,8 +790,8 @@ void vst::m_print(int ac,const t_atom *av) } if ( header ) { - post("VST~ plugin: %s " , plug->GetName() ); - post("made by: %s " , plug->GetVendorName() ); + post("VST~ plugin: %s ", plug->GetName() ); + post("made by: %s ", plug->GetVendorName() ); post("parameters %d\naudio: %d in(s)/%d out(s) \nLoaded from library \"%s\".\n", plug->GetNumParams(), CntInSig(), @@ -868,12 +870,12 @@ void vst::ms_param(int pnum,float val) { if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; - float xval = plug->GetParamValue( pnum ); +// float xval = plug->GetParamValue( pnum ); // if(xval <= 1.0f) // What's that???? if(true) { plug->SetParamFloat( pnum, val ); - if(echoparam) display_parameter(pnum , true ); +// if(echoparam) display_parameter(pnum , true ); } else FLEXT_ASSERT(false); diff --git a/externals/grill/vst/src/vstedit.cpp b/externals/grill/vst/src/vstedit.cpp index 804e83ca..1536b9d3 100644 --- a/externals/grill/vst/src/vstedit.cpp +++ b/externals/grill/vst/src/vstedit.cpp @@ -27,50 +27,56 @@ 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; - } + if(Is() && IsEdited()) + Dispatch(effEditClose); } -void VSTPlugin::Visible(bool vis) +void VSTPlugin::Visible(bool vis,bool upd) { - if(Is() && IsEdited()) ShowEditor(this,vis); + visible = vis; + if(upd && Is() && IsEdited()) ShowEditor(this,vis); } -bool VSTPlugin::IsVisible() const -{ - return Is() && IsEdited() && IsEditorShown(this); +void VSTPlugin::SetPos(int x,int y,bool upd) +{ + posx = x; posy = y; + if(upd && Is() && IsEdited()) MoveEditor(this,posx,posy); } - -void VSTPlugin::SetPos(int x,int y,bool upd) +void VSTPlugin::SetSize(int x,int y,bool upd) { - if(Is()) { - posx = x; posy = y; - if(upd && IsEdited()) MoveEditor(this,posx,posy); - } + sizex = x; sizey = y; + if(upd && Is() && IsEdited()) SizeEditor(this,sizex,sizey); } void VSTPlugin::SetCaption(bool c) { - if(Is()) { - caption = c; - if(IsEdited()) CaptionEditor(this,c); - } + caption = c; + if(Is() && IsEdited()) CaptionEditor(this,c); +} + +void VSTPlugin::SetHandle(bool h) +{ + handle = h; + if(Is() && IsEdited()) HandleEditor(this,h); } void VSTPlugin::SetTitle(const char *t) { - if(Is()) { - title = t; - if(IsEdited()) TitleEditor(this,t); + title = t; + if(Is() && IsEdited()) TitleEditor(this,t); +} + +void VSTPlugin::ToFront() +{ + if(Is() && IsEdited()) { + FrontEditor(this); + Dispatch(effEditTop,0,0,vendorname); } } diff --git a/externals/grill/vst/src/vsthost.cpp b/externals/grill/vst/src/vsthost.cpp index 3b9d6241..5f2443fc 100644 --- a/externals/grill/vst/src/vsthost.cpp +++ b/externals/grill/vst/src/vsthost.cpp @@ -8,7 +8,9 @@ WARRANTIES, see the file, "license.txt," in this distribution. */ #include "vsthost.h" - +#include "editor.h" +#include +#include "flcontainers.h" const t_symbol *VSTPlugin::sym_param, @@ -22,8 +24,22 @@ const t_symbol *VSTPlugin::sym_ev_, *VSTPlugin::sym_midi[8]; + +class DelPlugin + : public Fifo::Cell +{ +public: + DelPlugin(VSTPlugin *p): plug(p) {} + VSTPlugin *plug; +}; + +static TypedLifo todel; +flext::ThrCond VSTPlugin::thrcond; + void VSTPlugin::Setup() { + LaunchThread(worker); + sym_param = flext::MakeSymbol("param"); sym_event = flext::MakeSymbol("event"); sym_evmidi = flext::MakeSymbol("midi"); @@ -34,22 +50,23 @@ void VSTPlugin::Setup() sym_evsysex = flext::MakeSymbol("sysex"); sym_ev_ = flext::MakeSymbol("???"); - sym_midi[0] = flext::MakeSymbol("noteon"); - sym_midi[1] = flext::MakeSymbol("noteoff"); - sym_midi[2] = flext::MakeSymbol("polyafter"); - sym_midi[3] = flext::MakeSymbol("cntl"); + sym_midi[0] = flext::MakeSymbol("noteoff"); + sym_midi[1] = flext::MakeSymbol("note"); + sym_midi[2] = flext::MakeSymbol("atouch"); + sym_midi[3] = flext::MakeSymbol("ctlchg"); sym_midi[4] = flext::MakeSymbol("progchg"); - sym_midi[5] = flext::MakeSymbol("chnafter"); - sym_midi[6] = flext::MakeSymbol("pitchbend"); - sym_midi[7] = sym__; + sym_midi[5] = flext::MakeSymbol("atouch"); + sym_midi[6] = flext::MakeSymbol("pbend"); + sym_midi[7] = flext::MakeSymbol("sysex"); } VSTPlugin::VSTPlugin(Responder *resp) : hdll(NULL),hwnd(NULL) , effect(NULL),pluginmain(NULL),audiomaster(NULL) , responder(resp) - , posx(0),posy(0),caption(true) - , midichannel(0),eventqusz(0) + , posx(0),posy(0),sizex(0),sizey(0) + , visible(true),caption(true),handle(false) + , midichannel(0),eventqusz(0),dumpevents(false) , paramnamecnt(0) , transchg(true) , playing(false),looping(false),feedback(false) @@ -67,7 +84,55 @@ VSTPlugin::~VSTPlugin() Free(); } +VSTPlugin *VSTPlugin::New(Responder *resp) +{ + FLEXT_ASSERT(resp); + return new VSTPlugin(resp); +} + +void VSTPlugin::Delete(VSTPlugin *p) +{ + FLEXT_ASSERT(p); + + // tell plugin to close editor! + StopEditor(p); + // transfer to deletion thread + todel.Push(new DelPlugin(p)); + thrcond.Signal(); +} + +void VSTPlugin::worker(thr_params *) +{ + TypedLifo tmp; + bool again = false; + for(;;) { + // wait for signal + if(again) { + thrcond.TimedWait(0.01); + again = false; + } + else + thrcond.Wait(); + + DelPlugin *p; + while((p = todel.Pop()) != NULL) { + // see if editing has stopped + if(p && p->plug->hwnd == NULL) { + // yes, it is now safe to delete the plug + delete p->plug; + delete p; + } + else { + tmp.Push(p); + again = true; + } + } + // put back remaining entries + while((p = tmp.Pop()) != NULL) todel.Push(p); + } +} + #if FLEXT_OS == FLEXT_OS_MAC OSStatus FSPathMakeFSSpec(const UInt8 *path,FSSpec *spec,Boolean *isDirectory) /* can be NULL */ { @@ -208,9 +273,17 @@ bool VSTPlugin::InstPlugin(long plugid) FLEXT_ASSERT(pluginmain && audiomaster); //This calls the "main" function and receives the pointer to the AEffect structure. - effect = pluginmain(audiomaster); - if(!effect || effect->magic != kEffectMagic) { - post("VST plugin : Unable to create effect"); + try { effect = pluginmain(audiomaster); } + catch(exception &e) { + flext::post("vst~ - caught exception while instantiating plugin: %s",e.what()); + } + catch(...) { + flext::post("vst~ - caught exception while instantiating plugin"); + } + + if(!effect) + return false; + else if(effect->magic != kEffectMagic) { effect = NULL; return false; } @@ -219,13 +292,19 @@ bool VSTPlugin::InstPlugin(long plugid) bool VSTPlugin::Instance(const char *name,const char *subname) { - bool ok = effect != NULL; + bool ok = false; + FLEXT_ASSERT(effect == NULL); + try { + +/* if(!ok && dllname != name) { FreePlugin(); // freshly load plugin ok = NewPlugin(name) && InstPlugin(); } +*/ + ok = NewPlugin(name) && InstPlugin(); if(ok && subname && *subname && Dispatch(effGetPlugCategory) == kPlugCategShell) { // sub plugin-name given -> scan plugs @@ -294,37 +373,53 @@ bool VSTPlugin::Instance(const char *name,const char *subname) Dispatch(effGetVendorString,0,0,vendorname); } + } + catch(exception &e) { + flext::post("vst~ - caught exception while loading plugin: %s",e.what()); + ok = false; + } + catch(...) { + flext::post("vst~ - Caught exception while loading plugin"); + ok = false; + } + if(!ok) Free(); return ok; } -void VSTPlugin::Free() // Called also in destruction +void VSTPlugin::Free() { - if(effect) { - Edit(false); + // This should only also in destruction - // shut down plugin - Dispatch(effMainsChanged, 0, 0); - Dispatch(effClose); - } + try { + if(effect) { + FLEXT_ASSERT(!IsEdited()); - // \TODO - // Here, we really have to wait until the editor thread has terminated - // otherwise WM_DESTROY etc. messages may still be pending - // in other words: this is a design flaw - // There should be a data stub accessible from the plugin object and the thread - // holding the necessary data, so that both can operate independently + // shut down plugin + Dispatch(effMainsChanged, 0, 0); + Dispatch(effClose); + } + } + catch(...) {} FreePlugin(); } void VSTPlugin::DspInit(float sr,int blsz) { - // sample rate and block size must _first_ be set - Dispatch(effSetSampleRate,0,0,NULL,samplerate = sr); - Dispatch(effSetBlockSize, 0,blsz); - // then signal that mains have changed! - Dispatch(effMainsChanged,0,1); + try { + // sample rate and block size must _first_ be set + Dispatch(effSetSampleRate,0,0,NULL,samplerate = sr); + Dispatch(effSetBlockSize, 0,blsz); + // then signal that mains have changed! + Dispatch(effMainsChanged,0,1); + } + catch(exception &e) { + flext::post("vst~ - caught exception while initializing dsp: %s",e.what()); + } + catch(...) { + flext::post("vst~ - caught exception while initializing dsp"); + } } void VSTPlugin::ListPlugs(const t_symbol *sym) const diff --git a/externals/grill/vst/src/vsthost.h b/externals/grill/vst/src/vsthost.h index bda1d538..0b1adef0 100644 --- a/externals/grill/vst/src/vsthost.h +++ b/externals/grill/vst/src/vsthost.h @@ -40,19 +40,27 @@ public: virtual void Respond(const t_symbol *sym,int argc = 0,const t_atom *argv = NULL) = 0; }; + class VSTPlugin: public flext { public: + static VSTPlugin *New(Responder *resp); + static void Delete(VSTPlugin *p); static void Setup(); + bool Instance(const char *plug,const char *subplug = NULL); + void DspInit(float samplerate,int blocksize); + +private: VSTPlugin(Responder *resp); ~VSTPlugin(); - bool Instance(const char *plug,const char *subplug = NULL); + static ThrCond thrcond; + static void worker(thr_params *p); + void Free(); - void DspInit(float samplerate,int blocksize); ////////////////////////////////////////////////////////////////////////////// @@ -119,81 +127,104 @@ private: public: void SetPos(int x,int y,bool upd = true); + void SetSize(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); } + void SetW(int x,bool upd = true) { SetSize(x,sizey,upd); } + void SetH(int y,bool upd = true) { SetSize(sizex,y,upd); } int GetX() const { return posx; } int GetY() const { return posy; } + int GetW() const { return sizex; } + int GetH() const { return sizey; } void SetCaption(bool b); bool GetCaption() const { return caption; } + void SetHandle(bool h); + bool GetHandle() const { return handle; } void SetTitle(const char *t); const char *GetTitle() const { return title.c_str(); } + void ToFront(); void Edit(bool open); - void StartEditing(WHandle h ); + void StartEditing(WHandle h); void StopEditing(); bool IsEdited() const { return hwnd != NULL; } WHandle EditorHandle() const { return hwnd; } + void EditingEnded() { hwnd = NULL; thrcond.Signal(); } void GetEditorRect(ERect &er) const { ERect *r; Dispatch(effEditGetRect,0,0,&r); er = *r; } void EditorIdle() { Dispatch(effEditIdle); } - void Visible(bool vis); - bool IsVisible() const; + void Visible(bool vis,bool upd = true); + bool IsVisible() const { return visible; } void Paint(ERect &r) const { Dispatch(effEditDraw,0,0,&r); } private: - int posx,posy; // Window position + bool visible; + int posx,posy,sizex,sizey; // Window position bool caption; // Window border + bool handle; // Window handle (like taskbar button) std::string title; // Window title ////////////////////////////////////////////////////////////////////////////// public: enum { - MIDI_NOTEON = 144, - MIDI_NOTEOFF = 128, - MIDI_POLYAFTERTOUCH = 160, - MIDI_CONTROLCHANGE = 176, - MIDI_PROGRAMCHANGE = 192, - MIDI_AFTERTOUCH = 208, - MIDI_PITCHBEND = 224 + MIDI_NOTEOFF = 0x80, + MIDI_NOTEON = 0x90, + MIDI_POLYAFTERTOUCH = 0xa0, + MIDI_CONTROLCHANGE = 0xb0, + MIDI_PROGRAMCHANGE = 0xc0, + MIDI_AFTERTOUCH = 0xd0, + MIDI_PITCHBEND = 0xe0, + MIDI_SYSEX = 0xf0, }; + void SetEvents(bool ev) { dumpevents = ev; } + bool GetEvents() const { return dumpevents; } + bool AddMIDI(unsigned char data0,unsigned char data1 = 0,unsigned char data2 = 0); static int range(int value,int mn = 0,int mx = 127) { return value < mn?mn:(value > mx?mx:value); } - bool AddNoteOn(unsigned char note,unsigned char speed,unsigned char midichannel = 0) + void SetChannel(int channel) { midichannel = range(channel,0,0xf); } + int GetChannel() const { return midichannel; } + + bool AddNoteOn(unsigned char note,unsigned char speed /*,unsigned char midichannel = 0*/) { - return AddMIDI((char)MIDI_NOTEON|midichannel,note,speed); + return AddMIDI(MIDI_NOTEON+midichannel,note,speed); } - bool AddNoteOff(unsigned char note,unsigned char midichannel = 0) + bool AddNoteOff(unsigned char note /*,unsigned char midichannel = 0*/) { - return AddMIDI((char)MIDI_NOTEOFF|midichannel,note,0); + return AddMIDI(MIDI_NOTEOFF+midichannel,note,0); } void AddControlChange(int control,int value) { - AddMIDI(MIDI_CONTROLCHANGE+(midichannel&0xf),range(control),range(value)); + AddMIDI(MIDI_CONTROLCHANGE+midichannel,range(control),range(value)); } void AddProgramChange(int value) { - AddMIDI(MIDI_PROGRAMCHANGE+(midichannel&0xf),range(value),0); + AddMIDI(MIDI_PROGRAMCHANGE+midichannel,range(value),0); } void AddPitchBend(int value) { - AddMIDI(MIDI_PITCHBEND+(midichannel&0xf),((value>>7)&127),(value&127)); + AddMIDI(MIDI_PITCHBEND+midichannel,((value>>7)&127),(value&127)); } void AddAftertouch(int value) { - AddMIDI((char)MIDI_AFTERTOUCH|midichannel,range(value)); + AddMIDI(MIDI_AFTERTOUCH+midichannel,range(value)); + } + + void AddPolyAftertouch(unsigned char note,int value) + { + AddMIDI(MIDI_POLYAFTERTOUCH+midichannel,note,range(value)); } private: @@ -205,6 +236,7 @@ private: int eventqusz; char midichannel; + bool dumpevents; ////////////////////////////////////////////////////////////////////////////// diff --git a/externals/grill/vst/src/vstmaster.cpp b/externals/grill/vst/src/vstmaster.cpp index 108d8079..00a93c80 100644 --- a/externals/grill/vst/src/vstmaster.cpp +++ b/externals/grill/vst/src/vstmaster.cpp @@ -16,7 +16,7 @@ static const char *product = "vst~"; void VSTPlugin::ProcessEvent(const VstEvent &ev) { - if(!responder) return; + if(!responder && dumpevents) return; if(ev.type == kVstMidiType) { const VstMidiEvent &mev = (const VstMidiEvent &)ev; diff --git a/externals/grill/vst/src/vstparam.cpp b/externals/grill/vst/src/vstparam.cpp index 30515b23..bb80263e 100644 --- a/externals/grill/vst/src/vstparam.cpp +++ b/externals/grill/vst/src/vstparam.cpp @@ -16,6 +16,7 @@ static void striptrail(char *txt) 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; + else break; } void VSTPlugin::GetParamName(int numparam,char *name) const -- cgit v1.2.1