aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/dyn/dyn_create.cpp
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2004-10-27 18:19:51 +0000
committerThomas Grill <xovo@users.sourceforge.net>2004-10-27 18:19:51 +0000
commit1471f1a6b3cf6169c6aae49f2cef643bc3c3c872 (patch)
tree50ae6f3e94d60b611cfd9f6cdad98b7eed180645 /externals/grill/dyn/dyn_create.cpp
parent89ca5ec0c49ae8923a206668ef9284257c56a104 (diff)
fixes for dsp and abstraction inlets
a few fixes dyn documentation more functionality only one dyn_id type for clarity better interface for listeners dyn_Finish instead of dyn_Flush all the major things are working in dyn! OSX checkin name changes for svn repository small fixes doesn't really work, but should compile dyn python module checkin now able to have real root patchers initial coding a few more things deleted test/mar patches (moved to /doc branch) dyn SWIG module dyn additions a _few_ changes in UIUI, establishing node groups made API headers monolithic first working dyn! updated todo list svn path=/trunk/; revision=2173
Diffstat (limited to 'externals/grill/dyn/dyn_create.cpp')
-rw-r--r--externals/grill/dyn/dyn_create.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/externals/grill/dyn/dyn_create.cpp b/externals/grill/dyn/dyn_create.cpp
new file mode 100644
index 00000000..b53ed89a
--- /dev/null
+++ b/externals/grill/dyn/dyn_create.cpp
@@ -0,0 +1,246 @@
+/*
+dyn - dynamical object management
+
+Copyright (c)2003-2004 Thomas Grill (gr@grrrr.org)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+*/
+
+#include "dyn_proto.h"
+#include <list>
+
+static const t_symbol *k_obj = gensym("obj");
+static const t_symbol *k_msg = gensym("msg");
+static const t_symbol *k_text = gensym("text");
+
+static const t_symbol *sym_vis = gensym("vis");
+static const t_symbol *sym_loadbang = gensym("loadbang");
+static const t_symbol *sym_pd = gensym("pd");
+static const t_symbol *sym_dsp = gensym("dsp");
+
+static const t_symbol *sym_dyn = gensym("dyn");
+static const t_symbol *sym_dot = gensym(".");
+
+
+static t_gobj *getlast(t_glist *gl)
+{
+ t_gobj *go = gl->gl_list;
+ if(go)
+ while(go->g_next) go = go->g_next;
+ return go;
+}
+
+
+void *NewPDObject(int type,t_glist *glist,const t_symbol *hdr,int _argc_,const t_atom *_argv_)
+{
+// sys_lock();
+
+ const t_symbol *kind;
+ switch(type) {
+ case DYN_TYPE_PATCHER:
+ hdr = sym_pd;
+ // fall through
+ case DYN_TYPE_OBJECT:
+ kind = k_obj;
+ break;
+ case DYN_TYPE_MESSAGE:
+ kind = k_msg;
+ ASSERT(hdr == NULL);
+ break;
+ case DYN_TYPE_TEXT:
+ kind = k_text;
+ ASSERT(hdr == NULL);
+ break;
+ }
+
+ void *newest = NULL;
+ t_gobj *last = NULL;
+
+ if(type == DYN_TYPE_PATCHER && !glist) {
+ /*
+ For a dyn root canvas we can not simply put a [pd] into canvas_getcurrent
+ because the [pd] would be visible in this canvas then.
+
+ On the other hand, we can also not simply create a new canvas with
+ canvas_getcurrent active because it would not be on the list of root dsp canvases
+ then.
+
+ Hence, we have to pop all current canvases to be at the root, create our canvas
+ to be a real root canvas and then push back all the canvases.
+ */
+
+ /*
+ remember current directory -
+ abstractions residing in the directory of the current canvas
+ (which normally is the one hosting dyn) will be found
+ */
+ t_symbol *dir;
+ if(canvas_getcurrent()) dir = canvas_getcurrentdir();
+ else dir = const_cast<t_symbol *>(sym_dot);
+
+ // pop current canvases
+ std::list<t_glist *> glstack;
+ for(;;) {
+ t_glist *gl = canvas_getcurrent();
+ if(!gl) break;
+ glstack.push_front(gl);
+ canvas_unsetcurrent(gl);
+ }
+
+ // set canvas environment
+ // this must be done manually if there is no owner
+ glob_setfilename(NULL,const_cast<t_symbol *>(sym_dyn),dir);
+
+ t_atom arg[6];
+ SETFLOAT(arg+0,0); // xpos
+ SETFLOAT(arg+1,0); // ypos
+ SETFLOAT(arg+2,1000); // xwidth
+ SETFLOAT(arg+3,1000); // xwidth
+ SETSYMBOL(arg+4,const_cast<t_symbol *>(sym_dyncanvas)); // canvas name
+ SETFLOAT(arg+5,0); // invisible
+
+ t_glist *canvas = canvas_new(NULL,NULL,6,arg);
+ /* or, alternatively - but this needs some message processing
+ pd_typedmess(&pd_canvasmaker,gensym("canvas"),6,arg);
+ t_glist *canvas = canvas_getcurrent();
+ */
+
+ // must do that....
+ canvas_unsetcurrent(canvas);
+
+ // push back all the canvases
+ for(std::list<t_glist *>::iterator it = glstack.begin(); it != glstack.end(); ++it)
+ canvas_setcurrent(*it);
+
+ // clear environment
+ glob_setfilename(NULL,&s_,&s_);
+
+ newest = canvas;
+ }
+ else {
+ ASSERT(glist);
+
+ int argc = _argc_+(hdr?3:2);
+ t_atom *argv = new t_atom[argc];
+
+ // position x/y = 0/0
+ t_atom *a = argv;
+ SETFLOAT(a,0); a++;
+ SETFLOAT(a,0); a++;
+ if(hdr) { SETSYMBOL(a,const_cast<t_symbol *>(hdr)); a++; }
+ memcpy(a,_argv_,_argc_*sizeof(t_atom));
+
+ last = getlast(glist);
+
+ // set selected canvas as current
+ pd_typedmess((t_pd *)glist,(t_symbol *)kind,argc,argv);
+// canvas_obj(glist,(t_symbol *)kind,argc,argv);
+ newest = getlast(glist);
+
+ delete[] argv;
+ }
+
+ if(kind == k_obj && glist) {
+ // check for created objects and abstractions
+
+ t_object *o = (t_object *)pd_newest();
+
+ if(!o) {
+ // PD creates a text object when the intended object could not be created
+ t_gobj *trash = getlast(glist);
+
+ // Test for newly created object....
+ if(trash && last != trash) {
+ // Delete it!
+ glist_delete(glist,trash);
+ }
+ newest = NULL;
+ }
+ else
+ newest = &o->te_g;
+ }
+
+ // look for latest created object
+ if(newest) {
+// if(glist) canvas_setcurrent(glist);
+
+ // send loadbang (if it is an abstraction)
+ if(pd_class(&((t_gobj *)newest)->g_pd) == canvas_class) {
+ // hide the sub-canvas
+ pd_vmess((t_pd *)newest,const_cast<t_symbol *>(sym_vis),"i",0);
+
+ // loadbang the abstraction
+ pd_vmess((t_pd *)newest,const_cast<t_symbol *>(sym_loadbang),"");
+ }
+
+ // restart dsp - that's necessary because ToCanvas is called manually
+ canvas_update_dsp();
+
+ // pop the current canvas
+// if(glist) canvas_unsetcurrent(glist);
+ }
+
+// sys_unlock();
+
+ return newest;
+}
+
+dyn_patcher *root = NULL;
+
+dyn_ident *NewObject(int type,dyn_callback cb,dyn_ident *owner,const t_symbol *hdr,int argc,const t_atom *argv)
+{
+ int err = DYN_ERROR_NONE;
+ dyn_ident *ret = NULL;
+
+ dyn_patcher *p;
+ if(owner == DYN_ID_NONE) {
+ if(!root) {
+ void *newobj = NewPDObject(DYN_TYPE_PATCHER,NULL,NULL);
+ dyn_ident *id = new dyn_ident(DYN_TYPE_PATCHER,NULL);
+ root = new dyn_patcher(id,NULL,(t_glist *)newobj);
+ }
+ p = root;
+ }
+ else
+ p = owner->Patcher();
+
+ if(p) {
+ void *newobj = NewPDObject(type,p->glist(),hdr,argc,argv);
+ if(newobj) {
+ ret = new dyn_ident(type,cb);
+
+ switch(type) {
+ case DYN_TYPE_PATCHER:
+ ret->Set(new dyn_patcher(ret,p,(t_glist *)newobj));
+ break;
+ case DYN_TYPE_OBJECT:
+ ret->Set(new dyn_object(ret,p,(t_gobj *)newobj));
+ break;
+ case DYN_TYPE_MESSAGE:
+ ret->Set(new dyn_message(ret,p,(t_gobj *)newobj));
+ break;
+ case DYN_TYPE_TEXT:
+ ret->Set(new dyn_text(ret,p,(t_gobj *)newobj));
+ break;
+ }
+ }
+ else
+ err = DYN_ERROR_NOTCREATED;
+ }
+ else
+ err = DYN_ERROR_NOSUB;
+
+ if(err != DYN_ERROR_NONE) {
+ if(ret) delete ret;
+ throw err;
+ }
+ else
+ return ret;
+}
+
+void DelObject(dyn_ident *obj)
+{
+ ASSERT(obj);
+ if(obj->data) Destroy(obj->data); // delete database object
+ delete obj; // delete ID
+}