FLAM Primer

Luis Garrido


Table of Contents

1. Build and install from git repository
2. Create a GUI for your favourite LADSPA
2.1. Step 1: use flamwizard to generate a UI skeleton
2.2. Step 2: customize the plugin layout
2.3. Step 3: let hosts know that there is a FLAM for your plugin
2.4. Step 4: is it alive, Igor?
2.5. Troubleshooting
2.6. Keyboard Shortcuts
2.7. Response Curves
2.8. Master Widgets
2.9. Selectable UIs
2.10. Selectable Styles
2.11. Theming Using Style Sheets
3. Planned features
4. Recommended reading for the Qt novice

Figure 1. Rosegarden session using FLAM to control three plugins.

Rosegarden session using FLAM to control three plugins.

1. Build and install from git repository

First of all, we need to get the software, compile it and install it.

FLAM’s functionality is based on a number of libraries. You must therefore install them before being able to build FLAM.

  • Qt
  • lo
  • redland (also known as librdf)
  • lrdf

Bear in mind that you will need to install the development packages of those libraries. For more information please refer to the documentation or support channels of your Linux distribution.

Debian users will need to install libqt4-dev, liblo-dev, librdf0-dev and liblrdf0-dev (note the extra "l" between "lib" and "rdf0", it stands for LADSPA).

Fedora users will need qt-devel, liblo-devel, redland-devel and liblrdf-devel.

Additionally, to design your GUIs you will need Qt Designer. This is provided by the qt4-designer package in Debian. Fedora users will have it installed, since it is already bundled with qt-devel.

Once the dependencies are installed, clone flam’s repository to your disk and build it the usual way for projects using the cmake build system:

git clone http://vagar.org/git/flam
cd flam
mkdir build
cd build
cmake ..
make

If any of the steps fail, double-check you have all the requirements installed. If everything seems in order you can ask for help at the FLAM forums (registration needed.)

To install, execute as root:

make install

2. Create a GUI for your favourite LADSPA

In this primer we will be creating a GUI for ToneStack, a tube preamp plugin found at the excellent CAPS plugin suite. Go to your package manager and install it if you haven’t yet.

2.1. Step 1: use flamwizard to generate a UI skeleton

flamwizard will simplify the process of building a first version of your UI for a particular plugin that can later on be executed by a host using flammer.

Launch flamwizard from the command line. You will be presented with a list of all the LADSPA plugins installed in your system. Click on any of the headers to sort the list according to that particular parameter. ToneStack’s UID is 2589. Select it and press the "Next" button or just double-click on it.

Now we see a list of ToneStack ports and some information about them. The most important part is the last column, labelled "Widget", where we must select one of the available widgets to control the associated port. Since it has a scale, we will choose a QComboBox for port 0 ("model"). For the rest of the ports we will choose a QSlider. Press "Next".

Next step is to save the skeleton UI that flamwizard is going to generate for you. It is very important you don’t modify the directory in which flamwizard is going to save your UI, since it is a standard location where flammer will attempt to discover FLAMs for that particular plugin. You can, however, change the UI file name, since you may want to have more than one UI for a given plugin.

Let’s call this one "slidey.ui", for instance, since it is made out mainly of sliders. Change the name from "ToneStack.ui" to "slidey.ui" and press the "Save" button. If this is the first time you create a UI for this particular plugin, flamwizard will ask you for permission to create the folder on which the file will be saved.

That’s it. Let’s open this UI in Qt Designer so we can improve on its design. Note that the structure of the path to the file is constructed like this:

  1. Your $HOME directory.
  2. .local/share/flam/dssi
  3. Plugin library name.
  4. Plugin label.
  5. UI file name.

Now you know where to find it every time you feel the need to make any adjustment to it.

2.2. Step 2: customize the plugin layout

Launch Qt Designer using your distribution application menu or from the command line. Usually it is called "designer" or "designer-qt4". Open the UI that flamwizard just created for you.

Figure 2. UI created by flamwizard.

UI created by flamwizard.

Not looking too hot, is it? Ah, well, we will fix that soon enoug. flamwizard groups each widget with a label in a QVBoxLayout. Then all those VBoxes are spread around the dialog using a QGridLayout so they are easy to move around once the grid is broken. Normally we will want to break all those computer-generated ugly layouts and create our own.

We will start out simple:

  • Break the main QGridLayout (click on a free spot in the form and click the Break Layout button or press Ctrl+0.)
  • Drag all three label+slider boxes below the combo box, select them and wrap them in a horizontal layout (Ctrl+1.)

Figure 3. Rubberband-select three label+slider vboxes to group them in a hbox.

Rubberband-select three label+slider vboxes to group them in a hbox.

  • Set the main dialog to use a vertical layout (click on a free spot and press Ctrl+2.)
  • Resize the dialog to your liking (or press Ctrl+J to resize it to Qt’s defaults).
  • Capitalize the labels properly if you wish (double click on them to edit their content.)
  • Select all four labels (click one and add the rest to the selection using Ctrl+click.) Search for the "sizePolicy" property near the top and set their Horizontal Policy to "Expanding", so the enclosing box will encompass the width of the whole cell. Search for the "alignment" property near the bottom and set the Horizontal value to "AlignHCenter".

Figure 4. Change the alignment property for the four labels.

Change the alignment property for the four labels.

  • Select all three sliders and set their "sizePolicy/Horizontal Policy" property to "Expanding". In most Qt styles this will center them in their respective cells.

That looks nice enough. Press Ctrl+R to test out how the FLAM will look like when it is working. Close the preview and press Ctrl+S to save your changes.

Figure 5. Preview of the UI with a hand-made layout.

Preview of the UI with a hand-made layout.

Don’t close your Designer session just yet, we will be coming back to make some changes.

2.3. Step 3: let hosts know that there is a FLAM for your plugin

The DSSI GUI specification expects to find a plugin’s GUI as an executable file with a very specific name in a very specific folder in the filesystem. We will provide a symbolic link to flammer, instead, but the principle remains the same. You will only have to perform this step once for any given plugin.

For this step you will need root permissions: identify yourself as root or use sudo to execute the following commands:

cd /usr/lib/ladspa
mkdir caps              # GUI dir for plugins in the caps.so library.
ln -s /usr/local/bin/flammer caps/ToneStack_gui

2.4. Step 4: is it alive, Igor?

At the date of this writing Rosegarden is the only LADSPA host that has provision for DSSI-style GUIs for LADSPA plugins. So fire up good old RG, select an audio channel, and click on a plugin slot in the Instrument Parameters panel. In the plugin dialog select "C* ToneStack" (you can find it in the "Simulators" category).

Now cross your fingers and press the "Editor" button. If all went well, a version of our UI should appear in a separate window. Fool around a bit with its controls and see how their Rosegarden counterparts respond accordingly (and viceversa).

2.5. Troubleshooting

If the FLAM didn’t pop up, there are a number of things that could have gone wrong. Check again all the steps and make sure all the paths are exactly as described in the instructions.

You may also have been bitten by "the lo/NetworkManager/DSSI GUI issue", caused by some kind of disagreement between liblo and how NetworkManager or other automatic tools configure the /etc/hosts file. If your system is affected by this you won’t be able to run any DSSI GUI. Try to run some DSSI synths like hexter, fluidsynth-dssi or whysynth and see if you can see their GUIs. If you can, forget about this paragraph. Otherwise, you need to modify your /etc/hosts and how NM manages it. If you don’t need IPv6, disabling it seems to be a speedy, if heavy-handed, way of working around this issue.

If nothing seems to work, post a message in the FLAM forums and I will try to help as time allows.

2.6. Keyboard Shortcuts

For widgets like QPushButton or QCheckBox Qt allows you to define a keyboard shortcut using the "shortcut" property. Pressing the key is equivalent to pressing the button.

For widgets like QSlider, QDial, QSpinBox and QComboBox FLAM provides the "FlamShortcut" property. When you set this property and press the key or key combination at run time, the widget will receive the keyboard focus and "the mouse cursor will travel to point at its center."

The purpose of this impolite mouse hijacking is to allow you to put your keyboard and mousewheel to good use in live situations. Once the mouse is pointing to the widget and it has the focus you can use your mousewheel or the cursor control keys (arrows, PgUp, PgDn, Home and End) to alter its state.

Let’s try this. Go back to your Designer session and edit the FlamShortcut property in all four widgets to the following values:

  • model (QComboBox): W
  • bass (QSlider): A
  • mid (QSlider): S
  • treble (QSlider): D

I have chosen a key layout that mimics that of the widget. You could also use the first letter of the label as a mnemonic, if you prefer, or the numbers 1 to 4.

Save the changes to the .ui file. Now go back to Rosegarden, close flammer and open it again so the UI gets reloaded.

If you let your mouse rest over the widgets a tooltip will appear showing the label of the port it controls and its assigned shortcut, if there is one. You can use this feature to find out the shortcuts for a FLAM you have not created, or to get reminded of the ones you set.

Now give it a try. Press the keys W, A, S and D with your left hand and watch the mouse jump around. Use your mousewheel with your right hand at the same time, taking care of not moving your mouse too much, or use the cursor keys in your numeric keypad. Find it handy?

Bear in mind that for shortcuts to work your FLAM window must have the keyboard focus.

Now add another instance of ToneStack to your Rosegarden audio channel and launch its editor. flammer acts as a plugin rack, so the new FLAM will appear as a subwindow next to the first one. You can jump between them using Ctrl+Tab or Ctrl+Shift+Tab.

2.7. Response Curves

FLAM can assign non-linear response curves to graphical widgets, like QSlider and QDial, by means of the "FlamResponseCurve" property. At this moment the only alternative is "cube", which is a popular choice for volume widgets, giving some extra resolution in the top range at the expense of reducing it in the bottom range.

To make use of this feature go back to Designer, select the "Treble" slider and type "cube" without the quotes as a value for the "FlamResponseCurve" property.

Save your UI, go back to Rosegarden, close flammer and use the "Editor" button in RG’s ToneStack plugin window so the UI gets reloaded. Now move your FLAM’s sliders while watching RG’s controls and see how the "Treble" behaves differently, providing more resolution in the top range.

2.8. Master Widgets

Sliders and knobs are very visual, but somewhat imprecise. To get more precision you can increase their internal range arbitrarily acting on their "minimum" and "maximum" properties; then you can use the arrow keys to nudge their value step by step. But using the mouse you are limited by your screen resolution, even if you create a slider as wide as your whole screen.

Anyway, it would be nice if we could also see a numeric indication of their value and even type a desired value for that port.

Enter master widgets. Go to Designer’s Widget Box (usually at the left of your screen), search for "Double Spin Box" under "Input Widgets" and drag three of them just below each one of our three sliders, so they end up at the bottom of their respective vertical layouts (a blue line will indicate you where the new widget will appear within the existing layouts.) Press Ctrl+J to adjust the dialog size making room for the new additions.

Figure 6. Add a spinbox to the bottom of a vbox (note the blue line.)

Add a spinbox to the bottom of a vbox (note the blue line.)

Now Ctrl-select all three spin boxes.

FLAM will be looking for a "FlamMaster" property, but this is not a Qt default property, so we have to add it. Go to the Property Editor and click the big green plus sign at the top right corner to add a new dynamic property. Choose a "String" type for it from the drop-down box. In Property Name type "FlamMaster".We will fill a value for it later.

Now will take advantage of having the three widgets selected to adjust their value range, since the default is 0.0 to 99.99. Those three ToneStack’s ports have a range of 0.0 to 1.0, you can check it looking at the "DSSILowerBound" and "DSSIUpperBound" properties in the sliders. Still with the three boxes selected set "maximum" to "1.0" and "singleStep" to "0.01".

Then we must set a master for each spin box. Select the spin box you placed under the "Bass" slider, go to its "FlamMaster" property and type "bass" without the quotes, all in lower case. This is the objectName for our "Bass" slider widget, you can check it in the Object Inspector panel or selecting the slider and looking for its "objectName" property.

Do the same for the other two boxes, using "mid" and "treble" as their respective masters.

Finally, to have a perfect synchronization between slider steps and spin box steps we must change all three slider’s "maximum" property to 100 (the default is 99). This step is not necessary, but everything will look neater this way. Go change it, by now I am sure you know how.

That should do the trick. Save your changes and test.

The master widget mechanism is necessary to adapt widgets that control different types of data. QSlider delivers int data and QDoubleSpinBox uses double. If you want to link similar widgets, for instance, a QDial and a QComboBox, both using int data, you don’t need the FlamMaster feature: just use the usual Qt signal/slot connections.

2.9. Selectable UIs

As you have seen, creating a new UI is pretty straightforward. It is conceivable that you would want to have several different UIs, each tailored for a certain use. For instance, for a complex plugin with lost of controls of which you only use a few, you could find it useful to have a stripped down version in order to keep your screen real state uncluttered. Incidentally, there are other ways to achieve this: you could create a multitab GUI, for instance, each tab containing different controls. Qt offers a lot of possibilities.

You can have as many FLAMs as you want for any given plugin. Just save them all in the proper folder, as explained before. At runtime flammer will discover them and you will able to select one using its context menu. Right click on the current UI, go to the UI menu and pick your poison. Your preference will be remembered in future sessions.

Figure 7. Selectable UIs.

Selectable UIs.

2.10. Selectable Styles

Styles are Qt way of adapting its look and feel to the guidelines of the different platforms it supports: there is, thus, a Windows style, a Mac style (only in Mac OS), a Motif style, even a GTK+ style. You can choose your favourite style on a per-FLAM basis, using its context menu. Your preference will be remembered in future sessions.

2.11. Theming Using Style Sheets

Qt allows you to customize widget drawing using style sheets. Their syntax goes very much like the W3C’s CSS: you have very powerful selectors that determine to which widgets the properties will apply and a bunch of available properties, depending on which widget class you are trying to customize.

Qt Designer allows you to store a style sheet in any widget of your GUI. In addition to this, FLAM also allows you to store style sheets in separate files and apply them to any UI you want, using its context menu.

Let’s do a simple example. Create the following directory:

mkdir -p $HOME/.local/share/flam/themes/plasma

Inside it, create a file named "plasma.qss" with the following content:

QWidget {
  background: #221100;
  color: orange;
  font: bold 12px serif;
  border-radius: 3px;
  border: 2px solid Orange;
}
QLabel {
  border: none;
  font: 12px monospace;
}
QComboBox, QAbstractSpinBox {
  background: #cc6600;
  color: #221100;
}
QComboBox QAbstractItemView {
  background: orange;
}
QAbstractSpinBox {
  qproperty-alignment: AlignHCenter;
  qproperty-buttonSymbols: NoButtons;
}
QSlider {
  border: none;
}
QSlider::groove {
  width: 6px;
  background: orange;
  border-radius: 3px;
}
QSlider::handle {
  margin: 0 -5px 0 -0px;
  width: 20px;
  height: 6px;
  background: orange;
  border-radius: 3px;
}
QSlider::add-page {
  background: orange;
}
QSlider::sub-page {
  background: rgb(92, 46, 0);
}

It should be rather self-explanatory for those well-versed in CSS and puts a number of Qt style sheets features to good use.

Now restart flammer and the new theme should appear in your context menu. Try it out. If you want to experiment with modifications you can edit the qss file and re-apply the theme to see how your changes affect the outcome.

Figure 8. Plasma theme and theme menu.

Plasma theme and theme menu.

I don’t see theming as pure eye-candy, although that is more than enough justification for some users. Think of people with visual impairments, for instance, they will benefit from a high contrast, big, fat font theme. Also, a well-designed theme can indeed improve any application usability, giving the user good visual feedback about its status and the ability to manipulate it efficiently. Above all, FLAM gives you the choice.

In the first screenshot of this primer you can also see a somehow more sophisticated theme using hydrogen pixmaps to decorate vertical sliders.

3. Planned features

  • More types of plugins: DSSI, LV2.
  • More control protocols: MIDI.
  • More widgets: file selector, XY, envelop editor, filter/equalizer curves, etc.
  • Support scripting for more complex interaction.
  • More response curves: arbitrary polyline.
  • Generic OSC/MIDI messages support: build virtual OSC/MIDI control surfaces.
  • Factor out some key parts of FLAM so Qt-based hosts can integrate flams directly.
  • Better integration between flamwizard and Qt Designer (long term.)
  • Preset support.

4. Recommended reading for the Qt novice

You don’t need to be a programmer to build a FLAM GUI: FLAM and Qt Designer take care of most of the gory details for you. Someone who knows how to design a HTML form and style it using CSS should find FLAM relatively easy to learn and use.

FLAM is based on the GUI building capabilities of the Qt toolkit. In order to make the most out of it, it is advisable to become familiar with Qt’s widgets, their properties and how to use containers for laying them out.

Qt is extensively documented. A good, hands-on starting point is Qt Designer’s quick-start tutorial.

Some other documents about widgets and layouts are:

Unless you want to edit your .ui file directly in a text or XML editor, you will want to use Qt Designer to build and test your interface. Install it in your computer via your distribution package manager and have a look at its very fine manual.

You can use Qt’s powerful style sheets to control the look of your widgets, it is very much like CSS. If you want to design your own theme don’t miss the relevant sections of Qt’s documentation: