"README.md" did not exist on "58bfd19302e81a3c8262f94672212e191d1842a9"
Newer
Older
/* Copyright (c) 1997-1999 Miller Puckette.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* This file defines Text objects which traverse data contained in scalars
and arrays:
pointer - point to an object belonging to a template
get - get numeric fields
set - change numeric fields
element - get an array element
getsize - get the size of an array
setsize - change the size of an array
append - add an element to a list
sublist - get a pointer into a list which is an element of another scalar
field - get numeric/symbolic field while within a canvas field
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
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h> /* for read/write to files */
#include "m_pd.h"
#include "g_canvas.h"
/* ------------- gstubs and gpointers - safe pointing --------------- */
/* create a gstub which is "owned" by a glist (gl) or an array ("a"). */
t_gstub *gstub_new(t_glist *gl, t_array *a)
{
t_gstub *gs = t_getbytes(sizeof(*gs));
if (gl)
{
gs->gs_which = GP_GLIST;
gs->gs_un.gs_glist = gl;
}
else
{
gs->gs_which = GP_ARRAY;
gs->gs_un.gs_array = a;
}
gs->gs_refcount = 0;
return (gs);
}
/* when a "gpointer" is set to point to this stub (so we can later chase
down the owner) we increase a reference count. The following routine is called
whenever a gpointer is unset from pointing here. If the owner is
gone and the refcount goes to zero, we can free the gstub safely. */
static void gstub_dis(t_gstub *gs)
{
int refcount = --gs->gs_refcount;
if ((!refcount) && gs->gs_which == GP_NONE)
t_freebytes(gs, sizeof (*gs));
else if (refcount < 0) bug("gstub_dis");
}
/* this routing is called by the owner to inform the gstub that it is
being deleted. If no gpointers are pointing here, we can free the gstub;
otherwise we wait for the last gstub_dis() to free it. */
void gstub_cutoff(t_gstub *gs)
{
gs->gs_which = GP_NONE;
if (gs->gs_refcount < 0) bug("gstub_cutoff");
if (!gs->gs_refcount) t_freebytes(gs, sizeof (*gs));
}
int gpointer_docheck(const t_gpointer *gp, int headok, int gobjok)
{
t_gstub *gs = gp->gp_stub;
if (!gs) return (0);
if (gs->gs_which == GP_ARRAY)
{
if (gs->gs_un.gs_array->a_valid != gp->gp_valid) return (0);
else return (1);
}
else if (gs->gs_which == GP_GLIST)
{
if (!headok && !((t_scalar *)(gp->gp_un.gp_gobj)))
return (0);
else if (!gobjok && gp->gp_un.gp_gobj &&
pd_class(&gp->gp_un.gp_gobj->g_pd) != scalar_class)
return (0);
else if (gs->gs_un.gs_glist->gl_valid != gp->gp_valid)
return (0);
else
return (1);
/* call this to verify that a pointer is fresh, i.e., that it either
points to real data or to the head of a list, and that in either case
the object hasn't disappeared since this pointer was generated.
Unless "headok" is set, the routine also fails for the head of a list.*/
int gpointer_check(const t_gpointer *gp, int headok)
{
return (gpointer_docheck(gp, headok, 0));
}
/* more general form for checking for pointers to gobjs */
int gpointer_check_gobj(const t_gpointer *gp)
{
return (gpointer_docheck(gp, 0, 1));
}
/* get the template for the object pointer to. Assumes we've already checked
freshness. Returns 0 if head of list. */
static t_symbol *gpointer_gettemplatesym(const t_gpointer *gp)
{
t_gstub *gs = gp->gp_stub;
if (gs->gs_which == GP_GLIST)
{
t_scalar *sc = (t_scalar *)(gp->gp_un.gp_gobj);
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
if (sc)
return (sc->sc_template);
else return (0);
}
else
{
t_array *a = gs->gs_un.gs_array;
return (a->a_templatesym);
}
}
/* copy a pointer to another, assuming the second one hasn't yet been
initialized. New gpointers should be initialized either by this
routine or by gpointer_init below. */
void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto)
{
*gpto = *gpfrom;
if (gpto->gp_stub)
gpto->gp_stub->gs_refcount++;
else bug("gpointer_copy");
}
/* clear a gpointer that was previously set, releasing the associted
gstub if this was the last reference to it. */
void gpointer_unset(t_gpointer *gp)
{
t_gstub *gs;
if (gs = gp->gp_stub)
{
gstub_dis(gs);
gp->gp_stub = 0;
}
}
void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_gobj *x)
{
t_gstub *gs;
if (gs = gp->gp_stub) gstub_dis(gs);
gp->gp_stub = gs = glist->gl_stub;
gp->gp_valid = glist->gl_valid;
gp->gp_un.gp_gobj = x;
gs->gs_refcount++;
}
void gpointer_setarray(t_gpointer *gp, t_array *array, t_word *w)
{
t_gstub *gs;
if (gs = gp->gp_stub) gstub_dis(gs);
gp->gp_stub = gs = array->a_stub;
gp->gp_valid = array->a_valid;
gp->gp_un.gp_w = w;
gs->gs_refcount++;
}
void gpointer_init(t_gpointer *gp)
{
gp->gp_stub = 0;
gp->gp_valid = 0;
gp->gp_un.gp_gobj = 0;
/* templates are named using the name-bashing by which canvases bind
thenselves, with a leading "pd-". LATER see if we can have templates
occupy their real names. Meanwhile, if a template has an empty name
or is named "-" (as when passed as a "-" argument to "get", etc.), just
return &s_; objects should check for this and allow it as a wild
card when appropriate. */
static t_symbol *template_getbindsym(t_symbol *s)
{
if (!*s->s_name || !strcmp(s->s_name, "-"))
return (&s_);
else return (canvas_makebindsym(s));
}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* ---------------------- pointers ----------------------------- */
static t_class *ptrobj_class;
typedef struct
{
t_symbol *to_type;
t_outlet *to_outlet;
} t_typedout;
typedef struct _ptrobj
{
t_object x_obj;
t_gpointer x_gp;
t_typedout *x_typedout;
int x_ntypedout;
t_outlet *x_otherout;
t_outlet *x_bangout;
} t_ptrobj;
static void *ptrobj_new(t_symbol *classname, int argc, t_atom *argv)
{
t_ptrobj *x = (t_ptrobj *)pd_new(ptrobj_class);
t_typedout *to;
int n;
gpointer_init(&x->x_gp);
x->x_typedout = to = (t_typedout *)getbytes(argc * sizeof (*to));
x->x_ntypedout = n = argc;
for (; n--; to++)
{
to->to_outlet = outlet_new(&x->x_obj, &s_pointer);
to->to_type = template_getbindsym(atom_getsymbol(argv++));
}
x->x_otherout = outlet_new(&x->x_obj, &s_pointer);
x->x_bangout = outlet_new(&x->x_obj, &s_bang);
pointerinlet_new(&x->x_obj, &x->x_gp);
return (x);
}
static void ptrobj_traverse(t_ptrobj *x, t_symbol *s)
{
t_glist *glist = (t_glist *)pd_findbyclass(s, canvas_class);
if (glist) gpointer_setglist(&x->x_gp, glist, 0);
else pd_error(x, "pointer: list '%s' not found", s->s_name);
}
static void ptrobj_vnext(t_ptrobj *x, t_float f)
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
{
t_gobj *gobj;
t_gpointer *gp = &x->x_gp;
t_gstub *gs = gp->gp_stub;
t_glist *glist;
int wantselected = (f != 0);
if (!gs)
{
pd_error(x, "ptrobj_next: no current pointer");
return;
}
if (gs->gs_which != GP_GLIST)
{
pd_error(x, "ptrobj_next: lists only, not arrays");
return;
}
glist = gs->gs_un.gs_glist;
if (glist->gl_valid != gp->gp_valid)
{
pd_error(x, "ptrobj_next: stale pointer");
return;
}
if (wantselected && !glist_isvisible(glist))
{
pd_error(x,
"ptrobj_vnext: next-selected only works for a visible window");
return;
}
gobj = gp->gp_un.gp_gobj;
if (!gobj) gobj = glist->gl_list;
else gobj = gobj->g_next;
while (gobj && ((pd_class(&gobj->g_pd) != scalar_class) ||
(wantselected && !glist_isselected(glist, gobj))))
gobj = gobj->g_next;
if (gobj)
{
t_typedout *to;
int n;
t_scalar *sc = (t_scalar *)gobj;
t_symbol *templatesym = sc->sc_template;
gp->gp_un.gp_gobj = &sc->sc_gobj;
for (n = x->x_ntypedout, to = x->x_typedout; n--; to++)
{
if (to->to_type == templatesym)
{
outlet_pointer(to->to_outlet, &x->x_gp);
return;
}
}
outlet_pointer(x->x_otherout, &x->x_gp);
}
else
{
gpointer_unset(gp);
outlet_bang(x->x_bangout);
}
}
static void ptrobj_next(t_ptrobj *x)
{
ptrobj_vnext(x, 0);
}
/* send a message to the window containing the object pointed to */
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
static void ptrobj_sendwindow(t_ptrobj *x, t_symbol *s, int argc, t_atom *argv)
{
t_glist *glist;
t_pd *canvas;
t_gstub *gs;
if (!gpointer_check(&x->x_gp, 1))
{
pd_error(x, "ptrobj_bang: empty pointer");
return;
}
gs = x->x_gp.gp_stub;
if (gs->gs_which == GP_GLIST)
glist = gs->gs_un.gs_glist;
else
{
t_array *owner_array = gs->gs_un.gs_array;
while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY)
owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array;
glist = owner_array->a_gp.gp_stub->gs_un.gs_glist;
}
canvas = (t_pd *)glist_getcanvas(glist);
if (argc && argv->a_type == A_SYMBOL)
pd_typedmess(canvas, argv->a_w.w_symbol, argc-1, argv+1);
else pd_error(x, "send-window: no message?");
}
/* send the pointer to the named object */
static void ptrobj_send(t_ptrobj *x, t_symbol *s)
{
if (!s->s_thing)
pd_error(x, "%s: no such object", s->s_name);
else if (!gpointer_check(&x->x_gp, 1))
pd_error(x, "pointer_send: empty pointer");
else pd_pointer(s->s_thing, &x->x_gp);
}
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
static void ptrobj_bang(t_ptrobj *x)
{
t_symbol *templatesym;
int n;
t_typedout *to;
if (!gpointer_check(&x->x_gp, 1))
{
pd_error(x, "ptrobj_bang: empty pointer");
return;
}
templatesym = gpointer_gettemplatesym(&x->x_gp);
for (n = x->x_ntypedout, to = x->x_typedout; n--; to++)
{
if (to->to_type == templatesym)
{
outlet_pointer(to->to_outlet, &x->x_gp);
return;
}
}
outlet_pointer(x->x_otherout, &x->x_gp);
}
static void ptrobj_pointer(t_ptrobj *x, t_gpointer *gp)
{
gpointer_unset(&x->x_gp);
gpointer_copy(gp, &x->x_gp);
ptrobj_bang(x);
}
static void ptrobj_rewind(t_ptrobj *x)
{
t_glist *glist;
t_gstub *gs;
if (!gpointer_check(&x->x_gp, 1))
{
pd_error(x, "pointer_rewind: empty pointer");
return;
}
gs = x->x_gp.gp_stub;
if (gs->gs_which != GP_GLIST)
{
pd_error(x, "pointer_rewind: sorry, unavailable for arrays");
return;
}
glist = gs->gs_un.gs_glist;
gpointer_setglist(&x->x_gp, glist, 0);
ptrobj_bang(x);
}
static void ptrobj_free(t_ptrobj *x)
{
freebytes(x->x_typedout, x->x_ntypedout * sizeof (*x->x_typedout));
gpointer_unset(&x->x_gp);
}
static void ptrobj_setup(void)
{
ptrobj_class = class_new(gensym("pointer"), (t_newmethod)ptrobj_new,
(t_method)ptrobj_free, sizeof(t_ptrobj), 0, A_GIMME, 0);
class_addmethod(ptrobj_class, (t_method)ptrobj_next, gensym("next"), 0);
class_addmethod(ptrobj_class, (t_method)ptrobj_send, gensym("send"),
A_SYMBOL, 0);
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
class_addmethod(ptrobj_class, (t_method)ptrobj_traverse, gensym("traverse"),
A_SYMBOL, 0);
class_addmethod(ptrobj_class, (t_method)ptrobj_vnext, gensym("vnext"),
A_DEFFLOAT, 0);
class_addmethod(ptrobj_class, (t_method)ptrobj_sendwindow,
gensym("send-window"), A_GIMME, 0);
class_addmethod(ptrobj_class, (t_method)ptrobj_rewind,
gensym("rewind"), 0);
class_addpointer(ptrobj_class, ptrobj_pointer);
class_addbang(ptrobj_class, ptrobj_bang);
}
/* ---------------------- get ----------------------------- */
static t_class *get_class;
typedef struct _getvariable
{
t_symbol *gv_sym;
t_outlet *gv_outlet;
} t_getvariable;
typedef struct _get
{
t_object x_obj;
t_symbol *x_templatesym;
int x_nout;
t_getvariable *x_variables;
} t_get;
static void *get_new(t_symbol *why, int argc, t_atom *argv)
{
t_get *x = (t_get *)pd_new(get_class);
int varcount, i;
t_atom at, *varvec;
x->x_templatesym = canvas_makebindsym(atom_getsymbolarg(0, argc, argv));
if (argc < 2) /* have at least one outlet */
{
varcount = 1;
varvec = &at;
SETSYMBOL(&at, &s_); /* set field to empty symbol */
}
else varcount = argc - 1, varvec = argv + 1;
= (t_getvariable *)getbytes(varcount * sizeof (*x->x_variables));
x->x_nout = varcount;
for (i = 0, sp = x->x_variables; i < varcount; i++, sp++)
sp->gv_sym = atom_getsymbolarg(i, varcount, varvec);
sp->gv_outlet = outlet_new(&x->x_obj, 0);
/* LATER connect with the template and set the outlet's type
correctly. We can't yet guarantee that the template is there
before we hit this routine. */
}
return (x);
}
static void get_set(t_get *x, t_symbol *templatesym, t_symbol *field)
{
if (x->x_nout != 1)
pd_error(x, "get: cannot set multiple fields.");
else
{
x->x_templatesym = template_getbindsym(templatesym);
x->x_variables->gv_sym = field;
}
}
static void get_pointer(t_get *x, t_gpointer *gp)
{
int nitems = x->x_nout, i;
t_symbol *templatesym;
t_template *template;
t_word *vec;
if (!gpointer_check(gp, 0))
pd_error(x, "get: stale or empty pointer");
if (*x->x_templatesym->s_name)
if ((templatesym = x->x_templatesym) != gpointer_gettemplatesym(gp))
{
pd_error(x, "get %s: got wrong template (%s)",
templatesym->s_name, gpointer_gettemplatesym(gp)->s_name);
return;
}
}
else templatesym = gpointer_gettemplatesym(gp);
if (!(template = template_findbyname(templatesym)))
{
pd_error(x, "get: couldn't find template %s", templatesym->s_name);
return;
}
if (gs->gs_which == GP_ARRAY) vec = gp->gp_un.gp_w;
else vec = ((t_scalar *)(gp->gp_un.gp_gobj))->sc_vec;
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
for (i = nitems - 1, vp = x->x_variables + i; i >= 0; i--, vp--)
{
int onset, type;
t_symbol *arraytype;
if (template_find_field(template, vp->gv_sym, &onset, &type, &arraytype))
{
if (type == DT_FLOAT)
outlet_float(vp->gv_outlet,
*(t_float *)(((char *)vec) + onset));
else if (type == DT_SYMBOL)
outlet_symbol(vp->gv_outlet,
*(t_symbol **)(((char *)vec) + onset));
else pd_error(x, "get: %s.%s is not a number or symbol",
template->t_sym->s_name, vp->gv_sym->s_name);
}
else pd_error(x, "get: %s.%s: no such field",
template->t_sym->s_name, vp->gv_sym->s_name);
}
}
static void get_free(t_get *x)
{
freebytes(x->x_variables, x->x_nout * sizeof (*x->x_variables));
}
static void get_setup(void)
{
get_class = class_new(gensym("get"), (t_newmethod)get_new,
(t_method)get_free, sizeof(t_get), 0, A_GIMME, 0);
class_addpointer(get_class, get_pointer);
class_addmethod(get_class, (t_method)get_set, gensym("set"),
A_SYMBOL, A_SYMBOL, 0);
}
/* ---------------------- set ----------------------------- */
static t_class *set_class;
typedef struct _setvariable
{
t_symbol *gv_sym;
union word gv_w;
} t_setvariable;
typedef struct _set
{
t_object x_obj;
t_gpointer x_gp;
t_symbol *x_templatesym;
int x_nin;
int x_issymbol;
t_setvariable *x_variables;
} t_set;
static void *set_new(t_symbol *why, int argc, t_atom *argv)
{
t_set *x = (t_set *)pd_new(set_class);
int i, varcount;
t_atom at, *varvec;
if (argc && (argv[0].a_type == A_SYMBOL) &&
!strcmp(argv[0].a_w.w_symbol->s_name, "-symbol"))
{
x->x_issymbol = 1;
argc--;
argv++;
}
else x->x_issymbol = 0;
x->x_templatesym = template_getbindsym(atom_getsymbolarg(0, argc, argv));
if (argc < 2)
{
varcount = 1;
varvec = &at;
SETSYMBOL(&at, &s_);
}
else varcount = argc - 1, varvec = argv + 1;
= (t_setvariable *)getbytes(varcount * sizeof (*x->x_variables));
x->x_nin = varcount;
for (i = 0, sp = x->x_variables; i < varcount; i++, sp++)
sp->gv_sym = atom_getsymbolarg(i, varcount, varvec);
if (x->x_issymbol)
sp->gv_w.w_symbol = &s_;
else sp->gv_w.w_float = 0;
if (i)
{
symbolinlet_new(&x->x_obj, &sp->gv_w.w_symbol);
else floatinlet_new(&x->x_obj, &sp->gv_w.w_float);
}
}
pointerinlet_new(&x->x_obj, &x->x_gp);
gpointer_init(&x->x_gp);
return (x);
}
static void set_set(t_set *x, t_symbol *templatesym, t_symbol *field)
{
if (x->x_nin != 1)
pd_error(x, "set: cannot set multiple fields.");
else
{
x->x_templatesym = template_getbindsym(templatesym);
x->x_variables->gv_sym = field;
if (x->x_issymbol)
x->x_variables->gv_w.w_symbol = &s_;
else
x->x_variables->gv_w.w_float = 0;
}
}
extern void scalar_configure(t_scalar *x, t_glist *owner);
static void set_bang(t_set *x)
{
int nitems = x->x_nin, i;
t_symbol *templatesym;
t_template *template;
t_setvariable *vp;
t_gpointer *gp = &x->x_gp;
t_gstub *gs = gp->gp_stub;
t_word *vec;
if (!gpointer_check(gp, 0))
{
pd_error(x, "set: empty pointer");
return;
}
if (*x->x_templatesym->s_name)
{
if ((templatesym = x->x_templatesym) != gpointer_gettemplatesym(gp))
{
pd_error(x, "set %s: got wrong template (%s)",
templatesym->s_name, gpointer_gettemplatesym(gp)->s_name);
return;
}
}
else templatesym = gpointer_gettemplatesym(gp);
if (!(template = template_findbyname(templatesym)))
pd_error(x, "set: couldn't find template %s", templatesym->s_name);
return;
}
if (!nitems)
return;
if (gs->gs_which == GP_ARRAY)
vec = gp->gp_un.gp_w;
else vec = ((t_scalar *)(gp->gp_un.gp_gobj))->sc_vec;
if (x->x_issymbol)
for (i = 0, vp = x->x_variables; i < nitems; i++, vp++)
template_setsymbol(template, vp->gv_sym, vec, vp->gv_w.w_symbol, 1);
else for (i = 0, vp = x->x_variables; i < nitems; i++, vp++)
template_setfloat(template, vp->gv_sym, vec, vp->gv_w.w_float, 1);
if (gs->gs_which == GP_GLIST)
scalar_configure((t_scalar *)(gp->gp_un.gp_gobj), gs->gs_un.gs_glist);
else
{
t_array *owner_array = gs->gs_un.gs_array;
while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY)
owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array;
scalar_redraw((t_scalar *)(owner_array->a_gp.gp_un.gp_gobj),
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
owner_array->a_gp.gp_stub->gs_un.gs_glist);
}
}
static void set_float(t_set *x, t_float f)
{
if (x->x_nin && !x->x_issymbol)
{
x->x_variables[0].gv_w.w_float = f;
set_bang(x);
}
else pd_error(x, "type mismatch or no field specified");
}
static void set_symbol(t_set *x, t_symbol *s)
{
if (x->x_nin && x->x_issymbol)
{
x->x_variables[0].gv_w.w_symbol = s;
set_bang(x);
}
else pd_error(x, "type mismatch or no field specified");
}
static void set_free(t_set *x)
{
freebytes(x->x_variables, x->x_nin * sizeof (*x->x_variables));
gpointer_unset(&x->x_gp);
}
static void set_setup(void)
{
set_class = class_new(gensym("set"), (t_newmethod)set_new,
(t_method)set_free, sizeof(t_set), 0, A_GIMME, 0);
class_addfloat(set_class, set_float);
class_addsymbol(set_class, set_symbol);
class_addbang(set_class, set_bang);
class_addmethod(set_class, (t_method)set_set, gensym("set"),
A_SYMBOL, A_SYMBOL, 0);
}
/* ---------------------- elem ----------------------------- */
static t_class *elem_class;
typedef struct _elem
{
t_object x_obj;
t_symbol *x_templatesym;
t_symbol *x_fieldsym;
t_gpointer x_gp;
t_gpointer x_gparent;
} t_elem;
static void *elem_new(t_symbol *templatesym, t_symbol *fieldsym)
{
t_elem *x = (t_elem *)pd_new(elem_class);
x->x_templatesym = template_getbindsym(templatesym);
x->x_fieldsym = fieldsym;
gpointer_init(&x->x_gp);
gpointer_init(&x->x_gparent);
pointerinlet_new(&x->x_obj, &x->x_gparent);
outlet_new(&x->x_obj, &s_pointer);
return (x);
}
static void elem_set(t_elem *x, t_symbol *templatesym, t_symbol *fieldsym)
{
x->x_templatesym = template_getbindsym(templatesym);
x->x_fieldsym = fieldsym;
}
static void elem_float(t_elem *x, t_float f)
{
int indx = f, nitems, onset;
t_symbol *templatesym, *fieldsym = x->x_fieldsym, *elemtemplatesym;
t_template *template;
t_template *elemtemplate;
t_gpointer *gparent = &x->x_gparent;
t_word *w;
t_array *array;
int elemsize, type;
if (!gpointer_check(gparent, 0))
{
pd_error(x, "element: empty pointer");
return;
}
if (*x->x_templatesym->s_name)
{
if ((templatesym = x->x_templatesym) !=
gpointer_gettemplatesym(gparent))
{
pd_error(x, "elem %s: got wrong template (%s)",
templatesym->s_name, gpointer_gettemplatesym(gparent)->s_name);
return;
}
}
else templatesym = gpointer_gettemplatesym(gparent);
if (!(template = template_findbyname(templatesym)))
pd_error(x, "elem: couldn't find template %s", templatesym->s_name);
return;
}
if (gparent->gp_stub->gs_which == GP_ARRAY) w = gparent->gp_un.gp_w;
else w = ((t_scalar *)(gparent->gp_un.gp_gobj))->sc_vec;
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
if (!template)
{
pd_error(x, "element: couldn't find template %s", templatesym->s_name);
return;
}
if (!template_find_field(template, fieldsym,
&onset, &type, &elemtemplatesym))
{
pd_error(x, "element: couldn't find array field %s", fieldsym->s_name);
return;
}
if (type != DT_ARRAY)
{
pd_error(x, "element: field %s not of type array", fieldsym->s_name);
return;
}
if (!(elemtemplate = template_findbyname(elemtemplatesym)))
{
pd_error(x, "element: couldn't find field template %s",
elemtemplatesym->s_name);
return;
}
elemsize = elemtemplate->t_n * sizeof(t_word);
array = *(t_array **)(((char *)w) + onset);
nitems = array->a_n;
if (indx < 0) indx = 0;
if (indx >= nitems) indx = nitems-1;
gpointer_setarray(&x->x_gp, array,
(t_word *)((char *)(array->a_vec) + indx * elemsize));
outlet_pointer(x->x_obj.ob_outlet, &x->x_gp);
}
static void elem_free(t_elem *x, t_gpointer *gp)
{
gpointer_unset(&x->x_gp);
gpointer_unset(&x->x_gparent);
}
static void elem_setup(void)
{
elem_class = class_new(gensym("element"), (t_newmethod)elem_new,
(t_method)elem_free, sizeof(t_elem), 0, A_DEFSYM, A_DEFSYM, 0);
class_addfloat(elem_class, elem_float);
class_addmethod(elem_class, (t_method)elem_set, gensym("set"),
A_SYMBOL, A_SYMBOL, 0);
}
/* ---------------------- getsize ----------------------------- */
static t_class *getsize_class;
typedef struct _getsize
{
t_object x_obj;
t_symbol *x_templatesym;
t_symbol *x_fieldsym;
} t_getsize;
static void *getsize_new(t_symbol *templatesym, t_symbol *fieldsym)
{
t_getsize *x = (t_getsize *)pd_new(getsize_class);
x->x_templatesym = template_getbindsym(templatesym);
x->x_fieldsym = fieldsym;
outlet_new(&x->x_obj, &s_float);
return (x);
}
static void getsize_set(t_getsize *x, t_symbol *templatesym, t_symbol *fieldsym)
{
x->x_templatesym = template_getbindsym(templatesym);
x->x_fieldsym = fieldsym;
}
static void getsize_pointer(t_getsize *x, t_gpointer *gp)
{
int nitems, onset, type;
t_symbol *templatesym, *fieldsym = x->x_fieldsym, *elemtemplatesym;
t_template *template;
pd_error(x, "get: stale or empty pointer");
if ((templatesym = x->x_templatesym) !=
gpointer_gettemplatesym(gp))
{
pd_error(x, "elem %s: got wrong template (%s)",
templatesym->s_name, gpointer_gettemplatesym(gp)->s_name);
return;
}
else templatesym = gpointer_gettemplatesym(gp);
if (!(template = template_findbyname(templatesym)))
pd_error(x, "elem: couldn't find template %s", templatesym->s_name);
if (!template_find_field(template, fieldsym,
&onset, &type, &elemtemplatesym))
pd_error(x, "getsize: couldn't find array field %s", fieldsym->s_name);
pd_error(x, "getsize: field %s not of type array", fieldsym->s_name);
return;
}
if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w;
else w = ((t_scalar *)(gp->gp_un.gp_gobj))->sc_vec;
outlet_float(x->x_obj.ob_outlet, (t_float)(array->a_n));
}
static void getsize_setup(void)
{
getsize_class = class_new(gensym("getsize"), (t_newmethod)getsize_new, 0,
sizeof(t_getsize), 0, A_DEFSYM, A_DEFSYM, 0);
class_addpointer(getsize_class, getsize_pointer);
class_addmethod(getsize_class, (t_method)getsize_set, gensym("set"),
A_SYMBOL, A_SYMBOL, 0);
}
/* ---------------------- setsize ----------------------------- */
static t_class *setsize_class;
typedef struct _setsize
{
t_object x_obj;
t_symbol *x_templatesym;
t_symbol *x_fieldsym;
t_gpointer x_gp;
} t_setsize;
static void *setsize_new(t_symbol *templatesym, t_symbol *fieldsym,
t_floatarg newsize)
{
t_setsize *x = (t_setsize *)pd_new(setsize_class);
x->x_templatesym = template_getbindsym(templatesym);
x->x_fieldsym = fieldsym;
gpointer_init(&x->x_gp);
pointerinlet_new(&x->x_obj, &x->x_gp);
return (x);
}
static void setsize_set(t_setsize *x, t_symbol *templatesym, t_symbol *fieldsym)
{
x->x_templatesym = template_getbindsym(templatesym);
x->x_fieldsym = fieldsym;
}
static void setsize_float(t_setsize *x, t_float f)
{
int nitems, onset, type;
t_symbol *templatesym, *fieldsym = x->x_fieldsym, *elemtemplatesym;
t_template *template;
t_array *array;
int elemsize;
int newsize = f;
t_gpointer *gp = &x->x_gp;
t_gstub *gs = gp->gp_stub;
if (!gpointer_check(&x->x_gp, 0))
{
pd_error(x, "setsize: empty pointer");
return;
}
if ((templatesym = x->x_templatesym) !=
gpointer_gettemplatesym(gp))
{
pd_error(x, "elem %s: got wrong template (%s)",
templatesym->s_name, gpointer_gettemplatesym(gp)->s_name);
return;
}
else templatesym = gpointer_gettemplatesym(gp);
if (!(template = template_findbyname(templatesym)))
pd_error(x, "elem: couldn't find template %s", templatesym->s_name);
return;
}
if (!template_find_field(template, fieldsym,
&onset, &type, &elemtemplatesym))
{
pd_error(x, "setsize: couldn't find array field %s", fieldsym->s_name);
return;
}
if (type != DT_ARRAY)
{
pd_error(x,"setsize: field %s not of type array", fieldsym->s_name);
return;
}
if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w;
else w = ((t_scalar *)(gp->gp_un.gp_gobj))->sc_vec;
if (!(elemtemplate = template_findbyname(elemtemplatesym)))
{
pd_error(x,"element: couldn't find field template %s",
elemtemplatesym->s_name);
return;
}
elemsize = elemtemplate->t_n * sizeof(t_word);
array = *(t_array **)(((char *)w) + onset);