hi all, hi Miller,
how about adding to the core the following, minimal interface, and letting people define state-saving externals, like Guenter's state, cyclone's preset, or anything else:
--- m_pd.h~ 2003-10-01 06:05:28.000000000 +0200 +++ m_pd.h 2003-12-02 09:42:37.000000000 +0100 @@ -428,4 +428,8 @@ EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f); EXTERN t_propertiesfn class_getpropertiesfn(t_class *c); + /* prototype for functions to store Pd's state to a binbuf */ +typedef int (*t_statefn)(t_gobj *x, t_binbuf *b, int flags); +EXTERN void class_setstatefn(t_class *c, t_statefn f); +EXTERN t_statefn class_getstatefn(t_class *c);
#ifndef PD_CLASS_DEF
--- m_imp.h~ 2003-08-27 18:30:15.000000000 +0200 +++ m_imp.h 2003-12-02 09:33:23.000000000 +0100 @@ -47,4 +47,5 @@ t_savefn c_savefn; /* function to call when saving */ t_propertiesfn c_propertiesfn; /* function to start prop dialog */ + t_statefn c_statefn; /* function to store a state */ int c_floatsignalin; /* onset to float for signal input */ char c_gobj; /* true if is a gobj */
--- m_class.c~ 2003-09-16 06:39:26.000000000 +0200 +++ m_class.c 2003-12-02 09:36:59.000000000 +0100 @@ -209,4 +209,5 @@ c->c_externdir = class_extern_dir; c->c_savefn = (typeflag == CLASS_PATCHABLE ? text_save : class_nosavefn); + c->c_statefn = 0; #if 0 post("class: %s", c->c_name->s_name); @@ -446,4 +447,14 @@ }
+void class_setstatefn(t_class *c, t_statefn f) +{ + c->c_statefn = f; +} + +t_statefn class_getstatefn(t_class *c) +{ + return (c->c_statefn); +} +
That is all, really. Any class with a state, would then define something like the gatom below:
--- g_text.c~ 2003-10-27 22:09:10.000000000 +0100 +++ g_text.c 2003-12-02 09:43:10.000000000 +0100 @@ -862,4 +862,14 @@ }
+static int gatom_state(t_gobj *z, t_binbuf *bb, int flags) +{ + t_gatom *x = (t_gatom *)z; + t_atom at; + SETSYMBOL(&at, gensym("set")); + binbuf_add(bb, 1, &at); + binbuf_add(bb, 1, &x->a_atom); + binbuf_addsemi(bb); + return (0); +}
/* -------------------- widget behavior for text objects ------------ */ @@ -1308,4 +1318,5 @@ class_setwidget(gatom_class, &gatom_widgetbehavior); class_setpropertiesfn(gatom_class, gatom_properties); + class_setstatefn(gatom_class, gatom_state); }
Storing a glist's state into a preset/state/whatever requires only this:
t_gobj *g; t_binbuf *bb = binbuf_new(); int id; for (g = x->x_glist->gl_list, id = 0; g; g = g->g_next, id++) { t_object *ob; t_statefn statefn; if ((ob = pd_checkobject((t_pd *)g)) && (statefn = class_getstatefn(*(t_pd *)g))) { binbuf_addv(bb, "isii", id, gensym(class_getname(*(t_pd *)g)), (int)ob->te_xpix, (int)ob->te_ypix); (*statefn)(g, bb, 0); } } /* do what you like with the binbuf here */ binbuf_free(bb);
Validation could be based on checking an id against a class name, and, optionally, a position.
Krzysztof
Hallo, Krzysztof Czaja hat gesagt: // Krzysztof Czaja wrote:
...
Not that I really understand your patch fully, but does statefn also handle setting the state again afterwards? Or is this still only possible through the standard ways to set an internal state, i.e. through inlets or messages?
ciao
hi Frank,
these changes are for enabling external devs to code [preset], [state], etc.
[preset]'s user would just create a [preset] object, and click (shift-click for storing) on its slots, or control the thing with messages.
k
Frank Barknecht wrote: ...
Not that I really understand your patch fully, but does statefn also handle setting the state again afterwards? Or is this still only possible through the standard ways to set an internal state, i.e. through inlets or messages?
On Tue, 2 Dec 2003, Krzysztof Czaja wrote:
hi Frank,
these changes are for enabling external devs to code [preset], [state], etc.
[preset]'s user would just create a [preset] object, and click (shift-click for storing) on its slots, or control the thing with messages.
Hi
It is a good thing to have an official API for saving state. In the case of state the API doesn't really help (Well, it does if I wanted to save the sliders and GUIs from PD, but this is not the main problem yet).
The important question is how to make the system robust against later edits of the patch and how to make it possible to include more than one abstraction that has state saving in a patch.
This can not be solved with the object position and class name. Position has the problem that you can not move the object afterwards, the class name is too general (there will be only few, number, slider, toggle).
My experience when working with state is, that most of the time you do not want all the GUI's to be saved. This let me to the idea that in order to make one of the GUI objects save its state, it should have an unique identifier (more than position and class name), one that can be set in the settings dialog.
If every object has a settable "save-symbol", we solve both problems. Only objects with save-symbols are saved, and we can identify them upon loading easily.
The next problem is with multiple abstractions of the same type in one patch. In this case, the state(preset . whatever) itself has a parameter that can be changed per abstraction (either as an argument or via a set message). This way we can distinguish several abstractions.
This would mean the addition of a save_symbol for every saveable object within pd, together with the API K. suggested.
Does this make sense ?
Guenter
k
Frank Barknecht wrote: ...
Not that I really understand your patch fully, but does statefn also handle setting the state again afterwards? Or is this still only possible through the standard ways to set an internal state, i.e. through inlets or messages?
PD-dev mailing list PD-dev@iem.at http://iem.at/cgi-bin/mailman/listinfo/pd-dev
I think unique IDs for the objects makes sense. I've had to do this for my OSC abstractions (am using the first creation argument currently). I see a symbol_id for each abstraction (or gui object?) as giving these benifits:
possibility of namespaces for the abstractions, useful for OSC etc.. Adds the possibility (in the future) of making dynamic object connections much easier.
It would be great that the symbol be accessible iside pd via a new $ variable.
Sounds good...
Ben ----- Original Message ----- From: "guenter geiger" geiger@xdv.org To: "Krzysztof Czaja" czaja@chopin.edu.pl Cc: "Frank Barknecht" fbar@footils.org; "pd-dev" pd-dev@iem.kug.ac.at Sent: Tuesday, December 02, 2003 1:22 PM Subject: Re: [PD-dev] presets, a proposal
On Tue, 2 Dec 2003, Krzysztof Czaja wrote:
hi Frank,
these changes are for enabling external devs to code [preset], [state], etc.
[preset]'s user would just create a [preset] object, and click (shift-click for storing) on its slots, or control the thing with messages.
Hi
It is a good thing to have an official API for saving state. In the case of state the API doesn't really help (Well, it does if I wanted to save the sliders and GUIs from PD, but this is not the main problem yet).
The important question is how to make the system robust against later edits of the patch and how to make it possible to include more than one abstraction that has state saving in a patch.
This can not be solved with the object position and class name. Position has the problem that you can not move the object afterwards, the class name is too general (there will be only few, number, slider, toggle).
My experience when working with state is, that most of the time you do not want all the GUI's to be saved. This let me to the idea that in order to make one of the GUI objects save its state, it should have an unique identifier (more than position and class name), one that can be set in the settings dialog.
If every object has a settable "save-symbol", we solve both problems. Only objects with save-symbols are saved, and we can identify them upon loading easily.
The next problem is with multiple abstractions of the same type in one patch. In this case, the state(preset . whatever) itself has a parameter that can be changed per abstraction (either as an argument or via a set message). This way we can distinguish several abstractions.
This would mean the addition of a save_symbol for every saveable object within pd, together with the API K. suggested.
Does this make sense ?
Guenter
k
Frank Barknecht wrote: ...
Not that I really understand your patch fully, but does statefn also handle setting the state again afterwards? Or is this still only possible through the standard ways to set an internal state, i.e. through inlets or messages?
PD-dev mailing list PD-dev@iem.at http://iem.at/cgi-bin/mailman/listinfo/pd-dev
PD-dev mailing list PD-dev@iem.at http://iem.at/cgi-bin/mailman/listinfo/pd-dev
hi Guenter,
the main advantage of the proposal is simplicity. Another advantage is, that it is equivalent to the preset api in max, yet simpler, and different enough to avoid copyright claims. Besides, it works out-of-the-box (I have already done a preset's prototype, in order to test it).
The main point is that both validation, and object selection, is done in a client code. So, it is up to a client code to use symbolic ids, once these are available.
For my part, I do not feel they are needed so badly. What most users expect, is to be able to drop a [preset] object on a patch, and click on it. For more demanding users, there are various ways of including or excluding objects. The [preset] in max includes all guis in a patch by default (except [table]), and uses connections drawn from its outlets for specifying exceptions. This is a flat scheme, though -- subpatches and abstractions need their own [preset]s (synchronization is pretty easy).
Checking symbolic ids should be just another way, used by another client. Yet another could be based on the 'flags' argument and return value of the statefn call, as designed in the proposal ``for future use''.
Also with validation, just checking object's serial number against its class name should do for recalling from memory. An additional xy check, and a simple warning if failed, seems ok for loading from a file. There is no danger of corrupting things, because an object is guaranteed to handle restoring request -- the requst being a simple pd_forwardmess() call, which passes atoms stored by the object's class' statefn function. If this happens to be another object of the same class, then a user would probably figure out that the edits have been made, without much confusion (ask maxers).
Without knowing Miller's opinion, we are probably wasting our time, though...
Krzysztof
guenter geiger wrote: ...
It is a good thing to have an official API for saving state. In the case of state the API doesn't really help
why is it so, btw?
On Wed, 3 Dec 2003, Krzysztof Czaja wrote:
hi Guenter,
the main advantage of the proposal is simplicity. Another advantage is, that it is equivalent to the preset api in max, yet simpler, and different enough to avoid copyright claims. Besides, it works out-of-the-box (I have already done a preset's prototype, in order to test it).
Of course it works. No doubt.
The main point is that both validation, and object selection, is done in a client code. So, it is up to a client code to use symbolic ids, once these are available.
But how are you adding a symbolic id to an object outside of pd ? There is no way you can tell if the object is still the same with just its classname and coordinates.
For my part, I do not feel they are needed so badly. What most users expect, is to be able to drop a [preset] object on a patch, and click on it. For more demanding users, there are various ways of including or excluding objects. The [preset] in max includes all guis in a patch by default (except [table]), and uses connections drawn from its outlets for specifying exceptions.
Does not sound very intuitive to me.
This is a flat scheme, though -- subpatches and abstractions need their own [preset]s (synchronization is pretty easy).
Checking symbolic ids should be just another way, used by another client. Yet another could be based on the 'flags' argument and return value of the statefn call, as designed in the proposal ``for future use''.
Also with validation, just checking object's serial number against its class name should do for recalling from memory. An additional xy check, and a simple warning if failed, seems ok for loading from a file.
WIth symbolic ids you get the advantage that it won't fail to load load states if you just moved the object in the patch.
There is no danger of corrupting things, because an object is guaranteed to handle restoring request -- the requst being a simple pd_forwardmess() call, which passes atoms stored by the object's class' statefn function. If this happens to be another object of the same class, then a user would probably figure out that the edits have been made, without much confusion (ask maxers).
Without knowing Miller's opinion, we are probably wasting our time, though...
I did not say that your approach is bad. As we have been talking about this subject already, I know that Miller doesn't like the max approach, and I have to agree with him.
No matter if you put the logic of doing this into the state saving client, or if you put it into pd itself. Its still clumsy, checking class names (which will be the same most of the time), checking positions (which don't and shouldn't have anything to do with the object identity).
Serial number change too if you delete objects.
At the end you will probably have perfect error checking, but absolutely no tolerance (at the same time you could put timestamps onto the state files and the patch, and if the state is older than the patch you refuse to load).
These problems could be solved if you have a unique identifier for the objects, probably automatically generated, but saved in the patch.
Anyhow, I understand that you need your interface for max-style preset, so I invite you to commit it to the CVS.
(If you do not agree with the CVS, please tell us so, there was an unanswered mail by hc. about this topic. We can not read your mind, and your opinion is important)
Guenter
Krzysztof
guenter geiger wrote: ...
It is a good thing to have an official API for saving state. In the case of state the API doesn't really help
why is it so, btw?
guenter geiger wrote: ...
symbolic ids, once these are available.
But how are you adding a symbolic id to an object outside of pd ?
sure, I meant ``once these are available inside of the pd''. The plan is incremental -- lets have the easy part first, then add more features.
...
Without knowing Miller's opinion, we are probably wasting our time, though...
...
(If you do not agree with the CVS, please tell us so, there was
I fully agree with cvs for experimenting and testing. But in the end, both design, and code, will need Miller's acceptance.
Krzysztof
On Wed, 3 Dec 2003, Krzysztof Czaja wrote:
But how are you adding a symbolic id to an object outside of pd ?
sure, I meant ``once these are available inside of the pd''. The plan is incremental -- lets have the easy part first, then add more features.
ah, yes, I see, right ... misunderstood ..
...
Without knowing Miller's opinion, we are probably wasting our time, though...
...
(If you do not agree with the CVS, please tell us so, there was
I fully agree with cvs for experimenting and testing. But in the end, both design, and code, will need Miller's acceptance.
Right, I am trying to formulate my approach in design and code too.
Guenter
Krzysztof
PD-dev mailing list PD-dev@iem.at http://iem.at/cgi-bin/mailman/listinfo/pd-dev
Yep, and I'm sorry not to be taking part in this discussion! I don't have enought time right now to think clearly about this (which will probably take a few hours...)
cheers Miller
On Wed, Dec 03, 2003 at 12:33:38PM +0100, Krzysztof Czaja wrote:
guenter geiger wrote: ...
symbolic ids, once these are available.
But how are you adding a symbolic id to an object outside of pd ?
sure, I meant ``once these are available inside of the pd''. The plan is incremental -- lets have the easy part first, then add more features.
...
Without knowing Miller's opinion, we are probably wasting our time, though...
...
(If you do not agree with the CVS, please tell us so, there was
I fully agree with cvs for experimenting and testing. But in the end, both design, and code, will need Miller's acceptance.
Krzysztof
PD-dev mailing list PD-dev@iem.at http://iem.at/cgi-bin/mailman/listinfo/pd-dev