I'm struggling to find a basic example on how to set up a minimal plugin host with VST 3.x SDK. The official documentation is absolutely criptic and brief, I can't get anywhere. I would like to:
understand the minimal setup: required headers, interfaces to implement, ...;
load a VST3 plugin (no fancy GUI, for now);
print out some data (e.g. plugin name, parameters, ...).
That would be a great start :)
Yeah, VST3 is rather mysterious and poorly documented. There are not many good examples partially because not many companies (other than Steinberg) actually care about VST3. But all cynicism aside, your best bet would be to look at the Juce source code to see their implementation of a VST3 host:
https://github.com/julianstorer/JUCE/blob/master/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
There's a few other VST3-related files in that package which are worth checking out. Anyways, this should at least be enough information to get get you started with a VST3 host.
It's worth noting that Juce is GPL (unless you pay for a license), so it's a big no-no to borrow code directly from it unless you are also using the GPL or have a commercial license. Just a friendly reminder to be a responsible programmer when looking at GPL'd code on the net. :)
Simple VST3 hosts already exist in the VST SDK. It is not difficult to augment them, but there are some things to keep in mind.
The samples under public.skd/vst-hosting in the VST SDK contain an EditorHost and and AudioHost. The first handles the GUI, the second handles the effect (the signal processing). You can combine the two. Neither is a full implementation.
VST objects are COM objects and so you have to make sure to set up the application context correctly, so that your COM objects persist between calls. EditorHost and AudioHost both do that in a couple of lines in a global context variable (look for pluginContext).
If you use separate calls to load and unload effects, process data, and so on, you have to keep COM object pointers, so they are not unloaded. For example, you may be tempted to ignore the Steinberg::Vst::Module module, since you don't need it once the effect is loaded, but you would have to keep a pointer to it somewhere globally or in the main application thread. If not, the automatic unloading of that pointer will also unload the plugin as well and subsequent calls to the plugin will fail.
The construction of VST effects is relatively simple. They consist of a component (the effect) and a controller (the GUI). Both are instantiated when Steinberg::Vst::PlugProvider is loaded (some effects do not have a GUI). Both examples above load a plugprovider. Once you load a plugprovider, you are essentially done.
The following code is sufficient to load a plugprovider (the whole effect). Assume returning -1 means an error:
std::string error;
std::string path = "somepath/someeffect.vst3";
VST3::Hosting::Module::Ptr module =
VST3::Hosting::Module::create(path, error);
if (! module)
return -1;
IPtr<PlugProvider> plugProvider;
VST3::Optional<VST3::UID> effectID = std::move(uid);
for (auto& classInfo : module->
getFactory().classInfos())
{
if (classInfo.category() == kVstAudioEffectClass)
{
if (effectID)
{
if (*effectID != classInfo.ID())
continue;
}
plugProvider = owned(new
PlugProvider(module->getFactory(),
classInfo, true));
break;
}
}
if (! plugProvider)
return -1;
After this, plugProvider->getComponent() and plugProvider->getController() give you the effect and GUI. The controller has to be displayed in a window, of course, which is done in EditorHost. These are the implementations of IComponent,IAudioProcessor and IEditController in the VST SDK.
The source/vst/testsuite part of the VST SDK will show you the full functionality of both of these parts (it will essentially give you the functional calls that you can use to do everything you want to do).
Note the module and plugprovider loaded in the code above. As mentioned above, if you don't keep the module pointer, there is no guarantee the plugprovider pointer will survive. It is difficult to keep track of what gets released when in the VST SDK.
Related
I couldn't find a solution here after searching so I have to ask! Please excuse my language, because I'm pretty new in the NPAPI business.
What I have, is an existing plugin which receives data in a cycle of about 100ms out of a local running xulrunner application comming out of a nsComponent (the dataCreator). The result looks pretty well and the xul app is stable so far. But if I increase the occurance of data (which I have to), the xul app needs too long for reaction and this ends up in xul crashes. I think a XUL->Plugin I/O is a bit expensive!?
What I have learned until now, is that the plugin is able to create a new instance of a component:
// inside myPlugin.cpp
nsresult rv;
nsCOMptr< myCompClass > _myComPtr ;
_myComPtr = do_CreateInstance( "#myDomain.org/DIR/MYCOMPONENT;1", &rv ) ;
The function
do_CreateInstance( ) ;
comes from nsComponentManagerUtlis.h which is out of the xulrunner SDK, but it has nothing like
do_giveMeTheRunningInstanceOf( "#myDomain.org/DIR/MYDATACREATOR;1", &rv ) ;
My intuition now is to use the
nsScriptablePeer::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result )
method to pass a nsCOMptr of the running dataCreator into the plugin, make direct communication possible and reduce the xul<-->plugin I/O to a minimum.
Creating another instance of the dataCreator is definitely not an option!
To be honest: I've no idea how to "convert" the NPVariant (args[0]) into the needed nsCOMptr, did you? Or is there another possibility to receive the pointer inside the plugin?
Thanks for your help
There is no way that I am aware of to interact with the xulrunner sdk directly from a npapi plugin, as they use totally different APIs. NPVariants cannot pass a xulrunner object or other native pointer type.
This is a total brainstorm and I have no idea if it would work, but if you could somehow combine a xulrunner extension and a npapi plugin into the same module, you could probably use a global map and an id from the plugin to get shared memory, but I have no idea if that's possible or not.
You are correct that interfacing with javascript has a cost; really, though, it's the individual calls that have the most cost because they end up being cross-process. Often you can minimize this by using more efficient calls. Faster than 100ms should definitely not be an issue.
I'm debugging a segmentation fault in a php module written by someone for an application (so changing the workflow and other time consuming operations are out of the question).
I have the following code:
...
...some code...
int marker=0;
ENGINE_load_dynamic();
ENGINE *e=ENGINE_by_id("dynamic");
if (e==NULL) return NULL;
...some more code to set some parameters using ENGINE_ctrl_cmd_string(...)
marker++; // gets about 10 or something
e=ENGINE_by_id("pkcs11");
if (e==NULL) return NULL;
Here comes the fun part - SIGSEGV:
marker++; //11
if (!ENGINE_init(e)){
std::cout<<"..error..";
ENGINE_finish(e);
ENGINE_free(e);
ENGINE_cleanup();
return null;
}
...code using pkcs#11 token that does work....
The problem appears in a random manner, sort of. The snippet is part of a php module. The script is called from a PostgreSQL script which in turn is called by another php application residing on another server (don't blame me for this design, I'm here to debug). The SIGSEGV appears when I refresh the main php application page quickly, which I assume it calls the above scripts multiple times concurrently, therefore attempting to use the token from separate processes at the same time.
Are my assumptions correct? can calls to ENGINE_init/finish/free from separate processes using the same token collide and cause a segmentation fault?
The segmentation fault is captured using my handler that picks up the marker value and prints it before exit, it's the simplest method I could come up for sigsegv debug. If this method might yield wrong results I'd appreciate the notification.
Any thoughts?
There's a README.ENGINE that provides a discussion of engines. I'm not sure how useful it will be since it makes some tall claims. For example, "... the source code is reasonably well self-documenting, but some summaries and usage instructions are needed".
But here's something on the dynamic:
The new "dynamic" ENGINE provides a low-overhead way to support
ENGINE implementations that aren't pre-compiled and linked into
OpenSSL-based applications. This could be because existing
compiled-in implementations have known problems and you wish to use
a newer version with an existing application. It could equally be
because the application (or OpenSSL library) you are using simply
doesn't have support for the ENGINE you wish to use, and the ENGINE
provider (eg. hardware vendor) is providing you with a
self-contained implementation in the form of a shared-library. The
other use-case for "dynamic" is with applications that wish to
maintain the smallest foot-print possible and so do not link in
various ENGINE implementations from OpenSSL, but instead leaves you
to provide them, if you want them, in the form of "dynamic"-loadable
shared-libraries. It should be possible for hardware vendors to
provide their own shared-libraries to support arbitrary hardware to
work with applications based on OpenSSL 0.9.7 or later. If you're
using an application based on 0.9.7 (or later) and the support you
desire is only announced for versions later than the one you need,
ask the vendor to backport their ENGINE to the version you need.
How does "dynamic" work?
The dynamic ENGINE has a special flag in its implementation such that
every time application code asks for the 'dynamic' ENGINE, it in fact
gets its own copy of it. As such, multi-threaded code (or code that
multiplexes multiple uses of 'dynamic' in a single application in any
way at all) does not get confused by 'dynamic' being used to do many
independent things. Other ENGINEs typically don't do this so there is
only ever 1 ENGINE structure of its type (and reference counts are used
to keep order). The dynamic ENGINE itself provides absolutely no
cryptographic functionality, and any attempt to "initialise" the ENGINE
automatically fails. All it does provide are a few "control commands"
that can be used to control how it will load an external ENGINE
implementation from a shared-library. To see these control commands,
use the command-line;
openssl engine -vvvv dynamic
The "SO_PATH" control command should be used to identify the
shared-library that contains the ENGINE implementation, and "NO_VCHECK"
might possibly be useful if there is a minor version conflict and you
(or a vendor helpdesk) is convinced you can safely ignore it.
"ID" is probably only needed if a shared-library implements
multiple ENGINEs, but if you know the engine id you expect to be using,
it doesn't hurt to specify it (and this provides a sanity check if
nothing else). "LIST_ADD" is only required if you actually wish the
loaded ENGINE to be discoverable by application code later on using the
ENGINE's "id". For most applications, this isn't necessary - but some
application authors may have nifty reasons for using it. The "LOAD"
command is the only one that takes no parameters and is the command
that uses the settings from any previous commands to actually *load*
the shared-library ENGINE implementation. If this command succeeds, the
(copy of the) 'dynamic' ENGINE will magically morph into the ENGINE
that has been loaded from the shared-library. As such, any control
commands supported by the loaded ENGINE could then be executed as per
normal. Eg. if ENGINE "foo" is implemented in the shared-library
"libfoo.so" and it supports some special control command "CMD_FOO", the
following code would load and use it (NB: obviously this code has no
error checking);
ENGINE *e = ENGINE_by_id("dynamic");
ENGINE_ctrl_cmd_string(e, "SO_PATH", "/lib/libfoo.so", 0);
ENGINE_ctrl_cmd_string(e, "ID", "foo", 0);
ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
ENGINE_ctrl_cmd_string(e, "CMD_FOO", "some input data", 0);
For testing, the "openssl engine" utility can be useful for this sort
of thing. For example the above code excerpt would achieve much the
same result as;
openssl engine dynamic \
-pre SO_PATH:/lib/libfoo.so \
-pre ID:foo \
-pre LOAD \
-pre "CMD_FOO:some input data"
Or to simply see the list of commands supported by the "foo" ENGINE;
openssl engine -vvvv dynamic \
-pre SO_PATH:/lib/libfoo.so \
-pre ID:foo \
-pre LOAD
Applications that support the ENGINE API and more specifically, the
"control commands" mechanism, will provide some way for you to pass
such commands through to ENGINEs. As such, you would select "dynamic"
as the ENGINE to use, and the parameters/commands you pass would
control the *actual* ENGINE used. Each command is actually a name-value
pair and the value can sometimes be omitted (eg. the "LOAD" command).
Whilst the syntax demonstrated in "openssl engine" uses a colon to
separate the command name from the value, applications may provide
their own syntax for making that separation (eg. a win32 registry
key-value pair may be used by some applications). The reason for the
"-pre" syntax in the "openssl engine" utility is that some commands
might be issued to an ENGINE *after* it has been initialised for use.
Eg. if an ENGINE implementation requires a smart-card to be inserted
during initialisation (or a PIN to be typed, or whatever), there may be
a control command you can issue afterwards to "forget" the smart-card
so that additional initialisation is no longer possible. In
applications such as web-servers, where potentially volatile code may
run on the same host system, this may provide some arguable security
value. In such a case, the command would be passed to the ENGINE after
it has been initialised for use, and so the "-post" switch would be
used instead. Applications may provide a different syntax for
supporting this distinction, and some may simply not provide it at all
("-pre" is almost always what you're after, in reality).
So at work I have been working for a few months on a OPOS driver for a few different things. I didn't create the project, but I have taken it over and am the only one developing it. So today I got curious about the way that it was done and I think that it may have started off on the wrong foot. I had to do a little bit of digging to find out that it uses the OPOS drivers from a company called MCS (Monroe Consulting Services) I downloaded 1.13 and installed the MSI version. I fired up VS created a new mfc dll. I then went to add a class. This is where I am confused.
It doesn't matter if i choose Typelib or ActiveX it usually gives me the same list of interfaces that I can add/extend from(with one exception that comes to mind with MSR it has an events interface that I can extend) And they both make the same header file (in the case with msr it is COPOSMSR.h) but one extends CCmdTarget, and the other extends CWnd. This is my first question. Which should I choose? what is a typelib/ what is a ActiveX component and how do they differ from one another.
The one i've been working on extends CCmdTarget. For the life of me I can not figure out how the driver knows to use one of the files (USNMSRRFID) but that is where all the development went into. (I broke it up a bit so it wasn't just one huge file) But that file doesn't extend COPOSMSR..it extends CCmdTarget as well. The only time i see anything mention the USN file is in MSRRFID.idl (which confuses me even more) Any one have clarity for this?
Part of me thinks this could make a very big impact when it comes time to deploy. A few of the test apps that have been written that make use of this driver require a somewhat confusing setup process that involves registering different drivers, copying files into a specific folder, setting up the registry and so forth. I think that if i can get a grip on what this all means and how to make a nice application that extends one of these OPOS devices properly that I could save my self further grief in the future.
Any tips or pointers??? Sorry if it is a newb question..but i am new to C++. I started with Java then moved to C# so some of this stuff is WAY over my head....
Well so I've done TONS of digging, and it is like searching for dinosaurs. Not easy, and hard to find. I will end up writing a nice little how to on this, but for now I will put up my findings. Although I still don't have this 100% i know I am close.
Turns out the typelib and activeX things are not a big concern but come into play after you've gotten started. ActiveX is for Control objects, and Typelib is for the Service Object. The most important thing is to get started correctly. I found a article on some Chinese website that offers some OK tips after figuring out the translation errors. To start with you will want to make a C++ project with Automation. It can be ATL or MFC. My preference is MFC. In the UPOS 1.13 pdf (or newer) in Appendix A section 8 it describes the responsibilities of the Service object. It has the main methods you need to implement. There are 16 methods you have to add, and at least 4 methods that get/set the properties for your OPOS device.
So to get started you will need to open up the add class wizard (for MFC classes) and click Add MFC class. You wil want your base class to be CCmdTarget. Come up with a classy Class name (I chose PinpadSOCPP) Then in the automation radio buttons select Creatable by type ID. It should fill in your type id as [Project Name].[Class name] so mine was PinpadSO.PinpadSOCPP. hit finish. This makes a nice interface file that you can use Class view to add methods and so forth to it.
As for adding the methods there are 2 things to note about this, and one of them I haven't figured out 100% yet. The first is that you have to implement all the methods in that section with the correct parameters and return values. Most of them return LONG (32bit signed number). and the 2 most common parameters are LONG and BSTR. (there is the occasional pointers for when you have "out" parameters) This is the part that I think that I am currently failing as I don't know if I have them all implemented correctly and that is why I am getting error 104/305 (which from the Chinese article says that I am missing something from my methods) I'm not sure if it is case sensitive, and I'm not sure of the 7 properties that look to need to have get/set which ones need to be implemented because the MSR SO that i am working on from work doesn't use them all and that SO is working. The other is that after you implement the base OPOS methods you have to also implement the extra methods from your specific OPOS device. Since I am doing PINPad there are 6 additional methods I have to implement.
Now this is a lot of time consuming work because you have to open up class view, navigate to the name of your project class. Expand it and go to the Interface portion. My Project name is PinpadSO, and the file that I am implementing this in is PinpadSOCPP (which means the interface name is IPinpadSOCPP) right click on IPinpadSOCPP and click add > add method. This brings you to a 2 step process. You fill in your return value, name of your function, add in all your parameters. Hit next and fill out some help string info (if you want) and hit finish. Now after you do that 20+ times it gets old and slow...and if you are like me you type Computer instead of Compute and flip flop letters, or forget to hit add on all your parameters. A person could make a nice little program to edit the 3 files that get changed each time you add a method and that would speed it up considerably. If you make a mistake you will need to open up [project name].idl, [class name].h, and [class name].cpp those are the 3 files that get the methods added to it directly. I recommend not making a mistake.
so now that all that hard work is out of the way. Compile your program. If you want to save your self an extra step you could turn on Auto Register in the linker project settings (NOTE: if you do that you'll need to run Visual Studio as admin if you program in vista or higher) this would save you of having to open a command window (admin) navigate to your DLL and use the command regsvr32 on that DLL. Nice thing is that you don't have to do that over and over again, just the once will do. I have no hard facts that it works like that every time but the MSR SO that I am working on, I'll make changes to it, compile it, then open up my OPOS tester program and the changes have taken affect.
After that you need to make your registry additions. navigate to HKLM\software\OLEforRetail\ServiceOPOS
(NOTE if you have a x64 machine you'll do this twice. One there, and again at HKLM\software\Wow6432Node\OLEforRetail\ServiceOPOS )
You'll need to add a Key for whatever OPOS device you are working with. I am making a pinpad SO so I made a Key called PINPad (check your UPOS document to see what name you should give it) Lastly choose a name for your device. I chose the model type of the from the vendor as my device name (C100) and made a sub key in PINPad. The default REG_SZ value needs to be your registered SO Device TypeID. in my case it is PinpadSO.PinpadSOCPP
if you don't have a OPOS test program (which I just made my own as a console program) then you can use the Microsoft OPOS test app (I couldn't get it to work on my x64 machine...but maybe you'll have better luck with it) If you do decide to make your own OPOS test app make sure you compile it for x86 machines (even if you have x64) OPOS does not like x64 for some reason (probably the pointers length I'd assume)..at any rate. Once you got it all setup run your test app (for my case I am just running OPOSPinpadClass pin = new OPOSPinpadClass(); Console.WriteLine(pin.Open("C100")); and hope for 0 :)
I am currently getting 104 (E_NOSERVICE)..and like i said before i think it is because I don't have all my methods correct. If that turns out to be the case I'll edit this response, or I'll report back and say what it really was.
Anywho, i hope this helps anyone else who decides they want to make their own SO. Good luck
UPDATE
OPOS checks a couple of properties when you call the Open command. One of the properties that is a must to implement is the in the GetPropertyNumber, and it is PIDX_ServiceObjectVersion. You will need to set this number to return (1000000 * majorVersion) + (1000 * minorVersion) + revision since I am making a OPOS 1.13 compatible SO my returned ServiceObjectVersion is 1013000. You will also want to implement 3 properties in GetPropertyString:
PIDX_DeviceDescription
PIDX_DeviceName
PIDX_ServiceObjectDescription
For all other values you can return a empty string or 0 until you start hooking all those things up.
As a side note if you don't want to make it in C++ you don't have to. You can make it in any language that you can write a ActiveX object in (such as a COM visible .NET class library)
Suppose I have an OpenGL game running full screen (Left 4 Dead 2). I'd like to programmatically get a screen grab of it and then write it to a video file.
I've tried GDI, D3D, and OpenGL methods (eg glReadPixels) and either receive a blank screen or flickering in the capture stream.
Any ideas?
For what it's worth, a canonical example of something similar to what I'm trying to achieve is Fraps.
There are a few approaches to this problem. Most of them are icky, and it totally depends on what kind of graphics API you want to target, and which functions the target application uses.
Most DirectX, GDI+ and OpenGL applications are double or tripple-buffered, so they all call:
void SwapBuffers(HDC hdc)
at some point. They also generate WM_PAINT messages in their message queue whenever the window should be drawn. This gives you two options.
You can install a global hook or thread-local hook into the target process and capture WM_PAINT messages. This allows you to copy the contents from the device context just before the painting happens. The process can be found by enumerating all the processes on the system and look for a known window name, or a known module handle.
You can inject code into the target process's local copy of SwapBuffers. On Linux this would be easy to do via the LD_PRELOAD environmental variable, or by calling ld-linux.so.2 explicitly, but there is no equivalient on Windows. Luckily there is a framework from Microsoft Research which can do this for you called Detours. You can find this here: link.
The demoscene group Farbrausch made a demo-capturing tool named kkapture which makes use of the Detours library. Their tool targets applications that require no user input however, so they basically run the demos at a fixed framerate by hooking into all the possible time functions, like timeGetTime(), GetTickCount() and QueryPerformanceCounter(). It's totally rad. A presentation written by ryg (I think?) regarding kkapture's internals can be found here. I think that's of interest to you.
For more information about Windows hooks, see here and here.
EDIT:
This idea intrigued me, so I used Detours to hook into OpenGL applications and mess with the graphics. Here is Quake 2 with green fog added:
Some more information about how Detours works, since I've used it first hand now:
Detours works on two levels. The actual hooking only works in the same process space as the target process. So Detours has a function for injecting a DLL into a process and force its DLLMain to run too, as well as functions that are supposed to be used in that DLL. When DLLMain is run, the DLL should call DetourAttach() to specify the functions to hook, as well as the "detour" function, which is the code you want to override with.
So it basically works like this:
You have a launcher application who's only task is to call DetourCreateProcessWithDll(). It works the same way as CreateProcessW, only with a few extra parameters. This injects a DLL into a process and calls its DllMain().
You implement a DLL that calls the Detour functions and sets up trampoline functions. That means calling DetourTransactionBegin(), DetourUpdateThread(), DetourAttach() followed by DetourTransactionEnd().
Use the launcher to inject the DLL you implemented into a process.
There are some caveats though. When DllMain is run, libraries that are imported later with LoadLibrary() aren't visible yet. So you can't necessarily set up everything during the DLL attachment event. A workaround is to keep track of all the functions that are overridden so far, and try to initialize the others inside these functions that you can already call. This way you will discover new functions as soon as LoadLibrary have mapped them into the memory space of the process. I'm not quite sure how well this would work for wglGetProcAddress though. (Perhaps someone else here has ideas regarding this?)
Some LoadLibrary() calls seem to fail. I tested with Quake 2, and DirectSound and the waveOut API failed to initalize for some reason. I'm still investigating this.
I found a sourceforge'd project called taksi:
http://taksi.sourceforge.net/
Taksi does not provide audio capture, though.
I've written screen grabbers in the past (DirectX7-9 era). I found good old DirectDraw worked remarkably well and would reliably grab bits of hardware-accelerated/video screen content which other methods (D3D, GDI, OpenGL) seemed to leave blank or scrambled. It was very fast too.
I am trying to develop an IThumbnailProvider for use in Windows 7. Since this particular thumbnail would also be dependant on some other files in the same directory, I need to use something other than IInitializeWithStream to a path to work with, this being IInitializeWithItem. (Alternatively, I could use IInitializeWithFile, but that is even more frowned upon apparently.)
No matter what I do, I cannot get it to work. I have Microsoft's FileTypeVerifier.exe tool which gives the green light on using IInitializeWithItem, but when explorer calls it, it only seems to try IInitializeWithStream, ever. (This was tested by temporarily implementing said interface, and Beep()ing away in its Initialize()) Did I forget to configure something?
In short: how do I get this to work?
Okay, I finally found out what is the matter. To quote the Building Thumbnail Providers link on the MSDN website:
There are cases where initialization with streams is not possible. In scenarios where your thumbnail provider does not implement IInitializeWithStream, it must opt out of running in the isolated process where the system indexer places it by default when there is a change to the stream. To opt out of the process isolation feature, set the following registry value.
HKEY_CLASSES_ROOT
CLSID
{66742402-F9B9-11D1-A202-0000F81FEDEE}
DisableProcessIsolation = 1
I knew I was running out of process since I read elsewhere that thumbnailproviders ALWAYS ran out of process. But since that particular snippet is on almost -all- shell extension handlers, I interpreted it to be a overly happy copy-paste job, since it was -required- to run in-process the way I understood it.
And I was wrong. I hope this will help someone else in the near future. :)