diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2003-02-23 00:09:18 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2003-02-23 00:09:18 +0000 |
commit | abcb79a75c9d5784f41260d25fdd0029641cb968 (patch) | |
tree | 3233eee9223dfc226b5d843ba134690c95fc1766 /externals/grill/vst/src | |
parent | 90009cca00b50cc88e0ef0a26728e19418cbd12f (diff) |
""
svn path=/trunk/; revision=423
Diffstat (limited to 'externals/grill/vst/src')
-rw-r--r-- | externals/grill/vst/src/EditorThread.cpp | 61 | ||||
-rw-r--r-- | externals/grill/vst/src/EditorThread.h | 60 | ||||
-rw-r--r-- | externals/grill/vst/src/PopupWindow.cpp | 126 | ||||
-rw-r--r-- | externals/grill/vst/src/PopupWindow.h | 53 | ||||
-rw-r--r-- | externals/grill/vst/src/Resource.h | 16 | ||||
-rw-r--r-- | externals/grill/vst/src/StdAfx.cpp | 8 | ||||
-rw-r--r-- | externals/grill/vst/src/StdAfx.h | 42 | ||||
-rw-r--r-- | externals/grill/vst/src/VstHost.cpp | 589 | ||||
-rw-r--r-- | externals/grill/vst/src/VstHost.h | 158 | ||||
-rw-r--r-- | externals/grill/vst/src/main.cpp | 692 | ||||
-rw-r--r-- | externals/grill/vst/src/main.h | 40 | ||||
-rw-r--r-- | externals/grill/vst/src/vst.h | 46 | ||||
-rw-r--r-- | externals/grill/vst/src/vst.rc | 143 | ||||
-rw-r--r-- | externals/grill/vst/src/vst/AEffEditor.h | 44 | ||||
-rw-r--r-- | externals/grill/vst/src/vst/AEffect.h | 172 | ||||
-rw-r--r-- | externals/grill/vst/src/vst/AEffectx.h | 534 | ||||
-rw-r--r-- | externals/grill/vst/src/vst/AudioEffect.hpp | 109 | ||||
-rw-r--r-- | externals/grill/vst/src/vst/audioeffectx.h | 185 |
18 files changed, 3078 insertions, 0 deletions
diff --git a/externals/grill/vst/src/EditorThread.cpp b/externals/grill/vst/src/EditorThread.cpp new file mode 100644 index 00000000..1761542c --- /dev/null +++ b/externals/grill/vst/src/EditorThread.cpp @@ -0,0 +1,61 @@ +// EditorThread.cpp : implementation file +// + +#include "stdafx.h" +#include "vst.h" +#include "EditorThread.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CEditorThread + +IMPLEMENT_DYNCREATE(CEditorThread, CWinThread) + +CEditorThread::CEditorThread(): pop(NULL) {} + +CEditorThread::~CEditorThread() {} + + +BOOL CEditorThread::InitInstance() +{ + SetThreadPriority(THREAD_PRIORITY_LOWEST); + + m_pMainWnd = pop = new CPopupWindow; + pop->SetPlugin( plug); // window class, size etc. is set here! + return TRUE; +} + +int CEditorThread::ExitInstance() +{ + // TODO: perform any per-thread cleanup here + return CWinThread::ExitInstance(); +} + +BEGIN_MESSAGE_MAP(CEditorThread, CWinThread) + //{{AFX_MSG_MAP(CEditorThread) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CEditorThread message handlers + +void CEditorThread::SetPlugin(VSTPlugin *p) +{ + plug = p; +} + +void CEditorThread::Close() +{ + if(pop) pop->SendMessage(WM_CLOSE); +} + +void CEditorThread::Show(bool show) +{ + if(pop) pop->ShowWindow(show); +}
\ No newline at end of file diff --git a/externals/grill/vst/src/EditorThread.h b/externals/grill/vst/src/EditorThread.h new file mode 100644 index 00000000..cb9b2209 --- /dev/null +++ b/externals/grill/vst/src/EditorThread.h @@ -0,0 +1,60 @@ +#if !defined(AFX_EDITORTHREAD_H__9F3ACE98_7522_400D_9404_DFD67E3D721B__INCLUDED_) +#define AFX_EDITORTHREAD_H__9F3ACE98_7522_400D_9404_DFD67E3D721B__INCLUDED_ + +#include "PopupWindow.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// EditorThread.h : header file +// + +class VSTPLugin; + +///////////////////////////////////////////////////////////////////////////// +// CEditorThread thread + +class CEditorThread : public CWinThread +{ + DECLARE_DYNCREATE(CEditorThread) +protected: + +// Attributes +public: + CEditorThread(); // protected constructor used by dynamic creation + +// Operations +public: + void SetPlugin( VSTPlugin *); + + void Close(); + void Show(bool show); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEditorThread) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance(); + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CEditorThread(); + + VSTPlugin *plug; + CPopupWindow *pop; + + // Generated message map functions + //{{AFX_MSG(CEditorThread) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITORTHREAD_H__9F3ACE98_7522_400D_9404_DFD67E3D721B__INCLUDED_) diff --git a/externals/grill/vst/src/PopupWindow.cpp b/externals/grill/vst/src/PopupWindow.cpp new file mode 100644 index 00000000..35c30a81 --- /dev/null +++ b/externals/grill/vst/src/PopupWindow.cpp @@ -0,0 +1,126 @@ +// PopupWindow.cpp : implementation file +// + +#include "main.h" +#include "vst.h" +#include "PopupWindow.h" +#include "EditorThread.h" +#include "VstHost.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern CVstApp *theApp; + +///////////////////////////////////////////////////////////////////////////// +// CPopupWindow + +IMPLEMENT_DYNCREATE(CPopupWindow, CFrameWnd) + +CPopupWindow::CPopupWindow(): + plug(NULL) +{} + +CPopupWindow::~CPopupWindow() +{ + plug->OnEditorClose(); +} + + +BEGIN_MESSAGE_MAP(CPopupWindow, CFrameWnd) + //{{AFX_MSG_MAP(CPopupWindow) + ON_WM_ENTERIDLE() + ON_WM_TIMER() + ON_WM_MOVE() + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPopupWindow message handlers + +void CPopupWindow::OnEnterIdle(UINT nWhy, CWnd* pWho) +{ + CFrameWnd::OnEnterIdle(nWhy, pWho); + + // TODO: Add your message handler code here + if(plug) plug->EditorIdle(); +} + +void CPopupWindow::SetPlugin(VSTPlugin *p) +{ + plug = p; + + char tmp[256]; + sprintf(tmp,"vst~ - %s",plug->GetName()); + + CreateEx( WS_EX_DLGMODALFRAME,AfxRegisterWndClass(CS_DBLCLKS),tmp,WS_CAPTION|WS_THICKFRAME|WS_POPUP|WS_SYSMENU,0,0,0,0,NULL,NULL,NULL); + + plug->Dispatch(effEditOpen , 0 , 0 , m_hWnd , 0.0f ); + RECT r = plug->GetEditorRect(); +/* + 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); +*/ + SetWindowPos(&wndTopMost,plug->getX(),plug->getY(),(r.right - r.left) + 10 , r.bottom - r.top + 30 , SWP_SHOWWINDOW); + + DoInit(); + ShowWindow( SW_SHOW ); + BringWindowToTop(); +// SetFocus(); +} + + +//DEL BOOL CPopupWindow::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) +//DEL { +//DEL // TODO: Add your specialized code here and/or call the base class +//DEL +//DEL return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); +//DEL } + +void CPopupWindow::DoInit() +{ +// printf("DoInit\n"); + plug->Dispatch(effEditTop,0,0, 0,0.0f); +// printf("Dispatched to the top\n"); + SetTimer(0,25,NULL); +} + +void CPopupWindow::OnTimer(UINT nIDEvent) +{ + plug->Dispatch(effEditIdle, 0, 0, NULL, 0.0f); + CFrameWnd::OnTimer(nIDEvent); +} + +void CPopupWindow::OnMove(int x, int y) +{ + CFrameWnd::OnMove(x, y); + if(plug) plug->setPos(x,y); +/* + { + char buf[100]; + sprintf( buf , "%d,%d" , x , y ); + theApp->WriteProfileString( "VSTPos" , plug->GetName() , buf ); + } +*/ +} + + +//DEL void CPopupWindow::OnFinalRelease() +//DEL { +//DEL // +//DEL CFrameWnd::OnFinalRelease(); +//DEL } + +void CPopupWindow::OnClose() +{ + // TODO: Add your message handler code here and/or call default + plug->StopEditing(); + CFrameWnd::OnClose(); +} diff --git a/externals/grill/vst/src/PopupWindow.h b/externals/grill/vst/src/PopupWindow.h new file mode 100644 index 00000000..bacdc23b --- /dev/null +++ b/externals/grill/vst/src/PopupWindow.h @@ -0,0 +1,53 @@ +#if !defined(AFX_POPUPWINDOW_H__7B1E2281_5085_4F60_8002_5F79B2CAFFE3__INCLUDED_) +#define AFX_POPUPWINDOW_H__7B1E2281_5085_4F60_8002_5F79B2CAFFE3__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PopupWindow.h : header file +// + +class VSTPlugin; + +///////////////////////////////////////////////////////////////////////////// +// CPopupWindow frame + +class CPopupWindow : public CFrameWnd +{ + DECLARE_DYNCREATE(CPopupWindow) +// Attributes +public: + CPopupWindow(); + virtual ~CPopupWindow(); +// Operations +public: + void DoInit(); + void SetPlugin(VSTPlugin *p); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPopupWindow) + public: + //}}AFX_VIRTUAL + +// Implementation +protected: + + VSTPlugin *plug; + + // Generated message map functions + //{{AFX_MSG(CPopupWindow) + afx_msg void OnEnterIdle(UINT nWhy, CWnd* pWho); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnMove(int x, int y); + afx_msg void OnClose(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_POPUPWINDOW_H__7B1E2281_5085_4F60_8002_5F79B2CAFFE3__INCLUDED_) diff --git a/externals/grill/vst/src/Resource.h b/externals/grill/vst/src/Resource.h new file mode 100644 index 00000000..7fe29cea --- /dev/null +++ b/externals/grill/vst/src/Resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by VST.RC
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE 4000
+#define _APS_NEXT_CONTROL_VALUE 4000
+#define _APS_NEXT_SYMED_VALUE 4000
+#define _APS_NEXT_COMMAND_VALUE 32771
+#endif
+#endif
diff --git a/externals/grill/vst/src/StdAfx.cpp b/externals/grill/vst/src/StdAfx.cpp new file mode 100644 index 00000000..5a3a91f0 --- /dev/null +++ b/externals/grill/vst/src/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes
+// vst.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
diff --git a/externals/grill/vst/src/StdAfx.h b/externals/grill/vst/src/StdAfx.h new file mode 100644 index 00000000..ec2d51fb --- /dev/null +++ b/externals/grill/vst/src/StdAfx.h @@ -0,0 +1,42 @@ +// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__694C13F1_369D_446F_992D_3F454A0993C6__INCLUDED_)
+#define AFX_STDAFX_H__694C13F1_369D_446F_992D_3F454A0993C6__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxole.h> // MFC OLE classes
+#include <afxodlgs.h> // MFC OLE dialog classes
+#include <afxdisp.h> // MFC Automation classes
+#endif // _AFX_NO_OLE_SUPPORT
+
+
+#ifndef _AFX_NO_DB_SUPPORT
+#include <afxdb.h> // MFC ODBC database classes
+#endif // _AFX_NO_DB_SUPPORT
+
+#ifndef _AFX_NO_DAO_SUPPORT
+#include <afxdao.h> // MFC DAO database classes
+#endif // _AFX_NO_DAO_SUPPORT
+
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__694C13F1_369D_446F_992D_3F454A0993C6__INCLUDED_)
diff --git a/externals/grill/vst/src/VstHost.cpp b/externals/grill/vst/src/VstHost.cpp new file mode 100644 index 00000000..f0c3892b --- /dev/null +++ b/externals/grill/vst/src/VstHost.cpp @@ -0,0 +1,589 @@ +#include "stdafx.h" +#include "EditorThread.h" +#include "VstHost.h" +#include "PopupWindow.h" +#include "vst\aeffeditor.h" +#include "vst\aeffectx.h" + + +VstTimeInfo VSTPlugin::_timeInfo; + +float VSTPlugin::sample_rate = 44100; + + +extern "C" void post(char *fmt, ...); + +//////////////////// +// +///////////////////// +VSTPlugin::VSTPlugin(): + posx(0),posy(0) +{ + queue_size=0; + _sDllName = NULL; + h_dll=NULL; + instantiated=false; // Constructin' with no instance + overwrite = false; + w = GetForegroundWindow(); +// show_params = false; + _midichannel = 0; + edited = false; +} + +VSTPlugin::~VSTPlugin() +{ + Free(); // Call free + delete _sDllName; // if _sDllName = NULL , the operation does nothing -> it's safe. +} + +int VSTPlugin::Instance( const char *dllname) +{ + h_dll=LoadLibrary(dllname); + + if(h_dll==NULL) + { + return VSTINSTANCE_ERR_NO_VALID_FILE; + } + post("Loaded library %s" , dllname); + PVSTMAIN main = (PVSTMAIN)GetProcAddress(h_dll,"main"); + if(!main) + { + FreeLibrary(h_dll); + _pEffect=NULL; + instantiated=false; + return VSTINSTANCE_ERR_NO_VST_PLUGIN; + } + //post("Found main function - about to call it"); + //This calls the "main" function and receives the pointer to the AEffect structure. + _pEffect = main((audioMasterCallback)&(this->Master)); + + if(!_pEffect) + { + post("VST plugin : unable to create effect"); + FreeLibrary(h_dll); + _pEffect=NULL; + instantiated=false; + return VSTINSTANCE_ERR_REJECTED; + } + + if( _pEffect->magic!=kEffectMagic) + { + post("VST plugin : Instance query rejected by 0x%.8X\n",(int)_pEffect); + FreeLibrary(h_dll); + _pEffect=NULL; + instantiated=false; + return VSTINSTANCE_ERR_REJECTED; + } + + //post("VST plugin : Instanced at (Effect*): %.8X\n",(int)_pEffect); + + //init plugin + _pEffect->user = this; + Dispatch( effOpen , 0, 0, NULL, 0.0f); + Dispatch( effSetProgram , 0, 0, NULL, 0.0f); +// Dispatch( effMainsChanged, 0, 1, NULL, 0.0f); + + //************************************set samplerate and stream size here + // we get it when we init our DSP + +// Dispatch( effSetSampleRate, 0, 0, NULL, (float)Global::pConfig->_pOutputDriver->_samplesPerSec); +// Dispatch( effSetBlockSize, 0, STREAM_SIZE, NULL, 0.0f); + + + if (!Dispatch( effGetProductString, 0, 0, &_sProductName, 0.0f)) + { + CString str1(dllname); + CString str2 = str1.Mid(str1.ReverseFind('\\')+1); + int snip = str2.Find('.'); + if ( snip != -1 ) + { + str1 = str2.Left( snip ); + } + else + { + str1 = str2; + } + strcpy(_sProductName,str1); + + } + + if (!_pEffect->dispatcher(_pEffect, effGetVendorString, 0, 0, &_sVendorName, 0.0f)) + { + strcpy(_sVendorName, "Unknown vendor"); + } + _version = _pEffect->version; + _isSynth = (_pEffect->flags & effFlagsIsSynth)?true:false; + overwrite = (_pEffect->flags & effFlagsCanReplacing)?true:false; + editor = (_pEffect->flags & effFlagsHasEditor)?true:false; + + if ( _sDllName != NULL ) delete _sDllName; + _sDllName = new char[strlen(dllname)+1]; + sprintf(_sDllName,dllname); + + + + + //keep plugin name + instantiated=true; + + return VSTINSTANCE_NO_ERROR; +} + +int VSTPlugin::getNumInputs( void ) +{ + return _pEffect->numInputs; +} + +int VSTPlugin::getNumOutputs( void ) +{ + return _pEffect->numOutputs; +} + + +void VSTPlugin::Create(VSTPlugin *plug) +{ + h_dll=plug->h_dll; + _pEffect=plug->_pEffect; + _pEffect->user=this; + Dispatch( effMainsChanged, 0, 1, NULL, 0.0f); +// 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; +} + +void VSTPlugin::Free() // Called also in destruction +{ + if(instantiated) + { + instantiated=false; + post("VST plugin : Free query 0x%.8X\n",(int)_pEffect); + _pEffect->user = NULL; + Dispatch( effMainsChanged, 0, 0, NULL, 0.0f); + Dispatch( effClose, 0, 0, NULL, 0.0f); +// delete _pEffect; // <- Should check for the necessity of this command. + _pEffect=NULL; + FreeLibrary(h_dll); + } +} + +void VSTPlugin::Init( float samplerate , float blocksize ) +{ + sample_rate = samplerate; + Dispatch(effOpen , 0, 0, NULL, 0.f); + Dispatch(effMainsChanged, 0, 1, NULL, 0.f); + Dispatch(effSetSampleRate, 0, 0, 0, (float) sample_rate ); + Dispatch(effSetBlockSize, 0, blocksize, NULL, 0.f ); +} + + +bool VSTPlugin::DescribeValue(int p,char* psTxt) +{ + int parameter = p; + if(instantiated) + { + if(parameter<_pEffect->numParams) + { +// char par_name[64]; + char par_display[64]; + char par_label[64]; + +// Dispatch(effGetParamName,parameter,0,par_name,0.0f); + Dispatch(effGetParamDisplay,parameter,0,par_display,0.0f); + Dispatch(effGetParamLabel,parameter,0,par_label,0.0f); +// sprintf(psTxt,"%s:%s%s",par_name,par_display,par_label); + sprintf(psTxt,"%s%s",par_display,par_label); + return true; + } + else sprintf(psTxt,"NumParams Exeeded"); + } + else sprintf(psTxt,"Not loaded"); + + return false; +} + +bool VSTPlugin::SetParameter(int parameter, float value) +{ + if(instantiated) + { + if (( parameter >= 0 ) && (parameter<=_pEffect->numParams)) + { + _pEffect->setParameter(_pEffect,parameter,value); + return true; + } + } + + return false; +} + +bool VSTPlugin::SetParameter(int parameter, int value) +{ + return SetParameter(parameter,value/65535.0f); +} + +int VSTPlugin::GetCurrentProgram() +{ + if(instantiated) + return Dispatch(effGetProgram,0,0,NULL,0.0f); + else + return 0; +} + +void VSTPlugin::SetCurrentProgram(int prg) +{ + if(instantiated) + Dispatch(effSetProgram,0,prg,NULL,0.0f); +} + +bool VSTPlugin::AddMIDI(unsigned char data0,unsigned char data1,unsigned char data2) +{ + if (instantiated) + { + 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(/*instantiated &&*/ 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; + } +} + + +void VSTPlugin::processReplacing( float **inputs, float **outputs, long sampleframes ) +{ + _pEffect->processReplacing( _pEffect , inputs , outputs , sampleframes ); + +} + +void VSTPlugin::process( float **inputs, float **outputs, long sampleframes ) +{ + _pEffect->process( _pEffect , inputs , outputs , sampleframes ); +} + + +// Host callback dispatcher +long VSTPlugin::Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt) +{ + //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); + + // Support opcodes + switch(opcode) + { + case audioMasterAutomate: + return 0; // index, value, returns 0 + + case audioMasterVersion: + return 9; // vst version, currently 7 (0 for older) + + case audioMasterCurrentId: + return 'AASH'; // returns the unique id of a plug that's currently loading + + 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: + return false; // inquire if an input or output is beeing connected; + + 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 = sample_rate; + return (long)&_timeInfo; + + + case audioMasterTempoAt: + return 0; + + case audioMasterNeedIdle: + effect->dispatcher(effect, effIdle, 0, 0, NULL, 0.0f); + return 1; + + case audioMasterGetSampleRate: + return sample_rate; + + 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; + } + + + case audioMasterGetLanguage: + return kVstLangEnglish; + + case audioMasterUpdateDisplay: + post("audioMasterUpdateDisplay"); + effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f); + return 0; + + + case audioMasterSetTime: post("VST master dispatcher: Set Time");break; + case audioMasterGetNumAutomatableParameters: post("VST master dispatcher: GetNumAutPar");break; + case audioMasterGetParameterQuantization: post("VST master dispatcher: ParamQuant");break; + case audioMasterIOChanged: post("VST master dispatcher: IOchanged");break; + case audioMasterSizeWindow: post("VST master dispatcher: Size Window");break; + case audioMasterGetBlockSize: post("VST master dispatcher: GetBlockSize");break; + case audioMasterGetInputLatency: post("VST master dispatcher: GetInLatency");break; + case audioMasterGetOutputLatency: post("VST master dispatcher: GetOutLatency");break; + case audioMasterGetPreviousPlug: post("VST master dispatcher: PrevPlug");break; + case audioMasterGetNextPlug: post("VST master dispatcher: NextPlug");break; + case audioMasterWillReplaceOrAccumulate: post("VST master dispatcher: WillReplace"); break; + case audioMasterGetCurrentProcessLevel: return 0; break; + case audioMasterGetAutomationState: post("VST master dispatcher: GetAutState");break; + case audioMasterOfflineStart: post("VST master dispatcher: Offlinestart");break; + case audioMasterOfflineRead: post("VST master dispatcher: Offlineread");break; + case audioMasterOfflineWrite: post("VST master dispatcher: Offlinewrite");break; + case audioMasterOfflineGetCurrentPass: post("VST master dispatcher: OfflineGetcurrentpass");break; + case audioMasterOfflineGetCurrentMetaPass: post("VST master dispatcher: GetGetCurrentMetapass");break; + case audioMasterSetOutputSampleRate: post("VST master dispatcher: Setsamplerate");break; + case audioMasterGetSpeakerArrangement: post("VST master dispatcher: Getspeaker");break; + case audioMasterSetIcon: post("VST master dispatcher: seticon");break; + case audioMasterCanDo: post("VST master dispatcher: Can Do");break; + case audioMasterOpenWindow: post("VST master dispatcher: OpenWindow");break; + case audioMasterCloseWindow: post("VST master dispatcher: CloseWindow");break; + case audioMasterGetDirectory: post("VST master dispatcher: GetDirectory");break; +// case audioMasterUpdateDisplay: post("VST master dispatcher: audioMasterUpdateDisplay");break; + + default: post("VST master dispatcher: undefed: %d , %d",opcode , effKeysRequired ) ;break; + } + + return 0; +} + +bool VSTPlugin::AddNoteOn( unsigned char note,unsigned char speed,unsigned char midichannel) +{ + if(instantiated) + { + 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] = (char)MIDI_NOTEON | midichannel; // Midi On + pevent->midiData[1] = note; + pevent->midiData[2] = speed; + pevent->midiData[3] = 0; + + if ( queue_size < MAX_EVENTS ) queue_size++; + SendMidi(); + return true; + } + else + return false; +} + +bool VSTPlugin::AddNoteOff( unsigned char note,unsigned char midichannel) +{ + if (instantiated) + { + 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] = (char)MIDI_NOTEOFF | midichannel; // Midi Off + pevent->midiData[1] = note; + pevent->midiData[2] = 0; + pevent->midiData[3] = 0; + + if ( queue_size < MAX_EVENTS ) queue_size++; + + SendMidi(); + return true; + } + else + return false; +} + + +bool VSTPlugin::replace() +{ + return overwrite; +} + + +void VSTPlugin::edit(bool open) +{ + if(instantiated) { + if(open) { + if ( editor && !edited) { + edited = true; + b = new CEditorThread(); + b->SetPlugin( this); + b->CreateThread(); + } + } + else { + if (editor && edited) b->Close(); + } + } +} + +void VSTPlugin::visible(bool vis) +{ + if(instantiated && edited) b->Show(vis); +} + +void VSTPlugin::EditorIdle() +{ + Dispatch(effEditIdle,0,0, w,0.0f); +} + +RECT VSTPlugin::GetEditorRect() +{ + RECT ret; + ERect *r; + Dispatch(effEditGetRect,0,0, &r,0.0f); + ret.top = r->top; + ret.bottom = r->bottom; + ret.left = r->left; + ret.right = r->right; + return ret; +} + +void VSTPlugin::SetEditWindow(HWND h) +{ + w = h; + Dispatch(effEditOpen,0,0, w,0.0f); +} + +void VSTPlugin::OnEditorClose() +{ + Dispatch(effEditClose,0,0, w,0.0f); +} + +/* +void VSTPlugin::SetShowParameters(bool s) +{ + show_params = s; +} + +bool VSTPlugin::ShowParams() +{ + return show_params; +} +*/ + +void VSTPlugin::AddAftertouch(int value) +{ + if (value < 0) value = 0; else if (value > 127) value = 127; + AddMIDI( (char)MIDI_NOTEOFF | _midichannel , value ); +} + +void VSTPlugin::AddPitchBend(int value) +{ + AddMIDI( MIDI_PITCHBEND + (_midichannel & 0xf) , ((value>>7) & 127), (value & 127)); +} + +void VSTPlugin::AddProgramChange(int value) +{ + if (value < 0) value = 0; else if (value > 127) value = 127; + AddMIDI( MIDI_PROGRAMCHANGE + (_midichannel & 0xf), value, 0); +} + +void VSTPlugin::AddControlChange(int control, int value) +{ + if (control < 0) control = 0; else if (control > 127) control = 127; + if (value < 0) value = 0; else if (value > 127) value = 127; + AddMIDI( MIDI_CONTROLCHANGE + (_midichannel & 0xf), control, value); +} + + +bool VSTPlugin::GetProgramName( int cat , int p, char *buf) +{ + int parameter = p; + if(instantiated) + { + if(parameter<NumPrograms()) + { + Dispatch(effGetProgramNameIndexed,parameter,cat,buf,0.0f); + return true; + } + } + return false; +} + +int VSTPlugin::GetNumCategories() +{ + if(instantiated) + return Dispatch(effGetNumProgramCategories,0,0,NULL,0.0f); + else + return 0; +} + +void VSTPlugin::StopEditing() +{ + edited = false; +} diff --git a/externals/grill/vst/src/VstHost.h b/externals/grill/vst/src/VstHost.h new file mode 100644 index 00000000..60c793ab --- /dev/null +++ b/externals/grill/vst/src/VstHost.h @@ -0,0 +1,158 @@ +#ifndef _VSTPLUGIN_HOST +#define _VSTPLUGIN_HOST + +#include "Vst\AEffectx.h" +#include <afxcoll.h> +#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 + +typedef AEffect* (*PVSTMAIN)(audioMasterCallback audioMaster); +typedef HWND (*POPWIN)(void); +typedef HWND (*GETWIN)(void); + +class VSTPlugin +{ +public: + void StopEditing(); + int GetNumCategories(); + bool GetProgramName( int cat, int p , char* buf); + void AddControlChange( int control , int value ); + void AddProgramChange( int value ); + void AddPitchBend( int value ); + void AddAftertouch( int value ); + bool editor; + bool ShowParams(); + void SetShowParameters( bool s); + void OnEditorClose(); + void SetEditWindow( HWND h ); + CEditorThread* b; + RECT GetEditorRect(); + void EditorIdle(); + + void edit(bool open); + void visible(bool vis); + bool replace( ); + + VSTPlugin(); + ~VSTPlugin(); + + void Free(); + int Instance( const char *dllname); + void Create(VSTPlugin *plug); + void Init( float samplerate , float blocksize ); + + virtual int GetNumParams(void) { return _pEffect->numParams; } + virtual void GetParamName(int numparam,char* name) + { + if ( numparam < _pEffect->numParams ) Dispatch(effGetParamName,numparam,0,name,0.0f); + else strcpy(name,"Out of Range"); + + } + virtual void GetParamValue(int numparam,char* parval) + { + if ( numparam < _pEffect->numParams ) DescribeValue(numparam,parval); + else strcpy(parval,"Out of Range"); + } + virtual float GetParamValue(int numparam) + { + if ( numparam < _pEffect->numParams ) return (_pEffect->getParameter(_pEffect, numparam)); + else return -1.0; + } + + int getNumInputs( void ); + int getNumOutputs( void ); + + virtual char* GetName(void) { return _sProductName; } + unsigned long GetVersion() { return _version; } + char* GetVendorName(void) { return _sVendorName; } + char* GetDllName(void) { return _sDllName; } + + long NumParameters(void) { return _pEffect->numParams; } + float GetParameter(long parameter) { return _pEffect->getParameter(_pEffect, parameter); } + bool DescribeValue(int parameter,char* psTxt); + bool SetParameter(int parameter, float value); + bool SetParameter(int parameter, int value); + void SetCurrentProgram(int prg); + int GetCurrentProgram(); + int NumPrograms() { return _pEffect->numPrograms; } + bool IsSynth() { return _isSynth; } + + bool AddMIDI(unsigned char data0,unsigned char data1=0,unsigned char data2=0); + void SendMidi(); + + + void processReplacing( float **inputs, float **outputs, long sampleframes ); + void process( float **inputs, float **outputs, long sampleframes ); + + AEffect *_pEffect; + long Dispatch(long opCode, long index, long value, void *ptr, float opt) + { + return _pEffect->dispatcher(_pEffect, opCode, index, value, ptr, opt); + } + + static long Master(AEffect *effect, long opcode, long index, long value, void *ptr, float opt); + + bool AddNoteOn( unsigned char note,unsigned char speed,unsigned char midichannel=0); + bool AddNoteOff( unsigned char note,unsigned char midichannel=0); + + + char _midichannel; + bool instantiated; + int _instance; // Remove when Changing the FileFormat. + + HWND w; + + + void setPos(int x,int y) { posx = x; posy = y; } + void setX(int x) { posx = x; } + void setY(int y) { posy = y; } + int getX() const { return posx; } + int getY() const { return posy; } + + bool Edited() const { return edited; } + +protected: + + HMODULE h_dll; + HMODULE h_winddll; + + char _sProductName[64]; + char _sVendorName[64]; + char *_sDllName; // Contains dll name + ULONG _version; + bool _isSynth; + + float * inputs[MAX_INOUTS]; + float * outputs[MAX_INOUTS]; + float junk[256]; + + static VstTimeInfo _timeInfo; + VstMidiEvent midievent[MAX_EVENTS]; + VstEvents events; + int queue_size; + bool overwrite; + + + +private: + int posx,posy; + bool edited; + bool show_params; + static float sample_rate; +}; + + +#endif // _VSTPLUGIN_HOST
\ No newline at end of file diff --git a/externals/grill/vst/src/main.cpp b/externals/grill/vst/src/main.cpp new file mode 100644 index 00000000..fc4dd7d5 --- /dev/null +++ b/externals/grill/vst/src/main.cpp @@ -0,0 +1,692 @@ +/* + +vst - VST plugin object for PD +based on the work of mark@junklight.com + +Copyright (c)2003 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "main.h" +#include "vst.h" + +#include "EditorThread.h" +#include "VstHost.h" + +#include <stdlib.h> +#include <direct.h> +#include <io.h> + +#define VST_VERSION "0.1.0pre" + +#if 0 +/* ----- MFC stuff ------------- */ + +BEGIN_MESSAGE_MAP(CVstApp, CWinApp) + //{{AFX_MSG_MAP(CVstApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +CVstApp::CVstApp() {} + +CVstApp theApp; + +/* ----- MFC stuff ------------- */ +#endif + + +class vst: + public flext_dsp +{ + FLEXT_HEADER_S(vst,flext_dsp,Setup) + +public: + vst(I argc,const A *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); + + 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); } + + V ms_edit(BL on); + V mg_edit(BL &ed) { ed = plug && plug->Edited(); } + V ms_vis(BL vis); + + 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 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->NumPrograms():0; } + V mg_plugname(const S *&s) const { s = MakeSymbol(plug?plug->GetName():""); } + V mg_plugvendor(const S *&s) const { s = MakeSymbol(plug?plug->GetVendorName():""); } + V mg_plugdll(const S *&s) const { s = MakeSymbol(plug?plug->GetDllName():""); } + 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 m_control(const S *ctrl_name,I ctrl_value); + V m_pitchbend(I ctrl_value); + V m_programchange(I ctrl_value); + V m_ctrlchange(I control,I ctrl_value); + V m_note(I note,I vel); + + V ms_param(I pnum,F val); + V mg_param(I pnum); + V m_pname(I pnum); + V m_ptext(I pnum); + +private: + V display_parameter(I param,BL showparams); + + VSTPlugin *plug; + CString plugname; + BL echoparam,visible; + + I blsz; + V (VSTPlugin::*vstfun)(R **insigs,R **outsigs,L n); + BL sigmatch; + R **vstin,**vstout,**tmpin,**tmpout; + + V InitPlug(); + V ClearPlug(); + V InitBuf(); + V ClearBuf(); + static V Setup(t_classid); + + + FLEXT_CALLBACK_V(m_print) + + FLEXT_CALLVAR_V(mg_plug,ms_plug) + + FLEXT_CALLVAR_B(mg_edit,ms_edit) + FLEXT_CALLSET_B(ms_vis) + FLEXT_ATTRGET_B(visible) + +// FLEXT_CALLBACK_2(m_control,t_symptr,int) + FLEXT_CALLBACK_I(m_pitchbend) + FLEXT_CALLBACK_I(m_programchange) + FLEXT_CALLBACK_II(m_ctrlchange) + + FLEXT_CALLVAR_I(mg_program,ms_program) + FLEXT_CALLBACK_2(ms_param,int,float) + FLEXT_CALLBACK_I(mg_param) + FLEXT_CALLBACK_I(m_pname) + FLEXT_CALLBACK_I(m_ptext) + + FLEXT_CALLBACK_II(m_note) + + FLEXT_ATTRVAR_B(echoparam) + FLEXT_CALLVAR_I(mg_winx,ms_winx) + FLEXT_CALLVAR_I(mg_winy,ms_winy) + + FLEXT_CALLGET_I(mg_chnsin) + FLEXT_CALLGET_I(mg_chnsout) + FLEXT_CALLGET_I(mg_params) + FLEXT_CALLGET_I(mg_programs) + FLEXT_CALLGET_S(mg_plugname) + FLEXT_CALLGET_S(mg_plugvendor) + FLEXT_CALLGET_S(mg_plugdll) + FLEXT_CALLGET_I(mg_plugversion) + FLEXT_CALLGET_B(mg_issynth) +}; + +FLEXT_NEW_DSP_V("vst~",vst); + + +V vst::Setup(t_classid c) +{ +#if FLEXT_OS == FLEXT_OS_WIN + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxOleInit( ); +#endif + + post(""); + post("vst~ %s - VST plugin object, (C)2003 Thomas Grill",VST_VERSION); + post("based on the work of mark@junklight.com"); + post(""); + + FLEXT_CADDATTR_VAR(c,"plug",mg_plug,ms_plug); + FLEXT_CADDATTR_VAR(c,"edit",mg_edit,ms_edit); + FLEXT_CADDATTR_VAR(c,"vis",visible,ms_vis); + FLEXT_CADDMETHOD_(c,0,"print",m_print); + + FLEXT_CADDMETHOD_II(c,0,"note",m_note); +// FLEXT_CADDMETHOD_2(c,0,"control",m_control,t_symptr,int); + FLEXT_CADDMETHOD_(c,0,"pitchbend",m_pitchbend); + FLEXT_CADDMETHOD_II(c,0,"ctrlchange",m_ctrlchange); + + FLEXT_CADDMETHOD_(c,0,"programchange",m_programchange); + FLEXT_CADDATTR_VAR(c,"program",mg_program,ms_program); + + FLEXT_CADDMETHOD_2(c,0,"param",ms_param,int,float); + FLEXT_CADDMETHOD_(c,0,"getparam",mg_param); + FLEXT_CADDMETHOD_I(c,0,"getpname",m_pname); + FLEXT_CADDMETHOD_I(c,0,"getptext",m_ptext); + + 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_GET(c,"ins",mg_chnsin); + FLEXT_CADDATTR_GET(c,"outs",mg_chnsout); + FLEXT_CADDATTR_GET(c,"params",mg_params); + FLEXT_CADDATTR_GET(c,"programs",mg_programs); + FLEXT_CADDATTR_GET(c,"name",mg_plugname); + FLEXT_CADDATTR_GET(c,"vendor",mg_plugvendor); + FLEXT_CADDATTR_GET(c,"dll",mg_plugdll); + FLEXT_CADDATTR_GET(c,"version",mg_plugversion); + FLEXT_CADDATTR_GET(c,"synth",mg_issynth); +} + + +vst::vst(I argc,const A *argv): + plug(NULL),visible(false), + blsz(0), + vstfun(NULL),vstin(NULL),vstout(NULL),tmpin(NULL),tmpout(NULL), + echoparam(false) +{ + if(argc >= 2 && CanbeInt(argv[0]) && CanbeInt(argv[1])) { + AddInSignal(GetAInt(argv[0])); + AddOutSignal(GetAInt(argv[1])); + + if(!ms_plug(argc-2,argv+2)) InitProblem(); + } + else { + post("%s - syntax: vst~ inputs outputs [plug]",thisName()); + InitProblem(); + } +} + +vst::~vst() +{ + ClearPlug(); +} + +V vst::ClearPlug() +{ + if(plug) { + ClearBuf(); + delete plug; plug = NULL; + } +} + +V vst::InitPlug() +{ + FLEXT_ASSERT(plug); + + vstfun = plug->replace()?plug->processReplacing:plug->process; + sigmatch = plug->getNumInputs() == CntInSig() && plug->getNumOutputs() == CntOutSig(); + + InitBuf(); +} + +V vst::ClearBuf() +{ + if(!plug) return; + + if(vstin) { + for(I i = 0; i < plug->getNumInputs(); ++i) delete[] vstin[i]; + delete[] vstin; vstin = NULL; + delete[] tmpin; tmpin = NULL; + } + if(vstout) { + for(I i = 0; i < plug->getNumOutputs(); ++i) delete[] vstout[i]; + delete[] vstout; vstout = NULL; + delete[] tmpout; tmpout = NULL; + } +} + +V vst::InitBuf() +{ + FLEXT_ASSERT(!vstin && !tmpin && !vstout && !tmpout); + + I i; + + vstin = new R *[plug->getNumInputs()]; + tmpin = new R *[plug->getNumInputs()]; + for(i = 0; i < plug->getNumInputs(); ++i) vstin[i] = new R[Blocksize()]; + + vstout = new R *[plug->getNumOutputs()]; + tmpout = new R *[plug->getNumOutputs()]; + for(i = 0; i < plug->getNumOutputs(); ++i) vstout[i] = new R[Blocksize()]; +} + +static const C *findFilePath(const C *path,const C *dllname) +{ + CFileFind finder; + _chdir( path ); + + if(finder.FindFile( dllname )) + return path; + else { + finder.FindFile(); + while(finder.FindNextFile()) { + if(finder.IsDirectory()) { + if(!finder.IsDots()) { + CString *npath = new CString( finder.GetFilePath()); + const C *ret = findFilePath( *npath , dllname ); + if(ret) { + CString *retstr = new CString(ret); + return *retstr; + } + } + } + } + } + return NULL; +} + + +BL vst::ms_plug(I argc,const A *argv) +{ + ClearPlug(); + + plugname.Empty(); + C buf[255]; + for(I i = 0; i < argc; i++) { + if(i > 0) plugname += ' '; + GetAString(argv[i],buf,sizeof buf); + plugname += buf; + } + plugname.MakeLower(); + if(!plugname.GetLength()) return false; + + 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; + + // try loading the dll from the raw filename + if (plug->Instance(plugname) == VSTINSTANCE_NO_ERROR) { + //post( "it loaded fine "); + lf = true; + } + + if(!lf) { // try finding it on the PD path + C *name,dir[1024]; + I fd = open_via_path("",plugname,".dll",dir,&name,sizeof(dir)-1,0); + if(fd > 0) close(fd); + else name = NULL; + + // if dir is current working directory... name points to dir + if(dir == name) strcpy(dir,"."); + + CString dllname(dir); + dllname += "\\"; + dllname += name; + + lf = plug->Instance(dllname) == VSTINSTANCE_NO_ERROR; + } + + if(!lf) { // try finding it on the VST path + C *vst_path = getenv ("VST_PATH"); + + CString dllname(plugname); + if(dllname.Find(".dll") == -1) dllname += ".dll"; + + if(vst_path) { + char* tok_path = new C[strlen( vst_path)+1]; + strcpy( tok_path , vst_path); + char *tok = strtok( tok_path , ";" ); + while( tok != NULL ) { + CString abpath( tok ); + if( abpath.Right( 1 ) != _T("\\") ) abpath += "\\"; + + const char * realpath = findFilePath( abpath , dllname ); + //post( "findFilePath( %s , %s ) = %s\n" , abpath , dllname , realpath ); + if ( realpath != NULL ) { + CString rpath( realpath ); + rpath += _T("\\") + plugname; + post( "trying %s " , rpath ); + if(plug->Instance( rpath ) == VSTINSTANCE_NO_ERROR ) { +// post("%s - plugin '%s' loaded ",thisName(),plug->GetName()); + lf = true; + break; + } + } + + tok = strtok( NULL , ";" ); + if(!tok) post("%s - couldn't find plugin",thisName()); + } + + delete[] tok_path; + } + } + + if(!lf) { // failed - don't make any ins or outs + post("%s - unable to load plugin '%s'",thisName(),plugname); + ClearPlug(); + } + + // re-init dsp stuff + InitPlug(); + + return lf; +} + +V vst::m_dsp(I n,t_signalvec const *,t_signalvec const *) +{ + if(plug) { + plug->Init(Samplerate(),(F)Blocksize()); + FLEXT_ASSERT(vstfun); + + if(blsz != Blocksize()) { + blsz = Blocksize(); + ClearBuf(); + InitBuf(); + } + } +} + +V vst::m_signal(I n,R *const *insigs,R *const *outsigs) +{ + if(plug) { + if(sigmatch) + (plug->*vstfun)(const_cast<R **>(insigs),const_cast<R **>(outsigs),n); + else { + R **inv,**outv; + + if(plug->getNumInputs() <= CntInSig()) + inv = const_cast<R **>(insigs); + else { // more plug inputs than inlets + I i; + for(i = 0; i < CntInSig(); ++i) tmpin[i] = const_cast<R *>(insigs[i]); + + // set dangling inputs to zero + // according to mode... (e.g. set zero) + for(; i < plug->getNumInputs(); ++i) ZeroSamples(tmpin[i] = vstin[i],n); + + inv = tmpin; + } + + const BL more = plug->getNumOutputs() <= CntOutSig(); + if(more) // more outlets than plug outputs + outv = const_cast<R **>(outsigs); + else { + I i; + for(i = 0; i < CntOutSig(); ++i) tmpout[i] = outsigs[i]; + for(; i < plug->getNumOutputs(); ++i) tmpout[i] = vstout[i]; + + outv = tmpout; + } + + (plug->*vstfun)(inv,outv,n); + + if(more) { + // according to mode set dangling output vectors + } + } + } + else + flext_dsp::m_signal(n,insigs,outsigs); +} + + +#if 0 + +V vst::m_control(const S *ctrl_name,I ctrl_value) +{ + if(!plug) return; + + I 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 + +V vst::m_pitchbend(I ctrl_value) +{ + if(plug) plug->AddPitchBend(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); +} + +V vst::m_ctrlchange(I control,I ctrl_value) +{ + if(plug) plug->AddControlChange(control,ctrl_value ); +} + + + /** + * display the parameters names and values and some other bits and pieces that + * may be of use + */ + +V vst::m_print(I ac,const A *av) +{ + if(!plug) return; + + int i; + bool params = false; + bool header = true; + bool programs = false; + bool parameters = true; + int specific = -1; + if( ac > 0 ) { + for( i = 0 ; i < ac ; i++) { + if(IsString(av[i])) { + const C *buf = GetString(av[i]); + if ( strcmp( buf , "-params" ) == 0 ) { + params = true; + } + else if ( strcmp( buf , "-noheader" ) == 0 ) { + header = false; + } + else if ( strcmp( buf , "-programs" ) == 0 ) { + programs = true; + parameters = false; + } + else if ( strcmp( buf , "-parameters" ) == 0 ) { + parameters = false; + } + else if ( strcmp( buf , "-help" ) == 0 ) { + post("print options:"); + post("-help \t\tprint this"); + post("-programs \tshow the programs"); + post("-parameters \tshow the parameters"); + post("-params \tshow the parameter display values"); + post("-noheader \tdo not display the header"); + return; + } + } + else if(CanbeInt(av[i])) { + int p = GetAInt(av[i]); + if (( p > 0 ) && ( p <= plug->GetNumParams())) { + specific = p - 1; + } + } + } + } + + if ( header ) { + post("VST~ plugin: %s " , plug->GetName() ); + post("made by: %s " , plug->GetVendorName() ); + post("parameterss %d\naudio: %d in(s)/%d out(s) \nLoaded from library \"%s\".\n", + plug->GetNumParams(), + CntInSig(), + CntOutSig(), + plug->GetDllName()); + + post("Flags"); + if ( plug->_pEffect->flags & effFlagsHasEditor ) { + post("Has editor"); + } + if ( plug->_pEffect->flags & effFlagsCanReplacing ) { + post("Can do replacing"); + } + } + + if ( parameters ) { + if ( specific == -1) { + for (i = 0; i < plug->GetNumParams(); i++) + display_parameter( i , params ); + } + else + display_parameter( specific , params); + } + + if( programs ) { + for( int j = 0; j < plug->GetNumCategories() ; j++ ) { + for( i = 0 ; i < plug->GetNumParams() ; i++ ) { + char buf[64]; + plug->GetProgramName( j , i , buf ); + post("Program %d: %s ", i , buf ); + } + } + } +} + + +//! display an editor +V vst::ms_edit(BL on) +{ +#if FLEXT_OS == FLEXT_OS_WIN + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +#endif + + if(plug) plug->edit(on); +} + +V vst::ms_vis(BL vis) +{ +#if FLEXT_OS == FLEXT_OS_WIN + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +#endif + + if(plug) plug->visible(vis); +} + + +V vst::display_parameter(I param,BL showparams) +{ + int j = param; + /* the Steinberg(tm) way... */ + char name[109]; + char display[164]; + float val; + +// if(j == 0) post ("Control input/output(s):"); + + memset (name, 0, sizeof(name)); + memset( display, 0 ,sizeof(display)); + plug->GetParamName( j , name ); + + if(*name) { + if (showparams) { + plug->DescribeValue( j , display ); + val = plug->GetParamValue( j ); + post ("parameter[#%d], \"%s\" value=%f (%s) ", j, name, val,display); + } + else { + val = plug->GetParamValue( j ); + post ("parameter[#%d], \"%s\" value=%f ", j, name, val); + } + } +} + + +// set the value of a parameter +V vst::ms_param(I pnum,F val) +{ + if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; + + F xval = plug->GetParamValue( pnum ); +// if(xval <= 1.0f) // What's that???? + if(true) + { + plug->SetParameter( pnum, val ); + if(echoparam) display_parameter(pnum , true ); + } + else + FLEXT_ASSERT(false); +} + +V vst::mg_param(I pnum) +{ + if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; + + A at[2]; + SetInt(at[0],pnum); + SetFloat(at[1],plug->GetParamValue(pnum)); + ToOutAnything(GetOutAttr(),MakeSymbol("param"),2,at); +} + +V vst::m_pname(I pnum) +{ + if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; + + C name[109]; /* the Steinberg(tm) way... */ + + memset(name,0,sizeof(name)); + plug->GetParamName(pnum,name); + + A at[2]; + SetInt(at[0],pnum); + SetString(at[1],name); + ToOutAnything(GetOutAttr(),MakeSymbol("pname"),2,at); +} + +V vst::m_ptext(I pnum) +{ + if(!plug || pnum < 0 || pnum >= plug->GetNumParams()) return; + + C display[164]; /* the Steinberg(tm) way... */ + + memset(display,0,sizeof(display)); + plug->DescribeValue(pnum,display); + + A at[2]; + SetInt(at[0],pnum); + SetString(at[1],display); + ToOutAnything(GetOutAttr(),MakeSymbol("ptext"),2,at); +} + +V vst::m_note(I note,I velocity) +{ + if(!plug) return; + + if(velocity > 0) + plug->AddNoteOn(note,velocity); + else + plug->AddNoteOff(note); +} diff --git a/externals/grill/vst/src/main.h b/externals/grill/vst/src/main.h new file mode 100644 index 00000000..1f24d56b --- /dev/null +++ b/externals/grill/vst/src/main.h @@ -0,0 +1,40 @@ +/*
+
+vst - VST plugin object for PD
+based on the work of mark@junklight.com
+
+Copyright (c) 2003 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+#ifndef __VST_H
+#define __VST_H
+
+#define FLEXT_ATTRIBUTES 1
+
+#include <flext.h>
+
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 402)
+#error You need at least flext version 0.4.2
+#endif
+
+#if FLEXT_OS == FLEXT_OS_WIN
+#include "stdafx.h"
+#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.h b/externals/grill/vst/src/vst.h new file mode 100644 index 00000000..098fc67e --- /dev/null +++ b/externals/grill/vst/src/vst.h @@ -0,0 +1,46 @@ +// vst.h : main header file for the VST DLL
+//
+
+#if !defined(AFX_VST_H__013CDC75_CDE8_40AD_AE29_D952471B07F5__INCLUDED_)
+#define AFX_VST_H__013CDC75_CDE8_40AD_AE29_D952471B07F5__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CVstApp
+// See vst.cpp for the implementation of this class
+//
+
+class CVstApp : public CWinApp
+{
+public:
+ CVstApp();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CVstApp)
+ //}}AFX_VIRTUAL
+
+ //{{AFX_MSG(CVstApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_VST_H__013CDC75_CDE8_40AD_AE29_D952471B07F5__INCLUDED_)
+
diff --git a/externals/grill/vst/src/vst.rc b/externals/grill/vst/src/vst.rc new file mode 100644 index 00000000..10f6f46a --- /dev/null +++ b/externals/grill/vst/src/vst.rc @@ -0,0 +1,143 @@ +//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Englisch (USA) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "vst~ external\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "vst~\0"
+ VALUE "LegalCopyright", "Copyright (C) 2003\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "vst~.DLL\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "VST plugin object\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+#endif // Englisch (USA) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Deutsch (Österreich) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA)
+#ifdef _WIN32
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif //_WIN32\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Deutsch (Österreich) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/externals/grill/vst/src/vst/AEffEditor.h b/externals/grill/vst/src/vst/AEffEditor.h new file mode 100644 index 00000000..7bbf9102 --- /dev/null +++ b/externals/grill/vst/src/vst/AEffEditor.h @@ -0,0 +1,44 @@ +#ifndef __AEffEditor__ +#define __AEffEditor__ + +class AudioEffect; + +struct ERect +{ + short top; + short left; + short bottom; + short right; +}; + +class AEffEditor +{ +public: + AEffEditor (AudioEffect *effect) {this->effect = effect; updateFlag = 0; } + virtual ~AEffEditor() {} + + virtual long getRect(ERect **rect) {*rect = 0; return 0;} + virtual long open(void *ptr) {systemWindow = ptr; return 0;} + virtual void close() {} + virtual void idle() { if(updateFlag) {updateFlag = 0; update();} } + +#if MAC + virtual void draw(ERect *rect) {rect = rect;} + virtual long mouse(long x, long y) {x = x; y = y; return 0;} + virtual long key(long keyCode) {keyCode = keyCode; return 0;} + virtual void top() {} + virtual void sleep() {} +#endif + virtual void update() {} + virtual void postUpdate() {updateFlag = 1;} + +protected: + AEffEditor () {}; + + AudioEffect *effect; + void *systemWindow; + long updateFlag; +}; + +#endif + diff --git a/externals/grill/vst/src/vst/AEffect.h b/externals/grill/vst/src/vst/AEffect.h new file mode 100644 index 00000000..e1254612 --- /dev/null +++ b/externals/grill/vst/src/vst/AEffect.h @@ -0,0 +1,172 @@ +#ifndef __AEffect__ +#define __AEffect__ + +/* + to create an Audio Effect for power pc's, create a + code resource + file type: 'aPcs' + resource type: 'aEff' + ppc header: none (raw pef) + + for windows, it's a .dll + + the only symbol searched for is: + AEffect *main(float (*audioMaster)(AEffect *effect, long opcode, long index, + long value, void *ptr, float opt)); +*/ + +#if PRAGMA_ALIGN_SUPPORTED || __MWERKS__ + #pragma options align=mac68k +#elif defined CBUILDER + #pragma -a8 +#elif defined(WIN32) || defined(__FLAT__) + #pragma pack(push) + #pragma pack(8) +#endif + +#if defined(WIN32) || defined(__FLAT__) || defined CBUILDER + #define VSTCALLBACK __cdecl +#else + #define VSTCALLBACK +#endif + +//--------------------------------------------------------------------------------------------- +// misc def's +//--------------------------------------------------------------------------------------------- + +typedef struct AEffect AEffect; +typedef long (VSTCALLBACK *audioMasterCallback)(AEffect *effect, long opcode, long index, + long value, void *ptr, float opt); + +// prototype for plug-in main +// AEffect *main(audioMasterCallback audioMaster); + +#ifdef CBUILDER + #define kEffectMagic 'PtsV' +#else + #define kEffectMagic 'VstP' +#endif + +//--------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------- + +struct AEffect +{ + long magic; // must be kEffectMagic ('VstP') + long (VSTCALLBACK *dispatcher)(AEffect *effect, long opCode, long index, long value, + void *ptr, float opt); + void (VSTCALLBACK *process)(AEffect *effect, float **inputs, float **outputs, long sampleframes); + void (VSTCALLBACK *setParameter)(AEffect *effect, long index, float parameter); + float (VSTCALLBACK *getParameter)(AEffect *effect, long index); + + long numPrograms; + long numParams; // all programs are assumed to have numParams parameters + long numInputs; // + long numOutputs; // + long flags; // see constants + long resvd1; // reserved, must be 0 + long resvd2; // reserved, must be 0 + long initialDelay; // for algorithms which need input in the first place + long realQualities; // number of realtime qualities (0: realtime) + long offQualities; // number of offline qualities (0: realtime only) + float ioRatio; // input samplerate to output samplerate ratio, not used yet + void *object; // for class access (see AudioEffect.hpp), MUST be 0 else! + void *user; // user access + long uniqueID; // pls choose 4 character as unique as possible. + // this is used to identify an effect for save+load + long version; // + void (VSTCALLBACK *processReplacing)(AEffect *effect, float **inputs, float **outputs, long sampleframes); + char future[60]; // pls zero +}; + + +//--------------------------------------------------------------------------------------------- +// flags bits +//--------------------------------------------------------------------------------------------- + +#define effFlagsHasEditor 1 // if set, is expected to react to editor messages +#define effFlagsHasClip 2 // return > 1. in getVu() if clipped +#define effFlagsHasVu 4 // return vu value in getVu(); > 1. means clipped +#define effFlagsCanMono 8 // if numInputs == 2, makes sense to be used for mono in +#define effFlagsCanReplacing 16 // supports in place output (processReplacing() exsists) +#define effFlagsProgramChunks 32 // program data are handled in formatless chunks + +//--------------------------------------------------------------------------------------------- +// dispatcher opCodes +//--------------------------------------------------------------------------------------------- + +enum +{ + effOpen = 0, // initialise + effClose, // exit, release all memory and other resources! + + effSetProgram, // program no in <value> + effGetProgram, // return current program no. + effSetProgramName, // user changed program name (max 24 char + 0) to as passed in string + effGetProgramName, // stuff program name (max 24 char + 0) into string + + effGetParamLabel, // stuff parameter <index> label (max 8 char + 0) into string + // (examples: sec, dB, type) + effGetParamDisplay, // stuff parameter <index> textual representation into string + // (examples: 0.5, -3, PLATE) + effGetParamName, // stuff parameter <index> label (max 8 char + 0) into string + // (examples: Time, Gain, RoomType) + effGetVu, // called if (flags & (effFlagsHasClip | effFlagsHasVu)) + + // system + + effSetSampleRate, // in opt (float) + effSetBlockSize, // in value + effMainsChanged, // the user has switched the 'power on' button to + // value (0 off, else on). This only switches audio + // processing; you should flush delay buffers etc. + // editor + + effEditGetRect, // stuff rect (top, left, bottom, right) into ptr + effEditOpen, // system dependant Window pointer in ptr + effEditClose, // no arguments + effEditDraw, // draw method, ptr points to rect + effEditMouse, // index: x, value: y + effEditKey, // system keycode in value + effEditIdle, // no arguments. Be gentle! + effEditTop, // window has topped, no arguments + effEditSleep, // window goes to background + + // new + + effIdentify, // returns 'NvEf' + effGetChunk, // host requests pointer to chunk into (void**)ptr, byteSize returned + effSetChunk, // plug-in receives saved chunk, byteSize passed + + effNumOpcodes +}; + +//--------------------------------------------------------------------------------------------- +// audioMaster opCodes +//--------------------------------------------------------------------------------------------- + +enum +{ + audioMasterAutomate = 0, // index, value, returns 0 + audioMasterVersion, // vst version, currently 2 (0 for older) + audioMasterCurrentId, // returns the unique id of a plug that's currently + // loading + audioMasterIdle, // call application idle routine (this will + // call effEditIdle for all open editors too) + audioMasterPinConnected // inquire if an input or output is beeing connected; + // index enumerates input or output counting from zero, + // value is 0 for input and != 0 otherwise. note: the + // return value is 0 for <true> such that older versions + // will always return true. + +}; + +#if PRAGMA_ALIGN_SUPPORTED || __MWERKS__ + #pragma options align=reset +#elif defined(WIN32) || defined(__FLAT__) + #pragma pack(pop) +#elif defined CBUILDER + #pragma -a- +#endif + +#endif // __AEffect__ diff --git a/externals/grill/vst/src/vst/AEffectx.h b/externals/grill/vst/src/vst/AEffectx.h new file mode 100644 index 00000000..e694c1e1 --- /dev/null +++ b/externals/grill/vst/src/vst/AEffectx.h @@ -0,0 +1,534 @@ +#ifndef __aeffectx__ +#define __aeffectx__ + +#ifndef __AEffect__ +#include "AEffect.h" +#endif + +//------------------------------------------------------------------------------------------------------- +// VST Plug-Ins SDK +// version 2.0 extension +// (c)1999 Steinberg Soft+Hardware GmbH +//------------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------------- +// VstEvent +//------------------------------------------------------------------------------------------------------- + +typedef struct VstEvent VstEvent; +typedef struct VstMidiEvent VstMidiEvent; +typedef struct VstEvents VstEvents; + +struct VstEvent // a generic timestamped event +{ + long type; // see enum below + long byteSize; // of this event, excl. type and byteSize + long deltaFrames; // sample frames related to the current block start sample position + long flags; // generic flags, none defined yet (0) + + char data[16]; // size may vary but is usually 16 +}; + +enum // VstEvent types +{ + kVstMidiType = 1, // midi event, can be cast as VstMidiEvent (see below) + kVstAudioType, // audio + kVstVideoType, // video + kVstParameterType, // parameter + kVstTriggerType // trigger + // ...etc +}; + +struct VstMidiEvent // to be casted from a VstEvent +{ + long type; // kVstMidiType + long byteSize; // 24 + long deltaFrames; // sample frames related to the current block start sample position + long flags; // none defined yet + + long noteLength; // (in sample frames) of entire note, if available, else 0 + long noteOffset; // offset into note from note start if available, else 0 + + char midiData[4]; // 1 thru 3 midi bytes; midiData[3] is reserved (zero) + char detune; // -64 to +63 cents; for scales other than 'well-tempered' ('microtuning') + char noteOffVelocity; + char reserved1; // zero + char reserved2; // zero +}; + +struct VstEvents // a block of events for the current audio block +{ + long numEvents; + long reserved; // zero + VstEvent* events[2]; // variable +}; + +//------------------------------------------------------------------------------------------------------- +// VstTimeInfo +//------------------------------------------------------------------------------------------------------- + +typedef struct VstTimeInfo VstTimeInfo; + +// VstTimeInfo as requested via audioMasterGetTime (getTimeInfo()) +// refers to the current time slice. note the new slice is +// already started when processEvents() is called + +struct VstTimeInfo +{ + double samplePos; // current location + double sampleRate; + double nanoSeconds; // system time + double ppqPos; // 1 ppq + double tempo; // in bpm + double barStartPos; // last bar start, in 1 ppq + double cycleStartPos; // 1 ppq + double cycleEndPos; // 1 ppq + long timeSigNumerator; // time signature + long timeSigDenominator; + long smpteOffset; + long smpteFrameRate; // 0:24, 1:25, 2:29.97, 3:30, 4:29.97 df, 5:30 df + long samplesToNextClock; // midi clock resolution (24 ppq), can be negative + long flags; // see below +}; + +enum +{ + kVstTransportChanged = 1, + kVstTransportPlaying = 1 << 1, + kVstTransportCycleActive = 1 << 2, + + kVstAutomationWriting = 1 << 6, + kVstAutomationReading = 1 << 7, + + // flags which indicate which of the fields in this VstTimeInfo + // are valid; samplePos and sampleRate are always valid + kVstNanosValid = 1 << 8, + kVstPpqPosValid = 1 << 9, + kVstTempoValid = 1 << 10, + kVstBarsValid = 1 << 11, + kVstCyclePosValid = 1 << 12, // start and end + kVstTimeSigValid = 1 << 13, + kVstSmpteValid = 1 << 14, + kVstClockValid = 1 << 15 +}; + +//------------------------------------------------------------------------------------------------------- +// VarIo +//------------------------------------------------------------------------------------------------------- + +typedef struct VstVariableIo VstVariableIo; + +struct VstVariableIo +{ + float **inputs; + float **outputs; + long numSamplesInput; + long numSamplesOutput; + long *numSamplesInputProcessed; + long *numSamplesOutputProcessed; +}; + +//--------------------------------------------------------------------------------------------- +// new audioMaster opCodes +//--------------------------------------------------------------------------------------------- + +enum +{ + // VstEvents + VstTimeInfo + audioMasterWantMidi = audioMasterPinConnected + 2, // <value> is a filter which is currently ignored + audioMasterGetTime, // returns const VstTimeInfo* (or 0 if not supported) + // <value> should contain a mask indicating which fields are required + // (see valid masks above), as some items may require extensive + // conversions + audioMasterProcessEvents, // VstEvents* in <ptr> + audioMasterSetTime, // VstTimenfo* in <ptr>, filter in <value>, not supported + audioMasterTempoAt, // returns tempo (in bpm * 10000) at sample frame location passed in <value> + + // parameters + audioMasterGetNumAutomatableParameters, + audioMasterGetParameterQuantization, // returns the integer value for +1.0 representation, + // or 1 if full single float precision is maintained + // in automation. parameter index in <value> (-1: all, any) + // connections, configuration + audioMasterIOChanged, // numInputs and/or numOutputs has changed + audioMasterNeedIdle, // plug needs idle calls (outside its editor window) + audioMasterSizeWindow, // index: width, value: height + audioMasterGetSampleRate, + audioMasterGetBlockSize, + audioMasterGetInputLatency, + audioMasterGetOutputLatency, + audioMasterGetPreviousPlug, // input pin in <value> (-1: first to come), returns cEffect* + audioMasterGetNextPlug, // output pin in <value> (-1: first to come), returns cEffect* + + // realtime info + audioMasterWillReplaceOrAccumulate, // returns: 0: not supported, 1: replace, 2: accumulate + audioMasterGetCurrentProcessLevel, // returns: 0: not supported, + // 1: currently in user thread (gui) + // 2: currently in audio thread (where process is called) + // 3: currently in 'sequencer' thread (midi, timer etc) + // 4: currently offline processing and thus in user thread + // other: not defined, but probably pre-empting user thread. + audioMasterGetAutomationState, // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write + + // offline + audioMasterOfflineStart, + audioMasterOfflineRead, // ptr points to offline structure, see below. return 0: error, 1 ok + audioMasterOfflineWrite, // same as read + audioMasterOfflineGetCurrentPass, + audioMasterOfflineGetCurrentMetaPass, + + // other + audioMasterSetOutputSampleRate, // for variable i/o, sample rate in <opt> + audioMasterGetSpeakerArrangement, // (long)input in <value>, output in <ptr> + audioMasterGetVendorString, // fills <ptr> with a string identifying the vendor (max 64 char) + audioMasterGetProductString, // fills <ptr> with a string with product name (max 64 char) + audioMasterGetVendorVersion, // returns vendor-specific version + audioMasterVendorSpecific, // no definition, vendor specific handling + audioMasterSetIcon, // void* in <ptr>, format not defined yet + audioMasterCanDo, // string in ptr, see below + audioMasterGetLanguage, // see enum + audioMasterOpenWindow, // returns platform specific ptr + audioMasterCloseWindow, // close window, platform specific handle in <ptr> + audioMasterGetDirectory, // get plug directory, FSSpec on MAC, else char* + audioMasterUpdateDisplay // something has changed, update 'multi-fx' display +}; + +enum VstHostLanguage +{ + kVstLangEnglish = 1, + kVstLangGerman, + kVstLangFrench, + kVstLangItalian, + kVstLangSpanish, + kVstLangJapanese +}; + +//--------------------------------------------------------------------------------------------- +// dispatcher opCodes +//--------------------------------------------------------------------------------------------- + +enum +{ + // VstEvents + effProcessEvents = effSetChunk + 1, // VstEvents* in <ptr> + + // parameters and programs + effCanBeAutomated, // parameter index in <index> + effString2Parameter, // parameter index in <index>, string in <ptr> + effGetNumProgramCategories, // no arguments. this is for dividing programs into groups (like GM) + effGetProgramNameIndexed, // get program name of category <value>, program <index> into <ptr>. + // category (that is, <value>) may be -1, in which case program indices + // are enumerated linearily (as usual); otherwise, each category starts + // over with index 0. + effCopyProgram, // copy current program to destination <index> + // note: implies setParameter + // connections, configuration + effConnectInput, // input at <index> has been (dis-)connected; + // <value> == 0: disconnected, else connected + effConnectOutput, // same as input + effGetInputProperties, // <index>, VstPinProperties* in ptr, return != 0 => true + effGetOutputProperties, // dto + effGetPlugCategory, // no parameter, return value is category + + // realtime + effGetCurrentPosition, // for external dsp, see flag bits below + effGetDestinationBuffer, // for external dsp, see flag bits below. returns float* + + // offline + effOfflineNotify, // ptr = VstAudioFile array, value = count, index = start flag + effOfflinePrepare, // ptr = VstOfflineTask array, value = count + effOfflineRun, // dto + + // other + effProcessVarIo, // VstVariableIo* in <ptr> + effSetSpeakerArrangement, // VstSpeakerArrangement* pluginInput in <value> + // VstSpeakerArrangement* pluginOutput in <ptr> + effSetBlockSizeAndSampleRate, // block size in <value>, sampleRate in <opt> + effSetBypass, // onOff in <value> (0 = off) + effGetEffectName, // char* name (max 32 bytes) in <ptr> + effGetErrorText, // char* text (max 256 bytes) in <ptr> + effGetVendorString, // fills <ptr> with a string identifying the vendor (max 64 char) + effGetProductString, // fills <ptr> with a string with product name (max 64 char) + effGetVendorVersion, // returns vendor-specific version + effVendorSpecific, // no definition, vendor specific handling + effCanDo, // <ptr> + effGetTailSize, // returns tail size; 0 is default (return 1 for 'no tail') + effIdle, // idle call in response to audioMasterneedIdle. must + // return 1 to keep idle calls beeing issued + + // gui + effGetIcon, // void* in <ptr>, not yet defined + effSetViewPosition, // set view position (in window) to x <index> y <value> + + // and... + effGetParameterProperties, // of param <index>, VstParameterProperties* in <ptr> + effKeysRequired, // returns 0: needs keys (default for 1.0 plugs), 1: don't need + effGetVstVersion, // returns 2; older versions return 0 + + effNumV2Opcodes + // note that effNumOpcodes doesn't apply anymore +}; + +typedef struct VstParameterProperties VstParameterProperties; +typedef struct VstPinProperties VstPinProperties; + +struct VstParameterProperties +{ + float stepFloat; + float smallStepFloat; + float largeStepFloat; + char label[64]; + long flags; + long minInteger; + long maxInteger; + long stepInteger; + long largeStepInteger; + char shortLabel[8]; // recommended: 6 + delimiter + char future[48]; +}; + +// parameter properties flags +enum +{ + kVstParameterIsSwitch = 1 << 0, + kVstParameterUsesIntegerMinMax = 1 << 1, + kVstParameterUsesFloatStep = 1 << 2, + kVstParameterUsesIntStep = 1 << 3 +}; + +struct VstPinProperties +{ + char label[64]; + long flags; + long reserved; + char shortLabel[8]; // recommended: 6 + delimiter + char future[48]; +}; + +// pin properties flags +enum +{ + kVstPinIsActive = 1 << 0, + kVstPinIsStereo = 1 << 1 +}; + +// category +enum VstPlugCategory +{ + kPlugCategUnknown = 0, + kPlugCategEffect, + kPlugCategSynth, + kPlugCategAnalysis, + kPlugCategMastering, + kPlugCategSpacializer, // 'panners' + kPlugCategRoomFx, // delays and reverbs + kPlugSurroundFx // dedicated surround processor +}; + +//--------------------------------------------------------------------------------------------- +// flags bits +//--------------------------------------------------------------------------------------------- + +enum +{ + effFlagsIsSynth = 1 << 8, // host may assign mixer channels for its outputs + effFlagsNoSoundInStop = 1 << 9, // does not produce sound when input is all silence + effFlagsExtIsAsync = 1 << 10, // for external dsp; plug returns immedeately from process() + // host polls plug position (current block) via effGetCurrentPosition + effFlagsExtHasBuffer = 1 << 11 // external dsp, may have their own output buffe (32 bit float) + // host then requests this via effGetDestinationBuffer +}; + +//--------------------------------------------------------------------------------------------- +// surround setup +//--------------------------------------------------------------------------------------------- + +typedef struct VstSpeakerProperties VstSpeakerProperties; +typedef struct VstSpeakerArrangement VstSpeakerArrangement; + +struct VstSpeakerProperties +{ // units: range: except: + float azimuth; // rad -PI...PI 10.f for LFE channel + float elevation; // rad -PI/2...PI/2 10.f for LFE channel + float radius; // meter 0.f for LFE channel + float reserved; // 0. + char name[64]; // for new setups, new names should be given (L/R/C... won't do) + char future[32]; +}; + +// note: the origin for azimuth is right (as by math conventions dealing with radians); +// the elevation origin is also right, visualizing a rotation of a circle across the +// -pi/pi axis of the horizontal circle. thus, an elevation of -pi/2 corresponds +// to bottom, and a speaker standing on the left, and 'beaming' upwards would have +// an azimuth of -pi, and an elevation of pi/2. +// for user interface representation, grads are more likely to be used, and the +// origins will obviously 'shift' accordingly. + +struct VstSpeakerArrangement +{ + float lfeGain; // LFE channel gain is adjusted [dB] higher than other channels + long numChannels; // number of channels in this speaker arrangement + VstSpeakerProperties speakers[8]; // variable +}; + +//--------------------------------------------------------------------------------------------- +// offline +//--------------------------------------------------------------------------------------------- + +typedef struct VstOfflineTask VstOfflineTask; +typedef struct VstAudioFile VstAudioFile; +typedef struct VstAudioFileMarker VstAudioFileMarker; + +struct VstOfflineTask +{ + char processName[96]; // set by plug + + // audio access + double readPosition; // set by plug/host + double writePosition; // set by plug/host + long readCount; // set by plug/host + long writeCount; // set by plug + long sizeInputBuffer; // set by host + long sizeOutputBuffer; // set by host + void* inputBuffer; // set by host + void* outputBuffer; // set by host + double positionToProcessFrom; // set by host + double numFramesToProcess; // set by host + double maxFramesToWrite; // set by plug + + // other data access + void* extraBuffer; // set by plug + long value; // set by host or plug + long index; // set by host or plug + + // file attributes + double numFramesInSourceFile; // set by host + double sourceSampleRate; // set by host or plug + double destinationSampleRate; // set by host or plug + long numSourceChannels; // set by host or plug + long numDestinationChannels; // set by host or plug + long sourceFormat; // set by host + long destinationFormat; // set by plug + char outputText[512]; // set by plug or host + + // progress notification + double progress; // set by plug + long progressMode; // reserved for future + char progressText[100]; // set by plug + + long flags; // set by host and plug; see VstOfflineTaskFlags + long returnValue; // reserved for future + void* hostOwned; // set by host + void* plugOwned; // set by plug + + char future[1024]; +}; + +enum VstOfflineTaskFlags +{ + // set by host + kVstOfflineUnvalidParameter = 1 << 0, + kVstOfflineNewFile = 1 << 1, + + // set by plug + kVstOfflinePlugError = 1 << 10, + kVstOfflineInterleavedAudio = 1 << 11, + kVstOfflineTempOutputFile = 1 << 12, + kVstOfflineFloatOutputFile = 1 << 13, + kVstOfflineRandomWrite = 1 << 14, + kVstOfflineStretch = 1 << 15, + kVstOfflineNoThread = 1 << 16 +}; + +// option passed to offlineRead/offlineWrite + +enum VstOfflineOption +{ + kVstOfflineAudio, // reading/writing audio samples + kVstOfflinePeaks, // reading graphic representation + kVstOfflineParameter, // reading/writing parameters + kVstOfflineMarker, // reading/writing marker + kVstOfflineCursor, // reading/moving edit cursor + kVstOfflineSelection, // reading/changing selection + kVstOfflineQueryFiles // to request the host to call asynchronously offlineNotify +}; + +// structure passed to offlineNotify and offlineStart + +struct VstAudioFile +{ + long flags; // see enum VstAudioFileFlags + void* hostOwned; // any data private to host + void* plugOwned; // any data private to plugin + char name[100]; // file title + long uniqueId; // uniquely identify a file during a session + double sampleRate; // file sample rate + long numChannels; // number of channels (1 for mono, 2 for stereo...) + double numFrames; // number of frames in the audio file + long format; // reserved for future + double editCursorPosition; // -1 if no such cursor + double selectionStart; // frame index of first selected frame, or -1 + double selectionSize; // number of frames in selection, or 0 + long selectedChannelsMask; // 1 bit per channel + long numMarkers; // number of markers in the file + long timeRulerUnit; // see doc for possible values + double timeRulerOffset; // offset in time ruler (positive or negative) + double tempo; // as bpm + long timeSigNumerator; // time signature numerator + long timeSigDenominator; // time signature denominator + long ticksPerBlackNote; // resolution + long smpteFrameRate; // smpte rate (set as in VstTimeInfo) + + char future[64]; +}; + +enum VstAudioFileFlags +{ + // set by host (in call offlineNotify) + kVstOfflineReadOnly = 1 << 0, + kVstOfflineNoRateConversion = 1 << 1, + kVstOfflineNoChannelChange = 1 << 2, + + // Set by plug (in function offlineStart) + kVstOfflineCanProcessSelection = 1 << 10, + kVstOfflineNoCrossfade = 1 << 11, + kVstOfflineWantRead = 1 << 12, + kVstOfflineWantWrite = 1 << 13, + kVstOfflineWantWriteMarker = 1 << 14, + kVstOfflineWantMoveCursor = 1 << 15, + kVstOfflineWantSelect = 1 << 16 +}; + +struct VstAudioFileMarker +{ + double position; + char name[32]; + long type; + long id; + long reserved; +}; + +//--------------------------------------------------------------------------------------------- +// others +//--------------------------------------------------------------------------------------------- + +// structure passed to openWindow and closeWindow + +struct VstWindow +{ + char title[128]; // title + short xPos; // position and size + short yPos; + short width; + short height; + long style; // 0: with title, 1: without title + + void *parent; // parent of this window + void *userHandle; // reserved + void *winHandle; // reserved + + char future[104]; +}; + +#endif + diff --git a/externals/grill/vst/src/vst/AudioEffect.hpp b/externals/grill/vst/src/vst/AudioEffect.hpp new file mode 100644 index 00000000..ce127adf --- /dev/null +++ b/externals/grill/vst/src/vst/AudioEffect.hpp @@ -0,0 +1,109 @@ +#ifndef __AudioEffect__ +#define __AudioEffect__ + +#include "AEffect.h" // "c" interface +#include <string.h> + +class AEffEditor; +class AudioEffect; + +// Needs to be defined by the audio effect and is +// called to create the audio effect object instance. +AudioEffect* createEffectInstance (audioMasterCallback audioMaster); + +long dispatchEffectClass(AEffect *e, + long opCode, long index, long value, void *ptr, float opt); +float getParameterClass(long index); +void setParameterClass(long index, float value); +void processClass(AEffect *e, float **inputs, float **outputs, long sampleFrames); +void processClassReplacing(AEffect *e, float **inputs, float **outputs, long sampleFrames); + +class AudioEffect +{ +friend class AEffEditor; +friend long dispatchEffectClass(AEffect *e, long opCode, long index, long value, void *ptr, float opt); +friend float getParameterClass(AEffect *e, long index); +friend void setParameterClass(AEffect *e, long index, float value); +friend void processClass(AEffect *e, float **inputs, float **outputs, long sampleFrames); +friend void processClassReplacing(AEffect *e, float **inputs, float **outputs, long sampleFrames); + +public: + AudioEffect(audioMasterCallback audioMaster, long numPrograms, long numParams); + virtual ~AudioEffect(); + + virtual void setParameter(long index, float value) {index = index; value = value;} + virtual float getParameter(long index) {index = index; return 0;} + virtual void setParameterAutomated(long index, float value); + + AEffect *getAeffect() {return &cEffect;} + void setEditor(AEffEditor *editor) + { this->editor = editor; + if(editor) cEffect.flags |= effFlagsHasEditor; + else cEffect.flags &= ~effFlagsHasEditor;} + + // called from audio master + virtual void process(float **inputs, float **outputs, long sampleFrames) = 0; + virtual void processReplacing(float **inputs, float **outputs, long sampleFrames) + {inputs = inputs; outputs = outputs; sampleFrames = sampleFrames;} + virtual long dispatcher(long opCode, long index, long value, void *ptr, float opt); + virtual void open() {} + virtual void close() {} + virtual long getProgram() {return curProgram;} + virtual void setProgram(long program) {curProgram = program;} // don't forget to set curProgram + virtual void setProgramName(char *name) {*name = 0;} // all following refer to curProgram + virtual void getProgramName(char *name) {*name = 0;} + virtual void getParameterLabel(long index, char *label) {index = index; *label = 0;} + virtual void getParameterDisplay(long index, char *text) {index = index; *text = 0;} + virtual void getParameterName(long index, char *text) {index = index; *text = 0;} + virtual float getVu() {return 0;} + virtual long getChunk(void** data, bool isPreset = false) {return 0;} // returns byteSize + virtual long setChunk(void* data, long byteSize, bool isPreset = false) {return 0;} + virtual void setSampleRate(float sampleRate) {this->sampleRate = sampleRate;} + virtual void setBlockSize(long blockSize) {this->blockSize = blockSize;} + virtual void suspend() {} + virtual void resume() {} + + // setup + virtual void setUniqueID(long iD) {cEffect.uniqueID = iD;} // must call this! + virtual void setNumInputs(long inputs) {cEffect.numInputs = inputs;} + virtual void setNumOutputs(long outputs) {cEffect.numOutputs = outputs;} + virtual void hasVu(bool state = true); + virtual void hasClip(bool state = true); + virtual void canMono(bool state = true); + virtual void canProcessReplacing(bool state = true); + virtual void programsAreChunks(bool state = true); + virtual void setRealtimeQualities(long qualities); + virtual void setOfflineQualities(long qualities); + virtual void setInitialDelay(long delay); + + // inquiry + virtual float getSampleRate() {return sampleRate;} + virtual long getBlockSize() {return blockSize;} + + // host communication + virtual long getMasterVersion(); + virtual long getCurrentUniqueId(); + virtual void masterIdle(); + virtual bool isInputConnected(long input); + virtual bool isOutputConnected(long output); + + // tools + virtual void dB2string(float value, char *text); + virtual void Hz2string(float samples, char *text); + virtual void ms2string(float samples, char *text); + virtual void float2string(float value, char *string); + virtual void long2string(long value, char *text); + +protected: + // members + float sampleRate; + AEffEditor *editor; + audioMasterCallback audioMaster; + long numPrograms; + long numParams; + long curProgram; + long blockSize; + AEffect cEffect; +}; + +#endif diff --git a/externals/grill/vst/src/vst/audioeffectx.h b/externals/grill/vst/src/vst/audioeffectx.h new file mode 100644 index 00000000..11a9cb85 --- /dev/null +++ b/externals/grill/vst/src/vst/audioeffectx.h @@ -0,0 +1,185 @@ +#ifndef __audioeffectx__ +#define __audioeffectx__ + +//---------------------------------------------------------------------------------------------------------------------------- +// VST Plug-Ins SDK +// version 2.0 extension +// (c)1999 Steinberg Soft+Hardware GmbH +//---------------------------------------------------------------------------------------------------------------------------- + +#ifndef __AudioEffect__ +#include "AudioEffect.hpp" // version 1.0 base class AudioEffect +#endif + +#ifndef __aeffectx__ +#include "aeffectx.h" // version 2.0 'C' extensions and structures +#endif + +//---------------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------------- +// AudioEffectX extends AudioEffect with the new features. so you should derive +// your plug from AudioEffectX +//---------------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------------- + +class AudioEffectX : public AudioEffect +{ +public: + AudioEffectX (audioMasterCallback audioMaster, long numPrograms, long numParams); + virtual ~AudioEffectX (); + + virtual long dispatcher (long opCode, long index, long value, void *ptr, float opt); + + // 'host' are methods which go from plug to host, and are usually not overridden + // 'plug' are methods which you may override to implement the according functionality (to host) + +//---------------------------------------------------------------------------------------------------------------------------- +// events + time +//---------------------------------------------------------------------------------------------------------------------------- + + // host + virtual void wantEvents (long filter = 1); // filter is currently ignored, midi channel data only (default) + virtual VstTimeInfo* getTimeInfo (long filter); + // returns const VstTimeInfo* (or 0 if not supported) + // filter should contain a mask indicating which fields are requested + // (see valid masks in aeffectx.h), as some items may require extensive + // conversions + virtual long tempoAt (long pos); // returns tempo (in bpm * 10000) at sample frame location <pos> + bool sendVstEventsToHost (VstEvents* events); // true:success + + // plug + virtual long processEvents (VstEvents* events) {return 0;} // wants no more...else return 1! + // VstEvents and VstMidiEvents are declared in aeffectx.h + +//---------------------------------------------------------------------------------------------------------------------------- +// parameters and programs +//---------------------------------------------------------------------------------------------------------------------------- + + // host + virtual long getNumAutomatableParameters (); + virtual long getParameterQuantization (); // returns the integer value for +1.0 representation, + // or 1 if full single float precision is maintained + // in automation. parameter index in <value> (-1: all, any) + // plug + virtual bool canParameterBeAutomated (long index) { return true; } + virtual bool string2parameter (long index, char* text) {return false;} // note: implies setParameter. text==0 is to be + // expected to check the capability (returns true). + virtual float getChannelParameter (long channel, long index) {return 0;} + virtual long getNumCategories () {return 1L;} + virtual bool getProgramNameIndexed (long category, long index, char* text) {return false;} + virtual bool copyProgram (long destination) {return false;} + +//---------------------------------------------------------------------------------------------------------------------------- +// connections, configuration +//---------------------------------------------------------------------------------------------------------------------------- + + // host + virtual bool ioChanged (); // tell host numInputs and/or numOutputs and/or numParameters has changed + virtual bool needIdle (); // plug needs idle calls (outside its editor window) + virtual bool sizeWindow (long width, long height); + virtual double updateSampleRate (); // gets and returns sample rate from host (may issue setSampleRate() ) + virtual long updateBlockSize (); // same for block size + virtual long getInputLatency (); + virtual long getOutputLatency (); + virtual AEffect* getPreviousPlug (long input); // input can be -1 in which case the first found is returned + virtual AEffect* getNextPlug (long output); // output can be -1 in which case the first found is returned + + // plug + virtual void inputConnected (long index, bool state) {} // input at <index> has been (dis-)connected, + virtual void outputConnected (long index, bool state) {} // same as input; state == true: connected + virtual bool getInputProperties (long index, VstPinProperties* properties) {return false;} + virtual bool getOutputProperties (long index, VstPinProperties* properties) {return false;} + virtual VstPlugCategory getPlugCategory() + { if (cEffect.flags & effFlagsIsSynth) return kPlugCategSynth; return kPlugCategUnknown; } + +//---------------------------------------------------------------------------------------------------------------------------- +// realtime +//---------------------------------------------------------------------------------------------------------------------------- + + // host + virtual long willProcessReplacing (); // returns 0: not implemented, 1: replacing, 2: accumulating + virtual long getCurrentProcessLevel (); // returns: 0: not supported, + // 1: currently in user thread (gui) + // 2: currently in audio thread or irq (where process is called) + // 3: currently in 'sequencer' thread or irq (midi, timer etc) + // 4: currently offline processing and thus in user thread + // other: not defined, but probably pre-empting user thread. + virtual long getAutomationState (); // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write + virtual void wantAsyncOperation (bool state = true); // notify host that we want to operate asynchronously. + // process() will return immedeately; host will poll getCurrentPosition + // to see if data are available in time. + virtual void hasExternalBuffer (bool state = true); // external dsp, may have their own output buffe (32 bit float) + // host then requests this via effGetDestinationBuffer + + // plug + virtual long reportCurrentPosition () {return 0;} // for external dsp, see wantAsyncOperation () + virtual float* reportDestinationBuffer () {return 0;} // for external dsp (dma option) + +//---------------------------------------------------------------------------------------------------------------------------- +// offline +//---------------------------------------------------------------------------------------------------------------------------- + + // host + virtual bool offlineRead (VstOfflineTask* offline, VstOfflineOption option, bool readSource = true); + virtual bool offlineWrite (VstOfflineTask* offline, VstOfflineOption option); + virtual bool offlineStart (VstAudioFile* ptr, long numAudioFiles, long numNewAudioFiles); + virtual long offlineGetCurrentPass (); + virtual long offlineGetCurrentMetaPass (); + + // plug + virtual bool offlineNotify (VstAudioFile* ptr, long numAudioFiles, bool start) { return false; } + virtual bool offlinePrepare (VstOfflineTask* offline, long count) {return false;} + virtual bool offlineRun (VstOfflineTask* offline, long count) {return false;} + + virtual long offlineGetNumPasses () {return 0;} + virtual long offlineGetNumMetaPasses () {return 0;} + +//---------------------------------------------------------------------------------------------------------------------------- +// other +//---------------------------------------------------------------------------------------------------------------------------- + + // host + virtual void setOutputSamplerate (float samplerate); + virtual bool getSpeakerArrangement (VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput); + virtual bool getHostVendorString (char* text); // fills <text> with a string identifying the vendor (max 64 char) + virtual bool getHostProductString (char* text); // fills <text> with a string with product name (max 64 char) + virtual long getHostVendorVersion (); // returns vendor-specific version + virtual long hostVendorSpecific (long lArg1, long lArg2, void* ptrArg, float floatArg); // no definition + virtual long canHostDo (char* text); // see 'hostCanDos' in audioeffectx.cpp + // returns 0: don't know (default), 1: yes, -1: no + virtual void isSynth (bool state = true); // will call wantEvents if true + virtual void noTail (bool state = true); // true: tells host we produce no output when silence comes in + // enables host to omit process() when no data are present + // on any one input. + virtual long getHostLanguage (); // returns VstHostLanguage + virtual void* openWindow (VstWindow*); // create new window + virtual bool closeWindow (VstWindow*); // close a newly created window + virtual void* getDirectory (); // get the plug's directory, FSSpec on mac, else char* + virtual bool updateDisplay(); // something has changed, update 'multi-fx' display + // returns true if supported + + // plug + virtual bool processVariableIo (VstVariableIo* varIo) {return false;} + virtual bool setSpeakerArrangement (VstSpeakerArrangement* pluginInput, VstSpeakerArrangement* pluginOutput) {return false;} + virtual void setBlockSizeAndSampleRate (long blockSize, float sampleRate) + {this->blockSize = blockSize; this->sampleRate = sampleRate;} + virtual bool setBypass(bool onOff) {return false;} // for 'soft-bypass; process() still called + virtual bool getEffectName (char* name) {return false;} // name max 32 char + virtual bool getErrorText (char* text) {return false;} // max 256 char + virtual bool getVendorString (char* text) {return false;} // fill text with a string identifying the vendor (max 64 char) + virtual bool getProductString (char* text) {return false;} // fill text with a string identifying the product name (max 64 char) // fills <ptr> with a string with product name (max 64 char) + virtual long getVendorVersion () {return 0;} // return vendor-specific version + virtual long vendorSpecific (long lArg, long lArg2, void* ptrArg, float floatArg) {return 0;} + // no definition, vendor specific handling + virtual long canDo (char* text) {return 0;} // see 'plugCanDos' in audioeffectx.cpp. return values: + // 0: don't know (default), 1: yes, -1: no + virtual void* getIcon () {return 0;} // not yet defined + virtual bool setViewPosition (long x, long y) {return false;} + virtual long getGetTailSize () {return 0; } + virtual long fxIdle () {return 0;} + virtual bool getParameterProperties (long index, VstParameterProperties* p) {return false;} + virtual bool keysRequired () {return false;} // version 1 plugs will return true + virtual long getVstVersion () {return 2;} +}; + +#endif |