• sdaau_ml

    Meh, I should have thought of this earlier - the fix is just to use [set $1(, to update the value but not trigger a bang/message on the output:

    pd-sync-ok.png

    posted in technical issues read more
  • sdaau_ml

    Hi all,

    For a while I've wanted to have "synchronized" toggles, so that say I could have two of them, maybe one in top left of the patch window - and the other in the bottom right of the patch window, where I might be doing some work; and in case the window is large, then from the position of bottom right it would be a bit tedious and scroll to top left each time I wanted to click the button. In this kind of situation, I'd expect only one (say, the top left) to have its outlet connected to an actual object - the other would be there just to ease the working process.

    So basically, it would be "either/or" pair - if I toggle one button on, the other turns on too; if I then toggle the other off, the first one turns of too.

    Of course, if you just try to do the most trivial implementation of this:

    pd-recursegui.png

    ... that is, outlet of one into inlet of other, and vice versa - and then you click either one, - PD will either crash/segfault, or you'll get a "stack overflow" message; since in this case, a recursive update loop happens.

    So is there another method to allow for such "synchronized" buttons, without ending up in a recursive loop, and potentially crashing PD? Also, I could image synchronized number boxes to be useful, too...

    posted in technical issues read more
  • sdaau_ml

    Hi all,

    Let's assume you have an external, with this kind of code in it:

    ...
    typedef struct _MyExternal {
      ...
      int        var_a;
      int        var_b;
      int        var_c;
      int        var_d;
      ...
      t_symbol* obj_name;
     ...
    } t_MyExternal;
    ...
    
    void MyExternal_calcandprint(t_MyExternal *x) {
      x->var_d = x->var_a + x->var_b + x->var_c;
      post("The external has obj_name %s with values %d (%d+%d+%d)", x->obj_name->s_name, x->var_d, x->var_a, x->var_b, x->var_c );
    }
    
    void MyExternal_seta(t_MyExternal *x, t_float f) {
      x->var_a = f;
      MyExternal_calcandprint(x);
    }
    
    void MyExternal_setb(t_MyExternal *x, t_float f) {
      x->var_b = f;
      MyExternal_calcandprint(x);
    }
    
    void MyExternal_setc(t_MyExternal *x, t_float f) {
      x->var_c = f;
      MyExternal_calcandprint(x);
    }
    ...
      class_addmethod(MyExternal_class, (t_method)MyExternal_seta, gensym("seta"), A_FLOAT, 0);
      class_addmethod(MyExternal_class, (t_method)MyExternal_setb, gensym("setb"), A_FLOAT, 0);
      class_addmethod(MyExternal_class, (t_method)MyExternal_seta, gensym("setc"), A_FLOAT, 0);
    ...
    

    So, let's say I want to set these variables from PD, in a message like this:

    [ ;               <
    [ recvobj seta 3; |
    [ recvobj setb 4; |
    [ recvobj setc 5; <
    

    So, even if this content is in one message box, all of these message will be received individually, and so

    • first MyExternal_seta will run, calling MyExternal_calcandprint
    • then MyExternal_setb will run, calling MyExternal_calcandprint again
    • then MyExternal_setc will run, calling MyExternal_calcandprint yet again

    The thing is, these messages could come from different message boxes, but all sort of close in time, and this is the case I want to handle - I want each set* function to run individually as they do - but I'd want MyExternal_calcandprint to run only once, once all the variables have been set.

    However it is kind of impossible to predetermine whether only a, or also b and c will be changed in a call. So I imagine, if there existed a function, say, pd_defer_ctrl which I could use like:

    void MyExternal_setc(t_MyExternal *x, t_float f) {
      x->var_c = f;
      pd_defer_ctrl( 5, x->MyExternal_calcandprint );
    }
    

    it would help me with my problem, if it worked like this - if PD is not in "defer mode", then it enters it, and sets a threshold of 5 ms from now; then it adds MyExternal_calcandprint to a queue. Then when next set* message comes in, PD sees its already in "defer mode", sees it arrived before the threshold of 5 ms has expired - and so it first checks if MyExternal_calcandprint is already in the queue, and if it is, it does not add it again. Finally, once the threshold of 5 ms has expired, PD then runs all the functions in the defer queue.

    Is there something like that I could use in a PD external?


    EDIT: Turns out Max/MSP probably already has such an API function, because I can see in bonk~.c source:

    ...
    #ifdef MSP
    static void bonk_write(t_bonk *x, t_symbol *s)
    {
        defer(x, (method)bonk_dowrite, s, 0, NULL);
    }
    ...
    

    .... but I guess there is nothing like that for Pure Data...

    posted in extra~ read more
  • sdaau_ml

    Every once in a while, I come to having to program an external which ends up having some specific variables, which I'd prefer being set "internally" instead of exposing them through outlets, mostly to reduce clutter. And unfortunately, that is usually not easily visible in https://github.com/pure-data/externals-howto ...

    So, I'm not really sure if the below is the "correct" thing - I just managed to patch it together by reading from the PD source.

    You can find the code in:

    The help patch looks like this:

    sendtest-help.png

    Basically, this is a copy of [send], which when banged, triggers r AHA and r EHE - even if there aren't corresponding send objects. It turns out, there must be a pd_bind in order for this to work, and for a long time I thought the object argument there is the sender object - but actually it seems to be the receiving object reference. So this objects includes an additional "dummy" receiver class, a copy of [receive], which is there simply to initialize this binding, once this is done, other normal [receive] objects begin reacting on messages too.

    Now I noticed I don't actually have the code for setting [value] variables there, but it is easier - you simply declare a symbol, and then you call PD functions on it:

      t_symbol* s_mysimbol;
      ...
      x->s_mysimbol    = gensym("myvar");
      ...
      // initialize/instantiate the [value] variables (reading is with value_getfloat)
      // note - via value_get, these will also gain non-null ->s_thing property
      value_get(x->s_mysimbol);
      ...
      value_setfloat(x->s_mysimbol, 42);
      ...
      value_release(x->s_mysimbol);
    

    posted in extra~ read more
  • sdaau_ml

    Hi all,

    Is it possible for a PD external to detect its environment? By this I mean, distinguishing whether it runs on PD standalone on desktop, vs running in say libpd in an embedded environment?

    Thanks!

    posted in extra~ read more
  • sdaau_ml

    OK, I got the counting part solved - test.pd :

    pd-test2.png

    Simply another counter has to be added, it will count incoming messages on the cold inlet, and receive a slow "bang" on the hot one - and at the same time, this "bang" can reset this another counter...

    However, it will still be nice to know if there is a way to collect (and output) actual messages..

    posted in technical issues read more
  • sdaau_ml

    HI all,

    Consider the following patch, test.pd :

    pd-test.png

    Basically, when the [metro] is started, I'm having a message printed every 100 ms - this is as expected.

    However, this is what I'd like to do: put some sort of a "bucket" object at the output of the [hello $1 world $1( message box, and then have that "bucket" output connected to [print]. So, the incoming messages at 100 ms would be "collected"/"collated" by the "bucket" object, and nothing would be printed by [print] - and then when I "bang" the "bucket" object, either:

    • All messages received so fat would be output on the "bucket" object outlet, causing them to be printed
    • I would get a message such as "10 messages received" or similar, depending on how many messages arrived in the previous period

    As soon as the "bucket" object is "bang"ed in this way, it is "emptied", and a new period of collection can start again.

    Is there an object that does this in PD vanilla - or is there a combo of vanilla objects I could use to achieve this?

    posted in technical issues read more
  • sdaau_ml

    Awesome - many thanks for the help, @whale-av - I like both approaches, but I think I'd prefer the canvas properties.

    EDIT: if going through canvas properties, you must have "Graph on Parent" enabled, otherwise the size is not settable (and is ignored); but that is not really a problem, the default rendering is the same; also the default height for object boxes seems to be 18 pixels in PD vanilla...

    Btw, the limit that you noticed - I'm pretty sure there is a similar kind of limit of text character width in a comment box, so I guess it makes sense it is also applied to object boxes (at least 'pd' subpatch ones).

    Many thanks again!

    posted in technical issues read more
  • sdaau_ml

    Hi all, am on Ubuntu 18.04, using the PD vanilla that comes with it (puredata:all/bionic 0.48.1-3).

    This is the test I tried doing: I make a new patch (test.pd), inside I make a subpatch [pd blah], and inside blah, I put several [outlet]s:

    out1.png

    Clearly, the outlets on the subpatch are so tight close to each other, that it makes sense that I would "stretch" the width of the [pd blah] object:

    out2.png

    Great, it stretches, the outlets are now individually visible... So I save the test.pd, close it, reopen it again... and [pd blah] is again just as tight as on the first image?!

    Does anyone know, if there is some sort of a trick, so I can save the "widened" [pd blah] object in my test.pd patch?!

    posted in technical issues read more
  • sdaau_ml

    Thanks again for the discussion, all:

    Hi @sdaau_ml I was intrigued by how this might be done in Windows (you didn't say which OS).

    I'm on Ubuntu 18 / Linux, so [shell] would have been great, but not for patches that would run in vanilla...

    Thanks again!

    posted in technical issues read more

Internal error.

Oops! Looks like something went wrong!