MIDI Program Change broken (Solved)

I’m using the latest release and i don’t receive any MIDI Program Change messages anymore. Instead of that i receive normal controller change messages. This used to work for years and it looks like something changed.

Can someone reproduce this issue?

Where are you receiving the messages from? This is working as expected for me:

/*******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name:             MidiProgramChangeTest

  dependencies:     juce_audio_basics, juce_audio_devices, juce_core, juce_cryptography, juce_data_structures, 
                    juce_events
  exporters:        xcode_mac

  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1

  type:             Console

 END_JUCE_PIP_METADATA

*******************************************************************************/

#pragma once


//==============================================================================
int main (int argc, char* argv[])
{
    ScopedJuceInitialiser_GUI gui;
    
    struct Callback : public MidiInputCallback
    {
        void handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) override
        {
            jassert (message.isProgramChange());
        }
    };
    
    Callback cb;
    
    std::unique_ptr<MidiInput> input (MidiInput::createNewDevice ("JUCE_input", &cb));
    jassert (input.get() != nullptr);
    
    DBG ("Starting input");
    input->start();
    
    std::unique_ptr<MidiOutput> output (MidiOutput::openDevice (input->getIdentifier()));
    jassert (output.get() != nullptr);
    
    DBG ("Starting output");
    output->startBackgroundThread();
    
    MidiBuffer mb;
    mb.addEvent (MidiMessage::programChange (1, 1), 0);
    mb.addEvent (MidiMessage::programChange (1, 2), 100);
    mb.addEvent (MidiMessage::programChange (1, 3), 200);
    mb.addEvent (MidiMessage::programChange (1, 4), 300);
    
    output->sendBlockOfMessages (mb, Time::getMillisecondCounter() + 2000, 100);
    
    for (;;)
    {
        Thread::sleep (10);
    }
    
    return 0;
}


Hi Ed95
Thanks for looking at this. Sorry i wasn’t specific enough. I receive the MIDI messages in the plugins processBlock(…) method. I’m getting controller messages when a program change happens for the vst and vst3 version of the plugin. Not sure if AU is affected. I have tested this on OSX.

Any help is welcome.

I finally had time to take a closer look. It looks like the problem happens only with the VST3 version of the plugin. All other formats receive the MIDI program change event’s in the process block method.
Is this a bug or is MIDI program change not supported for VST3?

Edit: It’s not supported anymore with the standard MIDI program change event in the VST3 format: https://www.steinberg.net/forums/viewtopic.php?t=153909

I get the impression from reading your link that Steinberg staff with emphasis claims that it is supported, “yes this is possible the same as with old style VST 2 plug-ins” regarding receiving and handling external program change events. :thinking:

It is in some way… if you publish a preset list inside your VST 3 (think if your factory presets are inside the package).
They then select the presets for you. You never get any MIDI Program Change Message in the VST itself.

Was this change in behaviour caused by this commit?

I don’t think it’s a JUCE bug at the moment. In this thread it looks like MIDI Program Change events don’t work the same way as they did with VST2:

https://www.steinberg.net/forums/viewtopic.php?t=74526

Ah yes. I misread one of the posts and thought this was a change in JUCE’s VST3 behaviour.

Okay…

So if I publish the GM implementation with its 128 programs/instruments as my preset list, and then when I send a program change from my keyboard, any VST3 aware DAW will catch this event, select the appropriate preset, and then make my plugin aware of this? Then as an action to this, I can recreate the original program change event and inject this to the Midibuffer in the processBlock and voilá, my old VST2 code will work again?

any VST3 aware DAW will catch this event, select the appropriate preset, and then make my plugin aware of this?

I doubt it. The VST3 spec requires plugins to use the IProgramListData interface to provide the program list information (or to store the program as files in a particular location, iirc). But there’s nothing in the spec that implies the index of the list corresponds to a MIDI program change number, and those threads seem to imply they’re talking about Cubase features, not VST3.

But what is your goal? Switching presets with a MIDI controller? You can’t use program change data for that in VST3, it’s not supplied to the plugin at all.

Yes, i wanted to use MIDI program change, because i upgraded my VST2 plugins to VST3 and now the MIDI program change implementation does not work anymore. It was useful for people with a live setup.
And it looks that they filter out this MIDI Message because Cubase now use it to change the preset within the hosts presets list (that maybe most other hosts do not support). Is that right?

The goal is to have Midi (GM) work as it’s intended to do and as it did before VST3; selecting Electric Piano from my keyboard will send program change no 5 to the VST sample player, selecting drawbar organ will send no 17 etc and engage the organ sample.

Are you implying I can’t make a link between a specific preset in my preset list and a specific program change number?

And it looks that they filter out this MIDI Message because Cubase now use it to change the preset within the hosts presets list (that maybe most other hosts do not support). Is that right?

Pretty much. Steinberg changed the contract in VST3 where program changes are the responsibility of the host, not the plugin. Which makes a lot of sense, from the host perspective. But obviously is a point of friction with people who wanted to handle it themselves, just like the Midi CC stuff that changed in 3.6.12 back in December.

Yes. The VST3 SDK does not provide an API for MIDI program change data between the host/plugin, as far as I know (not pretending to know every detail of the spec, I’ve just read through it several times).

One “feature” of VST3 is that MIDI isn’t just piped to the plugin from the host. You don’t get raw MIDI data, just what the API allows to be exchanged (which is a subset of the MIDI spec).

Yeps, but why wouldn’t my workaround… work?

From the way you described it you’d be relying on the host to translate program changes to the correct preset, right? I’m just doubtful that you’d be able to do that in a sane way for every host

So you think if I produce a plug-in with 128 factory presets, selectable by program change events, different presets will be selected by the same program change on different hosts?

I’m hitting the exact same problem but this topic does not seem to come to a definite solution, why is it marked “Solved”?