~ubuntu-branches/ubuntu/utopic/glame/utopic

« back to all changes in this revision

Viewing changes to src/filter/filter_param.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-09 17:14:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020409171412-jzpnov7mbz2w6zsr
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * filter_param.c
 
3
 * $Id: filter_param.c,v 1.16 2001/11/18 14:48:09 richi Exp $
 
4
 *
 
5
 * Copyright (C) 2000 Richard Guenther
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 *
 
21
 */
 
22
 
 
23
#include <string.h>
 
24
#include "gldb_string.h"
 
25
#include "filter.h"
 
26
#include "filter_param.h"
 
27
 
 
28
 
 
29
#define ITEM(p) (&(p)->entry)
 
30
#define PARAM(i) ((filter_param_t *)(i))
 
31
 
 
32
static int default_set(filter_param_t *p, const void *val)
 
33
{
 
34
        return 0;
 
35
}
 
36
 
 
37
static int redirect_set(filter_param_t *param, const void *val)
 
38
{
 
39
        filter_t *node, *n;
 
40
        const char *map_node, *map_label;
 
41
        filter_param_t *p;
 
42
 
 
43
        /* pipe parameter setting does not go through the wrapped funcs */
 
44
        node = filterparam_filter(param);
 
45
        map_node = filterparam_get_property(param, FILTERPARAM_MAP_NODE);
 
46
        map_label = filterparam_get_property(param, FILTERPARAM_MAP_LABEL);
 
47
        if (!node || !map_node || !map_label)
 
48
                return -1;
 
49
 
 
50
        if (!(n = filter_get_node(node, map_node))) {
 
51
                DPRINTF("No such node %s\n", map_node);
 
52
                return -1;
 
53
        }
 
54
        if (!(p = filterparamdb_get_param(filter_paramdb(n), map_label))) {
 
55
                DPRINTF("No such param %s\n", map_label);
 
56
                return -1;
 
57
        }
 
58
        return filterparam_set(p, val);
 
59
}
 
60
 
 
61
 
 
62
static filter_param_t *paramdb_alloc_item()
 
63
{
 
64
        filter_param_t *p;
 
65
 
 
66
        if (!(p = ALLOC(filter_param_t)))
 
67
                return NULL;
 
68
        gldb_init_item(&p->entry);
 
69
        glsdb_init(&p->properties);
 
70
        INIT_GLSIG_EMITTER(&p->emitter);
 
71
        p->set = default_set;
 
72
        p->type = -1;
 
73
 
 
74
        return p;
 
75
}
 
76
 
 
77
static void paramdb_op_delete(gldb_item_t *item)
 
78
{
 
79
        filter_param_t *p = PARAM(item);
 
80
 
 
81
        /* Emit PARAM_DELETED signal. */
 
82
        glsig_emit(&p->emitter, GLSIG_PARAM_DELETED, p);
 
83
 
 
84
        glsdb_delete(&p->properties);
 
85
        if (FILTER_PARAM_IS_STRING(p))
 
86
                free(p->u.string);
 
87
        else if (FILTER_PARAM_IS_BUF(p))
 
88
                fbuf_unref(p->u.buf);
 
89
 
 
90
        /* Notify the associated filter of the change. */
 
91
        glsig_emit(&p->emitter, GLSIG_FILTER_CHANGED,
 
92
                   ((filter_paramdb_t *)p->entry.db)->node);
 
93
        glsig_delete_all(&p->emitter);
 
94
}
 
95
 
 
96
static gldb_item_t *paramdb_op_copy(gldb_item_t *source)
 
97
{
 
98
        filter_param_t *d;
 
99
        filter_param_t *s = PARAM(source);
 
100
 
 
101
        if (!(d = paramdb_alloc_item()))
 
102
                return NULL;
 
103
        d->set = s->set;
 
104
        d->type = s->type;
 
105
 
 
106
        if (FILTER_PARAM_IS_STRING(s)) {
 
107
                d->u.string = s->u.string ? strdup(s->u.string) : NULL;
 
108
        } else if (FILTER_PARAM_IS_BUF(s)) {
 
109
                fbuf_ref(s->u.buf);
 
110
                d->u.buf = s->u.buf;
 
111
        } else {
 
112
                memcpy(&d->u, &s->u, sizeof(s->u));
 
113
        }
 
114
 
 
115
        /* copy property db */
 
116
        glsdb_copy(&d->properties, &s->properties);
 
117
 
 
118
        /* copy signal handlers - not the redirectors. */
 
119
        glsig_copy_handlers(&d->emitter, &s->emitter);
 
120
 
 
121
        return ITEM(d);
 
122
}
 
123
 
 
124
static int paramdb_op_add(gldb_t *db, gldb_item_t *i, gldb_item_t *dest)
 
125
{
 
126
        filter_param_t *p = PARAM(i);
 
127
        glsig_handler_t *h;
 
128
 
 
129
        /* We can and should not try to do anything with
 
130
         * items of a db with no node associated -- we even fail for this now. */
 
131
        if (!((filter_paramdb_t *)p->entry.db)->node)
 
132
                DERROR("NULL node in parameters database\n");
 
133
 
 
134
        /* The task is to fix the signal redirector which
 
135
         * is probably attached to the item - or just to
 
136
         * add a new "right" one. -- now there should be no such there! [121200] */
 
137
        glame_list_foreach(&p->emitter.handlers, glsig_handler_t, list, h) {
 
138
                if (h->priv == (void *)&((filter_paramdb_t *)p->entry.db)->node->emitter)
 
139
                        DERROR("redirector got copied?");
 
140
        }
 
141
        glsig_add_redirector(&p->emitter, ~0,
 
142
                             &((filter_paramdb_t *)p->entry.db)->node->emitter);
 
143
        return 0;
 
144
}
 
145
 
 
146
static struct gldb_ops ops = { paramdb_op_delete,
 
147
                               paramdb_op_copy,
 
148
                               paramdb_op_add };
 
149
 
 
150
 
 
151
static filter_param_t *_filterparamdb_add_param(filter_paramdb_t *db,
 
152
                                                const char *label, int type,
 
153
                                                const void *val, va_list va)
 
154
{
 
155
        filter_param_t *p;
 
156
        gldb_item_t *i;
 
157
        const char *key, *prop;
 
158
 
 
159
        if (!db || FILTER_IS_PLUGIN(db->node) || !label || !val)
 
160
                return NULL;
 
161
 
 
162
        if ((i = gldb_query_item(&db->db, label)))
 
163
                return NULL;
 
164
        if (!(p = paramdb_alloc_item()))
 
165
                return NULL;
 
166
 
 
167
        p->type = type;
 
168
        if (FILTER_PARAM_IS_INT(p)) {
 
169
                p->u.i = *(int *)val;
 
170
        } else if (FILTER_PARAM_IS_FLOAT(p)) {
 
171
                p->u.f = *(float *)val;
 
172
        } else if (FILTER_PARAM_IS_SAMPLE(p)) {
 
173
                p->u.sample = *(SAMPLE *)val;
 
174
        } else if (FILTER_PARAM_IS_STRING(p)) {
 
175
                p->u.string = *(const char **)val ? strdup(*(const char **)val) : NULL;
 
176
        } else if (FILTER_PARAM_IS_POS(p)) {
 
177
                p->u.pos = *(long *)val;
 
178
        } else if (FILTER_PARAM_IS_BUF(p)) {
 
179
                p->u.buf = *(filter_buffer_t **)val;
 
180
        }
 
181
 
 
182
        if (gldb_add_item(&db->db, ITEM(p), label) == -1) {
 
183
                paramdb_op_delete(ITEM(p));
 
184
                return NULL;
 
185
        }
 
186
 
 
187
        /* Process the va and add the specified key/value pairs
 
188
         * to the property database. */
 
189
        while ((key = va_arg(va, const char *)) != FILTERPARAM_END) {
 
190
                prop = va_arg(va, const char *);
 
191
                filterparam_set_property(p, key, prop);
 
192
        }
 
193
 
 
194
        /* Notify the associated filter of the change. */
 
195
        glsig_emit(&p->emitter, GLSIG_FILTER_CHANGED,
 
196
                   ((filter_paramdb_t *)p->entry.db)->node);
 
197
 
 
198
        return p;
 
199
}
 
200
 
 
201
 
 
202
 
 
203
/* API stuff.
 
204
 */
 
205
 
 
206
void filterparamdb_init(filter_paramdb_t *db, filter_t *node)
 
207
{
 
208
        gldb_init(&db->db, &ops);
 
209
        db->node = node;
 
210
}
 
211
 
 
212
 
 
213
/* DB part. */
 
214
 
 
215
filter_param_t *filterparamdb_add_param(filter_paramdb_t *db,
 
216
                                        const char *label,
 
217
                                        int type, const void *val, ...)
 
218
{
 
219
        filter_param_t *p;
 
220
        va_list va;
 
221
 
 
222
        va_start(va, val);
 
223
        p = _filterparamdb_add_param(db, label, type, val, va);
 
224
        va_end(va);
 
225
 
 
226
        return p;
 
227
}
 
228
filter_param_t *filterparamdb_add_param_int(filter_paramdb_t *db,
 
229
                                            const char *label,
 
230
                                            int type, int val, ...)
 
231
{
 
232
        filter_param_t *p;
 
233
        va_list va;
 
234
 
 
235
        va_start(va, val);
 
236
        p = _filterparamdb_add_param(db, label, type, &val, va);
 
237
        va_end(va);
 
238
 
 
239
        return p;
 
240
}
 
241
filter_param_t *filterparamdb_add_param_float(filter_paramdb_t *db,
 
242
                                              const char *label,
 
243
                                              int type, float val, ...)
 
244
{
 
245
        filter_param_t *p;
 
246
        va_list va;
 
247
 
 
248
        va_start(va, val);
 
249
        p = _filterparamdb_add_param(db, label, type, &val, va);
 
250
        va_end(va);
 
251
 
 
252
        return p;
 
253
}
 
254
filter_param_t *filterparamdb_add_param_string(filter_paramdb_t *db,
 
255
                                               const char *label,
 
256
                                               int type, const char *val, ...)
 
257
{
 
258
        filter_param_t *p;
 
259
        va_list va;
 
260
 
 
261
        va_start(va, val);
 
262
        p = _filterparamdb_add_param(db, label, type, &val, va);
 
263
        va_end(va);
 
264
 
 
265
        return p;
 
266
}
 
267
static filter_param_t *_filterparamdb_add_param_pos(filter_paramdb_t *db, ...)
 
268
{
 
269
        filter_param_t *p;
 
270
        va_list va;
 
271
        long val = 0;
 
272
 
 
273
        va_start(va, db);
 
274
        p = _filterparamdb_add_param(db, FILTERPARAM_LABEL_POS,
 
275
                                     FILTER_PARAMTYPE_POS, &val, va);
 
276
        va_end(va);
 
277
 
 
278
        return p;
 
279
}
 
280
filter_param_t *filterparamdb_add_param_pos(filter_paramdb_t *db)
 
281
{
 
282
        return _filterparamdb_add_param_pos(db, FILTERPARAM_END);
 
283
}
 
284
 
 
285
filter_param_t *filterparamdb_get_param(filter_paramdb_t *db,
 
286
                                        const char *label)
 
287
{
 
288
        gldb_item_t *i;
 
289
 
 
290
        if (!db || !label)
 
291
                return NULL;
 
292
 
 
293
        if (!(i = gldb_query_item(&db->db, label)))
 
294
                return NULL;
 
295
        return PARAM(i);
 
296
}
 
297
 
 
298
void filterparamdb_delete_param(filter_paramdb_t *db, const char *label)
 
299
{
 
300
        gldb_item_t *i;
 
301
 
 
302
        if (!db || !label)
 
303
                return;
 
304
 
 
305
        if (!(i = gldb_query_item(&db->db, label)))
 
306
                return;
 
307
        gldb_delete_item(i);
 
308
}
 
309
 
 
310
char *filterparamdb_to_string(filter_paramdb_t *pdb, int props)
 
311
{
 
312
        filter_param_t *param;
 
313
        char *val;
 
314
        char *buf, *b;
 
315
 
 
316
        buf = b = alloca(64*1024); /* Wheee... */
 
317
 
 
318
        b += sprintf(b,
 
319
"(lambda (pdb)\n"
 
320
"  (let* ((params (map (lambda (param)\n"
 
321
"                        (cons (param-label param) param))\n"
 
322
"                      pdb))\n"
 
323
"         (pairs (map (lambda (spec)\n"
 
324
"                       (let ((p (assoc (car spec) params)))\n"
 
325
"                            (if p\n"
 
326
"                              (cons (cdr p) (cdr spec))\n"
 
327
"                              (throw 'glame-error))))\n"
 
328
"                     (list ");
 
329
 
 
330
        /* Write list of params with properties like
 
331
         * ( param val ("key" . "value") ("key" . "value))
 
332
         */
 
333
        filterparamdb_foreach_param(pdb, param) {
 
334
                char *tmp;
 
335
 
 
336
                val = filterparam_to_string(param);
 
337
                if (!val)
 
338
                        continue;
 
339
                if (props) {
 
340
                        tmp = glsdb_to_list_of_pairs(
 
341
                                filterparam_propertydb(param));
 
342
                        b += sprintf(b,
 
343
                                     "(append (list \"%s\" %s) %s)\n",
 
344
                                     filterparam_label(param), val, tmp);
 
345
                } else
 
346
                        b += sprintf(b,
 
347
                                     "(list \"%s\" %s)\n",
 
348
                                     filterparam_label(param), val);
 
349
 
 
350
                free(tmp);
 
351
        }
 
352
 
 
353
        b += sprintf(b,
 
354
"        ))))\n"
 
355
"        (for-each\n"
 
356
"          (lambda (p)\n"
 
357
"            (param-set! (car p) (cadr p))\n"
 
358
"            (for-each\n"
 
359
"              (lambda (prop)\n"
 
360
"                (set-property! (car p) (car prop) (cdr prop)))\n"
 
361
"              (cddr p)))\n"
 
362
"          pairs)))\n");
 
363
 
 
364
        return strdup(buf);
 
365
}
 
366
 
 
367
 
 
368
 
 
369
/* "Filter" part. */
 
370
 
 
371
int filterparam_set(filter_param_t *param, const void *val)
 
372
{
 
373
        if (!param || !val)
 
374
                return -1;
 
375
 
 
376
        /* First try to prevent useless parameter changing.
 
377
         * -- not a good idea, as parameters are re-set after copydb (121200)
 
378
         */
 
379
#if 0
 
380
        if (FILTER_PARAM_IS_INT(param)) {
 
381
                if (param->u.i == *(int *)val)
 
382
                        return 0;
 
383
        } else if (FILTER_PARAM_IS_FLOAT(param)) {
 
384
                if (param->u.f == *(float *)val)
 
385
                        return 0;
 
386
        } else if (FILTER_PARAM_IS_SAMPLE(param)) {
 
387
                if (param->u.sample == *(SAMPLE *)val)
 
388
                        return 0;
 
389
        } else if (FILTER_PARAM_IS_STRING(param)) {
 
390
                if ((!param->u.string && !*val)
 
391
                    || (param->u.string && *val
 
392
                        && strcmp(param->u.string, *(const char **)val) == 0))
 
393
                        return 0;
 
394
        } else if (FILTER_PARAM_IS_POS(param)) {
 
395
                if (param->u.pos == *(long *)val)
 
396
                        return 0;
 
397
        }
 
398
#endif
 
399
 
 
400
        /* Then ask the param about the change.
 
401
         */
 
402
        if (param->set(param, val) == -1)
 
403
                return -1;
 
404
 
 
405
        /* Finally do the change
 
406
         */
 
407
        if (FILTER_PARAM_IS_INT(param))
 
408
                param->u.i = *(int *)val;
 
409
        else if (FILTER_PARAM_IS_FLOAT(param))
 
410
                param->u.f = *(float *)val;
 
411
        else if (FILTER_PARAM_IS_SAMPLE(param))
 
412
                param->u.sample = *(SAMPLE *)val;
 
413
        else if (FILTER_PARAM_IS_STRING(param)) {
 
414
                /* _first_ copy, then free, in case theyre actually the same... */
 
415
                char *vval = *(const char **)val ? strdup(*(const char **)val) : NULL;
 
416
                free(param->u.string);
 
417
                param->u.string = vval;
 
418
        } else if (FILTER_PARAM_IS_POS(param)) {
 
419
                param->u.pos = *(long *)val;
 
420
        } else if (FILTER_PARAM_IS_BUF(param)) {
 
421
                fbuf_ref(*(filter_buffer_t **)val);
 
422
                fbuf_unref(param->u.buf);
 
423
                param->u.buf = *(filter_buffer_t **)val;
 
424
        }
 
425
 
 
426
        /* and signal the change.
 
427
         */
 
428
        glsig_emit(&param->emitter, GLSIG_PARAM_CHANGED, param);
 
429
 
 
430
        return 0;
 
431
}
 
432
 
 
433
int filterparam_set_string(filter_param_t *param, const char *val)
 
434
{
 
435
        filter_param_t p;
 
436
        char s[512];
 
437
        int res;
 
438
 
 
439
        if (!param || !val)
 
440
                return -1;
 
441
 
 
442
        if (FILTER_PARAM_IS_INT(param))
 
443
                res = sscanf(val, " %i ", &p.u.i);
 
444
        else if (FILTER_PARAM_IS_FLOAT(param))
 
445
                res = sscanf(val, " %f ", &p.u.f);
 
446
        else if (FILTER_PARAM_IS_SAMPLE(param)) {
 
447
                float f;
 
448
                res = sscanf(val, " %f ", &f);
 
449
                p.u.sample = f;
 
450
        } else if (FILTER_PARAM_IS_STRING(param)) {
 
451
                if ((res = sscanf(val, " \"%511[^\"]\" ", s)) != 1)
 
452
                        res = sscanf(val, " %511[^\"] ", s);
 
453
                p.u.string = s;
 
454
        } else if (FILTER_PARAM_IS_POS(param))
 
455
                res = sscanf(val, " %li ", &p.u.pos);
 
456
        else if (FILTER_PARAM_IS_BUF(param)) {
 
457
                filter_buffer_t *buf;
 
458
                unsigned char byte, *b;
 
459
                const unsigned char *c;
 
460
                int i;
 
461
                if (*val == '"')
 
462
                        val++;
 
463
                buf = fbuf_alloc(strlen(val)/2, NULL);
 
464
                c = val;
 
465
                b = fbuf_buf(buf);
 
466
                for (i=0; i<fbuf_size(buf); i++) {
 
467
                        byte = (*c <= '9' ? *c - '0' : *c - 'A' + 10) << 4;
 
468
                        c++;
 
469
                        byte += (*c <= '9' ? *c - '0' : *c - 'A' + 10);
 
470
                        c++;
 
471
                        *(b++) = byte;
 
472
                }
 
473
                p.u.buf = buf;
 
474
                res = 1;
 
475
        } else
 
476
                return -1;
 
477
        if (res != 1)
 
478
                return -1;
 
479
 
 
480
        res = filterparam_set(param, (void *)&p.u);
 
481
 
 
482
        if (FILTER_PARAM_IS_BUF(param))
 
483
                fbuf_unref(p.u.buf);
 
484
 
 
485
        return res;
 
486
}
 
487
 
 
488
char *filterparam_to_string(const filter_param_t *param)
 
489
{
 
490
        char buf[512];
 
491
 
 
492
        if (!param)
 
493
                return NULL;
 
494
 
 
495
        if (FILTER_PARAM_IS_INT(param))
 
496
                snprintf(buf, 511, "%i", param->u.i);
 
497
        else if (FILTER_PARAM_IS_FLOAT(param))
 
498
                snprintf(buf, 511, "%f", param->u.f);
 
499
        else if (FILTER_PARAM_IS_SAMPLE(param))
 
500
                snprintf(buf, 511, "%f", (float)param->u.sample);
 
501
        else if (FILTER_PARAM_IS_STRING(param) && param->u.string)
 
502
                snprintf(buf, 511, "\"%s\"", param->u.string);
 
503
        else if (FILTER_PARAM_IS_POS(param))
 
504
                snprintf(buf, 511, "%li", param->u.pos);
 
505
        else if (FILTER_PARAM_IS_BUF(param) && param->u.buf) {
 
506
                const char CHARS[16] = "0123456789ABCDEF";
 
507
                char *str, *chr;
 
508
                unsigned char *val;
 
509
                int i;
 
510
                str = malloc(2*fbuf_size(param->u.buf)+3);
 
511
                chr = str;
 
512
                val = fbuf_buf(param->u.buf);
 
513
                *(chr++) = '"';
 
514
                for (i=0; i<fbuf_size(param->u.buf); i++) {
 
515
                        *(chr++) = CHARS[(*val) >> 4];
 
516
                        *(chr++) = CHARS[*(val++) & 0x0f];
 
517
                }
 
518
                *(chr++) = '"';
 
519
                *chr = '\0';
 
520
                return str;
 
521
        } else
 
522
                return NULL;
 
523
 
 
524
        return strdup(buf);
 
525
}
 
526
 
 
527
int filterparam_redirect(filter_param_t *source, filter_param_t *dest)
 
528
{
 
529
        if (!source || !dest || !filterparam_filter(dest)
 
530
            || filterparam_type(source) != filterparam_type(dest))
 
531
                return -1;
 
532
 
 
533
        filterparam_set_property(source, FILTERPARAM_MAP_NODE,
 
534
                                 filter_name(filterparam_filter(dest)));
 
535
        filterparam_set_property(source, FILTERPARAM_MAP_LABEL,
 
536
                                 filterparam_label(dest));
 
537
        source->set = redirect_set;
 
538
 
 
539
        return 0;
 
540
}