No UI with vst2 wrapper using SDK3.7.2

After recompiling my plugin with the latest SDK 3.7.2 and deploying the vst2 version using the vst2wrapper included with the SDK, I am getting no UI at all when I open it in the DAW (tried with Reason and Maschine 2) as seen in this screenshot:

Do you have any idea what could be wrong? I would be more than happy to troubleshoot the issue but not too sure where to start. Any suggestions?

Working fine with SDK 3.7.1…

Thanks

I am seeing the exact same issue on Windows 10 but this time it is with VST3 directly. Running editorhost.exe with my vst3 compiled with 3.7.2 generates a blank window. See screenshot

editorhost

For vst2, it seems that the issue is in loading the xml/json file: it doesn’t get found anymore thus it opens with an “empty” default window. I was able to trace it down to:

// uidescription.cpp L244
bool UIDescription::parse ()
{
	if (parsed ())
		return true;
		
	static auto parseUIDesc = [] (IContentProvider* contentProvider) -> SharedPointer<UINode> {
		if (auto nodes = Detail::UIJsonDescReader::read (*contentProvider))
			return nodes;
#if VSTGUI_ENABLE_XML_PARSER
		Detail::UIXMLParser parser;
		if (auto nodes = parser.parse (contentProvider))
			return nodes;
#endif
		return nullptr;
	};

	if (impl->contentProvider)
	{
		if ((impl->nodes = parseUIDesc (impl->contentProvider)))
		{
			addDefaultNodes ();
			return true;
		}
	}
	else
	{
		CResourceInputStream resInputStream;
		if (resInputStream.open (impl->uidescFile))
		{
			InputStreamContentProvider contentProvider (resInputStream);
			if ((impl->nodes = parseUIDesc (&contentProvider)))
			{
				addDefaultNodes ();
				return true;
			}
		}
		else if (impl->uidescFile.type == CResourceDescription::kStringType)
		{
			CFileStream fileStream;
			if (fileStream.open (impl->uidescFile.u.name, CFileStream::kReadMode))
			{
				InputStreamContentProvider contentProvider (fileStream);
				if ((impl->nodes = parseUIDesc (&contentProvider)))
				{
					addDefaultNodes ();
					return true;
				}
			}
		}
	}
	if (!impl->nodes)
	{
		impl->nodes = makeOwned<UINode> ("vstgui-ui-description");
		addDefaultNodes ();
	}
	return false;
}

This method returns false. Both branches of the if fail to load the resource file which is on macOS located under Contents/Resources/JambaTestPlugin.uidesc.

I have tried both with the xml and json representation. Both fails (and I think it makes sense because the file is just not found).

I had none of these issues with vst 3.7.1

If the file is not found which path is it using?

It is using just the name: JambaTestPlugin.uidesc like it was previously.

Digging deeper, I have found what the issue is and I will report it in a github issue soon once I have validated the solution, but the idea is the following: the file is opened by using a resource stream in the bundle. But in vst3.7.2 the bundle is not initialized in the vst2 path and so the stream cannot be opened… see below

In vst 3.7.1 (for macOS)

  • for vst3, bundleEntry calls InitModule()
  • InitModule() does nothing (is actually implemented by plugins and in general do nothing at least in my case)
  • the GUI layer initializes the resource bundle in the VSTGUIEditor constructor so it is always done, whether vst3 or vst2wrapper
  • for vst2wrapper, InitModule is called in VSTPluginMain so potentially multiple times (once each time a plugin is instantiated), but because InitModule does nothing it is not a problem

In vst3.7.2 (macOS)

  • for vst3, bundleEntry does 2 things:
    • calls InitModule() (only once)
    • initializes moduleHandle which is then used by the GUI to get a reference to the bundle later on
  • InitModule() is now implemented by the SDK and is the one that ends up initializing the GUI using the moduleHandle that is set by bundleEntry
  • The vstw2wrapper has not changed at all from 3.7.1 and still calls InitModule in VSTPluginMain which leads to the 2 issues I have run into:
    • if you open 2 instances of the plugin, InitModule is called twice and because of an assert it crashes the DAW
    • because bundleEntry has not been called, then moduleHandle has not been set and as a result the bundle resource stream cannot be created and as a result the UI file is not loaded leading to an empty window

I have already implemented a fix which solves the 2 issues on macOS (which is calling bundleEntry instead of InitModule) and will open a github issue shortly with how I did it exactly. Now I am seeing another issue on Windows, where even running the editorhost leads to an empty window and I am still trying to figure out why.

1 Like

The VST2 wrapper issue fix is already in the works. I’m more interested of the failure for the VST3 plug-in.
Do you say that on macOS the VST3 version works, but on Windows it does not, correct?

Yes that is correct. If I run editorhost myplugin.vst3 on macOS it works. If I run editorhost myplugin.dll on Windows it doesn’t (empty window as shown above). Note that I am not using the bundle format under Windows because otherwise I cannot wrap it in a vst2 plugin… So I am using the dll format (not sure if that is the problem)

I am trying to figure out if it is my issue (compilation/linking, etc…) or in the sdk and I will report here for sure once I have more info.

You can use the bundle format on Windows even if you add the vst2 plug-in to the vst3 one. Just make a symbolic link to the vst3 file and change the file extension of the link to dll. Every host that can resolve links should be able to load it then.

@Arne_Scheffler I was able to investigate the issue with vst3 blank window on Win10.

  • If I use xml format for .uidesc then it works.
  • If I then open the UI editor (right click), and simply select Save As and regenerate the .uidesc, it then saves as a json file.
  • If I then close the app, recompile and reopen it now fails with error like this:
    JSON Parsing Error:
    The document root must not be followed by other values.
    At byte offset: 341473
    XML Parser Error on line: 1
    not well-formed (invalid token)
    {
    

What is odd is that it works fine on macOS with json. I made sure that I generated the json on Windows just in case that would be the issue… but no, it looks like json is not working. My IDE reports no error with the json file.

Is there a way to turn off json on save since it seems broken (and tbh I am not sure I see the advantage of json which turned a 470 lines of xml into a monster 11000+ lines of json…)?

Can you check what is written at the parsing error location?
You can turn off json writing but you have to patch vst3editor.cpp and the expat XML parser will be removed in a future release.
The reason for switching to JSON is
a) better read/write performance
b) better diffs on changes
c) security issues with expat on Windows

@Arne_Scheffler I am attaching the 2 versions of the file, xml and json so that you can see for yourself. The xml file is the one that was generated by the vst3 plugin generator with the only difference being that the size of the window is set to 500x300 (because when parsing fails, you end up with a window 300x300, so you cannot see the difference between failure and success…)

JambaTestPlugin.uidesc…zip (1.7 KB)

I just tried another time to reproduce this issue by creating a plug-in on Windows with the Project Generator build it, run it, resave the uidesc file, rebuild it and it all works. No issue here.

The project generated by the generator and the window generated when there is an error are identical (there is no obvious error, even in the output trace…). Are you sure you modified the UI (add a control or something), then saved, and rebuilt? Can you attach your project so that I can try to build it on my machine?

I found the issue. The changed uidesc file is not copied into the bundle on Windows when it is changed. Copying is done on Windows and Linux via ‘cmake -E copy_if_different source destination’ and this does not work on Windows (while it works on Linux). I have informed our cmake guys so that they can have a deeper look into this issue.
So it’s no issue of VSTGUI itself.

I am not using bundle on Windows. I am using the .rc file. The file is being opened/found. It is the json parsing that is failing.

All you need to do is tell the JSON parser to stop trying to process the remainder of the stream after it is done with the root.
It is done by adding the kParseStopWhenDoneFlag to RAPIDJSON_PARSE_DEFAULT_FLAGS.

I know this thread hasn’t been active for a while now but it took me quite some time and modifications to the editor till I figured there’s a much simpler solution.
So, I’m posting it in hopes of saving some time and frustration for others.

@Ishay_Berkovich thanks for the tip/workaround

In the end, why do I have to do anything at all? Shouldn’t this be part of the SDK? Isn’t everybody going to bump into the same issue?