The documentation is heavily incomplete. I know this. The situation will improve within the next five years. If you feel that you would really need some documentetaion, please ask. I might then get the motivation to write it.
The programming language is C++. The GUI toolkit is Qt by Troll-Tech (version 2.2.x, 2.3.x or 3.x). Mustajuuri currently requires a POSIX-compliant system. Supported platforms are Linux and IRIX. Most functionality is incorporated in the plugins. Plugins are loaded dynamically to the system.
The plugin system is meant for high-level signal processing. Within the plugins you can use any toolkits/libraries you like; STK (Synthesis toolkit), SPK (Sound processing kit), FFTW (Fastest Fourier transform in the west) etc. There is - however - a small standalone library that contains efficient implementations for few of the most common DSP operations. This library - libmjdsp - is used widely in the standard Mustajuuri plugins.
Basics: All plugins inherit a common base class MJ_ModuleDsp. This class has number of virtual methods that can (and need to) be overridden to insert your own functionality. A plugin may also define a custom user interface to replace the default UI. Currently there are two sorts of UIs, graphical ones (GUI) and text-based ones (TUI, not really that supported). As with he DSP code the GUI modules are plugins that inherit a common base class MJ_ModuleDspGui
As there are different ways to use a plugin there are different requirements for the user interface. Sometimes a small simplified interface is needed (when adjusting the most important parameters) while at other times more elaborate interface is needed (giving access to all of the functionality). Thus it is necessary that the plugin may define multiple GUIs for these purposes. The GUI may of course be the same for all purposes, but such behaviour is discouraged.
Granularity of the plugin interface: Plugins are meant to be medium to large pieces of code (reverb, EQ, chorus, synth). Of course you can make very small plugins (single delay line, adder, multiplier) as well. The current master interfaces (mixer and row) do not really support this kind of small plugins well, but you can build a canvas interface (a la Max or Kyma) that can take full benefit of the them.
When it works well: If it isn't too necessary that certain samples arrive to certain module a sample or two early or late. Such applications are mixers. Often this approach can be used with DSP nets like Max and Kyma (which do buffer the audio).
When it does not work well: The buffered signal IO causes inevitable problems when it comes to making very accurate DSP systems where sample-accurate delay-times are needed and maximum processing buffer size is one sample. Such application is for example physical modeling of musical instruments. For these situations a low-level signal processing library is the proper tool.
Signal IO: Each module has some number of signal (continuous IO at fixed sampling rate) input- and output terminals. Signals are passed via these terminals from one module (module = plugin instance) to another.
Event IO: Each module can also receive messages (MIDI, string, double, arbitrary). These messages are timestamped and they also contain target address in the form of a character string.
The API is fairly big and provides a rich set of fundamental tools. Most features that one can access are optional, not obligatory. The current API and library directly supports following features:
Note that the plugin API is not concerned with what your plugin does or how it will be eventually displayed. All current screenshots feature mixer or row layout, but a "wires and boxes" approach (a la Kyma or Max) is also possible. Such user interface can be built by making a new plugin that does it (the mixer and row interface are themselves plugins).
There are things that could also be done:
The first example plugin is a monophonic effect that squares the input values. The plugin is created with about thirty lines of effective code. The code is hopefully self-explanatory :-)
The second example plugin is a monophonic low-pass filter. It relies on Mustajuuri to create the GUI and save all the parameters to disk. While it does not take too much code or effort to create plugin (just make a new C++ class) the result is a full-featured module: internationalization is supported, the hosting system can save the parameters to a file and undo/redo is supported. After the code is compiled to a shared library you can start using modules of this type in your mixers etc.
The file and edit menus contain the things you
The third example plugin is a stereo eight-tap delay. It defines a GUI class of its own that is tuned to make the plugin easier and faster to use. Since it is a relatively simple plugin it can still rely on Mustajuuri to save the parameters (delay times, panning etc.) to the disk.
This is a fine example of why one might want to make a custom GUI for a plugin. The number of parameters is fairly large in this case (27 to be exact). Most of them need to grouped and weighted. Some of them are visualized in the graph. This way the plugin can be used much more effectively and easily.
While custom GUIs are nice so is code reuse. In this case the menu bar with its standard file and edit items is created with two lines of plugin code. The graphics in the middle are created with the widget extension library (libmjwidgets) that comes with Mustajuuri.