Need help: Most basic VST3 Plugin is crashing on savihost

projucer

#1

I found that the most basic vst3 audio plugin crashes on savihost.
(Vst2 and standalone versions run just fine.)
This is what I did to build and run a simple Hello World example:

  • create a new Prodjucer Plugin Project with VS2015 exporter
  • add VST3 and standalone Targets
  • add module “juce_audio_utils”
  • set the I/O configuration to {2,2}
  • add win32 platform
  • save and open in IDE
  • start debug session using Savihost

The x64 version throws an exception before the editor window is displayed.

Exception thrown: read access violation.
this->cachedImage.object was 0xFFFFFFFFFFFFFFFF.

(It breaks in juce_Component.cpp line 1152)

void Component::setBounds ( ...
(...)
        else if (cachedImage != nullptr)
        {
->          cachedImage->invalidateAll();
        }

The win32 version starts up with the main component resized to (0,0,0,0).
On closing savihost the plugin crashes.

I am new to VST3 development and I wonder: Am I doing something wrong, is there a problem with Juce or should I just forget about using Savihost as a test environment?


#2

Here is the jucer project.

<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="sqcFCr" name="CrashTest" displaySplashScreen="1" reportAppUsage="1"
              splashScreenColour="Dark" projectType="audioplug" version="1.0.0"
              bundleIdentifier="com.yourcompany.CrashTest" includeBinaryInAppConfig="1"
              buildVST="1" buildVST3="1" buildAU="1" buildAUv3="0" buildRTAS="0"
              buildAAX="1" buildStandalone="1" enableIAA="0" pluginName="CrashTest"
              pluginDesc="CrashTest" pluginManufacturer="yourcompany" pluginManufacturerCode="Manu"
              pluginCode="Sqcf" pluginChannelConfigs="{2,2}" pluginIsSynth="0"
              pluginWantsMidiIn="1" pluginProducesMidiOut="0" pluginIsMidiEffectPlugin="0"
              pluginEditorRequiresKeys="0" pluginAUExportPrefix="CrashTestAU"
              pluginRTASCategory="" aaxIdentifier="com.yourcompany.CrashTest"
              pluginAAXCategory="AAX_ePlugInCategory_Dynamics" jucerVersion="5.0.1">
  <MAINGROUP id="o7cG8x" name="CrashTest">
    <GROUP id="{F16B92ED-5351-00DE-EC90-360E3E155A1A}" name="Source">
      <FILE id="j7HFYA" name="PluginProcessor.cpp" compile="1" resource="0"
            file="Source/PluginProcessor.cpp"/>
      <FILE id="ob5s12" name="PluginProcessor.h" compile="0" resource="0"
            file="Source/PluginProcessor.h"/>
      <FILE id="Q2JXRr" name="PluginEditor.cpp" compile="1" resource="0"
            file="Source/PluginEditor.cpp"/>
      <FILE id="jLeCf6" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
    </GROUP>
  </MAINGROUP>
  <EXPORTFORMATS>
    <VS2015 targetFolder="Builds/VisualStudio2015" vst3Folder="" aaxFolder="">
      <CONFIGURATIONS>
        <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
                       isDebug="1" optimisation="1" targetName="CrashTest"/>
        <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
                       isDebug="0" optimisation="3" targetName="CrashTest"/>
        <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
                       isDebug="1" optimisation="1" targetName="CrashTest"/>
        <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
                       isDebug="0" optimisation="3" targetName="CrashTest"/>
      </CONFIGURATIONS>
      <MODULEPATHS>
        <MODULEPATH id="juce_core" path="../../modules"/>
        <MODULEPATH id="juce_events" path="../../modules"/>
        <MODULEPATH id="juce_graphics" path="../../modules"/>
        <MODULEPATH id="juce_data_structures" path="../../modules"/>
        <MODULEPATH id="juce_gui_basics" path="../../modules"/>
        <MODULEPATH id="juce_gui_extra" path="../../modules"/>
        <MODULEPATH id="juce_cryptography" path="../../modules"/>
        <MODULEPATH id="juce_video" path="../../modules"/>
        <MODULEPATH id="juce_opengl" path="../../modules"/>
        <MODULEPATH id="juce_audio_basics" path="../../modules"/>
        <MODULEPATH id="juce_audio_devices" path="../../modules"/>
        <MODULEPATH id="juce_audio_formats" path="../../modules"/>
        <MODULEPATH id="juce_audio_processors" path="../../modules"/>
        <MODULEPATH id="juce_audio_plugin_client" path="../../modules"/>
        <MODULEPATH id="juce_audio_utils" path="../../modules"/>
      </MODULEPATHS>
    </VS2015>
  </EXPORTFORMATS>
  <MODULES>
    <MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_core" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_cryptography" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_events" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0"/>
    <MODULE id="juce_video" showAllCode="1" useLocalCopy="0"/>
  </MODULES>
  <JUCEOPTIONS JUCE_QUICKTIME="disabled" JUCE_ASIO="enabled" JUCE_WASAPI="enabled"
               JUCE_WASAPI_EXCLUSIVE="enabled" JUCE_DIRECTSOUND="enabled" JUCE_ALSA="enabled"
               JUCE_JACK="enabled"/>
</JUCERPROJECT>

#3

Just to help us narrow down and reproduce the problem: Is this only in savihost? Can you test another more mainstream host such as Cubase?


#4

The problem is not present on the Steinberg VST3 test host and the Juce VST Host
(I am afraid I can not test with Cubase at the moment.)

I’d be very interested to know if anybody else has successfully used a juce5 created VST3 Plugin with Savihost?


#5

JFTR -

I’ve just uploaded a new beta of SAVIHost to http://www.hermannseib.com/programs/beta/ that works better with JUCE VST3 PlugIns.


#6

I have just heard from Hermann Seib (savihost developer). Once I had informed him of the problem he started rightaway to work it out. He has already created a fix for the issue that will be made available with the next release of the software.

Here is some background information he gave me (with english translation by me)
You might find it useful since Juce should not have any problems regardless of how many editors are attached to the processor. (that is at least what I understood from reading the documentation.)

[Quote]
(…) das Problem liegt zwar teilweise bei JUCE, tritt aber nur in einer sehr speziellen Kombination auf, die SAVIHost verwendete.

While the issue is partially with Juce, it will only show up under a certain circumstances, that were used by SAVIHost

Pseudocode:

Vst::IEditController *editController;
Vst::IPlugView *pVew, *pViewTemp;

pView = editController->createView(Vst::ViewType::kEditor);
pView->setFrame(<SAVIHost Host Interface>);
ViewRect vr;
pView->getSize(&vr);
...
pViewTemp = editController->createView(Vst::ViewType::kEditor);
pViewTemp->release();
...
pView->attached(<SAVIHost client window handle>);

Also zwischendurch mal eine temporäre editor view angelegt und wieder weggeworfen und dann mit der ersten View weitergearbeitet. Das dürfte JUCE ziemlich durcheinander bringen.

Also zwischendurch mal eine temporäre editor view angelegt und wieder weggeworfen und dann mit der ersten View weitergearbeitet. Das dürfte JUCE ziemlich durcheinander bringen.

In short: Savihost used to create a temporary view that was disposed of rightaway and then it continued to work with the original view

Nachdem der einzige Zweck dieser temporären view ist, herauszufinden, ob das PlugIn überhaupt einen Editor öffnen kann, prüfe ich jetzt vorab, ob schon eine view da ist (die ich vorher zum Ermitteln der Fenstergröße bereits angelegt habe); wenn ja, brauche ich die temporäre view nicht anzulegen, weil eh alles klar ist.

Since the only purpose of the of that temporary view is to find out wether the plugin is able to create an editor I am now checking in advance if one is already present. (that is beeing created anyway in order to get the editor panel size) ; if so there is no point in creating another temporary view.

… und das war’s im Prinzip.

… and that’s it.

Nota bene: VST3 enthält weder in Dokumentation noch Source Code irgendwelche Hinweise, dass das Anlegen mehrerer Editor Views schlecht wäre. Besonders sinnvoll ist’s halt normalerweise nicht … und JUCE scheint nicht damit zu rechnen. Eins der durch die “perfekte” Steinberg-Dokumentation möglichen Interpretationsprobleme halt.

Nota Bene: in VST3 there is nowhere a hint neither in documentation nor in the code that rules out the use of multiple editor views. Under normal circumstances it does not make much sense … and JUCE does not seem to handle it. (…)
[/Quote]


#7

That’s interesting… We’ve always said to our users that they should write their code to cope with zero, one or more editors being open.

However… because so many devs don’t think like that and write hacky code with hard-coded assumptions about not having more than one window, there are many many buggy plugins our there which crash if you open two editors. So in our own hosting code we’re always very careful to avoid that situation, and will never open more than one at once. That’ll also be true of all the major hosts, as it’s just too risky to do so.

So… I guess we would never have actually tested the VST3 code to see if it handles that situation! We probably should write a unit test for that!


#8

Is that something that auval and avids DISH would catch? And does such tool exist for VST/3 ?


#9

Maybe Steinbergs VST Scanner. But I don’t know what tests it actually performs.


#10

Ah, thank you. I think I should spend some time to set up a proper CI. That one could complete the setup (as far as such thing can be complete ;-))