diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2004-10-27 18:19:51 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2004-10-27 18:19:51 +0000 |
commit | 1471f1a6b3cf6169c6aae49f2cef643bc3c3c872 (patch) | |
tree | 50ae6f3e94d60b611cfd9f6cdad98b7eed180645 /externals/grill/dyn/dyn_create.cpp | |
parent | 89ca5ec0c49ae8923a206668ef9284257c56a104 (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.cpp | 246 |
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 +} |