1 /* gegl-chant contains incantations to that produce the boilerplate
2 * needed to write GEGL operation plug-ins. It abstracts away inheritance
3 * by giving a limited amount of base classes, and reduced creation of
4 * a properties struct and registration of properties for that structure to
5 * a minimum amount of code through use of the C preprocessor. You should
6 * look at the operations implemented using chanting (they #include this file)
7 * to see how it is used in practice.
8 *
9 * GEGL is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 3 of the License, or (at your option) any later version.
13 *
14 * GEGL is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
21 *
22 * 2006-2008 © Øyvind Kolås.
23 */
24
25
26 #ifdef GEGL_OP_C_SOURCE
27 #define __GEGL_HEADER(x) #x
28 #define _GEGL_HEADER(x) __GEGL_HEADER(x)
29 #define GEGL_HEADER(x) _GEGL_HEADER(x)
30
31 #define GEGL_OP_C_FILE GEGL_HEADER(GEGL_OP_C_SOURCE)
32 #endif
33
34 #ifndef GEGL_OP_NAME
35 #define GEGL_OP_NAME op
36 #error "define GEGL_OP_NAME"
37
38 #endif
39
40 #ifndef GEGL_OP_C_FILE
41 #ifdef GEGL_CHANT_C_FILE
42 #error GEGL_OP_C_FILE not defined, %s/GEGL_CHANT_C_FILE/GEGL_OP_C_FILE/
43 #endif
44 #error "GEGL_OP_C_FILE not defined"
45 #endif
46
47 /* XXX: */
48 #ifdef GEGL_CHANT_TYPE_POINT_RENDER
49 #error "GEGL_CHANT_TYPE_POINT_RENDER should be replaced with GEGL_OP_POINT_RENDER"
50 #endif
51
52 #ifdef GEGL_CHANT_PROPERTIES
53 #error "GEGL_CHANT_PROPERTIES should be replaced with GEGL_PROPERTIES"
54 #endif
55
56 #include <gegl-plugin.h>
57
58 G_BEGIN_DECLS
59
60 typedef struct _GeglProperties GeglProperties;
61 typedef struct _GeglOp GeglOp;
62
63
64 static void gegl_op_init_properties (GeglOp *self);
65 static void gegl_op_class_intern_init (gpointer klass);
66 static gpointer gegl_op_parent_class = NULL;
67
68 #define define_register_type_(a) \
69 void gegl_op_##a##_register_type (GTypeModule *module);\
70 GType gegl_op_##a##_get_type (void);
71 #define define_register_type(a) define_register_type_(a)
72 define_register_type(GEGL_OP_NAME)
73 #undef define_register_type
74 #undef define_register_type_
75
76 #define GEGL_DEFINE_DYNAMIC_OPERATION_EXTENDED(C_FILE, TypeName, type_name, TYPE_PARENT, flags, CODE) \
77 static void type_name##_init (TypeName *self); \
78 static void gegl_op_class_init (TypeName##Class *klass); \
79 static void type_name##_class_finalize (TypeName##Class *klass); \
80 static GType type_name##_type_id = 0; \
81 static void type_name##_class_chant_intern_init (gpointer klass) \
82 { \
83 gegl_op_parent_class = g_type_class_peek_parent (klass); \
84 gegl_op_class_intern_init (klass); \
85 gegl_op_class_init ((TypeName##Class*) klass); \
86 } \
87 GType \
88 type_name##_get_type (void) \
89 { \
90 return type_name##_type_id; \
91 } \
92 void \
93 type_name##_register_type (GTypeModule *type_module) \
94 { \
95 gchar tempname[256]; \
96 gchar *p; \
97 const GTypeInfo g_define_type_info = \
98 { \
99 sizeof (TypeName##Class), \
100 (GBaseInitFunc) NULL, \
101 (GBaseFinalizeFunc) NULL, \
102 (GClassInitFunc) type_name##_class_chant_intern_init, \
103 (GClassFinalizeFunc) type_name##_class_finalize, \
104 NULL, /* class_data */ \
105 sizeof (TypeName), \
106 0, /* n_preallocs */ \
107 (GInstanceInitFunc) type_name##_init, \
108 NULL /* value_table */ \
109 }; \
110 g_snprintf (tempname, sizeof (tempname), \
111 "%s", #TypeName C_FILE); \
112 for (p = tempname; *p; p++) \
113 if (*p=='.') *p='_'; \
114 \
115 type_name##_type_id = g_type_module_register_type (type_module, \
116 TYPE_PARENT, \
117 tempname, \
118 &g_define_type_info, \
119 (GTypeFlags) flags); \
120 { CODE ; } \
121 }
122
123 #define GEGL_DEFINE_DYNAMIC_OPERATION_(T_P, C_FILE, opname) GEGL_DEFINE_DYNAMIC_OPERATION_EXTENDED(C_FILE, GeglOp, gegl_op_##opname, T_P, 0, {})
124 #define GEGL_DEFINE_DYNAMIC_OPERATION__(a,b,c) GEGL_DEFINE_DYNAMIC_OPERATION_(a,b,c)
125 #define GEGL_DEFINE_DYNAMIC_OPERATION(T_P) GEGL_DEFINE_DYNAMIC_OPERATION__(T_P, GEGL_OP_C_FILE, GEGL_OP_NAME)
126
127
128 #define GEGL_PROPERTIES(op) ((GeglProperties *) (((GeglOp*)(op))->properties))
129
130 #define MKCLASS(a) MKCLASS2(a)
131 #define MKCLASS2(a) a##Class
132
133 #ifdef GEGL_OP_BASE
134 #define GEGL_OP_Parent GeglOperation
135 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION
136 #endif
137
138 #ifdef GEGL_OP_POINT_FILTER
139 #define GEGL_OP_Parent GeglOperationPointFilter
140 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_FILTER
141 #endif
142
143 #ifdef GEGL_OP_POINT_COMPOSER
144 #define GEGL_OP_Parent GeglOperationPointComposer
145 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_COMPOSER
146 #endif
147
148 #ifdef GEGL_OP_POINT_COMPOSER3
149 #define GEGL_OP_Parent GeglOperationPointComposer3
150 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_COMPOSER3
151 #endif
152
153 #ifdef GEGL_OP_POINT_RENDER
154 #define GEGL_OP_Parent GeglOperationPointRender
155 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_RENDER
156 #endif
157
158 #ifdef GEGL_OP_AREA_FILTER
159 #define GEGL_OP_Parent GeglOperationAreaFilter
160 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_AREA_FILTER
161 #endif
162
163 #ifdef GEGL_OP_FILTER
164 #define GEGL_OP_Parent GeglOperationFilter
165 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_FILTER
166 #endif
167
168 #ifdef GEGL_OP_TEMPORAL
169 #define GEGL_OP_Parent GeglOperationTemporal
170 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_TEMPORAL
171 #endif
172
173 #ifdef GEGL_OP_SOURCE
174 #define GEGL_OP_Parent GeglOperationSource
175 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_SOURCE
176 #endif
177
178 #ifdef GEGL_OP_SINK
179 #define GEGL_OP_Parent GeglOperationSink
180 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_SINK
181 #endif
182
183 #ifdef GEGL_OP_COMPOSER
184 #define GEGL_OP_Parent GeglOperationComposer
185 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_COMPOSER
186 #endif
187
188 #ifdef GEGL_OP_COMPOSER3
189 #define GEGL_OP_Parent GeglOperationComposer3
190 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_COMPOSER3
191 #endif
192
193 #ifdef GEGL_OP_META
194 #include <operation/gegl-operation-meta.h>
195 #define GEGL_OP_Parent GeglOperationMeta
196 #define GEGL_OP_PARENT GEGL_TYPE_OPERATION_META
197 #endif
198
199
200 #ifdef GEGL_OP_Parent
201 struct _GeglOp
202 {
203 GEGL_OP_Parent parent_instance;
204 gpointer properties;
205 };
206
207 typedef struct
208 {
209 MKCLASS(GEGL_OP_Parent) parent_class;
210 } GeglOpClass;
211
212 GEGL_DEFINE_DYNAMIC_OPERATION(GEGL_OP_PARENT)
213
214 #else
215 //#error "no parent class specified"
216 #endif
217
218
219 #define GEGL_OP(obj) ((GeglOp*)(obj))
220
221 /* if GEGL_OP_CUSTOM is defined you have to provide the following
222 * code or your own implementation of it
223 */
224 #ifndef GEGL_OP_CUSTOM
225
226 #define define_init_(a) \
227 static void gegl_op_##a##_init (GeglOp *self) { gegl_op_init_properties (self); }\
228 static void gegl_op_##a##_class_finalize (GeglOpClass *self) { }
229 #define define_init(a) define_init_(a)
230 define_init(GEGL_OP_NAME)
231 #undef define_init
232 #undef define_init_
233
234 static const GeglModuleInfo modinfo =
235 {
236 GEGL_MODULE_ABI_VERSION
237 };
238
239 /* prototypes added to silence warnings from gcc for -Wmissing-prototypes*/
240 gboolean gegl_module_register (GTypeModule *module);
241 const GeglModuleInfo * gegl_module_query (GTypeModule *module);
242
243 #ifndef GEGL_OP_BUNDLE
244 G_MODULE_EXPORT const GeglModuleInfo *
gegl_module_query(GTypeModule * module)245 gegl_module_query (GTypeModule *module)
246 {
247 return &modinfo;
248 }
249
250 G_MODULE_EXPORT gboolean
gegl_module_register(GTypeModule * module)251 gegl_module_register (GTypeModule *module)
252 {
253 #define do_reg_(a) gegl_op_##a##_register_type (module)
254 #define do_reg(b) do_reg_(b)
255 do_reg(GEGL_OP_NAME);
256 #undef do_reg
257 return TRUE;
258 }
259 #endif
260 #endif
261
262
263 #define description(blurb)
264 #define value_range(min,max)
265 #define ui_range(min,max)
266 #define ui_gamma(gamma)
267 #define ui_steps(small_increment, big_increment)
268 #define ui_meta(key,val)
269 #define ui_digits(digits)
270
271 #define ITEM(name,label,def_val, type)
272 #define ITEM2(name,label,def_val,type) ITEM(name,label,def_val,type)
273
274 /* enum registration */
275
276 #define property_double(name, label, def_val) ITEM(name,label,def_val,double)
277 #define property_int(name, label, def_val) ITEM(name,label,def_val,int)
278 #define property_string(name, label, def_val) ITEM(name,label,def_val,string)
279 #define property_file_path(name, label, def_val) ITEM(name,label,def_val,string)
280 #define property_uri(name, label, def_val) ITEM(name,label,def_val,string)
281 #define property_boolean(name, label, def_val) ITEM(name,label,def_val,boolean)
282 #define property_pointer(name, label, def_val) ITEM(name,label,def_val,pointer)
283 #define property_object(name, label, def_val) ITEM2(name,label,def_val,object)
284 #define property_enum(name, label, enm, enum_name, def_val) ITEM(name,label,def_val,pointer)
285 #define property_seed(name, label, rand_name) ITEM(name,label,def_val,uint)
286 #define property_format(name, label, def_val) ITEM(name,label,def_val,pointer)
287 #define property_curve(name, label, def_val) ITEM2(name,label,def_val,object)
288 #define property_path(name, label, def_val) ITEM2(name,label,def_val,object)
289 #define property_color(name, label, def_val) ITEM2(name,label,def_val,object)
290 #define property_audio_fragment(name, label, def_val) ITEM2(name,label,NULL,object)
291
292 #define enum_start(enum_name) typedef enum {
293 #define enum_value(value, nick, name) value ,
294 #define enum_value_skip(value) value ,
295 #define enum_end(enum) } enum ;
296
297 #include GEGL_OP_C_FILE
298
299 #undef enum_start
300 #undef enum_value
301 #undef enum_value_skip
302 #undef enum_end
303
304 #ifdef GETTEXT_PACKAGE
305 static const gchar *gegl_op_gettext_package G_GNUC_UNUSED = GETTEXT_PACKAGE;
306 #else
307 static const gchar *gegl_op_gettext_package G_GNUC_UNUSED = NULL;
308 #endif
309
310 #define enum_start(enum_name) \
311 static GType enum_name ## _get_type (void) G_GNUC_CONST; \
312 static GType enum_name ## _get_type (void) \
313 { \
314 static GType etype = 0; \
315 if (etype == 0) { \
316 static GEnumValue values[] = {
317
318 #define enum_value(value, nick, name) \
319 { value, name, nick },
320
321 #define enum_value_skip(value)
322
323 #define enum_end(enum) \
324 { 0, NULL, NULL } \
325 }; \
326 if (gegl_op_gettext_package) \
327 { \
328 guint i; \
329 for (i = 0; i < G_N_ELEMENTS (values); i++) \
330 if (values[i].value_name) \
331 values[i].value_name = \
332 dgettext (GETTEXT_PACKAGE, values[i].value_name); \
333 } \
334 etype = g_enum_register_static (#enum, values); \
335 } \
336 return etype; \
337 }
338
339 #include GEGL_OP_C_FILE
340
341 #undef property_double
342 #undef property_int
343 #undef property_string
344 #undef property_boolean
345 #undef property_file_path
346 #undef property_uri
347 #undef property_object
348 #undef property_pointer
349 #undef property_format
350 #undef property_enum
351 #undef property_seed
352 #undef property_curve
353 #undef property_color
354 #undef property_audio_fragment
355 #undef property_path
356 #undef enum_start
357 #undef enum_value
358 #undef enum_value_skip
359 #undef enum_end
360 #define enum_start(enum_name)
361 #define enum_value(value, nick, name)
362 #define enum_value_skip(value)
363 #define enum_end(enum)
364
365 /* Properties */
366
367 struct _GeglProperties
368 {
369 gpointer user_data; /* for use by the op implementation */
370 #define property_double(name, label, def_val) gdouble name;
371 #define property_int(name, label, def_val) gint name;
372 #define property_string(name, label, def_val) gchar *name;
373 #define property_boolean(name, label, def_val) gboolean name;
374 #define property_file_path(name, label, def_val) gchar *name;
375 #define property_uri(name, label, def_val) gchar *name;
376 #define property_object(name, label, def_val) GObject *name;
377 #define property_curve(name, label, def_val) GeglCurve *name;
378 #define property_color(name, label, def_val) GeglColor *name;
379 #define property_audio_fragment(name, label, def_val) GeglAudioFragment *name;
380 #define property_path(name, label, def_val) GeglPath *name; gulong path_changed_handler;
381 #define property_pointer(name, label, def_val) gpointer name;
382 #define property_format(name, label, def_val) gpointer name;
383 #define property_enum(name, label, enum, enum_name, def_val) enum name;
384 #define property_seed(name, label, rand_name) guint name;\
385 GeglRandom *rand_name;
386
387 #include GEGL_OP_C_FILE
388
389 #undef property_double
390 #undef property_int
391 #undef property_string
392 #undef property_boolean
393 #undef property_file_path
394 #undef property_uri
395 #undef property_object
396 #undef property_pointer
397 #undef property_format
398 #undef property_enum
399 #undef property_seed
400 #undef property_curve
401 #undef property_color
402 #undef property_audio_fragment
403 #undef property_path
404 };
405
406 #define GEGL_OP_OPERATION(obj) ((Operation*)(obj))
407
408 enum
409 {
410 PROP_0,
411
412 #undef ITEM
413 #define ITEM(name,label,def_val, type) PROP_##name,
414 #define ITEM2(name,label,def_val, type) ITEM(name,label,def_val,type)
415
416 #define property_double(name, label, def_val) ITEM(name,label,def_val,double)
417 #define property_int(name, label, def_val) ITEM(name,label,def_val,int)
418 #define property_string(name, label, def_val) ITEM(name,label,def_val,string)
419 #define property_file_path(name, label, def_val) ITEM(name,label,def_val,string)
420 #define property_uri(name, label, def_val) ITEM(name,label,def_val,string)
421 #define property_boolean(name, label, def_val) ITEM(name,label,def_val,boolean)
422 #define property_object(name, label, def_val) ITEM2(name,label,def_val,object)
423 #define property_curve(name, label, def_val) ITEM2(name,label,def_val,object)
424 #define property_color(name, label, def_val) ITEM2(name,label,def_val,object)
425 #define property_audio_fragment(name, label, def_val) ITEM2(name,label,def_val,object)
426 #define property_path(name, label, def_val) ITEM2(name,label,def_val,object)
427 #define property_pointer(name, label, def_val) ITEM(name,label,def_val,pointer)
428 #define property_format(name, label, def_val) ITEM(name,label,def_val,pointer)
429 #define property_enum(name, label, enm, enum_name, def_val) ITEM(name,label,def_val,enum)
430 #define property_seed(name, label, rand_name) ITEM(name,label,def_val,uint)
431
432 #include GEGL_OP_C_FILE
433
434 #undef ITEM
435 #define ITEM(name,label,def_val, type) \
436 case PROP_##name: \
437 g_value_set_##type (value, properties->name); \
438 break;
439 #define ITEM2(name,label,def_val, type) ITEM(name,label,def_val,type)
440
441 PROP_LAST
442 };
443
444 static void
get_property(GObject * gobject,guint property_id,GValue * value,GParamSpec * pspec)445 get_property (GObject *gobject,
446 guint property_id,
447 GValue *value,
448 GParamSpec *pspec)
449 {
450 GeglProperties *properties;
451
452 properties = GEGL_PROPERTIES(gobject);
453
454 switch (property_id)
455 {
456
457 #include GEGL_OP_C_FILE
458
459 #undef property_double
460 #undef property_int
461 #undef property_string
462 #undef property_boolean
463 #undef property_file_path
464 #undef property_uri
465 #undef property_object
466 #undef property_pointer
467 #undef property_format
468 #undef property_enum
469 #undef property_seed
470 #undef property_curve
471 #undef property_color
472 #undef property_audio_fragment
473 #undef property_path
474 default:
475 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
476 break;
477 }
478 if (properties) {}; /* silence gcc */
479 }
480
481 static void
set_property(GObject * gobject,guint property_id,const GValue * value,GParamSpec * pspec)482 set_property (GObject *gobject,
483 guint property_id,
484 const GValue *value,
485 GParamSpec *pspec)
486 {
487 GeglProperties *properties;
488
489 properties = GEGL_PROPERTIES(gobject);
490
491 switch (property_id)
492 {
493 #define property_double(name, label, def_val) \
494 case PROP_##name: \
495 properties->name = g_value_get_double (value); \
496 break;
497 #define property_int(name, label, def_val) \
498 case PROP_##name: \
499 properties->name = g_value_get_int (value); \
500 break;
501 #define property_string(name, label, def_val) \
502 case PROP_##name: \
503 g_free (properties->name); \
504 properties->name = g_value_dup_string (value); \
505 break;
506 #define property_boolean(name, label, def_val) \
507 case PROP_##name: \
508 properties->name = g_value_get_boolean (value); \
509 break;
510 #define property_file_path(name, label, def_val) \
511 case PROP_##name: \
512 g_free (properties->name); \
513 properties->name = g_value_dup_string (value); \
514 break;
515 #define property_uri(name, label, def_val) \
516 case PROP_##name: \
517 g_free (properties->name); \
518 properties->name = g_value_dup_string (value); \
519 break;
520 #define property_object(name, label, def_val) \
521 case PROP_##name: \
522 g_clear_object (&properties->name); \
523 properties->name = G_OBJECT (g_value_dup_object (value)); \
524 break;
525 #define property_curve(name, label, def_val) \
526 case PROP_##name: \
527 g_clear_object (&properties->name); \
528 properties->name = GEGL_CURVE (g_value_dup_object (value)); \
529 break;
530 #define property_color(name, label, def_val) \
531 case PROP_##name: \
532 g_clear_object (&properties->name); \
533 properties->name = GEGL_COLOR (g_value_dup_object (value)); \
534 break;
535 #define property_audio_fragment(name, label, def_val) \
536 case PROP_##name: \
537 g_clear_object (&properties->name); \
538 properties->name = \
539 GEGL_AUDIO_FRAGMENT (g_value_dup_object (value)); \
540 break;
541 #define property_path(name, label, def_val) \
542 case PROP_##name: \
543 if (properties->name != NULL) \
544 { \
545 if (properties->path_changed_handler) \
546 g_signal_handler_disconnect (G_OBJECT (properties->name), \
547 properties->path_changed_handler); \
548 properties->path_changed_handler = 0; \
549 g_object_unref (properties->name); \
550 } \
551 properties->name = GEGL_PATH (g_value_dup_object (value)); \
552 if (properties->name != NULL) \
553 { \
554 properties->path_changed_handler = \
555 g_signal_connect (G_OBJECT (properties->name), "changed", \
556 G_CALLBACK(path_changed), gobject); \
557 } \
558 break;
559 #define property_pointer(name, label, def_val) \
560 case PROP_##name: \
561 properties->name = g_value_get_pointer (value); \
562 break;
563 #define property_format(name, label, def_val) \
564 case PROP_##name: \
565 properties->name = g_value_get_pointer (value); \
566 break;
567 #define property_enum(name, label, enum, enum_name, def_val) \
568 case PROP_##name: \
569 properties->name = (enum) g_value_get_enum (value); \
570 break;
571 #define property_seed(name, label, rand_name) \
572 case PROP_##name: \
573 properties->name = g_value_get_uint (value); \
574 if (!properties->rand_name) \
575 properties->rand_name = gegl_random_new_with_seed (properties->name);\
576 else \
577 gegl_random_set_seed (properties->rand_name, properties->name);\
578 break;
579
580 #include GEGL_OP_C_FILE
581
582 #undef property_double
583 #undef property_int
584 #undef property_string
585 #undef property_boolean
586 #undef property_file_path
587 #undef property_uri
588 #undef property_object
589 #undef property_pointer
590 #undef property_curve
591 #undef property_color
592 #undef property_audio_fragment
593 #undef property_path
594 #undef property_format
595 #undef property_enum
596 #undef property_seed
597
598 default:
599 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
600 break;
601 }
602
603 if (properties) {}; /* silence gcc */
604 }
605
gegl_op_destroy_notify(gpointer data)606 static void gegl_op_destroy_notify (gpointer data)
607 {
608 GeglProperties *properties = GEGL_PROPERTIES (data);
609
610 #define property_double(name, label, def_val)
611 #define property_int(name, label, def_val)
612 #define property_string(name, label, ...) \
613 g_clear_pointer (&properties->name, g_free);
614 #define property_boolean(name, label, def_val)
615 #define property_file_path(name, label, def_val) \
616 g_clear_pointer (&properties->name, g_free);
617 #define property_uri(name, label, def_val) \
618 g_clear_pointer (&properties->name, g_free);
619 #define property_object(name, label, def_val) \
620 g_clear_object (&properties->name);
621 #define property_curve(name, label, def_val) \
622 g_clear_object (&properties->name);
623 #define property_color(name, label, def_val) \
624 g_clear_object (&properties->name);
625 #define property_audio_fragment(name, label, def_val) \
626 g_clear_object (&properties->name);
627 #define property_path(name, label, def_val) \
628 g_clear_object (&properties->name);
629 #define property_pointer(name, label, ...)
630 #define property_format(name, label, ...)
631 #define property_enum(name, label, ...)
632 #define property_seed(name, label, ...)
633
634 #include GEGL_OP_C_FILE
635
636 #undef property_double
637 #undef property_int
638 #undef property_string
639 #undef property_boolean
640 #undef property_file_path
641 #undef property_uri
642 #undef property_object
643 #undef property_pointer
644 #undef property_format
645 #undef property_enum
646 #undef property_seed
647 #undef property_curve
648 #undef property_color
649 #undef property_audio_fragment
650 #undef property_path
651
652 g_slice_free (GeglProperties, properties);
653 }
654
655 static GObject *
gegl_op_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)656 gegl_op_constructor (GType type,
657 guint n_construct_properties,
658 GObjectConstructParam *construct_properties)
659 {
660 GObject *obj;
661 GeglProperties *properties;
662
663 obj = G_OBJECT_CLASS (gegl_op_parent_class)->constructor (
664 type, n_construct_properties, construct_properties);
665
666 /* create dummy colors and vectors */
667 properties = GEGL_PROPERTIES (obj);
668
669 #define property_double(name, label, def_val)
670 #define property_int(name, label, def_val)
671 #define property_string(name, label, def_val)
672 #define property_boolean(name, label, def_val)
673 #define property_file_path(name, label, def_val)
674 #define property_uri(name, label, def_val)
675 #define property_object(name, label, def_val)
676 #define property_pointer(name, label, def_val)
677 #define property_format(name, label, def_val)
678 #define property_curve(name, label, def_val)
679 #define property_audio_fragment(name, label, def_val)\
680 if (properties->name == NULL) \
681 {properties->name = gegl_audio_fragment_new(48000, 2, 0, 8192);}
682 #define property_color(name, label, def_val)\
683 if (properties->name == NULL) \
684 {properties->name = gegl_color_new(def_val?def_val:"black");}
685 #define property_path(name, label, def_val)
686 #define property_enum(name, ...)
687 #define property_seed(name, label, rand_name) \
688 if (properties->rand_name == NULL) \
689 {properties->rand_name = gegl_random_new_with_seed (0);}
690
691 #include GEGL_OP_C_FILE
692
693 #undef property_double
694 #undef property_int
695 #undef property_string
696 #undef property_boolean
697 #undef property_file_path
698 #undef property_uri
699 #undef property_object
700 #undef property_pointer
701 #undef property_format
702 #undef property_enum
703 #undef property_seed
704 #undef property_curve
705 #undef property_color
706 #undef property_audio_fragment
707 #undef property_path
708
709 g_object_set_data_full (obj, "chant-data", obj, gegl_op_destroy_notify);
710 properties ++; /* evil hack to silence gcc */
711 return obj;
712 }
713
has_key(GParamSpec * pspec,const gchar * key,const gchar * value)714 static gboolean has_key (GParamSpec *pspec,
715 const gchar *key,
716 const gchar *value)
717 {
718 const char *set_value = gegl_param_spec_get_property_key (pspec, key);
719 if (set_value && g_str_equal (value, set_value))
720 return TRUE;
721 return FALSE;
722 }
723
724 static void
param_spec_update_ui(GParamSpec * pspec,gboolean ui_range_set,gboolean ui_steps_set,gboolean ui_digits_set)725 param_spec_update_ui (GParamSpec *pspec,
726 gboolean ui_range_set,
727 gboolean ui_steps_set,
728 gboolean ui_digits_set)
729 {
730 if (GEGL_IS_PARAM_SPEC_DOUBLE (pspec))
731 {
732 GeglParamSpecDouble *upspec = GEGL_PARAM_SPEC_DOUBLE (pspec);
733 GParamSpecDouble *vpspec = G_PARAM_SPEC_DOUBLE (pspec);
734
735 if (!ui_steps_set)
736 {
737 if (!ui_range_set)
738 {
739 upspec->ui_maximum = vpspec->maximum;
740 upspec->ui_minimum = vpspec->minimum;
741 }
742
743 if (has_key (pspec, "unit", "degree"))
744 {
745 upspec->ui_step_small = 1.0;
746 upspec->ui_step_big = 15.0;
747 }
748 else if (upspec->ui_maximum <= 5.0)
749 {
750 upspec->ui_step_small = 0.001;
751 upspec->ui_step_big = 0.100;
752 }
753 else if (upspec->ui_maximum <= 50)
754 {
755 upspec->ui_step_small = 0.01;
756 upspec->ui_step_big = 1.00;
757 }
758 else if (upspec->ui_maximum <= 500)
759 {
760 upspec->ui_step_small = 1.0;
761 upspec->ui_step_big = 10.0;
762 }
763 else if (upspec->ui_maximum <= 5000)
764 {
765 upspec->ui_step_small = 1.0;
766 upspec->ui_step_big = 100.0;
767 }
768 }
769
770 if (!ui_digits_set)
771 {
772 if (has_key (pspec, "unit", "degrees"))
773 {
774 upspec->ui_digits = 2;
775 }
776 else if (upspec->ui_maximum <= 5.0)
777 {
778 upspec->ui_digits = 4;
779 }
780 if (upspec->ui_maximum <= 50.0)
781 {
782 upspec->ui_digits = 3;
783 }
784 else if (upspec->ui_maximum <= 500)
785 {
786 upspec->ui_digits = 2;
787 }
788 else
789 {
790 upspec->ui_digits = 1;
791 }
792 }
793 }
794 else if (GEGL_IS_PARAM_SPEC_INT (pspec))
795 {
796 GeglParamSpecInt *upspec = GEGL_PARAM_SPEC_INT (pspec);
797 GParamSpecInt *vpspec = G_PARAM_SPEC_INT (pspec);
798
799 if (!ui_steps_set)
800 {
801 if (!ui_range_set)
802 {
803 upspec->ui_maximum = vpspec->maximum;
804 upspec->ui_minimum = vpspec->minimum;
805 }
806
807 if (upspec->ui_maximum <= 5)
808 {
809 upspec->ui_step_small = 1;
810 upspec->ui_step_big = 2;
811 }
812 else if (upspec->ui_maximum <= 50)
813 {
814 upspec->ui_step_small = 1;
815 upspec->ui_step_big = 5;
816 }
817 else if (upspec->ui_maximum <= 500)
818 {
819 upspec->ui_step_small = 1;
820 upspec->ui_step_big = 10;
821 }
822 else if (upspec->ui_maximum <= 5000)
823 {
824 upspec->ui_step_small = 1;
825 upspec->ui_step_big = 100;
826 }
827 }
828 }
829 }
830
831 static void
gegl_op_class_intern_init(gpointer klass)832 gegl_op_class_intern_init (gpointer klass)
833 {
834 GObjectClass *object_class = G_OBJECT_CLASS (klass);
835 int current_prop = -1;
836 gboolean G_GNUC_UNUSED ui_range_set = FALSE;
837 gboolean G_GNUC_UNUSED ui_steps_set = FALSE;
838 gboolean G_GNUC_UNUSED ui_digits_set = FALSE;
839 GParamFlags flags G_GNUC_UNUSED = (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT | GEGL_PARAM_PAD_INPUT);
840
841 object_class->set_property = set_property;
842 object_class->get_property = get_property;
843 object_class->constructor = gegl_op_constructor;
844
845 {
846 GParamSpec *pspec = NULL;
847
848 #undef description
849 #undef value_range
850 #undef ui_range
851 #undef ui_steps
852 #undef ui_gamma
853 #undef ui_meta
854 #undef ui_digits
855
856 #define REGISTER_IF_ANY \
857 if (pspec && current_prop >=0) {\
858 param_spec_update_ui (pspec, ui_range_set, ui_steps_set, ui_digits_set);\
859 g_object_class_install_property (object_class, current_prop, pspec);\
860 pspec = NULL; current_prop = -1;\
861 ui_range_set = ui_steps_set = ui_digits_set = FALSE;\
862 }
863
864 #define description(blurb) \
865 pspec->_blurb = g_strdup (blurb);
866 #define value_range(min,max) \
867 vpspec->minimum = min; vpspec->maximum = max; \
868 upspec->ui_minimum = min; upspec->ui_maximum = max;
869 #define ui_range(min,max) \
870 upspec->ui_minimum = min; upspec->ui_maximum = max;\
871 ui_range_set = TRUE;
872 #define ui_steps(step_small,step_big) \
873 upspec->ui_step_small = step_small; upspec->ui_step_big = step_big; \
874 ui_steps_set = TRUE;
875 #define ui_gamma(gamma) \
876 upspec->ui_gamma = gamma;
877 #define ui_meta(key,val) \
878 gegl_param_spec_set_property_key(pspec, key, val);
879 #define ui_digits(digits) \
880 upspec->ui_digits = digits; \
881 ui_digits_set = TRUE;
882
883 #define property_double(name, label, def_val) \
884 REGISTER_IF_ANY \
885 }{ GParamSpec *pspec = \
886 gegl_param_spec_double (#name, label, NULL,-G_MAXDOUBLE,G_MAXDOUBLE,def_val,-100,100,1.0,flags);\
887 GeglParamSpecDouble *upspec G_GNUC_UNUSED = GEGL_PARAM_SPEC_DOUBLE (pspec);\
888 GParamSpecDouble *vpspec G_GNUC_UNUSED = G_PARAM_SPEC_DOUBLE (pspec);\
889 current_prop = PROP_##name ;
890
891 #define property_int(name, label, def_val) \
892 REGISTER_IF_ANY \
893 }{ GParamSpec *pspec = \
894 gegl_param_spec_int (#name, label, NULL,G_MININT,G_MAXINT,def_val,-100,100,1.0,flags);\
895 GeglParamSpecInt *upspec G_GNUC_UNUSED = GEGL_PARAM_SPEC_INT (pspec);\
896 GParamSpecInt *vpspec G_GNUC_UNUSED = G_PARAM_SPEC_INT (pspec);\
897 current_prop = PROP_##name ;
898
899 #define property_string(name, label, def_val) \
900 REGISTER_IF_ANY \
901 }{ GParamSpec *pspec = \
902 g_param_spec_string (#name, label, NULL, def_val, flags);\
903 current_prop = PROP_##name ;
904
905 #define property_boolean(name, label, def_val) \
906 REGISTER_IF_ANY \
907 }{ GParamSpec *pspec = \
908 g_param_spec_boolean (#name, label, NULL, def_val, flags);\
909 current_prop = PROP_##name ;
910
911 #define property_file_path(name, label, def_val) \
912 REGISTER_IF_ANY \
913 }{ GParamSpec *pspec = \
914 gegl_param_spec_file_path (#name, label, NULL, FALSE, FALSE, def_val, flags);\
915 current_prop = PROP_##name ;
916
917 #define property_uri(name, label, def_val) \
918 REGISTER_IF_ANY \
919 }{ GParamSpec *pspec = \
920 gegl_param_spec_uri (#name, label, NULL, FALSE, FALSE, def_val, flags);\
921 current_prop = PROP_##name ;
922
923 #define property_object(name, label, type) \
924 REGISTER_IF_ANY \
925 }{ GParamSpec *pspec = \
926 g_param_spec_object (#name, label, NULL, type, flags);\
927 current_prop = PROP_##name ;
928
929 #define property_curve(name, label, def_val) \
930 REGISTER_IF_ANY \
931 }{ GeglCurve *_gegl_op_default_curve = gegl_curve_new_default (); \
932 GParamSpec *pspec = \
933 gegl_param_spec_curve (#name, label, NULL, _gegl_op_default_curve, flags);\
934 current_prop = PROP_##name ;\
935 g_object_unref (_gegl_op_default_curve);\
936
937 #define property_color(name, label, def_val) \
938 REGISTER_IF_ANY \
939 }{ GParamSpec *pspec = \
940 gegl_param_spec_color_from_string (#name, label, NULL, def_val, flags);\
941 current_prop = PROP_##name ;
942
943 #define property_audio_fragment(name, label, def_val) \
944 REGISTER_IF_ANY \
945 }{ GParamSpec *pspec = \
946 gegl_param_spec_audio_fragment (#name, label, NULL, flags);\
947 current_prop = PROP_##name ;
948
949 #define property_path(name, label, def_val) \
950 REGISTER_IF_ANY \
951 }{ GParamSpec *pspec = \
952 gegl_param_spec_path (#name, label, NULL, def_val, flags);\
953 current_prop = PROP_##name ;
954
955 #define property_pointer(name, label, def_val) \
956 REGISTER_IF_ANY \
957 }{ GParamSpec *pspec = \
958 g_param_spec_pointer (#name, label, NULL, flags);\
959 current_prop = PROP_##name ;
960
961 #define property_format(name, label, def_val) \
962 REGISTER_IF_ANY \
963 }{ GParamSpec *pspec = \
964 gegl_param_spec_format (#name, label, NULL, flags);\
965 current_prop = PROP_##name ;
966
967 #define property_enum(name, label, enum, enum_name, def_val) \
968 REGISTER_IF_ANY \
969 }{ GParamSpec *pspec = gegl_param_spec_enum (#name, label, NULL, enum_name ##_get_type(), def_val, flags); \
970 current_prop = PROP_##name ;
971
972 #define property_seed(name, label, rand_name) \
973 REGISTER_IF_ANY \
974 }{ GParamSpec *pspec = gegl_param_spec_seed (#name, label, NULL, flags); \
975 current_prop = PROP_##name ;
976
977 #include GEGL_OP_C_FILE
978
979 REGISTER_IF_ANY
980 }
981
982 #undef REGISTER_IF_ANY
983 #undef description
984 #undef value_range
985 #undef ui_range
986 #undef ui_steps
987 #undef ui_gamma
988 #undef ui_meta
989 #undef property_double
990 #undef property_int
991 #undef property_string
992 #undef property_enum
993 #undef property_seed
994 #undef property_pointer
995 #undef property_path
996 #undef property_curve
997 #undef property_color
998 #undef property_audio_fragment
999 #undef property_object
1000 #undef property_format
1001
1002 }
1003
1004 static void
gegl_op_init_properties(GeglOp * self)1005 gegl_op_init_properties (GeglOp *self)
1006 {
1007 self->properties = g_slice_new0 (GeglProperties);
1008 }
1009
1010 G_END_DECLS
1011