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, callingMyExternal_calcandprint
- then
MyExternal_setb
will run, callingMyExternal_calcandprint
again - then
MyExternal_setc
will run, callingMyExternal_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...