LiVES 3.2.0
paramwindow.c
Go to the documentation of this file.
1// paramwindow.c
2// LiVES
3// (c) G. Finch 2004 - 2018 <salsaman+lives@gmail.com>
4// released under the GNU GPL 3 or later
5// see file ../COPYING or www.gnu.org for licensing details
6
7// dynamic window generation from parameter arrays :-)
8
9#include "main.h"
10#include "paramwindow.h"
11#include "callbacks.h"
12#include "resample.h"
13#include "effects.h"
14#include "rte_window.h"
15#include "framedraw.h"
16#include "ce_thumbs.h"
17#include "interface.h"
18
19#ifdef ENABLE_GIW
20#include "giw/giwknob.h"
21#endif
22
23static int ireinit = 0;
24
25extern boolean do_effect(lives_rfx_t *, boolean is_preview); //effects.c in LiVES
26extern void on_realfx_activate(LiVESMenuItem *, livespointer rfx); // effects.c in LiVES
27
28static void after_param_text_buffer_changed(LiVESTextBuffer *textbuffer, lives_rfx_t *rfx);
29
30// TODO -
31// use list of these in case we have multiple windows open
32// right now this is single threaded because of this
33static LiVESSList *usrgrp_to_livesgrp[2] = {NULL, NULL}; // ordered list of lives_widget_group_t
34
35LiVESList *do_onchange_init(lives_rfx_t *rfx) {
36 LiVESList *onchange = NULL;
37 LiVESList *retvals = NULL;
38 char **array;
39 char *type;
40
41 register int i;
42
43 if (rfx->status == RFX_STATUS_WEED) return NULL;
44
45 switch (rfx->status) {
47 type = lives_strdup(PLUGIN_RFX_SCRAP);
48 break;
50 type = lives_strdup(PLUGIN_RENDERED_EFFECTS_BUILTIN);
51 break;
53 type = lives_strdup(PLUGIN_RENDERED_EFFECTS_CUSTOM);
54 break;
55 default:
57 break;
58 }
59 if ((onchange = plugin_request_by_line(type, rfx->name, "get_onchange")) != NULL) {
60 for (i = 0; i < lives_list_length(onchange); i++) {
61 array = lives_strsplit((char *)lives_list_nth_data(onchange, i), rfx->delim, -1);
62 if (!strcmp(array[0], "init")) {
63 // onchange is init
64 // create dummy object with data
65 LiVESWidget *dummy_widget = lives_label_new(NULL);
66 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(dummy_widget), PARAM_NUMBER_KEY,
67 LIVES_INT_TO_POINTER(-1));
68 retvals = do_onchange(LIVES_WIDGET_OBJECT(dummy_widget), rfx);
69 lives_widget_destroy(dummy_widget);
70 lives_strfreev(array);
71 break;
72 }
73 lives_strfreev(array);
74 }
75 lives_list_free_all(&onchange);
76 }
77 lives_free(type);
78
79 return retvals;
80}
81
82
83static void on_paramwindow_button_clicked2(LiVESButton *button, lives_rfx_t *rfx) {
84 // close from rte window
86 lives_freep((void **)&fx_dialog[1]);
87}
88
89
90void on_paramwindow_button_clicked(LiVESButton *button, lives_rfx_t *rfx) {
91 LiVESWidget *dialog = NULL;
92 boolean def_ok = FALSE;
93 int i;
94
95 if (button) {
96 lives_widget_set_sensitive(LIVES_WIDGET(button), FALSE);
97 dialog = lives_widget_get_toplevel(LIVES_WIDGET(button));
98 }
99
100 if (dialog && LIVES_IS_DIALOG(dialog)) {
101 if (lives_dialog_get_response_for_widget(LIVES_DIALOG(dialog), LIVES_WIDGET(button)) == LIVES_RESPONSE_OK) {
102 def_ok = TRUE;
103 }
104 }
105
106 if (mainw->textwidget_focus && LIVES_IS_WIDGET_OBJECT(mainw->textwidget_focus)) {
107 // make sure text widgets are updated if they activate the default
108 LiVESWidget *textwidget =
109 (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mainw->textwidget_focus), TEXTWIDGET_KEY);
110 after_param_text_changed(textwidget, rfx);
111 }
112
113 if (!special_cleanup(def_ok)) {
114 lives_dialog_response(LIVES_DIALOG(lives_widget_get_toplevel(LIVES_WIDGET(button))), LIVES_RESPONSE_RETRY);
115 if (button) lives_widget_set_sensitive(LIVES_WIDGET(button), TRUE);
116 return;
117 }
118
119 mainw->textwidget_focus = NULL;
120
121 if (def_ok && rfx && rfx->status != RFX_STATUS_SCRAP) mainw->keep_pre = mainw->did_rfx_preview;
122
124
125 if (mainw->did_rfx_preview) {
126 if (def_ok) {
127 for (i = 0; i < rfx->num_params; i++) {
128 if (rfx->params[i].changed) {
130 break;
131 }
132 }
133 }
134
135 if (!mainw->keep_pre) {
137
138 if (cfile->start == 0) {
139 cfile->start = 1;
140 cfile->end = cfile->frames;
141 }
142
143 do_rfx_cleanup(rfx);
145 }
147 }
148
149 if (!def_ok) {
152 rfx->name && rfx->status != RFX_STATUS_WEED && rfx->status != RFX_STATUS_SCRAP &&
153 rfx->num_in_channels == 0 && rfx->min_frames >= 0 && !rfx->is_template) {
154 // for a generator, we silently close the (now) temporary file we would have generated frames into
160 rfx->source = NULL;
162 }
164 }
165
166 if (!rfx) {
167 if (usrgrp_to_livesgrp[1]) lives_slist_free(usrgrp_to_livesgrp[1]);
168 usrgrp_to_livesgrp[1] = NULL;
169 } else {
170 if (rfx->status == RFX_STATUS_WEED) {
171 if (usrgrp_to_livesgrp[1]) lives_slist_free(usrgrp_to_livesgrp[1]);
172 usrgrp_to_livesgrp[1] = NULL;
174 rfx_free(rfx);
175 lives_free(rfx);
176 }
177 } else {
178 if (usrgrp_to_livesgrp[0]) lives_slist_free(usrgrp_to_livesgrp[0]);
179 usrgrp_to_livesgrp[0] = NULL;
180 }
181 }
182
184
185 if (def_ok && rfx && rfx->status == RFX_STATUS_SCRAP) return;
186
187 if (button)
188 if (dialog) {
189 // prevent a gtk+ crash by removing the focus before detroying the dialog
190 LiVESWidget *content_area = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
191 lives_container_set_focus_child(LIVES_CONTAINER(content_area), NULL);
192 }
193
194 lives_general_button_clicked(button, NULL);
195
196 if (def_ok) {
197 if (rfx->status == RFX_STATUS_WEED) on_realfx_activate(NULL, rfx);
198 else on_render_fx_activate(NULL, rfx);
199 }
200
201 if (mainw->multitrack) {
205 }
206}
207
208
212static lives_widget_group_t *get_group(lives_rfx_t *rfx, lives_param_t *param) {
213 if (rfx->status == RFX_STATUS_WEED) {
214 return livesgrp_from_usrgrp(usrgrp_to_livesgrp[1], param->group);
215 } else {
216 return livesgrp_from_usrgrp(usrgrp_to_livesgrp[0], param->group);
217 }
218 return NULL;
219}
220
221
222void on_render_fx_activate(LiVESMenuItem *menuitem, lives_rfx_t *rfx) {
223 uint32_t chk_mask = 0;
224
225 if (menuitem && rfx->num_in_channels > 0) {
227 if (!check_for_layout_errors(NULL, mainw->current_file, cfile->start, cfile->end, &chk_mask)) {
228 return;
229 }
230 }
231
232 // do onchange|init
233 if (menuitem) {
234 LiVESList *retvals = do_onchange_init(rfx);
235 lives_list_free_all(&retvals);
236 }
237 if (rfx->min_frames > -1) {
238 do_effect(rfx, FALSE);
239 }
240
241 if (chk_mask != 0) popup_lmap_errors(NULL, LIVES_INT_TO_POINTER(chk_mask));
242}
243
244
245static void gen_width_changed(LiVESSpinButton *spin, livespointer user_data) {
246 weed_plant_t *ctmpl = (weed_plant_t *)user_data;
248 int error, old_val = 0;
249 int step;
250 // value in chantmp in pixels, not macropixels
251 if (weed_plant_has_leaf(ctmpl, WEED_LEAF_HOST_WIDTH)) old_val = weed_get_int_value(ctmpl, WEED_LEAF_HOST_WIDTH, &error);
252 if (val == old_val) return;
253 step = 1;
254 if (weed_plant_has_leaf(ctmpl, WEED_LEAF_HSTEP)) step = weed_get_int_value(ctmpl, WEED_LEAF_HSTEP, &error);
255
256 val = ALIGN_CEIL(val, step);
257 weed_set_int_value(ctmpl, WEED_LEAF_HOST_WIDTH, val);
258 lives_spin_button_set_value(spin, (double)val);
259}
260
261
262static void gen_height_changed(LiVESSpinButton *spin, livespointer user_data) {
263 weed_plant_t *ctmpl = (weed_plant_t *)user_data;
265 int error, old_val = 0;
266 int step;
267
268 if (weed_plant_has_leaf(ctmpl, WEED_LEAF_HOST_HEIGHT)) old_val = weed_get_int_value(ctmpl, WEED_LEAF_HOST_HEIGHT, &error);
269
270 if (val == old_val) return;
271 step = 1;
272 if (weed_plant_has_leaf(ctmpl, WEED_LEAF_HSTEP)) step = weed_get_int_value(ctmpl, WEED_LEAF_HSTEP, &error);
273
274 val = ALIGN_CEIL(val, step);
275 weed_set_int_value(ctmpl, WEED_LEAF_HOST_HEIGHT, val);
276 lives_spin_button_set_value(spin, (double)val);
277}
278
279
280static void gen_fps_changed(LiVESSpinButton *spin, livespointer user_data) {
281 weed_plant_t *filter = (weed_plant_t *)user_data;
282 double val = lives_spin_button_get_value(spin);
283 weed_set_double_value(filter, WEED_LEAF_HOST_FPS, val);
284}
285
286
287static void trans_in_out_pressed(lives_rfx_t *rfx, boolean in) {
288 weed_plant_t **in_params;
289
290 weed_plant_t *inst = (weed_plant_t *)rfx->source;
291 weed_plant_t *filter = weed_instance_get_filter(inst, TRUE);
292 weed_plant_t *tparam;
293 weed_plant_t *tparamtmpl;
294
295 int key = -1;
296 int ptype, nparams;
297 int trans = get_transition_param(filter, FALSE);
298
299 do {
300 // handle compound fx
301 if (weed_plant_has_leaf(inst, WEED_LEAF_IN_PARAMETERS)) {
302 nparams = weed_leaf_num_elements(inst, WEED_LEAF_IN_PARAMETERS);
303 if (trans < nparams) break;
304 trans -= nparams;
305 }
306 } while (weed_plant_has_leaf(inst, WEED_LEAF_HOST_NEXT_INSTANCE) &&
307 (inst = weed_get_plantptr_value(inst, WEED_LEAF_HOST_NEXT_INSTANCE, NULL)) != NULL);
308
309 in_params = weed_instance_get_in_params(inst, NULL);
310 tparam = in_params[trans];
311 tparamtmpl = weed_param_get_template(tparam);
312 ptype = weed_paramtmpl_get_type(tparamtmpl);
313
314 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
315 if (!filter_mutex_trylock(key)) {
316 if (ptype == WEED_PARAM_INTEGER) {
317 if (in) weed_set_int_value(tparam, WEED_LEAF_VALUE, weed_get_int_value(tparamtmpl, WEED_LEAF_MIN, NULL));
318 else weed_set_int_value(tparam, WEED_LEAF_VALUE, weed_get_int_value(tparamtmpl, WEED_LEAF_MAX, NULL));
319 } else {
320 if (in) weed_set_double_value(tparam, WEED_LEAF_VALUE, weed_get_double_value(tparamtmpl, WEED_LEAF_MIN, NULL));
321 else weed_set_double_value(tparam, WEED_LEAF_VALUE, weed_get_double_value(tparamtmpl, WEED_LEAF_MAX, NULL));
322 }
324 set_copy_to(inst, trans, rfx, TRUE);
325 }
326
328 lives_free(in_params);
330}
331
332
333static void transition_in_pressed(LiVESToggleButton *tbut, livespointer rfx) {
334 trans_in_out_pressed((lives_rfx_t *)rfx, TRUE);
335}
336
337
338static void transition_out_pressed(LiVESToggleButton *tbut, livespointer rfx) {
339 trans_in_out_pressed((lives_rfx_t *)rfx, FALSE);
340}
341
342
343static void after_transaudio_toggled(LiVESToggleButton *togglebutton, livespointer rfx) {
344 weed_plant_t *init_event = mainw->multitrack->init_event;
345
346 if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(togglebutton)))
347 weed_set_boolean_value(init_event, WEED_LEAF_HOST_AUDIO_TRANSITION, WEED_TRUE);
348 else weed_set_boolean_value(init_event, WEED_LEAF_HOST_AUDIO_TRANSITION, WEED_FALSE);
349}
350
351
352void transition_add_in_out(LiVESBox *vbox, lives_rfx_t *rfx, boolean add_audio_check) {
353 // add in/out radios for multitrack transitions
354 LiVESWidget *radiobutton_in;
355 LiVESWidget *radiobutton_out;
356 LiVESWidget *radiobutton_dummy;
357 LiVESWidget *hbox, *hbox2;
358 LiVESWidget *hseparator;
359
360 LiVESSList *radiobutton_group = NULL;
361
362 weed_plant_t *filter = weed_instance_get_filter((weed_plant_t *)rfx->source, TRUE);
363 int trans = get_transition_param(filter, FALSE);
364
365 char *tmp, *tmp2;
366
367 hbox = lives_hbox_new(FALSE, 0);
368 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_width);
369
370 if (add_audio_check) {
371 int error;
372
373 LiVESWidget *checkbutton;
374
375 hbox2 = lives_hbox_new(FALSE, 0);
376
377 if (has_video_chans_in(filter, FALSE))
378 lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, widget_opts.packing_width);
379
380 checkbutton = lives_standard_check_button_new((tmp = (_("_Crossfade audio"))),
381 weed_plant_has_leaf(mainw->multitrack->init_event, WEED_LEAF_HOST_AUDIO_TRANSITION) &&
382 weed_get_boolean_value(mainw->multitrack->init_event, WEED_LEAF_HOST_AUDIO_TRANSITION, &error) == WEED_TRUE,
383 LIVES_BOX(hbox2), (tmp2 = lives_strdup(
384 _("If checked, audio from both layers is mixed relative to the transition parameter.\n"
385 "The setting is applied instantly to the entire transition."))));
386
387 lives_free(tmp);
388 lives_free(tmp2);
389
390 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
391 LIVES_GUI_CALLBACK(after_transaudio_toggled),
392 (livespointer)rfx);
393
394 after_transaudio_toggled(LIVES_TOGGLE_BUTTON(checkbutton), (livespointer)rfx);
395 }
396
397 // dummy radiobutton so we can have neither in nor out set
398 radiobutton_dummy = lives_standard_radio_button_new(NULL, &radiobutton_group, LIVES_BOX(hbox), NULL);
399 lives_widget_set_no_show_all(radiobutton_dummy, TRUE);
400
402 radiobutton_out = lives_standard_radio_button_new((tmp = (_("Transition _Out"))),
403 &radiobutton_group, LIVES_BOX(hbox),
404 (tmp2 = (_("Click to set the transition parameter to show only the rear frame"))));
405
406 lives_free(tmp);
407 lives_free(tmp2);
408
409 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(radiobutton_out), LIVES_WIDGET_TOGGLED_SIGNAL,
410 LIVES_GUI_CALLBACK(transition_out_pressed),
411 (livespointer)rfx);
412
413 radiobutton_in = lives_standard_radio_button_new((tmp = (_("Transition _In"))),
414 &radiobutton_group, LIVES_BOX(hbox),
415 (tmp2 = (_("Click to set the transition parameter to show only the front frame"))));
416 lives_free(tmp); lives_free(tmp2);
417
418 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(radiobutton_in), LIVES_WIDGET_TOGGLED_SIGNAL,
419 LIVES_GUI_CALLBACK(transition_in_pressed), (livespointer)rfx);
420
422
423 if (palette->style & STYLE_1) {
424 lives_widget_set_fg_color(hbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
425 }
426
427 hseparator = lives_hseparator_new();
428 lives_box_pack_start(vbox, hseparator, FALSE, FALSE, 0);
429
430 rfx->params[trans].widgets[WIDGET_RB_IN] = radiobutton_in;
431 rfx->params[trans].widgets[WIDGET_RB_OUT] = radiobutton_out;
432 rfx->params[trans].widgets[WIDGET_RB_DUMMY] = radiobutton_dummy;
433}
434
435
436static boolean add_sizes(LiVESBox *vbox, boolean add_fps, boolean has_param, lives_rfx_t *rfx) {
437 // add size settings for generators and resize effects
438 LiVESWidget *label, *hbox;
439 LiVESWidget *spinbuttonh = NULL, *spinbuttonw = NULL;
440 LiVESWidget *spinbuttonf;
441 int num_chans = 0;
442
443 weed_plant_t *filter = weed_instance_get_filter((weed_plant_t *)rfx->source, TRUE), *tmpl;
444 weed_plant_t **ctmpls = weed_get_plantptr_array_counted(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, &num_chans);
445
446 double def_fps = 0.;
447
448 char *cname, *ltxt;
449
450 boolean chk_params = (vbox == NULL);
451 boolean added = FALSE;
452
453 int def_width = 0, max_width, width_step;
454 int def_height = 0, max_height, height_step;
455 int wopw = widget_opts.packing_width;
456
457 register int i;
458
459 if (chk_params) {
460 if (add_fps) return TRUE;
461 } else {
462 if (!has_param) lives_widget_set_size_request(LIVES_WIDGET(vbox), RFX_WINSIZE_H, RFX_WINSIZE_V);
463
464 if (add_fps) {
465 added = TRUE;
466
467 hbox = lives_hbox_new(FALSE, 0);
468 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height * 2);
469
470 add_fill_to_box(LIVES_BOX(hbox));
471
472 if (weed_plant_has_leaf(filter, WEED_LEAF_HOST_FPS)) def_fps = weed_get_double_value(filter, WEED_LEAF_HOST_FPS, NULL);
473 else if (weed_plant_has_leaf(filter, WEED_LEAF_PREFERRED_FPS))
474 def_fps = weed_get_double_value(filter, WEED_LEAF_PREFERRED_FPS, NULL);
475
476 if (def_fps == 0.) def_fps = prefs->default_fps;
477
478 spinbuttonf = lives_standard_spin_button_new(_("Target _FPS (plugin may override this)"),
479 def_fps, 1., FPS_MAX, 1., 10., 3, LIVES_BOX(hbox), NULL);
480
481 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbuttonf), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
482 LIVES_GUI_CALLBACK(gen_fps_changed), filter);
483
484 add_fill_to_box(LIVES_BOX(hbox));
485 }
486 }
487
488 for (i = 0; i < num_chans; i++) {
489 tmpl = ctmpls[i];
490
491 // TODO ***: allow alteration of "host_disabled" under some circumstances
492 // (e.g. allow enabling a first or second in channel, or first out_channel, or more for alphas)
493
494 // make this into function called from here and from effects with optional enable-able channels
495 if (weed_get_boolean_value(tmpl, WEED_LEAF_HOST_DISABLED, NULL) == WEED_TRUE) continue;
496 if (weed_get_int_value(tmpl, WEED_LEAF_WIDTH, NULL)) continue;
497 if (weed_get_int_value(tmpl, WEED_LEAF_HEIGHT, NULL)) continue;
498
499 if (chk_params) return TRUE;
500
501 added = TRUE;
502
503 if (rfx->is_template) {
504 cname = weed_get_string_value(tmpl, WEED_LEAF_NAME, NULL);
505 ltxt = lives_strdup_printf(_("%s : size"), cname);
506 lives_free(cname);
507 } else {
508 ltxt = (_("New size (pixels)"));
509 }
510
511 label = lives_standard_label_new(ltxt);
512 lives_free(ltxt);
513
514 hbox = lives_hbox_new(FALSE, 0);
516 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, widget_opts.packing_width);
517
518 def_width = weed_get_int_value(tmpl, WEED_LEAF_HOST_WIDTH, NULL);
519 if (!def_width) def_width = DEF_GEN_WIDTH;
520 max_width = weed_get_int_value(tmpl, WEED_LEAF_MAXWIDTH, NULL);
521 if (!max_width) max_width = INT_MAX;
522 if (def_width > max_width) def_width = max_width;
523 width_step = weed_get_int_value(tmpl, WEED_LEAF_HSTEP, NULL);
524 if (!width_step) width_step = 4;
525
526 spinbuttonw = lives_standard_spin_button_new(_("_Width"), def_width, width_step, max_width, width_step,
527 width_step, 0, LIVES_BOX(hbox), NULL);
528 lives_spin_button_set_snap_to_multiples(LIVES_SPIN_BUTTON(spinbuttonw), width_step);
529 lives_spin_button_update(LIVES_SPIN_BUTTON(spinbuttonw));
530
531 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbuttonw), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
532 LIVES_GUI_CALLBACK(gen_width_changed), tmpl);
533 weed_leaf_delete(tmpl, WEED_LEAF_HOST_WIDTH); // force a reset
534 gen_width_changed(LIVES_SPIN_BUTTON(spinbuttonw), tmpl);
535
537 add_fill_to_box(LIVES_BOX(hbox));
539
540 def_height = weed_get_int_value(tmpl, WEED_LEAF_HOST_HEIGHT, NULL);
541 if (!def_height) def_height = DEF_GEN_HEIGHT;
542 max_height = weed_get_int_value(tmpl, WEED_LEAF_MAXHEIGHT, NULL);
543 if (!max_height) max_height = INT_MAX;
544 if (def_height > max_height) def_height = max_height;
545 height_step = weed_get_int_value(tmpl, WEED_LEAF_VSTEP, NULL);
546 if (!height_step) height_step = 4;
547
548 spinbuttonh = lives_standard_spin_button_new(_("_Height"), def_height, height_step, max_height, height_step,
549 height_step, 0, LIVES_BOX(hbox), NULL);
550 lives_spin_button_set_snap_to_multiples(LIVES_SPIN_BUTTON(spinbuttonh), height_step);
551 lives_spin_button_update(LIVES_SPIN_BUTTON(spinbuttonh));
552
553 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbuttonh), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
554 LIVES_GUI_CALLBACK(gen_height_changed), tmpl);
555 weed_leaf_delete(tmpl, WEED_LEAF_HOST_HEIGHT); // force a reset
556 gen_height_changed(LIVES_SPIN_BUTTON(spinbuttonh), tmpl);
557 }
558
559 if (!rfx->is_template && num_chans == 1) {
560 if (chk_params) return TRUE;
561 added = TRUE;
562 // add "aspectratio" widget
563 add_aspect_ratio_button(LIVES_SPIN_BUTTON(spinbuttonw), LIVES_SPIN_BUTTON(spinbuttonh), LIVES_BOX(vbox));
564 }
565
566 if (added) {
567 if (has_param) {
568 add_fill_to_box(LIVES_BOX(vbox));
569 add_hsep_to_box(vbox);
570 } else has_param = TRUE;
571 }
572 return has_param;
573}
574
575
576static void add_gen_to(LiVESBox *vbox, lives_rfx_t *rfx) {
577 // add "generate to clipboard/new clip" for rendered generators
578 LiVESSList *radiobutton_group = NULL;
579
580 LiVESWidget *radiobutton;
581 LiVESWidget *hseparator;
582
583 LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
584
585 char *tmp, *tmp2;
586
588
589 radiobutton = lives_standard_radio_button_new((tmp = (_("Generate to _Clipboard"))),
590 &radiobutton_group, LIVES_BOX(hbox),
591 (tmp2 = (_("Generate frames to the clipboard"))));
592
593 lives_free(tmp);
594 lives_free(tmp2);
595
597 radiobutton = lives_standard_radio_button_new((tmp = (_("Generate to _New Clip"))),
598 &radiobutton_group, LIVES_BOX(hbox),
599 (tmp2 = (_("Generate frames to a new clip"))));
601
602 lives_free(tmp);
603 lives_free(tmp2);
604
605 hseparator = lives_hseparator_new();
606 lives_box_pack_start(vbox, hseparator, FALSE, FALSE, 0);
607
608 toggle_toggles_var(LIVES_TOGGLE_BUTTON(radiobutton), &mainw->gen_to_clipboard, TRUE);
609}
610
611
612static void xspinw_changed(LiVESSpinButton *spinbutton, livespointer user_data) {
613 cfile->ohsize = cfile->hsize = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
615}
616
617static void xspinh_changed(LiVESSpinButton *spinbutton, livespointer user_data) {
618 cfile->ovsize = cfile->vsize = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
620}
621
622static void xspinfr_changed(LiVESSpinButton *spinbutton, livespointer user_data) {
623 cfile->end = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
624}
625
626static void xspinfps_changed(LiVESSpinButton *spinbutton, livespointer user_data) {
627 cfile->pb_fps = cfile->fps = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
629}
630
631static void add_genparams(LiVESWidget *vbox, lives_rfx_t *rfx) {
632 // add nframes, fps, width, heights
633 LiVESWidget *sp_width, *sp_height, *sp_frames, *sp_fps;
634 LiVESWidget *frame = add_video_options(&sp_width, cfile->hsize, &sp_height, cfile->vsize, &sp_fps, cfile->fps,
635 &sp_frames, cfile->end, TRUE, NULL);
636 lives_box_pack_start(LIVES_BOX(vbox), frame, FALSE, TRUE, 0);
637
638 lives_spin_button_update(LIVES_SPIN_BUTTON(sp_width));
639 lives_spin_button_update(LIVES_SPIN_BUTTON(sp_height));
640 if (sp_frames) lives_spin_button_update(LIVES_SPIN_BUTTON(sp_frames));
641 lives_spin_button_update(LIVES_SPIN_BUTTON(sp_fps));
642 cfile->ohsize = cfile->hsize = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_width));
643 cfile->ovsize = cfile->vsize = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_height));
644
645 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(sp_width), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
646 LIVES_GUI_CALLBACK(xspinw_changed), NULL);
647 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(sp_height), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
648 LIVES_GUI_CALLBACK(xspinh_changed), NULL);
649 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(sp_frames), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
650 LIVES_GUI_CALLBACK(xspinfr_changed), NULL);
651 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(sp_fps), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
652 LIVES_GUI_CALLBACK(xspinfps_changed), NULL);
653}
654
655
656LIVES_GLOBAL_INLINE void on_render_fx_pre_activate(LiVESMenuItem *menuitem, lives_rfx_t *rfx) {
657 _fx_dialog *fxdialog;
658 uint32_t chk_mask;
659 int start, end;
660
662 if ((rfx->props & RFX_PROPS_MAY_RESIZE && rfx->num_in_channels == 1) || rfx->min_frames < 0) {
663 start = 1;
664 end = 0;
665 } else {
666 start = cfile->start;
667 end = cfile->end;
668 }
669
670 if (rfx->num_in_channels > 0) {
672 if (!check_for_layout_errors(NULL, mainw->current_file, start, end, &chk_mask)) {
673 return;
674 }
675 }
676 fxdialog = on_fx_pre_activate(rfx, FALSE, NULL);
677 if (fxdialog) {
678 if (menuitem == LIVES_MENU_ITEM(mainw->resize_menuitem)) add_resnn_label(LIVES_DIALOG(fxdialog->dialog));
679 /* do { */
680 /* resp = lives_dialog_run(LIVES_DIALOG(fxdialog->dialog)); */
681 /* } while (resp == LIVES_RESPONSE_RETRY); */
682 }
683
684}
685
686
687_fx_dialog *on_fx_pre_activate(lives_rfx_t *rfx, boolean is_realtime, LiVESWidget *pbox) {
688 // render a pre dialog for: rendered effects (fx_dialog[0]), or rte(fx_dialog[1]), or encoder plugin, or vpp (fx_dialog[1])
689 LiVESWidget *top_dialog_vbox = NULL;
690 LiVESAccelGroup *fxw_accel_group;
691 LiVESList *retvals = NULL;
692
693 char *txt;
694
695 boolean no_process = FALSE;
696 boolean is_defaults = FALSE;
697 boolean add_reset_ok = FALSE;
698 boolean has_param;
699
700 int scrw, didx = 0;
701
702 if (mainw->multitrack) {
703 if (mainw->multitrack->idlefunc > 0) {
705 mainw->multitrack->idlefunc = 0;
706 }
708 }
709
710 if (is_realtime) {
711 didx = 1;
712 no_process = TRUE;
713 } else if (rfx->status != RFX_STATUS_WEED) {
714 retvals = do_onchange_init(rfx);
715 }
716 if (rfx->min_frames < 0) no_process = TRUE;
717
718 if (!no_process && rfx->num_in_channels == 0) {
719 int new_file;
721
722 // create a new file to generate frames into
723 if (!get_new_handle((new_file = mainw->first_free_file), NULL)) {
724 if (mainw->multitrack) {
727 }
728
729 lives_list_free_all(&retvals);
730
731 return NULL;
732 }
733
735 mainw->files[new_file]->hsize = cfile->hsize;
736 mainw->files[new_file]->vsize = cfile->vsize;
737 mainw->files[new_file]->fps = cfile->fps;
738 } else {
739 mainw->files[new_file]->hsize = DEF_GEN_WIDTH;
740 mainw->files[new_file]->vsize = DEF_GEN_HEIGHT;
741 mainw->files[new_file]->fps = DEF_FPS;
742 }
743
745 mainw->current_file = new_file;
747 rfx->source = cfile;
748
749 cfile->ohsize = cfile->hsize;
750 cfile->ovsize = cfile->vsize;
751 cfile->pb_fps = cfile->fps;
752
753 // dummy values
754 cfile->start = 1;
755 cfile->end = 100;
756 }
757
758 if (!no_process && rfx->num_in_channels > 0) {
759 // check we have a real clip open
761 lives_list_free_all(&retvals);
762 return NULL;
763 }
764 if (cfile->end - cfile->start + 1 < rfx->min_frames) {
765 lives_list_free_all(&retvals);
766 txt = lives_strdup_printf(_("\nYou must select at least %d frames to use this effect.\n\n"),
767 rfx->min_frames);
768 do_error_dialog(txt);
769 lives_free(txt);
770 return NULL;
771 }
772
773 // here we invalidate cfile->ohsize, cfile->ovsize
774 cfile->ohsize = cfile->hsize;
775 cfile->ovsize = cfile->vsize;
776
777 if (cfile->undo_action == UNDO_RESIZABLE) {
778 set_undoable(NULL, FALSE);
779 }
780 }
781
782 if (rfx->status == RFX_STATUS_WEED && rfx->is_template) is_defaults = TRUE;
783
784 if (!pbox) {
785 char *title, *defstr;
786
787 // width works well with scale 0.7
788 if (rfx->status == RFX_STATUS_WEED || no_process || (rfx->num_in_channels == 0 &&
791
792 fx_dialog[didx] = (_fx_dialog *)lives_malloc(sizeof(_fx_dialog));
793 fx_dialog[didx]->okbutton = fx_dialog[didx]->cancelbutton = fx_dialog[didx]->resetbutton = NULL;
794 fx_dialog[didx]->rfx = NULL;
795 fx_dialog[didx]->key = fx_dialog[didx]->mode = -1;
796 if (is_defaults) defstr = (_("Defaults for "));
797 else defstr = lives_strdup("");
798 title = lives_strdup_printf("%s%s", defstr, _(rfx->menu_text[0] == '_' ? rfx->menu_text + 1 : rfx->menu_text));
799
801 lives_free(defstr);
802 lives_free(title);
803 pbox = top_dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(fx_dialog[didx]->dialog));
804 fx_dialog[didx]->rfx = rfx;
806 }
807
808 if (rfx->status != RFX_STATUS_WEED && !no_process) {
809 // rendered fx preview
810
811 LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
812 lives_box_pack_start(LIVES_BOX(top_dialog_vbox), hbox, TRUE, TRUE, 0);
813
816
817 pbox = lives_vbox_new(FALSE, 0);
818 lives_box_pack_start(LIVES_BOX(hbox), pbox, TRUE, TRUE, 0);
819
822
823 // add preview window
824 if (rfx->num_in_channels > 0 || !(rfx->props & RFX_PROPS_BATCHG)) {
825 mainw->framedraw_frame = cfile->start;
826 widget_add_framedraw(LIVES_VBOX(pbox), cfile->start, cfile->end, !(rfx->props & RFX_PROPS_MAY_RESIZE),
827 cfile->hsize, cfile->vsize, rfx);
829 }
830
831 if (!(rfx->props & RFX_PROPS_BATCHG)) {
832 // connect spinbutton to preview
834 }
835 }
836
837 // add the param widgets; here we also set parameters for any special widgets in the framedraw
838 //main_thread_execute((lives_funcptr_t)make_param_box, WEED_SEED_BOOLEAN, &has_param, "vv", pbox, rfx);
839 has_param = make_param_box(LIVES_VBOX(pbox), rfx);
840
841 // update widgets from onchange_init here
842 if (top_dialog_vbox) {
843 fxw_accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
844 lives_window_add_accel_group(LIVES_WINDOW(fx_dialog[didx]->dialog), fxw_accel_group);
845
846 if (!no_process || is_defaults || rfx->status == RFX_STATUS_SCRAP) {
847 if (!is_defaults) {
848 fx_dialog[didx]->cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(fx_dialog[didx]->dialog),
849 LIVES_STOCK_CANCEL, NULL, LIVES_RESPONSE_CANCEL);
850 fx_dialog[didx]->okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(fx_dialog[didx]->dialog),
851 LIVES_STOCK_OK, NULL, LIVES_RESPONSE_OK);
852 } else add_reset_ok = TRUE;
853 } else {
854 if (rfx->status == RFX_STATUS_WEED) {
855 add_reset_ok = TRUE;
856 }
857 }
858
859 if (add_reset_ok) {
860 fx_dialog[didx]->resetbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(fx_dialog[didx]->dialog),
861 LIVES_STOCK_REVERT_TO_SAVED, _("Reset"), LIVES_RESPONSE_RESET);
862 fx_dialog[didx]->okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(fx_dialog[didx]->dialog), LIVES_STOCK_APPLY,
863 _("Set as default"), LIVES_RESPONSE_OK);
864 if (!has_param) {
865 lives_widget_set_sensitive(fx_dialog[didx]->resetbutton, FALSE);
867 }
868 }
869
870 if (fx_dialog[didx]->cancelbutton == NULL) {
871 fx_dialog[didx]->cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(fx_dialog[didx]->dialog), LIVES_STOCK_CLOSE,
872 _("_Close Window"), LIVES_RESPONSE_CANCEL);
873 }
874 lives_widget_add_accelerator(fx_dialog[didx]->cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, fxw_accel_group,
875 LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
876
877 if (fx_dialog[didx]->okbutton) {
879 } else {
880 lives_button_grab_default_special(fx_dialog[didx]->cancelbutton);
881 }
882
883 if (no_process && !is_defaults) {
884 if (!is_realtime) {
885 if (fx_dialog[didx]->okbutton)
886 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
887 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked), rfx);
888 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
889 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked), rfx);
890 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->dialog), LIVES_WIDGET_DELETE_EVENT,
891 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked), rfx);
892 } else {
893 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
894 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked2), rfx);
895 if (rfx->status == RFX_STATUS_SCRAP)
896 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
897 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked2), rfx);
898 else {
899 if (fx_dialog[didx]->okbutton)
900 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
901 LIVES_GUI_CALLBACK(rte_set_key_defs), rfx);
902 if (fx_dialog[didx]->resetbutton) {
903 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(fx_dialog[didx]->resetbutton), LIVES_WIDGET_CLICKED_SIGNAL,
904 LIVES_GUI_CALLBACK(rte_reset_defs_clicked), rfx);
905 }
906 }
907 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->dialog), LIVES_WIDGET_DELETE_EVENT,
908 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked2), rfx);
909 }
910 } else {
911 if (!is_defaults) {
912 if (fx_dialog[didx]->okbutton)
913 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
914 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked), (livespointer)rfx);
915 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
916 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked), (livespointer)rfx);
917 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->dialog), LIVES_WIDGET_DELETE_EVENT,
918 LIVES_GUI_CALLBACK(on_paramwindow_button_clicked), (livespointer)rfx);
919 } else {
920 if (fx_dialog[didx]->okbutton)
921 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(fx_dialog[didx]->okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
922 LIVES_GUI_CALLBACK(rte_set_defs_ok), rfx);
923 if (fx_dialog[didx]->resetbutton) {
924 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(fx_dialog[didx]->resetbutton), LIVES_WIDGET_CLICKED_SIGNAL,
925 LIVES_GUI_CALLBACK(rte_reset_defs_clicked), rfx);
926 }
927 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
928 LIVES_GUI_CALLBACK(rte_set_defs_cancel), rfx);
929 lives_signal_sync_connect(LIVES_GUI_OBJECT(fx_dialog[didx]->dialog), LIVES_WIDGET_DELETE_EVENT,
930 LIVES_GUI_CALLBACK(rte_set_defs_cancel), rfx);
931 }
932 }
933 }
934
935 // tweak some things to do with framedraw preview
936 if (mainw->framedraw) fd_tweak(rfx);
937
938 if (!mainw->ce_thumbs)
939 lives_widget_show_all(fx_dialog[didx]->dialog);
940
941 if (retvals) {
942 // now apply visually anything we got from onchange_init
943 param_demarshall(rfx, retvals, TRUE, TRUE);
944 lives_list_free_all(&retvals);
945 }
946 return fx_dialog[didx];
947}
948
949
950static void check_hidden_gui(weed_plant_t *inst, lives_param_t *param, int idx) {
951 weed_plant_t *wparam;
952 if (param->type == LIVES_PARAM_UNDISPLAYABLE || param->type == LIVES_PARAM_UNKNOWN)
954 if ((param->reinit & REINIT_FUNCTIONAL)
955 && weed_get_int_value(inst, WEED_LEAF_HOST_REFS, NULL) >= 2) {
956 // effect is running and user is editing the params, we should hide reinit params
957 // so as not to disturb the flow !
958 param->hidden |= HIDDEN_NEEDS_REINIT;
959 } else param->hidden &= ~HIDDEN_NEEDS_REINIT;
960
961 if (is_hidden_param(inst, idx)) param->hidden |= HIDDEN_GUI_PERM;
962
963 wparam = weed_inst_in_param(inst, idx, FALSE, FALSE);
964
965 if (wparam) {
966 if (weed_param_is_hidden(wparam, WEED_FALSE) == WEED_FALSE) {
967 if (weed_param_is_hidden(wparam, WEED_TRUE)) param->hidden |= HIDDEN_GUI_TEMP;
968 else param->hidden &= ~HIDDEN_GUI_TEMP;
969 }
970 }
971}
972
973
974static int num_in_params_for_nth_instance(weed_plant_t *inst, int idx) {
975 // get number of params for nth instance in a compound effect - gives an offset for param number within the compound
976 while (--idx > 0) inst = weed_get_plantptr_value(inst, WEED_LEAF_HOST_NEXT_INSTANCE, NULL);
977 return weed_leaf_num_elements(inst, WEED_LEAF_IN_PARAMETERS);
978}
979
980
981static boolean fmt_match(char *fmt_string) {
982 const char *myfmt = fmt_string, *xfmt = myfmt + FMT_STRING_SIZE;
983 size_t xlen = lives_strlen(myfmt), ylen;
984
985 // g_print("\nROW\n");
986 if (xlen == 0) {
987 //g_print("HSEP\n");
988 return FALSE;
989 }
990 ylen = lives_strlen(xfmt);
991 if (ylen == 0) {
992 //g_print("2HSEP\n");
993 return FALSE;
994 }
995
996 if (xlen < ylen) ylen = xlen;
997
998 for (int j = 0; j < ylen; j++) {
999 //g_print(" CF %d %d", myfmt[j], xfmt[j]);
1000 if (xfmt[j] != -1 && myfmt[j] != -1 && xfmt[j] != myfmt[j]) return FALSE;
1001 if ((xfmt[j] == -2 || myfmt[j] == -2) && xfmt[j] != myfmt[j]) return FALSE;
1002 }
1003
1004 //g_print("\nMATch\n");
1005 return TRUE;
1006}
1007
1008
1015boolean make_param_box(LiVESVBox *top_vbox, lives_rfx_t *rfx) {
1016 lives_param_t *param = NULL;
1017
1018 LiVESWidget *param_vbox = NULL;
1019 LiVESWidget *top_hbox = NULL;
1020 LiVESWidget *hbox = NULL;
1021 LiVESWidget *last_label = NULL;
1022 LiVESWidget *layoutx = NULL;
1023 LiVESWidget *dummy_label = NULL;
1024
1025 // put whole thing in scrolled window
1026 LiVESWidget *scrolledwindow;
1027
1028 LiVESList *hints = NULL;
1029 LiVESList *onchange = NULL;
1030 LiVESList *layout = NULL;
1031 LiVESList *list;
1032
1033 char **array;
1034 char label_text[256]; // max length of a label in layout hints
1035
1036 char *line;
1037 char *type = NULL;
1038 char *format = NULL;
1039
1040 char fmt_strings[MAX_FMT_STRINGS][FMT_STRING_SIZE];
1041
1042 size_t fmtlen, ll;
1043
1044 boolean used[rfx->num_params];
1045 boolean has_box = FALSE;
1046 boolean internal = FALSE;
1047 boolean noslid;
1048 boolean has_param = FALSE;
1049 boolean chk_params = FALSE;
1050 boolean needs_sizes = FALSE;
1051 boolean layout_mode = FALSE;
1052 boolean keepsmall;
1053
1054 int pnum;
1055 int length;
1056 int poffset = 0, inum = 0;
1057 int wofl = widget_opts.filler_len;
1058
1059 int num_tok;
1060
1061 int c_fmt_strings = 0;
1062 int pass;
1063 int woph = widget_opts.packing_height;
1064
1065 int i, j, k;
1066
1067 char sepnpnum[1024];
1068 size_t sepnpnumlen;
1069
1070 lives_snprintf(sepnpnum, 1024, "s%s", rfx->delim);
1071 sepnpnumlen = strlen(sepnpnum);
1072
1073 if (!top_vbox) {
1074 // just check how many non-hidden params without displaying
1075 chk_params = TRUE;
1076 } else {
1077 dummy_label = lives_label_new(NULL);
1078 lives_widget_object_ref_sink(LIVES_WIDGET_OBJECT(dummy_label));
1079
1080 mainw->textwidget_focus = NULL;
1081
1082 // initialise special widgets
1083 init_special();
1084
1085 if (rfx->status == RFX_STATUS_WEED) usrgrp_to_livesgrp[1] = NULL;
1086 else usrgrp_to_livesgrp[0] = NULL;
1087
1088 // paramwindow start, everything goes in top_hbox
1090
1091 // param_vbox holds the dynamic parameters
1093 lives_widget_set_halign(param_vbox, LIVES_ALIGN_FILL);
1094 lives_widget_set_valign(param_vbox, LIVES_ALIGN_CENTER);
1095 lives_box_pack_start(LIVES_BOX(top_hbox), param_vbox, TRUE, TRUE, widget_opts.packing_width);
1096
1097 for (i = 0; i < rfx->num_params; i++) {
1098 used[i] = FALSE;
1099 for (j = 0; j < MAX_PARAM_WIDGETS; j++) {
1100 if (rfx->params[i].transition && j > 0 && j < 4) continue;
1101 rfx->params[i].widgets[j] = NULL;
1102 }
1103 }
1104 }
1105
1106 switch (rfx->status) {
1107 case RFX_STATUS_BUILTIN:
1108 if (!chk_params) type = lives_strdup(PLUGIN_RENDERED_EFFECTS_BUILTIN);
1109 break;
1110 case RFX_STATUS_CUSTOM:
1111 if (!chk_params) type = lives_strdup(PLUGIN_RENDERED_EFFECTS_CUSTOM);
1112 break;
1113 case RFX_STATUS_SCRAP:
1114 if (!chk_params) type = lives_strdup(PLUGIN_RFX_SCRAP);
1115 break;
1116 case RFX_STATUS_WEED:
1117 if (!mainw->multitrack && rfx->is_template) {
1118 weed_plant_t *filter = weed_instance_get_filter((weed_plant_t *)rfx->source, TRUE);
1119 if (enabled_in_channels(filter, FALSE) == 0 && enabled_out_channels(filter, FALSE) > 0
1120 && has_video_chans_out(filter, TRUE)) {
1121 // out channel size(s) and target_fps for generators
1122 needs_sizes = TRUE;
1123 }
1124 }
1125 // extras for converters
1126 if (weed_instance_is_resizer((weed_plant_t *)rfx->source)) {
1127 has_param = add_sizes(LIVES_BOX(param_vbox), FALSE, FALSE, rfx);
1128 if (chk_params && has_param) return TRUE;
1129 }
1130 internal = TRUE;
1131 break;
1132 default:
1133 if (!chk_params) type = lives_strdup(PLUGIN_RENDERED_EFFECTS_TEST);
1134 break;
1135 }
1136
1137 if (internal) {
1138 if (mainw->multitrack) {
1139 // extras for multitrack
1140 weed_plant_t *filter = weed_instance_get_filter((weed_plant_t *)rfx->source, TRUE);
1141 if (enabled_in_channels(filter, FALSE) == 2 && get_transition_param(filter, FALSE) != -1) {
1142 // add in/out for multitrack transition
1143 if (chk_params) return TRUE;
1144 has_param = TRUE;
1145 transition_add_in_out(LIVES_BOX(param_vbox), rfx, (mainw->multitrack->opts.pertrack_audio));
1146 }
1147 }
1148 if (!chk_params) hints = get_external_window_hints(rfx);
1149 } else {
1150 if (rfx->status != RFX_STATUS_SCRAP && rfx->num_in_channels == 0 && rfx->min_frames > -1) {
1151 if (!mainw->multitrack) {
1152 if (chk_params) return TRUE;
1153 add_gen_to(LIVES_BOX(param_vbox), rfx);
1154 } else mainw->gen_to_clipboard = FALSE;
1156 add_genparams(param_vbox, rfx);
1157 has_param = TRUE;
1158 }
1159
1160 if (!chk_params) {
1161 // do onchange|init
1162 if ((onchange = plugin_request_by_line(type, rfx->name, "get_onchange"))) {
1163 for (i = 0; i < lives_list_length(onchange); i++) {
1164 array = lives_strsplit((char *)lives_list_nth_data(onchange, i), rfx->delim, -1);
1165 if (strcmp(array[0], "init")) {
1166 // note other onchanges so we don't have to keep parsing the list
1167 int which = atoi(array[0]);
1168 if (which >= 0 && which < rfx->num_params) {
1169 rfx->params[which].onchange = TRUE;
1170 }
1171 }
1172 lives_strfreev(array);
1173 }
1174 lives_list_free_all(&onchange);
1175 }
1176 hints = plugin_request_by_line(type, rfx->name, "get_param_window");
1177 lives_free(type);
1178 }
1179 }
1180
1181 // do param window hints
1182 if (hints) {
1183 LiVESList *list;
1184 char *lstring = lives_strconcat("layout", rfx->delim, NULL);
1185 char *sstring = lives_strconcat("special", rfx->delim, NULL);
1186 char *istring = lives_strconcat("internal", rfx->delim, NULL);
1187 for (list = hints; list; list = list->next) {
1188 char *line = (char *)list->data;
1189 if (!lives_strncmp(line, lstring, 7)) {
1190 layout = lives_list_append(layout, lives_strdup(line + 7));
1191 } else if (!lives_strncmp(line, istring, 9)) {
1192 layout = lives_list_append(layout, lives_strdup(line + 9));
1193 } else if (!lives_strncmp(line, sstring, 8)) {
1194 add_to_special(line + 8, rfx); // add any special actions to the framedraw preview
1195 }
1196 }
1197 lives_list_free_all(&hints);
1198 lives_free(lstring);
1199 lives_free(sstring);
1200 lives_free(istring);
1201 }
1202
1203 lives_memset(fmt_strings, 0, MAX_FMT_STRINGS * FMT_STRING_SIZE);
1204
1205 for (pass = 0; pass < 2; pass++) {
1206 // in this mode we do 2 passes: first check if the row is similar to the following row
1207 // (ignoring any rows with just labels or hseparators)
1208 // if so we mark it as 'layoutable'
1209
1210 // to compare: make a string with the following vals: paramtype, or label (-2), or fill (-1)
1211 // following this we compare the strings
1212
1213 // if the string has the same value as its successor we will create or extend the layout
1214 if (chk_params) pass = 1;
1215 //g_print("in pass %d\n", pass);
1216
1217 list = layout;
1218 // use layout hints to build as much as we can
1219 for (i = 0; list; i++) {
1220 line = (char *)list->data;
1221 list = list->next;
1222 layout_mode = FALSE;
1223 has_box = FALSE;
1224 last_label = NULL;
1225 noslid = FALSE;
1226 if (i < MAX_FMT_STRINGS - 1) {
1227 format = fmt_strings[i];
1228 if (pass == 1 && !chk_params && (i > 0 || list)) {
1229 if (fmt_match((char *)fmt_strings[list == NULL ? i - 1 : i])) {
1230 layout_mode = TRUE;
1231 if (!layoutx) {
1233 layoutx = lives_layout_new(LIVES_BOX(param_vbox));
1234 lives_widget_set_halign(layoutx, LIVES_ALIGN_CENTER);
1236 }
1237 //g_print("LAYOUT MODE\n");
1238 }
1239 }
1240 } else if (pass == 0) break;
1241
1242 num_tok = get_token_count(line, (unsigned int)rfx->delim[0]);
1243 // ignore | inside strings
1244 array = lives_strsplit(line, rfx->delim, num_tok);
1245 if (!*(array[num_tok - 1])) num_tok--;
1246
1247 for (j = 0; j < num_tok; j++) {
1248 if (!strcmp(array[j], "nextfilter")) {
1249 // handling for compound fx - add an offset to the param number
1250 poffset += num_in_params_for_nth_instance((weed_plant_t *)rfx->source, inum);
1251 inum++;
1252 continue;
1253 }
1254
1255 if (!strcmp(array[j], "hseparator")) {
1256 // hseparator ///////////////
1257 if (pass == 1 && !chk_params) {
1258 // add a separator
1259 if (layoutx) lives_layout_add_separator(LIVES_LAYOUT(layoutx), TRUE);
1260 else add_hsep_to_box(LIVES_BOX(param_vbox));
1261 }
1262 break; // ignore anything after hseparator
1263 }
1264
1265 if (!strncmp(array[j], "p", 1) && (pnum = atoi((char *)(array[j] + 1))) >= 0
1266 && (pnum = pnum + poffset) < rfx->num_params && !used[pnum]) {
1267 // parameter, eg. p1 ////////////////////////////
1268 param = &rfx->params[pnum];
1269 if (!chk_params && !(rfx->flags & RFX_FLAGS_NO_RESET)) {
1270 rfx->params[pnum].changed = FALSE;
1271 }
1272 if (rfx->source_type == LIVES_RFX_SOURCE_WEED) {
1273 check_hidden_gui((weed_plant_t *)rfx->source, param, pnum);
1274 if (param->hidden & HIDDEN_STRUCTURAL) continue;
1275 }
1276
1277 has_param = TRUE;
1278
1279 if (pass == 0) {
1280 if ((fmtlen = lives_strlen((const char *)format)) < FMT_STRING_SIZE - 1) format[fmtlen] = (unsigned char)param->type;
1281 } else {
1282 used[pnum] = TRUE;
1283 if (!has_box) {
1284 // add a new row if needed
1285 if (layoutx) lives_layout_add_row(LIVES_LAYOUT(layoutx));
1286 else {
1287 hbox = lives_hbox_new(FALSE, 0);
1288 lives_box_pack_start(LIVES_BOX(param_vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1289 }
1290 has_box = TRUE;
1291 } else {
1292 widget_opts.filler_len >>= 2;
1293 if (layoutx) lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1294 else add_fill_to_box(LIVES_BOX(hbox));
1295 widget_opts.filler_len = wofl;
1296 }
1297
1298 if (last_label) {
1299 lives_widget_set_halign(last_label, LIVES_ALIGN_START);
1300 }
1301 if (layoutx) hbox = lives_layout_hbox_new(LIVES_LAYOUT(layoutx));
1302 if (add_param_to_box(LIVES_BOX(hbox), rfx, pnum, (j == (num_tok - 1)) && !noslid)) noslid = TRUE;
1303 }
1304 } else if (!strncmp(array[j], "fill", 4)) {
1306 // (can be filln)
1307
1308 if (strlen(array[j]) == 4 || (length = atoi(array[j] + 4)) == 0) length = 1;
1309
1310 if (pass == 1) {
1311 if (!has_box) {
1312 // add a new row if needed
1313 if (layoutx) lives_layout_add_row(LIVES_LAYOUT(layoutx));
1314 else {
1315 hbox = lives_hbox_new(FALSE, 0);
1316 lives_box_pack_start(LIVES_BOX(param_vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1317 }
1318 if (layoutx) lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1319 else add_fill_to_box(LIVES_BOX(hbox));
1320 has_box = TRUE;
1321 } else {
1322 if (last_label) lives_widget_set_halign(last_label, LIVES_ALIGN_START);
1323 widget_opts.filler_len >>= 1;
1324 if (layoutx) {
1325 lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1326 lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1327 } else {
1328 add_fill_to_box(LIVES_BOX(hbox));
1329 add_fill_to_box(LIVES_BOX(hbox));
1330 }
1331 widget_opts.filler_len = wofl;
1332 }
1333 }
1334
1335 for (k = 1; k < length; k++) {
1336 if (pass == 1) {
1337 widget_opts.filler_len >>= 1;
1338 if (layoutx) {
1339 lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1340 lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1341 } else {
1342 add_fill_to_box(LIVES_BOX(hbox));
1343 add_fill_to_box(LIVES_BOX(hbox));
1344 }
1345 widget_opts.filler_len = wofl;
1346 } else if ((fmtlen = lives_strlen((const char *)format)) < FMT_STRING_SIZE) format[fmtlen] = -1;
1347 }
1348 } else if (*array[j] == '"') {
1349 // add a label
1350 if (pass == 0) {
1351 if ((fmtlen = lives_strlen((const char *)format)) < FMT_STRING_SIZE) format[fmtlen] = -2;
1352 if (has_box) last_label = dummy_label;
1353 continue;
1354 }
1355
1356 if (!has_box) {
1357 // add a new row if needed
1358 if (layoutx) lives_layout_add_row(LIVES_LAYOUT(layoutx));
1359 else {
1360 hbox = lives_hbox_new(FALSE, 0);
1361 lives_box_pack_start(LIVES_BOX(param_vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
1362 }
1363 has_box = TRUE;
1364 } else {
1365 widget_opts.filler_len >>= 1;
1366 if (layoutx) lives_layout_add_fill(LIVES_LAYOUT(layoutx), TRUE);
1367 else add_fill_to_box(LIVES_BOX(hbox));
1368 widget_opts.filler_len = wofl;
1369 }
1370
1371 ll = lives_snprintf(label_text, 256, "%s", array[j] + 1);
1372 if (ll > 255) ll = 255;
1373
1374 while (j < num_tok - 1 && label_text[ll - 1] != '"') {
1375 // handle separators within label text
1376 ll += lives_strappend(label_text, 256, rfx->delim);
1377 ll += lives_strappend(label_text, 256, array[++j]);
1378 }
1379
1380 keepsmall = TRUE;
1381 if (!last_label && !has_param) {
1382 if (j == num_tok - 1 || strncmp(array[j + 1], sepnpnum, sepnpnumlen)) keepsmall = TRUE;
1383 }
1384
1385 if (ll) {
1386 if (label_text[ll - 1] == '"') label_text[ll - 1] = 0;
1387
1388 if (!keepsmall) widget_opts.justify = LIVES_JUSTIFY_CENTER;
1389 else if (last_label) {
1390 lives_widget_set_halign(last_label, LIVES_ALIGN_START);
1391 lives_widget_set_hexpand(last_label, FALSE);
1392 }
1393
1394 if (layoutx) {
1395 last_label = lives_layout_add_label(LIVES_LAYOUT(layoutx), label_text, keepsmall);
1396 } else last_label = add_param_label_to_box(LIVES_BOX(hbox), !keepsmall, label_text);
1398 lives_widget_set_hexpand(last_label, TRUE);
1399 }
1400 }
1401 }
1402 if (!layout_mode) layoutx = NULL;
1403 lives_strfreev(array);
1404 }
1405
1406 if (!chk_params) {
1407 c_fmt_strings = i;
1408 if (pass == 1) lives_list_free_all(&layout);
1409 }
1410
1411 // add any unused parameters
1412 for (i = 0; i < rfx->num_params; i++) {
1413 if (!chk_params && !(rfx->flags & RFX_FLAGS_NO_RESET)) {
1414 rfx->params[i].changed = FALSE;
1415 if (used[i]) continue;
1416 }
1417
1418 layout_mode = FALSE;
1419 format = NULL;
1420
1421 if (c_fmt_strings + i < MAX_FMT_STRINGS - 1) {
1422 format = fmt_strings[c_fmt_strings + i];
1423 if (pass == 1 && !chk_params) {
1424 if (fmt_match((char *)fmt_strings[i + c_fmt_strings])) {
1425 layout_mode = TRUE;
1426 if (!layoutx) {
1428 layoutx = lives_layout_new(LIVES_BOX(param_vbox));
1429 lives_widget_set_halign(layoutx, LIVES_ALIGN_CENTER);
1431 }
1432 //g_print("LAYOUT MODE\n");
1433 }
1434 }
1435 } else if (pass == 0) break;
1436
1437 if (rfx->source_type == LIVES_RFX_SOURCE_WEED) {
1438 check_hidden_gui((weed_plant_t *)rfx->source, &rfx->params[i], i);
1439 if (rfx->params[i].hidden & HIDDEN_STRUCTURAL) continue;
1440 }
1441
1442 if (chk_params) return TRUE;
1443
1444 has_param = TRUE;
1445 if (pass == 0) {
1446 if ((fmtlen = lives_strlen((const char *)format)) < FMT_STRING_SIZE) format[fmtlen] =
1447 (unsigned char)(rfx->params[i].type);
1448 } else {
1449 if (layoutx) {
1450 add_param_to_box(LIVES_BOX(lives_layout_row_new(LIVES_LAYOUT(layoutx))), rfx, i, TRUE);
1451 } else add_param_to_box(LIVES_BOX(param_vbox), rfx, i, TRUE);
1452 }
1453 if (!layout_mode) layoutx = NULL;
1454 }
1455 }
1456
1457 if (needs_sizes) has_param = add_sizes(chk_params ? NULL : LIVES_BOX(top_vbox), TRUE, has_param, rfx);
1458 if (chk_params) return has_param;
1459
1460 if (!has_param) {
1461 widget_opts.justify = LIVES_JUSTIFY_CENTER;
1462 LiVESWidget *label = lives_standard_label_new(_("No parameters"));
1463 hbox = lives_hbox_new(FALSE, 0);
1464 lives_box_pack_start(LIVES_BOX(param_vbox), hbox, TRUE, FALSE, 0);
1465 lives_box_pack_start(LIVES_BOX(hbox), label, TRUE, FALSE, 0);
1467 }
1468
1469 if (!mainw->multitrack || rfx->status != RFX_STATUS_WEED) {
1470 float box_scale = 1.;
1471 // for resize effects we add the framedraw to get its widgets, but hide it, so the box should get extra width and less height
1472 if (rfx->props & RFX_PROPS_MAY_RESIZE) box_scale = 1.5 * widget_opts.scale;
1473 scrolledwindow = lives_standard_scrolled_window_new(RFX_WINSIZE_H * box_scale, RFX_WINSIZE_V >> 1, top_hbox);
1474 } else scrolledwindow = lives_standard_scrolled_window_new(-1, -1, top_hbox);
1475
1476 lives_box_pack_start(LIVES_BOX(top_vbox), scrolledwindow, TRUE, TRUE, 0);
1477 lives_widget_destroy(dummy_label);
1478 if (has_param)
1479 update_widget_vis(rfx, -1, -1);
1480 return has_param;
1481}
1482
1483
1484boolean add_param_to_box(LiVESBox *box, lives_rfx_t *rfx, int pnum, boolean add_slider) {
1485 // box here is vbox inside top_hbox inside top_dialog
1486
1487 // add paramter pnum for rfx to box
1488
1489 LiVESWidget *label;
1490 LiVESWidget *checkbutton;
1491 LiVESWidget *radiobutton;
1492 LiVESWidget *spinbutton;
1493 LiVESWidget *scale = NULL;
1494 LiVESWidget *spinbutton_red;
1495 LiVESWidget *spinbutton_green;
1496 LiVESWidget *spinbutton_blue;
1497 LiVESWidget *cbutton;
1498 LiVESWidget *entry = NULL;
1499 LiVESWidget *hbox;
1500 LiVESWidget *combo;
1501 //LiVESWidget *dlabel = NULL;
1502 LiVESWidget *textview = NULL;
1503 LiVESWidget *scrolledwindow;
1504 LiVESWidget *layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(box),
1506
1507 LiVESAdjustment *spinbutton_adj;
1508
1509 LiVESTextBuffer *textbuffer = NULL;
1510
1511 lives_param_t *param;
1512 lives_widget_group_t *group;
1513 LiVESSList *rbgroup;
1514
1515 lives_colRGB48_t rgb;
1516 lives_colRGBA64_t rgba;
1517
1518 char *name;
1519 char *txt;//, *tmp;
1520 //char *disp_string;
1521
1522 int wcount = 0;
1523
1524 boolean use_mnemonic;
1525 boolean was_num = FALSE;
1526
1527 boolean add_scalers = TRUE;
1528
1529 if (pnum >= rfx->num_params) {
1530 add_param_label_to_box(box, FALSE, (_("Invalid parameter")));
1531 return FALSE;
1532 }
1533
1534 param = &rfx->params[pnum];
1535
1536 name = lives_strdup_printf("%s", param->label);
1537 use_mnemonic = param->use_mnemonic;
1538
1539 // reinit can cause the window to be redrawn, which invalidates the slider adjustment...and bang !
1540 // so dont add sliders for such params
1541 if (param->reinit) add_scalers = FALSE;
1542
1543 // for plugins (encoders and video playback) sliders look silly
1544 if (rfx->flags & RFX_FLAGS_NO_SLIDERS) add_scalers = FALSE;
1545
1546 if (LIVES_IS_HBOX(LIVES_WIDGET(box))) {
1547 hbox = LIVES_WIDGET(box);
1548 } else {
1549 hbox = lives_hbox_new(FALSE, 0);
1551 }
1552
1553 // see if there were any 'special' hints
1554 if (!layout)
1555 check_for_special_type(rfx, param, LIVES_BOX(lives_widget_get_parent(LIVES_WIDGET(box))));
1556 else
1557 check_for_special_type(rfx, param, LIVES_BOX(lives_widget_get_parent(layout)));
1558
1559 switch (param->type) {
1560 case LIVES_PARAM_BOOL:
1561 if (!param->group) {
1562 widget_opts.mnemonic_label = use_mnemonic;
1563 checkbutton = lives_standard_check_button_new(name, get_bool_param(param->value), (LiVESBox *)hbox, param->desc);
1564 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
1565 LIVES_GUI_CALLBACK(after_boolean_param_toggled),
1566 (livespointer)rfx);
1568
1569 // store parameter so we know whose trigger to use
1570 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(checkbutton), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1571 param->widgets[0] = checkbutton;
1572 } else {
1573 group = get_group(rfx, param);
1574
1575 if (group) rbgroup = group->rbgroup;
1576 else rbgroup = NULL;
1577
1578 widget_opts.mnemonic_label = use_mnemonic;
1579 radiobutton = lives_standard_radio_button_new(name, &rbgroup, LIVES_BOX(hbox), param->desc);
1581
1582 if (group == NULL) {
1583 if (rfx->status == RFX_STATUS_WEED) {
1584 usrgrp_to_livesgrp[1] = add_usrgrp_to_livesgrp(usrgrp_to_livesgrp[1],
1585 rbgroup, param->group);
1586 } else {
1587 usrgrp_to_livesgrp[0] = add_usrgrp_to_livesgrp(usrgrp_to_livesgrp[0],
1588 rbgroup, param->group);
1589 }
1590 }
1591
1592 group = get_group(rfx, param);
1593
1594 if (group) {
1595 group->rbgroup = rbgroup;
1596 if (get_bool_param(param->value)) {
1597 group->active_param = pnum + 1;
1598 }
1599 } else LIVES_WARN("Button group was NULL");
1600
1601 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(radiobutton), get_bool_param(param->value));
1602
1603 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
1604 LIVES_GUI_CALLBACK(after_boolean_param_toggled), (livespointer)rfx);
1605
1606 // store parameter so we know whose trigger to use
1607 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(radiobutton), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1608 param->widgets[0] = radiobutton;
1609 }
1610 param->widgets[1] = widget_opts.last_label;
1611 break;
1612
1613 case LIVES_PARAM_NUM:
1614 was_num = TRUE;
1615
1616 widget_opts.mnemonic_label = use_mnemonic;
1617 if (param->dp) {
1618 spinbutton = lives_standard_spin_button_new(name, get_double_param(param->value), param->min,
1619 param->max, param->step_size, param->step_size, param->dp,
1620 (LiVESBox *)hbox, param->desc);
1621 } else {
1622 spinbutton = lives_standard_spin_button_new(name, (double)get_int_param(param->value), param->min,
1623 param->max, param->step_size, param->step_size, param->dp,
1624 (LiVESBox *)hbox, param->desc);
1625 }
1627
1628 lives_spin_button_set_wrap(LIVES_SPIN_BUTTON(spinbutton), param->wrap);
1629
1630 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbutton), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
1631 LIVES_GUI_CALLBACK(after_param_value_changed), (livespointer)rfx);
1632
1633 // store parameter so we know whose trigger to use
1634 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1635 param->widgets[0] = spinbutton;
1636 param->widgets[++wcount] = widget_opts.last_label;
1637 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(param->widgets[0]), RFX_KEY, rfx);
1638
1639 if (add_scalers) {
1640 spinbutton_adj = lives_spin_button_get_adjustment(LIVES_SPIN_BUTTON(spinbutton));
1641#ifdef ENABLE_GIW
1642 if (prefs->lamp_buttons) {
1643 scale = giw_knob_new(LIVES_ADJUSTMENT(spinbutton_adj));
1644 giw_knob_set_wrap(GIW_KNOB(scale), param->wrap);
1646 giw_knob_set_legends_digits(GIW_KNOB(scale), 0);
1647 if (layout) {
1648 hbox = lives_layout_hbox_new(LIVES_LAYOUT(layout));
1649 lives_layout_pack(LIVES_HBOX(hbox), scale);
1650 lives_widget_set_show_hide_with(spinbutton, hbox);
1651 } else
1652 lives_box_pack_start(LIVES_BOX(hbox), scale, FALSE, FALSE, widget_opts.packing_width >> 1);
1653 if (param->desc) lives_widget_set_tooltip_text(scale, param->desc);
1654 lives_widget_set_fg_color(scale, LIVES_WIDGET_STATE_NORMAL, &palette->white);
1655 lives_widget_set_fg_color(scale, LIVES_WIDGET_STATE_PRELIGHT, &palette->dark_orange);
1656 lives_widget_set_bg_color(scale, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
1657 param->widgets[++wcount] = scale;
1658 }
1659#endif
1660
1661 if (add_slider && !param->wrap && (param->dp || param->transition)) {
1662 spinbutton_adj = lives_spin_button_get_adjustment(LIVES_SPIN_BUTTON(spinbutton));
1663 scale = lives_standard_hscale_new(LIVES_ADJUSTMENT(spinbutton_adj));
1665 if (layout) {
1666 hbox = lives_layout_hbox_new(LIVES_LAYOUT(layout));
1667 lives_layout_pack(LIVES_HBOX(hbox), scale);
1668 lives_widget_set_show_hide_with(spinbutton, hbox);
1669 } else {
1670 lives_box_pack_start(LIVES_BOX(hbox), scale, TRUE, TRUE, widget_opts.packing_width >> 1);
1671 if (!LIVES_IS_HBOX(LIVES_WIDGET(box))) add_fill_to_box(LIVES_BOX(hbox));
1672 }
1673 lives_widget_apply_theme(scale, LIVES_WIDGET_STATE_NORMAL);
1674 if (param->desc) lives_widget_set_tooltip_text(scale, param->desc);
1675 param->widgets[++wcount] = scale;
1676 }
1677 }
1678
1679 if (param->desc) lives_widget_set_tooltip_text(scale, param->desc);
1680 break;
1681
1683 get_colRGB24_param(param->value, &rgb);
1684
1685 rgba.red = rgb.red << 8;
1686 rgba.green = rgb.green << 8;
1687 rgba.blue = rgb.blue << 8;
1688 rgba.alpha = 65535;
1689
1690 widget_opts.mnemonic_label = use_mnemonic;
1691 cbutton = lives_standard_color_button_new(LIVES_BOX(hbox), _(name), FALSE, &rgba, &spinbutton_red, &spinbutton_green,
1692 &spinbutton_blue, NULL);
1695
1696 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(cbutton), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1697 if (param->desc) lives_widget_set_tooltip_text(cbutton, param->desc);
1698
1699 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbutton_red), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
1700 LIVES_GUI_CALLBACK(after_param_red_changed), (livespointer)rfx);
1701 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbutton_green), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
1702 LIVES_GUI_CALLBACK(after_param_green_changed), (livespointer)rfx);
1703 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(spinbutton_blue), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
1704 LIVES_GUI_CALLBACK(after_param_blue_changed), (livespointer)rfx);
1705
1706 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(cbutton), LIVES_WIDGET_COLOR_SET_SIGNAL,
1707 LIVES_GUI_CALLBACK(on_pwcolsel), (livespointer)rfx);
1708
1709 // store parameter so we know whose trigger to use
1710 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_red), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1711 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_green), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1712 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_blue), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1713
1714 param->widgets[0] = spinbutton_red;
1715 param->widgets[1] = spinbutton_green;
1716 param->widgets[2] = spinbutton_blue;
1717 //param->widgets[3]=spinbutton_alpha;
1718 param->widgets[4] = cbutton;
1719 param->widgets[5] = widget_opts.last_label;
1720 break;
1721
1722 case LIVES_PARAM_STRING:
1723 if (param->max == 0.) txt = lives_strdup((char *)param->value);
1724 else txt = lives_strndup((char *)param->value, (int)param->max);
1725
1726 if (((int)param->max > RFX_TEXT_MAGIC || param->max == 0.) &&
1730 LiVESWidget *vbox = lives_vbox_new(FALSE, 0);
1731 int woat = widget_opts.apply_theme;
1732
1733 widget_opts.justify = LIVES_JUSTIFY_CENTER;
1734 if (use_mnemonic) label = lives_standard_label_new_with_mnemonic_widget(_(name), NULL);
1735 else label = lives_standard_label_new(_(name));
1737
1738 lives_box_pack_start(LIVES_BOX(hbox), vbox, TRUE, TRUE, widget_opts.packing_width);
1739 if (layout) lives_layout_expansion_row_new(LIVES_LAYOUT(layout), vbox);
1740
1741 lives_box_pack_start(LIVES_BOX(vbox), label, FALSE, FALSE, widget_opts.packing_height >> 1);
1742
1743 hbox = lives_hbox_new(FALSE, 0);
1744 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height >> 1);
1745
1746 param->widgets[0] = textview = lives_text_view_new();
1747 if (param->desc) lives_widget_set_tooltip_text(textview, param->desc);
1748 textbuffer = lives_text_view_get_buffer(LIVES_TEXT_VIEW(textview));
1749
1750 lives_signal_sync_connect_after(LIVES_WIDGET_OBJECT(textbuffer), LIVES_WIDGET_CHANGED_SIGNAL,
1751 LIVES_GUI_CALLBACK(after_param_text_buffer_changed),
1752 (livespointer) rfx);
1753
1754 lives_text_view_set_editable(LIVES_TEXT_VIEW(textview), TRUE);
1755 lives_text_view_set_wrap_mode(LIVES_TEXT_VIEW(textview), LIVES_WRAP_WORD);
1756 lives_text_view_set_cursor_visible(LIVES_TEXT_VIEW(textview), TRUE);
1757
1758 lives_text_buffer_set_text(textbuffer, txt, -1);
1759
1762 scrolledwindow = lives_standard_scrolled_window_new(-1, RFX_TEXT_SCROLL_HEIGHT, textview);
1764 widget_opts.apply_theme = woat;
1765
1766 if (mainw->multitrack == NULL)
1767 lives_widget_apply_theme3(textview, LIVES_WIDGET_STATE_NORMAL);
1768 else
1769 lives_widget_apply_theme2(textview, LIVES_WIDGET_STATE_NORMAL, TRUE);
1770
1771 lives_box_pack_start(LIVES_BOX(hbox), scrolledwindow, TRUE, TRUE, 0);
1772
1773 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(textbuffer), "textview", textview);
1774 } else {
1775 if (use_mnemonic) label = lives_standard_label_new_with_mnemonic_widget(_(name), NULL);
1776 else label = lives_standard_label_new(_(name));
1777
1778 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, widget_opts.packing_width);
1779 param->widgets[0] = entry = lives_standard_entry_new(NULL, txt, (int)param->max,
1780 (int)param->max, LIVES_BOX(hbox), param->desc);
1781
1782 if (rfx->status == RFX_STATUS_WEED && param->special_type != LIVES_PARAM_SPECIAL_TYPE_FILEREAD) {
1783 lives_signal_sync_connect_after(LIVES_WIDGET_OBJECT(entry), LIVES_WIDGET_CHANGED_SIGNAL,
1784 LIVES_GUI_CALLBACK(after_param_text_changed), (livespointer)rfx);
1785 }
1786 }
1787 param->widgets[1] = widget_opts.last_label;
1788
1789 if (param->desc) lives_widget_set_tooltip_text(label, param->desc);
1790
1791 lives_signal_sync_connect_after(LIVES_WIDGET_OBJECT(hbox), LIVES_WIDGET_SET_FOCUS_CHILD_SIGNAL,
1792 LIVES_GUI_CALLBACK(after_param_text_focus_changed),
1793 (livespointer)rfx);
1794
1795 if (use_mnemonic) lives_label_set_mnemonic_widget(LIVES_LABEL(label), param->widgets[0]);
1796
1797 lives_free(txt);
1798
1799 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), TEXTWIDGET_KEY, (livespointer)param->widgets[0]);
1800 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(param->widgets[0]), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1801 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(param->widgets[0]), RFX_KEY, rfx);
1802
1803 param->widgets[1] = label;
1804
1805 break;
1806
1809 widget_opts.mnemonic_label = use_mnemonic;
1810
1811 combo = lives_standard_combo_new(name, param->list, (LiVESBox *)hbox, param->desc);
1814
1815 if (param->list) {
1816 lives_combo_set_active_string(LIVES_COMBO(combo),
1817 (char *)lives_list_nth_data(param->list, get_int_param(param->value)));
1818 }
1819
1820 lives_signal_sync_connect_after(LIVES_WIDGET_OBJECT(combo), LIVES_WIDGET_CHANGED_SIGNAL,
1821 LIVES_GUI_CALLBACK(after_string_list_changed), (livespointer)rfx);
1822
1823 // store parameter so we know whose trigger to use
1824 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo), PARAM_NUMBER_KEY, LIVES_INT_TO_POINTER(pnum));
1825 param->widgets[0] = combo;
1826 param->widgets[1] = widget_opts.last_label;
1827 break;
1828
1829 default:
1830 break;
1831 }
1832
1833 // see if there were any 'special' hints
1834 if (!layout) {
1835 check_for_special(rfx, param, LIVES_BOX(lives_widget_get_parent(LIVES_WIDGET(box))));
1836 } else {
1837 check_for_special(rfx, param, LIVES_BOX(lives_widget_get_parent(layout)));
1838 }
1839 lives_free(name);
1840 return was_num;
1841}
1842
1843
1844LiVESWidget *add_param_label_to_box(LiVESBox *box, boolean do_trans, const char *text) {
1845 LiVESWidget *label;
1846
1847 lives_box_set_homogeneous(LIVES_BOX(box), FALSE);
1848
1849 if (do_trans) {
1850 char *markup;
1851#ifdef GUI_GTK
1852 markup = g_markup_printf_escaped("<span weight=\"bold\" style=\"italic\"> %s </span>", _(text));
1853#endif
1854#ifdef GUI_QT
1855 QString qs = QString("<span weight=\"bold\" style=\"italic\"> %s </span>").arg(_(text));
1856 markup = strdup((const char *)qs.toHtmlEscaped().constData());
1857#endif
1858 label = lives_standard_label_new(NULL);
1859 lives_label_set_markup(LIVES_LABEL(label), markup);
1860 lives_free(markup);
1861 } else label = lives_standard_label_new_with_mnemonic_widget(text, NULL);
1862
1863 if (LIVES_IS_HBOX(LIVES_WIDGET(box)))
1865 else
1867
1868 return label;
1869}
1870
1871
1872LiVESSList *add_usrgrp_to_livesgrp(LiVESSList *u2l, LiVESSList *rbgroup, int usr_number) {
1874 wgroup->usr_number = usr_number;
1875 wgroup->rbgroup = rbgroup;
1876 wgroup->active_param = 0;
1877 u2l = lives_slist_append(u2l, (livespointer)wgroup);
1878 return u2l;
1879}
1880
1881
1882lives_widget_group_t *livesgrp_from_usrgrp(LiVESSList *u2l, int usrgrp) {
1883 lives_widget_group_t *group;
1884 LiVESSList *list = u2l;
1885 for (; list; list = list->next) {
1886 group = (lives_widget_group_t *)list->data;
1887 if (group->usr_number == usrgrp) return group;
1888 }
1889 return NULL;
1890}
1891
1892
1893boolean update_widget_vis(lives_rfx_t *rfx, int key, int mode) {
1894 weed_plant_t *wparam = NULL, *inst;
1895 int keyw, modew;
1896 lives_param_t *param;
1897
1898 if (mainw->multitrack == NULL) {
1899 if (fx_dialog[1]) {
1900 rfx = fx_dialog[1]->rfx;
1901 if (!rfx->is_template) {
1902 keyw = fx_dialog[1]->key;
1903 modew = fx_dialog[1]->mode;
1904 }
1905 if (!rfx->is_template && (key != keyw && mode != modew)) return FALSE;
1906 }
1907 }
1908
1909 if ((!fx_dialog[1] && !mainw->multitrack) || !rfx || rfx->status != RFX_STATUS_WEED) return FALSE;
1910 inst = (weed_plant_t *)rfx->source;
1911 for (int i = 0; i < rfx->num_params; i++) {
1912 param = &rfx->params[i];
1913 if ((wparam = weed_inst_in_param(inst, i, FALSE, FALSE)) != NULL) {
1914 check_hidden_gui(inst, param, i);
1915 if (param->hidden & HIDDEN_STRUCTURAL) continue;
1916 for (int j = 0; j < RFX_MAX_NORM_WIDGETS; j++) {
1917 if (param->type == LIVES_PARAM_COLRGB24 && j == 3 && !param->widgets[j]) continue;
1918 if (!param->widgets[j]) break;
1919 if (param->hidden) {
1920 lives_widget_hide(param->widgets[j]);
1922 } else {
1924 lives_widget_show_all(param->widgets[j]);
1925 // *INDENT-OFF*
1926 }}}}
1927 // *INDENT-ON*
1928
1929 return TRUE;
1930}
1931
1932
1933static void after_any_changed_1(lives_rfx_t *rfx, int param_number, int index) {
1934 weed_plant_t *inst = (weed_plant_t *)rfx->source;
1935 weed_plant_t *wparam = weed_inst_in_param(inst, param_number, FALSE, FALSE), *paramtmpl;
1936 int numvals = weed_leaf_num_elements(wparam, WEED_LEAF_VALUE);
1937 int *ign, nvals;
1940 if (index >= numvals) {
1941 paramtmpl = weed_param_get_template(wparam);
1942 fill_param_vals_to(wparam, paramtmpl, index);
1943 numvals = index + 1;
1944 }
1945
1946 if (mainw->multitrack && is_perchannel_multi(rfx, param_number)) {
1947 if (weed_plant_has_leaf(wparam, WEED_LEAF_IGNORE)) {
1948 ign = weed_get_boolean_array_counted(wparam, WEED_LEAF_IGNORE, &nvals);
1949 if (index >= 0 && index < nvals) {
1950 ign[index] = WEED_FALSE;
1951 weed_set_boolean_array(wparam, WEED_LEAF_IGNORE, nvals, ign);
1952 }
1953 lives_freep((void **)&ign);
1954 }
1955 }
1956}
1957
1958
1962static void after_any_changed_2(lives_rfx_t *rfx, lives_param_t *param, boolean needs_update) {
1963 weed_plant_t *wparam = NULL, *gui, *inst = NULL;
1965
1967 if (needs_update) update_visual_params(rfx, FALSE);
1968 needs_update = FALSE;
1969
1971 if (--ireinit > 0) {
1972 param->changed = TRUE;
1973 param->change_blocked = FALSE;
1974 return;
1975 }
1976
1979 if (rfx->status == RFX_STATUS_WEED) {
1980 if (mainw->multitrack) {
1981 for (int i = 0; i < rfx->num_params; i++) {
1982 if ((wparam = weed_inst_in_param(inst, i, FALSE, FALSE)) != NULL) {
1983 if ((gui = weed_param_get_gui(wparam, FALSE)) != NULL) {
1984 if (retval != FILTER_INFO_REDRAWN) {
1985 if (weed_get_boolean_value(gui, "host_hidden_backup", NULL) != weed_get_boolean_value(gui, WEED_LEAF_HIDDEN, NULL))
1986 needs_update = TRUE;
1987 }
1988 weed_leaf_delete(gui, "host_hidden_backup");
1989 // *INDENT-OFF*
1990 }}}}
1991 // *INDENT-ON*
1992
1993 inst = (weed_plant_t *)rfx->source;
1994 if (rfx->needs_reinit) {
1995 if (!(rfx->needs_reinit & REINIT_FUNCTIONAL)) {
1996 weed_instance_set_flags(inst, weed_instance_get_flags(inst) | WEED_INSTANCE_UPDATE_GUI_ONLY);
1997 }
1998
1999 retval = weed_reinit_effect(inst, FALSE);
2000
2001 if (!(rfx->needs_reinit & REINIT_FUNCTIONAL)) {
2002 weed_instance_set_flags(inst, weed_instance_get_flags(inst) ^ WEED_INSTANCE_UPDATE_GUI_ONLY);
2003 }
2004 rfx->needs_reinit = 0;
2005 }
2006 }
2007
2008 needs_update = FALSE;
2009 rfx->needs_reinit = 0;
2010
2011 if (fx_dialog[1]) {
2012 // transfer param changes from rte_window to ce_thumbs window, and vice-versa
2013 lives_rfx_t *rte_rfx = fx_dialog[1]->rfx;
2014 int key = fx_dialog[1]->key;
2015 int mode = fx_dialog[1]->mode;
2017 if (rfx == rte_rfx && mainw->ce_thumbs) ce_thumbs_update_visual_params(key);
2018 else if (mode == rte_key_getmode(key + 1)) ce_thumbs_check_for_rte(rfx, rte_rfx, key);
2020 }
2021
2022 if (!weed_param_value_irrelevant(wparam)) {
2023 param->changed = TRUE;
2024 }
2025
2026 if (mainw->multitrack && rfx->status == RFX_STATUS_WEED) {
2027 update_widget_vis(rfx, -1, -1);
2029 }
2030
2031 param->change_blocked = FALSE;
2032}
2033
2034
2035void after_boolean_param_toggled(LiVESToggleButton * togglebutton, lives_rfx_t *rfx) {
2036 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(togglebutton), PARAM_NUMBER_KEY));
2037 LiVESList *retvals = NULL;
2038 weed_plant_t *inst = NULL;
2039 lives_param_t *param = &rfx->params[param_number];
2040 boolean old_bool = get_bool_param(param->value), new_bool;
2041 boolean needs_update = FALSE;
2042 int copyto = -1;
2043
2044 new_bool = lives_toggle_button_get_active(togglebutton);
2045 if (old_bool == new_bool) return;
2046
2048 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2049 return; // updates are blocked until all params are ready
2050 }
2051
2052 ireinit++;
2053
2054 set_bool_param(param->value, new_bool);
2056 param->change_blocked = TRUE;
2057
2058 if (rfx->status == RFX_STATUS_WEED) {
2059 inst = (weed_plant_t *)rfx->source;
2060 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2061 //char *disp_string;
2062 int index = 0, numvals;
2063 int key = -1;
2064 weed_plant_t *wparam = weed_inst_in_param(inst, param_number, FALSE, FALSE);
2065 int *valis = weed_get_boolean_array(wparam, WEED_LEAF_VALUE, NULL);
2066
2067 if (mainw->multitrack && is_perchannel_multi(rfx, param_number)) {
2068 index = mainw->multitrack->track_index;
2069 }
2070
2071 after_any_changed_1(rfx, param_number, index);
2072
2073 valis[index] = new_bool;
2074 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2075 numvals = weed_leaf_num_elements(wparam, WEED_LEAF_VALUE);
2076 if (!filter_mutex_trylock(key)) {
2077 weed_set_boolean_array(wparam, WEED_LEAF_VALUE, numvals, valis);
2078 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2079 filter_mutex_unlock(key); \
2080 if (copyto != -1) needs_update = TRUE;
2081 }
2082 lives_freep((void **)&valis);
2083
2085 // if we are recording, add this change to our event_list
2086 rec_param_change(inst, param_number);
2087 }
2088 if (param->reinit) rfx->needs_reinit |= param->reinit;
2089 }
2090 }
2091
2092 if (get_bool_param(param->value) != old_bool && param->onchange) {
2093 param->change_blocked = TRUE;
2094 retvals = do_onchange(LIVES_WIDGET_OBJECT(togglebutton), rfx);
2095 lives_list_free_all(&retvals);
2096 needs_update = TRUE;
2097 }
2098 after_any_changed_2(rfx, param, needs_update);
2099}
2100
2101
2102void after_param_value_changed(LiVESSpinButton * spinbutton, lives_rfx_t *rfx) {
2103 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), PARAM_NUMBER_KEY));
2104 LiVESList *retvals = NULL;
2105 lives_param_t *param = &rfx->params[param_number];
2106 double new_double = 0., old_double = 0.;
2107 int new_int = 0, old_int = 0;
2108 boolean needs_update = FALSE;
2109 int copyto = -1;
2110
2111 lives_spin_button_update(LIVES_SPIN_BUTTON(spinbutton));
2112
2113 if (param->dp > 0) {
2114 old_double = get_double_param(param->value);
2115 new_double = lives_spin_button_get_value(LIVES_SPIN_BUTTON(spinbutton));
2116 if (old_double == new_double) return;
2117 } else {
2118 old_int = get_int_param(param->value);
2119 new_int = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
2120 if (old_int == new_int) return;
2121 }
2122
2124 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2125 return; // updates are blocked until all params are ready
2126 }
2127
2128 ireinit++;
2129
2131
2133 (prefs->rec_opts & REC_EFFECTS)) {
2134 // if we are recording, add this (pre)change to our event_list
2135 rec_param_change((weed_plant_t *)rfx->source, param_number);
2136 copyto = set_copy_to((weed_plant_t *)rfx->source, param_number, rfx, FALSE);
2137 }
2138
2139 if (param->dp > 0) {
2140 set_double_param(param->value, new_double);
2141 } else {
2142 set_int_param(param->value, new_int);
2143 }
2144
2145 param->change_blocked = TRUE;
2146
2147 if (rfx->status == RFX_STATUS_WEED) {
2148 weed_plant_t *inst = (weed_plant_t *)rfx->source;
2149 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2150 weed_plant_t *wparam = weed_inst_in_param(inst, param_number, FALSE, FALSE);
2151 int index = 0, numvals;
2152 int key = -1;
2153 double *valds;
2154 int *valis;
2155
2156 // update transition in/out radios
2157 if (mainw->multitrack) {
2158 weed_plant_t *filter = weed_instance_get_filter(inst, TRUE);
2159 if (enabled_in_channels(filter, FALSE) == 2 && param->transition) {
2160 if (param->dp == 0) {
2161 if (new_int == (int)param->min)
2162 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[WIDGET_RB_IN]), TRUE);
2163 else if (new_int == (int)param->max)
2164 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[WIDGET_RB_OUT]), TRUE);
2165 else lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[WIDGET_RB_DUMMY]), TRUE);
2166 } else {
2167 if (new_double == param->min)
2168 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[WIDGET_RB_IN]), TRUE);
2169 else if (new_double == param->max)
2170 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[WIDGET_RB_OUT]), TRUE);
2171 else lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[WIDGET_RB_DUMMY]), TRUE);
2172 }
2173 }
2174 }
2175
2176 if (mainw->multitrack && is_perchannel_multi(rfx, param_number)) {
2177 index = mainw->multitrack->track_index;
2178 }
2179
2180 after_any_changed_1(rfx, param_number, index);
2181
2182 numvals = weed_leaf_num_elements(wparam, WEED_LEAF_VALUE);
2183 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2184 if (weed_leaf_seed_type(wparam, WEED_LEAF_VALUE) == WEED_SEED_DOUBLE) {
2185 valds = weed_get_double_array(wparam, WEED_LEAF_VALUE, NULL);
2186 if (param->dp > 0) valds[index] = new_double;
2187 else valds[index] = (double)new_int;
2188 if (!filter_mutex_trylock(key)) {
2189 weed_set_double_array(wparam, WEED_LEAF_VALUE, numvals, valds);
2190 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2192 if (copyto != -1) needs_update = TRUE;
2193 }
2194 lives_freep((void **)&valds);
2195 } else {
2196 valis = weed_get_int_array(wparam, WEED_LEAF_VALUE, NULL);
2197 valis[index] = new_int;
2198 weed_set_int_array(wparam, WEED_LEAF_VALUE, numvals, valis);
2199 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2201 if (copyto != -1) needs_update = TRUE;
2202 lives_freep((void **)&valis);
2203 }
2204 }
2205
2207 // if we are recording, add this change to our event_list
2208 rec_param_change(inst, param_number);
2209 }
2210 if (param->reinit) rfx->needs_reinit |= param->reinit;
2211 }
2212
2213 if (((param->dp > 0 && (get_double_param(param->value) != old_double)) || (param->dp == 0 &&
2214 (get_int_param(param->value) != old_int))) && param->onchange) {
2215 param->change_blocked = TRUE;
2216 retvals = do_onchange(LIVES_WIDGET_OBJECT(spinbutton), rfx);
2217 lives_list_free_all(&retvals);
2218 needs_update = TRUE;
2219 }
2220
2221 after_any_changed_2(rfx, param, needs_update);
2222}
2223
2224
2225void update_weed_color_value(weed_plant_t *plant, int pnum, int c1, int c2, int c3, int c4, lives_rfx_t *rfx) {
2226 weed_plant_t *ptmpl;
2227 weed_plant_t *param = NULL;
2228
2229 int *maxs = NULL, *mins = NULL;
2230 int cols[4] = {c1, c2, c3, c4};
2231 int cspace;
2232 int rmax, rmin, gmax, gmin, bmax, bmin;
2233
2234 boolean is_default = WEED_PLANT_IS_FILTER_CLASS(plant);
2235 boolean is_int;
2236
2237 double *maxds = NULL, *minds = NULL;
2238 double colds[4];
2239 double rmaxd, rmind, gmaxd, gmind, bmaxd, bmind;
2240
2241 if (!is_default) {
2242 param = weed_inst_in_param(plant, pnum, FALSE, FALSE);
2243 ptmpl = weed_get_plantptr_value(param, WEED_LEAF_TEMPLATE, NULL);
2244 } else {
2245 // called only from rte_set_defs_ok
2246 ptmpl = weed_filter_in_paramtmpl(plant, pnum, FALSE);
2247 }
2248
2249 if (mainw->block_param_updates) return; // updates are blocked until all params are ready
2250
2251 is_int = (weed_leaf_seed_type(ptmpl, WEED_LEAF_DEFAULT) == WEED_SEED_INT);
2252 cspace = weed_get_int_value(ptmpl, WEED_LEAF_COLORSPACE, NULL);
2253
2254 switch (cspace) {
2255 // TODO - other cspaces
2256 case WEED_COLORSPACE_RGB:
2257 if (is_int) {
2258 if (weed_leaf_num_elements(ptmpl, WEED_LEAF_MAX) == 3) {
2259 maxs = weed_get_int_array(ptmpl, WEED_LEAF_MAX, NULL);
2260 rmax = maxs[0];
2261 gmax = maxs[1];
2262 bmax = maxs[2];
2263 lives_free(maxs);
2264 } else rmax = gmax = bmax = weed_get_int_value(ptmpl, WEED_LEAF_MAX, NULL);
2265 if (weed_leaf_num_elements(ptmpl, WEED_LEAF_MIN) == 3) {
2266 mins = weed_get_int_array(ptmpl, WEED_LEAF_MIN, NULL);
2267 rmin = mins[0];
2268 gmin = mins[1];
2269 bmin = mins[2];
2270 lives_free(mins);
2271 } else rmin = gmin = bmin = weed_get_int_value(ptmpl, WEED_LEAF_MIN, NULL);
2272
2273 cols[0] = rmin + (int)((double)cols[0] / 255.*(double)(rmax - rmin));
2274 cols[1] = gmin + (int)((double)cols[1] / 255.*(double)(gmax - gmin));
2275 cols[2] = bmin + (int)((double)cols[2] / 255.*(double)(bmax - bmin));
2276 if (is_default) {
2277 weed_set_int_array(ptmpl, WEED_LEAF_HOST_DEFAULT, 3, cols);
2278 } else {
2279 int index = 0, numvals;
2280 int *valis;
2281
2282 if (mainw->multitrack && is_perchannel_multiw(ptmpl)) {
2283 index = mainw->multitrack->track_index;
2284 }
2285 numvals = weed_leaf_num_elements(param, WEED_LEAF_VALUE);
2286 if (index * 3 >= numvals) {
2287 weed_plant_t *paramtmpl = weed_get_plantptr_value(param, WEED_LEAF_TEMPLATE, NULL);
2288 fill_param_vals_to(param, paramtmpl, index);
2289 numvals = (index + 1) * 3;
2290 }
2291
2292 if (mainw->multitrack && is_perchannel_multi(rfx, pnum)) {
2293 if (weed_plant_has_leaf(param, WEED_LEAF_IGNORE)) {
2294 int nvals = weed_leaf_num_elements(param, WEED_LEAF_IGNORE);
2295 if (index >= 0 && index < nvals) {
2296 int *ign = weed_get_boolean_array(param, WEED_LEAF_IGNORE, NULL);
2297 ign[index] = WEED_FALSE;
2298 weed_set_boolean_array(param, WEED_LEAF_IGNORE, nvals, ign);
2299 lives_free(ign);
2300 }
2301 }
2302 }
2303
2304 valis = weed_get_int_array(param, WEED_LEAF_VALUE, NULL);
2305 valis[index * 3] = cols[0];
2306 valis[index * 3 + 1] = cols[1];
2307 valis[index * 3 + 2] = cols[2];
2308 weed_set_int_array(param, WEED_LEAF_VALUE, numvals, valis);
2309 lives_free(valis);
2310 }
2311 break;
2312 } else {
2313 // double
2314 if (weed_leaf_num_elements(ptmpl, WEED_LEAF_MAX) == 3) {
2315 maxds = weed_get_double_array(ptmpl, WEED_LEAF_MAX, NULL);
2316 rmaxd = maxds[0];
2317 gmaxd = maxds[1];
2318 bmaxd = maxds[2];
2319 lives_free(maxds);
2320 } else rmaxd = gmaxd = bmaxd = weed_get_double_value(ptmpl, WEED_LEAF_MAX, NULL);
2321 if (weed_leaf_num_elements(ptmpl, WEED_LEAF_MIN) == 3) {
2322 minds = weed_get_double_array(ptmpl, WEED_LEAF_MIN, NULL);
2323 rmind = minds[0];
2324 gmind = minds[1];
2325 bmind = minds[2];
2326 lives_free(minds);
2327 } else rmind = gmind = bmind = weed_get_double_value(ptmpl, WEED_LEAF_MIN, NULL);
2328 colds[0] = rmind + (double)cols[0] / 255.*(rmaxd - rmind);
2329 colds[1] = gmind + (double)cols[1] / 255.*(gmaxd - gmind);
2330 colds[2] = bmind + (double)cols[2] / 255.*(bmaxd - bmind);
2331 if (is_default) {
2332 weed_set_double_array(ptmpl, WEED_LEAF_HOST_DEFAULT, 3, colds);
2333 } else {
2334 int index = 0, numvals;
2335 double *valds;
2336
2337 if (mainw->multitrack && is_perchannel_multiw(ptmpl)) {
2338 index = mainw->multitrack->track_index;
2339 }
2340 numvals = weed_leaf_num_elements(param, WEED_LEAF_VALUE);
2341 if (index * 3 >= numvals) {
2342 weed_plant_t *paramtmpl = weed_get_plantptr_value(param, WEED_LEAF_TEMPLATE, NULL);
2343 fill_param_vals_to(param, paramtmpl, index);
2344 numvals = (index + 1) * 3;
2345 }
2346
2347 if (mainw->multitrack && is_perchannel_multi(rfx, pnum)) {
2348 if (weed_plant_has_leaf(param, WEED_LEAF_IGNORE)) {
2349 int nvals = weed_leaf_num_elements(param, WEED_LEAF_IGNORE);
2350 if (index >= 0 && index < nvals) {
2351 int *ign = weed_get_boolean_array(param, WEED_LEAF_IGNORE, NULL);
2352 ign[index] = WEED_FALSE;
2353 weed_set_boolean_array(param, WEED_LEAF_IGNORE, nvals, ign);
2354 lives_free(ign);
2355 }
2356 }
2357 }
2358
2359 valds = weed_get_double_array(param, WEED_LEAF_VALUE, NULL);
2360 valds[index * 3] = colds[0];
2361 valds[index * 3 + 1] = colds[1];
2362 valds[index * 3 + 2] = colds[2];
2363 weed_set_double_array(param, WEED_LEAF_VALUE, numvals, valds);
2364 lives_free(valds);
2365 }
2366 }
2367 break;
2368 }
2369}
2370
2371
2372void after_param_red_changed(LiVESSpinButton * spinbutton, lives_rfx_t *rfx) {
2373 LiVESList *retvals = NULL;
2374 lives_colRGB48_t old_value;
2375 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), PARAM_NUMBER_KEY));
2376 int new_red;
2377 boolean needs_update = FALSE;
2378 int copyto = -1;
2379 lives_param_t *param = &rfx->params[param_number];
2380
2381 get_colRGB24_param(param->value, &old_value);
2382 new_red = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
2383 if (old_value.red == new_red) return;
2384
2386 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2387 return; // updates are blocked until all params are ready
2388 }
2389
2390 ireinit++;
2391
2393 (prefs->rec_opts & REC_EFFECTS)) {
2394 // if we are recording, add this change to our event_list
2395
2396 rec_param_change((weed_plant_t *)rfx->source, param_number);
2397 copyto = set_copy_to((weed_plant_t *)rfx->source, param_number, rfx, FALSE);
2398 }
2399
2400 set_colRGB24_param(param->value, new_red, old_value.green, old_value.blue);
2401
2403 param->change_blocked = TRUE;
2404
2405 if (rfx->status == RFX_STATUS_WEED) {
2406 int key = -1;
2407 weed_plant_t *inst = (weed_plant_t *)rfx->source;
2408 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2409 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2410 if (!filter_mutex_trylock(key)) {
2411 update_weed_color_value(inst, param_number, new_red, old_value.green, old_value.blue, 0, rfx);
2412 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2414 if (copyto != -1) needs_update = TRUE;
2415 }
2416
2418 // if we are recording, add this change to our event_list
2419 rec_param_change(inst, param_number);
2420 }
2421 if (param->reinit) rfx->needs_reinit |= param->reinit;
2422 }
2423 }
2424
2425 if (new_red != old_value.red && param->onchange) {
2426 param->change_blocked = TRUE;
2427 retvals = do_onchange(LIVES_WIDGET_OBJECT(spinbutton), rfx);
2428 lives_list_free_all(&retvals);
2429 needs_update = TRUE;
2430 }
2431 after_any_changed_2(rfx, param, needs_update);
2432}
2433
2434
2435void after_param_green_changed(LiVESSpinButton * spinbutton, lives_rfx_t *rfx) {
2436 LiVESList *retvals = NULL;
2437 lives_colRGB48_t old_value;
2438 int new_green;
2439 int copyto = -1;
2440 boolean needs_update = FALSE;
2441 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), PARAM_NUMBER_KEY));
2442 lives_param_t *param = &rfx->params[param_number];
2443
2444 get_colRGB24_param(param->value, &old_value);
2445 new_green = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
2446 if (old_value.green == new_green) return;
2447
2449 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2450 return; // updates are blocked until all params are ready
2451 }
2452
2453 ireinit++;
2454
2456 (prefs->rec_opts & REC_EFFECTS)) {
2457 // if we are recording, add this change to our event_list
2458 rec_param_change((weed_plant_t *)rfx->source, param_number);
2459 copyto = set_copy_to((weed_plant_t *)rfx->source, param_number, rfx, FALSE);
2460 }
2461
2462 set_colRGB24_param(param->value, old_value.red, new_green, old_value.blue);
2463
2465 param->change_blocked = TRUE;
2466
2467 if (rfx->status == RFX_STATUS_WEED) {
2468 int key = -1;
2469 weed_plant_t *inst = (weed_plant_t *)rfx->source;
2470 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2471 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2472 if (!filter_mutex_trylock(key)) {
2473 update_weed_color_value(inst, param_number, old_value.red, new_green, old_value.blue, 0, rfx);
2474 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2476 if (copyto != -1) needs_update = TRUE;
2477 }
2478
2480 // if we are recording, add this change to our event_list
2481 rec_param_change(inst, param_number);
2482 }
2483 rfx->needs_reinit |= param->reinit;
2484 }
2485 }
2486
2487 if (new_green != old_value.green && param->onchange) {
2488 param->change_blocked = TRUE;
2489 retvals = do_onchange(LIVES_WIDGET_OBJECT(spinbutton), rfx);
2490 lives_list_free_all(&retvals);
2491 needs_update = TRUE;
2492 }
2493 after_any_changed_2(rfx, param, needs_update);
2494}
2495
2496
2497void after_param_blue_changed(LiVESSpinButton * spinbutton, lives_rfx_t *rfx) {
2498 LiVESList *retvals = NULL;
2499 lives_colRGB48_t old_value;
2500 int new_blue;
2501 int copyto = -1;
2502 boolean needs_update = FALSE;
2503 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), PARAM_NUMBER_KEY));
2504 lives_param_t *param = &rfx->params[param_number];
2505
2506 get_colRGB24_param(param->value, &old_value);
2507 new_blue = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
2508 if (old_value.blue == new_blue) return;
2509
2511 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2512 return; // updates are blocked until all params are ready
2513 }
2514
2515 ireinit++;
2516
2518 (prefs->rec_opts & REC_EFFECTS)) {
2519 // if we are recording, add this change to our event_list
2520 rec_param_change((weed_plant_t *)rfx->source, param_number);
2521 }
2522
2523 set_colRGB24_param(param->value, old_value.red, old_value.green, new_blue);
2524
2526 param->change_blocked = TRUE;
2527
2528 if (rfx->status == RFX_STATUS_WEED) {
2529 int key = -1;
2530 weed_plant_t *inst = (weed_plant_t *)rfx->source;
2531 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2532 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2533 if (!filter_mutex_trylock(key)) {
2534 update_weed_color_value(inst, param_number, old_value.red, old_value.green, new_blue, 0, rfx);
2535 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2537 if (copyto != -1) needs_update = TRUE;
2538 }
2539
2541 // if we are recording, add this change to our event_list
2542 rec_param_change(inst, param_number);
2543 }
2544 rfx->needs_reinit |= param->reinit;
2545 }
2546 }
2547
2548 if (new_blue != old_value.blue && param->onchange) {
2549 param->change_blocked = TRUE;
2550 retvals = do_onchange(LIVES_WIDGET_OBJECT(spinbutton), rfx);
2551 lives_list_free_all(&retvals);
2552 needs_update = TRUE;
2553 }
2554 after_any_changed_2(rfx, param, needs_update);
2555}
2556
2557
2558void after_param_alpha_changed(LiVESSpinButton * spinbutton, lives_rfx_t *rfx) {
2559 // not used yet
2560 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), PARAM_NUMBER_KEY));
2561 LiVESList *retvals = NULL;
2562 lives_param_t *param = &rfx->params[param_number];
2563 lives_colRGBA64_t old_value;
2564 int new_alpha = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
2565 int copyto = -1;
2566 boolean needs_update = FALSE;
2567
2569 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2570 return; // updates are blocked until all params are ready
2571 }
2572
2573 ireinit++;
2574
2576 (prefs->rec_opts & REC_EFFECTS)) {
2577 // if we are recording, add this change to our event_list
2578 rec_param_change((weed_plant_t *)rfx->source, param_number);
2579 copyto = set_copy_to((weed_plant_t *)rfx->source, param_number, rfx, FALSE);
2580 }
2581
2582 get_colRGBA32_param(param->value, &old_value);
2583
2585
2586 set_colRGBA32_param(param->value, old_value.red, old_value.green, old_value.blue, new_alpha);
2587 param->change_blocked = TRUE;
2588
2590 (prefs->rec_opts & REC_EFFECTS)) {
2591 // if we are recording, add this change to our event_list
2592 rec_param_change((weed_plant_t *)rfx->source, param_number);
2593 if (copyto != -1) rec_param_change((weed_plant_t *)rfx->source, copyto);
2594 }
2595
2596 if (new_alpha != old_value.alpha && param->onchange) {
2597 param->change_blocked = TRUE;
2598 retvals = do_onchange(LIVES_WIDGET_OBJECT(spinbutton), rfx);
2599 lives_list_free_all(&retvals);
2600 needs_update = TRUE;
2601 }
2602 after_any_changed_2(rfx, param, needs_update);
2603}
2604
2605
2606boolean after_param_text_focus_changed(LiVESWidget * hbox, LiVESWidget * child, lives_rfx_t *rfx) {
2607 // for non realtime effects
2608 // we don't usually want to run the trigger every single time the user presses a key in a text widget
2609 // so we only update when the user clicks OK or focusses out of the widget
2610
2611 LiVESWidget *textwidget;
2612
2613 if (rfx == NULL) return FALSE;
2614
2615 if (mainw->multitrack) {
2616 if (child)
2618 else
2620 }
2621
2622 if (mainw->textwidget_focus) {
2623 textwidget = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mainw->textwidget_focus), TEXTWIDGET_KEY);
2624 after_param_text_changed(textwidget, rfx);
2625 }
2626
2627 if (hbox) {
2628 mainw->textwidget_focus = hbox;
2629 }
2630
2631 return FALSE;
2632}
2633
2634
2635void after_param_text_changed(LiVESWidget * textwidget, lives_rfx_t *rfx) {
2636 //LiVESTextBuffer *textbuffer = NULL;
2637 weed_plant_t *inst = NULL, *wparam = NULL;
2638 LiVESList *retvals = NULL;
2639 lives_param_t *param;
2640 char *old_text;
2641 const char *new_text;
2642 int copyto = -1;
2643 boolean needs_update = FALSE;
2644 int param_number;
2645
2646 if (rfx == NULL || rfx->params == NULL || textwidget == NULL) return;
2647
2648
2649 param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(textwidget), PARAM_NUMBER_KEY));
2650 param = &rfx->params[param_number];
2651 old_text = (char *)param->value;
2652
2653 if (LIVES_IS_TEXT_VIEW(textwidget)) {
2654 new_text = lives_text_view_get_text(LIVES_TEXT_VIEW(textwidget));
2655 if (!lives_strcmp(new_text, old_text)) return;
2656 } else {
2657 new_text = lives_entry_get_text(LIVES_ENTRY(textwidget));
2658 if (!lives_strcmp(new_text, old_text)) return;
2659 }
2660
2662 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2663 return; // updates are blocked until all params are ready
2664 }
2665
2666 ireinit++;
2667
2668 param->value = lives_strdup(new_text);
2669
2671 param->change_blocked = TRUE;
2672
2673 if (rfx->status == RFX_STATUS_WEED) {
2674 inst = (weed_plant_t *)rfx->source;
2675 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2676 char **valss;
2677 int index = 0, numvals, key = -1;
2678 wparam = weed_inst_in_param(inst, param_number, FALSE, FALSE);
2679
2680 if (mainw->multitrack && is_perchannel_multi(rfx, param_number)) {
2681 index = mainw->multitrack->track_index;
2682 }
2683
2684 after_any_changed_1(rfx, param_number, index);
2685
2686 numvals = weed_leaf_num_elements(wparam, WEED_LEAF_VALUE);
2687
2688 valss = weed_get_string_array(wparam, WEED_LEAF_VALUE, NULL);
2689 valss[index] = lives_strdup((char *)param->value);
2690
2691 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2692 if (!filter_mutex_trylock(key)) {
2693 weed_set_string_array(wparam, WEED_LEAF_VALUE, numvals, valss);
2694 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2696 if (copyto != -1) needs_update = TRUE;
2697 }
2698 for (int i = 0; i < numvals; i++) lives_free(valss[i]);
2699 lives_free(valss);
2700
2702 // if we are recording, add this change to our event_list
2703 rec_param_change(inst, param_number);
2704 //if (copyto != -1) rec_param_change(inst, copyto);
2705 }
2706 rfx->needs_reinit |= param->reinit;
2707 }
2708 }
2709
2710 if (lives_strcmp(old_text, (char *)param->value) && param->onchange) {
2711 param->change_blocked = TRUE;
2712 retvals = do_onchange(LIVES_WIDGET_OBJECT(textwidget), rfx);
2713 lives_list_free_all(&retvals);
2714 needs_update = TRUE;
2715 }
2716 after_any_changed_2(rfx, param, needs_update);
2717}
2718
2719
2720static void after_param_text_buffer_changed(LiVESTextBuffer * textbuffer, lives_rfx_t *rfx) {
2721 LiVESWidget *textview = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(textbuffer), "textview");
2722 after_param_text_changed(textview, rfx);
2723}
2724
2725
2726void after_string_list_changed(LiVESWidget * entry, lives_rfx_t *rfx) {
2727 LiVESList *retvals = NULL;
2728 int param_number = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(entry), PARAM_NUMBER_KEY));
2729 LiVESCombo *combo = (LiVESCombo *)(rfx->params[param_number].widgets[0]);
2730 lives_param_t *param = &rfx->params[param_number];
2731 const char *txt = lives_combo_get_active_text(combo);
2732 int old_index = get_int_param(param->value);
2733 int new_index = lives_list_strcmp_index(param->list, txt, TRUE);
2734 boolean needs_update = FALSE;
2735 int copyto = -1;
2736
2737 if (new_index == -1) return;
2738 if (new_index == old_index) return;
2739
2741 if (rfx->status == RFX_STATUS_WEED && param->reinit) rfx->needs_reinit |= param->reinit;
2742 return; // updates are blocked until all params are ready
2743 }
2744
2745 ireinit++;
2746
2747 set_int_param(param->value, new_index);
2748
2750 param->change_blocked = TRUE;
2751 if (rfx->status == RFX_STATUS_WEED) {
2752 weed_plant_t *inst = (weed_plant_t *)rfx->source;
2753 if (inst && WEED_PLANT_IS_FILTER_INSTANCE(inst)) {
2754 //char *disp_string = get_weed_display_string(inst, param_number);
2755 weed_plant_t *wparam = weed_inst_in_param(inst, param_number, FALSE, FALSE);
2756 int index = 0, numvals;
2757 int key = -1;
2758 int *valis;
2759
2760 if (mainw->multitrack && is_perchannel_multi(rfx, param_number)) {
2761 index = mainw->multitrack->track_index;
2762 }
2763
2764 after_any_changed_1(rfx, param_number, index);
2765
2766 valis = weed_get_int_array(wparam, WEED_LEAF_VALUE, NULL);
2767 valis[index] = new_index;
2768 numvals = weed_leaf_num_elements(wparam, WEED_LEAF_VALUE);
2769 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, NULL);
2770 if (!filter_mutex_trylock(key)) {
2771 weed_set_int_array(wparam, WEED_LEAF_VALUE, numvals, valis);
2772 copyto = set_copy_to(inst, param_number, rfx, TRUE);
2774 if (copyto != -1) needs_update = TRUE;
2775 }
2776 lives_free(valis);
2777
2779 // if we are recording, add this change to our event_list
2780 rec_param_change(inst, param_number);
2781 //if (copyto != -1) rec_param_change(inst, copyto);
2782 }
2783 rfx->needs_reinit |= param->reinit;
2784 }
2785 }
2786
2787 if (old_index != new_index && param->onchange) {
2788 param->change_blocked = TRUE;
2789 retvals = do_onchange(LIVES_WIDGET_OBJECT(combo), rfx);
2790 lives_list_free_all(&retvals);
2791 needs_update = TRUE;
2792 }
2793 after_any_changed_2(rfx, param, needs_update);
2794}
2795
2796
2798 // this function will marshall all parameters into a argv array
2799 // last array element will be NULL
2800
2801 // the returned **argv should be lives_free()'ed after use
2802
2803 lives_colRGB48_t rgb;
2804
2805 char **argv = (char **)lives_malloc((rfx->num_params + 1) * (sizeof(char *)));
2806
2807 char *tmp;
2808
2809 register int i;
2810
2811 for (i = 0; i < rfx->num_params; i++) {
2812 switch (rfx->params[i].type) {
2814 get_colRGB24_param(rfx->params[i].value, &rgb);
2815 argv[i] = lives_strdup_printf("%u", (((rgb.red << 8) + rgb.green) << 8) + rgb.blue);
2816 break;
2817
2818 case LIVES_PARAM_STRING:
2819 // escape strings
2820 argv[i] = lives_strdup_printf("%s", (tmp = U82L((char *)rfx->params[i].value)));
2821 lives_free(tmp);
2822 break;
2823
2825 // escape strings
2826 argv[i] = lives_strdup_printf("%d", get_int_param(rfx->params[i].value));
2827 break;
2828
2829 default:
2830 if (rfx->params[i].dp) {
2831 char *return_pattern = lives_strdup_printf("%%.%df", rfx->params[i].dp);
2832 argv[i] = lives_strdup_printf(return_pattern, get_double_param(rfx->params[i].value));
2833 lives_free(return_pattern);
2834 } else {
2835 argv[i] = lives_strdup_printf("%d", get_int_param(rfx->params[i].value));
2836 }
2837 }
2838 }
2839 argv[i] = NULL;
2840 return argv;
2841}
2842
2843
2844char *param_marshall(lives_rfx_t *rfx, boolean with_min_max) {
2845 // this function will marshall all parameters into a space separated string
2846 // in case of string parameters, these will be surrounded by " and all
2847 // quotes will be escaped \"
2848
2849 // the returned string should be lives_free()'ed after use
2850 lives_colRGB48_t rgb;
2851
2852 char *new_return = lives_strdup("");
2853 char *old_return = new_return;
2854 char *return_pattern;
2855 char *tmp, *mysubst, *mysubst2;
2856
2857 for (int i = 0; i < rfx->num_params; i++) {
2858 switch (rfx->params[i].type) {
2860 continue;
2862 get_colRGB24_param(rfx->params[i].value, &rgb);
2863 if (!with_min_max) {
2864 new_return = lives_strdup_printf("%s %u", old_return, (((rgb.red << 8) + rgb.green) << 8) + rgb.blue);
2865 } else {
2866 new_return = lives_strdup_printf("%s %d %d %d", old_return, rgb.red, rgb.green, rgb.blue);
2867 }
2868 lives_free(old_return);
2869 old_return = new_return;
2870 break;
2871
2872 case LIVES_PARAM_STRING:
2873 // we need to doubly escape strings
2874 mysubst = subst((char *)rfx->params[i].value, "\\", "\\\\\\\\");
2875 mysubst2 = subst(mysubst, "\"", "\\\\\\\"");
2876 lives_free(mysubst);
2877 mysubst = subst(mysubst2, "`", "\\`");
2878 lives_free(mysubst2);
2879 mysubst2 = subst(mysubst, "'", "\\`");
2880 lives_free(mysubst);
2881 new_return = lives_strdup_printf("%s \"%s\"", old_return, (tmp = U82L(mysubst2)));
2882 lives_free(tmp);
2883 lives_free(mysubst2);
2884 lives_free(old_return);
2885 old_return = new_return;
2886 break;
2887
2889 new_return = lives_strdup_printf("%s %d", old_return, get_int_param(rfx->params[i].value));
2890 lives_free(old_return);
2891 old_return = new_return;
2892 break;
2893
2894 default:
2895 if (rfx->params[i].dp) {
2896 return_pattern = lives_strdup_printf("%%s %%.%df", rfx->params[i].dp);
2897 new_return = lives_strdup_printf(return_pattern, old_return, get_double_param(rfx->params[i].value));
2898 if (with_min_max) {
2899 lives_free(old_return);
2900 old_return = new_return;
2901 new_return = lives_strdup_printf(return_pattern, old_return, rfx->params[i].min);
2902 lives_free(old_return);
2903 old_return = new_return;
2904 new_return = lives_strdup_printf(return_pattern, old_return, rfx->params[i].max);
2905 }
2906 lives_free(return_pattern);
2907 } else {
2908 new_return = lives_strdup_printf("%s %d", old_return, get_int_param(rfx->params[i].value));
2909 if (with_min_max && rfx->params[i].type != LIVES_PARAM_BOOL) {
2910 lives_free(old_return);
2911 old_return = new_return;
2912 new_return = lives_strdup_printf("%s %d", old_return, (int)rfx->params[i].min);
2913 lives_free(old_return);
2914 old_return = new_return;
2915 new_return = lives_strdup_printf("%s %d", old_return, (int)rfx->params[i].max);
2916 }
2917 }
2918 lives_free(old_return);
2919 old_return = new_return;
2920 }
2921 }
2922 if (mainw->current_file > 0 && with_min_max) {
2923 if (rfx->num_in_channels < 2) {
2924 new_return = lives_strdup_printf("%s %d %d %d %d %d", old_return, cfile->hsize, cfile->vsize, cfile->start,
2925 cfile->end, cfile->frames);
2926 } else {
2927 // for transitions, change the end to indicate the merge section
2928 // this is better for length calculations
2929 int cb_frames = clipboard->frames;
2930 int start = cfile->start, end = cfile->end, ttl;
2931
2932 if (prefs->ins_resample && clipboard->fps != cfile->fps) {
2933 cb_frames = count_resampled_frames(clipboard->frames, clipboard->fps, cfile->fps);
2934 }
2935
2937 && cfile->end - cfile->start + 1 > (cb_frames * (ttl = lives_spin_button_get_value_as_int
2938 (LIVES_SPIN_BUTTON(merge_opts->spinbutton_loops)))) &&
2940 end = cb_frames * ttl;
2941 if (!merge_opts->align_start) {
2942 start = cfile->end - end + 1;
2943 end = cfile->end;
2944 } else {
2945 start = cfile->start;
2946 end += start - 1;
2947 }
2948 }
2949 new_return = lives_strdup_printf("%s %d %d %d %d %d %d %d", old_return, cfile->hsize, cfile->vsize, start, end,
2950 cfile->frames, clipboard->hsize, clipboard->vsize);
2951 }
2952 } else {
2953 new_return = lives_strdup(old_return);
2954 }
2955 lives_free(old_return);
2956
2957 return new_return;
2958}
2959
2960
2961char *reconstruct_string(LiVESList * plist, int start, int *offs) {
2962 // convert each piece from locale to utf8
2963 // concat list entries to get reconstruct
2964 // replace \" with "
2965
2966 char *word = NULL;
2967 char *ret = lives_strdup(""), *ret2;
2968 char *tmp;
2969
2970 boolean lastword = FALSE;
2971
2972 register int i;
2973
2974 word = L2U8((char *)lives_list_nth_data(plist, start));
2975
2976 if (!word || !*word || word[0] != '\"') {
2977 if (word) lives_free(word);
2978 return 0;
2979 }
2980
2981 word++;
2982
2983 for (i = start; i < lives_list_length(plist); i++) {
2984 size_t wl = lives_strlen(word);
2985 if (wl > 0) {
2986 if ((word[wl - 1] == '\"') && (wl == 1 || word[wl - 2] != '\\')) {
2987 lastword = TRUE;
2988 lives_memset(word + wl - 1, 0, 1);
2989 }
2990 }
2991
2992 ret2 = lives_strconcat(ret, (tmp = subst(word, "\\\"", "\"")), " ", NULL);
2993 lives_free(tmp);
2994 if (ret2 != ret) lives_free(ret);
2995 ret = ret2;
2996
2997 if (i == start) word--;
2998 lives_free(word);
2999
3000 if (lastword) break;
3001
3002 if (i < lives_list_length(plist) - 1) word = L2U8((char *)lives_list_nth_data(plist, i + 1));
3003 }
3004
3005 set_int_param(offs, i - start + 1);
3006
3007 // remove trailing space
3008 lives_memset(ret + lives_strlen(ret) - 1, 0, 1);
3009 return ret;
3010}
3011
3012
3013void param_demarshall(lives_rfx_t *rfx, LiVESList * plist, boolean with_min_max, boolean upd) {
3014 int i;
3015 int pnum = 0;
3016 lives_param_t *param;
3017
3018 // here we take a LiVESList * of param values, set them in rfx, and if upd is TRUE we also update their visual appearance
3019
3020 // param->widgets[n] are only valid if upd==TRUE
3021
3022 if (plist == NULL) return;
3023
3024 for (i = 0; i < rfx->num_params; i++) {
3025 param = &rfx->params[i];
3026 pnum = set_param_from_list(plist, param, pnum, with_min_max, upd);
3027 }
3028}
3029
3030
3031LiVESList *argv_to_marshalled_list(lives_rfx_t *rfx, int argc, char **argv) {
3032 LiVESList *plist = NULL;
3033
3034 char *tmp, *tmp2, *tmp3;
3035
3036 register int i;
3037
3038 if (argc == 0) return plist;
3039
3040 for (i = 0; i <= argc && argv[i]; i++) {
3041 if (rfx->params[i].type == LIVES_PARAM_STRING) {
3042 tmp = lives_strdup_printf("\"%s\"", (tmp2 = U82L(tmp3 = subst(argv[i], "\"", "\\\""))));
3043 plist = lives_list_append(plist, tmp);
3044 lives_free(tmp2);
3045 lives_free(tmp3);
3046 } else {
3047 plist = lives_list_append(plist, lives_strdup(argv[i]));
3048 }
3049 }
3050 return plist;
3051}
3052
3053
3065int set_param_from_list(LiVESList * plist, lives_param_t *param, int pnum, boolean with_min_max, boolean upd) {
3066 char *tmp;
3067 char *strval;
3068 int red, green, blue;
3069 int offs = 0;
3070 int maxlen = lives_list_length(plist) - 1;
3071
3072 if (ABS(pnum) > maxlen) return 0;
3073
3074 switch (param->type) {
3075 case LIVES_PARAM_BOOL:
3076 if (param->change_blocked) {
3077 pnum++;
3078 break;
3079 }
3080 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3081 if (upd) {
3082 if (param->widgets[0] && LIVES_IS_TOGGLE_BUTTON(param->widgets[0])) {
3083 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(param->widgets[0]), atoi(tmp));
3084 }
3085 } else set_bool_param(param->def, (atoi(tmp)));
3086 if (upd && param->widgets[0] && LIVES_IS_TOGGLE_BUTTON(param->widgets[0])) {
3087 set_bool_param(param->value,
3088 lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(param->widgets[0])));
3089 } else set_bool_param(param->value, (atoi(tmp)));
3090 lives_free(tmp);
3091 break;
3092 case LIVES_PARAM_NUM:
3093 if (param->change_blocked) {
3094 pnum++;
3095 if (with_min_max) pnum += 2;
3096 break;
3097 }
3098 if (param->dp) {
3099 double double_val;
3100 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3101 double_val = lives_strtod(tmp, NULL);
3102 lives_free(tmp);
3103 if (with_min_max) {
3104 if (ABS(pnum) > maxlen) return 1;
3105 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3106 param->min = lives_strtod(tmp, NULL);
3107 lives_free(tmp);
3108 if (ABS(pnum) > maxlen) return 2;
3109 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3110 param->max = lives_strtod(tmp, NULL);
3111 lives_free(tmp);
3112 if (double_val < param->min) double_val = param->min;
3113 if (double_val > param->max) double_val = param->max;
3114 }
3115 if (upd) {
3116 if (param->widgets[0] && LIVES_IS_SPIN_BUTTON(param->widgets[0])) {
3117 lives_rfx_t *rfx = (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(param->widgets[0]), RFX_KEY);
3118 lives_signal_handlers_block_by_func(param->widgets[0], (livespointer)after_param_value_changed, (livespointer)rfx);
3119 lives_spin_button_set_range(LIVES_SPIN_BUTTON(param->widgets[0]), param->min, param->max);
3120 lives_spin_button_update(LIVES_SPIN_BUTTON(param->widgets[0]));
3121 lives_signal_handlers_unblock_by_func(param->widgets[0], (livespointer)after_param_value_changed, (livespointer)rfx);
3122 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), double_val);
3123 lives_spin_button_update(LIVES_SPIN_BUTTON(param->widgets[0]));
3124 }
3125 } else set_double_param(param->def, double_val);
3126 if (upd && param->widgets[0] && LIVES_IS_SPIN_BUTTON(param->widgets[0])) {
3127 set_double_param(param->value,
3128 lives_spin_button_get_value(LIVES_SPIN_BUTTON(param->widgets[0])));
3129 } else set_double_param(param->value, double_val);
3130 } else {
3131 int int_value;
3132 int int_min, int_max;
3133 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3134 int_value = atoi(tmp);
3135 lives_free(tmp);
3136 if (param->step_size > 1.)
3137 int_value = (int)((double)int_value / param->step_size + .5) * (int)param->step_size;
3138 int_min = (int)param->min;
3139 int_max = (int)param->max;
3140 if (int_value < int_min) int_value = int_min;
3141 if (int_value > int_max) int_value = int_max;
3142
3143 if (with_min_max) {
3144 if (ABS(pnum) > maxlen) return 1;
3145 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3146 int_min = atoi(tmp);
3147 lives_free(tmp);
3148 if (ABS(pnum) > maxlen) return 2;
3149 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3150 int_max = atoi(tmp);
3151 lives_free(tmp);
3152 if (int_value < int_min) int_value = int_min;
3153 if (int_value > int_max) int_value = int_max;
3154 param->min = (double)int_min;
3155 param->max = (double)int_max;
3156 }
3157 if (upd) {
3158 if (param->widgets[0] && LIVES_IS_SPIN_BUTTON(param->widgets[0])) {
3159 lives_rfx_t *rfx = (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(param->widgets[0]), RFX_KEY);
3160 lives_signal_handlers_block_by_func(param->widgets[0], (livespointer)after_param_value_changed, (livespointer)rfx);
3161 lives_spin_button_set_range(LIVES_SPIN_BUTTON(param->widgets[0]), param->min, param->max);
3162 lives_spin_button_update(LIVES_SPIN_BUTTON(param->widgets[0]));
3163 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)int_value);
3164 lives_spin_button_update(LIVES_SPIN_BUTTON(param->widgets[0]));
3165 lives_signal_handlers_unblock_by_func(param->widgets[0], (livespointer)after_param_value_changed, (livespointer)rfx);
3166 }
3167 } else set_int_param(param->def, int_value);
3168 if (upd && param->widgets[0] && LIVES_IS_SPIN_BUTTON(param->widgets[0])) {
3169 set_int_param(param->value,
3170 lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(param->widgets[0])));
3171 } else set_int_param(param->value, int_value);
3172 }
3173 break;
3175 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3176 red = atoi(tmp);
3177 lives_free(tmp);
3178 if (ABS(pnum) > maxlen) return 1;
3179 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3180 green = atoi(tmp);
3181 lives_free(tmp);
3182 if (ABS(pnum) > maxlen) return 2;
3183 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3184 blue = atoi(tmp);
3185 lives_free(tmp);
3186 if (param->change_blocked) break;
3187 if (upd) {
3188 if (param->widgets[0] && LIVES_IS_SPIN_BUTTON(param->widgets[0])) {
3189 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)red);
3190 }
3191 if (param->widgets[1] && LIVES_IS_SPIN_BUTTON(param->widgets[1])) {
3192 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[1]), (double)green);
3193 }
3194 if (param->widgets[2] && LIVES_IS_SPIN_BUTTON(param->widgets[2])) {
3195 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[2]), (double)blue);
3196 }
3197 } else set_colRGB24_param(param->def, red, green, blue);
3198 if (upd && param->widgets[0] && LIVES_IS_SPIN_BUTTON(param->widgets[0])
3199 && param->widgets[1] && LIVES_IS_SPIN_BUTTON(param->widgets[1])
3200 && param->widgets[2] && LIVES_IS_SPIN_BUTTON(param->widgets[2])) {
3202 lives_spin_button_get_value(LIVES_SPIN_BUTTON(param->widgets[0])),
3203 lives_spin_button_get_value(LIVES_SPIN_BUTTON(param->widgets[1])),
3204 lives_spin_button_get_value(LIVES_SPIN_BUTTON(param->widgets[2])));
3205 } else set_colRGB24_param(param->value, red, green, blue);
3206 break;
3207 case LIVES_PARAM_STRING:
3208 strval = reconstruct_string(plist, pnum, &offs);
3209 pnum += offs;
3210 if (param->change_blocked) {
3211 lives_free(strval);
3212 break;
3213 }
3214 if (upd) {
3215 if (param->widgets[0]) {
3216 if (LIVES_IS_TEXT_VIEW(param->widgets[0])) {
3217 lives_text_view_set_text(LIVES_TEXT_VIEW(param->widgets[0]), strval, -1);
3218 } else {
3219 lives_entry_set_text(LIVES_ENTRY(param->widgets[0]), strval);
3220
3221 }
3222 }
3223 } else {
3224 if (param->def) lives_free(param->def);
3225 param->def = (void *)lives_strdup(strval);
3226 }
3227 if (param->value) lives_free(param->value);
3228
3230 if (upd && param->widgets[0] && (LIVES_IS_TEXT_VIEW(param->widgets[0])
3231 || LIVES_IS_ENTRY(param->widgets[0]))) {
3232 lives_free(strval);
3233 if (LIVES_IS_TEXT_VIEW(param->widgets[0])) {
3234 param->value = lives_strdup(lives_text_view_get_text(LIVES_TEXT_VIEW(param->widgets[0])));
3235 } else {
3236 param->value = lives_strdup(lives_entry_get_text(LIVES_ENTRY(param->widgets[0])));
3237 }
3238 } else {
3239 param->value = strval;
3240 }
3241 break;
3243 int int_value;
3244 tmp = lives_strdup((char *)lives_list_nth_data(plist, pnum++));
3245 int_value = atoi(tmp);
3246 lives_free(tmp);
3247 if (param->change_blocked) break;
3248 if (upd && param->widgets[0] && LIVES_IS_COMBO(param->widgets[0]) && int_value < lives_list_length(param->list))
3249 lives_combo_set_active_string(LIVES_COMBO(param->widgets[0]), (char *)lives_list_nth_data(param->list, int_value));
3250 if (!upd) set_int_param(param->def, int_value);
3251 if (upd && param->widgets[0] && LIVES_IS_COMBO(param->widgets[0])) {
3252 const char *txt = lives_combo_get_active_text(LIVES_COMBO(param->widgets[0]));
3253 int new_index = lives_list_strcmp_index(param->list, txt, TRUE);
3254 set_int_param(param->value, new_index);
3255 } else set_int_param(param->value, int_value);
3256 break;
3257 }
3258 default:
3259 break;
3260 }
3261 return pnum;
3262}
3263
3264
3265LiVESList *do_onchange(LiVESWidgetObject * object, lives_rfx_t *rfx) {
3266 LiVESList *retvals;
3267
3268 int which = LIVES_POINTER_TO_INT(lives_widget_object_get_data(object, PARAM_NUMBER_KEY));
3269 int width = 0, height = 0;
3270
3271 const char *handle = "";
3272
3273 char *plugdir;
3274 char *com, *tmp;
3275
3276 // weed plugins do not have triggers
3277 if (rfx->status == RFX_STATUS_WEED) return NULL;
3278
3279 if (which < 0) {
3280 // init
3281 switch (rfx->status) {
3282 case RFX_STATUS_BUILTIN:
3283 plugdir = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_RENDERED_EFFECTS_BUILTIN, NULL);
3284 break;
3285 case RFX_STATUS_CUSTOM:
3286 plugdir = lives_build_filename(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_CUSTOM, NULL);
3287 break;
3288 case RFX_STATUS_TEST:
3289 plugdir = lives_build_filename(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_TEST, NULL);
3290 break;
3291 default:
3292 plugdir = lives_strdup_printf("%s", prefs->workdir);
3293 }
3294
3295 if (mainw->current_file > 0) {
3296 width = cfile->hsize;
3297 height = cfile->vsize;
3298 handle = cfile->handle;
3299 }
3300
3301 com = lives_strdup_printf("%s \"fxinit_%s\" \"%s\" \"%s\" %d %d %s", prefs->backend_sync, rfx->name, handle, plugdir,
3302 width, height, (tmp = param_marshall(rfx, TRUE)));
3303 retvals = plugin_request_by_space(NULL, NULL, com);
3304
3305 lives_free(tmp);
3306 lives_free(plugdir);
3307 } else {
3308 com = lives_strdup_printf("onchange_%d%s", which, param_marshall(rfx, TRUE));
3309 switch (rfx->status) {
3310 case RFX_STATUS_BUILTIN:
3312 break;
3313 case RFX_STATUS_CUSTOM:
3315 break;
3316 case RFX_STATUS_TEST:
3318 break;
3319 default:
3320 retvals = plugin_request_by_space(PLUGIN_RFX_SCRAP, rfx->name, com);
3321 }
3322 }
3323
3324 if (retvals) {
3325 param_demarshall(rfx, retvals, TRUE, which >= 0);
3326 } else {
3327 if (which <= 0 && mainw->error) {
3328 mainw->error = FALSE;
3330 }
3331 }
3332 lives_free(com);
3333
3334 return retvals;
3335}
3336
3337
3338void on_pwcolsel(LiVESButton * button, lives_rfx_t *rfx) {
3339 LiVESWidgetColor selected;
3340
3341 int pnum = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button), PARAM_NUMBER_KEY));
3342 int r, g, b;
3343
3344 lives_param_t *param = &rfx->params[pnum];
3345
3346 lives_color_button_get_color(LIVES_COLOR_BUTTON(button), &selected);
3347
3348 r = (int)((double)(selected.red + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
3349 g = (int)((double)(selected.green + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
3350 b = (int)((double)(selected.blue + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
3351
3352 set_colRGB24_param(param->value, r, g, b);
3353
3354 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)r);
3355 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[1]), (double)g);
3356 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[2]), (double)b);
3357 lives_color_button_set_color(LIVES_COLOR_BUTTON(param->widgets[4]), &selected);
3358}
3359
3360
3361void update_visual_params(lives_rfx_t *rfx, boolean update_hidden) {
3362 // update parameters visually from an rfx object
3363 LiVESList *list;
3364
3365 weed_plant_t **in_params, *in_param;
3366 weed_plant_t *inst = (weed_plant_t *)rfx->source;
3367 weed_plant_t *paramtmpl;
3368
3369 int *colsi, *colsis, *valis;
3370 int *maxis = NULL, *minis = NULL;
3371
3372 double *colsd, *colsds, *valds;
3373 double *maxds = NULL, *minds = NULL;
3374
3375 double red_maxd, green_maxd, blue_maxd;
3376 double red_mind, green_mind, blue_mind;
3377 double vald, mind, maxd;
3378
3379 char **valss;
3380
3381 char *vals, *pattern;
3382 char *tmp, *tmp2;
3383
3384 int cspace;
3385 int error;
3386 int num_params = 0;
3387 int param_type;
3388 int vali, mini, maxi;
3389
3390 int red_max, green_max, blue_max;
3391 int red_min, green_min, blue_min;
3392
3393 int index, numvals;
3394 int key = -1;
3395
3396 register int i, j;
3397
3398 if (rfx->source_type != LIVES_RFX_SOURCE_WEED) return;
3399
3400 in_params = weed_instance_get_in_params(inst, &num_params);
3401 if (num_params == 0) return;
3402
3403 if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_KEY)) key = weed_get_int_value(inst, WEED_LEAF_HOST_KEY, &error);
3404
3405 for (i = 0; i < num_params; i++) {
3406 if (!is_hidden_param(inst, i) || (!(rfx->params[i].hidden & HIDDEN_STRUCTURAL) && update_hidden)) {
3407 // by default we dont update hidden or reinit params
3408 in_param = in_params[i];
3409 paramtmpl = weed_param_get_template(in_param);
3410 param_type = weed_paramtmpl_get_type(paramtmpl);
3411 list = NULL;
3412
3413 // assume index is 0, unless we are a framedraw multi parameter
3414 // most of the time this will be ok, as other such multivalued parameters should be hidden
3415 index = 0;
3416
3417 if (mainw->multitrack && is_perchannel_multi(rfx, i)) {
3418 index = mainw->multitrack->track_index;
3419 }
3420
3421 filter_mutex_lock(key);
3422
3423 numvals = weed_leaf_num_elements(in_param, WEED_LEAF_VALUE);
3424
3425 if (param_type != WEED_PARAM_COLOR && index >= numvals) {
3426 fill_param_vals_to(in_param, paramtmpl, index);
3427 numvals = index + 1;
3428 }
3429
3430 switch (param_type) {
3431 case WEED_PARAM_INTEGER:
3432 valis = weed_get_int_array(in_param, WEED_LEAF_VALUE, &error);
3433 vali = valis[index];
3434 lives_free(valis);
3435
3436 mini = weed_get_int_value(paramtmpl, WEED_LEAF_MIN, &error);
3437 maxi = weed_get_int_value(paramtmpl, WEED_LEAF_MAX, &error);
3438
3439 list = lives_list_append(list, lives_strdup_printf("%d", vali));
3440 list = lives_list_append(list, lives_strdup_printf("%d", mini));
3441 list = lives_list_append(list, lives_strdup_printf("%d", maxi));
3442 set_param_from_list(list, &rfx->params[i], 0, TRUE, TRUE);
3443 lives_list_free_all(&list);
3444
3445 break;
3446 case WEED_PARAM_FLOAT:
3447 valds = weed_get_double_array(in_param, WEED_LEAF_VALUE, &error);
3448 vald = valds[index];
3449 lives_free(valds);
3450
3451 mind = weed_get_double_value(paramtmpl, WEED_LEAF_MIN, &error);
3452 maxd = weed_get_double_value(paramtmpl, WEED_LEAF_MAX, &error);
3453
3454 pattern = lives_strdup("%.2f");
3455
3456 if (weed_plant_has_leaf(paramtmpl, WEED_LEAF_GUI)) {
3457 weed_plant_t *gui = weed_get_plantptr_value(paramtmpl, WEED_LEAF_GUI, &error);
3458 if (weed_plant_has_leaf(gui, WEED_LEAF_DECIMALS)) {
3459 int dp = weed_get_int_value(gui, WEED_LEAF_DECIMALS, &error);
3460 lives_free(pattern);
3461 pattern = lives_strdup_printf("%%.%df", dp);
3462 }
3463 }
3464
3465 list = lives_list_append(list, lives_strdup_printf(pattern, vald));
3466 list = lives_list_append(list, lives_strdup_printf(pattern, mind));
3467 list = lives_list_append(list, lives_strdup_printf(pattern, maxd));
3468
3469 lives_free(pattern);
3470
3471 set_param_from_list(list, &rfx->params[i], 0, TRUE, TRUE);
3472 lives_list_free_all(&list);
3473
3474 break;
3475 case WEED_PARAM_SWITCH:
3476 valis = weed_get_boolean_array(in_param, WEED_LEAF_VALUE, &error);
3477 vali = valis[index];
3478 lives_free(valis);
3479
3480 list = lives_list_append(list, lives_strdup_printf("%d", vali));
3481 set_param_from_list(list, &rfx->params[i], 0, FALSE, TRUE);
3482 lives_list_free_all(&list);
3483
3484 break;
3485 case WEED_PARAM_TEXT:
3486 valss = weed_get_string_array(in_param, WEED_LEAF_VALUE, &error);
3487 vals = valss[index];
3488 list = lives_list_append(list, lives_strdup_printf("\"%s\"", (tmp = U82L(tmp2 = subst(vals, "\"", "\\\"")))));
3489 lives_free(tmp);
3490 lives_free(tmp2);
3491 set_param_from_list(list, &rfx->params[i], 0, FALSE, TRUE);
3492 for (j = 0; j < numvals; j++) {
3493 lives_free(valss[j]);
3494 }
3495 lives_free(valss);
3496 lives_list_free_all(&list);
3497
3498 break;
3499 case WEED_PARAM_COLOR:
3500 cspace = weed_get_int_value(paramtmpl, WEED_LEAF_COLORSPACE, &error);
3501 switch (cspace) {
3502 case WEED_COLORSPACE_RGB:
3503 numvals = weed_leaf_num_elements(in_param, WEED_LEAF_VALUE);
3504 if (index * 3 >= numvals) fill_param_vals_to(in_param, paramtmpl, index);
3505
3506 if (weed_leaf_seed_type(paramtmpl, WEED_LEAF_DEFAULT) == WEED_SEED_INT) {
3507 colsis = weed_get_int_array(in_param, WEED_LEAF_VALUE, &error);
3508 colsi = &colsis[3 * index];
3509
3510 if (weed_leaf_num_elements(paramtmpl, WEED_LEAF_MAX) == 1) {
3511 red_max = green_max = blue_max = weed_get_int_value(paramtmpl, WEED_LEAF_MAX, &error);
3512 } else {
3513 maxis = weed_get_int_array(paramtmpl, WEED_LEAF_MAX, &error);
3514 red_max = maxis[0];
3515 green_max = maxis[1];
3516 blue_max = maxis[2];
3517 }
3518 if (weed_leaf_num_elements(paramtmpl, WEED_LEAF_MIN) == 1) {
3519 red_min = green_min = blue_min = weed_get_int_value(paramtmpl, WEED_LEAF_MIN, &error);
3520 } else {
3521 minis = weed_get_int_array(paramtmpl, WEED_LEAF_MIN, &error);
3522 red_min = minis[0];
3523 green_min = minis[1];
3524 blue_min = minis[2];
3525 }
3526
3527 colsi[0] = (int)((double)(colsi[0] - red_min) / (double)(red_max - red_min) * 255. + .5);
3528 colsi[1] = (int)((double)(colsi[1] - green_min) / (double)(green_max - green_min) * 255. + .5);
3529 colsi[2] = (int)((double)(colsi[2] - blue_min) / (double)(blue_max - blue_min) * 255. + .5);
3530
3531 if (colsi[0] < red_min) colsi[0] = red_min;
3532 if (colsi[1] < green_min) colsi[1] = green_min;
3533 if (colsi[2] < blue_min) colsi[2] = blue_min;
3534 if (colsi[0] > red_max) colsi[0] = red_max;
3535 if (colsi[1] > green_max) colsi[1] = green_max;
3536 if (colsi[2] > blue_max) colsi[2] = blue_max;
3537
3538 list = lives_list_append(list, lives_strdup_printf("%d", colsi[0]));
3539 list = lives_list_append(list, lives_strdup_printf("%d", colsi[1]));
3540 list = lives_list_append(list, lives_strdup_printf("%d", colsi[2]));
3541
3542 set_param_from_list(list, &rfx->params[i], 0, FALSE, TRUE);
3543
3544 lives_list_free_all(&list);
3545 lives_free(colsis);
3546 if (maxis) lives_free(maxis);
3547 if (minis) lives_free(minis);
3548 } else {
3549 colsds = weed_get_double_array(in_param, WEED_LEAF_VALUE, &error);
3550 colsd = &colsds[3 * index];
3551 if (weed_leaf_num_elements(paramtmpl, WEED_LEAF_MAX) == 1) {
3552 red_maxd = green_maxd = blue_maxd = weed_get_double_value(paramtmpl, WEED_LEAF_MAX, &error);
3553 } else {
3554 maxds = weed_get_double_array(paramtmpl, WEED_LEAF_MAX, &error);
3555 red_maxd = maxds[0];
3556 green_maxd = maxds[1];
3557 blue_maxd = maxds[2];
3558 }
3559 if (weed_leaf_num_elements(paramtmpl, WEED_LEAF_MIN) == 1) {
3560 red_mind = green_mind = blue_mind = weed_get_double_value(paramtmpl, WEED_LEAF_MIN, &error);
3561 } else {
3562 minds = weed_get_double_array(paramtmpl, WEED_LEAF_MIN, &error);
3563 red_mind = minds[0];
3564 green_mind = minds[1];
3565 blue_mind = minds[2];
3566 }
3567 colsd[0] = (colsd[0] - red_mind) / (red_maxd - red_mind) * 255. + .5;
3568 colsd[1] = (colsd[1] - green_mind) / (green_maxd - green_mind) * 255. + .5;
3569 colsd[2] = (colsd[2] - blue_mind) / (blue_maxd - blue_mind) * 255. + .5;
3570
3571 if (colsd[0] < red_mind) colsd[0] = red_mind;
3572 if (colsd[1] < green_mind) colsd[1] = green_mind;
3573 if (colsd[2] < blue_mind) colsd[2] = blue_mind;
3574 if (colsd[0] > red_maxd) colsd[0] = red_maxd;
3575 if (colsd[1] > green_maxd) colsd[1] = green_maxd;
3576 if (colsd[2] > blue_maxd) colsd[2] = blue_maxd;
3577
3578 list = lives_list_append(list, lives_strdup_printf("%.2f", colsd[0]));
3579 list = lives_list_append(list, lives_strdup_printf("%.2f", colsd[1]));
3580 list = lives_list_append(list, lives_strdup_printf("%.2f", colsd[2]));
3581 set_param_from_list(list, &rfx->params[i], 0, FALSE, TRUE);
3582
3583 lives_list_free_all(&list);
3584 lives_free(colsds);
3585 if (maxds) lives_free(maxds);
3586 if (minds) lives_free(minds);
3587 }
3588 break;
3589 // TODO - other color spaces, e.g. RGBA24
3590 }
3591 break;
3592 } // hint
3593 }
3595 }
3596 lives_free(in_params);
3597}
void popup_lmap_errors(LiVESMenuItem *menuitem, livespointer user_data)
Definition: callbacks.c:9335
boolean check_for_layout_errors(const char *operation, int fileno, int start, int end, uint32_t *in_mask)
check for layout errors, using in_mask as a guide (mask values are taken from prefs->warn_mask,...
Definition: callbacks.c:4059
void ce_thumbs_update_visual_params(int key)
Definition: ce_thumbs.c:590
void ce_thumbs_check_for_rte(lives_rfx_t *rfx, lives_rfx_t *rte_rfx, int key)
Definition: ce_thumbs.c:602
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
boolean check_storage_space(int clipno, boolean is_processing)
Definition: dialogs.c:1086
void add_resnn_label(LiVESDialog *dialog)
Definition: dialogs.c:4567
boolean is_hidden_param(weed_plant_t *plant, int i)
returns the permanent (structural) state c.f check_hidden_gui() which sets flag values for params lin...
LIVES_GLOBAL_INLINE int filter_mutex_unlock(int key)
Definition: effects-weed.c:108
int rte_key_getmode(int key)
returns current active mode for a key (or -1)
weed_plant_t * weed_instance_get_filter(weed_plant_t *inst, boolean get_compound_parent)
Definition: effects-weed.c:180
int enabled_out_channels(weed_plant_t *plant, boolean count_repeats)
void rec_param_change(weed_plant_t *inst, int pnum)
record a parameter value change in our event_list
boolean has_video_chans_in(weed_plant_t *filter, boolean count_opt)
Definition: effects-weed.c:620
LIVES_GLOBAL_INLINE int filter_mutex_lock(int key)
Definition: effects-weed.c:96
boolean is_perchannel_multiw(weed_plant_t *param)
void fill_param_vals_to(weed_plant_t *param, weed_plant_t *paramtmpl, int index)
for a multi valued parameter or pchange, we will fill WEED_LEAF_VALUE up to element index with WEED_L...
LIVES_GLOBAL_INLINE int filter_mutex_trylock(int key)
Definition: effects-weed.c:74
int enabled_in_channels(weed_plant_t *plant, boolean count_repeats)
int set_copy_to(weed_plant_t *inst, int pnum, lives_rfx_t *rfx, boolean update)
LIVES_GLOBAL_INLINE boolean weed_instance_is_resizer(weed_plant_t *inst)
Definition: effects-weed.c:571
weed_plant_t * weed_filter_in_paramtmpl(weed_plant_t *filter, int param_num, boolean skip_internal)
boolean has_video_chans_out(weed_plant_t *filter, boolean count_opt)
Definition: effects-weed.c:676
int get_transition_param(weed_plant_t *filter, boolean skip_internal)
weed_plant_t * weed_inst_in_param(weed_plant_t *inst, int param_num, boolean skip_hidden, boolean skip_internal)
lives_filter_error_t weed_reinit_effect(weed_plant_t *inst, boolean reinit_compound)
lives_filter_error_t
filter apply errors
Definition: effects-weed.h:14
@ FILTER_SUCCESS
Definition: effects-weed.h:15
@ FILTER_INFO_REDRAWN
Definition: effects-weed.h:41
#define WEED_LEAF_HOST_NEXT_INSTANCE
Definition: effects-weed.h:104
#define WEED_LEAF_HOST_DISABLED
Definition: effects-weed.h:70
#define WEED_LEAF_HOST_WIDTH
Definition: effects-weed.h:63
#define WEED_LEAF_HOST_KEY
Definition: effects-weed.h:67
#define WEED_LEAF_HOST_REFS
Definition: effects-weed.h:72
#define WEED_LEAF_HOST_DEFAULT
Definition: effects-weed.h:62
#define WEED_LEAF_HOST_FPS
Definition: effects-weed.h:65
#define WEED_LEAF_HOST_HEIGHT
Definition: effects-weed.h:64
LiVESWidget * add_video_options(LiVESWidget **spwidth, int defwidth, LiVESWidget **spheight, int defheight, LiVESWidget **spfps, double deffps, LiVESWidget **spframes, int defframes, boolean add_aspect, LiVESWidget *extra)
Definition: events.c:6072
#define WEED_LEAF_HOST_AUDIO_TRANSITION
Definition: events.h:86
void widget_add_framedraw(LiVESVBox *box, int start, int end, boolean add_preview_button, int width, int height, lives_rfx_t *rfx)
call this to add framedraw widget to an hbox
Definition: framedraw.c:279
const lives_special_aspect_t * add_aspect_ratio_button(LiVESSpinButton *sp_width, LiVESSpinButton *sp_height, LiVESBox *box)
Definition: interface.c:4963
error("LSD_RANDFUNC(ptr, size) must be defined")
LIVES_GLOBAL_INLINE boolean lives_strcmp(const char *st1, const char *st2)
returns FALSE if strings match
LIVES_GLOBAL_INLINE size_t lives_strlen(const char *s)
LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew)
LIVES_GLOBAL_INLINE boolean lives_strncmp(const char *st1, const char *st2, size_t len)
returns FALSE if strings match
#define lives_free
Definition: machinestate.h:52
#define lives_memset
Definition: machinestate.h:61
#define lives_malloc
Definition: machinestate.h:46
_palette * palette
interface colour settings
Definition: main.c:101
mainwindow * mainw
Definition: main.c:103
void close_current_file(int file_to_switch_to)
close current file, and try to switch to file_to_switch_to
Definition: main.c:9373
#define LIVES_WARN(x)
Definition: main.h:1862
#define clipboard
Definition: main.h:1835
void lives_list_free_all(LiVESList **)
Definition: utils.c:4873
@ UNDO_RESIZABLE
Definition: main.h:662
size_t get_token_count(const char *string, int delim)
Definition: utils.c:5430
#define LIVES_GLOBAL_INLINE
Definition: main.h:239
char * subst(const char *string, const char *from, const char *to)
Definition: utils.c:5484
#define LIVES_IS_PLAYING
Definition: main.h:840
void set_undoable(const char *what, boolean sensitive)
Definition: utils.c:4784
void lives_kill_subprocesses(const char *dirname, boolean kill_parent)
Definition: utils.c:4516
boolean get_new_handle(int index, const char *name)
Definition: saveplay.c:3821
#define ALIGN_CEIL(a, b)
Definition: main.h:286
int count_resampled_frames(int in_frames, double orig_fps, double resampled_fps)
Definition: resample.c:72
#define FPS_MAX
maximum fps we will allow (double)
Definition: main.h:218
#define CURRENT_CLIP_IS_NORMAL
Definition: main.h:838
#define cfile
Definition: main.h:1833
int lives_list_strcmp_index(LiVESList *list, livesconstpointer data, boolean case_sensitive)
Definition: utils.c:4678
#define CURRENT_CLIP_IS_VALID
Definition: main.h:809
boolean lives_freep(void **ptr)
Definition: utils.c:1411
#define PLUGIN_EXEC_DIR
Definition: mainwindow.h:599
#define DEF_FPS
Definition: mainwindow.h:47
#define LIVES_MAIN_WINDOW_WIDGET
Definition: mainwindow.h:188
#define DEF_BUTTON_WIDTH
Definition: mainwindow.h:182
#define DEF_GEN_HEIGHT
Definition: mainwindow.h:150
#define RFX_WINSIZE_V
Definition: mainwindow.h:177
#define GUI_SCREEN_WIDTH
Definition: mainwindow.h:99
#define DEF_GEN_WIDTH
Definition: mainwindow.h:149
#define STYLE_1
turn on theming if set
Definition: mainwindow.h:299
_merge_opts * merge_opts
Definition: mainwindow.h:1849
#define RFX_WINSIZE_H
size of the fx dialog windows scrollwindow
Definition: mainwindow.h:175
_fx_dialog * fx_dialog[2]
Definition: mainwindow.h:1851
#define SCR_WIDTH_SAFETY
sepwin/screen size safety margins in pixels
Definition: mainwindow.h:89
uint32_t mt_idle_add(lives_mt *mt)
Definition: multitrack.c:901
void mt_desensitise(lives_mt *mt)
Definition: multitrack.c:16979
void activate_mt_preview(lives_mt *mt)
sensitize Show Preview and Apply buttons
Definition: multitrack.c:19400
void polymorph(lives_mt *mt, lives_mt_poly_state_t poly)
Definition: multitrack.c:12777
void mt_sensitise(lives_mt *mt)
Definition: multitrack.c:17052
@ POLY_CLIPS
Definition: multitrack.h:123
@ POLY_NONE
Definition: multitrack.h:122
void check_for_special(lives_rfx_t *rfx, lives_param_t *param, LiVESBox *pbox)
Definition: paramspecial.c:298
boolean special_cleanup(boolean is_ok)
Definition: paramspecial.c:641
void add_to_special(const char *sp_string, lives_rfx_t *rfx)
Definition: paramspecial.c:53
void fd_connect_spinbutton(lives_rfx_t *rfx)
Definition: paramspecial.c:174
boolean is_perchannel_multi(lives_rfx_t *rfx, int i)
Definition: paramspecial.c:765
void init_special(void)
Definition: paramspecial.c:30
void fd_tweak(lives_rfx_t *rfx)
Definition: paramspecial.c:159
void reset_framedraw_preview(void)
Definition: paramspecial.c:27
void check_for_special_type(lives_rfx_t *rfx, lives_param_t *param, LiVESBox *pbox)
Definition: paramspecial.c:228
LiVESList * argv_to_marshalled_list(lives_rfx_t *rfx, int argc, char **argv)
Definition: paramwindow.c:3031
LiVESWidget * add_param_label_to_box(LiVESBox *box, boolean do_trans, const char *text)
Definition: paramwindow.c:1844
boolean do_effect(lives_rfx_t *, boolean is_preview)
defined as extern in paramwindow.c
Definition: effects.c:127
char * param_marshall(lives_rfx_t *rfx, boolean with_min_max)
Definition: paramwindow.c:2844
void on_render_fx_activate(LiVESMenuItem *menuitem, lives_rfx_t *rfx)
Definition: paramwindow.c:222
void on_pwcolsel(LiVESButton *button, lives_rfx_t *rfx)
Definition: paramwindow.c:3338
void after_param_red_changed(LiVESSpinButton *spinbutton, lives_rfx_t *rfx)
Definition: paramwindow.c:2372
boolean add_param_to_box(LiVESBox *box, lives_rfx_t *rfx, int pnum, boolean add_slider)
Definition: paramwindow.c:1484
void after_param_alpha_changed(LiVESSpinButton *spinbutton, lives_rfx_t *rfx)
Definition: paramwindow.c:2558
void on_realfx_activate(LiVESMenuItem *, livespointer rfx)
Definition: effects.c:799
lives_widget_group_t * livesgrp_from_usrgrp(LiVESSList *u2l, int usrgrp)
Definition: paramwindow.c:1882
LiVESList * do_onchange(LiVESWidgetObject *object, lives_rfx_t *rfx)
object should have g_set_object_data "param_number" set to parameter number
Definition: paramwindow.c:3265
LIVES_GLOBAL_INLINE void on_render_fx_pre_activate(LiVESMenuItem *menuitem, lives_rfx_t *rfx)
Definition: paramwindow.c:656
void transition_add_in_out(LiVESBox *vbox, lives_rfx_t *rfx, boolean add_audio_check)
Definition: paramwindow.c:352
boolean after_param_text_focus_changed(LiVESWidget *hbox, LiVESWidget *child, lives_rfx_t *rfx)
Definition: paramwindow.c:2606
int set_param_from_list(LiVESList *plist, lives_param_t *param, int pnum, boolean with_min_max, boolean upd)
update values for param using values in plist if upd is TRUE, the widgets for that param also are upd...
Definition: paramwindow.c:3065
void on_paramwindow_button_clicked(LiVESButton *button, lives_rfx_t *rfx)
Definition: paramwindow.c:90
char ** param_marshall_to_argv(lives_rfx_t *rfx)
Definition: paramwindow.c:2797
void update_visual_params(lives_rfx_t *rfx, boolean update_hidden)
apply internal value changes to interface widgets
Definition: paramwindow.c:3361
void after_param_green_changed(LiVESSpinButton *spinbutton, lives_rfx_t *rfx)
Definition: paramwindow.c:2435
void param_demarshall(lives_rfx_t *rfx, LiVESList *plist, boolean with_min_max, boolean upd)
Definition: paramwindow.c:3013
void after_boolean_param_toggled(LiVESToggleButton *togglebutton, lives_rfx_t *rfx)
Definition: paramwindow.c:2035
boolean update_widget_vis(lives_rfx_t *rfx, int key, int mode)
show / hide widgets set by plugin in init_func()
Definition: paramwindow.c:1893
_fx_dialog * on_fx_pre_activate(lives_rfx_t *rfx, boolean is_realtime, LiVESWidget *pbox)
Definition: paramwindow.c:687
void after_param_blue_changed(LiVESSpinButton *spinbutton, lives_rfx_t *rfx)
Definition: paramwindow.c:2497
char * reconstruct_string(LiVESList *plist, int start, int *offs)
Definition: paramwindow.c:2961
void after_param_text_changed(LiVESWidget *textwidget, lives_rfx_t *rfx)
Definition: paramwindow.c:2635
void update_weed_color_value(weed_plant_t *plant, int pnum, int c1, int c2, int c3, int c4, lives_rfx_t *rfx)
Definition: paramwindow.c:2225
void after_string_list_changed(LiVESWidget *entry, lives_rfx_t *rfx)
Definition: paramwindow.c:2726
boolean make_param_box(LiVESVBox *top_vbox, lives_rfx_t *rfx)
make a dynamic parameter window
Definition: paramwindow.c:1015
void after_param_value_changed(LiVESSpinButton *spinbutton, lives_rfx_t *rfx)
Definition: paramwindow.c:2102
LiVESList * do_onchange_init(lives_rfx_t *rfx)
Definition: paramwindow.c:35
LiVESSList * add_usrgrp_to_livesgrp(LiVESSList *u2l, LiVESSList *rbgroup, int usr_number)
Definition: paramwindow.c:1872
#define DEF_SLIDER_WIDTH
Definition: paramwindow.h:27
#define GIW_KNOB_WIDTH
Definition: paramwindow.h:24
#define GIW_KNOB_HEIGHT
Definition: paramwindow.h:25
#define RFX_TEXT_MAGIC
length at which entry turns into textview
Definition: paramwindow.h:16
#define FMT_STRING_SIZE
Definition: paramwindow.h:20
#define RFX_TEXT_SCROLL_HEIGHT
height of textview scrolled window
Definition: paramwindow.h:22
#define MAX_FMT_STRINGS
Definition: paramwindow.h:19
void set_colRGBA32_param(void *value, short red, short green, short blue, short alpha)
Definition: plugins.c:3166
LiVESList * get_external_window_hints(lives_rfx_t *rfx)
get the interface hints set by a Weed filter in the filter_class.
Definition: plugins.c:3618
void do_rfx_cleanup(lives_rfx_t *rfx)
Definition: plugins.c:2671
void get_colRGBA32_param(void *value, lives_colRGBA64_t *rgba)
Definition: plugins.c:3098
void get_colRGB24_param(void *value, lives_colRGB48_t *rgb)
Definition: plugins.c:3093
void rfx_free(lives_rfx_t *rfx)
Definition: plugins.c:2987
void set_double_param(void *value, double _const)
Definition: plugins.c:3119
double get_double_param(void *value)
Definition: plugins.c:3086
void set_bool_param(void *value, boolean _const)
Definition: plugins.c:3103
boolean get_bool_param(void *value)
Definition: plugins.c:3072
LIVES_GLOBAL_INLINE LiVESList * plugin_request_by_line(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:59
int get_int_param(void *value)
Definition: plugins.c:3079
LIVES_GLOBAL_INLINE LiVESList * plugin_request_by_space(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:64
void set_colRGB24_param(void *value, short red, short green, short blue)
Definition: plugins.c:3149
void set_int_param(void *value, int _const)
Definition: plugins.c:3114
#define FX_CANDIDATE_RESIZER
Definition: plugins.h:695
#define PLUGIN_RENDERED_EFFECTS_CUSTOM
in the config directory
Definition: plugins.h:472
#define REINIT_FUNCTIONAL
Definition: plugins.h:566
#define MAX_PARAM_WIDGETS
max number of display widgets per parameter (currently 7 for transition param with mergealign - spin ...
Definition: plugins.h:488
#define HIDDEN_GUI_PERM
Definition: plugins.h:551
@ RFX_STATUS_TEST
test effects in the advanced menu
Definition: plugins.h:614
@ RFX_STATUS_CUSTOM
custom effects in the custom menu
Definition: plugins.h:613
@ RFX_STATUS_WEED
indicates an internal RFX, created from a weed instance
Definition: plugins.h:616
@ RFX_STATUS_BUILTIN
factory presets
Definition: plugins.h:612
@ RFX_STATUS_SCRAP
used for parsing RFX scraps from external apps
Definition: plugins.h:617
@ LIVES_PARAM_SPECIAL_TYPE_FILEREAD
Definition: plugins.h:528
@ LIVES_PARAM_SPECIAL_TYPE_FONT_CHOOSER
Definition: plugins.h:531
@ LIVES_PARAM_SPECIAL_TYPE_FILEWRITE
Definition: plugins.h:529
#define HIDDEN_GUI_TEMP
Definition: plugins.h:558
@ LIVES_PARAM_COLRGB24
Definition: plugins.h:504
@ LIVES_PARAM_STRING
Definition: plugins.h:505
@ LIVES_PARAM_UNDISPLAYABLE
Definition: plugins.h:509
@ LIVES_PARAM_STRING_LIST
Definition: plugins.h:506
@ LIVES_PARAM_BOOL
Definition: plugins.h:503
@ LIVES_PARAM_UNKNOWN
Definition: plugins.h:501
@ LIVES_PARAM_NUM
Definition: plugins.h:502
#define HIDDEN_NEEDS_REINIT
non-structural (temporary)
Definition: plugins.h:557
#define WIDGET_RB_OUT
Definition: plugins.h:494
#define RFX_MAX_NORM_WIDGETS
Definition: plugins.h:490
#define PLUGIN_RENDERED_EFFECTS_TEST
Definition: plugins.h:473
#define HIDDEN_STRUCTURAL
Definition: plugins.h:554
@ LIVES_RFX_SOURCE_WEED
Definition: plugins.h:514
@ LIVES_RFX_SOURCE_RFX
Definition: plugins.h:513
@ LIVES_RFX_SOURCE_NEWCLIP
Definition: plugins.h:515
#define WIDGET_RB_IN
special widgets
Definition: plugins.h:493
#define HIDDEN_UNDISPLAYABLE
structural (permanent)
Definition: plugins.h:550
#define PLUGIN_RFX_SCRAP
scraps are passed between programs to generate param windows
Definition: plugins.h:483
#define RFX_PROPS_BATCHG
is a batch generator
Definition: plugins.h:636
#define RFX_FLAGS_NO_RESET
Definition: plugins.h:647
#define WIDGET_RB_DUMMY
Definition: plugins.h:495
#define PLUGIN_RENDERED_EFFECTS_BUILTIN
external rendered fx plugins (RFX plugins)
Definition: plugins.h:469
#define RFX_FLAGS_NO_SLIDERS
internal use
Definition: plugins.h:646
#define RFX_PROPS_MAY_RESIZE
is a tool
Definition: plugins.h:635
_prefs * prefs
Definition: preferences.h:847
#define WARN_MASK_LAYOUT_ALTER_FRAMES
off by default on a fresh install
Definition: preferences.h:102
#define REC_EFFECTS
Definition: preferences.h:199
void rte_set_key_defs(LiVESButton *button, lives_rfx_t *rfx)
Definition: rte_window.c:2531
void rte_set_defs_cancel(LiVESButton *button, lives_rfx_t *rfx)
Definition: rte_window.c:2593
void rte_reset_defs_clicked(LiVESButton *button, lives_rfx_t *rfx)
Definition: rte_window.c:2599
void rte_set_defs_ok(LiVESButton *button, lives_rfx_t *rfx)
Definition: rte_window.c:2547
lives_rfx_t * rfx
Definition: mainwindow.h:1843
LiVESWidget * resetbutton
Definition: mainwindow.h:1842
LiVESWidget * dialog
Definition: mainwindow.h:1839
LiVESWidget * okbutton
Definition: mainwindow.h:1841
LiVESWidget * cancelbutton
Definition: mainwindow.h:1840
boolean loop_to_fit
Definition: mainwindow.h:1829
LiVESWidget * spinbutton_loops
Definition: mainwindow.h:1827
boolean align_start
Definition: mainwindow.h:1830
LiVESWidgetColor dark_orange
Definition: mainwindow.h:312
LiVESWidgetColor normal_fore
Definition: mainwindow.h:325
int style
Definition: mainwindow.h:297
LiVESWidgetColor white
Definition: mainwindow.h:306
LiVESWidgetColor normal_back
Definition: mainwindow.h:324
double default_fps
Definition: preferences.h:173
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
int rec_opts
Definition: preferences.h:196
char config_datadir[PATH_MAX]
kept in locale encoding (general config files) (default ~/.local/share/lives)
Definition: preferences.h:64
boolean ins_resample
Definition: preferences.h:184
char lib_dir[PATH_MAX]
Definition: preferences.h:75
char backend_sync[PATH_MAX *4]
Definition: preferences.h:410
boolean lamp_buttons
Definition: preferences.h:343
int vsize
frame height (vertical) in pixels
Definition: main.h:897
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
double fps
Definition: main.h:893
uint16_t green
Definition: main.h:318
uint16_t red
Definition: main.h:317
uint16_t blue
Definition: main.h:319
uint16_t alpha
Definition: main.h:326
uint16_t blue
Definition: main.h:325
uint16_t green
Definition: main.h:324
uint16_t red
Definition: main.h:323
lives_rfx_t * rfx
pointer to rfx for current delegate (or NULL)
Definition: plugins.h:690
lives_param_type_t type
Definition: plugins.h:573
boolean use_mnemonic
Definition: plugins.h:545
char * label
Definition: plugins.h:543
boolean changed
Definition: plugins.h:597
boolean onchange
is there a trigger ?
Definition: plugins.h:595
boolean wrap
Definition: plugins.h:571
int dp
decimals, 0 for int and bool
Definition: plugins.h:575
LiVESWidget * widgets[MAX_PARAM_WIDGETS]
TODO - change to LiVESWidget **widgets, terminated with a NULL.
Definition: plugins.h:594
uint32_t hidden
Definition: plugins.h:546
char * desc
Definition: plugins.h:541
boolean transition
Definition: plugins.h:564
void * def
default values
Definition: plugins.h:581
double min
Definition: plugins.h:578
double step_size
Definition: plugins.h:562
lives_param_special_t special_type
Definition: plugins.h:607
void * value
current value(s)
Definition: plugins.h:576
double max
for string this is max characters
Definition: plugins.h:579
boolean change_blocked
Definition: plugins.h:600
LiVESList * list
for string list (choices)
Definition: plugins.h:582
int num_params
Definition: plugins.h:644
uint32_t props
Definition: plugins.h:633
char * menu_text
for Weed, this is the filter_class "name"
Definition: plugins.h:627
char delim[2]
Definition: plugins.h:652
uint32_t flags
Definition: plugins.h:645
lives_param_t * params
Definition: plugins.h:649
lives_rfx_status_t status
Definition: plugins.h:631
int num_in_channels
Definition: plugins.h:630
void * source
points to the source (e.g. a weed_plant_t)
Definition: plugins.h:651
boolean is_template
Definition: plugins.h:656
lives_rfx_source_t source_type
Definition: plugins.h:650
int needs_reinit
Definition: plugins.h:657
int min_frames
for Weed, 1
Definition: plugins.h:629
char * name
the name of the executable (so we can run it !)
Definition: plugins.h:626
LiVESSList * rbgroup
Definition: paramwindow.h:12
boolean ce_thumbs
Definition: mainwindow.h:1676
boolean gen_to_clipboard
rendered generators
Definition: mainwindow.h:1564
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
volatile boolean record
Definition: mainwindow.h:794
boolean block_param_updates
block visual param changes from updating real values
Definition: mainwindow.h:1550
LiVESWidget * resize_menuitem
Definition: mainwindow.h:1436
int current_file
Definition: mainwindow.h:727
boolean show_procd
override showing of "processing..." dialog
Definition: mainwindow.h:1548
LiVESWidget * framedraw_preview
the 'redraw' button
Definition: mainwindow.h:1265
int pre_src_file
video file we were playing before any ext input started
Definition: mainwindow.h:971
LiVESWidget * textwidget_focus
Definition: mainwindow.h:1569
boolean did_rfx_preview
Definition: mainwindow.h:1056
boolean error
Definition: mainwindow.h:801
lives_fx_candidate_t fx_candidates[MAX_FX_CANDIDATE_TYPES]
< effects which can have candidates from which a delegate is selected (current examples are: audio_vo...
Definition: mainwindow.h:1514
boolean suppress_dprint
tidy up, e.g. by blocking "switched to file..." and "closed file..." messages
Definition: mainwindow.h:1537
LiVESWidget * framedraw
for the framedraw special widget - TODO - use a sub-struct
Definition: mainwindow.h:1263
int framedraw_frame
current displayed frame
Definition: mainwindow.h:1278
volatile boolean record_paused
pause during recording
Definition: mainwindow.h:1557
boolean keep_pre
set if previewed frames should be retained as processed frames (for rendered effects / generators)
Definition: mainwindow.h:1567
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
int first_free_file
Definition: mainwindow.h:728
int fd_max_frame
max effected / generated frame
Definition: mainwindow.h:1279
boolean is_generating
Definition: mainwindow.h:1565
LiVESJustification justify
justify for labels
LiVESWidget * last_label
commonly adjusted values //////
double scale
scale factor for all sizes
int packing_height
vertical pixels between widgets
int filler_len
length of extra "fill" between widgets
boolean mnemonic_label
if underscore in label text should be mnemonic accelerator
boolean pack_end
pack widget at end or start
lives_expand_t expand
how much space to apply between widgets
int packing_width
horizontal pixels between widgets
int apply_theme
theming variation for widget (0 -> no theme, 1 -> normal colours, 2+ -> theme variants)
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
#define _(String)
Definition: support.h:44
#define TRUE
Definition: videoplugin.h:59
#define FALSE
Definition: videoplugin.h:60
#define ABS(a)
Definition: videoplugin.h:63
WEED_GLOBAL_INLINE void weed_instance_set_flags(weed_plant_t *inst, int flags)
WEED_GLOBAL_INLINE weed_plant_t * weed_param_get_template(weed_plant_t *param)
WEED_GLOBAL_INLINE weed_plant_t * weed_param_get_gui(weed_plant_t *param, int create_if_not_exists)
WEED_GLOBAL_INLINE int weed_paramtmpl_get_type(weed_plant_t *paramtmpl)
WEED_GLOBAL_INLINE int weed_param_is_hidden(weed_plant_t *param, int temporary)
WEED_GLOBAL_INLINE weed_plant_t ** weed_instance_get_in_params(weed_plant_t *instance, int *nparams)
WEED_GLOBAL_INLINE int weed_instance_get_flags(weed_plant_t *inst)
WEED_GLOBAL_INLINE int weed_param_value_irrelevant(weed_plant_t *param)
#define WEED_PLANT_IS_FILTER_INSTANCE(plant)
#define WEED_PLANT_IS_FILTER_CLASS(plant)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_response(LiVESDialog *dialog, int response)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_remove_accel_group(LiVESWindow *window, LiVESAccelGroup *group)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_hexpand(LiVESWidget *widget, boolean state)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_mnemonic_widget(LiVESLabel *label, LiVESWidget *widget)
boolean lives_widget_set_show_hide_with(LiVESWidget *widget, LiVESWidget *other)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_new(LiVESBox *box)
WIDGET_HELPER_GLOBAL_INLINE int lives_layout_add_row(LiVESLayout *layout)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_value(LiVESSpinButton *button, double value)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_bg_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment * lives_spin_button_get_adjustment(LiVESSpinButton *button)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_set_tooltip_text(LiVESWidget *widget, const char *tip_text)
WIDGET_HELPER_GLOBAL_INLINE LiVESTextBuffer * lives_text_view_get_buffer(LiVESTextView *tview)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_cursor_visible(LiVESTextView *tview, boolean setting)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetColor * lives_color_button_get_color(LiVESColorButton *button, LiVESWidgetColor *color)
WIDGET_HELPER_GLOBAL_INLINE int lives_dialog_get_response_for_widget(LiVESDialog *dialog, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vbox_new(boolean homogeneous, int spacing)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_label_new(const char *text)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_hbox_new(LiVESLayout *layout)
WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup * lives_accel_group_new(void)
LiVESWidget * lives_standard_entry_new(const char *labeltext, const char *txt, int dispwidth, int maxchars, LiVESBox *box, const char *tooltip)
boolean lives_button_grab_default_special(LiVESWidget *button)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_wrap(LiVESSpinButton *button, boolean wrap)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_update(LiVESSpinButton *button)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
LiVESWidget * lives_standard_color_button_new(LiVESBox *box, const char *name, boolean use_alpha, lives_colRGBA64_t *rgba, LiVESWidget **sb_red, LiVESWidget **sb_green, LiVESWidget **sb_blue, LiVESWidget **sb_alpha)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_ref_sink(livespointer object)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_start(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill, uint32_t padding)
LiVESWidget * lives_standard_dialog_new(const char *title, boolean add_std_buttons, int width, int height)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_color_button_set_color(LiVESColorButton *button, const LiVESWidgetColor *color)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_fg_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_set_text(LiVESTextBuffer *tbuff, const char *text, int len)
WIDGET_HELPER_GLOBAL_INLINE const char * lives_entry_get_text(LiVESEntry *entry)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive(LiVESWidget *widget, boolean state)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_unblock_by_func(livespointer instance, LiVESGuiCallback func, livespointer data)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_row_new(LiVESLayout *layout)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_string(LiVESCombo *combo, const char *active_str)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_markup(LiVESLabel *label, const char *markup)
WIDGET_HELPER_GLOBAL_INLINE boolean toggle_toggles_var(LiVESToggleButton *tbut, boolean *var, boolean invert)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_dialog_get_content_area(LiVESDialog *dialog)
LiVESWidget * lives_standard_hscale_new(LiVESAdjustment *adj)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_halign(LiVESWidget *widget, LiVESAlign align)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_pack(LiVESHBox *box, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_add_label(LiVESLayout *layout, const char *text, boolean horizontal)
LiVESWidget * add_hsep_to_box(LiVESBox *box)
LiVESWidget * add_fill_to_box(LiVESBox *box)
WIDGET_HELPER_GLOBAL_INLINE const char * lives_combo_get_active_text(LiVESCombo *combo)
WIDGET_HELPER_GLOBAL_INLINE int lives_spin_button_get_value_as_int(LiVESSpinButton *button)
void lives_widget_apply_theme3(LiVESWidget *widget, LiVESWidgetState state)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_add_separator(LiVESLayout *layout, boolean horizontal)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_vexpand(LiVESWidget *widget, boolean state)
void lives_widget_apply_theme2(LiVESWidget *widget, LiVESWidgetState state, boolean set_fg)
boolean lives_text_view_set_text(LiVESTextView *textview, const char *text, int len)
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
LiVESWidget * lives_standard_label_new_with_mnemonic_widget(const char *text, LiVESWidget *mnemonic_widget)
LiVESWidget * lives_standard_scrolled_window_new(int width, int height, LiVESWidget *child)
LiVESWidget * lives_dialog_add_button_from_stock(LiVESDialog *dialog, const char *stock_id, const char *label, int response_id)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_editable(LiVESTextView *tview, boolean setting)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_block_by_func(livespointer instance, LiVESGuiCallback func, livespointer data)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_no_show_all(LiVESWidget *widget, boolean set)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_active(LiVESToggleButton *button, boolean active)
WIDGET_HELPER_GLOBAL_INLINE double lives_spin_button_get_value(LiVESSpinButton *button)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_add_fill(LiVESLayout *layout, boolean horizontal)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_hide(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_snap_to_multiples(LiVESSpinButton *button, double mult)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_get_parent(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hseparator_new(void)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hbox_new(boolean homogeneous, int spacing)
LiVESWidget * lives_standard_label_new(const char *text)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_wrap_mode(LiVESTextView *tview, LiVESWrapMode wrapmode)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_valign(LiVESWidget *widget, LiVESAlign align)
char * lives_text_view_get_text(LiVESTextView *textview)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_get_toplevel(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_size_request(LiVESWidget *widget, int width, int height)
LiVESWidget * lives_standard_check_button_new(const char *labeltext, boolean active, LiVESBox *box, const char *tooltip)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_add_accelerator(LiVESWidget *widget, const char *accel_signal, LiVESAccelGroup *accel_group, uint32_t accel_key, LiVESXModifierType accel_mods, LiVESAccelFlags accel_flags)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_source_remove(uint32_t handle)
LiVESWidget * lives_standard_spin_button_new(const char *labeltext, double val, double min, double max, double step, double page, int dp, LiVESBox *box, const char *tooltip)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_set_focus_child(LiVESContainer *cont, LiVESWidget *child)
LiVESWidget * lives_standard_combo_new(const char *labeltext, LiVESList *list, LiVESBox *box, const char *tooltip)
LiVESWidget * lives_layout_expansion_row_new(LiVESLayout *layout, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_text_view_new(void)
void lives_general_button_clicked(LiVESButton *button, livespointer data_to_free)
LiVESWidget * lives_standard_radio_button_new(const char *labeltext, LiVESSList **rbgroup, LiVESBox *box, const char *tooltip)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_add_accel_group(LiVESWindow *window, LiVESAccelGroup *group)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_set_homogeneous(LiVESBox *box, boolean homogenous)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_range(LiVESSpinButton *button, double min, double max)
void lives_widget_apply_theme(LiVESWidget *widget, LiVESWidgetState state)
#define RFX_KEY
#define TEXTWIDGET_KEY
#define PARAM_NUMBER_KEY
#define LIVES_EXPAND_EXTRA
#define LIVES_EXPAND_DEFAULT
#define WH_LAYOUT_KEY
widget_opts_t widget_opts
#define LIVES_JUSTIFY_DEFAULT