VST plugin AGain reloaded with a Qt GUI

Years ago, I’ve tried to use the GPL version of Qt, but it couldn’t be done without a Qt Solution that was at the time non-free. Now, Nokia has freed and Qt and the appropriate Qt Solution.

I’ve searched if someone has already used this new version to create a VST plugin. The only blog post I’ve found does not use the Qt Solution and is not perfect. According to the documentation what is missing in this solution is precisely what the Solution should do. So let’s try it.

So I’ve download the 2.4 VST SDK as well as Qt 4.5 and the WinMigrate Solution. As I’ll be using Qt with signals and slots, I used SCons to build my small plugin.

Designing the interface and testing it

The interface is really simple: a label with a name, the value of the gain and a slider. Here is what it looks like in Tracktion 3:
QtAgain in Tracktion 3
The slider takes values from 0 to 99, value that will be displayed in a label. This will be the gain factor in percentage.

Nothing fancy here with the class header:

class QVstPanel : public QWinWidget
{
  HWND h_parent;
  AudioEffectX *again;

  QLabel *valueLabel;
  QSlider *slider;
public:
  QVstPanel(AudioEffectX *again, HWND h_parent = NULL);
};

The panel is created with a link to the actual audio effect (needed in the future) and the parent HWND given by the host.

The actual code is even simplier:

QVstPanel::QVstPanel(AudioEffectX *again, HWND h_parent)
:QWinWidget(h_parent, NULL), again(again), h_parent(h_parent)
{
  setAttribute(Qt::WA_DeleteOnClose);

  QLabel *label = new QLabel("Gain", this);
  valueLabel = new QLabel("0", this);
  slider = new QSlider(Qt::Horizontal, this);
  QHBoxLayout *layout = new QHBoxLayout(this);
  layout->addWidget(label);
  layout->addWidget(valueLabel);
  layout->addWidget(slider);
  setLayout(layout);
}

Now this is the class that will be opened by the VST editor this way:

class QtAGain : public AEffEditor
{
  QWinWidget* widget;
  AudioEffectX* effect;

public:
  QtAGain(AudioEffectX* effect)
    :widget(NULL), effect(effect)
  {
  }

  ~QtAGain()
  {
  }

  bool open(void* ptr);
  void close();
};
bool QtAGain::open(void* ptr)
{
  AEffEditor::open (ptr);
  widget = new QVstPanel(effect, static_cast(ptr));
  widget->move( 0, 0 );
  widget->adjustSize();
  widget->setMinimumSize(widget->size());
  widget->show();

  return true;
}

void QtAGain::close()
{
  delete widget;
}

Now, in AGain’s constructor, I can add my custom editor:

  QtAGain* again = new QtAGain(this);
  setEditor(again);

So there isn’t anything really fancy, it kind of works out of the box. Unfortunately, it doesn’t work as well as in T3 in every host. I cannot resize the window VSTHost gives to the open() method, even if I tested it with almost all solutions I’ve found on MSDN.

Adding interactivity

Now, I will eventually use the power of Qt. The QtAGain class will be a QObject, as will be the AGain effect. This way, I can connect signals from the GUI to the effect when a parameter is modified by the user, and vice-versa, the UI will be updated when the effect sees a parameter change (indicated by the host for instance).

So I add a connection inside the QVstPanel constructor to a new slot that will update the underlying effect:

connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(update(int)));

void QVstPanel::update(int value)
{
  valueLabel->setText(QString::number(value));
  again->setParameter(0, value / 100.);
}

The trouble arises from the effect: what should I do if the effect gets a setParameter that didn’t come from the UI? If there is no UI, everything is fine though. So I will add a signal inside QtAgain, the editor, that will forward a signal emitted by AGain only if the UI is up.

void AGain::setParameter (VstInt32 index, float value)
{
  fGain = value;
  emit update(value);
}

So now, the signal that the UI will get is a float, so I can reuse the name update() for my slot:

void QVstPanel::update(float value)
{
  int intValue = value * 100;
  valueLabel->setText(QString::number(intValue));
  slider->setValue(intValue);  
}

Of course, you will have several parameters inside your VST plugin, I suggest you use the editor instance to the mapping between the effect and the different slots you may have inside your UI.

Conclusion

Although I couldn’t get it to work with VSTHost (the host widget is not resized), I think the QWinWidget is a good class to help developing Qt VST plugins. I may want to use this skeletton to test some digital effects with a cool UI.

If you have a solution to make VSTHost work, I’m all ears.

The code is available on Launchpad.

Buy Me a Coffee!
Other Amount:
Your Email Address:

9 thoughts on “VST plugin AGain reloaded with a Qt GUI”

  1. Hi.

    First I´ve to say that this is my first Qt experience and wanted to learn it a little doing a funny thing like a synth (I already have a good OSC that I have to refactor).

    The point is that I´ve tried the example with Qt 4.6.3 and WinMigrate 2.81 and it´s hanging my host (Reaper x86) in Windows 7 x64 and with visual 2008, I build it without using scons because it did fail to recognize Python and didn´t wanted to spend time with it.

    When I debug the critical point is that the DllMain function calls QMfcApp::pluginInstance, inside QMfcApp::pluginInstance “new QApplication” is called, containing this call another call to initializeMultitouch, and inside there a call to “CoCreateInstance” is done, with the consequent hanging because:

    http://support.microsoft.com/kb/305723

    Due to my total Qt unknowledge I´m relying on you to know if I should open a bug or I´m doing something bad.

    Looks like multitouch was added in 4.6 so I´m trying to find Qt 4.5.

    BTW, thanks for sharing this.

    1. Thanks for the report, I’ll have to update my Qt version to check your bug report. It seems it may an issue with Qt though, so I will also check if there’s already a bug report on Qt tracker.

    1. I’ve tried with Qt 4.7.1 today and QtWinMigrate-head, it worked with the minihost sample, although I couldn’t make it work with VST Host.
      Tested with Windows 7 64bits.

  2. Lorenz: You’re thinking about Quicktime (the audio/video framework by Apple), but Matt is actually talking about Qt, the cross-platform GUI framework by Nokia.

Leave a Reply