<div dir="ltr">Miller<div><br></div><div>Does that still prevent multiple instances of a libpd based VST from loading in a host?</div><div><br></div><div>Chris</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Mon, May 12, 2014 at 10:12 AM, Miller Puckette <span dir="ltr">&lt;<a href="mailto:msp@ucsd.edu" target="_blank">msp@ucsd.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I think the global shared symbol space will cause some confusion (patches<br>
will have to protect their sends and receives, etc., by fabricating local<br>
names using &#39;$&#39; characters.<br>
<br>
Also, it won&#39;t be possible to run several Pds concurrently on several<br>
threads - in a threaded environment, each Pd instance will have to lock<br>
all others out while it runs.  (There might be a fix for that by replacing<br>
all static variables in Pd by thread-local ones, but this is untested and<br>
I&#39;d hate to do it unless there&#39;s a real need for it, since it would involve<br>
systematically changing 100s of variable definitions in Pd.)<br>
<br>
I&#39;m not sure about timing - that depends partly on the libpd release process<br>
that I&#39;m not involved in.<br>
<br>
cheers<br>
Miller<br>
<div><div class="h5">On Mon, May 12, 2014 at 09:45:25AM -0400, Rob Bairos wrote:<br>
&gt; Hi Miller.<br>
&gt; Thats very exciting news!<br>
&gt; Can you give a brief synopsis of what you think the biggest remaining<br>
&gt; limitations are and a rough  timeline as to when a stable multi-instance<br>
&gt; pdlib would be available for general use?<br>
&gt;<br>
&gt; Thanks again!<br>
&gt; Rob Bairos.<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; On Sun, May 11, 2014 at 3:00 AM, Miller Puckette &lt;<a href="mailto:msp@ucsd.edu">msp@ucsd.edu</a>&gt; wrote:<br>
&gt;<br>
&gt; &gt; To Pd developers...<br>
&gt; &gt;<br>
&gt; &gt; I&#39;ve adapted Pd to nternally use a &quot;pdinstance&quot; structure to allow<br>
&gt; &gt; multiple schedulers (including DSP chains) to run in one address space.<br>
&gt; &gt; With slight modification (see below) libpd can use this to run separate<br>
&gt; &gt; patches asynchronously.<br>
&gt; &gt;<br>
&gt; &gt; I tried to &quot;instance-ize&quot; all Pd symbols to keep them private but ran into<br>
&gt; &gt; seemingly insoluble problems, so am leaving all symbols global for now.<br>
&gt; &gt; (So patches used in pdlib, if they want to be usable in a multiple-instance<br>
&gt; &gt; scenaro, should protect all send/receive/table/delay/etc named objects with<br>
&gt; &gt; a $[0-9] somewhere.<br>
&gt; &gt;<br>
&gt; &gt; I didn&#39;t look hard, but I thnk pdlib now will need a way to send $<br>
&gt; &gt; arguments<br>
&gt; &gt; to patches via libpd_openfile() somehow.  Also, libpd_init_audio() will<br>
&gt; &gt; want to<br>
&gt; &gt; make number of channels per-instance, etc.  I&#39;ve put some relevant comments<br>
&gt; &gt; in the test program I&#39;ll include below (and sorry for the length of this<br>
&gt; &gt; mail!)<br>
&gt; &gt;<br>
&gt; &gt; Here&#39;s how I modified libpd_wrapper/z_libpd.c:<br>
&gt; &gt;<br>
&gt; &gt; 55d54<br>
&gt; &gt; &lt;   sys_time = 0;<br>
&gt; &gt; 110c109<br>
&gt; &gt; &lt;   sched_tick(sys_time + sys_time_per_dsp_tick);<br>
&gt; &gt; ---<br>
&gt; &gt; &gt;   sched_tick();<br>
&gt; &gt; 130c129<br>
&gt; &gt; &lt;     sched_tick(sys_time + sys_time_per_dsp_tick); \<br>
&gt; &gt; ---<br>
&gt; &gt; &gt;     sched_tick(); \<br>
&gt; &gt;<br>
&gt; &gt; ----------------------<br>
&gt; &gt; and here (sorry again) is the test program, &quot;pdtest2.c&quot; adapted from<br>
&gt; &gt; libpd-master/samples/c_samples/c/pdtest.c :<br>
&gt; &gt; ---------------------<br>
&gt; &gt;<br>
&gt; &gt; #include &lt;stdio.h&gt;<br>
&gt; &gt; #include &quot;z_libpd.h&quot;<br>
&gt; &gt; #include &quot;m_imp.h&quot;<br>
&gt; &gt; #define TIMEUNITPERMSEC (32. * 441.)<br>
&gt; &gt;<br>
&gt; &gt; void pdprint(const char *s) {<br>
&gt; &gt;   printf(&quot;%s&quot;, s);<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; void pdnoteon(int ch, int pitch, int vel) {<br>
&gt; &gt;   printf(&quot;noteon: %d %d %d\n&quot;, ch, pitch, vel);<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; int main(int argc, char **argv) {<br>
&gt; &gt;   t_pdinstance *pd1 = pdinstance_new(), *pd2 = pdinstance_new();<br>
&gt; &gt;   if (argc &lt; 3) {<br>
&gt; &gt;     fprintf(stderr, &quot;usage: %s file folder\n&quot;, argv[0]);<br>
&gt; &gt;     return -1;<br>
&gt; &gt;   }<br>
&gt; &gt;<br>
&gt; &gt;   int srate = 44100;<br>
&gt; &gt;     // maybe these two calls should be available per-instnace somehow:<br>
&gt; &gt;   libpd_set_printhook(pdprint);<br>
&gt; &gt;   libpd_set_noteonhook(pdnoteon);<br>
&gt; &gt;     /* set a &quot;current&quot; instance before libpd_init() or else Pd will make<br>
&gt; &gt;     an unnecessary third &quot;default&quot; instance. */<br>
&gt; &gt;   pd_setinstance(pd1);<br>
&gt; &gt;   libpd_init();<br>
&gt; &gt;     /* ... here we&#39;d sure like to be able to have number of channels be<br>
&gt; &gt;     per-nstance.  The sample rate is still global within Pd but we might<br>
&gt; &gt;     also consider relaxing that restrction. */<br>
&gt; &gt;   libpd_init_audio(1, 2, srate);<br>
&gt; &gt;<br>
&gt; &gt;   float inbuf[64], outbuf[128];  // one input channel, two output channels<br>
&gt; &gt;                                  // block size 64, one tick per buffer<br>
&gt; &gt;<br>
&gt; &gt;   pd_setinstance(pd1);  // talk to first pd instance<br>
&gt; &gt;<br>
&gt; &gt;   // compute audio    [; pd dsp 1(<br>
&gt; &gt;   libpd_start_message(1); // one entry in list<br>
&gt; &gt;   libpd_add_float(1.0f);<br>
&gt; &gt;   libpd_finish_message(&quot;pd&quot;, &quot;dsp&quot;);<br>
&gt; &gt;<br>
&gt; &gt;   // open patch       [; pd open file folder(<br>
&gt; &gt;   libpd_openfile(argv[1], argv[2]);<br>
&gt; &gt;<br>
&gt; &gt;   pd_setinstance(pd2);<br>
&gt; &gt;<br>
&gt; &gt;   // compute audio    [; pd dsp 1(<br>
&gt; &gt;   libpd_start_message(1); // one entry in list<br>
&gt; &gt;   libpd_add_float(1.0f);<br>
&gt; &gt;   libpd_finish_message(&quot;pd&quot;, &quot;dsp&quot;);<br>
&gt; &gt;<br>
&gt; &gt;   // open patch       [; pd open file folder(<br>
&gt; &gt;   libpd_openfile(argv[1], argv[2]);<br>
&gt; &gt;<br>
&gt; &gt;     /* the follownig two messages can be sent without setting the pd<br>
&gt; &gt; nstance<br>
&gt; &gt;     and anyhow the symbols are global so they may affect multiple<br>
&gt; &gt; instances.<br>
&gt; &gt;     However, if the messages change anyhing in the pd instacne structure<br>
&gt; &gt;     (DSP state; current time; list of all canvases n our instance) those<br>
&gt; &gt;     changes will apply to the current Pd nstance, so the earlier messages,<br>
&gt; &gt;     for instance, were sensitive to which was the current one.<br>
&gt; &gt;<br>
&gt; &gt;     Note also that I&#39;m using the fact taht $0 is set to 1003, 1004, ...<br>
&gt; &gt;     as patches are opened -it would be better to opent the patches with<br>
&gt; &gt;     settable $1, etc parameters to libpd_openfile().  */<br>
&gt; &gt;<br>
&gt; &gt;   // [; pd frequency 1 (<br>
&gt; &gt;   libpd_start_message(1); // one entry in list<br>
&gt; &gt;   libpd_add_float(1.0f);<br>
&gt; &gt;   libpd_finish_message(&quot;1003-frequency&quot;, &quot;float&quot;);<br>
&gt; &gt;<br>
&gt; &gt;   // [; pd frequency 1 (<br>
&gt; &gt;   libpd_start_message(1); // one entry in list<br>
&gt; &gt;   libpd_add_float(2.0f);<br>
&gt; &gt;   libpd_finish_message(&quot;1004-frequency&quot;, &quot;float&quot;);<br>
&gt; &gt;<br>
&gt; &gt;   // now run pd for ten seconds (logical time)<br>
&gt; &gt;   int i, j;<br>
&gt; &gt;   for (i = 0; i &lt; 3; i++) {<br>
&gt; &gt;     // fill inbuf here<br>
&gt; &gt;     pd_setinstance(pd1);<br>
&gt; &gt;     libpd_process_float(1, inbuf, outbuf);<br>
&gt; &gt;     if (i &lt; 2)<br>
&gt; &gt;     {<br>
&gt; &gt;         for (j = 0; j &lt; 8; j++)<br>
&gt; &gt;             printf(&quot;%f &quot;, outbuf[j]);<br>
&gt; &gt;         printf(&quot;\n&quot;);<br>
&gt; &gt;     }<br>
&gt; &gt;     pd_setinstance(pd2);<br>
&gt; &gt;     libpd_process_float(1, inbuf, outbuf);<br>
&gt; &gt;     if (i &lt; 2)<br>
&gt; &gt;     {<br>
&gt; &gt;         for (j = 0; j &lt; 8; j++)<br>
&gt; &gt;             printf(&quot;%f &quot;, outbuf[j]);<br>
&gt; &gt;         printf(&quot;\n&quot;);<br>
&gt; &gt;     }<br>
&gt; &gt;   }<br>
&gt; &gt;<br>
&gt; &gt;   return 0;<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; ----------------------<br>
&gt; &gt; I replaced &quot;test.c&quot; as follows:<br>
&gt; &gt; ---------------------<br>
&gt; &gt;<br>
&gt; &gt; #N canvas 406 290 450 300 10;<br>
&gt; &gt; #X obj 97 64 loadbang;<br>
&gt; &gt; #X obj 97 131 print;<br>
&gt; &gt; #X obj 186 106 dac~;<br>
&gt; &gt; #X obj 97 107 f 0;<br>
&gt; &gt; #X obj 128 107 + 1;<br>
&gt; &gt; #X obj 97 86 metro 2;<br>
&gt; &gt; #X obj 185 41 r \$0-frequency;<br>
&gt; &gt; #X obj 188 73 osc~;<br>
&gt; &gt; #X obj 248 127 print \$0-frequency;<br>
&gt; &gt; #X obj 248 97 loadbang;<br>
&gt; &gt; #X connect 0 0 5 0;<br>
&gt; &gt; #X connect 3 0 1 0;<br>
&gt; &gt; #X connect 3 0 4 0;<br>
&gt; &gt; #X connect 4 0 3 1;<br>
&gt; &gt; #X connect 5 0 3 0;<br>
&gt; &gt; #X connect 6 0 7 0;<br>
&gt; &gt; #X connect 6 0 8 0;<br>
&gt; &gt; #X connect 7 0 2 0;<br>
&gt; &gt; #X connect 7 0 2 1;<br>
&gt; &gt; #X connect 9 0 8 0;<br>
&gt; &gt;<br>
&gt; &gt; ----------------------------<br>
&gt; &gt; and got this output:<br>
&gt; &gt;<br>
&gt; &gt; print: 0<br>
&gt; &gt; 1003-frequency: bang<br>
&gt; &gt; print: 0<br>
&gt; &gt; 1004-frequency: bang<br>
&gt; &gt; 1003-frequency: 1<br>
&gt; &gt; 1004-frequency: 2<br>
&gt; &gt; 1.000000 1.000000 0.999999 0.999999 0.999998 0.999998 0.999997 0.999997<br>
&gt; &gt; 1.000000 1.000000 0.999998 0.999998 0.999996 0.999996 0.999995 0.999995<br>
&gt; &gt; print: 1<br>
&gt; &gt; 0.999944 0.999944 0.999943 0.999943 0.999942 0.999942 0.999941 0.999941<br>
&gt; &gt; print: 1<br>
&gt; &gt; 0.999815 0.999815 0.999810 0.999810 0.999804 0.999804 0.999799 0.999799<br>
&gt; &gt; print: 2<br>
&gt; &gt; print: 2<br>
&gt; &gt;<br>
&gt; &gt; ... Looks like there are 2 schedulers adn DSP chains running :)<br>
&gt; &gt;<br>
&gt; &gt; Miller<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; _______________________________________________<br>
&gt; &gt; Pd-dev mailing list<br>
&gt; &gt; <a href="mailto:Pd-dev@iem.at">Pd-dev@iem.at</a><br>
&gt; &gt; <a href="http://lists.puredata.info/listinfo/pd-dev" target="_blank">http://lists.puredata.info/listinfo/pd-dev</a><br>
&gt; &gt;<br>
<br>
</div></div>_______________________________________________<br>
Pd-dev mailing list<br>
<a href="mailto:Pd-dev@lists.iem.at">Pd-dev@lists.iem.at</a><br>
<a href="http://lists.puredata.info/listinfo/pd-dev" target="_blank">http://lists.puredata.info/listinfo/pd-dev</a><br>
</blockquote></div><br></div>