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

« back to all changes in this revision

Viewing changes to src/x_qlist.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 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.  */
 
4
 
 
5
#include "m_pd.h"
 
6
#include <string.h>
 
7
#ifdef UNISTD
 
8
#include <unistd.h>
 
9
#endif
 
10
#ifdef MSW
 
11
#include <io.h>
 
12
#endif
 
13
 
 
14
typedef struct _qlist
 
15
{
 
16
    t_object x_ob;
 
17
    t_outlet *x_bangout;
 
18
    void *x_binbuf;
 
19
    int x_onset;                /* playback position */
 
20
    t_clock *x_clock;
 
21
    t_float x_tempo;
 
22
    double x_whenclockset;
 
23
    t_float x_clockdelay;
 
24
    t_symbol *x_dir;
 
25
    t_canvas *x_canvas;
 
26
    int x_reentered;
 
27
} t_qlist;
 
28
 
 
29
static void qlist_tick(t_qlist *x);
 
30
 
 
31
static t_class *qlist_class;
 
32
 
 
33
static void *qlist_new( void)
 
34
{
 
35
    t_symbol *name, *filename = 0;
 
36
    t_qlist *x = (t_qlist *)pd_new(qlist_class);
 
37
    x->x_binbuf = binbuf_new();
 
38
    x->x_clock = clock_new(x, (t_method)qlist_tick);
 
39
    outlet_new(&x->x_ob, &s_list);
 
40
    x->x_bangout = outlet_new(&x->x_ob, &s_bang);
 
41
    x->x_onset = 0x7fffffff;
 
42
    x->x_tempo = 1;
 
43
    x->x_whenclockset = 0;
 
44
    x->x_clockdelay = 0;
 
45
    x->x_canvas = canvas_getcurrent();
 
46
    x->x_reentered = 0;
 
47
    return (x);
 
48
}
 
49
 
 
50
static void qlist_rewind(t_qlist *x)
 
51
{
 
52
    x->x_onset = 0;
 
53
    if (x->x_clock) clock_unset(x->x_clock);
 
54
    x->x_whenclockset = 0;
 
55
    x->x_reentered = 1;
 
56
}
 
57
 
 
58
static void qlist_donext(t_qlist *x, int drop, int automatic)
 
59
{
 
60
    t_pd *target = 0;
 
61
    while (1)
 
62
    {
 
63
        int argc = binbuf_getnatom(x->x_binbuf),
 
64
            count, onset = x->x_onset, onset2, wasreentered;
 
65
        t_atom *argv = binbuf_getvec(x->x_binbuf);
 
66
        t_atom *ap = argv + onset, *ap2;
 
67
        if (onset >= argc) goto end;
 
68
        while (ap->a_type == A_SEMI || ap->a_type == A_COMMA)
 
69
        {
 
70
            if (ap->a_type == A_SEMI) target = 0;
 
71
            onset++, ap++;
 
72
            if (onset >= argc) goto end;
 
73
        }
 
74
 
 
75
        if (!target && ap->a_type == A_FLOAT)
 
76
        {
 
77
            ap2 = ap + 1;
 
78
            onset2 = onset + 1;
 
79
            while (onset2 < argc && ap2->a_type == A_FLOAT)
 
80
                onset2++, ap2++;
 
81
            x->x_onset = onset2;
 
82
            if (automatic)
 
83
            {
 
84
                clock_delay(x->x_clock,
 
85
                    x->x_clockdelay = ap->a_w.w_float * x->x_tempo);
 
86
                x->x_whenclockset = clock_getsystime();
 
87
            }
 
88
            else outlet_list(x->x_ob.ob_outlet, 0, onset2-onset, ap);
 
89
            return;
 
90
        }
 
91
        ap2 = ap + 1;
 
92
        onset2 = onset + 1;
 
93
        while (onset2 < argc &&
 
94
            (ap2->a_type == A_FLOAT || ap2->a_type == A_SYMBOL))
 
95
                onset2++, ap2++;
 
96
        x->x_onset = onset2;
 
97
        count = onset2 - onset;
 
98
        if (!target)
 
99
        {
 
100
            if (ap->a_type != A_SYMBOL) continue;
 
101
            else if (!(target = ap->a_w.w_symbol->s_thing))
 
102
            {
 
103
                pd_error(x, "qlist: %s: no such object",
 
104
                    ap->a_w.w_symbol->s_name);
 
105
                continue;
 
106
            }
 
107
            ap++;
 
108
            onset++;
 
109
            count--;
 
110
            if (!count) 
 
111
            {
 
112
                x->x_onset = onset2;
 
113
                continue;
 
114
            }
 
115
        }
 
116
        wasreentered = x->x_reentered;
 
117
        x->x_reentered = 0;
 
118
        if (!drop)
 
119
        {   
 
120
            if (ap->a_type == A_FLOAT)
 
121
                typedmess(target, &s_list, count, ap);
 
122
            else if (ap->a_type == A_SYMBOL)
 
123
                typedmess(target, ap->a_w.w_symbol, count-1, ap+1);
 
124
        }
 
125
        if (x->x_reentered)
 
126
            return;
 
127
        x->x_reentered = wasreentered;
 
128
    }  /* while (1); never falls through */
 
129
 
 
130
end:
 
131
    x->x_onset = 0x7fffffff;
 
132
    outlet_bang(x->x_bangout);
 
133
    x->x_whenclockset = 0;
 
134
}
 
135
 
 
136
static void qlist_next(t_qlist *x, t_floatarg drop)
 
137
{
 
138
    qlist_donext(x, drop != 0, 0);
 
139
}
 
140
 
 
141
static void qlist_bang(t_qlist *x)
 
142
{
 
143
    qlist_rewind(x);
 
144
    qlist_donext(x, 0, 1);
 
145
}
 
146
 
 
147
static void qlist_tick(t_qlist *x)
 
148
{
 
149
    x->x_whenclockset = 0;
 
150
    qlist_donext(x, 0, 1);
 
151
}
 
152
 
 
153
static void qlist_add(t_qlist *x, t_symbol *s, int ac, t_atom *av)
 
154
{
 
155
    t_atom a;
 
156
    SETSEMI(&a);
 
157
    binbuf_add(x->x_binbuf, ac, av);
 
158
    binbuf_add(x->x_binbuf, 1, &a);
 
159
}
 
160
 
 
161
static void qlist_add2(t_qlist *x, t_symbol *s, int ac, t_atom *av)
 
162
{
 
163
    binbuf_add(x->x_binbuf, ac, av);
 
164
}
 
165
 
 
166
static void qlist_clear(t_qlist *x)
 
167
{
 
168
    qlist_rewind(x);
 
169
    binbuf_clear(x->x_binbuf);
 
170
}
 
171
 
 
172
static void qlist_set(t_qlist *x, t_symbol *s, int ac, t_atom *av)
 
173
{
 
174
    qlist_clear(x);
 
175
    qlist_add(x, s, ac, av);
 
176
}
 
177
 
 
178
static void qlist_read(t_qlist *x, t_symbol *filename, t_symbol *format)
 
179
{
 
180
    int cr = 0;
 
181
    if (!strcmp(format->s_name, "cr"))
 
182
        cr = 1;
 
183
    else if (*format->s_name)
 
184
        pd_error(x, "qlist_read: unknown flag: %s", format->s_name);
 
185
 
 
186
    if (binbuf_read_via_canvas(x->x_binbuf, filename->s_name, x->x_canvas, cr))
 
187
            pd_error(x, "%s: read failed", filename->s_name);
 
188
    x->x_onset = 0x7fffffff;
 
189
    x->x_reentered = 1;
 
190
}
 
191
 
 
192
static void qlist_write(t_qlist *x, t_symbol *filename, t_symbol *format)
 
193
{
 
194
    int cr = 0;
 
195
    char buf[MAXPDSTRING];
 
196
    canvas_makefilename(x->x_canvas, filename->s_name,
 
197
        buf, MAXPDSTRING);
 
198
    if (!strcmp(format->s_name, "cr"))
 
199
        cr = 1;
 
200
    else if (*format->s_name)
 
201
        pd_error(x, "qlist_read: unknown flag: %s", format->s_name);
 
202
    if (binbuf_write(x->x_binbuf, buf, "", cr))
 
203
            pd_error(x, "%s: write failed", filename->s_name);
 
204
}
 
205
 
 
206
static void qlist_print(t_qlist *x)
 
207
{
 
208
    post("--------- textfile or qlist contents: -----------");
 
209
    binbuf_print(x->x_binbuf);
 
210
}
 
211
 
 
212
static void qlist_tempo(t_qlist *x, t_float f)
 
213
{
 
214
    t_float newtempo;
 
215
    if (f < 1e-20) f = 1e-20;
 
216
    else if (f > 1e20) f = 1e20;
 
217
    newtempo = 1./f;
 
218
    if (x->x_whenclockset != 0)
 
219
    {
 
220
        t_float elapsed = clock_gettimesince(x->x_whenclockset);
 
221
        t_float left = x->x_clockdelay - elapsed;
 
222
        if (left < 0) left = 0;
 
223
        left *= newtempo / x->x_tempo;
 
224
        clock_delay(x->x_clock, left);
 
225
    }
 
226
    x->x_tempo = newtempo;
 
227
}
 
228
 
 
229
static void qlist_free(t_qlist *x)
 
230
{
 
231
    binbuf_free(x->x_binbuf);
 
232
    if (x->x_clock) clock_free(x->x_clock);
 
233
}
 
234
 
 
235
/* -------------------- textfile ------------------------------- */
 
236
 
 
237
static t_class *textfile_class;
 
238
typedef t_qlist t_textfile;
 
239
 
 
240
static void *textfile_new( void)
 
241
{
 
242
    t_symbol *name, *filename = 0;
 
243
    t_textfile *x = (t_textfile *)pd_new(textfile_class);
 
244
    x->x_binbuf = binbuf_new();
 
245
    outlet_new(&x->x_ob, &s_list);
 
246
    x->x_bangout = outlet_new(&x->x_ob, &s_bang);
 
247
    x->x_onset = 0x7fffffff;
 
248
    x->x_reentered = 0;
 
249
    x->x_tempo = 1;
 
250
    x->x_whenclockset = 0;
 
251
    x->x_clockdelay = 0;
 
252
    x->x_clock = NULL;
 
253
    x->x_canvas = canvas_getcurrent();
 
254
    return (x);
 
255
}
 
256
 
 
257
static void textfile_bang(t_textfile *x)
 
258
{
 
259
    int argc = binbuf_getnatom(x->x_binbuf),
 
260
        count, onset = x->x_onset, onset2;
 
261
    t_atom *argv = binbuf_getvec(x->x_binbuf);
 
262
    t_atom *ap = argv + onset, *ap2;
 
263
    while (onset < argc &&
 
264
        (ap->a_type == A_SEMI || ap->a_type == A_COMMA))
 
265
            onset++, ap++;
 
266
    onset2 = onset;
 
267
    ap2 = ap;
 
268
    while (onset2 < argc &&
 
269
        (ap2->a_type != A_SEMI && ap2->a_type != A_COMMA))
 
270
            onset2++, ap2++;
 
271
    if (onset2 > onset)
 
272
    {
 
273
        x->x_onset = onset2;
 
274
        if (ap->a_type == A_SYMBOL)
 
275
            outlet_anything(x->x_ob.ob_outlet, ap->a_w.w_symbol,
 
276
                onset2-onset-1, ap+1);
 
277
        else outlet_list(x->x_ob.ob_outlet, 0, onset2-onset, ap);
 
278
    }
 
279
    else
 
280
    {
 
281
        x->x_onset = 0x7fffffff;
 
282
        outlet_bang(x->x_bangout);
 
283
    }
 
284
}
 
285
 
 
286
static void textfile_rewind(t_qlist *x)
 
287
{
 
288
    x->x_onset = 0;
 
289
}
 
290
 
 
291
static void textfile_free(t_textfile *x)
 
292
{
 
293
    binbuf_free(x->x_binbuf);
 
294
}
 
295
 
 
296
/* ---------------- global setup function -------------------- */
 
297
 
 
298
void x_qlist_setup(void )
 
299
{
 
300
    qlist_class = class_new(gensym("qlist"), (t_newmethod)qlist_new,
 
301
        (t_method)qlist_free, sizeof(t_qlist), 0, 0);
 
302
    class_addmethod(qlist_class, (t_method)qlist_rewind, gensym("rewind"), 0);
 
303
    class_addmethod(qlist_class, (t_method)qlist_next,
 
304
        gensym("next"), A_DEFFLOAT, 0);  
 
305
    class_addmethod(qlist_class, (t_method)qlist_set, gensym("set"),
 
306
        A_GIMME, 0);
 
307
    class_addmethod(qlist_class, (t_method)qlist_clear, gensym("clear"), 0);
 
308
    class_addmethod(qlist_class, (t_method)qlist_add, gensym("add"),
 
309
        A_GIMME, 0);
 
310
    class_addmethod(qlist_class, (t_method)qlist_add2, gensym("add2"),
 
311
        A_GIMME, 0);
 
312
    class_addmethod(qlist_class, (t_method)qlist_add, gensym("append"),
 
313
        A_GIMME, 0);
 
314
    class_addmethod(qlist_class, (t_method)qlist_read, gensym("read"),
 
315
        A_SYMBOL, A_DEFSYM, 0);
 
316
    class_addmethod(qlist_class, (t_method)qlist_write, gensym("write"),
 
317
        A_SYMBOL, A_DEFSYM, 0);
 
318
    class_addmethod(qlist_class, (t_method)qlist_print, gensym("print"),
 
319
        A_DEFSYM, 0);
 
320
    class_addmethod(qlist_class, (t_method)qlist_tempo,
 
321
        gensym("tempo"), A_FLOAT, 0);
 
322
    class_addbang(qlist_class, qlist_bang);
 
323
 
 
324
    textfile_class = class_new(gensym("textfile"), (t_newmethod)textfile_new,
 
325
        (t_method)textfile_free, sizeof(t_textfile), 0, 0);
 
326
    class_addmethod(textfile_class, (t_method)textfile_rewind, gensym("rewind"),
 
327
        0);
 
328
    class_addmethod(textfile_class, (t_method)qlist_set, gensym("set"),
 
329
        A_GIMME, 0);
 
330
    class_addmethod(textfile_class, (t_method)qlist_clear, gensym("clear"), 0);
 
331
    class_addmethod(textfile_class, (t_method)qlist_add, gensym("add"),
 
332
        A_GIMME, 0);
 
333
    class_addmethod(textfile_class, (t_method)qlist_add2, gensym("add2"),
 
334
        A_GIMME, 0);
 
335
    class_addmethod(textfile_class, (t_method)qlist_add, gensym("append"),
 
336
        A_GIMME, 0);
 
337
    class_addmethod(textfile_class, (t_method)qlist_read, gensym("read"), 
 
338
        A_SYMBOL, A_DEFSYM, 0);
 
339
    class_addmethod(textfile_class, (t_method)qlist_write, gensym("write"), 
 
340
        A_SYMBOL, A_DEFSYM, 0);
 
341
    class_addmethod(textfile_class, (t_method)qlist_print, gensym("print"),
 
342
        A_DEFSYM, 0);
 
343
    class_addbang(textfile_class, textfile_bang);
 
344
}
 
345