IPluginCompatibility clarifications

The docs about this are not entirely clear so here a few questions.

In IPluginCompatibility there is

class PluginCompatibility : public FObject, public IPluginCompatibility
{
  public:
    //...
    tresult PLUGIN_API getCompatibilityJSON (IBStream* stream) override
    {
      /* write in the stream the JSON compatibility array
      [
          {
              "New": "BD58B550F9E5634E9D2EFF39EA0927B1",
              "Old": [
                  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
              ],
          }
      ]
      */
        return kResultTrue;
    }
    //... 
};

//------------------------------------------------------------------------
static FUnknown* createCompatibilityInstance (void* context)
{
    return (IPluginCompatibility*)new PluginCompatibility;
}

//------------------------------------------------------------------------
BEGIN_FACTORY_DEF (stringCompanyName, stringCompanyWeb, stringCompanyEmail)

    //...
    DEF_CLASS2 (INLINE_UID_FROM_FUID(PluginCompatibilityUID),
                PClassInfo::kManyInstances,
                kPluginCompatibilityClass,
                stringPluginName,
                Vst::kDistributable,
                "",
                FULL_VERSION_STR,
                kVstVersionString,
                createCompatibilityInstance)

I assume ‘New’ supposed to be the VST3 processor UID , but what about the two ‘old’ ones ?
Perhaps it’s a UID generated from the VST2 four character ID and plugin name as described in How can I update my VST 2 version of my plug-in to a VST 3 version and be sure that Cubase will load it instead of my old one? using convertVST2UID_To_FUID(), but then what about the second 'BBBBBBB … ’ one ?

Then what is the PluginCompatibilityUID supposed to be ?

For Automation compatibility, you have to ensure that VST 3 parameter IDs have the same value than the indexes of their associated parameters in VST 2 . Only with this condition the host can play back the automation. The parameter value has the same meaning in VST 2 and VST 3 .

Does this mean the VST2 and VST3 parameter indexes must match or should the VST3 id’s actually be the samed as VST2 indexes ? I hope it’s the former otherwise that would seriously limit the use case of this feature.

It would be great if there was a fully working sample demonstrating this in the next SDK release.

Thanks,
Lorcan

Hi Lorcan,
if possible please use a moduleinfo.json file instead of using this interface.

The ‘old’ ones can be any other UID of a plug-in (VST2 or VST3). If you have a VST2 plug-in then you need to pass in the UID you can generate for a VST2 with the method you already mentioned.

Of course it is the former one.

The mda example plug-ins use the moduleinfo.json file to make them compatible with the old VST2 variants.

Hi Arne,

thanks, I’ve gone the moduleinfo.json route instead as you advised.
Unfortunately neither Cubase nor Reaper load the VST3 instead of the VST2 when I reload a project previously saved with the VST2 version.

My VST2 id is lmsy, name is superchord and the VST3 processor ID is 98239B7A-61A3-43AD-B693-0EAEA843994F,
which gives a compatibility ID of 56535479736D6C737570657263686F72 using convertVST2UID_To_FUID .

Do you have an idea why this isn’t working ?
Perhaps I need to implement the FUID vendor specific opcode in my VST2 too ?
But it seems that should be handled by the .json already.

Here is my moduleinfo.json:


  "Name": "Superchord",
  "Version": "1.2.4.6053",
  "Factory Info": {
    "Vendor": "lmdsp",
    "URL": "https://www.lmdsp.com/",
    "E-Mail": "mailto:xxx",
    "Flags": {
      "Unicode": true,
      "Classes Discardable": false,
      "Component Non Discardable": false
    }
  },
  "Classes": [
    {
      "CID": "98239B7A61A343ADB6930EAEA843994F",
      "Category": "Audio Module Class",
      "Name": "Superchord",
      "Vendor": "lmdsp",
      "Version": "1.2.4.6053",
      "SDKVersion": "VST 3.7.7",
      "Sub Categories": [
        "Fx",
        "Modulation"
      ],
      "Class Flags": 1,
      "Cardinality": 2147483647,
      "Snapshots": [
        {
          "Scale Factor": 1,
          "Path": "Contents/Resources/Snapshots/98239B7A61A343ADB6930EAEA843994F_snapshot.png"
        },
        {
          "Scale Factor": 2,
          "Path": "Contents/Resources/Snapshots/98239B7A61A343ADB6930EAEA843994F_snapshot_2.0x.png"
        }]
    },
    {
      "CID": "70C9E567AFBE497D9839F2C42FE99290",
      "Category": "Component Controller Class",
      "Name": "Superchord Controller",
      "Vendor": "lmdsp",
      "Version": "1.2.4.6053",
      "SDKVersion": "VST 3.7.7",
      "Sub Categories": [
        "Fx",
        "Modulation"
      ],
      "Class Flags": 0,
      "Cardinality": 2147483647,
      "Snapshots": []
    }
  ],
  "Compatibility": [
    {
      "New": "98239B7A61A343ADB6930EAEA843994F",
      "Old": [
        "56535479736D6C737570657263686F72"
      ]
    }
  ]
}

I think only the latest Cubase Version 12.0.52 has support for this yet. Have you checked it with that version?

Yes this is the version I tested with.

Ah, I remember: Cubase only replaces the plug-in with the new one, if the old one is not installed. So remove the VST2 plug-in and Cubase should load the VST3 one instead.

Are you sure ? Here it just tells me the plugin cannot be found

It could be possible that you need to force Cubase to rescan your plug-in. If you only changed the moduleinfo.json, Cubase won’t rescan your plug-in.

Thanks but unfortunately this doesn’t work either.

Double check your UIDs. There is a xml file in Cubase preference folder where you can search for your UIDs.

1 Like

I was indeed able to locate the expected VST2 compatibility ID in C:\Users\<Name>\AppData\Roaming\Steinberg\Cubase 12_64\Vst2xPlugin Infos Cubase.xml.

Turns out I was writing the VST2 FOURCC in big Endian instead of the expected little Endian.

Thanks for your help.

I have implemented the IPluginCompatibility solution, and migration now works as expected in Native Instruments’ Komplete Kontrol. Migration still does not work in Cubase (12.0.52).

I also tried implementing using the moduleinfo.json, but Cubase still would not migrate my VST2 plugins over to VST3 dito.

It may be worth mentioning that putting files directly in the Contents folder of a Mac bundle is not allowed according to Apple’s bundle structure guidelines, and will fail both codesigning and notarization. I would recommend changing the expected path to Plugin.vst3/Contents/Resources/moduleinfo.json.

According to the XML files in ~/Library/Preferences/Cubase 12, the migration ID’s are registered, after I have cleared out the plugin cache and re-scanned all plugins.

Do you have any ideas on what could be going wrong?

@azeteg Arne is looking into the json location issue Moduleinfo.json and macOS notarization - #14 by Arne_Scheffler

Make sure to deinstall the VST2 version as Cubase only replaces plug-ins that are not available on the system.

Thanks Arne, you mentioned this earlier in the thread, so I’ve already ensured the VST2 is removed and Cubase XML files don’t have any mention of it.

Can you describe step by step what you do in Cubase? Maybe there’s a misunderstanding how this replacement works?

  1. Instantiate VST2 plugin as an instrument track
  2. Save project
  3. Close Cubase
  4. Delete VST2 plugin
  5. Open Cubase
  6. Load Project

Expected: plugin replaced with VST3 version

Observed: Error message about missing plugin on Track 1.

OK, your expectation is correct and should work. Have you double checked the UIDs you provide in IPluginCompatibility. Other then that I’m out of ideas.

Arne,

yes - I’ve doublechecked the UIDs. The transition from VST2 to VST3 also works just fine inside of Native Instruments Komplete Kontrol, where we provide VST2 NKS presets, so I would think that the IPluginCompatibility implementation is just fine from our side.

Thanks,
Martin