aboutsummaryrefslogtreecommitdiff
path: root/src/findbrokenobject.c
blob: 6087c1101366d48fcf37f05538e0c6a05bc032ca (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

/******************************************************
 *
 * findbrokenobject - 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 (or later)
 *
 ******************************************************/


/* 
 * find broken objects (objects that could not be created)
 * these objects are of class 'text_class'

 objsrc = pd_checkobject(&src->g_pd);
 if (objsrc && pd_class(&src->g_pd) == text_class && objsrc->te_type == T_OBJECT) {
   // 'src' is a broken object
 }
 */

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

#include <string.h>

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

/* ------------------------- findbrokenobject ---------------------------- */

static t_class *findbrokenobject_class;

typedef struct _findbrokenobject
{
  t_object  x_obj;
  t_outlet *x_out;
  t_canvas *x_parent;   // the canvas we are acting on
} t_findbrokenobject;

extern t_class *text_class;
extern t_class *canvas_class;

static void print_obj(const char*prefix, t_object *obj) {
  int ntxt;
  char *txt;
  t_binbuf*bb=obj->te_binbuf;
  binbuf_gettext(bb, &txt, &ntxt);
  pd_error(obj, "%s%p\t%s", prefix, obj, txt);
}

static void findbrokenobject_doit(t_canvas*cnv) {
  t_gobj*src;
  for (src = cnv->gl_list; src; src = src->g_next) { /* traverse all objects in canvas */
    t_object*obj=pd_checkobject(&src->g_pd);
    if (obj && (pd_class(&src->g_pd) == text_class && obj->te_type == T_OBJECT)) {
      // found broken object
      print_obj("broken:\t", obj);
    }
  }
}

static void fbo_iterate(t_canvas*x) {
  // iterate over all top-level canvases
  if(!(x && x->gl_name && x->gl_name->s_name))
    return;
  t_gobj*g=0;

  for(g=x->gl_list;g;g=g->g_next) {
    // iterate over all objects on the canvas
    t_object*ob=pd_checkobject(&g->g_pd);
    t_class*cls=0;

    if(!(ob && ob->te_type == T_OBJECT))
      continue;

    cls=pd_class(&g->g_pd);
    //const char*classname=cls->c_name->s_name;
    if (cls == canvas_class) {
      // this is just another abstraction, recurse into it
      fbo_iterate(ob);
    } else if (cls == text_class) {
      /* broken object */
      int ntxt;
      char *txt;
      t_binbuf*bb=ob->te_binbuf;
      binbuf_gettext(bb, &txt, &ntxt);
      pd_error(ob, "[%s] broken object!", txt);
      freebytes(txt, ntxt);
    }
  }
}

static void findbrokenobject_bang(t_findbrokenobject *x) {
  // find all broken objects in the current patch
  if(x->x_parent) {
    fbo_iterate(x->x_parent);
  } else {
    t_canvas *x;
    for (x = pd_getcanvaslist(); x; x = x->gl_next) {
      const char*name=x->gl_name->s_name;
      /* only allow names ending with '.pd'
       * (reject template canvases)
       */
      const int len=strlen(name);
      if(len>3 && name[len-3]=='.' && name[len-2]=='p' && name[len-1]=='d') {
	fbo_iterate(x);
      } //else post("canvas: %s", name);
    }
  }
}

static void findbrokenobject_free(t_findbrokenobject *x)
{
  outlet_free(x->x_out);
}

static void *findbrokenobject_new(t_symbol*s, int argc, t_atom*argv)
{
  t_findbrokenobject *x = (t_findbrokenobject *)pd_new(findbrokenobject_class);
  x->x_parent=0;
  if(argc==1 && argv->a_type == A_FLOAT) {
    int depth=atom_getint(argv);
    t_glist *glist=(t_glist *)canvas_getcurrent();
    if(depth>=0) {
      t_canvas *canvas=(t_canvas*)glist_getcanvas(glist);
      while(depth && canvas) {
	canvas=canvas->gl_owner;
	depth--;
      }
      if(canvas)
	x->x_parent = canvas;
    }
  }
  post("findbrokenobj @ %p", x->x_parent);

  x->x_out = outlet_new(&x->x_obj, &s_float);
  return (x);
}

static char fbo_file[];
static void fbo_persist(void) {
  static t_pd*fbo_canvas=0;
  if(fbo_canvas)
    return;
  
  
  t_binbuf *b = binbuf_new();
  glob_setfilename(0, gensym("_deken_workspace"), gensym("."));
  binbuf_text(b, fbo_file, strlen(fbo_file));
  binbuf_eval(b, &pd_canvasmaker, 0, 0);
  fbo_canvas = s__X.s_thing;
  vmess(s__X.s_thing, gensym("pop"), "i", 0);
  glob_setfilename(0, &s_, &s_);
  binbuf_free(b);  
}

void findbrokenobject_setup(void)
{
  findbrokenobject_class = class_new(gensym("findbrokenobject"), (t_newmethod)findbrokenobject_new,
				     (t_method)findbrokenobject_free, sizeof(t_findbrokenobject), 0, 
				     A_GIMME, 0);
  class_addbang  (findbrokenobject_class, (t_method)findbrokenobject_bang);
  fbo_persist();
}
static char fbo_file[] = "\
canvas 0 0 300 200;\n\
#X obj 20 20 receive __deken_findbroken_objects;\n\
#X obj 20 60 findbrokenobject;\n\
#X obj 20 80 list prepend plugin-dispatch deken;\n\
#X msg 20 40 unique;\n\
#X obj 20 100 list trim;\n\
#X obj 20 120 s pd;\n\
#X connect 0 0 3 0;\n\
#X connect 1 0 2 0;\n\
#X connect 2 0 4 0;\n\
#X connect 3 0 1 0;\n\
#X connect 4 0 5 0;\n\
";