3
* $Id: filter_param.c,v 1.16 2001/11/18 14:48:09 richi Exp $
5
* Copyright (C) 2000 Richard Guenther
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.
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.
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
24
#include "gldb_string.h"
26
#include "filter_param.h"
29
#define ITEM(p) (&(p)->entry)
30
#define PARAM(i) ((filter_param_t *)(i))
32
static int default_set(filter_param_t *p, const void *val)
37
static int redirect_set(filter_param_t *param, const void *val)
40
const char *map_node, *map_label;
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)
50
if (!(n = filter_get_node(node, map_node))) {
51
DPRINTF("No such node %s\n", map_node);
54
if (!(p = filterparamdb_get_param(filter_paramdb(n), map_label))) {
55
DPRINTF("No such param %s\n", map_label);
58
return filterparam_set(p, val);
62
static filter_param_t *paramdb_alloc_item()
66
if (!(p = ALLOC(filter_param_t)))
68
gldb_init_item(&p->entry);
69
glsdb_init(&p->properties);
70
INIT_GLSIG_EMITTER(&p->emitter);
77
static void paramdb_op_delete(gldb_item_t *item)
79
filter_param_t *p = PARAM(item);
81
/* Emit PARAM_DELETED signal. */
82
glsig_emit(&p->emitter, GLSIG_PARAM_DELETED, p);
84
glsdb_delete(&p->properties);
85
if (FILTER_PARAM_IS_STRING(p))
87
else if (FILTER_PARAM_IS_BUF(p))
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);
96
static gldb_item_t *paramdb_op_copy(gldb_item_t *source)
99
filter_param_t *s = PARAM(source);
101
if (!(d = paramdb_alloc_item()))
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)) {
112
memcpy(&d->u, &s->u, sizeof(s->u));
115
/* copy property db */
116
glsdb_copy(&d->properties, &s->properties);
118
/* copy signal handlers - not the redirectors. */
119
glsig_copy_handlers(&d->emitter, &s->emitter);
124
static int paramdb_op_add(gldb_t *db, gldb_item_t *i, gldb_item_t *dest)
126
filter_param_t *p = PARAM(i);
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");
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?");
141
glsig_add_redirector(&p->emitter, ~0,
142
&((filter_paramdb_t *)p->entry.db)->node->emitter);
146
static struct gldb_ops ops = { paramdb_op_delete,
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)
157
const char *key, *prop;
159
if (!db || FILTER_IS_PLUGIN(db->node) || !label || !val)
162
if ((i = gldb_query_item(&db->db, label)))
164
if (!(p = paramdb_alloc_item()))
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;
182
if (gldb_add_item(&db->db, ITEM(p), label) == -1) {
183
paramdb_op_delete(ITEM(p));
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);
194
/* Notify the associated filter of the change. */
195
glsig_emit(&p->emitter, GLSIG_FILTER_CHANGED,
196
((filter_paramdb_t *)p->entry.db)->node);
206
void filterparamdb_init(filter_paramdb_t *db, filter_t *node)
208
gldb_init(&db->db, &ops);
215
filter_param_t *filterparamdb_add_param(filter_paramdb_t *db,
217
int type, const void *val, ...)
223
p = _filterparamdb_add_param(db, label, type, val, va);
228
filter_param_t *filterparamdb_add_param_int(filter_paramdb_t *db,
230
int type, int val, ...)
236
p = _filterparamdb_add_param(db, label, type, &val, va);
241
filter_param_t *filterparamdb_add_param_float(filter_paramdb_t *db,
243
int type, float val, ...)
249
p = _filterparamdb_add_param(db, label, type, &val, va);
254
filter_param_t *filterparamdb_add_param_string(filter_paramdb_t *db,
256
int type, const char *val, ...)
262
p = _filterparamdb_add_param(db, label, type, &val, va);
267
static filter_param_t *_filterparamdb_add_param_pos(filter_paramdb_t *db, ...)
274
p = _filterparamdb_add_param(db, FILTERPARAM_LABEL_POS,
275
FILTER_PARAMTYPE_POS, &val, va);
280
filter_param_t *filterparamdb_add_param_pos(filter_paramdb_t *db)
282
return _filterparamdb_add_param_pos(db, FILTERPARAM_END);
285
filter_param_t *filterparamdb_get_param(filter_paramdb_t *db,
293
if (!(i = gldb_query_item(&db->db, label)))
298
void filterparamdb_delete_param(filter_paramdb_t *db, const char *label)
305
if (!(i = gldb_query_item(&db->db, label)))
310
char *filterparamdb_to_string(filter_paramdb_t *pdb, int props)
312
filter_param_t *param;
316
buf = b = alloca(64*1024); /* Wheee... */
320
" (let* ((params (map (lambda (param)\n"
321
" (cons (param-label param) param))\n"
323
" (pairs (map (lambda (spec)\n"
324
" (let ((p (assoc (car spec) params)))\n"
326
" (cons (cdr p) (cdr spec))\n"
327
" (throw 'glame-error))))\n"
330
/* Write list of params with properties like
331
* ( param val ("key" . "value") ("key" . "value))
333
filterparamdb_foreach_param(pdb, param) {
336
val = filterparam_to_string(param);
340
tmp = glsdb_to_list_of_pairs(
341
filterparam_propertydb(param));
343
"(append (list \"%s\" %s) %s)\n",
344
filterparam_label(param), val, tmp);
347
"(list \"%s\" %s)\n",
348
filterparam_label(param), val);
357
" (param-set! (car p) (cadr p))\n"
360
" (set-property! (car p) (car prop) (cdr prop)))\n"
371
int filterparam_set(filter_param_t *param, const void *val)
376
/* First try to prevent useless parameter changing.
377
* -- not a good idea, as parameters are re-set after copydb (121200)
380
if (FILTER_PARAM_IS_INT(param)) {
381
if (param->u.i == *(int *)val)
383
} else if (FILTER_PARAM_IS_FLOAT(param)) {
384
if (param->u.f == *(float *)val)
386
} else if (FILTER_PARAM_IS_SAMPLE(param)) {
387
if (param->u.sample == *(SAMPLE *)val)
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))
394
} else if (FILTER_PARAM_IS_POS(param)) {
395
if (param->u.pos == *(long *)val)
400
/* Then ask the param about the change.
402
if (param->set(param, val) == -1)
405
/* Finally do the change
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;
426
/* and signal the change.
428
glsig_emit(¶m->emitter, GLSIG_PARAM_CHANGED, param);
433
int filterparam_set_string(filter_param_t *param, const char *val)
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)) {
448
res = sscanf(val, " %f ", &f);
450
} else if (FILTER_PARAM_IS_STRING(param)) {
451
if ((res = sscanf(val, " \"%511[^\"]\" ", s)) != 1)
452
res = sscanf(val, " %511[^\"] ", 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;
463
buf = fbuf_alloc(strlen(val)/2, NULL);
466
for (i=0; i<fbuf_size(buf); i++) {
467
byte = (*c <= '9' ? *c - '0' : *c - 'A' + 10) << 4;
469
byte += (*c <= '9' ? *c - '0' : *c - 'A' + 10);
480
res = filterparam_set(param, (void *)&p.u);
482
if (FILTER_PARAM_IS_BUF(param))
488
char *filterparam_to_string(const filter_param_t *param)
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";
510
str = malloc(2*fbuf_size(param->u.buf)+3);
512
val = fbuf_buf(param->u.buf);
514
for (i=0; i<fbuf_size(param->u.buf); i++) {
515
*(chr++) = CHARS[(*val) >> 4];
516
*(chr++) = CHARS[*(val++) & 0x0f];
527
int filterparam_redirect(filter_param_t *source, filter_param_t *dest)
529
if (!source || !dest || !filterparam_filter(dest)
530
|| filterparam_type(source) != filterparam_type(dest))
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;