[PD-dev] Multi-instance support for libPD

Pierre Guillot guillotpierre6 at gmail.com
Sat Apr 2 11:11:19 CEST 2016


Hi,

I created a plugin that loads Pure Data patches so I had to use several
instances of Pure Data in a multi thread context. I managed to solve the
problems using t_pdinstance and locks (so I needed to create my own wrapper
like libpd). I think it would be great to integrate some of these
improvements to libpd. Before sending a pull request or opening another
issue on the repository about it, I thought that it would be better to
present how I did this here.



I'm assuming that several instances can't run in parallel for 3 main
reasons:


1 - The clocks can be created on the fly, so if the current instance is not
the right one, the clocks can be integrated in a wrong list. This problem
implies that all the methods that can create a clock (so potentially all
the messages sent to Pure Data) and the sched_tick method must be called
sequentially. I tried to find a solution (
https://sourceforge.net/p/pure-data/patches/559/) but there are always some
specific cases that can’t be thread safe. The only real solution is (by a
way or another) to set up the instance of the clock at its creation but
this implies to change the interface of Pure Data and potentially (surely)
a lot of externals would be deprecated.


2 - The vectors of audio input and output are global and the dsp_add method
is global. So the DSP method must be called with the right instance. Here
again, the only real solution would be to change the interface of Pure
Data, to receive the instance in the dsp method and to add the perform
methods to this instance. The dac and adc objects would also be able to
retrieve the the vector of audio input and output specific to the instance.


3 - The MIDI methods are global. That implies that most the methods must be
called sequentially if you don’t want to receive or send MIDI events to the
wrong instance.



So the best solution is simply to use t_pdinstance. If the interface is
opaque and before calling any method you set the instance and lock it, you
should not have any problem. Basically, my interface is like this: First,
initialize Pure Data and after you can call

-  Create an instance (lock – create the instance – unlock). Each instance
has its own vectors of audio input and output, MIDI methods, print method.

- Create a patch (lock, set the instance, create the patch, unlock).

- Prepare the dsp (lock, set the instance, reallocate the vectors of audio
if the sample rate or the number of inputs or outputs changed, send dsp
start message, unlock). In the DAWs like Reaper you must be able to have
two instances running with two different sample rates.

-  All the other methods are called like this:

    - Lock and set the instance

   - Send the MIDI events, send the messages, process the DSP

   - Unlock

When you set the instance it also sets the current vectors of audio, the
print method and the MIDI methods so the instance receives all the MIDI
output event, output messages, posts, etc. It seems better to gather the
methods for the messages, MIDI and DSP together. You can avoid this but in
practise, I don’t see any reason.

The instance management is mostly in the c wrapper and the lock feature is
in the C++ wrapper. Here the code: (
https://github.com/pierreguillot/Camomile/tree/master/Source/Pd).  Most of
the important stuff are in z_pd.c/.h (and PdInstance.cpp/.hpp). Of course,
I have my own programming style, if you are interested I'll submit merge
requests trying to respect the libPD programming style.


Cheers
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20160402/ece32613/attachment.html>


More information about the Pd-dev mailing list