[PD-cvs] SF.net SVN: pure-data:[10209] trunk/externals/iem/iemguts/src/oreceive.c

zmoelnig at users.sourceforge.net zmoelnig at users.sourceforge.net
Wed Jul 23 12:16:02 CEST 2008


Revision: 10209
          http://pure-data.svn.sourceforge.net/pure-data/?rev=10209&view=rev
Author:   zmoelnig
Date:     2008-07-23 10:16:01 +0000 (Wed, 23 Jul 2008)

Log Message:
-----------
ordered receive: this is similar as [gemhead] priorities
but more general

Added Paths:
-----------
    trunk/externals/iem/iemguts/src/oreceive.c

Added: trunk/externals/iem/iemguts/src/oreceive.c
===================================================================
--- trunk/externals/iem/iemguts/src/oreceive.c	                        (rev 0)
+++ trunk/externals/iem/iemguts/src/oreceive.c	2008-07-23 10:16:01 UTC (rev 10209)
@@ -0,0 +1,272 @@
+
+#include "m_pd.h"
+
+#if 0
+# define debug_post post
+#else
+# define debug_post
+#endif
+
+static t_class *oreceive_class, *oreceive_proxy_class, *oreceive_guts_class;
+
+
+/* ------------------------------------------------------------- */
+/* there come the guts: our own bind/unbind mechanism that
+ * includes priorities
+ *
+ * the plan is as follows:
+ *  [oreceive] tells us, which name it wants to bind to; 
+ *   it doesn't _really_ get bound to this name!
+ *
+ *  we have an invisible permanent object, that keeps track of 
+ *  sorted (by priority) lists of the [oreceive] objects
+ *
+ *  this object binds itself to the requested name
+ *  and when it gets called, it in turn calls all the [oreceive] objects
+ *
+ * that's it
+ */
+
+
+typedef struct _bind_element {
+  t_pd   *object;
+  t_float priority;
+  struct _bind_element*next;
+} t_bind_element;
+
+typedef struct _bind_list {
+  t_object p_obj;
+
+  t_symbol*key;
+  t_bind_element*elements;
+  struct _bind_list*next;
+} t_oreceive_proxy;
+
+static t_oreceive_proxy*priority_receiver=0;
+
+static t_oreceive_proxy*guts_find_key(t_symbol*key)
+{
+  t_oreceive_proxy*binding=0;
+
+  for(binding=priority_receiver; binding; binding=binding->next) {
+    if(binding->key == key)
+      return binding;
+  }
+  /* not found */
+  return 0;
+}
+
+
+static t_oreceive_proxy*guts_add_key(t_symbol*key)
+{
+  t_oreceive_proxy*bind_list=0;
+  bind_list=(t_oreceive_proxy*)pd_new(oreceive_proxy_class);
+  bind_list->key=key;
+  bind_list->elements=0;
+  bind_list->next=0;
+
+  debug_post("binding %x to %s", bind_list, key->s_name);
+  pd_bind(&bind_list->p_obj.ob_pd, key);
+
+  t_oreceive_proxy*last=priority_receiver;
+
+  if(last) {
+    while(last->next) {
+      last=last->next;
+    }
+    last->next = bind_list;
+  } else {
+    priority_receiver = bind_list;
+  }
+
+  return bind_list;
+}
+
+static void guts_add_element(t_oreceive_proxy*bind_list, t_bind_element*element)
+{
+  /* insert the object according to it's priority 
+   * this is already the right queue
+   */
+  t_float priority=element->priority;
+  t_bind_element*elements=bind_list->elements, *last=0;
+  debug_post("priority insert of %x:%g", element, priority);
+
+  if(!elements || elements->priority >= priority) {
+    bind_list->elements = element;
+    element->next = elements;
+    debug_post("inserting in the beginngin");
+    return;
+  }
+
+
+  debug_post("trying %x:%g", elements, elements->priority);
+  while(elements && elements->priority < priority) {
+    debug_post("skipping %x:%g to %x", elements, elements->priority, elements->next);
+    last=elements;
+    elements=elements->next;
+  }
+
+  debug_post("inserting after %x:%g", last,     (last    ?    (last->priority):0));
+  debug_post("inserting befor %x:%g", elements, (elements?(elements->priority):0));
+
+  element->next=elements;    
+  if(last) {
+    last->next = element;
+  } else {
+    bug("\nlast object invalid when inserting prioritized receiver\n");
+  }
+}
+
+
+static void pd_bind_priority(t_pd*x, t_symbol*key, t_float priority) {
+  t_oreceive_proxy*bind_list=0;
+  t_bind_element*element=0;
+  debug_post("trying to bind '%s':%g via %x", key->s_name, priority, priority_receiver);
+
+  bind_list=guts_find_key(key);
+  if(!bind_list)
+    bind_list=guts_add_key(key);
+  if(!bind_list)return;
+
+  element=(t_bind_element*)getbytes(sizeof(t_bind_element));
+  element->object=x;
+  element->priority=priority;
+  element->next=0;
+
+  guts_add_element(bind_list, element);
+}
+
+
+static void pd_unbind_priority(t_pd*x, t_symbol*key) {
+  t_oreceive_proxy*list=0, *last=0;
+  t_bind_element*elements=0, *lastlmn=0;
+
+  debug_post("trying to unbind '%s' from %x", key->s_name, priority_receiver);
+
+  for(list=priority_receiver; list && list->key!=key; list=list->next){
+    last=list;
+  }
+  if(!list)return;
+
+  for(elements=list->elements; elements && elements->object != x; elements=elements->next) {
+    lastlmn=elements;
+  }
+
+  if(elements) {
+    /* found it, now remove it */
+    if(lastlmn) {
+      lastlmn->next=elements->next;
+    } else {
+      list->elements=elements->next;
+    }
+
+    elements->object=0;
+    elements->priority=0;
+    elements->next=0;
+
+    freebytes(elements, sizeof(elements));
+  } else {
+    // not here...
+  }
+
+  if(0==list->elements) {
+    // should we unbind ??
+    if(last) {
+      last->next=list->next;
+    } else {
+      priority_receiver=list->next;
+    }    
+
+    pd_unbind(&list->p_obj.ob_pd, list->key);
+    list->next=0;
+    list->key=0;
+
+    pd_free(&list->p_obj.ob_pd);
+  }
+}
+
+/* -------------------- oreceive ------------------------------ */
+
+typedef struct _oreceive
+{
+  t_object x_obj;
+  t_symbol *x_sym;
+  t_float   x_priority;
+
+  t_inlet*x_symin,*x_fltin;
+} t_oreceive;
+
+static void oreceive_anything(t_oreceive *x, t_symbol *s, int argc, t_atom *argv);
+
+static void oreceive_proxy_anything(t_oreceive_proxy*p, t_symbol*s, int argc, t_atom*argv)
+{
+  t_bind_element*elements=p->elements;
+
+  debug_post("proxy anything: %x", p);
+
+  while(elements) {
+    t_pd*o=elements->object;
+    elements=elements->next;
+    if(o) {
+      oreceive_anything((t_oreceive*)o, s, argc, argv);
+    }
+  }
+}
+
+/* ------------------------------------------------------------- */
+
+static void oreceive_anything(t_oreceive *x, t_symbol *s, int argc, t_atom *argv)
+{
+    outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
+}
+
+static void oreceive_priority(t_oreceive *x, t_float p)
+{
+  x->x_priority=p;
+  if(x->x_sym) {
+    pd_unbind_priority(&x->x_obj.ob_pd, x->x_sym);
+  }
+  pd_bind_priority(&x->x_obj.ob_pd, x->x_sym, x->x_priority);
+}
+
+static void oreceive_name(t_oreceive *x, t_symbol*s)
+{
+  if(x->x_sym) {
+    pd_unbind_priority(&x->x_obj.ob_pd, x->x_sym);
+  }
+  x->x_sym=s;
+  pd_bind_priority(&x->x_obj.ob_pd, x->x_sym, x->x_priority);
+}
+
+
+static void *oreceive_new(t_symbol *s, t_float priority)
+{
+    t_oreceive *x = (t_oreceive *)pd_new(oreceive_class);
+
+    x->x_symin = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_symbol, &s_symbol);
+    x->x_fltin = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, &s_float);
+
+    x->x_sym = s;
+    x->x_priority = priority;
+    pd_bind_priority(&x->x_obj.ob_pd, s, priority);
+    //    pd_bind(&x->x_obj.ob_pd, s);
+    outlet_new(&x->x_obj, 0);
+    return (x);
+}
+
+static void oreceive_free(t_oreceive *x)
+{
+    pd_unbind_priority(&x->x_obj.ob_pd, x->x_sym);
+}
+
+void oreceive_setup(void)
+{
+    oreceive_class = class_new(gensym("oreceive"), (t_newmethod)oreceive_new, 
+                               (t_method)oreceive_free, sizeof(t_oreceive), CLASS_NOINLET, A_DEFSYM, A_DEFFLOAT, 0);
+    class_addcreator((t_newmethod)oreceive_new, gensym("r"), A_DEFSYM, A_DEFFLOAT, 0);
+    class_addsymbol(oreceive_class, oreceive_name);
+    class_addmethod(oreceive_class, (t_method)oreceive_priority, &s_float, A_FLOAT, 0);
+
+    oreceive_proxy_class = class_new(0, 0, 0, sizeof(t_oreceive_proxy), CLASS_NOINLET | CLASS_PD, 0);
+    class_addanything(oreceive_proxy_class, oreceive_proxy_anything);
+}


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Pd-cvs mailing list