VST SDK plugin example

Share your advanced PureBasic knowledge/code with the community.
Aleks_Longard
User
User
Posts: 59
Joined: Mon Dec 24, 2012 9:07 am
Location: Germany, Munich

Re: VST SDK plugin example

Post by Aleks_Longard »

I don’t understand some things in PB or simply don’t know. My experiments with the plugin window are very bad, it turns out the window on top of the host instead of the client area inside the host window.
Canvas gadget is attached to the window pane after OpenWindow (), and without the main window it is not working.

Sorry guys, I use screenreader software for watching the screen and for me the plug-in window is almost useless, for this reason I did not pay attention to how the GUI works in plug-ins.
I will try to write a window using WinApi, I already did this when I studied VST on C++, so it will be easier to understand how it works.
Sory my bad english
User avatar
oreopa
Enthusiast
Enthusiast
Posts: 281
Joined: Sat Jun 24, 2006 3:29 am
Location: Edinburgh, Scotland.

Re: VST SDK plugin example

Post by oreopa »

Hey Aleks.

Too bad about your experiments with the native stuff... I assumed there would be some way to create a canvas gadget and just use the handle of that (or a borderless window with canvas gadget that docks seamlessly in the host vst "container")... I tried myself but i cannot work it out... I also can only get a floating window that does not dock/attach to host gui... (I'm still kinda hopeful this canvasgadget approach could work tho...)

I'd like to know how sq4 does it also, maybe he has some hints... ;)

Cheers all!
Proud supporter of PB! * Musician * C64/6502 Freak
User avatar
oreopa
Enthusiast
Enthusiast
Posts: 281
Joined: Sat Jun 24, 2006 3:29 am
Location: Edinburgh, Scotland.

Re: VST SDK plugin example

Post by oreopa »

Ok. I am hacking around like crazy, and finally I got somewhere...

This seems to open and attach a window with gadgets to the host gui in dispatcher...

Code: Select all

    Case #effEditOpen
      result = OpenWindow(#PB_Any, 0, 0, 500, 500, "!", #WS_CHILD, *ptr)
      ButtonGadget(#PB_Any, 0, 0, 64, 64, "PRESS ME", #PB_Button_Toggle)
      Global g_CANVAS = CanvasGadget(#PB_Any, 100,100,250,250)
      
      StartDrawing(CanvasOutput(g_CANVAS))
        Box(100, 100, 50, 50, #Red)
      StopDrawing()
Now the mission is to find a place to put some waitwindowevent or similar... I want to mousedown and move the red square now! ;)

edit;

Ok. terrible code... probably already running into the cross-thread variable problems ive seen sq4 mentioning.... but what the heck :D

Code: Select all

Procedure uiEventThread(*ptr)
  Protected ev.l
  Protected x,y ,z
  Global uiWindowHandle = OpenWindow(#PB_Any, 0, 0, 500, 500, "", #WS_CHILD, *ptr)
  Global threadrunninng = #True
  Global result 

  Global g_BUTTON = ButtonGadget(#PB_Any, 0, 0, 64, 64, "PRESS ME", #PB_Button_Toggle)
  Global g_CANVAS = CanvasGadget(#PB_Any, 100,100,250,250)
  
  StartDrawing(CanvasOutput(g_CANVAS))
    Box(100, 100, 50, 50, RGB(128+Random(127), 128+Random(127), 128+Random(127)))
  StopDrawing()
  
        
  Repeat
    ev = WaitWindowEvent()
    
    Select ev
      Case #PB_Event_Gadget
        Select EventGadget()
          Case g_CANVAS
            Select EventType()
              Case #PB_EventType_MouseMove
                If GetGadgetAttribute(g_CANVAS, #PB_Canvas_Buttons) = #PB_Canvas_LeftButton
                  x = GetGadgetAttribute(g_CANVAS, #PB_Canvas_MouseX)
                  y = GetGadgetAttribute(g_CANVAS, #PB_Canvas_MouseY)
                  StartDrawing(CanvasOutput(g_CANVAS))  
                    Box(x, y, 50, 50, RGB(128+Random(127), 128+Random(127), 128+Random(127)))
                  StopDrawing()
                EndIf
            EndSelect
        EndSelect
    EndSelect
  Until threadrunninng = #False
EndProcedure
and
in dispatcher proc:

Code: Select all

    Case #effEditOpen
      CreateThread(@uiEventThread(), *ptr)
      Delay(100)
      result = uiWindowHandle
      
    Case #effEditClose
      threadrunninng = #False
      Delay(100)
      CloseWindow(uiWindowHandle)
It's awful hacky... but it does *something* :D
Proud supporter of PB! * Musician * C64/6502 Freak
sq4
User
User
Posts: 98
Joined: Wed Feb 26, 2014 3:16 pm
Contact:

Re: VST SDK plugin example

Post by sq4 »

The use of PB's window functions is a no go. I know that p.e. Reaper will crash when reopening the editor window.
So you need to use WinApi.
But first you have to register the window class in AttachProcess and unregister in DetachProcess.
To create the window, you could do with something like this :

Code: Select all

          lStyle.l=#WS_CHILD | #WS_VISIBLE | #WS_CLIPSIBLINGS | #WS_CLIPCHILDREN | #WS_EX_ACCEPTFILES
          hPluginWin = CreateWindowEx_(#WS_EX_ACCEPTFILES, @g_szClassName, 0, lStyle, 0, 0, #Plugin_Width, #Plugin_Height,  *AEffect\Editor\ParentId, 0, gInstance, 0) 
          If hPluginWin
            *AEffect\Editor\Gadget=hPluginWin
            SetProp_(*AEffect\Editor\Gadget,"oldproc",SetWindowLongPtr_(*AEffect\Editor\Gadget,#GWL_WNDPROC, @EditorCallback())) 
            SetProp_(*AEffect\Editor\Gadget,"ptrAEffect",*AEffect) 
            ShowWindow_(*AEffect\Editor\Gadget,#SW_SHOW)
            UpdateWindow_(*AEffect\Editor\Gadget)
            VST_EditOpenClose(*AEffect, #Open) 
         endif
No need to create an extra thread for event handling, just do everything in the callback (in this case EditorCallback().
In #WM_Paint do a Bitblt_() of your editors image.
User avatar
oreopa
Enthusiast
Enthusiast
Posts: 281
Joined: Sat Jun 24, 2006 3:29 am
Location: Edinburgh, Scotland.

Re: VST SDK plugin example

Post by oreopa »

sq4 wrote:The use of PB's window functions is a no go[...]
That's too bad... i thought CanvasGagdet would be great to make it cross platform (graphically).
sq4 wrote:So you need to use WinApi[...]
sq4 wrote:No need to create an extra thread for event handling, just do everything in the callback (in this case EditorCallback().
In #WM_Paint do a Bitblt_() of your editors image.
Ok, I'll try it. Thanx a lot for the tips.
Proud supporter of PB! * Musician * C64/6502 Freak
Aleks_Longard
User
User
Posts: 59
Joined: Mon Dec 24, 2012 9:07 am
Location: Germany, Munich

Re: VST SDK plugin example

Post by Aleks_Longard »

I try to write with WinApi, this not work properly...
Bad idea with this plug's...

Ups... I was late, Sq4 already answered.

Code: Select all

EnableExplicit
IncludeFile "aeffect.pbi"
IncludeFile "aeffectx.pbi"

Global handle ; for VST window

Global channels.l = 2
Global  paramvolume.f = 1.0

; VST-plugin window
Procedure WinProcCallback(handle, message, wparam, lparam)
 Protected r
 
Select message
Case #WM_CLOSE
DestroyWindow_(handle)
Case #WM_DESTROY
PostQuitMessage_(0)
r = 0
Default
r = DefWindowProc_(handle, message, wparam, lparam)
EndSelect
ProcedureReturn r
EndProcedure

Procedure OpenVSTWindow(hosthandle.i)
Protected text.s = "Hello World for VST plugin"
Protected THandle
Protected wc.WNDCLASS
Protected WinVSTClass.s = "VSTPluginClass"
wc\style = #CS_GLOBALCLASS
wc\lpfnWndProc = @WinProcCallback()
wc\lpszClassName = @WinVSTClass
If RegisterClass_(@wc)
handle = CreateWindowEx_(0, @WinVSTClass, "Hello! Plugin", #WS_CHILD | #WS_VISIBLE | #WS_CLIPCHILDREN, 0, 0, 300, 500, hosthandle, 0, 0, 0)

THandle = CreateWindowEx_(0, "Static", text, #WS_CHILD | #WS_VISIBLE, 5, 5, 150, 50, handle, 0, 0, 0)
SendMessage_(THandle, #WM_SETFONT, #DEFAULT_GUI_FONT, 1)
ShowWindow_(handle, #SW_SHOWDEFAULT)
UpdateWindow_(handle)
Else
 MessageRequester("Error", "Can not create window", 0)
 EndIf
EndProcedure

Procedure CloseVSTWindow()
SendMessage_(handle, #WM_CLOSE, 0, 0)
EndProcedure
 
 
; other procedures
Procedure getParameterName(index.l, *text)
Select index
Case 0
PokeS(*text, "Volume", #kVstMaxParamStrLen, #PB_Ascii)
EndSelect
EndProcedure

Procedure getParameterDisplay(index.l, *text)
Select index
Case 0
PokeS(*text, StrF(paramvolume, 4), 4, #PB_Ascii)
EndSelect
EndProcedure


; procedures for VST sdk
ProcedureC.i DispatcherProc(*d.AEffect, opcode.l, index.l, Value.i, *ptr, opt.f)
Protected result.i
Select opcode
Case #effClose
FreeStructure(*d)
Case #effGetParamDisplay
 getParameterDisplay(index, *ptr)
Case #effGetParamName
getParameterName(index, *ptr)
Case #effGetPlugCategory
result = #kPlugCategEffect | #kPlugCategAnalysis
Case #effGetEffectName
PokeS(*ptr, "test plugin", #kVstMaxEffectNameLen, #PB_Ascii)
Case #effGetVendorString
PokeS(*ptr, "Alex Longard", #kVstMaxVendorStrLen, #PB_Ascii)
Case #effEditOpen
OpenVSTWindow(PeekI(*ptr))
Case #effEditClose
CloseVSTWindow()
Default
EndSelect
ProcedureReturn result
EndProcedure

ProcedureC ProcessReplacingProc(*ap.AEffect, *inputs, *outputs, sampleframes.l)
Protected *In1, *In2, *Out1, *Out2, i.l
*In1 = PeekI(*inputs)
*Out1 = PeekI(*outputs)
If channels = 2
*In2 = PeekI(*inputs + SizeOf(integer))
*Out2 = PeekI(*outputs + SizeOf(integer))
EndIf
For i = 0 To sampleframes - 1
PokeF(*Out1 + i * SizeOf(float), PeekF(*In1 + i * SizeOf(float)) * paramvolume)
If channels = 2
PokeF(*Out2 + i * SizeOf(float), PeekF(*In2 + i * SizeOf(float)) * paramvolume)
EndIf
Next i
EndProcedure

ProcedureC ProcessDoubleReplacingProc(*ap.AEffect, *inputs, *outputs, sampleframes.l)

EndProcedure

ProcedureC SetParameterProc(*asp.AEffect, index.l, value.f)
paramvolume = value
EndProcedure

ProcedureC.f GetParameterProc(*agp.AEffect, index.l)
ProcedureReturn paramvolume
EndProcedure

ProcedureCDLL VSTPluginMain(*audioMaster)
Protected *Aef.AEffect = AllocateStructure(AEffect)
*aef\magic = #kEffectMagic
*aef\dispatcher = @DispatcherProc()
*aef\setParameter = @SetParameterProc()
*aef\getParameter = @GetParameterProc()
*aef\numParams = 1
*aef\numInputs = channels
*aef\numOutputs = channels
*aef\flags = #effFlagsHasEditor | #effFlagsCanReplacing
*aef\processReplacing = @ProcessReplacingProc()
; *aef\processDoubleReplacing = @ProcessDoubleReplacingProc()
*aef\uniqueID = 02081987
*aef\version = 1
*aef\Object = 0
ProcedureReturn *aef
EndProcedure
Sory my bad english
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: VST SDK plugin example

Post by Joris »

@Aleks_Longard and others.

Hi
To me this is still (a bit or a lot) above my experiences, aside I wonder if this code is also ment to handle midi-vst's ? And if so how ?
The terms used in the code here are about effect's (AE) etc. nothing that would link to MIDI, which for me is a simpler thing then audio programming.
Are you intended to work on that too or just on audio vst's (vsti) ?

Thanks.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
sq4
User
User
Posts: 98
Joined: Wed Feb 26, 2014 3:16 pm
Contact:

Re: VST SDK plugin example

Post by sq4 »

Joris wrote:@Aleks_Longard and others.

Hi
To me this is still (a bit or a lot) above my experiences, aside I wonder if this code is also ment to handle midi-vst's ? And if so how ?
The terms used in the code here are about effect's (AE) etc. nothing that would link to MIDI, which for me is a simpler thing then audio programming.
Are you intended to work on that too or just on audio vst's (vsti) ?

Thanks.
For a midiplugin:
You need to set the flags to include effFlagsIsSynth
In cando you need to expose following :
-canDoSendVstEvents
-canDoSendVstMidiEvent

In process/processreplacing you need to queue your midievents ( p.e. in a list) and at the end call audiomaster with "audioMasterProcessEvents" and the array of pointers to MidiEvent structures...
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: VST SDK plugin example

Post by Joris »

Thanks sq4, I hope I'll grow a bit more into this very complicated stuff.
To me it all looks more like 'why making it easy, while it can be made difficult..."
;-)
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
sq4
User
User
Posts: 98
Joined: Wed Feb 26, 2014 3:16 pm
Contact:

Re: VST SDK plugin example

Post by sq4 »

Joris wrote:Thanks sq4, I hope I'll grow a bit more into this very complicated stuff.
To me it all looks more like 'why making it easy, while it can be made difficult..."
;-)
Perhaps easier alternatives :
- Synthedit
- Flowstone
- Blue Cat plug 'n script
- ...

I've started with PB (v 3.81) to create RnT2 which is a VST experimental HOST.

TBH it took me over 4 years to finish it.
Once you know the inner workings of a HOST it's naturally much easier to develop VST-plugins.

But you are right : it's quite complex!
Aleks_Longard
User
User
Posts: 59
Joined: Mon Dec 24, 2012 9:07 am
Location: Germany, Munich

Re: VST SDK plugin example

Post by Aleks_Longard »

Hi Joris!
I do not have free time to experiment with PB VST. I can show you my C function for you to get information about all VstEvents, with this function you can manipulate midi.

Code: Select all

VstInt32 processEvents(VstEvents* ev) {
for (int i = 0; i < ev->numEvents; i++)
{
VstEvent* event = ev->events[i];
if (event->type == kVstMidiType)
{
VstMidiEvent* midiEvent = (VstMidiEvent*) event;
VstInt8 status = midiEvent->midiData[0];
VstInt8 data1 = midiEvent->midiData[0];
VstInt8 data2 = midiEvent->midiData[0];
printf("MIDI: %02x %02x %02x\n", status, data1, data2);
}
}
return 0;
}
Sory my bad english
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: VST SDK plugin example

Post by Joris »

@Aleks_Longard thanks.
I'm still busy with a 'Drum-DAW' and would later on be able to build a midi-vst in which the data form that 'Drum-DAW' can be played. So, I need to read the clock from the host and be able to send the data out.
Your code looks close to be going that way...
Nice.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Aleks_Longard
User
User
Posts: 59
Joined: Mon Dec 24, 2012 9:07 am
Location: Germany, Munich

Re: VST SDK plugin example

Post by Aleks_Longard »

Hello all!
I write new example with window (not controls)
Please compile to test code in file: vst_window.pb
All sdk files there:
https://www.dropbox.com/sh/j0vun0sg751f ... drVEa?dl=0
Sory my bad english
SofT MANiAC
Enthusiast
Enthusiast
Posts: 142
Joined: Mon Sep 17, 2007 10:28 am
Location: P.O.P
Contact:

Re: VST SDK plugin example

Post by SofT MANiAC »

Aleks_Longard wrote:Hello all!
I write new example with window (not controls)
Please compile to test code in file: vst_window.pb
All sdk files there:
https://www.dropbox.com/sh/j0vun0sg751f ... drVEa?dl=0
hello! link is dead :(
POiNT.OF.PRESENCE group
Aleks_Longard
User
User
Posts: 59
Joined: Mon Dec 24, 2012 9:07 am
Location: Germany, Munich

Re: VST SDK plugin example

Post by Aleks_Longard »

Hello SofT MANiAC and all!
Sorry for bad link, my notebook is dead and i not have new full plugin code, i post dropbox link for last worked code

https://www.dropbox.com/sh/sz1dgj2d08dr ... UJBWa?dl=0

If you have questions for this - i will can to ask.
Cheers!
Sory my bad english
Post Reply