~ubuntu-branches/ubuntu/precise/puredata/precise

« back to all changes in this revision

Viewing changes to src/m_obj.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Brossier
  • Date: 2009-12-22 21:29:31 UTC
  • mfrom: (1.2.6 upstream) (4.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091222212931-nhwkzapjwsmjao1l
Tags: 0.42.5-3
* debian/control:
  - add community site to homepage field
  - improve long description
  - remove Replaces and Conflicts fields
  - add Suggests on pd-csound, pd-pdp, pd-zexy, pd-aubio
* debian/rules: add per-arch configuration flags
* debian/patches/02_kfreebsd.diff:
  - also define pd_tilde_dllextent on FreeBSD
  - fix typo (really closing #414414 this time)
  - also add hurd glue
* debian/patches/04_hurd.diff:
  - add hurd glue and s_midi_dummy.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1997-1999 Miller Puckette.
 
2
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
 
3
* WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
 
4
 
 
5
/* this file handles Max-style patchable objects, i.e., objects which
 
6
can interconnect via inlets and outlets; also, the (terse) generic
 
7
behavior for "gobjs" appears at the end of this file.  */
 
8
 
 
9
#include "m_pd.h"
 
10
#include "m_imp.h"
 
11
 
 
12
union inletunion
 
13
{
 
14
    t_symbol *iu_symto;
 
15
    t_gpointer *iu_pointerslot;
 
16
    t_float *iu_floatslot;
 
17
    t_symbol **iu_symslot;
 
18
    t_float iu_floatsignalvalue;
 
19
};
 
20
 
 
21
struct _inlet
 
22
{
 
23
    t_pd i_pd;
 
24
    struct _inlet *i_next;
 
25
    t_object *i_owner;
 
26
    t_pd *i_dest;
 
27
    t_symbol *i_symfrom;
 
28
    union inletunion i_un;
 
29
};
 
30
 
 
31
#define i_symto i_un.iu_symto
 
32
#define i_pointerslot i_un.iu_pointerslot
 
33
#define i_floatslot i_un.iu_floatslot
 
34
#define i_symslot i_un.iu_symslot
 
35
 
 
36
static t_class *inlet_class, *pointerinlet_class, *floatinlet_class,
 
37
    *symbolinlet_class;
 
38
 
 
39
#define ISINLET(pd) ((*(pd) == inlet_class) || \
 
40
    (*(pd) == pointerinlet_class) || \
 
41
    (*(pd) == floatinlet_class) || \
 
42
    (*(pd) == symbolinlet_class))
 
43
 
 
44
/* --------------------- generic inlets ala max ------------------ */
 
45
 
 
46
t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1, t_symbol *s2)
 
47
{
 
48
    t_inlet *x = (t_inlet *)pd_new(inlet_class), *y, *y2;
 
49
    x->i_owner = owner;
 
50
    x->i_dest = dest;
 
51
    if (s1 == &s_signal)
 
52
        x->i_un.iu_floatsignalvalue = 0;
 
53
    else x->i_symto = s2;
 
54
    x->i_symfrom = s1;
 
55
    x->i_next = 0;
 
56
    if (y = owner->ob_inlet)
 
57
    {
 
58
        while (y2 = y->i_next) y = y2;
 
59
        y->i_next = x;
 
60
    }
 
61
    else owner->ob_inlet = x;
 
62
    return (x);
 
63
}
 
64
 
 
65
t_inlet *signalinlet_new(t_object *owner, t_float f)
 
66
{
 
67
    t_inlet *x = inlet_new(owner, &owner->ob_pd, &s_signal, &s_signal);
 
68
    x->i_un.iu_floatsignalvalue = f;
 
69
    return (x);
 
70
}
 
71
 
 
72
static void inlet_wrong(t_inlet *x, t_symbol *s)
 
73
{
 
74
    pd_error(x->i_owner, "inlet: expected '%s' but got '%s'",
 
75
        x->i_symfrom->s_name, s->s_name);
 
76
}
 
77
 
 
78
    /* LATER figure out how to make these efficient: */
 
79
static void inlet_bang(t_inlet *x)
 
80
{
 
81
    if (x->i_symfrom == &s_bang) 
 
82
        pd_vmess(x->i_dest, x->i_symto, "");
 
83
    else if (!x->i_symfrom) pd_bang(x->i_dest);
 
84
    else inlet_wrong(x, &s_bang);
 
85
}
 
86
 
 
87
static void inlet_pointer(t_inlet *x, t_gpointer *gp)
 
88
{
 
89
    if (x->i_symfrom == &s_pointer) 
 
90
        pd_vmess(x->i_dest, x->i_symto, "p", gp);
 
91
    else if (!x->i_symfrom) pd_pointer(x->i_dest, gp);
 
92
    else inlet_wrong(x, &s_pointer);
 
93
}
 
94
 
 
95
static void inlet_float(t_inlet *x, t_float f)
 
96
{
 
97
    if (x->i_symfrom == &s_float)
 
98
        pd_vmess(x->i_dest, x->i_symto, "f", (t_floatarg)f);
 
99
    else if (x->i_symfrom == &s_signal)
 
100
        x->i_un.iu_floatsignalvalue = f;
 
101
    else if (!x->i_symfrom)
 
102
        pd_float(x->i_dest, f);
 
103
    else inlet_wrong(x, &s_float);
 
104
}
 
105
 
 
106
static void inlet_symbol(t_inlet *x, t_symbol *s)
 
107
{
 
108
    if (x->i_symfrom == &s_symbol) 
 
109
        pd_vmess(x->i_dest, x->i_symto, "s", s);
 
110
    else if (!x->i_symfrom) pd_symbol(x->i_dest, s);
 
111
    else inlet_wrong(x, &s_symbol);
 
112
}
 
113
 
 
114
static void inlet_list(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
 
115
{
 
116
    t_atom at;
 
117
    if (x->i_symfrom == &s_list || x->i_symfrom == &s_float
 
118
        || x->i_symfrom == &s_symbol || x->i_symfrom == &s_pointer)
 
119
            typedmess(x->i_dest, x->i_symto, argc, argv);
 
120
    else if (!x->i_symfrom) pd_list(x->i_dest, s, argc, argv);
 
121
    else inlet_wrong(x, &s_list);
 
122
}
 
123
 
 
124
static void inlet_anything(t_inlet *x, t_symbol *s, int argc, t_atom *argv)
 
125
{
 
126
    if (x->i_symfrom == s)
 
127
        typedmess(x->i_dest, x->i_symto, argc, argv);
 
128
    else if (!x->i_symfrom)
 
129
        typedmess(x->i_dest, s, argc, argv);
 
130
    else inlet_wrong(x, s);
 
131
}
 
132
 
 
133
void inlet_free(t_inlet *x)
 
134
{
 
135
    t_object *y = x->i_owner;
 
136
    t_inlet *x2;
 
137
    if (y->ob_inlet == x) y->ob_inlet = x->i_next;
 
138
    else for (x2 = y->ob_inlet; x2; x2 = x2->i_next)
 
139
        if (x2->i_next == x)
 
140
    {
 
141
        x2->i_next = x->i_next;
 
142
        break;
 
143
    }
 
144
    t_freebytes(x, sizeof(*x));
 
145
}
 
146
 
 
147
/* ----- pointerinlets, floatinlets, syminlets: optimized inlets ------- */
 
148
 
 
149
static void pointerinlet_pointer(t_inlet *x, t_gpointer *gp)
 
150
{
 
151
    gpointer_unset(x->i_pointerslot);
 
152
    *(x->i_pointerslot) = *gp;
 
153
    if (gp->gp_stub) gp->gp_stub->gs_refcount++;
 
154
}
 
155
 
 
156
t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp)
 
157
{
 
158
    t_inlet *x = (t_inlet *)pd_new(pointerinlet_class), *y, *y2;
 
159
    x->i_owner = owner;
 
160
    x->i_dest = 0;
 
161
    x->i_symfrom = &s_pointer;
 
162
    x->i_pointerslot = gp;
 
163
    x->i_next = 0;
 
164
    if (y = owner->ob_inlet)
 
165
    {
 
166
        while (y2 = y->i_next) y = y2;
 
167
        y->i_next = x;
 
168
    }
 
169
    else owner->ob_inlet = x;
 
170
    return (x);
 
171
}
 
172
 
 
173
static void floatinlet_float(t_inlet *x, t_float f)
 
174
{
 
175
    *(x->i_floatslot) = f;
 
176
}
 
177
 
 
178
t_inlet *floatinlet_new(t_object *owner, t_float *fp)
 
179
{
 
180
    t_inlet *x = (t_inlet *)pd_new(floatinlet_class), *y, *y2;
 
181
    x->i_owner = owner;
 
182
    x->i_dest = 0;
 
183
    x->i_symfrom = &s_float;
 
184
    x->i_floatslot = fp;
 
185
    x->i_next = 0;
 
186
    if (y = owner->ob_inlet)
 
187
    {
 
188
        while (y2 = y->i_next) y = y2;
 
189
        y->i_next = x;
 
190
    }
 
191
    else owner->ob_inlet = x;
 
192
    return (x);
 
193
}
 
194
 
 
195
static void symbolinlet_symbol(t_inlet *x, t_symbol *s)
 
196
{
 
197
    *(x->i_symslot) = s;
 
198
}
 
199
 
 
200
t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp)
 
201
{
 
202
    t_inlet *x = (t_inlet *)pd_new(symbolinlet_class), *y, *y2;
 
203
    x->i_owner = owner;
 
204
    x->i_dest = 0;
 
205
    x->i_symfrom = &s_symbol;
 
206
    x->i_symslot = sp;
 
207
    x->i_next = 0;
 
208
    if (y = owner->ob_inlet)
 
209
    {
 
210
        while (y2 = y->i_next) y = y2;
 
211
        y->i_next = x;
 
212
    }
 
213
    else owner->ob_inlet = x;
 
214
    return (x);
 
215
}
 
216
 
 
217
/* ---------------------- routine to handle lists ---------------------- */
 
218
 
 
219
    /* objects interpret lists by feeding them to the individual inlets.
 
220
    Before you call this check that the object doesn't have a more
 
221
    specific way to handle lists. */
 
222
void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv)
 
223
{
 
224
    t_atom *ap;
 
225
    int count;
 
226
    t_inlet *ip = ((t_object *)x)->ob_inlet;
 
227
    if (!argc) return;
 
228
    for (count = argc-1, ap = argv+1; ip && count--; ap++, ip = ip->i_next)
 
229
    {
 
230
        if (ap->a_type == A_POINTER) pd_pointer(&ip->i_pd, ap->a_w.w_gpointer);
 
231
        else if (ap->a_type == A_FLOAT) pd_float(&ip->i_pd, ap->a_w.w_float);
 
232
        else pd_symbol(&ip->i_pd, ap->a_w.w_symbol);
 
233
    }
 
234
    if (argv->a_type == A_POINTER) pd_pointer(&x->ob_pd, argv->a_w.w_gpointer);
 
235
    else if (argv->a_type == A_FLOAT) pd_float(&x->ob_pd, argv->a_w.w_float);
 
236
    else pd_symbol(&x->ob_pd, argv->a_w.w_symbol);
 
237
 
238
 
 
239
void obj_init(void)
 
240
{
 
241
    inlet_class = class_new(gensym("inlet"), 0, 0,
 
242
        sizeof(t_inlet), CLASS_PD, 0);
 
243
    class_addbang(inlet_class, inlet_bang);
 
244
    class_addpointer(inlet_class, inlet_pointer);
 
245
    class_addfloat(inlet_class, inlet_float);
 
246
    class_addsymbol(inlet_class, inlet_symbol);
 
247
    class_addlist(inlet_class, inlet_list);
 
248
    class_addanything(inlet_class, inlet_anything);
 
249
 
 
250
    pointerinlet_class = class_new(gensym("inlet"), 0, 0,
 
251
        sizeof(t_inlet), CLASS_PD, 0);
 
252
    class_addpointer(pointerinlet_class, pointerinlet_pointer);
 
253
    class_addanything(pointerinlet_class, inlet_wrong);
 
254
    
 
255
    floatinlet_class = class_new(gensym("inlet"), 0, 0,
 
256
        sizeof(t_inlet), CLASS_PD, 0);
 
257
    class_addfloat(floatinlet_class, (t_method)floatinlet_float);
 
258
    class_addanything(floatinlet_class, inlet_wrong);
 
259
 
 
260
    symbolinlet_class = class_new(gensym("inlet"), 0, 0,
 
261
        sizeof(t_inlet), CLASS_PD, 0);
 
262
    class_addsymbol(symbolinlet_class, symbolinlet_symbol);
 
263
    class_addanything(symbolinlet_class, inlet_wrong);
 
264
 
 
265
}
 
266
 
 
267
/* --------------------------- outlets ------------------------------ */
 
268
 
 
269
static int stackcount = 0; /* iteration counter */
 
270
#define STACKITER 1000 /* maximum iterations allowed */
 
271
 
 
272
static int outlet_eventno;
 
273
 
 
274
    /* set a stack limit (on each incoming event that can set off messages)
 
275
    for the outlet functions to check to prevent stack overflow from message
 
276
    recursion */
 
277
        
 
278
void outlet_setstacklim(void)
 
279
{
 
280
    outlet_eventno++;
 
281
}
 
282
 
 
283
    /* get a number unique to the (clock, MIDI, GUI, etc.) event we're on */
 
284
int sched_geteventno( void)
 
285
{
 
286
    return (outlet_eventno);
 
287
}
 
288
 
 
289
struct _outconnect
 
290
{
 
291
    struct _outconnect *oc_next;
 
292
    t_pd *oc_to;
 
293
};
 
294
 
 
295
struct _outlet
 
296
{
 
297
    t_object *o_owner;
 
298
    struct _outlet *o_next;
 
299
    t_outconnect *o_connections;
 
300
    t_symbol *o_sym;
 
301
};
 
302
 
 
303
t_outlet *outlet_new(t_object *owner, t_symbol *s)
 
304
{
 
305
    t_outlet *x = (t_outlet *)getbytes(sizeof(*x)), *y, *y2;
 
306
    x->o_owner = owner;
 
307
    x->o_next = 0;
 
308
    if (y = owner->ob_outlet)
 
309
    {
 
310
        while (y2 = y->o_next) y = y2;
 
311
        y->o_next = x;
 
312
    }
 
313
    else owner->ob_outlet = x;
 
314
    x->o_connections = 0;
 
315
    x->o_sym = s;
 
316
    return (x);
 
317
}
 
318
 
 
319
static void outlet_stackerror(t_outlet *x)
 
320
{
 
321
    pd_error(x->o_owner, "stack overflow");
 
322
}
 
323
 
 
324
void outlet_bang(t_outlet *x)
 
325
{
 
326
    t_outconnect *oc;
 
327
    if(++stackcount >= STACKITER)
 
328
        outlet_stackerror(x);
 
329
    else 
 
330
    for (oc = x->o_connections; oc; oc = oc->oc_next)
 
331
        pd_bang(oc->oc_to);
 
332
    --stackcount;
 
333
}
 
334
 
 
335
void outlet_pointer(t_outlet *x, t_gpointer *gp)
 
336
{
 
337
    t_outconnect *oc;
 
338
    t_gpointer gpointer;
 
339
    if(++stackcount >= STACKITER)
 
340
        outlet_stackerror(x);
 
341
    else
 
342
    {
 
343
        gpointer = *gp;
 
344
        for (oc = x->o_connections; oc; oc = oc->oc_next)
 
345
            pd_pointer(oc->oc_to, &gpointer);
 
346
    }
 
347
    --stackcount;
 
348
}
 
349
 
 
350
void outlet_float(t_outlet *x, t_float f)
 
351
{
 
352
    t_outconnect *oc;
 
353
    if(++stackcount >= STACKITER)
 
354
        outlet_stackerror(x);
 
355
    else
 
356
    for (oc = x->o_connections; oc; oc = oc->oc_next)
 
357
        pd_float(oc->oc_to, f);
 
358
    --stackcount;
 
359
}
 
360
 
 
361
void outlet_symbol(t_outlet *x, t_symbol *s)
 
362
{
 
363
    t_outconnect *oc;
 
364
    if(++stackcount >= STACKITER)
 
365
        outlet_stackerror(x);
 
366
    else
 
367
    for (oc = x->o_connections; oc; oc = oc->oc_next)
 
368
        pd_symbol(oc->oc_to, s);
 
369
    --stackcount;
 
370
}
 
371
 
 
372
void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
 
373
{
 
374
    t_outconnect *oc;
 
375
    if(++stackcount >= STACKITER)
 
376
        outlet_stackerror(x);
 
377
    else
 
378
    for (oc = x->o_connections; oc; oc = oc->oc_next)
 
379
        pd_list(oc->oc_to, s, argc, argv);
 
380
    --stackcount;
 
381
}
 
382
 
 
383
void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv)
 
384
{
 
385
    t_outconnect *oc;
 
386
    if(++stackcount >= STACKITER)
 
387
        outlet_stackerror(x);
 
388
    else
 
389
    for (oc = x->o_connections; oc; oc = oc->oc_next)
 
390
        typedmess(oc->oc_to, s, argc, argv);
 
391
    --stackcount;
 
392
}
 
393
 
 
394
    /* get the outlet's declared symbol */
 
395
t_symbol *outlet_getsymbol(t_outlet *x)
 
396
{
 
397
    return (x->o_sym);
 
398
}
 
399
 
 
400
void outlet_free(t_outlet *x)
 
401
{
 
402
    t_object *y = x->o_owner;
 
403
    t_outlet *x2;
 
404
    if (y->ob_outlet == x) y->ob_outlet = x->o_next;
 
405
    else for (x2 = y->ob_outlet; x2; x2 = x2->o_next)
 
406
        if (x2->o_next == x)
 
407
    {
 
408
        x2->o_next = x->o_next;
 
409
        break;
 
410
    }
 
411
    t_freebytes(x, sizeof(*x));
 
412
}
 
413
 
 
414
t_outconnect *obj_connect(t_object *source, int outno,
 
415
    t_object *sink, int inno)
 
416
{
 
417
    t_inlet *i;
 
418
    t_outlet *o;
 
419
    t_pd *to;
 
420
    t_outconnect *oc, *oc2;
 
421
    
 
422
    for (o = source->ob_outlet; o && outno; o = o->o_next, outno--) ;
 
423
    if (!o) return (0);
 
424
    
 
425
    if (sink->ob_pd->c_firstin)
 
426
    {
 
427
        if (!inno)
 
428
        {
 
429
            to = &sink->ob_pd;
 
430
            goto doit;
 
431
        }
 
432
        else inno--;
 
433
    }
 
434
    for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ;
 
435
    if (!i) return (0);
 
436
    to = &i->i_pd;
 
437
doit:
 
438
    oc = (t_outconnect *)t_getbytes(sizeof(*oc));
 
439
    oc->oc_next = 0;
 
440
    oc->oc_to = to;
 
441
        /* append it to the end of the list */
 
442
        /* LATER we might cache the last "oc" to make this faster. */
 
443
    if ((oc2 = o->o_connections))
 
444
    {
 
445
        while (oc2->oc_next) oc2 = oc2->oc_next;
 
446
        oc2->oc_next = oc;
 
447
    }
 
448
    else o->o_connections = oc;
 
449
    if (o->o_sym == &s_signal) canvas_update_dsp();
 
450
 
 
451
    return (oc);
 
452
}
 
453
 
 
454
void obj_disconnect(t_object *source, int outno, t_object *sink, int inno)
 
455
{
 
456
    t_inlet *i;
 
457
    t_outlet *o;
 
458
    t_pd *to;
 
459
    t_outconnect *oc, *oc2;
 
460
    
 
461
    for (o = source->ob_outlet; o && outno; o = o->o_next, outno--)
 
462
    if (!o) return;
 
463
    if (sink->ob_pd->c_firstin)
 
464
    {
 
465
        if (!inno)
 
466
        {
 
467
            to = &sink->ob_pd;
 
468
            goto doit;
 
469
        }
 
470
        else inno--;
 
471
    }
 
472
    for (i = sink->ob_inlet; i && inno; i = i->i_next, inno--) ;
 
473
    if (!i) return;
 
474
    to = &i->i_pd;
 
475
doit:
 
476
    if (!(oc = o->o_connections)) return;
 
477
    if (oc->oc_to == to)
 
478
    {
 
479
        o->o_connections = oc->oc_next;
 
480
        freebytes(oc, sizeof(*oc));
 
481
        goto done;
 
482
    }
 
483
    while (oc2 = oc->oc_next)
 
484
    {
 
485
        if (oc2->oc_to == to)
 
486
        {
 
487
            oc->oc_next = oc2->oc_next;
 
488
            freebytes(oc2, sizeof(*oc2));
 
489
            goto done;
 
490
        }
 
491
        oc = oc2;
 
492
    }
 
493
done:
 
494
    if (o->o_sym == &s_signal) canvas_update_dsp();
 
495
}
 
496
 
 
497
/* ------ traversal routines for code that can't see our structures ------ */
 
498
 
 
499
int obj_noutlets(t_object *x)
 
500
{
 
501
    int n;
 
502
    t_outlet *o;
 
503
    for (o = x->ob_outlet, n = 0; o; o = o->o_next) n++;
 
504
    return (n);
 
505
}
 
506
 
 
507
int obj_ninlets(t_object *x)
 
508
{
 
509
    int n;
 
510
    t_inlet *i;
 
511
    for (i = x->ob_inlet, n = 0; i; i = i->i_next) n++;
 
512
    if (x->ob_pd->c_firstin) n++;
 
513
    return (n);
 
514
}
 
515
 
 
516
t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, int nout)
 
517
{
 
518
    t_outlet *o = x->ob_outlet;
 
519
    while (nout-- && o) o = o->o_next;
 
520
    *op = o;
 
521
    if (o) return (o->o_connections);
 
522
    else return (0);
 
523
}
 
524
 
 
525
t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect,
 
526
    t_object **destp, t_inlet **inletp, int *whichp)
 
527
{
 
528
    t_pd *y;
 
529
    y = lastconnect->oc_to;
 
530
    if (ISINLET(y))
 
531
    {
 
532
        int n;
 
533
        t_inlet *i = (t_inlet *)y, *i2;
 
534
        t_object *dest = i->i_owner;
 
535
        for (n = dest->ob_pd->c_firstin, i2 = dest->ob_inlet;
 
536
            i2 && i2 != i; i2 = i2->i_next) n++;
 
537
        *whichp = n;
 
538
        *destp = dest;
 
539
        *inletp = i;
 
540
    }
 
541
    else
 
542
    {
 
543
        *whichp = 0;
 
544
        *inletp = 0;
 
545
        *destp = ((t_object *)y);
 
546
    }
 
547
    return (lastconnect->oc_next);
 
548
}
 
549
 
 
550
    /* this one checks that a pd is indeed a patchable object, and returns
 
551
    it, correctly typed, or zero if the check failed. */
 
552
t_object *pd_checkobject(t_pd *x)
 
553
{
 
554
    if ((*x)->c_patchable) return ((t_object *)x);
 
555
    else return (0);
 
556
}
 
557
 
 
558
    /* move an inlet or outlet to the head of the list */
 
559
void obj_moveinletfirst(t_object *x, t_inlet *i)
 
560
{
 
561
    t_inlet *i2;
 
562
    if (x->ob_inlet == i) return;
 
563
    else for (i2 = x->ob_inlet; i2; i2 = i2->i_next)
 
564
        if (i2->i_next == i)
 
565
    {
 
566
        i2->i_next = i->i_next;
 
567
        i->i_next = x->ob_inlet;
 
568
        x->ob_inlet = i;
 
569
        return;
 
570
    }
 
571
}
 
572
 
 
573
void obj_moveoutletfirst(t_object *x, t_outlet *o)
 
574
{
 
575
    t_outlet *o2;
 
576
    if (x->ob_outlet == o) return;
 
577
    else for (o2 = x->ob_outlet; o2; o2 = o2->o_next)
 
578
        if (o2->o_next == o)
 
579
    {
 
580
        o2->o_next = o->o_next;
 
581
        o->o_next = x->ob_outlet;
 
582
        x->ob_outlet = o;
 
583
        return;
 
584
    }
 
585
}
 
586
 
 
587
    /* routines for DSP sorting, which are used in d_ugen.c and g_canvas.c */
 
588
    /* LATER try to consolidate all the slightly different routines. */
 
589
 
 
590
int obj_nsiginlets(t_object *x)
 
591
{
 
592
    int n;
 
593
    t_inlet *i;
 
594
    for (i = x->ob_inlet, n = 0; i; i = i->i_next)
 
595
        if (i->i_symfrom == &s_signal) n++;
 
596
    if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) n++;
 
597
    return (n);
 
598
}
 
599
 
 
600
    /* get the index, among signal inlets, of the mth inlet overall */
 
601
int obj_siginletindex(t_object *x, int m)
 
602
{
 
603
    int n = 0;
 
604
    t_inlet *i;
 
605
    if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin)
 
606
    {
 
607
        if (!m--) return (0);
 
608
        n++;
 
609
    }
 
610
    for (i = x->ob_inlet; i; i = i->i_next, m--)
 
611
        if (i->i_symfrom == &s_signal)
 
612
    {
 
613
        if (m == 0) return (n);
 
614
        n++;
 
615
    }
 
616
    return (-1);
 
617
}
 
618
 
 
619
int obj_issignalinlet(t_object *x, int m)
 
620
{
 
621
    t_inlet *i;
 
622
    if (x->ob_pd->c_firstin)
 
623
    {
 
624
        if (!m)
 
625
            return (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin);
 
626
        else m--;
 
627
    }
 
628
    for (i = x->ob_inlet; i && m; i = i->i_next, m--)
 
629
        ;
 
630
    return (i && (i->i_symfrom == &s_signal));
 
631
}
 
632
 
 
633
int obj_nsigoutlets(t_object *x)
 
634
{
 
635
    int n;
 
636
    t_outlet *o;
 
637
    for (o = x->ob_outlet, n = 0; o; o = o->o_next)
 
638
        if (o->o_sym == &s_signal) n++;
 
639
    return (n);
 
640
}
 
641
 
 
642
int obj_sigoutletindex(t_object *x, int m)
 
643
{
 
644
    int n;
 
645
    t_outlet *o2;
 
646
    for (o2 = x->ob_outlet, n = 0; o2; o2 = o2->o_next, m--)
 
647
        if (o2->o_sym == &s_signal)
 
648
    {
 
649
        if (m == 0) return (n);
 
650
        n++;
 
651
    }
 
652
    return (-1);
 
653
}
 
654
 
 
655
int obj_issignaloutlet(t_object *x, int m)
 
656
{
 
657
    int n;
 
658
    t_outlet *o2;
 
659
    for (o2 = x->ob_outlet, n = 0; o2 && m--; o2 = o2->o_next);
 
660
    return (o2 && (o2->o_sym == &s_signal));
 
661
}
 
662
 
 
663
t_float *obj_findsignalscalar(t_object *x, int m)
 
664
{
 
665
    int n = 0;
 
666
    t_inlet *i;
 
667
    if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin)
 
668
    {
 
669
        if (!m--)
 
670
            return (x->ob_pd->c_floatsignalin > 0 ?
 
671
                (t_float *)(((char *)x) + x->ob_pd->c_floatsignalin) : 0);
 
672
        n++;
 
673
    }
 
674
    for (i = x->ob_inlet; i; i = i->i_next, m--)
 
675
        if (i->i_symfrom == &s_signal)
 
676
    {
 
677
        if (m == 0)
 
678
            return (&i->i_un.iu_floatsignalvalue);
 
679
        n++;
 
680
    }
 
681
    return (0);
 
682
}
 
683
 
 
684
/* and these are only used in g_io.c... */
 
685
 
 
686
int inlet_getsignalindex(t_inlet *x)
 
687
{
 
688
    int n = 0;
 
689
    t_inlet *i;
 
690
    if (x->i_symfrom != &s_signal)
 
691
        bug("inlet_getsignalindex");
 
692
    for (i = x->i_owner->ob_inlet, n = 0; i && i != x; i = i->i_next)
 
693
        if (i->i_symfrom == &s_signal) n++;
 
694
    return (n);
 
695
}
 
696
 
 
697
int outlet_getsignalindex(t_outlet *x)
 
698
{
 
699
    int n = 0;
 
700
    t_outlet *o;
 
701
    for (o = x->o_owner->ob_outlet, n = 0; o && o != x; o = o->o_next) 
 
702
        if (o->o_sym == &s_signal) n++;
 
703
    return (n);
 
704
}
 
705