[Object Notifications] notify buffer to redraw it's window
Hi there!
I have been programming some C MSP externals, one dealing with recording into / playing back from a buffer.
One of the things that also appears elsewhere in the forum, with some links to Tim's 74 objects blog, is how do you get the buffer to redraw its window when its data is changed.
Although I went through the various conversations / resources I still do not understand what is the best way to do it for *Max 5* and would very much appreciate your, more experienced, input on this.
cheers,
Panos
I believe the correct approach is:
object_method ((t_object *)buffer_pointer, gensym("dirty"));
That's what I've been using and it seems to work for me....
Alex
Thank you Alex!
for people asking the same question in the future, here is an addendum:
if you want your buffer to redraw itself, be sure to put the function call Alex mentioned above,
into your perform routine (a sane person would not call it on every sample, rather call it just before you are about to return)
Hi there,
with all due respect, let me say that putting the function in the perform routine might not be a good idea...
- Luigi
No - I probably wouldn't call that directly from the perform routine either.
It's hard to say exactly what scheme you should be using in your case (without any code or further details), but I would either:
1 - start a clock when recording / modification is triggered and have the clock recall itself at a specified interval to call the routine.
2 - Implement a sample counter in the perform routine and every x number of samples (according to the sample rate and a sensible time interval) call defer to call a routine that calls dirty (or something like that).
Both these methods avoid calling this routine too often (imagine you are running at a vector size of 1 for instance) and keep the call in a max thread where you will not have issues (it is not certain you will have issues otherwise but it is a possibility). At the very least I would implement the sample counter so that behaviour is fairly consistent with a range of vector sizes...
Someone at c74 may be able to advise better on whether this particular call to object_method is safe or not - in general max type calls in the perform thread are not a good idea...
A
Hi.
If I may add my 2 cents, I would not set up a sample counter, but a vector counter. Or, which is basically the same, updating your sample counter only once per vector.
cheers
aa
!!!Sorry!!!!! I made a mistake when posting my previous reply!! I did not mean to write "sample", I meant "sample vector". Somebody should think/look twice before posting :(
In my case I do it upon a sample counter reset (that is there anyway) to reduce overhead (since it is not reset often), almost like what you described, Alex. Not with defer though...
I will investigate the first way further too (seems safer). Here is the current state of affairs of my code:
Thank you for all your input so far!
sincerely,
Panos
t_int *LPPerformSig(t_int *w) {
/*assume:
a struct x with members count, mbuf resetTime
a long int counter in your struct x
and all inputs from w initialized...
*/
if (x->m_obj.z_disabled) { goto mute; }
if (!x->mbuf) { goto zero; }
//lock:
ATOMIC_INCREMENT(&x->mbuf->b_inuse);
if (!x->mbuf->b_valid) {
ATOMIC_DECREMENT(&x->mbuf->b_inuse);
goto zero;
}
while(i--) {
//do stuff...
x->counter++;
if (x->counter >= x->resetTime) {
counter = 0;
//the way i do it now, will look at using a clock instead:
object_method ((t_object *)x->mbuf, sym_dirty);
}
//do more stuff...
}
ATOMIC_DECREMENT(&x->mbuf->b_inuse);
return (w+9);
zero:
while (i--) {
*out++ = 0.0f;
*out2++ = 0.0f;
}
mute:
return (w+9);
}
It is, in fact, safe to dirty the buffer in the perform method. This is how we do it (at the vector rate) in our objects in the standard MSP object set (e.g. record~, poke~, etc.).
Cheers
Thank you for your input Tim. Also, I enjoyed reading your posts on 74objects!
sincerely,
Panos