|
|
|
06-12-2021, 09:07 AM
|
#1
|
Human being with feelings
Join Date: Dec 2020
Location: Miami, FL USA
Posts: 396
|
[NEWS] Reaper VST UI embedding, C++ SDK access merged to JUCE, with official example!
It's been a long journey, but we've arrived at the finish line!
https://github.com/juce-framework/JU...ment-859547159
This would not have been possible without the help of, by no exaggeration, nearly a dozen people, but let us give special thanks and recognition to:
- reuk - JUCE core dev team.
- He provided feedback, answered my incessant questions every step of the way, let me bug him every single week for a status update, and ultimately wrote the final implementation and the JUCE official example.
- This is largely reuk's work.
- Schwa
- Helping me debug & telling me what REAPER was seeing
- Sharing the section of REAPER code that does the queryInterface() for IReaperUIEmbed and then calls the embed_message()
- Patching the VST3 interface to fix a small issue then releasing, a day after reporting a bug
- Gertius (https://forums.cockos.com/member.php?u=53591)
- He contributed the first VST2 sample which contained the implementation for conversion of a juce::Component to a bitmap that was then copied into a LICE bitmap
See here for the official example (supports both VST2 and VST3):
https://github.com/juce-framework/JU...aaa300baf5d524
https://github.com/juce-framework/JU...ewPluginDemo.h
Code:
/* This demo shows how to use the VSTCallbackHandler and VST3ClientExtensions
classes to provide extended functionality in compatible VST/VST3 hosts.
If this project is built as a VST or VST3 plugin and loaded in REAPER
6.29 or higher, it will provide an embedded level meter in the track
control panel. To enable the embedded view, right-click on the plugin
and select "Show embedded UI in TCP".
The plugin's editor also include a button which can be used to toggle
all inserts on and off.
*/
And a little bit of humor in the example:
PHP Code:
case REAPER_FXEMBED_WM_GETMINMAXINFO: return getSizeInfo (reinterpret_cast<reaper::REAPER_FXEMBED_SizeHints*> (parm3));
// Implementing mouse behaviour is left as an exercise for the reaper, I mean reader case REAPER_FXEMBED_WM_CREATE: break; case REAPER_FXEMBED_WM_DESTROY: break; case REAPER_FXEMBED_WM_SETCURSOR: break; case REAPER_FXEMBED_WM_MOUSEMOVE: break; case REAPER_FXEMBED_WM_LBUTTONDOWN: break; case REAPER_FXEMBED_WM_LBUTTONUP: break; case REAPER_FXEMBED_WM_LBUTTONDBLCLK: break; case REAPER_FXEMBED_WM_RBUTTONDOWN: break; case REAPER_FXEMBED_WM_RBUTTONUP: break; case REAPER_FXEMBED_WM_RBUTTONDBLCLK: break; case REAPER_FXEMBED_WM_MOUSEWHEEL: break;
__________________
Seasoned codemonkey
Dunno a thing about making music (here to learn!)
Last edited by gxray; 06-12-2021 at 09:19 AM.
|
|
|
06-12-2021, 09:17 AM
|
#2
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Yay, great news!
Thank you for starting this and to all involved.
|
|
|
06-12-2021, 09:34 AM
|
#3
|
Human being with feelings
Join Date: Dec 2020
Location: Miami, FL USA
Posts: 396
|
Quote:
Originally Posted by nofish
Yay, great news!
Thank you for starting this and to all involved.
|
\o/ thanks!
(How cool is it that REAPER headers are now in JUCE source btw?)
https://github.com/juce-framework/JU...Plugins/extern
What is also exciting is that the changes made to support this were not just for REAPER's UI embedding (though it started out that way).
It's now possible to "install" custom VST3 interfaces on JUCE's default ones, to add support for features they don't have out of the box.
This is going to be useful for the Surge synth team as well, since they need one of the VST3 interfaces for custom context menus and they had it in VSTGUI but JUCE doesn't support it OOB.
This allows you to also get the hostContext pointer and whatnot too:
PHP Code:
struct VST3ClientExtensions
{
virtual ~VST3ClientExtensions() = default;
/** This function may be used by implementations of queryInterface()
in the VST3's implementation of IEditController to return
additional supported interfaces.
*/
virtual int32_t queryIEditController (const Steinberg::TUID, void** obj)
{
*obj = nullptr;
return -1;
}
/** This function may be used by implementations of queryInterface()
in the VST3's implementation of IAudioProcessor to return
additional supported interfaces.
*/
virtual int32_t queryIAudioProcessor (const Steinberg::TUID, void** obj)
{
*obj = nullptr;
return -1;
}
/** This may be called by the VST3 wrapper when the host sets an
IComponentHandler for the plugin to use.
You should not make any assumptions about how and when this will be
called - this function may not be called at all!
*/
virtual void setIComponentHandler (Steinberg::FUnknown*) {}
/** This may be called shortly after the AudioProcessor is constructed
with the current IHostApplication.
You should not make any assumptions about how and when this will be
called - this function may not be called at all!
*/
virtual void setIHostApplication (Steinberg::FUnknown*) {}
};
The way it works is that when you override/provide an implementation of these virtual functions for querying interfaces on the IAudioProcessor and IEditController, JUCE will try to resolve them along with it's own IID's.
PHP Code:
template <typename Member>
static QueryInterfaceResult queryAdditionalInterfaces (AudioProcessor* processor,
const TUID targetIID,
Member&& member)
{
if (processor == nullptr)
return {};
void* obj = nullptr;
if (auto* extensions = dynamic_cast<VST3ClientExtensions*> (processor))
{
const auto result = (extensions->*member) (targetIID, &obj);
return { result, obj };
}
return {};
}
User-specified implementations take precedence too, so there's in theory no limitation on what extra functionality you can add (as long as it's in the VST3 interfaces and some component is going to query for it from either the EditController or AudioProcessor
__________________
Seasoned codemonkey
Dunno a thing about making music (here to learn!)
|
|
|
06-12-2021, 10:49 AM
|
#4
|
Human being with feelings
Join Date: Jan 2021
Posts: 10
|
Thanks for the kind words, I'm looking forward to seeing how this feature is used! I wanted to add a few words to some of the points you made:
Quote:
Originally Posted by gxray
This is going to be useful for the Surge synth team as well, since they need one of the VST3 interfaces for custom context menus and they had it in VSTGUI but JUCE doesn't support it OOB.
|
I added built-in support for VST3 parameter menus recently, too: here
In the DSPModulePluginDemo, right-clicking a slider will now display a PopupMenu with some host-provided entries. Adding this functionality using the new extensions support would be a bit tricky, because it would require leaking quite a lot of low-level knowledge of the VST3 API. Providing a higher-level JUCE-ified interface seemed like a cleaner solution than exposing all the necessary bits and pieces.
Quote:
Originally Posted by gxrgay
User-specified implementations take precedence too, so there's in theory no limitation on what extra functionality you can add (as long as it's in the VST3 interfaces and some component is going to query for it from either the EditController or AudioProcessor
|
Although this is true, I'd *strongly* recommend avoiding duplicating interfaces that JUCE already implements. If you run into problems with the JUCE implementation, please let us know on the JUCE forum. Hopefully we'll be able to find a way of accommodating the desired behaviour right in our wrapper (unless the desired behaviour is very esoteric or would break existing plugins).
Also, if you find yourself implementing an extension which is supported in multiple hosts (like the parameter menus), we'd like to hear about it. There's a good chance we'll be able to provide a friendlier interface than the raw VST3 API. Depending on the extension, we may be able to add support for other plugin formats too.
|
|
|
06-12-2021, 09:03 PM
|
#5
|
Human being with feelings
Join Date: Dec 2017
Location: Brazil
Posts: 1,992
|
hey gxray, reuk and any other involved in this, thanks a lot for your time and efform just waiting to see it being used to make some cool integration even further inside reaper!
|
|
|
06-12-2021, 11:31 PM
|
#6
|
Human being with feelings
Join Date: Feb 2017
Posts: 4,813
|
Seems amazing, altho i won't use it. 1280 x 800 screen here and i don't want to change it
I wish reaper could have a proper window/inspector with all this stuff, instead of trying to do everything in TCP, MCP.
Cockos please do a CSP - Channel Settings Panel.
__________________
🙏🏻
|
|
|
06-12-2021, 11:51 PM
|
#7
|
Human being with feelings
Join Date: May 2014
Location: Germany
Posts: 643
|
Wow, this is cool. Just explored the stuff, very usefull. Thank you!
|
|
|
06-13-2021, 03:44 PM
|
#8
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Based on the JUCE ReaperEmbeddedViewPluginDemo.h example I'm trying to get the parent track (the track the VST3 lives on) but doesn't work (see code below)
Am I doing something wrong?
Code:
void setIHostApplication (Steinberg::FUnknown* ptr) override
{
if (ptr == nullptr)
return;
void* objPtr = nullptr;
if (ptr->queryInterface (reaper::IReaperHostApplication::iid, &objPtr) == Steinberg::kResultOk)
{
// this from the example code works
if (void* fnPtr = static_cast<reaper::IReaperHostApplication*> (objPtr)->getReaperApi ("BypassFxAllTracks"))
globalBypassFn = reinterpret_cast<void (*) (int)> (fnPtr);
// this (my code) always returns null, why?
if (void* foo = static_cast<reaper::IReaperHostApplication*> (objPtr)->getReaperParent(1))
// ...
}
}
Last edited by nofish; 06-14-2021 at 06:02 AM.
|
|
|
06-13-2021, 10:18 PM
|
#9
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Many thanks to those who made this happen !
I'll try to port my current unofficial example to the official API ASAP. (Might take some days due to some - not so bad - illness.)
Thanks again to those who made it possible !
-Michael
Last edited by mschnell; 06-14-2021 at 07:07 AM.
|
|
|
06-14-2021, 07:03 AM
|
#10
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by nofish
Based on the JUCE ReaperEmbeddedViewPluginDemo.h example I'm trying to get the parent track (the track the VST3 lives on) but doesn't work (see code below)
Am I doing something wrong?
|
I would not try to implement a way to use just a single API function.
REAPERAPI_LoadAPI(getfuncaddr); is provided to cereate normally callable functions for all (or an arbitrary set of) the Reaper API functions.
I'll try port my example (see the other thread and maybe the source code for details) to the new official JUCE standard ASAP. Here (and also in a VST2) I successfully used REAPERAPI_LoadAPI .
-Michael
Last edited by mschnell; 06-15-2021 at 05:53 AM.
|
|
|
06-15-2021, 04:54 AM
|
#11
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Can't get it to work to get the host context (parent track) for a VST2 plugin either (though I'm more interested in doing this in a VST3), what am I missing?
Code:
void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& hostcb) override
{
// this from the example code works
char functionName[] = "BypassFxAllTracks";
globalBypassFn = reinterpret_cast<void (*) (int)> (hostcb ((int32_t) 0xdeadbeef, (int32_t) 0xdeadf00d, 0, functionName, 0.0));
// this (my code) always returns null, why?
// reference: https://www.reaper.fm/sdk/vst/vst_ext.php#vst_hostctx
void* foo = (void*)hostcb(0xdeadbeef, 0xdeadf00e, 1, nullptr, 0.0);
}
(Reaper v6.29, Win 8.1)
Last edited by nofish; 06-15-2021 at 05:47 AM.
|
|
|
06-15-2021, 04:59 AM
|
#12
|
Human being with feelings
Join Date: May 2020
Posts: 434
|
hmmm interesting
what is this?
what can you actually do with this that you couldn't do with scripts so far?
not a programmer here.
|
|
|
06-15-2021, 05:01 AM
|
#13
|
Human being with feelings
Join Date: Mar 2019
Posts: 425
|
Awesome! Big thanks to everyone involved
|
|
|
06-15-2021, 05:19 AM
|
#14
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Quote:
Originally Posted by UknownSource
hmmm interesting
what is this?
what can you actually do with this that you couldn't do with scripts so far?
not a programmer here.
|
You can make plugins which can have their GUIs embedded in Reaper TCP/MCP (and use the Reaper API functions).
(You could make this before also but with this it can get more straight forward as the JUCE framework can be used.)
This is the provided example plugin.
Last edited by nofish; 06-15-2021 at 05:25 AM.
|
|
|
06-15-2021, 06:00 AM
|
#15
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by nofish
Can't get it to work to get the host context (parent track) for a VST2 plugin either
|
You might want to take a look at my example code (-> www.bschnell.de/VST3_Test_mschnell.zip ) for that as well.
It does not compile for VST2 due to some twists with the CBuild configuration, but the appropriate code (within the #if _Build_VST == 2 sections) should work as is is just a copy from a pure VST2 project.
-Michael
Last edited by mschnell; 06-28-2021 at 04:24 AM.
|
|
|
06-15-2021, 06:03 AM
|
#16
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by UknownSource
h
what can you actually do with this that you couldn't do with scripts so far?
|
E.g.:
It produces plugins like JSFX "scripts".
It can access the complete Reaper API like Reaper Scrips .
It uses C++ language which can be a lot faster that scrips.
It can use all features of the operating system Reaper is running in.
It can rather easily produce a nice and sophisticated GUI.
It can read and write files.
It can use the network.
it can use any hardware devices that are not supported by Reaper.
-Michael
|
|
|
06-15-2021, 07:01 AM
|
#17
|
Human being with feelings
Join Date: May 2020
Posts: 434
|
Quote:
Originally Posted by mschnell
E.g.:
It produces plugins like JSFX "scripts".
It can access the complete Reaper API like Reaper Scrips .
It uses C++ language which can be a lot faster that scrips.
It can use all features of the operating system Reaper is running in.
It can rather easily produce a nice and sophisticated GUI.
It can read and write files.
It can use the network.
it can use any hardware devices that are not supported by Reaper.
-Michael
|
can you make an fx container with this?
|
|
|
06-15-2021, 10:34 AM
|
#18
|
Human being with feelings
Join Date: Nov 2006
Posts: 855
|
Quote:
Originally Posted by mschnell
E.g.:
It produces plugins like JSFX "scripts".
It can access the complete Reaper API like Reaper Scrips .
It uses C++ language which can be a lot faster that scrips.
It can use all features of the operating system Reaper is running in.
It can rather easily produce a nice and sophisticated GUI.
It can read and write files.
It can use the network.
it can use any hardware devices that are not supported by Reaper.
-Michael
|
Ooh wow, didn;t know it brought all of this, very exciting
|
|
|
06-15-2021, 01:05 PM
|
#19
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by UknownSource
can you make an fx container with this?
|
Yes, but not as perfect as it should be.
-Michael
|
|
|
06-15-2021, 01:09 PM
|
#20
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by todd_r
Ooh wow, didn;t know it brought all of this
|
That's some of the differences vs. scripts. Of course you could do VST2 with all those features using JUCE and also not JUCE based VST3s since some time.
-Michael
Last edited by mschnell; 06-16-2021 at 03:29 PM.
|
|
|
06-17-2021, 10:40 AM
|
#21
|
Human being with feelings
Join Date: Sep 2018
Location: Oxford, England
Posts: 218
|
Is there any official Reaper documentation about these extensions for those of us who don't use JUCE?
|
|
|
06-17-2021, 01:08 PM
|
#23
|
Human being with feelings
Join Date: Sep 2018
Location: Oxford, England
Posts: 218
|
Quote:
Originally Posted by nofish
There's only the header files with some comments afaik...
|
Got it - thanks, I think that's all I need.
|
|
|
06-20-2021, 05:34 AM
|
#24
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Sorry for my ignorance, but I seem to be unable to build a VTS3 using the "ReaperEmbeddedViewPluginDemo.h" example provided by the d/l of "JUCE-4b0b245b55429b33a638ccea94aaa300baf5d524". In VS Code, it does not provide the option to build examples.
As this supposedly right now is the only source of documentation on how to use the "official" JUCE way of doing VST3s (and VSTs ? ) with DAW specific extensions, I can't port my demo project yet. (I understand I will need to slightly modify as well the CMakeLists.txt and the source code in the "PluginProcessor.*" files.
Did anybody succeed with that ?
Thanks for any hints !
-Michael
|
|
|
06-20-2021, 11:30 AM
|
#25
|
Human being with feelings
Join Date: May 2020
Posts: 434
|
Quote:
Originally Posted by mschnell
Yes, but not as perfect as it should be.
-Michael
|
show me! lol
|
|
|
06-20-2021, 02:46 PM
|
#26
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by UknownSource
show me! lol
|
In the appropriate forum threads in "Feature Requests" you'll find multiple attempts already made
-Michael
Last edited by mschnell; 06-22-2021 at 10:18 PM.
|
|
|
06-22-2021, 01:56 PM
|
#27
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by mschnell
Sorry for my ignorance, ... Thanks for any hints !
|
@gxray:
Do you have a "dedicated" example project (or some documentation) using this feature that has a dedicated CMakeLists.txt file and *.cpp file instead of being integrated in an example suite ?
Thanks a lot
-Michael ( not being able to extract the necessary information from the "ReaperEmbeddedViewExample.h" example provided by reuk )
|
|
|
06-27-2021, 10:12 PM
|
#28
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
With help by reuk, I seem to have gotten this sorted out.
I'll upload a new version of the example project ASAP.
-Michael
|
|
|
06-28-2021, 04:28 AM
|
#29
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by mschnell
I would not try to implement a way to use just a single API function.
REAPERAPI_LoadAPI(getfuncaddr); is provided to cereate normally callable functions for all (or an arbitrary set of) the Reaper API functions.
I'll try port my example (see the other thread and maybe the source code for details) to the new official JUCE standard ASAP. Here (and also in a VST2) I successfully used REAPERAPI_LoadAPI .
-Michael
|
@nofish:
Trying exactly this, I see the problem you are having.
The getfuncaddr() function needs a constant value for " reaperApplicationPtr" (named " reaper" in my original example code, but renamed as in the newe JUCE version "reaper" is a namespace), which is defined as FUnknownPtr<reaper::IReaperHostApplication> reaperApplication and needs to be set in setIHostApplication().
While this worked fine in my pre-pre release example, I am struggling with defining the type of that variable.
Did you already find out more ?
-Michael
Last edited by mschnell; 06-28-2021 at 04:55 AM.
|
|
|
06-28-2021, 02:17 PM
|
#30
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
I uploaded a draft version of the example project (-> www.bschnell.de/VST3_Test_mschnell.zip ).
It seems to work as a VST3. I'll try to make it compilable as a VST2 ASAP.
It demonstrates the Reaper Embedded VST view and the implementation of the complete Reaper API as native local functions.
Please come up with any comments !
-Michael
|
|
|
07-03-2021, 06:49 AM
|
#31
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Quote:
Originally Posted by mschnell
With help by reuk, I seem to have gotten this sorted out.
I'll upload a new version of the example project ASAP.
-Michael
|
I uploaded the new version of the example project on the stash as embedded_plugin.zip.
Please check out and post any comments !
Thanks,
-Michael
|
|
|
09-23-2021, 11:46 AM
|
#32
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
JUCE 6.1 has just (edit: well, in August) been released where this has become official.
Quote:
VST3 Plug-in Extensions
JUCE's VST3 backend has been redesigned, offering greater compatibility with the VST3 specification and enabling access to VST3-specific extensions. Plug-in developers can now access a much richer interface to any DAWs that provide their own set of extensions, such as those published by PreSonus, Cockos and others.
|
Thanks again to all involved!
Last edited by nofish; 09-23-2021 at 12:40 PM.
|
|
|
09-23-2021, 02:03 PM
|
#33
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,690
|
Checking this already is very high on my ToDo list
-Michael
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 06:09 AM.
|