simplistic linux/vst3 plugin example/framework

Programming applications for making music on Linux.

Moderators: MattKingUSA, khz

User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

simplistic linux/vst3 plugin example/framework

Post by skei »

k9_4aug2019.zip (152k)
(temporarily)

pretty basic and hacky, but it seems to work, and shows the main principles.. k9_vst3.h contains all vst3 specific stuff.. the few missing bits and pieces should be easy to add in.. the (crappy) README has some info about compiler (gcc) arguments.. compiled plugins tested (and working) in bitwig and reaper.. do what you want with my code (consider it public domain), but if you use the vst3 sdk, you need to honor steinberg's licenses..

this is a simplification of (extracts from) my 'real' plugin framework (k9 - 'canine') that i'm currently rebuilding from scratch.. i decided to upload this before i continued with the gui part (which always messes things up), and more plugin formats, in case anybody wants to start looking into vst3..

who will be the first to compile the included event_horizon and sonic_maximizer plugins? :-)

(thanks to justin (reaper) for a lot of help getting an initial vst3 plugin working)
Basslint
Established Member
Posts: 1511
Joined: Sun Jan 27, 2019 2:25 pm
Location: Italy
Has thanked: 382 times
Been thanked: 298 times

Re: simplistic linux/vst3 plugin example/framework

Post by Basslint »

Thank you! If you uploaded this file to a repository hosting service like Gitlab or Github and included a proper LICENSE file people could easily find it outside of this forum and use them as a starting point for their code, since VST3 resources are scarce.
The community of believers was of one heart and mind, and no one claimed that any of his possessions was his own, but they had everything in common. [Acts 4:32]

Please donate time (even bug reports) or money to libre software 🎁

Jam on openSUSE + GeekosDAW!
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

yeah, probably.. but i would prefer to work on it a bit more before i eventually do that.. make it more full featured or finished.. i especially want to get the base gui stuff in place.. (which is more or less working here, already)..
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

update..
things are progressing nicely, and i now have a simple, working plugin with a minimal gui.. before i start massaging and cleaning up the code, and combining it with the rest of my plugin framework/library, it would be great to test it a little.. so, i made this little plugin, sonic_maximizer, and hope somebody could be interesterd in helping me test it in various distros and hosts.. i have tested it myself in bitwig and reaper, where they seem to work well.. but there's not many vst3 hosts for linux.. does the linux version of tracktion/waveform support vst3 plugins? anything else? mixbus? also, i have only tested it in linux mint 19.1, but the plugin doesn't have much dependencies (pthread and xcb, mainly), so i guess it should work pretty much everywhere.. in theory..

sonic_maximizer.vst3-08.sep.2019.zip (60 kb)
(source code will be released a little later, together with the full plugin framework/library code)

Image

the gui is pure xlib (xcb) at the moment (but double-buffered).. i also have cairo graphics support in there already, but i need to squash a few bugs before it can be used..

- tor-helge
tramp
Established Member
Posts: 2335
Joined: Mon Jul 01, 2013 8:13 am
Has thanked: 9 times
Been thanked: 454 times

Re: simplistic linux/vst3 plugin example/framework

Post by tramp »

skei wrote:the gui is pure xlib (xcb) at the moment (but double-buffered).. i also have cairo graphics support in there already, but i need to squash a few bugs before it can be used..
You may be interested in my damn tiny abstraction Layer to create X11 window/widgets with cairo surfaces
It use only plain Xlib and cairo and been written in C for static linkage.
It use double buffering, allow transparent drawing and image loading from in-linked binary blobs.
Some examples on how to use it, including a LV2 plug example, been included.
Currently it include some example widgets like knobs, sliders, buttons, menus and a combo-box, were the menu and combo-box supports scrolling.
Basic UTF8 support is included.

It comes with the moderate BSD Zero Clause License, so you could do with it what ever you want, even if you just want to have a look on it to help you to find the bugs in your layer.
here it is:
https://github.com/brummer10/Xputty
On the road again.
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

@tramp:

yeah.. i was actually looking at that a short while ago!
but the thing is, i already have my own widget system (much more than the screenshot above shows) that i have slowly built up over many years.. which i'm pretty satisfied with.. i have just begun pasting back the code from previous framework versions, now that the lower level gui stuff is in place, and seems to be working ok.. but, from the start, i have been focusing on making it easy to replace parts of the framework (for example the gui system) with your own.. but i will look more into all that in a while.. at the moment, i'm working on bringing back support for other relevant plugin formats.. vst2 is already in place, using either the official steinberg sdk, or vestige..

- tor-helge

edit: and, btw, my cairo wrapper works in reaper, but in bitwig, the second time i open the editor, it won't redraw the editor window, so it comes up blank (or distorted).. maybe something related to shutting down cairo properly (it works the first time the editor is opened), or maybe some flushing, as i use both xcb/xlib drawing primitives (to blit the backbuffer to the screen/window), and cairo (for drawing into the backbuffer)..
tramp
Established Member
Posts: 2335
Joined: Mon Jul 01, 2013 8:13 am
Has thanked: 9 times
Been thanked: 454 times

Re: simplistic linux/vst3 plugin example/framework

Post by tramp »

skei wrote: as i use both xcb/xlib drawing primitives (to blit the backbuffer to the screen/window), and cairo (for drawing into the backbuffer)..
I don't do that, I use for drawing a double buffered cairo xlib surface (don't use a cairo image surface to draw operations with xlib !!) and draw only with cairo.
Xlib just provide a blank Window.
There is not a single call to flush desktop needed.
On the road again.
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

tramp wrote:I don't do that, I use for drawing a double buffered cairo xlib surface (don't use a cairo image surface to draw operations with xlib !!) and draw only with cairo.
Xlib just provide a blank Window.
There is not a single call to flush desktop needed.

i found that when i started using xcb instead of 'pure' xlib, i had to put flushes in a lot of places, as xcb doesn't automatically flush as much as xlib.. haven't gone through it all and tested which of them is actually necessary.. will do later..

to clarify a little: in my framework, when i create a window, i also create a pixmap backbuffer.. i use cairo to draw into that pixmap, and finally, xcb_copy_area() to transfer the relevant part of the backbuffer pixmap to the screen/window.. so, similar to how you do it, i think?

a while ago i did some bench-marking, and i found that creating an ximage, painting into that with cairo, and then xcb_image_put() that to the screen, was actually quite faster! xcb was probably using libxcb-shm for transferring the final ximage?

anyway, i just want to make this work first, then do a bunch of tests and benchmarking..

the weird thing is that it works the first time the plugin is loaded, and the gui is automatically opened.. both in reaper and bitwig.. it updates correctly when i change parameters, all painting done using cairo, 'blitting' done using xcb.. but if i close the editor, and reopen it, the editor usually comes up blank (nothing painted), and the gui doesn't react to my mouse events.. in reaper, i can quickly close and reopen the editor several times in a row, and it works, but once in a while, it crashes too..

i destroy everything, and recreate it all each time i close/reopen the editor, so there shouldn't be anytihng left over in memory or settings not being initialized properly? unless.. hmm.. cairo does some ref counting in the background, i think? hmm.. need to investigate..

using pure xcb for the painting part, and everything works correctly..

maybe i need to take a break from cairo, and do some other things for a while, before i get back to it? i can still code widgets and stuff, and when the cairo layer works as intended, they will just look better.. :-)

- tor-helge
tramp
Established Member
Posts: 2335
Joined: Mon Jul 01, 2013 8:13 am
Has thanked: 9 times
Been thanked: 454 times

Re: simplistic linux/vst3 plugin example/framework

Post by tramp »

skei wrote:i found that when i started using xcb instead of 'pure' xlib, i had to put flushes in a lot of places, as xcb doesn't automatically flush as much as xlib.. haven't gone through it all and tested which of them is actually necessary.. will do later..
When I need to re-draw a widget, I send a expose call to the event loop, so, anything was handled in the event loop. Never flush.
skei wrote:to clarify a little: in my framework, when i create a window, i also create a pixmap backbuffer.. i use cairo to draw into that pixmap, and finally, xcb_copy_area() to transfer the relevant part of the backbuffer pixmap to the screen/window.. so, similar to how you do it, i think?
Nope, as I said, I didn't use any xlib functions for drawing, so no backbuffer. What I do is
cairo_xlib_surface_create(app->dpy, w->widget, DefaultVisual(app->dpy, DefaultScreen(app->dpy)), width, height)
and as buffer
cairo_surface_create_similar (w->surface, CAIRO_CONTENT_COLOR_ALPHA, width, height);

The second surface is used for drawing operations, the first surface provide a copy of the parent. On expose the first surface take a copy of the underlying area from the parent Window and the drawing from the second surface get copied to the first surface, then the first surface get pushed on screen. that's all.

Writing a proper event loop is the secret, my layer provide one, which handle any events, memory allocation and deallocation, provide a child-list for any widget, handle resizing, provide adjustment stacks for controllers or scrollable windows, create and destroy widgets, . . .

To proper destroy any widget and clean up the memory used on exit, just a call to main_quit(&app); is needed.

However, this isn't a toolkit, this is just a abstraction layer which will make it easy to create your own toolkit (widget set) with just cairo drawing.
The base Widget_t, is a transparent Drawing Area, a Event Box and a Container, have x y adjustment in place, and support a couple of scaling mods.
On the road again.
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

i've been staring at the sources for hours now.. and i think i need to focus on something else for a while.. :-/

the cairo gui works perfectly the first time the plugin is opened.. both in bitwig and reaper..

Image

but, in bitwig, when i close the editor, and then immediately reopen it again, it doesn't work properly anymore.. or, it seems to kind of work.. f.ex events and widget tweaking, and from printouts and logs i can see that the painting functions are being called, but the final result is not correct.. btw, for this test-version of the plugin, i draw directly to the screen (no double-buffering) with cairo, no xcb drawing involved..

Image

in reaper, it works a little bit better.. but not much.. i can open/close the editor 5-6-7 times, then, suddenly it looks like the above, then ok again for 5-6 times, etc..

i destroy everything, and re-create everything from scratch when i close, and reopen the editor, so there shouldn't be any leftovers anywhere, but it seems there's some state elsewhere not being reset properly.. or something.. but i can't find it right now.. need to clear my head, and look at something else for a while.. until then, i'll just use the basic xcb (xlib) version..

vst2 and vst3 works properly now, not sure what other formats i will bring back.. we'll see..
tramp
Established Member
Posts: 2335
Joined: Mon Jul 01, 2013 8:13 am
Has thanked: 9 times
Been thanked: 454 times

Re: simplistic linux/vst3 plugin example/framework

Post by tramp »

I've seen such behave often.
First attempt is: Only do drawing to screen in the expose event callback. Never ever call flush. As this will only hide a bug in your source. Send a expose event for to window when needed.
Second: When use cairo, use cairo_push_group before draw anything to the surface, use cairo_pop_group_to_source when finished the drawing.
Third: don't use cairo_image_surface with X11.

Also, in the expose event handling, you should use

case Expose:
if (xev->xexpose.count == 0) {
do_expose_what_ever(); // here is your callback
}
break;
to only handle the last committed state.

Side note, you may try Xputty to create your UI's, that will keep a lot of trouble away from you, and you could focus on the framework for the plugin standards.
On the road again.
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

@tramp:

thanks!

i will seriously look int all of this..
and i will probably experiment with Xputty anyway, no matter if i can get this working or not.. :-)

the xlib/xcb layer is working perfectly, and have done so for years (in different versions).. so i don't anticipate any problems there.. i already do most of the things you suggested (expose/events) .. i used cairo with xlib (not xcb) in pascal before..
but i have changed a few things related to how you select and use different layers and 'modules' in the framework, so i think the problem is in there somewhere..

- tor-helge

edit:
btw, why does my editor works perfectly the first time i open the editor, with cairo and all, but not after i close and then immediately reopen it?
(so there's no problems with a standalone executable, only plugins)..
tramp
Established Member
Posts: 2335
Joined: Mon Jul 01, 2013 8:13 am
Has thanked: 9 times
Been thanked: 454 times

Re: simplistic linux/vst3 plugin example/framework

Post by tramp »

skei wrote:btw, why does my editor works perfectly the first time i open the editor, with cairo and all, but not after i close and then immediately reopen it?
Hard to say, do you host your code public somewhere?
Most likely is that the host didn't shot down the interface, but only hide it. Then, on the next run, your UI started with undefined behave because events get lost in the mean time.
The event loop should take care of that no event get handled when the UI isn't mapped.
On the road again.
tramp
Established Member
Posts: 2335
Joined: Mon Jul 01, 2013 8:13 am
Has thanked: 9 times
Been thanked: 454 times

Re: simplistic linux/vst3 plugin example/framework

Post by tramp »

This is a example of Xputty:
Image
On the road again.
User avatar
skei
Established Member
Posts: 337
Joined: Sun May 18, 2014 4:24 pm
Has thanked: 8 times
Been thanked: 57 times
Contact:

Re: simplistic linux/vst3 plugin example/framework

Post by skei »

tramp wrote:do you host your code public somewhere?
yeah, i just uploaded it to:
https://github.com/skei/kode9
be warned, it is "in progress" :-)
tramp wrote:Most likely is that the host didn't shot down the interface, but only hide it. Then, on the next run, your UI started with undefined behave because events get lost in the mean time.
hmm.. i'll investigate that..
Post Reply