aboutsummaryrefslogtreecommitdiff
path: root/src/canvasconnections.c
blob: cebd085ef69ddc0fa86493b1d33cd3f84bc043ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

/******************************************************
 *
 * canvasconnections - implementation file
 *
 * copyleft (c) IOhannes m zmölnig
 *
 *   2007:forum::für::umläute:2007
 *
 *   institute of electronic music and acoustics (iem)
 *
 ******************************************************
 *
 * license: GNU General Public License v.2
 *
 ******************************************************/


/* 
 * this object provides a way to send messages to upstream canvases
 * by default it sends messages to the containing canvas, but you can give the
 * "depth" as argument;
 * e.g. [canvasconnections 1] will send messages to the parent of the containing canvas
 */

#include "m_pd.h"
#include "g_canvas.h"
#include "m_imp.h"

int glist_getindex(t_glist *x, t_gobj *y);

/* ------------------------- canvasconnections ---------------------------- */

static t_class *canvasconnections_class;

typedef struct _canvasconnections
{
  t_object  x_obj;
  t_canvas  *x_parent;
  t_object  *x_object;
  t_outlet  *x_out;
} t_canvasconnections;

static void canvasconnections_outlets(t_canvasconnections *x)
{
  int noutlets=0;
  int nout=0;
  t_atom at;

  if(0==x->x_object || 0==x->x_parent)
    return;

  noutlets=obj_noutlets(x->x_object);
  SETFLOAT(&at, (t_float)noutlets);

  outlet_anything(x->x_out, gensym("outlets"), 1, &at);
  for(nout=0; nout<noutlets; nout++) {
    t_outlet*out=0;
    t_outconnect*conn=obj_starttraverseoutlet(x->x_object, &out, nout);
    t_object*dest=0;
    t_inlet*in=0;
    int which=0;
    int count=0, i=0;
    t_atom*abuf=0;
    while(conn) {
      conn=obj_nexttraverseoutlet(conn, &dest, &in, &which);
      count++;
    }
    abuf=(t_atom*)getbytes(sizeof(t_atom)*(count+1));
    SETFLOAT(abuf, nout);
    conn=obj_starttraverseoutlet(x->x_object, &out, nout);
    while(conn) {
      t_float connid=0;
      conn=obj_nexttraverseoutlet(conn, &dest, &in, &which);
      connid = glist_getindex(x->x_parent, (t_gobj*)dest);
      SETFLOAT(abuf+1+i, connid);
      i++;
    }
    outlet_anything(x->x_out, gensym("outlet"), count+1, abuf);
    freebytes(abuf, sizeof(t_atom)*(count+1));
  }
}

static void canvasconnections_bang(t_canvasconnections *x)
{
  canvasconnections_outlets(x);
}


static void canvasconnections_free(t_canvasconnections *x)
{
  x->x_object=0;
  outlet_free(x->x_out);
  x->x_out=0;
}

static void *canvasconnections_new(t_floatarg f)
{
  t_canvasconnections *x = (t_canvasconnections *)pd_new(canvasconnections_class);
  t_glist *glist=(t_glist *)canvas_getcurrent();
  t_canvas *canvas=(t_canvas*)glist_getcanvas(glist);
  int depth=(int)f;
  if(depth<0)depth=0;

  x->x_parent=0;
  x->x_object=0;

  while(depth && canvas) {
    canvas=canvas->gl_owner;
    depth--;
  }

  if(canvas) {
    x->x_object = pd_checkobject((t_pd*)canvas);
    x->x_parent = canvas->gl_owner;
  }

  x->x_out=outlet_new(&x->x_obj, 0);

  return (x);
}

void canvasconnections_setup(void)
{
  canvasconnections_class = class_new(gensym("canvasconnections"), 
                                      (t_newmethod)canvasconnections_new, (t_method)canvasconnections_free, 
                                      sizeof(t_canvasconnections), 0, 
                                      A_DEFFLOAT, 0);
  class_addbang(canvasconnections_class, (t_method)canvasconnections_bang);
}