1 /* Copyright (c) 1997-1999 Miller Puckette and others.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
7 #include "../../pdbox.h"
27 int x_onset
; /* playback position */
30 double x_whenclockset
;
37 static void qlist_tick(t_qlist
*x
);
39 static t_class
*qlist_class
;
41 static void *qlist_new( void)
44 t_symbol
*name
, *filename
= 0;
46 t_qlist
*x
= (t_qlist
*)pd_new(qlist_class
);
47 x
->x_binbuf
= binbuf_new();
48 x
->x_clock
= clock_new(x
, (t_method
)qlist_tick
);
49 outlet_new(&x
->x_ob
, &s_list
);
50 x
->x_bangout
= outlet_new(&x
->x_ob
, &s_bang
);
51 x
->x_onset
= 0x7fffffff;
53 x
->x_whenclockset
= 0;
55 x
->x_canvas
= canvas_getcurrent();
60 static void qlist_rewind(t_qlist
*x
)
63 if (x
->x_clock
) clock_unset(x
->x_clock
);
64 x
->x_whenclockset
= 0;
68 static void qlist_donext(t_qlist
*x
, int drop
, int automatic
)
73 int argc
= binbuf_getnatom(x
->x_binbuf
),
74 count
, onset
= x
->x_onset
, onset2
, wasreentered
;
75 t_atom
*argv
= binbuf_getvec(x
->x_binbuf
);
76 t_atom
*ap
= argv
+ onset
, *ap2
;
77 if (onset
>= argc
) goto end
;
78 while (ap
->a_type
== A_SEMI
|| ap
->a_type
== A_COMMA
)
80 if (ap
->a_type
== A_SEMI
) target
= 0;
82 if (onset
>= argc
) goto end
;
85 if (!target
&& ap
->a_type
== A_FLOAT
)
89 while (onset2
< argc
&& ap2
->a_type
== A_FLOAT
)
94 clock_delay(x
->x_clock
,
95 x
->x_clockdelay
= ap
->a_w
.w_float
* x
->x_tempo
);
96 x
->x_whenclockset
= clock_getsystime();
98 else outlet_list(x
->x_ob
.ob_outlet
, 0, onset2
-onset
, ap
);
103 while (onset2
< argc
&&
104 (ap2
->a_type
== A_FLOAT
|| ap2
->a_type
== A_SYMBOL
))
107 count
= onset2
- onset
;
110 if (ap
->a_type
!= A_SYMBOL
) continue;
111 else if (!(target
= ap
->a_w
.w_symbol
->s_thing
))
113 error("qlist: %s: no such object", ap
->a_w
.w_symbol
->s_name
);
125 wasreentered
= x
->x_reentered
;
129 if (ap
->a_type
== A_FLOAT
)
130 typedmess(target
, &s_list
, count
, ap
);
131 else if (ap
->a_type
== A_SYMBOL
)
132 typedmess(target
, ap
->a_w
.w_symbol
, count
-1, ap
+1);
136 x
->x_reentered
= wasreentered
;
137 } /* while (1); never falls through */
140 x
->x_onset
= 0x7fffffff;
141 outlet_bang(x
->x_bangout
);
142 x
->x_whenclockset
= 0;
145 static void qlist_next(t_qlist
*x
, t_floatarg drop
)
147 qlist_donext(x
, drop
!= 0, 0);
150 static void qlist_bang(t_qlist
*x
)
153 qlist_donext(x
, 0, 1);
156 static void qlist_tick(t_qlist
*x
)
158 x
->x_whenclockset
= 0;
159 qlist_donext(x
, 0, 1);
162 static void qlist_add(t_qlist
*x
, t_symbol
*s
, int ac
, t_atom
*av
)
169 binbuf_add(x
->x_binbuf
, ac
, av
);
170 binbuf_add(x
->x_binbuf
, 1, &a
);
173 static void qlist_add2(t_qlist
*x
, t_symbol
*s
, int ac
, t_atom
*av
)
178 binbuf_add(x
->x_binbuf
, ac
, av
);
181 static void qlist_clear(t_qlist
*x
)
184 binbuf_clear(x
->x_binbuf
);
187 static void qlist_set(t_qlist
*x
, t_symbol
*s
, int ac
, t_atom
*av
)
190 qlist_add(x
, s
, ac
, av
);
193 static void qlist_read(t_qlist
*x
, t_symbol
*filename
, t_symbol
*format
)
196 if (!strcmp(format
->s_name
, "cr"))
198 else if (*format
->s_name
)
199 error("qlist_read: unknown flag: %s", format
->s_name
);
201 if (binbuf_read_via_path(x
->x_binbuf
, filename
->s_name
,
202 canvas_getdir(x
->x_canvas
)->s_name
, cr
))
203 error("%s: read failed", filename
->s_name
);
204 x
->x_onset
= 0x7fffffff;
208 static void qlist_write(t_qlist
*x
, t_symbol
*filename
, t_symbol
*format
)
211 char buf
[MAXPDSTRING
];
212 canvas_makefilename(x
->x_canvas
, filename
->s_name
,
214 if (!strcmp(format
->s_name
, "cr"))
216 else if (*format
->s_name
)
217 error("qlist_read: unknown flag: %s", format
->s_name
);
218 if (binbuf_write(x
->x_binbuf
, buf
, "", cr
))
219 error("%s: write failed", filename
->s_name
);
222 static void qlist_print(t_qlist
*x
)
224 post("--------- textfile or qlist contents: -----------");
225 binbuf_print(x
->x_binbuf
);
228 static void qlist_tempo(t_qlist
*x
, t_float f
)
231 if (f
< 1e-20) f
= 1e-20;
232 else if (f
> 1e20
) f
= 1e20
;
234 if (x
->x_whenclockset
!= 0)
236 float elapsed
= clock_gettimesince(x
->x_whenclockset
);
237 float left
= x
->x_clockdelay
- elapsed
;
238 if (left
< 0) left
= 0;
239 left
*= newtempo
/ x
->x_tempo
;
240 clock_delay(x
->x_clock
, left
);
242 x
->x_tempo
= newtempo
;
245 static void qlist_free(t_qlist
*x
)
247 binbuf_free(x
->x_binbuf
);
248 if (x
->x_clock
) clock_free(x
->x_clock
);
251 /* -------------------- textfile ------------------------------- */
253 static t_class
*textfile_class
;
254 typedef t_qlist t_textfile
;
256 static void *textfile_new( void)
259 t_symbol
*name
, *filename
= 0;
261 t_textfile
*x
= (t_textfile
*)pd_new(textfile_class
);
262 x
->x_binbuf
= binbuf_new();
263 outlet_new(&x
->x_ob
, &s_list
);
264 x
->x_bangout
= outlet_new(&x
->x_ob
, &s_bang
);
265 x
->x_onset
= 0x7fffffff;
268 x
->x_whenclockset
= 0;
271 x
->x_canvas
= canvas_getcurrent();
275 static void textfile_bang(t_textfile
*x
)
277 int argc
= binbuf_getnatom(x
->x_binbuf
),
279 onset
= x
->x_onset
, onset2
;
281 count
, onset
= x
->x_onset
, onset2
;
283 t_atom
*argv
= binbuf_getvec(x
->x_binbuf
);
284 t_atom
*ap
= argv
+ onset
, *ap2
;
285 while (onset
< argc
&&
286 (ap
->a_type
== A_SEMI
|| ap
->a_type
== A_COMMA
))
290 while (onset2
< argc
&&
291 (ap2
->a_type
!= A_SEMI
&& ap2
->a_type
!= A_COMMA
))
296 if (ap
->a_type
== A_SYMBOL
)
297 outlet_anything(x
->x_ob
.ob_outlet
, ap
->a_w
.w_symbol
,
298 onset2
-onset
-1, ap
+1);
299 else outlet_list(x
->x_ob
.ob_outlet
, 0, onset2
-onset
, ap
);
303 x
->x_onset
= 0x7fffffff;
304 outlet_bang(x
->x_bangout
);
308 static void textfile_rewind(t_qlist
*x
)
313 static void textfile_free(t_textfile
*x
)
315 binbuf_free(x
->x_binbuf
);
318 /* ---------------- global setup function -------------------- */
320 void x_qlist_setup(void )
322 qlist_class
= class_new(gensym("qlist"), (t_newmethod
)qlist_new
,
323 (t_method
)qlist_free
, sizeof(t_qlist
), 0, 0);
324 class_addmethod(qlist_class
, (t_method
)qlist_rewind
, gensym("rewind"), 0);
325 class_addmethod(qlist_class
, (t_method
)qlist_next
,
326 gensym("next"), A_DEFFLOAT
, 0);
327 class_addmethod(qlist_class
, (t_method
)qlist_set
, gensym("set"),
329 class_addmethod(qlist_class
, (t_method
)qlist_clear
, gensym("clear"), 0);
330 class_addmethod(qlist_class
, (t_method
)qlist_add
, gensym("add"),
332 class_addmethod(qlist_class
, (t_method
)qlist_add2
, gensym("add2"),
334 class_addmethod(qlist_class
, (t_method
)qlist_add
, gensym("append"),
336 class_addmethod(qlist_class
, (t_method
)qlist_read
, gensym("read"),
337 A_SYMBOL
, A_DEFSYM
, 0);
338 class_addmethod(qlist_class
, (t_method
)qlist_write
, gensym("write"),
339 A_SYMBOL
, A_DEFSYM
, 0);
340 class_addmethod(qlist_class
, (t_method
)qlist_print
, gensym("print"),
342 class_addmethod(qlist_class
, (t_method
)qlist_tempo
,
343 gensym("tempo"), A_FLOAT
, 0);
344 class_addbang(qlist_class
, qlist_bang
);
346 textfile_class
= class_new(gensym("textfile"), (t_newmethod
)textfile_new
,
347 (t_method
)textfile_free
, sizeof(t_textfile
), 0, 0);
348 class_addmethod(textfile_class
, (t_method
)textfile_rewind
, gensym("rewind"),
350 class_addmethod(textfile_class
, (t_method
)qlist_set
, gensym("set"),
352 class_addmethod(textfile_class
, (t_method
)qlist_clear
, gensym("clear"), 0);
353 class_addmethod(textfile_class
, (t_method
)qlist_add
, gensym("add"),
355 class_addmethod(textfile_class
, (t_method
)qlist_add2
, gensym("add2"),
357 class_addmethod(textfile_class
, (t_method
)qlist_add
, gensym("append"),
359 class_addmethod(textfile_class
, (t_method
)qlist_read
, gensym("read"),
360 A_SYMBOL
, A_DEFSYM
, 0);
361 class_addmethod(textfile_class
, (t_method
)qlist_write
, gensym("write"),
362 A_SYMBOL
, A_DEFSYM
, 0);
363 class_addmethod(textfile_class
, (t_method
)qlist_print
, gensym("print"),
365 class_addbang(textfile_class
, textfile_bang
);