summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/x_time.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/x_time.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/x_time.c1040
1 files changed, 1040 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/x_time.c b/apps/plugins/pdbox/PDa/src/x_time.c
new file mode 100644
index 0000000000..580a30b36d
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/src/x_time.c
@@ -0,0 +1,1040 @@
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/* clock objects */
6
7#include "m_pd.h"
8#include <stdio.h>
9/* -------------------------- delay ------------------------------ */
10static t_class *delay_class;
11
12typedef struct _delay
13{
14 t_object x_obj;
15 t_clock *x_clock;
16 double x_deltime;
17} t_delay;
18
19static void delay_bang(t_delay *x)
20{
21 clock_delay(x->x_clock, x->x_deltime);
22}
23
24static void delay_stop(t_delay *x)
25{
26 clock_unset(x->x_clock);
27}
28
29static void delay_ft1(t_delay *x, t_floatarg g)
30{
31 if (g < 0) g = 0;
32 x->x_deltime = g;
33}
34
35static void delay_float(t_delay *x, t_float f)
36{
37 delay_ft1(x, f);
38 delay_bang(x);
39}
40
41static void delay_tick(t_delay *x)
42{
43 outlet_bang(x->x_obj.ob_outlet);
44}
45
46static void delay_free(t_delay *x)
47{
48 clock_free(x->x_clock);
49}
50
51static void *delay_new(t_floatarg f)
52{
53 t_delay *x = (t_delay *)pd_new(delay_class);
54 delay_ft1(x, f);
55 x->x_clock = clock_new(x, (t_method)delay_tick);
56 outlet_new(&x->x_obj, gensym("bang"));
57 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
58 return (x);
59}
60
61static void delay_setup(void)
62{
63 delay_class = class_new(gensym("delay"), (t_newmethod)delay_new,
64 (t_method)delay_free, sizeof(t_delay), 0, A_DEFFLOAT, 0);
65 class_addcreator((t_newmethod)delay_new, gensym("del"), A_DEFFLOAT, 0);
66 class_addbang(delay_class, delay_bang);
67 class_addmethod(delay_class, (t_method)delay_stop, gensym("stop"), 0);
68 class_addmethod(delay_class, (t_method)delay_ft1,
69 gensym("ft1"), A_FLOAT, 0);
70 class_addfloat(delay_class, (t_method)delay_float);
71}
72
73/* -------------------------- metro ------------------------------ */
74static t_class *metro_class;
75
76typedef struct _metro
77{
78 t_object x_obj;
79 t_clock *x_clock;
80 double x_deltime;
81 int x_hit;
82} t_metro;
83
84static void metro_tick(t_metro *x)
85{
86 x->x_hit = 0;
87 outlet_bang(x->x_obj.ob_outlet);
88 if (!x->x_hit) clock_delay(x->x_clock, x->x_deltime);
89}
90
91static void metro_float(t_metro *x, t_float f)
92{
93 if (f != 0) metro_tick(x);
94 else clock_unset(x->x_clock);
95 x->x_hit = 1;
96}
97
98static void metro_bang(t_metro *x)
99{
100 metro_float(x, 1);
101}
102
103static void metro_stop(t_metro *x)
104{
105 metro_float(x, 0);
106}
107
108static void metro_ft1(t_metro *x, t_floatarg g)
109{
110 if (g < 1) g = 1;
111 x->x_deltime = g;
112}
113
114static void metro_free(t_metro *x)
115{
116 clock_free(x->x_clock);
117}
118
119static void *metro_new(t_floatarg f)
120{
121 t_metro *x = (t_metro *)pd_new(metro_class);
122 metro_ft1(x, f);
123 x->x_hit = 0;
124 x->x_clock = clock_new(x, (t_method)metro_tick);
125 outlet_new(&x->x_obj, gensym("bang"));
126 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
127 return (x);
128}
129
130static void metro_setup(void)
131{
132 metro_class = class_new(gensym("metro"), (t_newmethod)metro_new,
133 (t_method)metro_free, sizeof(t_metro), 0, A_DEFFLOAT, 0);
134 class_addbang(metro_class, metro_bang);
135 class_addmethod(metro_class, (t_method)metro_stop, gensym("stop"), 0);
136 class_addmethod(metro_class, (t_method)metro_ft1, gensym("ft1"),
137 A_FLOAT, 0);
138 class_addfloat(metro_class, (t_method)metro_float);
139}
140
141/* -------------------------- line ------------------------------ */
142static t_class *line_class;
143
144typedef struct _line
145{
146 t_object x_obj;
147 t_clock *x_clock;
148 double x_targettime;
149 t_float x_targetval;
150 double x_prevtime;
151 t_float x_setval;
152 int x_gotinlet;
153 t_float x_grain;
154 double x_1overtimediff;
155 double x_in1val;
156} t_line;
157
158static void line_tick(t_line *x)
159{
160 double timenow = clock_getsystime();
161 double msectogo = - clock_gettimesince(x->x_targettime);
162 if (msectogo < 1E-9)
163 {
164 outlet_float(x->x_obj.ob_outlet, x->x_targetval);
165 }
166 else
167 {
168 outlet_float(x->x_obj.ob_outlet,
169 x->x_setval + x->x_1overtimediff * (timenow - x->x_prevtime)
170 * (x->x_targetval - x->x_setval));
171 clock_delay(x->x_clock,
172 (x->x_grain > msectogo ? msectogo : x->x_grain));
173 }
174}
175
176static void line_float(t_line *x, t_float f)
177{
178 double timenow = clock_getsystime();
179 if (x->x_gotinlet && x->x_in1val > 0)
180 {
181 if (timenow > x->x_targettime) x->x_setval = x->x_targetval;
182 else x->x_setval = x->x_setval + x->x_1overtimediff *
183 (timenow - x->x_prevtime)
184 * (x->x_targetval - x->x_setval);
185 x->x_prevtime = timenow;
186 x->x_targettime = clock_getsystimeafter(x->x_in1val);
187 x->x_targetval = f;
188 line_tick(x);
189 x->x_gotinlet = 0;
190 x->x_1overtimediff = 1./ (x->x_targettime - timenow);
191 clock_delay(x->x_clock,
192 (x->x_grain > x->x_in1val ? x->x_in1val : x->x_grain));
193
194 }
195 else
196 {
197 clock_unset(x->x_clock);
198 x->x_targetval = x->x_setval = f;
199 outlet_float(x->x_obj.ob_outlet, f);
200 }
201 x->x_gotinlet = 0;
202}
203
204static void line_ft1(t_line *x, t_floatarg g)
205{
206 x->x_in1val = g;
207 x->x_gotinlet = 1;
208}
209
210static void line_stop(t_line *x)
211{
212 x->x_targetval = x->x_setval;
213 clock_unset(x->x_clock);
214}
215
216static void line_free(t_line *x)
217{
218 clock_free(x->x_clock);
219}
220
221static void *line_new(t_floatarg f, t_floatarg grain)
222{
223 t_line *x = (t_line *)pd_new(line_class);
224 x->x_targetval = x->x_setval = f;
225 x->x_gotinlet = 0;
226 x->x_1overtimediff = 1;
227 x->x_clock = clock_new(x, (t_method)line_tick);
228 x->x_targettime = x->x_prevtime = clock_getsystime();
229 if (grain <= 0) grain = 20;
230 x->x_grain = grain;
231 outlet_new(&x->x_obj, gensym("float"));
232 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
233 return (x);
234}
235
236static void line_setup(void)
237{
238 line_class = class_new(gensym("line"), (t_newmethod)line_new,
239 (t_method)line_free, sizeof(t_line), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
240 class_addmethod(line_class, (t_method)line_ft1,
241 gensym("ft1"), A_FLOAT, 0);
242 class_addmethod(line_class, (t_method)line_stop,
243 gensym("stop"), 0);
244 class_addfloat(line_class, (t_method)line_float);
245}
246
247/* -------------------------- timer ------------------------------ */
248static t_class *timer_class;
249
250typedef struct _timer
251{
252 t_object x_obj;
253 t_time x_settime;
254} t_timer;
255
256static void timer_bang(t_timer *x)
257{
258 x->x_settime = clock_getsystime();
259}
260
261static void timer_bang2(t_timer *x)
262{
263 t_time diff = clock_gettimesince(x->x_settime);
264 outlet_float(x->x_obj.ob_outlet, diff);
265}
266
267static void *timer_new(t_floatarg f)
268{
269 t_timer *x = (t_timer *)pd_new(timer_class);
270 timer_bang(x);
271 outlet_new(&x->x_obj, gensym("float"));
272 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
273 return (x);
274}
275
276static void timer_setup(void)
277{
278 timer_class = class_new(gensym("timer"), (t_newmethod)timer_new, 0,
279 sizeof(t_timer), 0, A_DEFFLOAT, 0);
280 class_addbang(timer_class, timer_bang);
281 class_addmethod(timer_class, (t_method)timer_bang2, gensym("bang2"), 0);
282}
283
284
285/* -------------------------- pipe -------------------------- */
286
287static t_class *pipe_class;
288
289typedef struct _hang
290{
291 t_clock *h_clock;
292 struct _hang *h_next;
293 struct _pipe *h_owner;
294 t_gpointer *h_gp;
295 union word h_vec[1]; /* not the actual number. */
296} t_hang;
297
298typedef struct pipeout
299{
300 t_atom p_atom;
301 t_outlet *p_outlet;
302} t_pipeout;
303
304typedef struct _pipe
305{
306 t_object x_obj;
307 int x_n;
308 int x_nptr;
309 float x_deltime;
310 t_pipeout *x_vec;
311 t_gpointer *x_gp;
312 t_hang *x_hang;
313} t_pipe;
314
315static void *pipe_new(t_symbol *s, int argc, t_atom *argv)
316{
317 t_pipe *x = (t_pipe *)pd_new(pipe_class);
318 t_atom defarg, *ap;
319 t_pipeout *vec, *vp;
320 t_gpointer *gp;
321 int nptr = 0;
322 int i;
323 float deltime;
324 if (argc)
325 {
326 if (argv[argc-1].a_type != A_FLOAT)
327 {
328 char stupid[80];
329 atom_string(&argv[argc-1], stupid, 79);
330 post("pipe: %s: bad time delay value", stupid);
331 deltime = 0;
332 }
333 else deltime = argv[argc-1].a_w.w_float;
334 argc--;
335 }
336 else deltime = 0;
337 if (!argc)
338 {
339 argv = &defarg;
340 argc = 1;
341 SETFLOAT(&defarg, 0);
342 }
343 x->x_n = argc;
344 vec = x->x_vec = (t_pipeout *)getbytes(argc * sizeof(*x->x_vec));
345
346 for (i = argc, ap = argv; i--; ap++)
347 if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p')
348 nptr++;
349
350 gp = x->x_gp = (t_gpointer *)t_getbytes(nptr * sizeof (*gp));
351 x->x_nptr = nptr;
352
353 for (i = 0, vp = vec, ap = argv; i < argc; i++, ap++, vp++)
354 {
355 if (ap->a_type == A_FLOAT)
356 {
357 vp->p_atom = *ap;
358 vp->p_outlet = outlet_new(&x->x_obj, &s_float);
359 if (i) floatinlet_new(&x->x_obj, &vp->p_atom.a_w.w_float);
360 }
361 else if (ap->a_type == A_SYMBOL)
362 {
363 char c = *ap->a_w.w_symbol->s_name;
364 if (c == 's')
365 {
366 SETSYMBOL(&vp->p_atom, &s_symbol);
367 vp->p_outlet = outlet_new(&x->x_obj, &s_symbol);
368 if (i) symbolinlet_new(&x->x_obj, &vp->p_atom.a_w.w_symbol);
369 }
370 else if (c == 'p')
371 {
372 vp->p_atom.a_type = A_POINTER;
373 vp->p_atom.a_w.w_gpointer = gp;
374 gpointer_init(gp);
375 vp->p_outlet = outlet_new(&x->x_obj, &s_pointer);
376 if (i) pointerinlet_new(&x->x_obj, gp);
377 gp++;
378 }
379 else
380 {
381 if (c != 'f') error("pack: %s: bad type",
382 ap->a_w.w_symbol->s_name);
383 SETFLOAT(&vp->p_atom, 0);
384 vp->p_outlet = outlet_new(&x->x_obj, &s_float);
385 if (i) floatinlet_new(&x->x_obj, &vp->p_atom.a_w.w_float);
386 }
387 }
388 }
389 floatinlet_new(&x->x_obj, &x->x_deltime);
390 x->x_hang = 0;
391 x->x_deltime = deltime;
392 return (x);
393}
394
395static void hang_free(t_hang *h)
396{
397 t_pipe *x = h->h_owner;
398 t_gpointer *gp;
399 int i;
400 for (gp = h->h_gp, i = x->x_nptr; i--; gp++)
401 gpointer_unset(gp);
402 freebytes(h->h_gp, x->x_nptr * sizeof(*h->h_gp));
403 clock_free(h->h_clock);
404 freebytes(h, sizeof(*h) + (x->x_n - 1) * sizeof(*h->h_vec));
405}
406
407static void hang_tick(t_hang *h)
408{
409 t_pipe *x = h->h_owner;
410 t_hang *h2, *h3;
411 t_pipeout *p;
412 int i;
413 union word *w;
414 if (x->x_hang == h) x->x_hang = h->h_next;
415 else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3)
416 {
417 if (h3 == h)
418 {
419 h2->h_next = h3->h_next;
420 break;
421 }
422 }
423 for (i = x->x_n, p = x->x_vec + (x->x_n - 1), w = h->h_vec + (x->x_n - 1);
424 i--; p--, w--)
425 {
426 switch (p->p_atom.a_type)
427 {
428 case A_FLOAT: outlet_float(p->p_outlet, w->w_float); break;
429 case A_SYMBOL: outlet_symbol(p->p_outlet, w->w_symbol); break;
430 case A_POINTER:
431 if (gpointer_check(w->w_gpointer, 1))
432 outlet_pointer(p->p_outlet, w->w_gpointer);
433 else post("pipe: stale pointer");
434 break;
435 }
436 }
437 hang_free(h);
438}
439
440static void pipe_list(t_pipe *x, t_symbol *s, int ac, t_atom *av)
441{
442 t_hang *h = (t_hang *)
443 getbytes(sizeof(*h) + (x->x_n - 1) * sizeof(*h->h_vec));
444 t_gpointer *gp, *gp2;
445 t_pipeout *p;
446 int i, n = x->x_n;
447 t_atom *ap;
448 t_word *w;
449 h->h_gp = (t_gpointer *)getbytes(x->x_nptr * sizeof(t_gpointer));
450 if (ac > n) ac = n;
451 for (i = 0, gp = x->x_gp, p = x->x_vec, ap = av; i < ac;
452 i++, p++, ap++)
453 {
454 switch (p->p_atom.a_type)
455 {
456 case A_FLOAT: p->p_atom.a_w.w_float = atom_getfloat(ap); break;
457 case A_SYMBOL: p->p_atom.a_w.w_symbol = atom_getsymbol(ap); break;
458 case A_POINTER:
459 gpointer_unset(gp);
460 if (ap->a_type != A_POINTER)
461 post("pipe: bad pointer");
462 else
463 {
464 *gp = *(ap->a_w.w_gpointer);
465 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
466 }
467 gp++;
468 }
469 }
470 for (i = 0, gp = x->x_gp, gp2 = h->h_gp, p = x->x_vec, w = h->h_vec;
471 i < n; i++, p++, w++)
472 {
473 if (p->p_atom.a_type == A_POINTER)
474 {
475 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
476 w->w_gpointer = gp2;
477 *gp2++ = *gp++;
478 }
479 else *w = p->p_atom.a_w;
480 }
481 h->h_next = x->x_hang;
482 x->x_hang = h;
483 h->h_owner = x;
484 h->h_clock = clock_new(h, (t_method)hang_tick);
485 clock_delay(h->h_clock, (x->x_deltime >= 0 ? x->x_deltime : 0));
486}
487
488static void pipe_flush(t_pipe *x)
489{
490 while (x->x_hang) hang_tick(x->x_hang);
491}
492
493static void pipe_clear(t_pipe *x)
494{
495 t_hang *hang;
496 while (hang = x->x_hang)
497 {
498 x->x_hang = hang->h_next;
499 hang_free(hang);
500 }
501}
502
503static void pipe_setup(void)
504{
505 pipe_class = class_new(gensym("pipe"),
506 (t_newmethod)pipe_new, (t_method)pipe_clear,
507 sizeof(t_pipe), 0, A_GIMME, 0);
508 class_addlist(pipe_class, pipe_list);
509 class_addmethod(pipe_class, (t_method)pipe_flush, gensym("flush"), 0);
510 class_addmethod(pipe_class, (t_method)pipe_clear, gensym("clear"), 0);
511}
512
513void x_time_setup(void)
514{
515 delay_setup();
516 metro_setup();
517 line_setup();
518 timer_setup();
519 pipe_setup();
520}
521/* Copyright (c) 1997-1999 Miller Puckette.
522* For information on usage and redistribution, and for a DISCLAIMER OF ALL
523* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
524
525/* clock objects */
526
527#include "m_pd.h"
528#include <stdio.h>
529/* -------------------------- delay ------------------------------ */
530static t_class *delay_class;
531
532typedef struct _delay
533{
534 t_object x_obj;
535 t_clock *x_clock;
536 double x_deltime;
537} t_delay;
538
539static void delay_bang(t_delay *x)
540{
541 clock_delay(x->x_clock, x->x_deltime);
542}
543
544static void delay_stop(t_delay *x)
545{
546 clock_unset(x->x_clock);
547}
548
549static void delay_ft1(t_delay *x, t_floatarg g)
550{
551 if (g < 0) g = 0;
552 x->x_deltime = g;
553}
554
555static void delay_float(t_delay *x, t_float f)
556{
557 delay_ft1(x, f);
558 delay_bang(x);
559}
560
561static void delay_tick(t_delay *x)
562{
563 outlet_bang(x->x_obj.ob_outlet);
564}
565
566static void delay_free(t_delay *x)
567{
568 clock_free(x->x_clock);
569}
570
571static void *delay_new(t_floatarg f)
572{
573 t_delay *x = (t_delay *)pd_new(delay_class);
574 delay_ft1(x, f);
575 x->x_clock = clock_new(x, (t_method)delay_tick);
576 outlet_new(&x->x_obj, gensym("bang"));
577 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
578 return (x);
579}
580
581static void delay_setup(void)
582{
583 delay_class = class_new(gensym("delay"), (t_newmethod)delay_new,
584 (t_method)delay_free, sizeof(t_delay), 0, A_DEFFLOAT, 0);
585 class_addcreator((t_newmethod)delay_new, gensym("del"), A_DEFFLOAT, 0);
586 class_addbang(delay_class, delay_bang);
587 class_addmethod(delay_class, (t_method)delay_stop, gensym("stop"), 0);
588 class_addmethod(delay_class, (t_method)delay_ft1,
589 gensym("ft1"), A_FLOAT, 0);
590 class_addfloat(delay_class, (t_method)delay_float);
591}
592
593/* -------------------------- metro ------------------------------ */
594static t_class *metro_class;
595
596typedef struct _metro
597{
598 t_object x_obj;
599 t_clock *x_clock;
600 double x_deltime;
601 int x_hit;
602} t_metro;
603
604static void metro_tick(t_metro *x)
605{
606 x->x_hit = 0;
607 outlet_bang(x->x_obj.ob_outlet);
608 if (!x->x_hit) clock_delay(x->x_clock, x->x_deltime);
609}
610
611static void metro_float(t_metro *x, t_float f)
612{
613 if (f != 0) metro_tick(x);
614 else clock_unset(x->x_clock);
615 x->x_hit = 1;
616}
617
618static void metro_bang(t_metro *x)
619{
620 metro_float(x, 1);
621}
622
623static void metro_stop(t_metro *x)
624{
625 metro_float(x, 0);
626}
627
628static void metro_ft1(t_metro *x, t_floatarg g)
629{
630 if (g < 1) g = 1;
631 x->x_deltime = g;
632}
633
634static void metro_free(t_metro *x)
635{
636 clock_free(x->x_clock);
637}
638
639static void *metro_new(t_floatarg f)
640{
641 t_metro *x = (t_metro *)pd_new(metro_class);
642 metro_ft1(x, f);
643 x->x_hit = 0;
644 x->x_clock = clock_new(x, (t_method)metro_tick);
645 outlet_new(&x->x_obj, gensym("bang"));
646 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
647 return (x);
648}
649
650static void metro_setup(void)
651{
652 metro_class = class_new(gensym("metro"), (t_newmethod)metro_new,
653 (t_method)metro_free, sizeof(t_metro), 0, A_DEFFLOAT, 0);
654 class_addbang(metro_class, metro_bang);
655 class_addmethod(metro_class, (t_method)metro_stop, gensym("stop"), 0);
656 class_addmethod(metro_class, (t_method)metro_ft1, gensym("ft1"),
657 A_FLOAT, 0);
658 class_addfloat(metro_class, (t_method)metro_float);
659}
660
661/* -------------------------- line ------------------------------ */
662static t_class *line_class;
663
664typedef struct _line
665{
666 t_object x_obj;
667 t_clock *x_clock;
668 double x_targettime;
669 t_float x_targetval;
670 double x_prevtime;
671 t_float x_setval;
672 int x_gotinlet;
673 t_float x_grain;
674 double x_1overtimediff;
675 double x_in1val;
676} t_line;
677
678static void line_tick(t_line *x)
679{
680 double timenow = clock_getsystime();
681 double msectogo = - clock_gettimesince(x->x_targettime);
682 if (msectogo < 1E-9)
683 {
684 outlet_float(x->x_obj.ob_outlet, x->x_targetval);
685 }
686 else
687 {
688 outlet_float(x->x_obj.ob_outlet,
689 x->x_setval + x->x_1overtimediff * (timenow - x->x_prevtime)
690 * (x->x_targetval - x->x_setval));
691 clock_delay(x->x_clock,
692 (x->x_grain > msectogo ? msectogo : x->x_grain));
693 }
694}
695
696static void line_float(t_line *x, t_float f)
697{
698 double timenow = clock_getsystime();
699 if (x->x_gotinlet && x->x_in1val > 0)
700 {
701 if (timenow > x->x_targettime) x->x_setval = x->x_targetval;
702 else x->x_setval = x->x_setval + x->x_1overtimediff *
703 (timenow - x->x_prevtime)
704 * (x->x_targetval - x->x_setval);
705 x->x_prevtime = timenow;
706 x->x_targettime = clock_getsystimeafter(x->x_in1val);
707 x->x_targetval = f;
708 line_tick(x);
709 x->x_gotinlet = 0;
710 x->x_1overtimediff = 1./ (x->x_targettime - timenow);
711 clock_delay(x->x_clock,
712 (x->x_grain > x->x_in1val ? x->x_in1val : x->x_grain));
713
714 }
715 else
716 {
717 clock_unset(x->x_clock);
718 x->x_targetval = x->x_setval = f;
719 outlet_float(x->x_obj.ob_outlet, f);
720 }
721 x->x_gotinlet = 0;
722}
723
724static void line_ft1(t_line *x, t_floatarg g)
725{
726 x->x_in1val = g;
727 x->x_gotinlet = 1;
728}
729
730static void line_stop(t_line *x)
731{
732 x->x_targetval = x->x_setval;
733 clock_unset(x->x_clock);
734}
735
736static void line_free(t_line *x)
737{
738 clock_free(x->x_clock);
739}
740
741static void *line_new(t_floatarg f, t_floatarg grain)
742{
743 t_line *x = (t_line *)pd_new(line_class);
744 x->x_targetval = x->x_setval = f;
745 x->x_gotinlet = 0;
746 x->x_1overtimediff = 1;
747 x->x_clock = clock_new(x, (t_method)line_tick);
748 x->x_targettime = x->x_prevtime = clock_getsystime();
749 if (grain <= 0) grain = 20;
750 x->x_grain = grain;
751 outlet_new(&x->x_obj, gensym("float"));
752 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
753 return (x);
754}
755
756static void line_setup(void)
757{
758 line_class = class_new(gensym("line"), (t_newmethod)line_new,
759 (t_method)line_free, sizeof(t_line), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
760 class_addmethod(line_class, (t_method)line_ft1,
761 gensym("ft1"), A_FLOAT, 0);
762 class_addmethod(line_class, (t_method)line_stop,
763 gensym("stop"), 0);
764 class_addfloat(line_class, (t_method)line_float);
765}
766
767/* -------------------------- timer ------------------------------ */
768static t_class *timer_class;
769
770typedef struct _timer
771{
772 t_object x_obj;
773 t_time x_settime;
774} t_timer;
775
776static void timer_bang(t_timer *x)
777{
778 x->x_settime = clock_getsystime();
779}
780
781static void timer_bang2(t_timer *x)
782{
783 t_time diff = clock_gettimesince(x->x_settime);
784 outlet_float(x->x_obj.ob_outlet, diff);
785}
786
787static void *timer_new(t_floatarg f)
788{
789 t_timer *x = (t_timer *)pd_new(timer_class);
790 timer_bang(x);
791 outlet_new(&x->x_obj, gensym("float"));
792 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
793 return (x);
794}
795
796static void timer_setup(void)
797{
798 timer_class = class_new(gensym("timer"), (t_newmethod)timer_new, 0,
799 sizeof(t_timer), 0, A_DEFFLOAT, 0);
800 class_addbang(timer_class, timer_bang);
801 class_addmethod(timer_class, (t_method)timer_bang2, gensym("bang2"), 0);
802}
803
804
805/* -------------------------- pipe -------------------------- */
806
807static t_class *pipe_class;
808
809typedef struct _hang
810{
811 t_clock *h_clock;
812 struct _hang *h_next;
813 struct _pipe *h_owner;
814 t_gpointer *h_gp;
815 union word h_vec[1]; /* not the actual number. */
816} t_hang;
817
818typedef struct pipeout
819{
820 t_atom p_atom;
821 t_outlet *p_outlet;
822} t_pipeout;
823
824typedef struct _pipe
825{
826 t_object x_obj;
827 int x_n;
828 int x_nptr;
829 float x_deltime;
830 t_pipeout *x_vec;
831 t_gpointer *x_gp;
832 t_hang *x_hang;
833} t_pipe;
834
835static void *pipe_new(t_symbol *s, int argc, t_atom *argv)
836{
837 t_pipe *x = (t_pipe *)pd_new(pipe_class);
838 t_atom defarg, *ap;
839 t_pipeout *vec, *vp;
840 t_gpointer *gp;
841 int nptr = 0;
842 int i;
843 float deltime;
844 if (argc)
845 {
846 if (argv[argc-1].a_type != A_FLOAT)
847 {
848 char stupid[80];
849 atom_string(&argv[argc-1], stupid, 79);
850 post("pipe: %s: bad time delay value", stupid);
851 deltime = 0;
852 }
853 else deltime = argv[argc-1].a_w.w_float;
854 argc--;
855 }
856 else deltime = 0;
857 if (!argc)
858 {
859 argv = &defarg;
860 argc = 1;
861 SETFLOAT(&defarg, 0);
862 }
863 x->x_n = argc;
864 vec = x->x_vec = (t_pipeout *)getbytes(argc * sizeof(*x->x_vec));
865
866 for (i = argc, ap = argv; i--; ap++)
867 if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p')
868 nptr++;
869
870 gp = x->x_gp = (t_gpointer *)t_getbytes(nptr * sizeof (*gp));
871 x->x_nptr = nptr;
872
873 for (i = 0, vp = vec, ap = argv; i < argc; i++, ap++, vp++)
874 {
875 if (ap->a_type == A_FLOAT)
876 {
877 vp->p_atom = *ap;
878 vp->p_outlet = outlet_new(&x->x_obj, &s_float);
879 if (i) floatinlet_new(&x->x_obj, &vp->p_atom.a_w.w_float);
880 }
881 else if (ap->a_type == A_SYMBOL)
882 {
883 char c = *ap->a_w.w_symbol->s_name;
884 if (c == 's')
885 {
886 SETSYMBOL(&vp->p_atom, &s_symbol);
887 vp->p_outlet = outlet_new(&x->x_obj, &s_symbol);
888 if (i) symbolinlet_new(&x->x_obj, &vp->p_atom.a_w.w_symbol);
889 }
890 else if (c == 'p')
891 {
892 vp->p_atom.a_type = A_POINTER;
893 vp->p_atom.a_w.w_gpointer = gp;
894 gpointer_init(gp);
895 vp->p_outlet = outlet_new(&x->x_obj, &s_pointer);
896 if (i) pointerinlet_new(&x->x_obj, gp);
897 gp++;
898 }
899 else
900 {
901 if (c != 'f') error("pack: %s: bad type",
902 ap->a_w.w_symbol->s_name);
903 SETFLOAT(&vp->p_atom, 0);
904 vp->p_outlet = outlet_new(&x->x_obj, &s_float);
905 if (i) floatinlet_new(&x->x_obj, &vp->p_atom.a_w.w_float);
906 }
907 }
908 }
909 floatinlet_new(&x->x_obj, &x->x_deltime);
910 x->x_hang = 0;
911 x->x_deltime = deltime;
912 return (x);
913}
914
915static void hang_free(t_hang *h)
916{
917 t_pipe *x = h->h_owner;
918 t_gpointer *gp;
919 int i;
920 for (gp = h->h_gp, i = x->x_nptr; i--; gp++)
921 gpointer_unset(gp);
922 freebytes(h->h_gp, x->x_nptr * sizeof(*h->h_gp));
923 clock_free(h->h_clock);
924 freebytes(h, sizeof(*h) + (x->x_n - 1) * sizeof(*h->h_vec));
925}
926
927static void hang_tick(t_hang *h)
928{
929 t_pipe *x = h->h_owner;
930 t_hang *h2, *h3;
931 t_pipeout *p;
932 int i;
933 union word *w;
934 if (x->x_hang == h) x->x_hang = h->h_next;
935 else for (h2 = x->x_hang; h3 = h2->h_next; h2 = h3)
936 {
937 if (h3 == h)
938 {
939 h2->h_next = h3->h_next;
940 break;
941 }
942 }
943 for (i = x->x_n, p = x->x_vec + (x->x_n - 1), w = h->h_vec + (x->x_n - 1);
944 i--; p--, w--)
945 {
946 switch (p->p_atom.a_type)
947 {
948 case A_FLOAT: outlet_float(p->p_outlet, w->w_float); break;
949 case A_SYMBOL: outlet_symbol(p->p_outlet, w->w_symbol); break;
950 case A_POINTER:
951 if (gpointer_check(w->w_gpointer, 1))
952 outlet_pointer(p->p_outlet, w->w_gpointer);
953 else post("pipe: stale pointer");
954 break;
955 }
956 }
957 hang_free(h);
958}
959
960static void pipe_list(t_pipe *x, t_symbol *s, int ac, t_atom *av)
961{
962 t_hang *h = (t_hang *)
963 getbytes(sizeof(*h) + (x->x_n - 1) * sizeof(*h->h_vec));
964 t_gpointer *gp, *gp2;
965 t_pipeout *p;
966 int i, n = x->x_n;
967 t_atom *ap;
968 t_word *w;
969 h->h_gp = (t_gpointer *)getbytes(x->x_nptr * sizeof(t_gpointer));
970 if (ac > n) ac = n;
971 for (i = 0, gp = x->x_gp, p = x->x_vec, ap = av; i < ac;
972 i++, p++, ap++)
973 {
974 switch (p->p_atom.a_type)
975 {
976 case A_FLOAT: p->p_atom.a_w.w_float = atom_getfloat(ap); break;
977 case A_SYMBOL: p->p_atom.a_w.w_symbol = atom_getsymbol(ap); break;
978 case A_POINTER:
979 gpointer_unset(gp);
980 if (ap->a_type != A_POINTER)
981 post("pipe: bad pointer");
982 else
983 {
984 *gp = *(ap->a_w.w_gpointer);
985 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
986 }
987 gp++;
988 }
989 }
990 for (i = 0, gp = x->x_gp, gp2 = h->h_gp, p = x->x_vec, w = h->h_vec;
991 i < n; i++, p++, w++)
992 {
993 if (p->p_atom.a_type == A_POINTER)
994 {
995 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
996 w->w_gpointer = gp2;
997 *gp2++ = *gp++;
998 }
999 else *w = p->p_atom.a_w;
1000 }
1001 h->h_next = x->x_hang;
1002 x->x_hang = h;
1003 h->h_owner = x;
1004 h->h_clock = clock_new(h, (t_method)hang_tick);
1005 clock_delay(h->h_clock, (x->x_deltime >= 0 ? x->x_deltime : 0));
1006}
1007
1008static void pipe_flush(t_pipe *x)
1009{
1010 while (x->x_hang) hang_tick(x->x_hang);
1011}
1012
1013static void pipe_clear(t_pipe *x)
1014{
1015 t_hang *hang;
1016 while (hang = x->x_hang)
1017 {
1018 x->x_hang = hang->h_next;
1019 hang_free(hang);
1020 }
1021}
1022
1023static void pipe_setup(void)
1024{
1025 pipe_class = class_new(gensym("pipe"),
1026 (t_newmethod)pipe_new, (t_method)pipe_clear,
1027 sizeof(t_pipe), 0, A_GIMME, 0);
1028 class_addlist(pipe_class, pipe_list);
1029 class_addmethod(pipe_class, (t_method)pipe_flush, gensym("flush"), 0);
1030 class_addmethod(pipe_class, (t_method)pipe_clear, gensym("clear"), 0);
1031}
1032
1033void x_time_setup(void)
1034{
1035 delay_setup();
1036 metro_setup();
1037 line_setup();
1038 timer_setup();
1039 pipe_setup();
1040}