LiVES  3.2.0
rfx-builder.c
Go to the documentation of this file.
1 // rfx-builder.c
2 // LiVES
3 // (c) G. Finch 2004 - 2020 <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 #include <errno.h>
8 
9 #include "main.h"
10 #include "rfx-builder.h"
11 #include "interface.h"
12 #include "paramwindow.h"
13 #include "effects.h"
14 
15 #define BG_LOAD
16 
17 static LiVESWidget *make_param_dialog(int pnum, rfx_build_window_t *rfxbuilder);
18 static LiVESWidget *make_param_window_dialog(int hnum, rfx_build_window_t *rfxbuilder);
19 static LiVESWidget *make_trigger_dialog(int tnum, rfx_build_window_t *rfxbuilder);
20 static void on_table_add_row(LiVESButton *, livespointer rfxbuilder);
21 static void on_table_edit_row(LiVESButton *, livespointer rfxbuilder);
22 static void on_table_swap_row(LiVESButton *, livespointer rfxbuilder);
23 static void on_table_delete_row(LiVESButton *, livespointer rfxbuilder);
24 
25 static void param_set_from_dialog(lives_param_t *copy_param, rfx_build_window_t *rfxbuilder);
26 
27 static void after_param_dp_changed(LiVESSpinButton *, livespointer rfxbuilder);
28 static void after_param_min_changed(LiVESSpinButton *, livespointer rfxbuilder);
29 static void after_param_max_changed(LiVESSpinButton *, livespointer rfxbuilder);
30 static void after_param_def_changed(LiVESSpinButton *, livespointer rfxbuilder);
31 static void after_rfxbuilder_type_toggled(LiVESToggleButton *, livespointer rfxbuilder);
32 static void on_param_type_changed(LiVESCombo *, livespointer rfxbuilder);
33 static void on_paramw_kw_changed(LiVESCombo *, livespointer rfxbuilder);
34 static void on_paramw_sp_changed(LiVESCombo *, livespointer rfxbuilder);
35 static void on_paramw_spsub_changed(LiVESCombo *, livespointer rfxbuilder);
36 static void populate_script_combo(LiVESCombo *script_combo, lives_rfx_status_t status);
37 static void on_script_status_changed(LiVESCombo *status_combo, livespointer script_combo);
38 
39 // builder window widgets/callbacks
40 static rfx_build_window_t *make_rfx_build_window(const char *in_script_name, lives_rfx_status_t in_status);
41 static void on_rfxbuilder_ok(LiVESButton *, livespointer);
42 static void on_rfxbuilder_cancel(LiVESButton *, livespointer);
43 static void rfxbuilder_destroy(rfx_build_window_t *);
44 static void on_list_table_clicked(LiVESButton *, livespointer rfxbuilder);
45 static void on_requirements_ok(LiVESButton *, livespointer rfxbuilder);
46 static void on_requirements_cancel(LiVESButton *, livespointer);
47 static void on_properties_clicked(LiVESButton *, livespointer rfxbuilder);
48 static void on_properties_ok(LiVESButton *, livespointer rfxbuilder);
49 static void on_params_ok(LiVESButton *, livespointer rfxbuilder);
50 static void on_params_cancel(LiVESButton *, livespointer);
51 static void on_param_window_ok(LiVESButton *, livespointer rfxbuilder);
52 static void on_param_window_cancel(LiVESButton *, livespointer);
53 static void on_code_clicked(LiVESButton *, livespointer rfxbuilder);
54 static void on_code_ok(LiVESButton *, livespointer rfxbuilder);
55 static void on_triggers_ok(LiVESButton *, livespointer rfxbuilder);
56 static void on_triggers_cancel(LiVESButton *, livespointer);
57 
58 static LiVESWidget *copy_script_okbutton;
59 
60 static void table_select_row(rfx_build_window_t *rfxbuilder, int row);
61 
62 void on_new_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data) {
63  rfx_build_window_t *rfxbuilder;
64 
65  if (!check_builder_programs()) return;
66  rfxbuilder = make_rfx_build_window(NULL, RFX_STATUS_ANY);
67  lives_widget_show(rfxbuilder->dialog);
68 }
69 
70 
71 void on_edit_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data) {
72  rfx_build_window_t *rfxbuilder;
73  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
74  char *script_name;
75 
76  if (!check_builder_programs()) return;
77  if (status != RFX_STATUS_TEST) return; // we only edit test effects currently
78 
79  if ((script_name = prompt_for_script_name(NULL, RFX_STATUS_TEST)) == NULL) return;
80  if (!strlen(script_name)) {
81  lives_free(script_name);
82  return;
83  }
84  if ((rfxbuilder = make_rfx_build_window(script_name, RFX_STATUS_TEST)) == NULL) {
85  lives_free(script_name);
86  return; // script not loaded
87  }
88  lives_free(script_name);
89  rfxbuilder->mode = RFX_BUILDER_MODE_EDIT;
90  rfxbuilder->oname = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->name_entry)));
91  lives_widget_show(rfxbuilder->dialog);
92 }
93 
94 
95 void on_copy_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data) {
96  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
97 
98  if (!check_builder_programs()) return;
99  if (status != RFX_STATUS_TEST) return; // we only copy to test effects currently
100 
101  // prompt_for_script_name will create our builder window from the input
102  // script and set the name : note, we have no rfxbuilder reference
103 
104  // TODO - use RFXBUILDER_MODE-*
106 }
107 
108 
109 void on_rename_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data) {
110  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
111 
112  if (status != RFX_STATUS_TEST) return; // we only copy to test effects currently
113 
115 }
116 
117 
118 rfx_build_window_t *make_rfx_build_window(const char *script_name, lives_rfx_status_t status) {
119  // TODO - set mnemonic widgets for entries
120 
121  LiVESWidget *dialog_vbox;
122  LiVESWidget *hbox;
123  LiVESWidget *layout;
124  LiVESWidget *label;
125  LiVESWidget *okbutton;
126  LiVESWidget *cancelbutton;
127  LiVESWidget *scrollw;
128  LiVESWidget *top_vbox;
129 
130  LiVESSList *radiobutton_type_group = NULL;
131  LiVESList *langc = NULL;
132 
134 
135  LiVESAccelGroup *accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
136 
137  int winsize_h, winsize_v;
138 
139  char *tmp, *tmp2, *title, *string;
140 
141  rfxbuilder->rfx_version = lives_strdup(RFX_VERSION);
142 
143  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT1; // the default
144 
145  rfxbuilder->num_reqs = 0;
146  rfxbuilder->num_params = 0;
147  rfxbuilder->num_paramw_hints = 0;
148 
149  rfxbuilder->num_triggers = 0;
150 
151  rfxbuilder->has_init_trigger = FALSE;
152  rfxbuilder->props = 0;
153 
154  rfxbuilder->plugin_version = 1;
155 
156  rfxbuilder->pre_code = lives_strdup("");
157  rfxbuilder->loop_code = lives_strdup("");
158  rfxbuilder->post_code = lives_strdup("");
159 
160  rfxbuilder->field_delim = lives_strdup("|");
161 
162  rfxbuilder->script_name = NULL; // use default name.script
163  rfxbuilder->oname = NULL;
164 
165  rfxbuilder->mode = RFX_BUILDER_MODE_NEW;
166 
167  rfxbuilder->table_swap_row1 = -1;
168 
170 
171  if (!script_name) {
172  title = (_("New Test RFX"));
173  } else {
174  title = (_("Edit Test RFX"));
175  }
176 
178  SCR_WIDTH_SAFETY / 5.;
179 
181  SCR_HEIGHT_SAFETY / 2.;
182 
183  rfxbuilder->dialog = lives_standard_dialog_new(title, FALSE, winsize_h, winsize_v);
184  lives_free(title);
185 
186  lives_window_add_accel_group(LIVES_WINDOW(rfxbuilder->dialog), accel_group);
187 
188  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(rfxbuilder->dialog));
190 
191  top_vbox = lives_vbox_new(FALSE, 0);
192 
193  scrollw = lives_standard_scrolled_window_new(winsize_h, winsize_v, top_vbox);
194 
195  lives_box_pack_start(LIVES_BOX(dialog_vbox), scrollw, TRUE, TRUE, 0);
196 
197  // types
198  hbox = lives_hbox_new(FALSE, 0);
199  lives_box_pack_start(LIVES_BOX(top_vbox), hbox, TRUE, TRUE, 0);
200 
201  label = lives_standard_label_new(_("Type:"));
202  lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, widget_opts.packing_width);
203 
205  rfxbuilder->type_effect1_radiobutton = lives_standard_radio_button_new(string, &radiobutton_type_group, LIVES_BOX(hbox), NULL);
206  lives_free(string);
207 
209  rfxbuilder->type_effect2_radiobutton = lives_standard_radio_button_new(string, &radiobutton_type_group, LIVES_BOX(hbox), NULL);
210  lives_free(string);
211 
213  rfxbuilder->type_effect0_radiobutton = lives_standard_radio_button_new(string, &radiobutton_type_group, LIVES_BOX(hbox), NULL);
214  lives_free(string);
215 
216  rfxbuilder->type_tool_radiobutton = lives_standard_radio_button_new(_("tool"), &radiobutton_type_group, LIVES_BOX(hbox), NULL);
217  lives_widget_show(label);
218 
219  rfxbuilder->type_utility_radiobutton = lives_standard_radio_button_new(_("utility"), &radiobutton_type_group, LIVES_BOX(hbox),
220  NULL);
221 
222  layout = lives_layout_new(LIVES_BOX(top_vbox));
223  hbox = lives_layout_hbox_new(LIVES_LAYOUT(layout));
224 
225  // name
226 
227  rfxbuilder->name_entry = lives_standard_entry_new((tmp = (_("Name: "))), NULL, -1, -1,
228  LIVES_BOX(hbox), (tmp2 = (_("The name of the plugin. No spaces allowed."))));
229  lives_free(tmp); lives_free(tmp2);
230 
231  // version
232  hbox = lives_layout_row_new(LIVES_LAYOUT(layout));
233 
234  rfxbuilder->spinbutton_version = lives_standard_spin_button_new((tmp = (_("Version: "))),
235  rfxbuilder->plugin_version, rfxbuilder->plugin_version, 1000000., 1., 1., 0,
236  LIVES_BOX(hbox), (tmp2 = (_("The script version."))));
237  lives_free(tmp); lives_free(tmp2);
238 
239  // author
240  hbox = lives_layout_row_new(LIVES_LAYOUT(layout));
241 
242  rfxbuilder->author_entry = lives_standard_entry_new((tmp = (_(" Author: "))), NULL, -1, -1,
243  LIVES_BOX(hbox), (tmp2 = (_("The script author."))));
244  lives_free(tmp); lives_free(tmp2);
245 
246  // URL
247  hbox = lives_layout_row_new(LIVES_LAYOUT(layout));
248 
249  rfxbuilder->url_entry = lives_standard_entry_new((tmp = (_(" URL (optional): "))), NULL, -1, -1,
250  LIVES_BOX(hbox), (tmp2 = (_("URL for the plugin maintainer."))));
251  lives_free(tmp); lives_free(tmp2);
252 
253  // menu entry
254  hbox = lives_layout_row_new(LIVES_LAYOUT(layout));
255 
256  rfxbuilder->menu_text_entry = lives_standard_entry_new((tmp = (_("Menu text: "))), NULL, -1, -1,
257  LIVES_BOX(hbox), (tmp2 = (_("The text to show in the menu."))));
258  lives_free(tmp); lives_free(tmp2);
259 
260  rfxbuilder->action_desc_hsep = add_hsep_to_box(LIVES_BOX(top_vbox));
261 
262  // action description
263 
264  rfxbuilder->action_desc_hbox = lives_hbox_new(FALSE, 0);
265  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->action_desc_hbox, FALSE, FALSE, widget_opts.packing_height);
266 
267  rfxbuilder->action_desc_entry = lives_standard_entry_new((tmp = (_("Action description: "))), NULL, -1, -1,
268  LIVES_BOX(rfxbuilder->action_desc_hbox),
269  (tmp2 = (_("Describe what the plugin is doing. E.g. \"Edge detecting\""))));
270  lives_free(tmp); lives_free(tmp2);
271 
272  rfxbuilder->spinbutton_min_frames = lives_standard_spin_button_new((tmp = (_("Minimum frames:"))),
273  1., 1., 1000., 1., 1., 0, LIVES_BOX(top_vbox),
274  (tmp2 = (_("Minimum number of frames this effect/tool can be applied to. Normally 1."))));
275  lives_free(tmp); lives_free(tmp2);
277 
278  // requirements
279 
280  add_hsep_to_box(LIVES_BOX(top_vbox));
281 
282  rfxbuilder->requirements_button = lives_standard_button_new_with_label(_("_Requirements..."),
284 
285  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->requirements_button, TRUE, TRUE, 0);
287  (_("Enter any binaries required by the plugin.")));
288 
289  add_hsep_to_box(LIVES_BOX(top_vbox));
290 
291  rfxbuilder->properties_button = lives_standard_button_new_with_label(_("_Properties..."),
293 
294  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->properties_button, TRUE, TRUE, 0);
296  (_("Set properties for the plugin. Optional.")));
297 
298  add_hsep_to_box(LIVES_BOX(top_vbox));
299 
300  rfxbuilder->params_button = lives_standard_button_new_with_label(_("_Parameters..."),
302 
303  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->params_button, TRUE, TRUE, 0);
305  (_("Set up parameters used in pre/loop/post/trigger code. Optional.")));
306 
307  add_hsep_to_box(LIVES_BOX(top_vbox));
308 
309  rfxbuilder->param_window_button = lives_standard_button_new_with_label(_("Parameter _Window Hints..."),
311 
312  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->param_window_button, TRUE, TRUE, 0);
314  (_("Set hints about how to lay out the parameter window. Optional.")));
315 
316  add_hsep_to_box(LIVES_BOX(top_vbox));
317 
318  langc = lives_list_append(langc, (livespointer)"0xF0 - LiVES-Perl");
319 
320  rfxbuilder->langc_combo = lives_standard_combo_new((tmp = (_("_Language code:"))), langc, LIVES_BOX(top_vbox),
321  (tmp2 = (_("Language for pre/loop/post/triggers. Optional."))));
322 
323  lives_free(tmp); lives_free(tmp2);
324  lives_list_free(langc);
325 
326  add_hsep_to_box(LIVES_BOX(top_vbox));
327 
328  rfxbuilder->pre_button = lives_standard_button_new_with_label(_("_Pre loop code..."),
330 
331  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->pre_button, TRUE, TRUE, 0);
333  (_("Code to be executed before the loop. Optional.")));
334 
335  add_hsep_to_box(LIVES_BOX(top_vbox));
336 
337  rfxbuilder->loop_button = lives_standard_button_new_with_label(_("_Loop code..."),
339 
340  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->loop_button, TRUE, TRUE, 0);
342  (_("Loop code to be applied to each frame.")));
343 
344  add_hsep_to_box(LIVES_BOX(top_vbox));
345 
346  rfxbuilder->post_button = lives_standard_button_new_with_label(_("_Post loop code..."),
348 
349  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->post_button, TRUE, TRUE, 0);
351  (_("Code to be executed after the loop. Optional.")));
352 
353  add_hsep_to_box(LIVES_BOX(top_vbox));
354 
355  rfxbuilder->trigger_button = lives_standard_button_new_with_label(_("_Trigger code..."),
357 
358  lives_box_pack_start(LIVES_BOX(top_vbox), rfxbuilder->trigger_button, TRUE, TRUE, 0);
360  (_("Set trigger code for when the parameter window is shown, or when a parameter is changed. "
361  "Optional (except for Utilities).")));
362 
363  cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(rfxbuilder->dialog), LIVES_STOCK_CANCEL, NULL,
364  LIVES_RESPONSE_CANCEL);
365 
366  okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(rfxbuilder->dialog), LIVES_STOCK_OK, NULL,
367  LIVES_RESPONSE_OK);
368 
370 
371  lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
372  LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
373 
374  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
375  LIVES_GUI_CALLBACK(on_rfxbuilder_ok), (livespointer)rfxbuilder);
376 
377  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
378  LIVES_GUI_CALLBACK(on_rfxbuilder_cancel), (livespointer)rfxbuilder);
379 
380  lives_signal_sync_connect(rfxbuilder->requirements_button, LIVES_WIDGET_CLICKED_SIGNAL,
381  LIVES_GUI_CALLBACK(on_list_table_clicked), (livespointer)rfxbuilder);
382 
383  lives_signal_sync_connect(rfxbuilder->properties_button, LIVES_WIDGET_CLICKED_SIGNAL,
384  LIVES_GUI_CALLBACK(on_properties_clicked), (livespointer)rfxbuilder);
385 
386  lives_signal_sync_connect(rfxbuilder->params_button, LIVES_WIDGET_CLICKED_SIGNAL,
387  LIVES_GUI_CALLBACK(on_list_table_clicked), (livespointer)rfxbuilder);
388 
389  lives_signal_sync_connect(rfxbuilder->param_window_button, LIVES_WIDGET_CLICKED_SIGNAL,
390  LIVES_GUI_CALLBACK(on_list_table_clicked), (livespointer)rfxbuilder);
391 
392  lives_signal_sync_connect(rfxbuilder->trigger_button, LIVES_WIDGET_CLICKED_SIGNAL,
393  LIVES_GUI_CALLBACK(on_list_table_clicked), (livespointer)rfxbuilder);
394 
395  lives_signal_sync_connect(rfxbuilder->pre_button, LIVES_WIDGET_CLICKED_SIGNAL,
396  LIVES_GUI_CALLBACK(on_code_clicked), (livespointer)rfxbuilder);
397 
398  lives_signal_sync_connect(rfxbuilder->loop_button, LIVES_WIDGET_CLICKED_SIGNAL,
399  LIVES_GUI_CALLBACK(on_code_clicked), (livespointer)rfxbuilder);
400 
401  lives_signal_sync_connect(rfxbuilder->post_button, LIVES_WIDGET_CLICKED_SIGNAL,
402  LIVES_GUI_CALLBACK(on_code_clicked), (livespointer)rfxbuilder);
403 
404  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->type_effect1_radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
405  LIVES_GUI_CALLBACK(after_rfxbuilder_type_toggled), (livespointer)rfxbuilder);
406 
407  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->type_effect2_radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
408  LIVES_GUI_CALLBACK(after_rfxbuilder_type_toggled), (livespointer)rfxbuilder);
409 
410  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->type_effect0_radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
411  LIVES_GUI_CALLBACK(after_rfxbuilder_type_toggled), (livespointer)rfxbuilder);
412 
413  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->type_tool_radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
414  LIVES_GUI_CALLBACK(after_rfxbuilder_type_toggled), (livespointer)rfxbuilder);
415 
416  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->type_utility_radiobutton), LIVES_WIDGET_TOGGLED_SIGNAL,
417  LIVES_GUI_CALLBACK(after_rfxbuilder_type_toggled), (livespointer)rfxbuilder);
418 
419  // edit mode
420  if (script_name) {
421  // we assume the name is valid
422  char *script_file;
423 
424  switch (status) {
425  case RFX_STATUS_CUSTOM:
426  script_file = lives_build_filename(prefs->config_datadir,
427  PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS, script_name, NULL);
428  break;
429  case RFX_STATUS_BUILTIN:
430  script_file = lives_build_filename(prefs->prefix_dir, PLUGIN_SCRIPTS_DIR,
431  PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS, script_name, NULL);
432  break;
433  default:
434  script_file = lives_build_filename(prefs->config_datadir,
435  PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS, script_name, NULL);
436  break;
437  }
438  if (!script_to_rfxbuilder(rfxbuilder, script_file)) {
439  char *msg = lives_strdup_printf(_("\n\nUnable to parse the script file:\n%s\n%s\n"), script_file, mainw->msg);
440  // must use blocking error dialogs as the scriptname window is modal
441  do_error_dialog(msg);
442  lives_free(msg);
443  rfxbuilder_destroy(rfxbuilder);
444  lives_free(script_file);
445  return NULL;
446  }
447  lives_free(script_file);
448  switch (rfxbuilder->type) {
449  case RFX_BUILD_TYPE_TOOL:
450  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->type_tool_radiobutton), TRUE);
451  break;
453  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->type_effect0_radiobutton), TRUE);
454  break;
456  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->type_utility_radiobutton), TRUE);
457  break;
459  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->type_effect2_radiobutton), TRUE);
460  break;
461  default:
462  break;
463  }
464  } else {
465  lives_widget_grab_focus(rfxbuilder->name_entry);
466  }
467 
468  lives_widget_show_all(rfxbuilder->dialog);
469 
470  return rfxbuilder;
471 }
472 
473 
474 void after_rfxbuilder_type_toggled(LiVESToggleButton *togglebutton, livespointer user_data) {
475  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
476 
483  lives_widget_show(rfxbuilder->min_frames_label);
484  lives_widget_show(rfxbuilder->action_desc_hbox);
485  lives_widget_show(rfxbuilder->action_desc_hsep);
486 
487  if (togglebutton == LIVES_TOGGLE_BUTTON(rfxbuilder->type_effect1_radiobutton)) {
488  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT1;
489  } else if (togglebutton == LIVES_TOGGLE_BUTTON(rfxbuilder->type_effect2_radiobutton)) {
490  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT2;
492  } else if (togglebutton == LIVES_TOGGLE_BUTTON(rfxbuilder->type_effect0_radiobutton)) {
493  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT0;
495  lives_widget_hide(rfxbuilder->min_frames_label);
496  } else if (togglebutton == LIVES_TOGGLE_BUTTON(rfxbuilder->type_tool_radiobutton)) {
497  rfxbuilder->type = RFX_BUILD_TYPE_TOOL;
500  lives_widget_hide(rfxbuilder->min_frames_label);
501  } else if (togglebutton == LIVES_TOGGLE_BUTTON(rfxbuilder->type_utility_radiobutton)) {
502  rfxbuilder->type = RFX_BUILD_TYPE_UTILITY;
509  lives_widget_hide(rfxbuilder->min_frames_label);
510  lives_widget_hide(rfxbuilder->action_desc_hbox);
511  lives_widget_hide(rfxbuilder->action_desc_hsep);
512  }
513 }
514 
515 
516 static void on_list_table_clicked(LiVESButton *button, livespointer user_data) {
517  LiVESWidget *dialog;
518  LiVESWidget *dialog_vbox;
519  LiVESWidget *hbox;
520  LiVESWidget *button_box;
521 
522  // buttons
523  LiVESWidget *okbutton;
524  LiVESWidget *scrolledwindow;
525  LiVESWidget *cancelbutton;
526 
527  LiVESAccelGroup *accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
528 
529  char *title = NULL;
530 
531  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
532 
533  register int i;
534 
535  if (button == LIVES_BUTTON(rfxbuilder->requirements_button)) {
537  } else if (button == LIVES_BUTTON(rfxbuilder->params_button)) {
538  rfxbuilder->table_type = RFX_TABLE_TYPE_PARAMS;
539  } else if (button == LIVES_BUTTON(rfxbuilder->param_window_button)) {
541  } else if (button == LIVES_BUTTON(rfxbuilder->trigger_button)) {
542  rfxbuilder->table_type = RFX_TABLE_TYPE_TRIGGERS;
543  }
544 
545  if (rfxbuilder->table_type == RFX_TABLE_TYPE_REQUIREMENTS) {
546  title = (_("RFX Requirements"));
547  rfxbuilder->onum_reqs = rfxbuilder->num_reqs;
548  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAMS) {
549  title = (_("RFX Parameters"));
550  rfxbuilder->onum_params = rfxbuilder->num_params;
551  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAM_WINDOW) {
552  title = (_("RFX Parameter Window Hints"));
553  rfxbuilder->onum_paramw_hints = rfxbuilder->num_paramw_hints;
554  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_TRIGGERS) {
555  title = (_("RFX Triggers"));
556  rfxbuilder->onum_triggers = rfxbuilder->num_triggers;
557  }
558 
560  lives_signal_handlers_disconnect_by_func(dialog, LIVES_GUI_CALLBACK(return_true), NULL);
561 
562  if (title) lives_free(title);
563 
564  lives_window_add_accel_group(LIVES_WINDOW(dialog), accel_group);
565 
566  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
567 
568  // create table and add rows
569  rfxbuilder->table_rows = 0;
570 
571  if (rfxbuilder->table_type == RFX_TABLE_TYPE_REQUIREMENTS) {
572  rfxbuilder->table = lives_table_new(rfxbuilder->num_reqs, 1, FALSE);
573  for (i = 0; i < rfxbuilder->num_reqs; i++) {
574  on_table_add_row(NULL, (livespointer)rfxbuilder);
575  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry[i]), rfxbuilder->reqs[i]);
576  }
577  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAMS) {
579  rfxbuilder->table = lives_table_new(rfxbuilder->num_params, 3, FALSE);
580  for (i = 0; i < rfxbuilder->num_params; i++) {
581  param_copy(&rfxbuilder->copy_params[i], &rfxbuilder->params[i], FALSE);
582  on_table_add_row(NULL, (livespointer)rfxbuilder);
583  }
584  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAM_WINDOW) {
585  rfxbuilder->table = lives_table_new(rfxbuilder->table_rows, 2, FALSE);
586  for (i = 0; i < rfxbuilder->num_paramw_hints; i++) {
587  on_table_add_row(NULL, (livespointer)rfxbuilder);
588  }
589  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_TRIGGERS) {
591  rfxbuilder->table = lives_table_new(rfxbuilder->table_rows, 1, FALSE);
592  for (i = 0; i < rfxbuilder->num_triggers; i++) {
593  rfxbuilder->copy_triggers[i].when = rfxbuilder->triggers[i].when;
594  rfxbuilder->copy_triggers[i].code = lives_strdup(rfxbuilder->triggers[i].code);
595  on_table_add_row(NULL, (livespointer)rfxbuilder);
596  }
597  }
598 
599  hbox = lives_hbox_new(FALSE, 0);
600 
601  lives_box_pack_start(LIVES_BOX(dialog_vbox), hbox, TRUE, TRUE, widget_opts.packing_height);
602 
603  scrolledwindow = lives_standard_scrolled_window_new(RFX_WINSIZE_H, RFX_WINSIZE_V / 4, rfxbuilder->table);
604 
605  lives_box_pack_start(LIVES_BOX(hbox), scrolledwindow, TRUE, TRUE, widget_opts.packing_width);
606 
607  add_vsep_to_box(LIVES_BOX(hbox));
608 
609  // button box on right
610 
611  button_box = lives_vbutton_box_new();
612  lives_button_box_set_layout(LIVES_BUTTON_BOX(button_box), LIVES_BUTTONBOX_START);
613 
614  lives_box_pack_start(LIVES_BOX(hbox), button_box, FALSE, FALSE, 0);
615 
616  rfxbuilder->new_entry_button = lives_standard_button_new_with_label(_("_New Entry"),
619 
620  lives_box_pack_start(LIVES_BOX(button_box), rfxbuilder->new_entry_button, FALSE, FALSE, widget_opts.packing_height);
622 
623  rfxbuilder->edit_entry_button = lives_standard_button_new_with_label(_("_Edit Entry"),
626 
627  lives_box_pack_start(LIVES_BOX(button_box), rfxbuilder->edit_entry_button, FALSE, FALSE, widget_opts.packing_height);
629 
630  rfxbuilder->remove_entry_button = lives_standard_button_new_with_label(_("_Remove Entry"),
633 
634  lives_box_pack_start(LIVES_BOX(button_box), rfxbuilder->remove_entry_button, FALSE, FALSE, widget_opts.packing_height);
636 
637  if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAM_WINDOW) {
638  rfxbuilder->move_up_button = lives_standard_button_new_with_label(_("Move _Up"),
641 
642  lives_box_pack_start(LIVES_BOX(button_box), rfxbuilder->move_up_button, FALSE, FALSE, widget_opts.packing_height);
644 
645  rfxbuilder->move_down_button = lives_standard_button_new_with_label(_("Move _Down"),
648 
649  lives_box_pack_start(LIVES_BOX(button_box), rfxbuilder->move_down_button, FALSE, FALSE, widget_opts.packing_height);
651 
654  } else {
655  rfxbuilder->move_up_button = rfxbuilder->move_down_button = NULL;
656  }
657 
660 
661  if (rfxbuilder->table_type == RFX_TABLE_TYPE_TRIGGERS) {
662  if (rfxbuilder->num_triggers > rfxbuilder->num_params) {
664  }
665  }
666 
667  cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_CANCEL, NULL,
668  LIVES_RESPONSE_CANCEL);
669 
670  okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_OK, NULL,
671  LIVES_RESPONSE_OK);
672 
673  lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
674  LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
675 
677 
678  if (rfxbuilder->table_type == RFX_TABLE_TYPE_REQUIREMENTS) {
679  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
680  LIVES_GUI_CALLBACK(on_requirements_ok), user_data);
681 
682  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
683  LIVES_GUI_CALLBACK(on_requirements_cancel), user_data);
684  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAMS) {
685  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
686  LIVES_GUI_CALLBACK(on_params_ok), user_data);
687 
688  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
689  LIVES_GUI_CALLBACK(on_params_cancel), user_data);
690  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAM_WINDOW) {
691  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
692  LIVES_GUI_CALLBACK(on_param_window_ok), user_data);
693 
694  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
695  LIVES_GUI_CALLBACK(on_param_window_cancel),
696  user_data);
697  } else if (rfxbuilder->table_type == RFX_TABLE_TYPE_TRIGGERS) {
698  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
699  LIVES_GUI_CALLBACK(on_triggers_ok), user_data);
700 
701  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
702  LIVES_GUI_CALLBACK(on_triggers_cancel), user_data);
703  }
704 
705  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->new_entry_button), LIVES_WIDGET_CLICKED_SIGNAL,
706  LIVES_GUI_CALLBACK(on_table_add_row), user_data);
707 
708  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->edit_entry_button), LIVES_WIDGET_CLICKED_SIGNAL,
709  LIVES_GUI_CALLBACK(on_table_edit_row), user_data);
710 
711  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->remove_entry_button), LIVES_WIDGET_CLICKED_SIGNAL,
712  LIVES_GUI_CALLBACK(on_table_delete_row), user_data);
713 
714  if (rfxbuilder->table_type == RFX_TABLE_TYPE_PARAM_WINDOW) {
715  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->move_up_button), LIVES_WIDGET_CLICKED_SIGNAL,
716  LIVES_GUI_CALLBACK(on_table_swap_row), user_data);
717 
718  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->move_down_button), LIVES_WIDGET_CLICKED_SIGNAL,
719  LIVES_GUI_CALLBACK(on_table_swap_row), user_data);
720  }
721 
722  lives_widget_show_all(dialog);
723  table_select_row(rfxbuilder, -1);
724 }
725 
726 
727 static void on_requirements_ok(LiVESButton *button, livespointer user_data) {
728  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
729 
730  int i;
731  for (i = 0; i < rfxbuilder->onum_reqs; i++) {
732  lives_free(rfxbuilder->reqs[i]);
733  }
734  for (i = 0; i < rfxbuilder->num_reqs; i++) {
735  rfxbuilder->reqs[i] = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[i])));
736  }
737  lives_general_button_clicked(button, NULL);
738 }
739 
740 
741 static void on_requirements_cancel(LiVESButton *button, livespointer user_data) {
742  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
743 
744  rfxbuilder->num_reqs = rfxbuilder->onum_reqs;
745  lives_general_button_clicked(button, NULL);
746 }
747 
748 
749 static void on_properties_ok(LiVESButton *button, livespointer user_data) {
750  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
751 
752  if (rfxbuilder->type != RFX_BUILD_TYPE_EFFECT0) {
753  if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(rfxbuilder->prop_slow))) {
754  rfxbuilder->props |= RFX_PROPS_SLOW;
755  } else if (rfxbuilder->props & RFX_PROPS_SLOW) {
756  rfxbuilder->props ^= RFX_PROPS_SLOW;
757  }
758  } else {
759  if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(rfxbuilder->prop_batchg))) {
760  rfxbuilder->props |= RFX_PROPS_BATCHG;
761  } else if (rfxbuilder->props & RFX_PROPS_BATCHG) {
762  rfxbuilder->props ^= RFX_PROPS_BATCHG;
763  }
764  }
765  lives_general_button_clicked(button, NULL);
766 }
767 
768 
769 static void on_params_ok(LiVESButton *button, livespointer user_data) {
770  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
771 
772  register int i;
773 
774  for (i = 0; i < rfxbuilder->onum_params; i++) {
775  lives_free(rfxbuilder->params[i].name);
776  lives_free(rfxbuilder->params[i].label);
777  if (rfxbuilder->params[i].type == LIVES_PARAM_STRING_LIST) {
778  if (rfxbuilder->params[i].list) lives_list_free(rfxbuilder->params[i].list);
779  }
780  if (rfxbuilder->copy_params[i].def) lives_free(rfxbuilder->params[i].def);
781  }
782  if (rfxbuilder->onum_params) {
783  lives_free(rfxbuilder->params);
784  }
785  rfxbuilder->params = (lives_param_t *)lives_malloc(rfxbuilder->num_params * sizeof(lives_param_t));
786  for (i = 0; i < rfxbuilder->num_params; i++) {
787  param_copy(&rfxbuilder->params[i], &rfxbuilder->copy_params[i], FALSE);
788 
789  // this is the only place these should be freed
790  lives_free(rfxbuilder->copy_params[i].name);
791  lives_free(rfxbuilder->copy_params[i].label);
792  if (rfxbuilder->copy_params[i].type == LIVES_PARAM_STRING_LIST) {
793  if (rfxbuilder->copy_params[i].list) lives_list_free(rfxbuilder->copy_params[i].list);
794  }
795  if (rfxbuilder->copy_params[i].def) lives_free(rfxbuilder->copy_params[i].def);
796  }
797  if (rfxbuilder->num_params) {
798  lives_free(rfxbuilder->copy_params);
799  }
800  lives_general_button_clicked(button, NULL);
801 }
802 
803 static void on_params_cancel(LiVESButton *button, livespointer user_data) {
804  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
805 
806  for (register int i = 0; i < rfxbuilder->num_params; i++) {
807  // this is the only place these should be freed
808  lives_free(rfxbuilder->copy_params[i].name);
809  lives_free(rfxbuilder->copy_params[i].label);
810  if (rfxbuilder->copy_params[i].type == LIVES_PARAM_STRING_LIST) {
811  if (rfxbuilder->copy_params[i].list) lives_list_free(rfxbuilder->copy_params[i].list);
812  }
813  if (rfxbuilder->copy_params[i].def) lives_free(rfxbuilder->copy_params[i].def);
814  }
815  if (rfxbuilder->num_params) {
816  lives_free(rfxbuilder->copy_params);
817  }
818  rfxbuilder->num_params = rfxbuilder->onum_params;
819  lives_general_button_clicked(button, NULL);
820 }
821 
822 
823 static void on_param_window_ok(LiVESButton *button, livespointer user_data) {
824  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
825 
826  register int i;
827 
828  for (i = 0; i < rfxbuilder->onum_paramw_hints; i++) {
829  lives_free(rfxbuilder->paramw_hints[i]);
830  }
831  for (i = 0; i < rfxbuilder->num_paramw_hints; i++) {
832  rfxbuilder->paramw_hints[i] = lives_strdup_printf("%s%s%s", lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[i])),
833  rfxbuilder->field_delim,
834  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry2[i])));
835  }
836  lives_general_button_clicked(button, NULL);
837 }
838 
839 static void on_param_window_cancel(LiVESButton *button, livespointer user_data) {
840  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
841 
842  rfxbuilder->num_paramw_hints = rfxbuilder->onum_paramw_hints;
843  lives_general_button_clicked(button, NULL);
844 }
845 
846 
847 static void on_code_ok(LiVESButton *button, livespointer user_data) {
848  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
849 
850  switch (rfxbuilder->codetype) {
851  case RFX_CODE_TYPE_PRE:
852  lives_free(rfxbuilder->pre_code);
853  rfxbuilder->pre_code = lives_text_view_get_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview));
854  break;
855 
856  case RFX_CODE_TYPE_LOOP:
857  lives_free(rfxbuilder->loop_code);
858  rfxbuilder->loop_code = lives_text_view_get_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview));
859  break;
860 
861  case RFX_CODE_TYPE_POST:
862  lives_free(rfxbuilder->post_code);
863  rfxbuilder->post_code = lives_text_view_get_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview));
864  break;
865 
866  case RFX_CODE_TYPE_STRDEF: {
867  int maxlen = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max));
868  char buf[++maxlen];
869 
870  if (rfxbuilder->copy_params[rfxbuilder->edit_param].def) lives_free(
871  rfxbuilder->copy_params[rfxbuilder->edit_param].def);
872  lives_snprintf(buf, maxlen, "%s", lives_text_view_get_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview)));
873 
874  rfxbuilder->copy_params[rfxbuilder->edit_param].def = subst(buf, rfxbuilder->field_delim, "");
875  break;
876  }
878  char *values = lives_text_view_get_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview));
879  int numlines = get_token_count(values, '\n');
880  char **lines = lives_strsplit(values, "\n", numlines);
881  int defindex = get_int_param(rfxbuilder->copy_params[rfxbuilder->edit_param].def);
882 
883  if (rfxbuilder->copy_params[rfxbuilder->edit_param].list) {
884  lives_list_free(rfxbuilder->copy_params[rfxbuilder->edit_param].list);
885  rfxbuilder->copy_params[rfxbuilder->edit_param].list = NULL;
886  }
887  for (register int i = 0; i < numlines; i++) {
888  if (i < numlines - 1 || strlen(lines[i])) {
889  rfxbuilder->copy_params[rfxbuilder->edit_param].list = lives_list_append
890  (rfxbuilder->copy_params[rfxbuilder->edit_param].list, lives_strdup(lines[i]));
891  }
892  }
893  lives_strfreev(lines);
894 
895  // set "default" combo - TODO - try to retain old default using string matching
896  lives_combo_populate(LIVES_COMBO(rfxbuilder->param_def_combo),
897  rfxbuilder->copy_params[rfxbuilder->edit_param].list);
898  if (!rfxbuilder->copy_params[rfxbuilder->edit_param].list ||
899  defindex > lives_list_length(rfxbuilder->copy_params[rfxbuilder->edit_param].list)) {
900  set_int_param(rfxbuilder->copy_params[rfxbuilder->edit_param].def, (defindex = 0));
901  }
902  if (rfxbuilder->copy_params[rfxbuilder->edit_param].list) {
903  lives_combo_set_active_string(LIVES_COMBO(rfxbuilder->param_def_combo),
904  (char *)lives_list_nth_data(rfxbuilder->copy_params[rfxbuilder->edit_param].list,
905  defindex));
906  // *INDENT-OFF*
907 }}}
908  // *INDENT-ON*
909 
910  lives_general_button_clicked(button, NULL);
911 }
912 
913 
914 static void on_triggers_ok(LiVESButton * button, livespointer user_data) {
915  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
916 
917  int i;
918  for (i = 0; i < rfxbuilder->onum_triggers; i++) {
919  lives_free(rfxbuilder->triggers[i].code);
920  }
921  if (rfxbuilder->onum_triggers) {
922  lives_free(rfxbuilder->triggers);
923  }
924  rfxbuilder->triggers = (rfx_trigger_t *)lives_malloc(rfxbuilder->num_triggers * sizeof(rfx_trigger_t));
925  for (i = 0; i < rfxbuilder->num_triggers; i++) {
926  rfxbuilder->triggers[i].when = rfxbuilder->copy_triggers[i].when;
927  rfxbuilder->triggers[i].code = lives_strdup(rfxbuilder->copy_triggers[i].code);
928  lives_free(rfxbuilder->copy_triggers[i].code);
929  }
930  if (rfxbuilder->num_triggers) {
931  lives_free(rfxbuilder->copy_triggers);
932  }
933  lives_general_button_clicked(button, NULL);
934 }
935 
936 
937 static void on_triggers_cancel(LiVESButton * button, livespointer user_data) {
938  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
939 
940  uint8_t *valid_triggers = NULL;
941 
942  boolean init_trigger_valid = FALSE;
943 
944  int i;
945 
946  if (rfxbuilder->num_params > 0)
947  valid_triggers = (uint8_t *)lives_calloc(rfxbuilder->num_params, 1);
948 
949  for (i = 0; i < rfxbuilder->num_triggers; i++) {
950  lives_free(rfxbuilder->copy_triggers[i].code);
951  }
952  if (rfxbuilder->num_triggers) {
953  lives_free(rfxbuilder->copy_triggers);
954  }
955  rfxbuilder->num_triggers = rfxbuilder->onum_triggers;
956 
957  for (i = 0; i < rfxbuilder->num_triggers; i++) {
958  int when = rfxbuilder->triggers[i].when;
959  if (when == 0) init_trigger_valid = 1;
960  else valid_triggers[when - 1] = 1;
961  }
962 
963  // reset onchange for anything not in triggers
964  for (i = 0; i < rfxbuilder->num_params; i++) {
965  if (!valid_triggers[i]) {
966  rfxbuilder->params[i].onchange = FALSE;
967  } else {
968  rfxbuilder->params[i].onchange = TRUE;
969  }
970  }
971 
972  if (valid_triggers) lives_free(valid_triggers);
973 
974  if (!init_trigger_valid) {
975  rfxbuilder->has_init_trigger = FALSE;
976  } else {
977  rfxbuilder->has_init_trigger = TRUE;
978  }
979 
980  lives_general_button_clicked(button, NULL);
981 }
982 
983 
984 static void on_properties_clicked(LiVESButton * button, livespointer user_data) {
985  LiVESWidget *dialog;
986  LiVESWidget *dialog_vbox;
987  LiVESWidget *cancelbutton;
988  LiVESWidget *okbutton;
989 
990  LiVESAccelGroup *accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
991 
992  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
993 
994  widget_opts.transient = LIVES_WINDOW(rfxbuilder->dialog);
995  dialog = lives_standard_dialog_new(_("RFX Properties"), FALSE, -1, -1);
996  lives_window_add_accel_group(LIVES_WINDOW(dialog), accel_group);
997 
998  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
999 
1000  rfxbuilder->prop_slow = lives_standard_check_button_new(_("_Slow (hint to GUI)"), FALSE, LIVES_BOX(dialog_vbox), NULL);
1001 
1002  if (rfxbuilder->type != RFX_BUILD_TYPE_EFFECT0) {
1003  lives_widget_show(rfxbuilder->prop_slow);
1004  }
1005 
1006  if (rfxbuilder->props & RFX_PROPS_SLOW) {
1007  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->prop_slow), TRUE);
1008  }
1009 
1010  if (rfxbuilder->type == RFX_BUILD_TYPE_EFFECT0) {
1011  rfxbuilder->prop_batchg = lives_standard_check_button_new(_("_Batch mode generator"), FALSE, LIVES_BOX(dialog_vbox), NULL);
1012  if (rfxbuilder->props & RFX_PROPS_BATCHG) {
1013  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->prop_batchg), TRUE);
1014  }
1015  }
1016 
1017  cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_CANCEL, NULL,
1018  LIVES_RESPONSE_CANCEL);
1019 
1020  okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_OK, NULL,
1021  LIVES_RESPONSE_OK);
1022 
1024 
1025  lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
1026  LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
1027 
1028  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1029  LIVES_GUI_CALLBACK(on_properties_ok), user_data);
1030 
1031  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
1032  LIVES_GUI_CALLBACK(lives_general_button_clicked), NULL);
1033 
1034  lives_widget_show_all(dialog);
1035 }
1036 
1037 
1038 static void table_select_row(rfx_build_window_t *rfxbuilder, int row) {
1039  for (register int i = 0; i < rfxbuilder->table_rows; i++) {
1040  if (i == row) {
1043  if (rfxbuilder->move_up_button) lives_widget_set_sensitive(rfxbuilder->move_up_button, i != 0);
1044  if (rfxbuilder->move_down_button) lives_widget_set_sensitive(rfxbuilder->move_down_button,
1045  i < rfxbuilder->table_rows - 1);
1046 
1047  lives_widget_set_sensitive(rfxbuilder->entry[i], TRUE);
1048  if (rfxbuilder->entry2[i]) {
1049  lives_widget_set_sensitive(rfxbuilder->entry2[i], TRUE);
1050  }
1051  if (rfxbuilder->entry3[i]) {
1052  lives_widget_set_sensitive(rfxbuilder->entry3[i], TRUE);
1053  }
1054  } else {
1055  lives_editable_select_region(LIVES_EDITABLE(rfxbuilder->entry[i]), 0, 0);
1056  lives_widget_set_sensitive(rfxbuilder->entry[i], FALSE);
1057  lives_entry_set_editable(LIVES_ENTRY(rfxbuilder->entry[i]), FALSE);
1058  if (rfxbuilder->entry2[i]) {
1059  lives_editable_select_region(LIVES_EDITABLE(rfxbuilder->entry2[i]), 0, 0);
1060  lives_widget_set_sensitive(rfxbuilder->entry2[i], FALSE);
1061  }
1062  if (rfxbuilder->entry3[i]) {
1063  lives_editable_select_region(LIVES_EDITABLE(rfxbuilder->entry3[i]), 0, 0);
1064  lives_widget_set_sensitive(rfxbuilder->entry3[i], FALSE);
1065  }
1066  }
1067  }
1068 }
1069 
1070 
1071 static boolean on_entry_click(LiVESWidget * widget, LiVESXEventButton * event, livespointer user_data) {
1072  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
1073 
1074  widget = lives_bin_get_child(LIVES_BIN(widget));
1075  for (register int i = 0; i < rfxbuilder->table_rows; i++) {
1076  if (widget == rfxbuilder->entry[i] || widget == rfxbuilder->entry2[i] || widget == rfxbuilder->entry3[i]) {
1077  table_select_row(rfxbuilder, i);
1078 
1079  if (event->type != LIVES_BUTTON_PRESS) {
1080  //double click
1081  on_table_edit_row(NULL, rfxbuilder);
1082  }
1083  return TRUE;
1084  }
1085  }
1086  return TRUE;
1087 }
1088 
1089 
1090 static void on_table_add_row(LiVESButton * button, livespointer user_data) {
1091  LiVESWidget *entry = NULL, *entry2 = NULL, *entry3 = NULL;
1092  LiVESWidget *param_dialog = NULL;
1093  LiVESWidget *param_window_dialog = NULL;
1094  LiVESWidget *trigger_dialog = NULL;
1095 
1096  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
1097  lives_param_t *param = NULL;
1098 
1099  register int i;
1100 
1101  char *tmpx;
1102  const char *ctext;
1103 
1104  LiVESWidget *ebox, *ebox2 = NULL, *ebox3 = NULL;
1105 
1106  rfxbuilder->entry2[rfxbuilder->table_rows] = rfxbuilder->entry3[rfxbuilder->table_rows] = NULL;
1107 
1108  switch (rfxbuilder->table_type) {
1110  if (rfxbuilder->table_rows >= RFXBUILD_MAX_REQ) return;
1111 
1112  for (i = 0; i < rfxbuilder->table_rows; i++) {
1113  lives_entry_set_editable(LIVES_ENTRY(rfxbuilder->entry[i]), FALSE);
1114  }
1115 
1116  entry = rfxbuilder->entry[rfxbuilder->table_rows] = lives_standard_entry_new(NULL, NULL, -1, -1, NULL, NULL);
1117 
1118  if (button)
1119  lives_entry_set_editable(LIVES_ENTRY(entry), TRUE);
1120  else
1121  lives_entry_set_editable(LIVES_ENTRY(entry), FALSE);
1122 
1123  ebox = lives_event_box_new();
1124  lives_widget_set_events(ebox, LIVES_BUTTON_PRESS_MASK);
1125 
1126  lives_container_add(LIVES_CONTAINER(ebox), entry);
1127 
1128  lives_table_resize(LIVES_TABLE(rfxbuilder->table), ++rfxbuilder->table_rows, 1);
1129  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox, 0, 1, rfxbuilder->table_rows - 1,
1130  rfxbuilder->table_rows,
1131  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
1132  (LiVESAttachOptions)(0), 0, 0);
1133 
1135  lives_widget_grab_focus(entry);
1136  if (button) {
1137  rfxbuilder->num_reqs++;
1138  } else goto add_row_done;
1139  break;
1140 
1141  case RFX_TABLE_TYPE_PARAMS:
1142  entry = rfxbuilder->entry[rfxbuilder->table_rows] = lives_entry_new();
1143  entry2 = rfxbuilder->entry2[rfxbuilder->table_rows] = lives_entry_new();
1144 
1145  if (button) {
1146  boolean param_ok = FALSE;
1147  param = &rfxbuilder->copy_params[rfxbuilder->num_params];
1148 
1149  param->def = NULL;
1150  param->list = NULL;
1151  param->type = LIVES_PARAM_UNKNOWN;
1152 
1153  param_dialog = make_param_dialog(-1, rfxbuilder);
1154  do {
1155  if (lives_dialog_run(LIVES_DIALOG(param_dialog)) == LIVES_RESPONSE_CANCEL) {
1156  lives_free(param->def);
1157  lives_widget_destroy(entry);
1158  lives_widget_destroy(entry2);
1159  return;
1160  }
1161  param_ok = perform_param_checks(rfxbuilder, rfxbuilder->num_params, rfxbuilder->num_params + 1);
1162  } while (!param_ok);
1163 
1164  rfxbuilder->num_params++;
1165 
1166  lives_entry_set_text(LIVES_ENTRY(entry2), lives_entry_get_text(LIVES_ENTRY(rfxbuilder->param_name_entry)));
1167  } else {
1168  lives_entry_set_text(LIVES_ENTRY(entry2), rfxbuilder->params[rfxbuilder->table_rows].name);
1169  }
1170 
1171  lives_entry_set_text(LIVES_ENTRY(entry), (tmpx = lives_strdup_printf("p%d", rfxbuilder->table_rows)));
1172  lives_free(tmpx);
1173 
1174  lives_entry_set_editable(LIVES_ENTRY(entry), FALSE);
1175 
1176  ebox = lives_event_box_new();
1177  lives_widget_set_events(ebox, LIVES_BUTTON_PRESS_MASK);
1178 
1179  lives_container_add(LIVES_CONTAINER(ebox), entry);
1180 
1181  lives_table_resize(LIVES_TABLE(rfxbuilder->table), ++rfxbuilder->table_rows, 3);
1182 
1183  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox, 0, 1, rfxbuilder->table_rows - 1,
1184  rfxbuilder->table_rows,
1185  (LiVESAttachOptions)(0),
1186  (LiVESAttachOptions)(0), 0, 0);
1187 
1188  lives_entry_set_editable(LIVES_ENTRY(entry2), FALSE);
1189 
1190  ebox2 = lives_event_box_new();
1191  lives_widget_set_events(ebox2, LIVES_BUTTON_PRESS_MASK);
1192  lives_container_add(LIVES_CONTAINER(ebox2), entry2);
1193 
1194  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox2, 1, 2, rfxbuilder->table_rows - 1,
1195  rfxbuilder->table_rows,
1196  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
1197  (LiVESAttachOptions)(0), 0, 0);
1198 
1199  entry3 = rfxbuilder->entry3[rfxbuilder->table_rows - 1] = lives_entry_new();
1200 
1201  if (!button) {
1202  param = &rfxbuilder->params[rfxbuilder->table_rows - 1];
1203  } else {
1204  param_set_from_dialog((param = &rfxbuilder->copy_params[rfxbuilder->table_rows - 1]), rfxbuilder);
1205  }
1206 
1207  switch (param->type) {
1208  case LIVES_PARAM_NUM:
1209  lives_entry_set_text(LIVES_ENTRY(entry3), (tmpx = lives_strdup_printf("num%d", param->dp)));
1210  lives_free(tmpx);
1211  break;
1212  case LIVES_PARAM_BOOL:
1213  lives_entry_set_text(LIVES_ENTRY(entry3), "bool");
1214  break;
1215  case LIVES_PARAM_COLRGB24:
1216  lives_entry_set_text(LIVES_ENTRY(entry3), "colRGB24");
1217  break;
1218  case LIVES_PARAM_STRING:
1219  lives_entry_set_text(LIVES_ENTRY(entry3), "string");
1220  break;
1222  lives_entry_set_text(LIVES_ENTRY(entry3), "string_list");
1223  break;
1224  default:
1225  break;
1226  }
1227 
1228  lives_entry_set_editable(LIVES_ENTRY(entry3), FALSE);
1229 
1230  ebox3 = lives_event_box_new();
1231  lives_widget_set_events(ebox3, LIVES_BUTTON_PRESS_MASK);
1232  lives_container_add(LIVES_CONTAINER(ebox3), entry3);
1233 
1234  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox3, 2, 3, rfxbuilder->table_rows - 1,
1235  rfxbuilder->table_rows,
1236  (LiVESAttachOptions)(LIVES_FILL),
1237  (LiVESAttachOptions)(0), 0, 0);
1238 
1239  if (param_dialog) lives_widget_destroy(param_dialog);
1240  if (!button) goto add_row_done;
1241 
1242  lives_widget_queue_resize(lives_widget_get_parent(LIVES_WIDGET(rfxbuilder->table)));
1243  break;
1244 
1246  if (button) {
1247  param_window_dialog = make_param_window_dialog(-1, rfxbuilder);
1248  if (lives_dialog_run(LIVES_DIALOG(param_window_dialog)) == LIVES_RESPONSE_CANCEL) {
1249  return;
1250  }
1251  entry = rfxbuilder->entry[rfxbuilder->table_rows] = lives_entry_new();
1252  ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->paramw_kw_combo));
1253  lives_entry_set_text(LIVES_ENTRY(entry), ctext);
1254  rfxbuilder->num_paramw_hints++;
1255  } else {
1256  char **array = lives_strsplit(rfxbuilder->paramw_hints[rfxbuilder->table_rows], rfxbuilder->field_delim, 2);
1257  entry = rfxbuilder->entry[rfxbuilder->table_rows] = lives_entry_new();
1258  lives_entry_set_text(LIVES_ENTRY(entry), array[0]);
1259  lives_strfreev(array);
1260  }
1261 
1262  lives_entry_set_editable(LIVES_ENTRY(entry), FALSE);
1263 
1264  ebox = lives_event_box_new();
1265  lives_widget_set_events(ebox, LIVES_BUTTON_PRESS_MASK);
1266  lives_container_add(LIVES_CONTAINER(ebox), entry);
1267 
1268  lives_table_resize(LIVES_TABLE(rfxbuilder->table), ++rfxbuilder->table_rows, 2);
1269  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox, 0, 1, rfxbuilder->table_rows - 1,
1270  rfxbuilder->table_rows,
1271  (LiVESAttachOptions)(LIVES_FILL),
1272  (LiVESAttachOptions)(0), 0, 0);
1273 
1274  entry2 = rfxbuilder->entry2[rfxbuilder->table_rows - 1] = lives_entry_new();
1275 
1276  if (button) {
1277  if (!strcmp(lives_entry_get_text(LIVES_ENTRY(entry)), "layout")) {
1278  lives_entry_set_text(LIVES_ENTRY(entry2), lives_entry_get_text(LIVES_ENTRY(rfxbuilder->paramw_rest_entry)));
1279  } else {
1280  // TODO - use lives_rfx_special_t->has_subtype,name,num_params
1281  ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->paramw_sp_combo));
1282  if (!strcmp(ctext, "framedraw")) {
1283  const char *ctext2 = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->paramw_spsub_combo));
1284  lives_entry_set_text(LIVES_ENTRY(entry2), (tmpx = lives_strdup_printf("%s%s%s%s%s",
1285  ctext, rfxbuilder->field_delim, ctext2,
1286  rfxbuilder->field_delim,
1287  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->paramw_rest_entry)))));
1288  } else {
1289  lives_entry_set_text(LIVES_ENTRY(entry2), (tmpx = lives_strdup_printf("%s%s%s", ctext, rfxbuilder->field_delim,
1290  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->paramw_rest_entry)))));
1291  }
1292  lives_free(tmpx);
1293  }
1294  } else {
1295  char **array = lives_strsplit(rfxbuilder->paramw_hints[rfxbuilder->table_rows - 1], rfxbuilder->field_delim, 2);
1296  lives_entry_set_text(LIVES_ENTRY(entry2), array[1]);
1297  lives_strfreev(array);
1298  }
1299 
1300  lives_entry_set_editable(LIVES_ENTRY(entry2), FALSE);
1301 
1302  ebox2 = lives_event_box_new();
1303  lives_widget_set_events(ebox2, LIVES_BUTTON_PRESS_MASK);
1304  lives_container_add(LIVES_CONTAINER(ebox2), entry2);
1305 
1306  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox2, 1, 2, rfxbuilder->table_rows - 1,
1307  rfxbuilder->table_rows,
1308  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
1309  (LiVESAttachOptions)(0), 0, 0);
1310 
1311  if (param_window_dialog) lives_widget_destroy(param_window_dialog);
1312  if (!button) goto add_row_done;
1313 
1314  lives_widget_queue_resize(lives_widget_get_parent(LIVES_WIDGET(rfxbuilder->table)));
1315  lives_widget_queue_resize(LIVES_WIDGET(rfxbuilder->table));
1316  break;
1317 
1319  entry = rfxbuilder->entry[rfxbuilder->table_rows] = lives_entry_new();
1320 
1321  if (button) {
1322  trigger_dialog = make_trigger_dialog(-1, rfxbuilder);
1323  if (lives_dialog_run(LIVES_DIALOG(trigger_dialog)) == LIVES_RESPONSE_CANCEL) {
1324  return;
1325  }
1326  lives_entry_set_text(LIVES_ENTRY(entry), lives_entry_get_text(LIVES_ENTRY(rfxbuilder->trigger_when_entry)));
1327  rfxbuilder->num_triggers++;
1328  } else {
1329  char *tmpx2 = NULL;
1330  lives_entry_set_text(LIVES_ENTRY(entry), rfxbuilder->triggers[rfxbuilder->table_rows].when ?
1331  (tmpx2 = lives_strdup_printf("%d", rfxbuilder->triggers[rfxbuilder->table_rows].when - 1)) : "init");
1332  if (tmpx2) lives_free(tmpx2);
1333  }
1334 
1335  lives_entry_set_editable(LIVES_ENTRY(entry), FALSE);
1336 
1337  ebox = lives_event_box_new();
1338  lives_widget_set_events(ebox, LIVES_BUTTON_PRESS_MASK);
1339  lives_container_add(LIVES_CONTAINER(ebox), entry);
1340 
1341  lives_table_resize(LIVES_TABLE(rfxbuilder->table), ++rfxbuilder->table_rows, 1);
1342  lives_table_attach(LIVES_TABLE(rfxbuilder->table), ebox, 0, 1, rfxbuilder->table_rows - 1,
1343  rfxbuilder->table_rows,
1344  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
1345  (LiVESAttachOptions)(0), 0, 0);
1346 
1347  if (!button) {
1348  if (trigger_dialog) lives_widget_destroy(trigger_dialog);
1349  goto add_row_done;
1350  }
1351 
1352  if (rfxbuilder->num_triggers > rfxbuilder->num_params) {
1354  }
1355 
1356  rfxbuilder->copy_triggers[rfxbuilder->table_rows - 1].code = lives_text_view_get_text(LIVES_TEXT_VIEW(
1357  rfxbuilder->code_textview));
1358 
1359  rfxbuilder->copy_triggers[rfxbuilder->table_rows - 1].when = atoi(lives_entry_get_text(LIVES_ENTRY(
1360  rfxbuilder->trigger_when_entry))) + 1;
1361  if (!strcmp(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->trigger_when_entry)), "init"))
1362  rfxbuilder->copy_triggers[rfxbuilder->table_rows - 1].when = 0;
1363 
1364  if (!rfxbuilder->copy_triggers[rfxbuilder->table_rows - 1].when) {
1365  rfxbuilder->has_init_trigger = TRUE;
1366  } else {
1367  rfxbuilder->params[rfxbuilder->copy_triggers[rfxbuilder->table_rows - 1].when - 1].onchange = TRUE;
1368  }
1369 
1370  if (trigger_dialog) lives_widget_destroy(trigger_dialog);
1371  lives_widget_queue_resize(lives_widget_get_parent(LIVES_WIDGET(rfxbuilder->table)));
1372  lives_widget_queue_resize(LIVES_WIDGET(rfxbuilder->table));
1373 
1374  break;
1375  default:
1376  return;
1377  }
1378 
1379 add_row_done:
1380 
1381  lives_widget_show_all(rfxbuilder->table);
1382 
1383  lives_event_box_set_above_child(LIVES_EVENT_BOX(ebox), TRUE);
1384 
1385  lives_signal_sync_connect(LIVES_GUI_OBJECT(ebox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
1386  LIVES_GUI_CALLBACK(on_entry_click), (livespointer)rfxbuilder);
1387 
1388  if (palette->style & STYLE_1) {
1389  if (palette->style & STYLE_3) {
1390  lives_widget_set_bg_color(entry, LIVES_WIDGET_STATE_INSENSITIVE, &palette->menu_and_bars);
1391  lives_widget_set_fg_color(entry, LIVES_WIDGET_STATE_INSENSITIVE, &palette->menu_and_bars_fore);
1392  } else {
1393  lives_widget_set_bg_color(entry, LIVES_WIDGET_STATE_INSENSITIVE, &palette->normal_back);
1394  lives_widget_set_fg_color(entry, LIVES_WIDGET_STATE_INSENSITIVE, &palette->normal_fore);
1395  }
1396  }
1397 
1398  if (entry2) {
1399  lives_event_box_set_above_child(LIVES_EVENT_BOX(ebox2), TRUE);
1400 
1401  lives_signal_sync_connect(LIVES_GUI_OBJECT(ebox2), LIVES_WIDGET_BUTTON_PRESS_EVENT,
1402  LIVES_GUI_CALLBACK(on_entry_click), (livespointer)rfxbuilder);
1403 
1404  if (palette->style & STYLE_1) {
1405  if (palette->style & STYLE_3) {
1406  lives_widget_set_bg_color(entry2, LIVES_WIDGET_STATE_INSENSITIVE, &palette->menu_and_bars);
1407  lives_widget_set_fg_color(entry2, LIVES_WIDGET_STATE_INSENSITIVE, &palette->menu_and_bars_fore);
1408  } else {
1409  lives_widget_set_bg_color(entry2, LIVES_WIDGET_STATE_INSENSITIVE, &palette->normal_back);
1410  lives_widget_set_fg_color(entry2, LIVES_WIDGET_STATE_INSENSITIVE, &palette->normal_fore);
1411  }
1412  }
1413  }
1414 
1415  if (entry3) {
1416  lives_event_box_set_above_child(LIVES_EVENT_BOX(ebox3), TRUE);
1417 
1418  lives_signal_sync_connect(LIVES_GUI_OBJECT(ebox3), LIVES_WIDGET_BUTTON_PRESS_EVENT,
1419  LIVES_GUI_CALLBACK(on_entry_click), (livespointer)rfxbuilder);
1420 
1421  if (palette->style & STYLE_1) {
1422  if (palette->style & STYLE_3) {
1423  lives_widget_set_bg_color(entry3, LIVES_WIDGET_STATE_INSENSITIVE, &palette->menu_and_bars);
1424  lives_widget_set_fg_color(entry3, LIVES_WIDGET_STATE_INSENSITIVE, &palette->menu_and_bars_fore);
1425  } else {
1426  lives_widget_set_bg_color(entry3, LIVES_WIDGET_STATE_INSENSITIVE, &palette->normal_back);
1427  lives_widget_set_fg_color(entry3, LIVES_WIDGET_STATE_INSENSITIVE, &palette->normal_fore);
1428  }
1429  }
1430  }
1431 
1432  if (button) {
1433  table_select_row(rfxbuilder, rfxbuilder->table_rows - 1);
1434 
1435  if (rfxbuilder->table_type == RFX_TABLE_TYPE_REQUIREMENTS) {
1436  on_table_edit_row(NULL, user_data);
1437  }
1438  }
1439 }
1440 
1441 
1442 static void param_set_from_dialog(lives_param_t *copy_param, rfx_build_window_t *rfxbuilder) {
1443  // set parameter values from param_dialog
1444  // this is called after adding a new copy_param or editing an existing one
1445  const char *ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_type_combo));
1446 
1447  copy_param->name = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->param_name_entry)));
1448  copy_param->label = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->param_label_entry)));
1449 
1450  if (!strcmp(ctext, "num")) {
1451  copy_param->type = LIVES_PARAM_NUM;
1452  } else if (!strcmp(ctext, "bool")) {
1453  copy_param->type = LIVES_PARAM_BOOL;
1454  } else if (!strcmp(ctext, "colRGB24")) {
1455  copy_param->type = LIVES_PARAM_COLRGB24;
1456  } else if (!strcmp(ctext, "string")) {
1457  copy_param->type = LIVES_PARAM_STRING;
1458  } else if (!strcmp(ctext, "string_list")) {
1459  copy_param->type = LIVES_PARAM_STRING_LIST;
1460  }
1461 
1462  copy_param->dp = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_dp));
1463  copy_param->group = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_group));
1464  copy_param->onchange = FALSE; // no trigger assigned yet
1465 
1466  // TODO - check
1467  if (copy_param->type != LIVES_PARAM_STRING && copy_param->def) lives_free(copy_param->def);
1468  if (copy_param->type != LIVES_PARAM_STRING_LIST && copy_param->list) lives_list_free(copy_param->list);
1469 
1470  switch (copy_param->type) {
1471  case LIVES_PARAM_NUM:
1472  copy_param->min = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min));
1473  copy_param->max = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max));
1474  copy_param->step_size = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step));
1475  copy_param->wrap = lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(rfxbuilder->param_wrap_checkbutton));
1476  if (!copy_param->dp) {
1477  copy_param->def = lives_malloc(sizint);
1478  set_int_param(copy_param->def, lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)));
1479  } else {
1480  copy_param->def = lives_malloc(sizdbl);
1481  set_double_param(copy_param->def, lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)));
1482  }
1483  break;
1484  case LIVES_PARAM_BOOL:
1485  copy_param->def = lives_malloc(sizint);
1486  set_bool_param(copy_param->def, lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)));
1487  copy_param->dp = 0;
1488  break;
1489  case LIVES_PARAM_STRING:
1490  copy_param->max = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max));
1491  copy_param->dp = 0;
1492  break;
1494  copy_param->dp = 0;
1495  copy_param->def = lives_malloc(sizdbl);
1496  ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_def_combo));
1497  set_int_param(copy_param->def, lives_list_strcmp_index(copy_param->list, ctext, TRUE));
1498  break;
1499  case LIVES_PARAM_COLRGB24:
1500  copy_param->def = lives_malloc(3 * sizint);
1501  set_colRGB24_param(copy_param->def, lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)),
1502  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)),
1503  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)));
1504  copy_param->dp = 0;
1505  break;
1506  default:
1507  break;
1508  }
1509 }
1510 
1511 
1512 static void on_table_edit_row(LiVESButton * button, livespointer user_data) {
1513  LiVESWidget *param_dialog;
1514  LiVESWidget *paramw_dialog;
1515  LiVESWidget *trigger_dialog;
1516 
1517  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
1518  lives_param_t *param;
1519 
1520  int i;
1521  int found = -1;
1522  boolean param_ok = FALSE;
1523 
1524  char *tmpx;
1525  const char *ctext;
1526 
1527  for (i = 0; i < rfxbuilder->table_rows && found == -1; i++) {
1528  if (lives_widget_is_sensitive(rfxbuilder->entry[i])) {
1529  found = i;
1530  break;
1531  }
1532  }
1533  if (found == -1) return;
1534 
1535  switch (rfxbuilder->table_type) {
1537  for (i = 0; i < rfxbuilder->table_rows; i++) {
1538  if (found == i) {
1539  lives_entry_set_editable(LIVES_ENTRY(rfxbuilder->entry[i]), TRUE);
1541  lives_widget_grab_focus(rfxbuilder->entry[i]);
1542  } else {
1543  lives_entry_set_editable(LIVES_ENTRY(rfxbuilder->entry[i]), FALSE);
1544  }
1545  }
1546  break;
1547 
1548  case RFX_TABLE_TYPE_PARAMS:
1549  param_dialog = make_param_dialog(found, rfxbuilder);
1550  do {
1551  if (lives_dialog_run(LIVES_DIALOG(param_dialog)) == LIVES_RESPONSE_CANCEL) {
1552  return;
1553  }
1554  param_ok = perform_param_checks(rfxbuilder, found, rfxbuilder->num_params);
1555  } while (!param_ok);
1556 
1557  param_set_from_dialog((param = &rfxbuilder->copy_params[found]), rfxbuilder);
1558  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry2[found]), param->name);
1559  switch (param->type) {
1560  case LIVES_PARAM_NUM:
1561  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry3[found]), (tmpx = lives_strdup_printf("num%d", param->dp)));
1562  lives_free(tmpx);
1563  break;
1564  case LIVES_PARAM_BOOL:
1565  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry3[found]), "bool");
1566  break;
1567  case LIVES_PARAM_COLRGB24:
1568  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry3[found]), "colRGB24");
1569  break;
1570  case LIVES_PARAM_STRING:
1571  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry3[found]), "string");
1572  break;
1574  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry3[found]), "string_list");
1575  break;
1576  default:
1577  break;
1578  }
1579  lives_widget_destroy(param_dialog);
1580  break;
1581 
1583  paramw_dialog = make_param_window_dialog(found, rfxbuilder);
1584  if (lives_dialog_run(LIVES_DIALOG(paramw_dialog)) == LIVES_RESPONSE_CANCEL) {
1585  return;
1586  }
1587  ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->paramw_kw_combo));
1588  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry[found]), ctext);
1589  if (!strcmp(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[found])), "layout")) {
1590  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry2[found]),
1591  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->paramw_rest_entry)));
1592  } else {
1593  // TODO - use lives_rfx_special_t->has_subtype,name,num_params
1594  ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->paramw_sp_combo));
1595  if (!strcmp(ctext, "framedraw")) {
1596  const char *ctext2 = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->paramw_spsub_combo));
1597  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry2[found]),
1598  (tmpx = lives_strdup_printf("%s%s%s%s%s", ctext, rfxbuilder->field_delim, ctext2,
1599  rfxbuilder->field_delim,
1600  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->paramw_rest_entry)))));
1601  } else {
1602  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry2[found]),
1603  (tmpx = lives_strdup_printf("%s%s%s", ctext, rfxbuilder->field_delim, lives_entry_get_text
1604  (LIVES_ENTRY(rfxbuilder->paramw_rest_entry)))));
1605  }
1606  lives_free(tmpx);
1607  }
1608  lives_widget_destroy(paramw_dialog);
1609  break;
1610 
1612  trigger_dialog = make_trigger_dialog(found, rfxbuilder);
1613  if (lives_dialog_run(LIVES_DIALOG(trigger_dialog)) == LIVES_RESPONSE_CANCEL) {
1614  return;
1615  }
1616 
1617  lives_free(rfxbuilder->copy_triggers[found].code);
1618  rfxbuilder->copy_triggers[found].code = lives_text_view_get_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview));
1619 
1620  lives_widget_destroy(trigger_dialog);
1621  break;
1622  }
1623 }
1624 
1625 
1626 static void on_table_swap_row(LiVESButton * button, livespointer user_data) {
1627  char *entry_text;
1628  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
1629  int found = -1;
1630 
1631  for (register int i = 0; i < rfxbuilder->table_rows && found == -1; i++) {
1632  if (!(lives_widget_get_state(rfxbuilder->entry[i])&LIVES_WIDGET_STATE_INSENSITIVE)) {
1633  found = i;
1634  break;
1635  }
1636  }
1637 
1638  if (found == -1) if ((found = rfxbuilder->table_swap_row1) == -1) return;
1639 
1640  switch (rfxbuilder->table_type) {
1642  if (button == LIVES_BUTTON(rfxbuilder->move_up_button)) {
1643  rfxbuilder->table_swap_row2 = found - 1;
1644  } else if (button == LIVES_BUTTON(rfxbuilder->move_down_button)) {
1645  rfxbuilder->table_swap_row2 = found + 1;
1646  }
1647  if (rfxbuilder->table_swap_row2 < 0 || rfxbuilder->table_swap_row2 >= rfxbuilder->table_rows) return;
1648 
1649  entry_text = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[found])));
1650  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry[found]),
1651  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[rfxbuilder->table_swap_row2])));
1652  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry[rfxbuilder->table_swap_row2]), entry_text);
1653  lives_free(entry_text);
1654 
1655  entry_text = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry2[found])));
1656  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry2[found]),
1657  lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry2[rfxbuilder->table_swap_row2])));
1658  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->entry2[rfxbuilder->table_swap_row2]), entry_text);
1659  lives_free(entry_text);
1660 
1661  break;
1662  default:
1663  break;
1664  }
1665  rfxbuilder->table_swap_row1 = rfxbuilder->table_swap_row2;
1666  table_select_row(rfxbuilder, rfxbuilder->table_swap_row1);
1667 }
1668 
1669 
1670 static void on_table_delete_row(LiVESButton * button, livespointer user_data) {
1671  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
1672 
1673  LiVESWidget *ebox;
1674 
1675 #if !LIVES_TABLE_IS_GRID
1676  LiVESWidget *ebox2 = NULL, *ebox3 = NULL, *ebox4 = NULL;
1677 #else
1678  LiVESWidget *entry = NULL, *entry2;
1679 #endif
1680 
1681  int move = 0;
1682  boolean triggers_adjusted = FALSE;
1683 
1684  register int i;
1685 
1686  switch (rfxbuilder->table_type) {
1688  for (i = 0; i < rfxbuilder->table_rows; i++) {
1689  if (move > 0) {
1690 #if !LIVES_TABLE_IS_GRID
1691  if (i < rfxbuilder->table_rows - 1) ebox2 = lives_widget_get_parent(rfxbuilder->entry[i]);
1692  lives_widget_reparent(rfxbuilder->entry[i], ebox);
1693  ebox = ebox2;
1694 #endif
1695  rfxbuilder->entry[i - 1] = rfxbuilder->entry[i];
1696  } else if (!(lives_widget_get_state(rfxbuilder->entry[i])&LIVES_WIDGET_STATE_INSENSITIVE)) {
1697 #if LIVES_TABLE_IS_GRID
1698  lives_grid_remove_row(LIVES_GRID(rfxbuilder->table), i);
1699 #else
1700  ebox = lives_widget_get_parent(rfxbuilder->entry[i]);
1701  if (rfxbuilder->table_rows > 1) {
1702  lives_table_resize(LIVES_TABLE(rfxbuilder->table), rfxbuilder->table_rows - 1, 1);
1703  }
1704  lives_widget_destroy(rfxbuilder->entry[i]);
1705 #endif
1706  move = i + 1;
1707  }
1708  }
1709  if (move == 0) return;
1710  rfxbuilder->table_rows--;
1711  rfxbuilder->num_reqs--;
1712  break;
1713 
1714  case RFX_TABLE_TYPE_PARAMS:
1715  for (i = 0; i < rfxbuilder->table_rows; i++) {
1716  if (move > 0) {
1717  // note - parameters become renumbered here
1718 
1719 #if !LIVES_TABLE_IS_GRID
1720  // move everything up except p%d
1721  if (i < rfxbuilder->table_rows - 1) {
1722  ebox3 = lives_widget_get_parent(rfxbuilder->entry2[i]);
1723  ebox4 = lives_widget_get_parent(rfxbuilder->entry3[i]);
1724  }
1725  lives_widget_reparent(rfxbuilder->entry2[i], ebox);
1726  lives_widget_reparent(rfxbuilder->entry3[i], ebox2);
1727  ebox = ebox3;
1728  ebox2 = ebox4;
1729 #else
1730  // move p%d up so when we remove the row the numbering is ok
1731  entry2 = rfxbuilder->entry[i];
1732  ebox = lives_widget_get_parent(rfxbuilder->entry[i]);
1733  lives_widget_object_ref(entry2);
1734  lives_widget_unparent(entry2);
1735  lives_container_add(LIVES_CONTAINER(ebox), entry);
1737  entry = entry2;
1738 #endif
1739 
1740  rfxbuilder->entry2[i - 1] = rfxbuilder->entry2[i];
1741  rfxbuilder->entry3[i - 1] = rfxbuilder->entry3[i];
1742  param_copy(&rfxbuilder->copy_params[i - 1], &rfxbuilder->copy_params[i], FALSE);
1743  lives_free(rfxbuilder->copy_params[i].name);
1744  lives_free(rfxbuilder->copy_params[i].label);
1745  lives_free(rfxbuilder->copy_params[i].def);
1746 
1747  } else if (!(lives_widget_get_state(rfxbuilder->entry[i])&LIVES_WIDGET_STATE_INSENSITIVE)) {
1748  if (rfxbuilder->copy_params[i].onchange) {
1749  do_error_dialog(_("\n\nCannot remove this parameter as it has a trigger.\nPlease remove the trigger first.\n\n"));
1750  return;
1751  }
1752 
1753 #if LIVES_TABLE_IS_GRID
1754  entry = rfxbuilder->entry[i];
1755  lives_widget_object_ref(entry);
1756  lives_widget_unparent(entry);
1757  lives_grid_remove_row(LIVES_GRID(rfxbuilder->table), i);
1758 #else
1759  ebox = lives_widget_get_parent(rfxbuilder->entry2[i]);
1760  ebox2 = lives_widget_get_parent(rfxbuilder->entry3[i]);
1761 
1762  lives_widget_destroy(rfxbuilder->entry[rfxbuilder->table_rows - 1]);
1763  lives_widget_destroy(rfxbuilder->entry2[i]);
1764  lives_widget_destroy(rfxbuilder->entry3[i]);
1765 
1766  if (rfxbuilder->table_rows > 1) {
1767  lives_table_resize(LIVES_TABLE(rfxbuilder->table), rfxbuilder->table_rows - 1, 3);
1768  }
1769 #endif
1770  lives_free(rfxbuilder->copy_params[i].name);
1771  lives_free(rfxbuilder->copy_params[i].label);
1772  lives_free(rfxbuilder->copy_params[i].def);
1773 
1774  move = i + 1;
1775  }
1776  }
1777 
1778 #if LIVES_TABLE_IS_GRID
1779  if (entry) lives_widget_destroy(entry);
1780 #endif
1781 
1782  if (move == 0) return;
1783  rfxbuilder->table_rows--;
1784  rfxbuilder->num_params--;
1785  for (i = 0; i < rfxbuilder->num_triggers; i++) {
1786  if (rfxbuilder->triggers[i].when > move) {
1787  rfxbuilder->params[rfxbuilder->triggers[i].when - 1].onchange = FALSE;
1788  rfxbuilder->params[--rfxbuilder->triggers[i].when - 1].onchange = TRUE;
1789  }
1790  triggers_adjusted = TRUE;
1791  }
1792  if (triggers_adjusted) {
1793  do_error_dialog(_("\n\nSome triggers were adjusted.\nPlease check the trigger code.\n"));
1794  }
1795  break;
1796 
1798  for (i = 0; i < rfxbuilder->table_rows; i++) {
1799  if (move > 0) {
1800 #if !LIVES_TABLE_IS_GRID
1801  if (i < rfxbuilder->table_rows - 1) {
1802  ebox3 = lives_widget_get_parent(rfxbuilder->entry[i]);
1803  ebox4 = lives_widget_get_parent(rfxbuilder->entry2[i]);
1804  }
1805  lives_widget_reparent(rfxbuilder->entry[i], ebox);
1806  lives_widget_reparent(rfxbuilder->entry2[i], ebox2);
1807  ebox = ebox3;
1808  ebox2 = ebox4;
1809 #endif
1810 
1811  rfxbuilder->entry[i - 1] = rfxbuilder->entry[i];
1812  rfxbuilder->entry2[i - 1] = rfxbuilder->entry2[i];
1813  } else if (!(lives_widget_get_state(rfxbuilder->entry[i])&LIVES_WIDGET_STATE_INSENSITIVE)) {
1814 #if LIVES_TABLE_IS_GRID
1815  lives_grid_remove_row(LIVES_GRID(rfxbuilder->table), i);
1816 #else
1817  ebox = lives_widget_get_parent(rfxbuilder->entry[i]);
1818  ebox2 = lives_widget_get_parent(rfxbuilder->entry2[i]);
1819 
1820  lives_widget_destroy(rfxbuilder->entry[i]);
1821  lives_widget_destroy(rfxbuilder->entry2[i]);
1822  if (rfxbuilder->table_rows > 1) {
1823  lives_table_resize(LIVES_TABLE(rfxbuilder->table), rfxbuilder->table_rows - 1, 1);
1824  }
1825 #endif
1826  move = i + 1;
1827  }
1828  }
1829  if (!move) return;
1830  rfxbuilder->table_rows--;
1831  rfxbuilder->num_paramw_hints--;
1832  break;
1833 
1835  for (i = 0; i < rfxbuilder->table_rows; i++) {
1836  if (move > 0) {
1837 #if !LIVES_TABLE_IS_GRID
1838  if (i < rfxbuilder->table_rows - 1) ebox2 = lives_widget_get_parent(rfxbuilder->entry[i]);
1839  lives_widget_reparent(rfxbuilder->entry[i], ebox);
1840  ebox = ebox2;
1841 #endif
1842 
1843  rfxbuilder->entry[i - 1] = rfxbuilder->entry[i];
1844  rfxbuilder->copy_triggers[i - 1].when = rfxbuilder->copy_triggers[i].when;
1845  rfxbuilder->copy_triggers[i - 1].code = lives_strdup(rfxbuilder->copy_triggers[i].code);
1846  lives_free(rfxbuilder->copy_triggers[i].code);
1847  } else if (!(lives_widget_get_state(rfxbuilder->entry[i])&LIVES_WIDGET_STATE_INSENSITIVE)) {
1848  int when = atoi(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[i]))) + 1;
1849 
1850  if (!strcmp(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[i])), "init")) rfxbuilder->has_init_trigger = FALSE;
1851  else rfxbuilder->params[when - 1].onchange = FALSE;
1852 
1853  lives_free(rfxbuilder->copy_triggers[i].code);
1854 
1855 #if LIVES_TABLE_IS_GRID
1856  lives_grid_remove_row(LIVES_GRID(rfxbuilder->table), i);
1857 #else
1858  ebox = lives_widget_get_parent(rfxbuilder->entry[i]);
1859  if (rfxbuilder->table_rows > 1) {
1860  lives_table_resize(LIVES_TABLE(rfxbuilder->table), rfxbuilder->table_rows - 1, 1);
1861  }
1862  lives_widget_destroy(rfxbuilder->entry[i]);
1863 #endif
1864  move = i + 1;
1865  }
1866  }
1867  if (!move) return;
1868  rfxbuilder->table_rows--;
1869  rfxbuilder->num_triggers--;
1870 
1871  if (rfxbuilder->table_rows <= rfxbuilder->num_params) {
1873  }
1874 
1875  break;
1876  default:
1877  return;
1878  }
1879 
1880  if (rfxbuilder->table_rows == 0) {
1883  if (rfxbuilder->move_up_button) lives_widget_set_sensitive(rfxbuilder->move_up_button, FALSE);
1884  if (rfxbuilder->move_down_button) lives_widget_set_sensitive(rfxbuilder->move_down_button, FALSE);
1885  } else {
1886  if (move >= rfxbuilder->table_rows) move = rfxbuilder->table_rows - 1;
1887  table_select_row(rfxbuilder, move);
1888  }
1889 }
1890 
1891 
1892 LiVESWidget *make_param_dialog(int pnum, rfx_build_window_t *rfxbuilder) {
1893  LiVESWidget *dialog;
1894  LiVESWidget *dialog_vbox;
1895 
1896  LiVESAccelGroup *accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
1897 
1898  LiVESList *typelist = NULL;
1899 
1900  lives_colRGB48_t rgb;
1901 
1902  char *tmp, *tmp2, *title;
1903 
1904  if (pnum < 0) {
1905  title = (_("New RFX Parameter"));
1906  } else {
1907  title = (_("Edit RFX Parameter"));
1908  }
1909 
1910  dialog = lives_standard_dialog_new(title, TRUE, -1, -1);
1911  lives_free(title);
1912 
1913  lives_window_add_accel_group(LIVES_WINDOW(dialog), accel_group);
1914 
1915  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
1916 
1917  // name
1918 
1919  rfxbuilder->param_name_entry = lives_standard_entry_new((tmp = (_("_Name: "))),
1920  pnum >= 0 ? rfxbuilder->copy_params[pnum].name : NULL,
1921  60.*widget_opts.scale, -1, LIVES_BOX(dialog_vbox),
1922  (tmp2 = lives_strdup((_("Name of the parameter, must be unique in the plugin.")))));
1923 
1924  if (pnum < 0) lives_widget_grab_focus(rfxbuilder->param_name_entry);
1925 
1926  lives_free(tmp);
1927  lives_free(tmp2);
1928 
1929  // label
1930 
1931  rfxbuilder->param_label_entry = lives_standard_entry_new((tmp = (_("_Label: "))),
1932  pnum >= 0 ? rfxbuilder->copy_params[pnum].label : NULL,
1933  60.*widget_opts.scale, -1, LIVES_BOX(dialog_vbox),
1934  (tmp2 = (_("Label to be shown by the parameter. "
1935  "An underscore represents mnemonic accelerator."))));
1936  lives_free(tmp);
1937  lives_free(tmp2);
1938 
1939  // type
1940 
1941  typelist = lives_list_append(typelist, (livespointer)"num");
1942  typelist = lives_list_append(typelist, (livespointer)"bool");
1943  typelist = lives_list_append(typelist, (livespointer)"string");
1944  typelist = lives_list_append(typelist, (livespointer)"colRGB24");
1945  typelist = lives_list_append(typelist, (livespointer)"string_list");
1946 
1947  rfxbuilder->param_type_combo = lives_standard_combo_new((tmp = (_("_Type: "))), typelist,
1948  LIVES_BOX(dialog_vbox), (tmp2 = (_("Parameter type (select from list)."))));
1949  lives_free(tmp);
1950  lives_free(tmp2);
1951  lives_list_free(typelist);
1952 
1953  rfxbuilder->edit_param = pnum;
1954 
1955  if (pnum >= 0) {
1956  switch (rfxbuilder->copy_params[pnum].type) {
1957  case LIVES_PARAM_NUM:
1958  lives_combo_set_active_index(LIVES_COMBO(rfxbuilder->param_type_combo), 0); break;
1959  case LIVES_PARAM_BOOL:
1960  lives_combo_set_active_index(LIVES_COMBO(rfxbuilder->param_type_combo), 1); break;
1961  case LIVES_PARAM_STRING:
1962  lives_combo_set_active_index(LIVES_COMBO(rfxbuilder->param_type_combo), 2); break;
1963  case LIVES_PARAM_COLRGB24:
1964  lives_combo_set_active_index(LIVES_COMBO(rfxbuilder->param_type_combo), 3); break;
1966  lives_combo_set_active_index(LIVES_COMBO(rfxbuilder->param_type_combo), 4); break;
1967  default: break;
1968  }
1969  } else rfxbuilder->edit_param = rfxbuilder->num_params;
1970 
1971  // dp
1972 
1973  rfxbuilder->spinbutton_param_dp = lives_standard_spin_button_new(_("Decimal _places: "),
1974  pnum >= 0 ? rfxbuilder->copy_params[pnum].dp : 0., 0., 16., 1., 1., 0, LIVES_BOX(dialog_vbox), NULL);
1975  rfxbuilder->param_dp_label = widget_opts.last_label;
1976 
1977  add_hsep_to_box(LIVES_BOX(dialog_vbox));
1978 
1979  // default val
1980 
1981  rfxbuilder->spinbutton_param_def = lives_standard_spin_button_new(_("_Default value: "), 0., -LIVES_MAXINT, LIVES_MAXINT, 1.,
1982  1., 0, LIVES_BOX(dialog_vbox), NULL);
1983  rfxbuilder->param_def_label = widget_opts.last_label;
1984 
1985  // extra bits for string/string_list
1986 
1987  rfxbuilder->param_strdef_hbox = lives_hbox_new(FALSE, 0);
1988  lives_box_pack_start(LIVES_BOX(dialog_vbox), rfxbuilder->param_strdef_hbox, TRUE, TRUE, widget_opts.packing_height);
1989 
1991 
1992  lives_box_pack_start(LIVES_BOX(rfxbuilder->param_strdef_hbox), rfxbuilder->param_strdef_button, TRUE, TRUE,
1994 
1995  rfxbuilder->param_strlist_hbox = lives_hbox_new(FALSE, 0);
1996  lives_box_pack_start(LIVES_BOX(dialog_vbox), rfxbuilder->param_strlist_hbox, FALSE, FALSE, widget_opts.packing_width);
1997 
1998  rfxbuilder->param_def_combo = lives_standard_combo_new(_("_Default: "), NULL, LIVES_BOX(rfxbuilder->param_strlist_hbox), NULL);
1999 
2000  lives_label_set_mnemonic_widget(LIVES_LABEL(rfxbuilder->param_def_label), rfxbuilder->param_def_combo);
2001 
2002  if (pnum >= 0) {
2003  switch (rfxbuilder->copy_params[pnum].type) {
2004  case LIVES_PARAM_NUM:
2005  if (!rfxbuilder->copy_params[pnum].dp) {
2006  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2007  (double)get_int_param(rfxbuilder->copy_params[pnum].def));
2008  } else {
2009  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2010  get_double_param(rfxbuilder->copy_params[pnum].def));
2011  }
2012  break;
2013  case LIVES_PARAM_BOOL:
2014  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2015  (double)get_bool_param(rfxbuilder->copy_params[pnum].def));
2016  break;
2017  case LIVES_PARAM_COLRGB24:
2018  get_colRGB24_param(rfxbuilder->copy_params[pnum].def, &rgb);
2019  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), (double)rgb.red);
2020  break;
2021  default:
2022  break;
2023  }
2024  }
2025 
2026  // group
2027 
2028  rfxbuilder->hbox_bg = lives_hbox_new(FALSE, 0);
2029  lives_box_pack_start(LIVES_BOX(dialog_vbox), rfxbuilder->hbox_bg, FALSE, FALSE, widget_opts.packing_height);
2030 
2031  rfxbuilder->spinbutton_param_group = lives_standard_spin_button_new((tmp = (_("Button _Group: "))), 0., 0., 16., 1.,
2032  1., 0, LIVES_BOX(rfxbuilder->hbox_bg),
2033  (tmp2 = (_("A non-zero value can be used to group radio buttons."))));
2034 
2035  if (pnum >= 0) {
2036  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_group),
2037  (double)rfxbuilder->copy_params[pnum].group);
2038  }
2039 
2040  // min
2041 
2042  rfxbuilder->spinbutton_param_min = lives_standard_spin_button_new(_("_Minimum value: "), 0., -LIVES_MAXINT, LIVES_MAXINT, 1.,
2043  1., 0, LIVES_BOX(dialog_vbox), NULL);
2044  rfxbuilder->param_min_label = widget_opts.last_label;
2045 
2046  // max
2047 
2048  rfxbuilder->spinbutton_param_max = lives_standard_spin_button_new(_("Ma_ximum value: "), RFX_DEF_NUM_MAX, -LIVES_MAXINT,
2049  LIVES_MAXINT, 1., 1., 0, LIVES_BOX(dialog_vbox), NULL);
2050  rfxbuilder->param_max_label = widget_opts.last_label;
2051 
2052  // step size
2053 
2054  rfxbuilder->spinbutton_param_step = lives_standard_spin_button_new((tmp = (_(" _Step size: "))), 1., 1.,
2055  LIVES_MAXINT, 1., 1., 0, LIVES_BOX(dialog_vbox),
2056  (tmp2 = (_("How much the parameter is adjusted when the spinbutton arrows are pressed."))));
2057  rfxbuilder->param_step_label = widget_opts.last_label;
2058  lives_free(tmp);
2059  lives_free(tmp2);
2060 
2061  // wrap
2062 
2063  rfxbuilder->param_wrap_hbox = lives_hbox_new(FALSE, 0);
2064  lives_box_pack_start(LIVES_BOX(dialog_vbox), rfxbuilder->param_wrap_hbox, TRUE, TRUE, widget_opts.packing_height);
2065 
2066  rfxbuilder->param_wrap_checkbutton = lives_standard_check_button_new((tmp = (_("_Wrap value"))), FALSE,
2067  LIVES_BOX(rfxbuilder->param_wrap_hbox),
2068  (tmp2 = (_("Whether the value wraps max->min and min->max."))));
2069 
2070  lives_free(tmp);
2071  lives_free(tmp2);
2072 
2073  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->param_strdef_button), LIVES_WIDGET_CLICKED_SIGNAL,
2074  LIVES_GUI_CALLBACK(on_code_clicked), (livespointer)rfxbuilder);
2075 
2076  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->param_type_combo), LIVES_WIDGET_CHANGED_SIGNAL,
2077  LIVES_GUI_CALLBACK(on_param_type_changed), (livespointer)rfxbuilder);
2078 
2079  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->spinbutton_param_dp), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
2080  LIVES_GUI_CALLBACK(after_param_dp_changed), (livespointer)rfxbuilder);
2081 
2082  rfxbuilder->def_spin_f = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->spinbutton_param_def),
2083  LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
2084  LIVES_GUI_CALLBACK(after_param_def_changed), (livespointer)rfxbuilder);
2085 
2086  rfxbuilder->min_spin_f = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->spinbutton_param_min),
2087  LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
2088  LIVES_GUI_CALLBACK(after_param_min_changed), (livespointer)rfxbuilder);
2089 
2090  rfxbuilder->max_spin_f = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(rfxbuilder->spinbutton_param_max),
2091  LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
2092  LIVES_GUI_CALLBACK(after_param_max_changed), (livespointer)rfxbuilder);
2093 
2094  if (pnum >= 0) {
2095  switch (rfxbuilder->copy_params[pnum].type) {
2096  case LIVES_PARAM_NUM:
2097  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), rfxbuilder->copy_params[pnum].min);
2098  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), rfxbuilder->copy_params[pnum].max);
2099  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step),
2100  rfxbuilder->copy_params[pnum].step_size);
2101  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rfxbuilder->param_wrap_checkbutton),
2102  rfxbuilder->copy_params[pnum].wrap);
2103  break;
2104  case LIVES_PARAM_COLRGB24:
2105  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), (double)rgb.green);
2106  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), (double)rgb.blue);
2107  break;
2108  case LIVES_PARAM_STRING:
2109  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), rfxbuilder->copy_params[pnum].max);
2110  break;
2111  default:
2112  break;
2113  }
2114  }
2115  lives_widget_show_all(dialog);
2116  on_param_type_changed(LIVES_COMBO(rfxbuilder->param_type_combo), (livespointer)rfxbuilder);
2117  after_param_dp_changed(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_dp), (livespointer)rfxbuilder);
2118  return dialog;
2119 }
2120 
2121 
2122 static void after_param_dp_changed(LiVESSpinButton * spinbutton, livespointer user_data) {
2123  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2124  const char *ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_type_combo));
2125  int dp;
2126 
2127  if (strcmp(ctext, "num")) return;
2128 
2129  dp = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
2130 
2131  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), dp);
2132  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), dp);
2133  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), dp);
2134  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step), dp);
2135 
2136  if (dp > 0) {
2137  double max = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max));
2138  double min = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min));
2139  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), -LIVES_MAXFLOAT, LIVES_MAXFLOAT);
2140  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), -LIVES_MAXFLOAT, LIVES_MAXFLOAT);
2141  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), -LIVES_MAXFLOAT, LIVES_MAXFLOAT);
2142  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step), 1. / (double)lives_10pow(dp),
2143  (max - min) > 1. ? (max - min) : 1.);
2144 
2145  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_step), MAXFLOATLEN + dp);
2146  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_def), MAXFLOATLEN + dp);
2147  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_min), MAXFLOATLEN + dp);
2148  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_max), MAXFLOATLEN + dp);
2149  } else {
2150  int max = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max));
2151  int min = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min));
2152  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), -LIVES_MAXINT, LIVES_MAXINT);
2153  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), -LIVES_MAXINT, LIVES_MAXINT);
2154  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), -LIVES_MAXINT, LIVES_MAXINT);
2155  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step), 1, (max - min) > 1 ? (max - min) : 1);
2156 
2157  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_step), MAXINTLEN);
2158  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_def), MAXINTLEN);
2159  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_min), MAXINTLEN);
2160  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_max), MAXINTLEN);
2161  }
2162 }
2163 
2164 
2165 static void after_param_min_changed(LiVESSpinButton * spinbutton, livespointer user_data) {
2166  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2167  int dp;
2168  const char *ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_type_combo));
2169 
2170  if (strcmp(ctext, "num")) return;
2171 
2174 
2175  if ((dp = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_dp))) > 0) {
2176  if (lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)) <
2177  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min))) {
2178  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2179  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)));
2180  }
2181 
2182  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max),
2183  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)), LIVES_MAXFLOAT);
2184  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step),
2185  1. / (double)lives_10pow(dp), lives_spin_button_get_value
2186  (LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)) -
2187  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)));
2188 
2189  } else {
2190  if (lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)) <
2191  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min))) {
2192  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2193  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)));
2194  }
2195 
2196  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max),
2197  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)),
2198  LIVES_MAXINT);
2199  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step), 1,
2200  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)) -
2201  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)));
2202  }
2203 
2206 }
2207 
2208 
2209 static void after_param_max_changed(LiVESSpinButton * spinbutton, livespointer user_data) {
2210  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2211  int dp;
2212  const char *ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_type_combo));
2213 
2214  if (strcmp(ctext, "num")) return;
2215 
2218 
2219  if ((dp = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_dp))) > 0) {
2220  if (lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)) >
2221  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max))) {
2222  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2223  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)));
2224  }
2225 
2226  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), -LIVES_MAXFLOAT,
2227  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)));
2228  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step),
2229  1. / (double)lives_10pow(dp),
2230  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)) -
2231  lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)));
2232  } else {
2233  if (lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def)) >
2234  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max))) {
2235  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def),
2236  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)));
2237  }
2238 
2239  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), -LIVES_MAXINT,
2240  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max)));
2241  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step), 1,
2242  lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max))
2243  - lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min)));
2244  }
2245 
2248 }
2249 
2250 
2251 static void after_param_def_changed(LiVESSpinButton * spinbutton, livespointer user_data) {
2252  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2253  const char *ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_type_combo));
2254 
2255  if (strcmp(ctext, "num")) return;
2256 
2257  if (lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_dp))) {
2258  double dbl_def = lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def));
2259  if (dbl_def < lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min))) {
2260  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), dbl_def);
2261  } else if (dbl_def > lives_spin_button_get_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max))) {
2262  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), dbl_def);
2263  }
2264  } else {
2265  int int_def = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def));
2266  if (int_def < lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min))) {
2267  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), (double)int_def);
2268  } else if (int_def > lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max))) {
2269  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), (double)int_def);
2270  }
2271  }
2272 }
2273 
2274 
2275 static void on_param_type_changed(LiVESCombo * param_type_combo, livespointer user_data) {
2276  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2277  int pnum = rfxbuilder->edit_param;
2278 
2279  const char *ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->param_type_combo));
2280 
2281  lives_widget_show(rfxbuilder->param_min_label);
2282  lives_widget_show(rfxbuilder->param_max_label);
2287  lives_widget_show(rfxbuilder->param_dp_label);
2288  lives_widget_show(rfxbuilder->param_def_label);
2289 
2290  lives_widget_hide(rfxbuilder->param_strdef_hbox);
2292  lives_widget_hide(rfxbuilder->hbox_bg);
2294  lives_widget_hide(rfxbuilder->param_step_label);
2295  lives_widget_hide(rfxbuilder->param_wrap_hbox);
2296 
2297  if (pnum < 0) return;
2298 
2299  if (!strcmp(ctext, "string_list")) {
2300  int defindex;
2301 
2302  if (rfxbuilder->copy_params[pnum].type != LIVES_PARAM_STRING_LIST) {
2303  if (rfxbuilder->copy_params[pnum].def) {
2304  lives_free(rfxbuilder->copy_params[pnum].def);
2305  }
2306  rfxbuilder->copy_params[pnum].def = lives_malloc(sizint);
2307  set_int_param(rfxbuilder->copy_params[pnum].def, 0);
2308  }
2309 
2310  rfxbuilder->copy_params[pnum].type = LIVES_PARAM_STRING_LIST;
2311  defindex = get_int_param(rfxbuilder->copy_params[pnum].def);
2312 
2313  lives_combo_populate(LIVES_COMBO(rfxbuilder->param_def_combo), rfxbuilder->copy_params[pnum].list);
2314 
2315  if (!rfxbuilder->copy_params[pnum].list || defindex > lives_list_length(rfxbuilder->copy_params[pnum].list)) {
2316  set_int_param(rfxbuilder->copy_params[pnum].def, (defindex = 0));
2317  }
2318 
2319  if (rfxbuilder->copy_params[pnum].list) {
2320  lives_combo_set_active_string(LIVES_COMBO(rfxbuilder->param_def_combo),
2321  (char *)lives_list_nth_data(rfxbuilder->copy_params[pnum].list, defindex));
2322  }
2323 
2325  lives_widget_hide(rfxbuilder->param_dp_label);
2327  lives_widget_hide(rfxbuilder->param_min_label);
2329  lives_widget_hide(rfxbuilder->param_def_label);
2331  lives_widget_hide(rfxbuilder->param_max_label);
2332 
2333  lives_button_set_label(LIVES_BUTTON(rfxbuilder->param_strdef_button), (_("Set _values")));
2334  lives_widget_show(rfxbuilder->param_strdef_hbox);
2336  } else {
2337  if (!strcmp(ctext, "num")) {
2338  rfxbuilder->copy_params[pnum].type = LIVES_PARAM_NUM;
2339  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_def_label), (_("_Default value: ")));
2340  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_min_label), (_("_Minimum value: ")));
2341  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_max_label), (_("Ma_ximum value: ")));
2343  lives_widget_show(rfxbuilder->param_step_label);
2345 
2346  after_param_dp_changed(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_dp), (livespointer)rfxbuilder);
2347 
2348  if (pnum < 0) {
2349  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), 0.);
2350  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), RFX_DEF_NUM_MAX);
2351  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0.);
2352  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_step), 1.);
2353  }
2354  } else if (!strcmp(ctext, "bool")) {
2355  rfxbuilder->copy_params[pnum].type = LIVES_PARAM_BOOL;
2356  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_def_label), (_("_Default value: ")));
2357  lives_widget_hide(rfxbuilder->param_min_label);
2358  lives_widget_hide(rfxbuilder->param_max_label);
2362  lives_widget_hide(rfxbuilder->param_dp_label);
2363  lives_widget_show(rfxbuilder->hbox_bg);
2364  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0, 1);
2365  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0);
2366  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), 0);
2367  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), 0);
2368  } else if (!strcmp(ctext, "colRGB24")) {
2369  rfxbuilder->copy_params[pnum].type = LIVES_PARAM_COLRGB24;
2371  lives_widget_hide(rfxbuilder->param_dp_label);
2372  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_def_label), (_("Default _Red: ")));
2373  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_min_label), (_("Default _Green:")));
2374  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_max_label), (_("Default _Blue: ")));
2375  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_def), 4);
2376  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_min), 4);
2377  lives_entry_set_width_chars(LIVES_ENTRY(rfxbuilder->spinbutton_param_max), 4);
2378  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0, 255);
2379  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), 0, 255);
2380  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), 0, 255);
2381  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0);
2382  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), 0);
2383  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), 0);
2384  if (pnum < 0) {
2385  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), 0.);
2386  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_min), 0.);
2387  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0.);
2388  }
2389  } else if (!strcmp(ctext, "string")) {
2390  rfxbuilder->copy_params[pnum].type = LIVES_PARAM_STRING;
2392  lives_widget_hide(rfxbuilder->param_dp_label);
2394  lives_widget_hide(rfxbuilder->param_min_label);
2396 
2397  lives_button_set_label(LIVES_BUTTON(rfxbuilder->param_strdef_button), (_("Set _default")));
2398  lives_widget_show(rfxbuilder->param_strdef_hbox);
2399  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_def_label), (_("Default value: ")));
2400  lives_label_set_text(LIVES_LABEL(rfxbuilder->param_max_label), (_("Maximum length (chars): ")));
2401  lives_spin_button_set_range(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), 1, RFX_MAXSTRINGLEN);
2402  if (pnum < 0) lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), RFX_TEXT_MAGIC);
2403  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_def), 0);
2404  lives_spin_button_set_digits(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max), 0);
2405 
2406  if (!rfxbuilder->copy_params[pnum].def) {
2407  rfxbuilder->copy_params[pnum].def = lives_strdup("");
2408  // *INDENT-OFF*
2409  }}}
2410  // *INDENT-ONt*
2411 }
2412 
2413 
2414 LiVESWidget *make_param_window_dialog(int pnum, rfx_build_window_t *rfxbuilder) {
2415  LiVESWidget *dialog;
2416  LiVESWidget *dialog_vbox;
2417 
2418  LiVESList *kwlist = NULL;
2419  LiVESList *splist = NULL;
2420  LiVESList *spsublist = NULL;
2421 
2422  char *kw = NULL;
2423  char *sp = NULL;
2424  char *spsub = NULL;
2425  char *rest = NULL;
2426  char *title;
2427 
2428  if (pnum < 0) {
2429  title = (_("New RFX Parameter Window Hint"));
2430  } else {
2431  title = (_("Edit RFX Parameter Window Hint"));
2432  }
2433 
2434  dialog = lives_standard_dialog_new(title, TRUE, -1, -1);
2435  lives_free(title);
2436 
2437  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
2438 
2439  if (pnum >= 0) {
2440  kw = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry[pnum])));
2441  if (!strcmp(kw, "layout")) {
2442  rest = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry2[pnum])));
2443  } else if (!strcmp(kw, "special")) {
2444  int numtok = get_token_count(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry2[pnum])),
2445  (int)rfxbuilder->field_delim[0]);
2446  char **array = lives_strsplit(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->entry2[pnum])), rfxbuilder->field_delim, 3);
2447  sp = lives_strdup(array[0]);
2448  if (!strcmp(sp, "framedraw")) {
2449  if (numtok > 1) {
2450  spsub = lives_strdup(array[1]);
2451  }
2452  if (numtok > 2) {
2453  rest = lives_strdup(array[2]);
2454  }
2455  } else {
2456  if (numtok > 1) {
2457  rest = lives_strdup(array[1]);
2458  }
2459  }
2460  lives_strfreev(array);
2461  }
2462  }
2463 
2464  // kw
2465  kwlist = lives_list_append(kwlist, (livespointer)"layout");
2466  kwlist = lives_list_append(kwlist, (livespointer)"special");
2467 
2468  rfxbuilder->paramw_kw_combo = lives_standard_combo_new(_("_Keyword: "), kwlist, LIVES_BOX(dialog_vbox), NULL);
2469  lives_list_free(kwlist);
2470 
2471  if (pnum >= 0 && kw) {
2472  lives_combo_set_active_string(LIVES_COMBO(rfxbuilder->paramw_kw_combo), kw);
2473  }
2474 
2475  // type
2476  splist = lives_list_append(splist, (livespointer)"aspect");
2477  splist = lives_list_append(splist, (livespointer)"framedraw");
2478  splist = lives_list_append(splist, (livespointer)"fileread");
2479  splist = lives_list_append(splist, (livespointer)"filewrite");
2480  splist = lives_list_append(splist, (livespointer)"password");
2481  if (rfxbuilder->type == RFX_BUILD_TYPE_EFFECT2) {
2482  splist = lives_list_append(splist, (livespointer)"mergealign");
2483  }
2484 
2485  rfxbuilder->paramw_sp_combo = lives_standard_combo_new(_("Special _Type: "), splist, LIVES_BOX(dialog_vbox), NULL);
2486  lives_list_free(splist);
2487 
2488  if (pnum >= 0 && sp) {
2489  lives_combo_set_active_string(LIVES_COMBO(rfxbuilder->paramw_sp_combo), sp);
2490  }
2491 
2492  // subtype
2493 
2494  spsublist = lives_list_append(spsublist, (livespointer)"rectdemask");
2495  spsublist = lives_list_append(spsublist, (livespointer)"multirect");
2496  spsublist = lives_list_append(spsublist, (livespointer)"singlepoint");
2497  spsublist = lives_list_append(spsublist, (livespointer)"scaledpoint");
2498 
2499  rfxbuilder->paramw_spsub_combo = lives_standard_combo_new(_("Special _Subtype: "), spsublist, LIVES_BOX(dialog_vbox),
2500  NULL);
2501  lives_list_free(spsublist);
2502 
2503  if (pnum >= 0 && spsub) {
2504  lives_combo_set_active_string(LIVES_COMBO(rfxbuilder->paramw_spsub_combo), spsub);
2505  }
2506 
2507  // paramwindow rest
2508 
2509  rfxbuilder->paramw_rest_entry = lives_standard_entry_new(_("Row: "), pnum >= 0 && rest ? rest : NULL,
2510  -1, -1, LIVES_BOX(dialog_vbox), NULL);
2512 
2513  if (kw) lives_free(kw);
2514  if (sp) lives_free(sp);
2515  if (spsub) lives_free(spsub);
2516  if (rest) lives_free(rest);
2517 
2519 
2520  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->paramw_kw_combo), LIVES_WIDGET_CHANGED_SIGNAL,
2521  LIVES_GUI_CALLBACK(on_paramw_kw_changed), (livespointer)rfxbuilder);
2522 
2523  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->paramw_sp_combo), LIVES_WIDGET_CHANGED_SIGNAL,
2524  LIVES_GUI_CALLBACK(on_paramw_sp_changed), (livespointer)rfxbuilder);
2525 
2526  lives_signal_sync_connect(LIVES_GUI_OBJECT(rfxbuilder->paramw_spsub_combo), LIVES_WIDGET_CHANGED_SIGNAL,
2527  LIVES_GUI_CALLBACK(on_paramw_spsub_changed), (livespointer)rfxbuilder);
2528 
2529  lives_widget_show_all(dialog);
2530  on_paramw_kw_changed(LIVES_COMBO(rfxbuilder->paramw_kw_combo), (livespointer)rfxbuilder);
2531 
2532  return dialog;
2533 }
2534 
2535 
2536 static void on_paramw_kw_changed(LiVESCombo * combo, livespointer user_data) {
2537  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2538  const char *ctext = lives_combo_get_active_text(combo);
2539 
2540  if (!strcmp(ctext, "special")) {
2542  on_paramw_sp_changed(LIVES_COMBO(rfxbuilder->paramw_sp_combo), (livespointer)rfxbuilder);
2544  } else {
2545  lives_label_set_text(LIVES_LABEL(rfxbuilder->paramw_rest_label), (_("Row: ")));
2549  }
2550 }
2551 
2552 
2553 static void paramw_set_splabel(LiVESLabel * label, int npars) {
2554  char *tmpx;
2555 
2556  if (npars == 1) {
2557  tmpx = (_("Linked parameter: "));
2558  } else {
2559  char example[256] = "0";
2560  for (register int i = 1; i < npars; i++) {
2561  char *xnew = lives_strdup_printf("|%d", i);
2562  lives_strappend(example, 256, xnew);
2563  lives_free(xnew);
2564  }
2565  tmpx = lives_strdup_printf(_("Linked parameters [%d] (example %s) :"), npars, example);
2566  }
2567  lives_label_set_text(label, tmpx);
2568  lives_free(tmpx);
2569 }
2570 
2571 
2572 static void on_paramw_sp_changed(LiVESCombo * combo, livespointer user_data) {
2573  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2574  int npars;
2575  const char *ctext = lives_combo_get_active_text(combo);
2576 
2577  if (!strcmp(ctext, "framedraw")) {
2579  on_paramw_spsub_changed(LIVES_COMBO(rfxbuilder->paramw_spsub_combo), (livespointer)rfxbuilder);
2581  } else {
2582  if (!strcmp(ctext, "fileread") || !strcmp(ctext, "filewrite") || !strcmp(ctext, "password")) npars = 1;
2583  else npars = 2;
2584  paramw_set_splabel(LIVES_LABEL(rfxbuilder->paramw_rest_label), npars);
2586  }
2587 
2589 }
2590 
2591 
2592 static void on_paramw_spsub_changed(LiVESCombo * combo, livespointer user_data) {
2593  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2594  const char *ctext = lives_combo_get_active_text(combo);
2595  int npars = 0;
2596 
2597  if (!strcmp(ctext, "rectdemask") || !strcmp(ctext, "multirect")) {
2598  npars = 4;
2599  } else if (!strcmp(ctext, "singlepoint")) {
2600  npars = 2;
2601  } else if (!strcmp(ctext, "scaledpoint")) {
2602  npars = 3;
2603  }
2604  paramw_set_splabel(LIVES_LABEL(rfxbuilder->paramw_rest_label), npars);
2605 }
2606 
2607 
2608 LiVESWidget *make_trigger_dialog(int tnum, rfx_build_window_t *rfxbuilder) {
2609  LiVESWidget *dialog;
2610  LiVESWidget *dialog_vbox;
2611  LiVESWidget *combo;
2612  LiVESWidget *scrolledwindow;
2613 
2614  LiVESList *whenlist = NULL;
2615 
2616  char *title;
2617 
2618  int woat;
2619  int i;
2620 
2621  if (tnum < 0) {
2622  title = (_("New RFX Trigger"));
2623  } else {
2624  title = (_("Edit RFX Trigger"));
2625  }
2626 
2628  lives_free(title);
2629 
2630  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
2631 
2632  // when
2633 
2634  if (tnum >= 0) whenlist = lives_list_append(whenlist, (livespointer)(rfxbuilder->copy_triggers[tnum].when ?
2635  lives_strdup_printf("%d", rfxbuilder->copy_triggers[tnum].
2636  when - 1) : "init"));
2637  else {
2638  if (!rfxbuilder->has_init_trigger) {
2639  whenlist = lives_list_append(whenlist, (livespointer)"init");
2640  }
2641  for (i = 0; i < rfxbuilder->num_params; i++) {
2642  if (!rfxbuilder->params[i].onchange) {
2643  whenlist = lives_list_append(whenlist, lives_strdup_printf("%d", i));
2644  }
2645  }
2646  }
2647 
2648  combo = lives_standard_combo_new(_("When: "), whenlist, LIVES_BOX(dialog_vbox), NULL);
2649  lives_list_free(whenlist);
2650 
2651  rfxbuilder->trigger_when_entry = lives_combo_get_entry(LIVES_COMBO(combo));
2652 
2653  // code area
2654  rfxbuilder->code_textview = lives_text_view_new();
2655  lives_text_view_set_editable(LIVES_TEXT_VIEW(rfxbuilder->code_textview), TRUE);
2656  lives_text_view_set_wrap_mode(LIVES_TEXT_VIEW(rfxbuilder->code_textview), LIVES_WRAP_WORD);
2657  lives_text_view_set_cursor_visible(LIVES_TEXT_VIEW(rfxbuilder->code_textview), TRUE);
2658 
2659  woat = widget_opts.apply_theme;
2661  widget_opts.expand = LIVES_EXPAND_EXTRA; // prevent centering
2662  scrolledwindow = lives_standard_scrolled_window_new(RFX_WINSIZE_H * 2. / 3., RFX_WINSIZE_V / 4., rfxbuilder->code_textview);
2664  widget_opts.apply_theme = woat;
2665 
2666  if (palette->style & STYLE_1) {
2667  lives_widget_set_base_color(rfxbuilder->code_textview, LIVES_WIDGET_STATE_NORMAL, &palette->white);
2668  lives_widget_set_text_color(rfxbuilder->code_textview, LIVES_WIDGET_STATE_NORMAL, &palette->black);
2669  }
2670 
2671  lives_box_pack_start(LIVES_BOX(dialog_vbox), scrolledwindow, TRUE, TRUE, 0);
2672 
2673  if (tnum >= 0) {
2674  lives_text_view_set_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview),
2675  rfxbuilder->copy_triggers[tnum].code, -1);
2676  }
2677 
2678  if (tnum >= 0 || rfxbuilder->num_params == 0) lives_widget_grab_focus(rfxbuilder->code_textview);
2679 
2680  lives_widget_show_all(dialog);
2681 
2682  return dialog;
2683 }
2684 
2685 
2686 static void on_code_clicked(LiVESButton * button, livespointer user_data) {
2687  LiVESWidget *dialog;
2688  LiVESWidget *dialog_vbox;
2689  LiVESWidget *cancelbutton;
2690  LiVESWidget *okbutton;
2691  LiVESWidget *scrolledwindow;
2692 
2693  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2694 
2695  int woat;
2696 
2697  char *tmpx;
2698 
2700 
2701  dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
2702 
2703  // code area
2704  rfxbuilder->code_textview = lives_text_view_new();
2705 
2706  woat = widget_opts.apply_theme;
2708  widget_opts.expand = LIVES_EXPAND_EXTRA; // prevent centering
2711  widget_opts.apply_theme = woat;
2712 
2713  if (palette->style & STYLE_1) {
2714  lives_widget_set_base_color(rfxbuilder->code_textview, LIVES_WIDGET_STATE_NORMAL, &palette->white);
2715  lives_widget_set_text_color(rfxbuilder->code_textview, LIVES_WIDGET_STATE_NORMAL, &palette->black);
2716  }
2717 
2718  lives_box_pack_start(LIVES_BOX(dialog_vbox), scrolledwindow, TRUE, TRUE, 0);
2719 
2720  lives_widget_object_ref(lives_scrolled_window_get_hadjustment(LIVES_SCROLLED_WINDOW(scrolledwindow)));
2721  lives_widget_object_ref(lives_scrolled_window_get_vadjustment(LIVES_SCROLLED_WINDOW(scrolledwindow)));
2722 
2723  lives_text_view_set_editable(LIVES_TEXT_VIEW(rfxbuilder->code_textview), TRUE);
2724  lives_text_view_set_wrap_mode(LIVES_TEXT_VIEW(rfxbuilder->code_textview), LIVES_WRAP_WORD);
2725  lives_text_view_set_cursor_visible(LIVES_TEXT_VIEW(rfxbuilder->code_textview), TRUE);
2726 
2728 
2729  // TODO !!
2730  /* if (glib_major_version>=2&&glib_minor_version>=4) {
2731  lives_text_view_set_accepts_tab (LIVES_TEXT_VIEW (rfxbuilder->code_textview),TRUE);
2732  } */
2733 
2734  if (button == LIVES_BUTTON(rfxbuilder->pre_button)) {
2735  rfxbuilder->codetype = RFX_CODE_TYPE_PRE;
2736  lives_window_set_title(LIVES_WINDOW(dialog), _("Pre Loop Code"));
2737  lives_text_view_set_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview),
2738  rfxbuilder->pre_code, -1);
2739  }
2740 
2741  else if (button == LIVES_BUTTON(rfxbuilder->loop_button)) {
2742  rfxbuilder->codetype = RFX_CODE_TYPE_LOOP;
2743  lives_window_set_title(LIVES_WINDOW(dialog), _("Loop Code"));
2744  lives_text_view_set_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview),
2745  rfxbuilder->loop_code, -1);
2746  }
2747 
2748  else if (button == LIVES_BUTTON(rfxbuilder->post_button)) {
2749  rfxbuilder->codetype = RFX_CODE_TYPE_POST;
2750  lives_window_set_title(LIVES_WINDOW(dialog), _("Post Loop Code"));
2751  lives_text_view_set_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview),
2752  rfxbuilder->post_code, -1);
2753  }
2754 
2755  else if (button == LIVES_BUTTON(rfxbuilder->param_strdef_button)) {
2756  if (rfxbuilder->copy_params[rfxbuilder->edit_param].type != LIVES_PARAM_STRING_LIST) {
2757  int len, maxlen = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_param_max));
2758 
2759  if ((len = strlen((char *)rfxbuilder->copy_params[rfxbuilder->edit_param].def)) > maxlen) len = maxlen;
2760 
2761  rfxbuilder->codetype = RFX_CODE_TYPE_STRDEF;
2762  lives_window_set_title(LIVES_WINDOW(dialog), (tmpx = lives_strdup_printf
2763  (_("Default text (max length %d)"), maxlen)));
2764  lives_free(tmpx);
2765  lives_text_view_set_wrap_mode(LIVES_TEXT_VIEW(rfxbuilder->code_textview), LIVES_WRAP_WORD);
2766 
2767  lives_text_view_set_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview),
2768  (char *)rfxbuilder->copy_params[rfxbuilder->edit_param].def, len);
2769  } else {
2770  LiVESTextIter start_iter;
2771  char *string = lives_strdup(""), *string_new;
2772  register int i;
2773 
2774  rfxbuilder->codetype = RFX_CODE_TYPE_STRING_LIST;
2775  lives_window_set_title(LIVES_WINDOW(dialog), (tmpx = (_("Enter values, one per line"))));
2776  lives_free(tmpx);
2777  if (rfxbuilder->copy_params[rfxbuilder->edit_param].list) {
2778  for (i = 0; i < lives_list_length(rfxbuilder->copy_params[rfxbuilder->edit_param].list); i++) {
2779  string_new = lives_strconcat(string, (char *)lives_list_nth_data(rfxbuilder->copy_params[rfxbuilder->edit_param].list, i),
2780  "\n", NULL);
2781  if (string != string_new) lives_free(string);
2782  string = string_new;
2783  }
2784  lives_text_view_set_text(LIVES_TEXT_VIEW(rfxbuilder->code_textview), string, strlen(string) - 1);
2785  lives_free(string);
2786  lives_text_buffer_get_start_iter(lives_text_view_get_buffer(LIVES_TEXT_VIEW(rfxbuilder->code_textview)), &start_iter);
2787  lives_text_buffer_place_cursor(lives_text_view_get_buffer(LIVES_TEXT_VIEW(rfxbuilder->code_textview)), &start_iter);
2788  }
2789  }
2790  }
2791 
2792  cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_CANCEL, NULL, LIVES_RESPONSE_CANCEL);
2793 
2794  okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_OK, NULL, LIVES_RESPONSE_OK);
2795 
2797 
2798  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
2799  LIVES_GUI_CALLBACK(on_code_ok), user_data);
2800 
2801  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
2802  LIVES_GUI_CALLBACK(lives_general_button_clicked), NULL);
2803 
2804  lives_widget_show_all(dialog);
2805 }
2806 
2807 
2808 static void on_rfxbuilder_ok(LiVESButton * button, livespointer user_data) {
2809  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2810 
2811  if (!perform_rfxbuilder_checks(rfxbuilder)) return;
2812  if (!rfxbuilder_to_script(rfxbuilder)) return;
2813 
2814  lives_general_button_clicked(button, NULL);
2815  rfxbuilder_destroy(rfxbuilder);
2816 }
2817 
2818 
2819 static void on_rfxbuilder_cancel(LiVESButton * button, livespointer user_data) {
2820  rfx_build_window_t *rfxbuilder = (rfx_build_window_t *)user_data;
2821 
2822  lives_general_button_clicked(button, NULL);
2823  rfxbuilder_destroy(rfxbuilder);
2824 }
2825 
2826 
2827 static void rfxbuilder_destroy(rfx_build_window_t *rfxbuilder) {
2828  register int i;
2829 
2830  for (i = 0; i < rfxbuilder->num_reqs; i++) {
2831  lives_free(rfxbuilder->reqs[i]);
2832  }
2833  for (i = 0; i < rfxbuilder->num_params; i++) {
2834  lives_free(rfxbuilder->params[i].name);
2835  lives_free(rfxbuilder->params[i].label);
2836  if (rfxbuilder->params[i].type == LIVES_PARAM_STRING_LIST) {
2837  if (rfxbuilder->params[i].list)lives_list_free(rfxbuilder->params[i].list);
2838  }
2839  lives_free(rfxbuilder->params[i].def);
2840  }
2841  if (rfxbuilder->num_params) {
2842  lives_free(rfxbuilder->params);
2843  }
2844  for (i = 0; i < rfxbuilder->num_paramw_hints; i++) {
2845  lives_free(rfxbuilder->paramw_hints[i]);
2846  }
2847  for (i = 0; i < rfxbuilder->num_triggers; i++) {
2848  lives_free(rfxbuilder->triggers[i].code);
2849  }
2850  if (rfxbuilder->num_triggers) {
2851  lives_free(rfxbuilder->triggers);
2852  }
2853 
2854  lives_free(rfxbuilder->pre_code);
2855  lives_free(rfxbuilder->loop_code);
2856  lives_free(rfxbuilder->post_code);
2857 
2858  lives_free(rfxbuilder->field_delim);
2859 
2860  if (rfxbuilder->script_name) {
2861  lives_free(rfxbuilder->script_name);
2862  }
2863  if (rfxbuilder->oname) {
2864  lives_free(rfxbuilder->oname);
2865  }
2866  lives_free(rfxbuilder->rfx_version);
2867 
2868  lives_free(rfxbuilder);
2869 }
2870 
2871 
2873  char *name = lives_strdup(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->name_entry)));
2874 
2875  if (!strlen(name)) {
2876  do_error_dialog(_("\n\nName must not be blank.\n"));
2877  lives_widget_grab_focus(rfxbuilder->name_entry);
2878  lives_free(name);
2879  return FALSE;
2880  }
2881  if (get_token_count(name, ' ') > 1) {
2882  do_error_dialog(_("\n\nName must not contain spaces.\n"));
2883  lives_free(name);
2884  return FALSE;
2885  }
2886  if (!strlen(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->menu_text_entry)))) {
2887  do_error_dialog(_("\n\nMenu text must not be blank.\n"));
2889  lives_free(name);
2890  return FALSE;
2891  }
2892  if (!strlen(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->action_desc_entry))) &&
2893  rfxbuilder->type != RFX_BUILD_TYPE_UTILITY) {
2894  do_error_dialog(_("\n\nAction description must not be blank.\n"));
2896  lives_free(name);
2897  return FALSE;
2898  }
2899  if (!strlen(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->author_entry)))) {
2900  do_error_dialog(_("\n\nAuthor must not be blank.\n"));
2902  lives_free(name);
2903  return FALSE;
2904  }
2905 
2906  if (rfxbuilder->mode != RFX_BUILDER_MODE_NEW && !(rfxbuilder->mode == RFX_BUILDER_MODE_EDIT &&
2907  !strcmp(rfxbuilder->oname, name))) {
2909  (name, RFX_STATUS_CUSTOM) > -1 || find_rfx_plugin_by_name(name, RFX_STATUS_BUILTIN) > -1) {
2910  do_error_dialog(_("\n\nThere is already a plugin with this name.\nName must be unique.\n"));
2911  lives_free(name);
2912  return FALSE;
2913  }
2914  }
2915 
2916  if (!strlen(rfxbuilder->loop_code) && rfxbuilder->type != RFX_BUILD_TYPE_UTILITY) {
2917  do_error_dialog(_("\n\nLoop code should not be blank.\n"));
2918  lives_free(name);
2919  return FALSE;
2920  }
2921 
2922  if (rfxbuilder->num_triggers == 0 && rfxbuilder->type == RFX_BUILD_TYPE_UTILITY) {
2923  do_error_dialog(_("\n\nTrigger code should not be blank for a utility.\n"));
2924  lives_free(name);
2925  return FALSE;
2926  }
2927 
2928  lives_free(name);
2929  return TRUE;
2930 }
2931 
2932 
2933 boolean perform_param_checks(rfx_build_window_t *rfxbuilder, int index, int rows) {
2934  register int i;
2935 
2936  if (!strlen(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->param_name_entry)))) {
2937  do_error_dialog(_("\n\nParameter name must not be blank.\n"));
2939  return FALSE;
2940  }
2941  for (i = 0; i < rows; i++) {
2942  if (i != index && !(strcmp(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->param_name_entry)),
2943  rfxbuilder->copy_params[i].name))) {
2944  do_error_dialog(_("\n\nDuplicate parameter name detected. Parameter names must be unique in a plugin.\n\n"));
2945  return FALSE;
2946  }
2947  }
2948  return TRUE;
2949 }
2950 
2951 
2953  FILE *sfile;
2954  lives_colRGB48_t rgb;
2955  char **array;
2956 
2957  double stepwrap;
2958 
2959  uint32_t props;
2960 
2961  const char *name = lives_entry_get_text(LIVES_ENTRY(rfxbuilder->name_entry));
2962 
2963  char *script_file, *script_file_dir;
2964  char *script_name = lives_strdup_printf("%s.%s", name, RFXBUILDER_SCRIPT_SUFFIX);
2965  char *new_name;
2966  char *buf, *tmp, *tmp2;
2967  const char *ctext;
2968 
2969  int retval, i, j;
2970 
2971  if (rfxbuilder->mode != RFX_BUILDER_MODE_EDIT) {
2972  if (!(new_name = prompt_for_script_name(script_name, RFX_STATUS_TEST))) {
2973  lives_free(script_name);
2974  return FALSE;
2975  }
2976  lives_free(script_name);
2977  script_name = new_name;
2978  }
2979 
2980  script_file_dir = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS, NULL);
2981 
2982  if (!lives_file_test(script_file_dir, LIVES_FILE_TEST_IS_DIR)) {
2983  if (lives_mkdir_with_parents(script_file_dir, capable->umask) == -1) {
2984  lives_free(script_name);
2985  return FALSE;
2986  }
2987  }
2988 
2989  script_file = lives_strdup_printf("%s%s", script_file_dir, script_name);
2990  lives_free(script_file_dir);
2991  lives_free(script_name);
2992 
2993  d_print(_("Writing script file %s..."), script_file);
2994 
2995  if (!check_file(script_file, TRUE)) {
2996  lives_free(script_file);
2997  d_print_failed();
2998  return FALSE;
2999  }
3000 
3001  do {
3002  retval = 0;
3003  if (!(sfile = fopen(script_file, "w"))) {
3004  widget_opts.transient = LIVES_WINDOW(rfxbuilder->dialog);
3005  retval = do_write_failed_error_s_with_retry(script_file, lives_strerror(errno));
3006  widget_opts.transient = NULL;
3007 
3008  if (retval == LIVES_RESPONSE_CANCEL) {
3009  lives_free(script_file);
3010  d_print_failed();
3011  return FALSE;
3012  }
3013  } else {
3014  THREADVAR(write_failed) = FALSE;
3015 
3016  lives_fputs("Script file generated from LiVES\n\n", sfile);
3017  lives_fputs("<define>\n", sfile);
3018  lives_fputs(rfxbuilder->field_delim, sfile);
3019  lives_fputs(rfxbuilder->rfx_version, sfile);
3020  lives_fputs("\n</define>\n\n", sfile);
3021  lives_fputs("<name>\n", sfile);
3022  lives_fputs(name, sfile);
3023  lives_fputs("\n</name>\n\n", sfile);
3024  lives_fputs("<version>\n", sfile);
3025  buf = lives_strdup_printf("%d", lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_version)));
3026  lives_fputs(buf, sfile);
3027  lives_free(buf);
3028  lives_fputs("\n</version>\n\n", sfile);
3029  lives_fputs("<author>\n", sfile);
3030  lives_fputs(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->author_entry)), sfile);
3031  lives_fputs(rfxbuilder->field_delim, sfile);
3032  lives_fputs(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->url_entry)), sfile);
3033  lives_fputs("\n</author>\n\n", sfile);
3034  lives_fputs("<description>\n", sfile);
3035  lives_fputs(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->menu_text_entry)), sfile);
3036  lives_fputs(rfxbuilder->field_delim, sfile);
3037  lives_fputs(lives_entry_get_text(LIVES_ENTRY(rfxbuilder->action_desc_entry)), sfile);
3038  lives_fputs(rfxbuilder->field_delim, sfile);
3039  if (rfxbuilder->type == RFX_BUILD_TYPE_UTILITY) {
3040  buf = lives_strdup("-1");
3041  } else {
3042  buf = lives_strdup_printf("%d", lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_min_frames)));
3043  }
3044  lives_fputs(buf, sfile);
3045  lives_free(buf);
3046  lives_fputs(rfxbuilder->field_delim, sfile);
3047  switch (rfxbuilder->type) {
3049  buf = lives_strdup("2");
3050  break;
3052  buf = lives_strdup("0");
3053  break;
3054  default:
3055  buf = lives_strdup("1");
3056  }
3057  lives_fputs(buf, sfile);
3058  lives_free(buf);
3059  lives_fputs(rfxbuilder->field_delim, sfile);
3060  lives_fputs("\n</description>\n\n", sfile);
3061  lives_fputs("<requires>\n", sfile);
3062  for (i = 0; i < rfxbuilder->num_reqs; i++) {
3063  lives_fputs(rfxbuilder->reqs[i], sfile);
3064  if (i < rfxbuilder->num_reqs - 1)
3065  lives_fputs("\n", sfile);
3066  }
3067  lives_fputs("\n</requires>\n\n", sfile);
3068  lives_fputs("<params>\n", sfile);
3069  for (i = 0; i < rfxbuilder->num_params; i++) {
3070  lives_fputs(rfxbuilder->params[i].name, sfile);
3071  lives_fputs(rfxbuilder->field_delim, sfile);
3072  lives_fputs(rfxbuilder->params[i].label, sfile);
3073  lives_fputs(rfxbuilder->field_delim, sfile);
3074  switch (rfxbuilder->params[i].type) {
3075  case LIVES_PARAM_NUM:
3076  stepwrap = rfxbuilder->params[i].step_size;
3077  if (rfxbuilder->params[i].wrap) stepwrap = -stepwrap;
3078  lives_fputs("num", sfile);
3079  buf = lives_strdup_printf("%d", rfxbuilder->params[i].dp);
3080  lives_fputs(buf, sfile);
3081  lives_free(buf);
3082  lives_fputs(rfxbuilder->field_delim, sfile);
3083  if (!rfxbuilder->params[i].dp) {
3084  buf = lives_strdup_printf("%d", get_int_param(rfxbuilder->params[i].def));
3085  lives_fputs(buf, sfile);
3086  lives_free(buf);
3087  lives_fputs(rfxbuilder->field_delim, sfile);
3088  buf = lives_strdup_printf("%d", (int)rfxbuilder->params[i].min);
3089  lives_fputs(buf, sfile);
3090  lives_free(buf);
3091  lives_fputs(rfxbuilder->field_delim, sfile);
3092  buf = lives_strdup_printf("%d", (int)rfxbuilder->params[i].max);
3093  lives_fputs(buf, sfile);
3094  lives_free(buf);
3095  lives_fputs(rfxbuilder->field_delim, sfile);
3096  if (stepwrap != 1.) {
3097  buf = lives_strdup_printf("%d", (int)stepwrap);
3098  lives_fputs(buf, sfile);
3099  lives_free(buf);
3100  lives_fputs(rfxbuilder->field_delim, sfile);
3101  }
3102  } else {
3103  char *pattern = lives_strdup_printf("%%.%df", rfxbuilder->params[i].dp);
3104  buf = lives_strdup_printf(pattern, get_double_param(rfxbuilder->params[i].def));
3105  lives_fputs(buf, sfile);
3106  lives_free(buf);
3107  lives_fputs(rfxbuilder->field_delim, sfile);
3108  buf = lives_strdup_printf(pattern, rfxbuilder->params[i].min);
3109  lives_fputs(buf, sfile);
3110  lives_free(buf);
3111  lives_fputs(rfxbuilder->field_delim, sfile);
3112  buf = lives_strdup_printf(pattern, rfxbuilder->params[i].max);
3113  lives_fputs(buf, sfile);
3114  lives_free(buf);
3115  lives_fputs(rfxbuilder->field_delim, sfile);
3116  if (stepwrap != 1.) {
3117  buf = lives_strdup_printf(pattern, stepwrap);
3118  lives_fputs(buf, sfile);
3119  lives_free(buf);
3120  lives_fputs(rfxbuilder->field_delim, sfile);
3121  }
3122  lives_free(pattern);
3123  }
3124  break;
3125  case LIVES_PARAM_BOOL:
3126  lives_fputs("bool", sfile);
3127  lives_fputs(rfxbuilder->field_delim, sfile);
3128  buf = lives_strdup_printf("%d", get_bool_param(rfxbuilder->params[i].def));
3129  lives_fputs(buf, sfile);
3130  lives_free(buf);
3131  lives_fputs(rfxbuilder->field_delim, sfile);
3132  if (rfxbuilder->params[i].group != 0) {
3133  buf = lives_strdup_printf("%d", rfxbuilder->params[i].group);
3134  lives_fputs(buf, sfile);
3135  lives_free(buf);
3136  lives_fputs(rfxbuilder->field_delim, sfile);
3137  }
3138  break;
3139  case LIVES_PARAM_COLRGB24:
3140  lives_fputs("colRGB24", sfile);
3141  lives_fputs(rfxbuilder->field_delim, sfile);
3142  get_colRGB24_param(rfxbuilder->params[i].def, &rgb);
3143  buf = lives_strdup_printf("%d", rgb.red);
3144  lives_fputs(buf, sfile);
3145  lives_free(buf);
3146  lives_fputs(rfxbuilder->field_delim, sfile);
3147  buf = lives_strdup_printf("%d", rgb.green);
3148  lives_fputs(buf, sfile);
3149  lives_free(buf);
3150  lives_fputs(rfxbuilder->field_delim, sfile);
3151  buf = lives_strdup_printf("%d", rgb.blue);
3152  lives_fputs(buf, sfile);
3153  lives_free(buf);
3154  lives_fputs(rfxbuilder->field_delim, sfile);
3155  break;
3156  case LIVES_PARAM_STRING:
3157  lives_fputs("string", sfile);
3158  lives_fputs(rfxbuilder->field_delim, sfile);
3159  lives_fputs((tmp = U82L(tmp2 = subst((char *)rfxbuilder->params[i].def, "\n", "\\n"))), sfile);
3160  lives_free(tmp);
3161  lives_free(tmp2);
3162  lives_fputs(rfxbuilder->field_delim, sfile);
3163  buf = lives_strdup_printf("%d", (int)rfxbuilder->params[i].max);
3164  lives_fputs(buf, sfile);
3165  lives_free(buf);
3166  lives_fputs(rfxbuilder->field_delim, sfile);
3167  break;
3169  lives_fputs("string_list", sfile);
3170  lives_fputs(rfxbuilder->field_delim, sfile);
3171  if (rfxbuilder->params[i].def) {
3172  buf = lives_strdup_printf("%d", get_bool_param(rfxbuilder->params[i].def));
3173  lives_fputs(buf, sfile);
3174  lives_free(buf);
3175  lives_fputs(rfxbuilder->field_delim, sfile);
3176  for (j = 0; j < lives_list_length(rfxbuilder->params[i].list); j++) {
3177  lives_fputs((tmp = U82L(tmp2 = subst((char *)lives_list_nth_data
3178  (rfxbuilder->params[i].list, j), "\n", "\\n"))), sfile);
3179  lives_free(tmp);
3180  lives_free(tmp2);
3181  lives_fputs(rfxbuilder->field_delim, sfile);
3182  }
3183  }
3184  break;
3185  default:
3186  break;
3187  }
3188  if (i < rfxbuilder->num_params - 1)
3189  lives_fputs("\n", sfile);
3190  }
3191  lives_fputs("\n</params>\n\n", sfile);
3192  lives_fputs("<param_window>\n", sfile);
3193  for (i = 0; i < rfxbuilder->num_paramw_hints; i++) {
3194  lives_fputs(rfxbuilder->paramw_hints[i], sfile);
3195  if (strlen(rfxbuilder->paramw_hints[i]) > strlen(rfxbuilder->field_delim) &&
3196  strcmp(rfxbuilder->paramw_hints[i] + strlen(rfxbuilder->paramw_hints[i])
3197  - strlen(rfxbuilder->field_delim), rfxbuilder->field_delim))
3198  lives_fputs(rfxbuilder->field_delim, sfile);
3199  lives_fputs("\n", sfile);
3200  }
3201  lives_fputs("</param_window>\n\n", sfile);
3202  lives_fputs("<properties>\n", sfile);
3203  if (rfxbuilder->type == RFX_BUILD_TYPE_TOOL) props = rfxbuilder->props | RFX_PROPS_MAY_RESIZE;
3204  else props = rfxbuilder->props;
3205 
3206  if (rfxbuilder->type != RFX_BUILD_TYPE_EFFECT0 && (rfxbuilder->props & RFX_PROPS_BATCHG))
3207  rfxbuilder->props ^= RFX_PROPS_BATCHG;
3208 
3209  buf = lives_strdup_printf("0x%04X", props);
3210  lives_fputs(buf, sfile);
3211  lives_free(buf);
3212  lives_fputs("\n</properties>\n\n", sfile);
3213  lives_fputs("<language_code>\n", sfile);
3214  ctext = lives_combo_get_active_text(LIVES_COMBO(rfxbuilder->langc_combo));
3215  array = lives_strsplit(ctext, " ", -1);
3216  lives_fputs(array[0], sfile);
3217  lives_strfreev(array);
3218  lives_fputs("\n</language_code>\n\n", sfile);
3219  lives_fputs("<pre>\n", sfile);
3220  lives_fputs(rfxbuilder->pre_code, sfile);
3221  if (strlen(rfxbuilder->pre_code) && strcmp(rfxbuilder->pre_code + strlen(rfxbuilder->pre_code) - 1, "\n"))
3222  lives_fputs("\n", sfile);
3223  lives_fputs("</pre>\n\n", sfile);
3224  lives_fputs("<loop>\n", sfile);
3225  lives_fputs(rfxbuilder->loop_code, sfile);
3226  if (strlen(rfxbuilder->loop_code) && strcmp(rfxbuilder->loop_code + strlen(rfxbuilder->loop_code) - 1, "\n"))
3227  lives_fputs("\n", sfile);
3228  lives_fputs("</loop>\n\n", sfile);
3229  lives_fputs("<post>\n", sfile);
3230  lives_fputs(rfxbuilder->post_code, sfile);
3231  if (strlen(rfxbuilder->post_code) && strcmp(rfxbuilder->post_code + strlen(rfxbuilder->post_code) - 1, "\n"))
3232  lives_fputs("\n", sfile);
3233  lives_fputs("</post>\n\n", sfile);
3234  lives_fputs("<onchange>\n", sfile);
3235  for (i = 0; i < rfxbuilder->num_triggers; i++) {
3236  int numtok = get_token_count(rfxbuilder->triggers[i].code, '\n');
3237  buf = rfxbuilder->triggers[i].when ? lives_strdup_printf("%d", rfxbuilder->triggers[i].when - 1) : lives_strdup("init");
3238  array = lives_strsplit(rfxbuilder->triggers[i].code, "\n", numtok);
3239  for (int j = 0; j < numtok; j++) {
3240  lives_fputs(buf, sfile);
3241  lives_fputs(rfxbuilder->field_delim, sfile);
3242  if (array[j]) lives_fputs(array[j], sfile);
3243  if (j < numtok - 1)
3244  lives_fputs("\n", sfile);
3245  }
3246  lives_fputs("\n", sfile);
3247  lives_free(buf);
3248  lives_strfreev(array);
3249  }
3250  lives_fputs("</onchange>\n\n", sfile);
3251  fclose(sfile);
3252 
3253  if (THREADVAR(write_failed)) {
3254  THREADVAR(write_failed) = FALSE;
3255  widget_opts.transient = LIVES_WINDOW(rfxbuilder->dialog);
3256  retval = do_write_failed_error_s_with_retry(script_file, NULL);
3257  widget_opts.transient = NULL;
3258  if (retval == LIVES_RESPONSE_CANCEL) d_print_file_error_failed();
3259  }
3260  }
3261  } while (retval == LIVES_RESPONSE_RETRY);
3262 
3263  lives_free(script_file);
3264 
3265  if (retval != LIVES_RESPONSE_CANCEL) {
3266  d_print_done();
3267 
3272 
3273  return TRUE;
3274  }
3275  return FALSE;
3276 }
3277 
3278 
3279 boolean script_to_rfxbuilder(rfx_build_window_t *rfxbuilder, const char *script_file) {
3280  LiVESList *list;
3281 
3282  char **array;
3283  char *tmp;
3284  char *line;
3285  char *version;
3286 
3287  int listlen;
3288  int num_channels;
3289  int tnum, found;
3290  int filled_triggers = 0;
3291  int len;
3292 
3293  register int i, j;
3294 
3295  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT1;
3296  if (!(list = get_script_section("define", script_file, TRUE))) {
3297  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("No <define> section found in script.\n")));
3298  return FALSE;
3299  }
3300  tmp = (char *)lives_list_nth_data(list, 0);
3301  if (strlen(tmp) < 2) {
3302  lives_list_free_all(&list);
3303  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("Bad script version.\n")));
3304  return FALSE;
3305  }
3306 
3307  version = lives_strdup(tmp + 1);
3309  lives_list_free_all(&list);
3311  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("Bad script version.\n")));
3312  return FALSE;
3313  }
3315 
3316  lives_memset(tmp + 1, 0, 1);
3317  lives_free(rfxbuilder->field_delim);
3318  rfxbuilder->field_delim = lives_strdup(tmp);
3319  lives_list_free_all(&list);
3320 
3321  if (!(list = get_script_section("name", script_file, TRUE))) {
3322  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("No <name> section found in script.\n")));
3323  return FALSE;
3324  }
3325  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->name_entry), (char *)lives_list_nth_data(list, 0));
3326  lives_list_free_all(&list);
3327 
3328  if (!(list = get_script_section("version", script_file, TRUE))) {
3329  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("No <version> section found in script.\n")));
3330  return FALSE;
3331  }
3332  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_version),
3333  (double)atoi((char *)lives_list_nth_data(list, 0)));
3334  lives_list_free_all(&list);
3335 
3336  if (!(list = get_script_section("author", script_file, TRUE))) {
3337  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("No <author> section found in script.\n")));
3338  return FALSE;
3339  }
3340  array = lives_strsplit((char *)lives_list_nth_data(list, 0), rfxbuilder->field_delim, 2);
3341  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->author_entry), array[0]);
3342  if (get_token_count((char *)lives_list_nth_data(list, 0), (int)rfxbuilder->field_delim[0]) > 1) {
3343  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->url_entry), array[1]);
3344  }
3345  lives_strfreev(array);
3346  lives_list_free_all(&list);
3347 
3348  if (!(list = get_script_section("description", script_file, TRUE))) {
3349  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", (_("No <description> section found in script.\n")));
3350  return FALSE;
3351  }
3352  if (get_token_count((char *)lives_list_nth_data(list, 0), (int)rfxbuilder->field_delim[0]) < 4) {
3353  lives_snprintf(mainw->msg, MAINW_MSG_SIZE, (_("Bad description. (%s)\n")), (char *)lives_list_nth_data(list, 0));
3354  lives_list_free_all(&list);
3355  return FALSE;
3356  }
3357  array = lives_strsplit((char *)lives_list_nth_data(list, 0), rfxbuilder->field_delim, -1);
3358  lives_list_free_all(&list);
3359  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->menu_text_entry), array[0]);
3360  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->action_desc_entry), array[1]);
3361  lives_spin_button_set_value(LIVES_SPIN_BUTTON(rfxbuilder->spinbutton_min_frames), (double)atoi(array[2]));
3362  num_channels = atoi(array[3]);
3363 
3364  if (num_channels == 2) {
3365  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT2;
3366  }
3367  if (num_channels == 0) {
3368  rfxbuilder->type = RFX_BUILD_TYPE_EFFECT0;
3369  }
3370  if (atoi(array[2]) == -1) rfxbuilder->type = RFX_BUILD_TYPE_UTILITY;
3371  lives_strfreev(array);
3372 
3373  rfxbuilder->script_name = lives_strdup(script_file);
3374 
3375  if ((list = get_script_section("requires", script_file, TRUE))) {
3376  rfxbuilder->num_reqs = lives_list_length(list);
3377  for (i = 0; i < rfxbuilder->num_reqs; i++) {
3378  rfxbuilder->reqs[i] = (char *)lives_list_nth_data(list, i);
3379  }
3380  lives_list_free(list);
3381  }
3382 
3383  rfxbuilder->props = 0;
3384 
3385  if ((list = get_script_section("properties", script_file, TRUE))) {
3386  if (!strncmp((char *)lives_list_nth_data(list, 0), "0x", 2) || !strncmp((char *)lives_list_nth_data(list, 0), "0x", 2)) {
3387  rfxbuilder->props = hextodec((char *)lives_list_nth_data(list, 0) + 2);
3388  } else rfxbuilder->props = atoi((char *)lives_list_nth_data(list, 0));
3389  lives_list_free_all(&list);
3390  }
3391 
3392  if (rfxbuilder->props & RFX_PROPS_MAY_RESIZE) rfxbuilder->type = RFX_BUILD_TYPE_TOOL;
3393 
3394  if ((list = get_script_section("params", script_file, TRUE))) {
3395  char *type;
3396 
3397  listlen = lives_list_length(list);
3398  rfxbuilder->num_params = listlen;
3399  rfxbuilder->params = (lives_param_t *)lives_malloc(rfxbuilder->num_params * sizeof(lives_param_t));
3400  i = 0;
3401 
3402  for (j = 0; j < listlen; j++) {
3403  line = (char *)lives_list_nth_data(list, j);
3404  len = get_token_count(line, (int)rfxbuilder->field_delim[0]); // will fail if field_delim contains repeated chars !
3405  if (len < 4) {
3406  rfxbuilder->num_params--;
3407  rfxbuilder->params = (lives_param_t *)lives_realloc(rfxbuilder->params, rfxbuilder->num_params * sizeof(lives_param_t));
3408  continue;
3409  }
3410  array = lives_strsplit(line, rfxbuilder->field_delim, -1);
3411  lives_free(line);
3412  rfxbuilder->params[i].name = lives_strdup(array[0]);
3413  rfxbuilder->params[i].label = lives_strdup(array[1]);
3414  rfxbuilder->params[i].onchange = FALSE;
3415  rfxbuilder->params[i].dp = 0;
3416  rfxbuilder->params[i].group = 0;
3417 
3419  rfxbuilder->params[i].desc = NULL;
3420  rfxbuilder->params[i].use_mnemonic = TRUE;
3421  rfxbuilder->params[i].step_size = 1.;
3422  rfxbuilder->params[i].hidden = FALSE;
3423  rfxbuilder->params[i].transition = FALSE;
3424  rfxbuilder->params[i].wrap = FALSE;
3426 
3427  type = lives_strdup(array[2]);
3428  if (!strncmp(type, "num", 3)) {
3429  if (len < 6) {
3430  lives_free(rfxbuilder->params[i].name);
3431  lives_free(rfxbuilder->params[i].label);
3432  rfxbuilder->num_params--;
3433  rfxbuilder->params = (lives_param_t *)lives_realloc(rfxbuilder->params, rfxbuilder->num_params * sizeof(lives_param_t));
3434  continue;
3435  }
3436  rfxbuilder->params[i].dp = atoi(type + 3);
3437  rfxbuilder->params[i].type = LIVES_PARAM_NUM;
3438  if (rfxbuilder->params[i].dp) {
3439  rfxbuilder->params[i].def = lives_malloc(sizint);
3440  set_double_param(rfxbuilder->params[i].def, lives_strtod(array[3], NULL));
3441  } else {
3442  rfxbuilder->params[i].def = lives_malloc(sizint);
3443  set_int_param(rfxbuilder->params[i].def, atoi(array[3]));
3444  }
3445  rfxbuilder->params[i].min = lives_strtod(array[4], NULL);
3446  rfxbuilder->params[i].max = lives_strtod(array[5], NULL);
3447  if (len > 6) {
3448  rfxbuilder->params[i].step_size = lives_strtod(array[6], NULL);
3449  if (rfxbuilder->params[i].step_size == 0.) rfxbuilder->params[i].step_size = 1.;
3450  else if (rfxbuilder->params[i].step_size < 0.) {
3451  rfxbuilder->params[i].step_size = -rfxbuilder->params[i].step_size;
3452  rfxbuilder->params[i].wrap = TRUE;
3453  }
3454  }
3455  } else if (!strcmp(type, "colRGB24")) {
3456  if (len < 6) {
3457  lives_free(rfxbuilder->params[i].name);
3458  lives_free(rfxbuilder->params[i].label);
3459  rfxbuilder->num_params--;
3460  rfxbuilder->params = (lives_param_t *)lives_realloc(rfxbuilder->params, rfxbuilder->num_params * sizeof(lives_param_t));
3461  continue;
3462  }
3463  rfxbuilder->params[i].type = LIVES_PARAM_COLRGB24;
3464  rfxbuilder->params[i].def = lives_malloc(3 * sizint);
3465  set_colRGB24_param(rfxbuilder->params[i].def, (short)atoi(array[3]),
3466  (short)atoi(array[4]), (short)atoi(array[5]));
3467  } else if (!strcmp(type, "string")) {
3468  rfxbuilder->params[i].type = LIVES_PARAM_STRING;
3469  rfxbuilder->params[i].def = subst((tmp = L2U8(array[3])), "\\n", "\n");
3470  lives_free(tmp);
3471  if (len > 4) rfxbuilder->params[i].max = (double)atoi(array[4]);
3472  else rfxbuilder->params[i].max = 1024; // TODO
3473  } else if (!strcmp(type, "string_list")) {
3474  rfxbuilder->params[i].type = LIVES_PARAM_STRING_LIST;
3475  rfxbuilder->params[i].def = lives_malloc(sizint);
3476  set_int_param(rfxbuilder->params[i].def, atoi(array[3]));
3477  if (len > 4) {
3478  rfxbuilder->params[i].list = array_to_string_list(array, 3, len);
3479  } else {
3480  rfxbuilder->params[i].list = NULL;
3481  set_int_param(rfxbuilder->params[i].def, 0);
3482  }
3483  } else {
3484  // default is bool
3485  rfxbuilder->params[i].type = LIVES_PARAM_BOOL;
3486  rfxbuilder->params[i].def = lives_malloc(sizint);
3487  set_bool_param(rfxbuilder->params[i].def, atoi(array[3]));
3488  if (len > 4) rfxbuilder->params[i].group = atoi(array[4]);
3489  }
3490  lives_free(type);
3491  lives_strfreev(array);
3492  i++;
3493  }
3494  lives_list_free(list);
3495  }
3496 
3497  if ((list = get_script_section("param_window", script_file, TRUE))) {
3498  rfxbuilder->num_paramw_hints = lives_list_length(list);
3499  for (i = 0; i < rfxbuilder->num_paramw_hints; i++) {
3500  rfxbuilder->paramw_hints[i] = (char *)lives_list_nth_data(list, i);
3501  }
3502  lives_list_free(list);
3503  }
3504 
3505  if ((list = get_script_section("onchange", script_file, TRUE))) {
3506  listlen = lives_list_length(list);
3507  for (i = 0; i < listlen; i++) {
3508  array = lives_strsplit((char *)lives_list_nth_data(list, i), rfxbuilder->field_delim, -1);
3509  if (!strcmp(array[0], "init")) {
3510  if (!rfxbuilder->has_init_trigger) {
3511  rfxbuilder->has_init_trigger = TRUE;
3512  rfxbuilder->num_triggers++;
3513  }
3514  } else if ((tnum = atoi(array[0]) + 1) <= rfxbuilder->num_params && tnum > 0) {
3515  if (!rfxbuilder->params[tnum - 1].onchange) {
3516  rfxbuilder->params[tnum - 1].onchange = TRUE;
3517  rfxbuilder->num_triggers++;
3518  }
3519  } else {
3520  //invalid trigger
3521  char *msg = lives_strdup_printf(_("\n\nInvalid trigger (%s)\nfound in script.\n\n"), array[0]);
3523  do_error_dialog(msg);
3525  lives_free(msg);
3526  }
3527  lives_strfreev(array);
3528  }
3529  //end pass 1
3530  rfxbuilder->triggers = (rfx_trigger_t *)lives_malloc(rfxbuilder->num_triggers * sizeof(rfx_trigger_t));
3531 
3532  for (i = 0; i < rfxbuilder->num_triggers; i++) {
3533  rfxbuilder->triggers[i].when = -1;
3534  rfxbuilder->triggers[i].code = lives_strdup("");
3535  }
3536 
3537  filled_triggers = 0;
3538  listlen = lives_list_length(list);
3539  for (i = 0; i < listlen; i++) {
3540  array = lives_strsplit((char *)lives_list_nth_data(list, i), rfxbuilder->field_delim, -1);
3541  if (!strcmp(array[0], "init")) {
3542  // find init trigger and concatenate code
3543  found = filled_triggers;
3544  for (j = 0; j < filled_triggers && found == filled_triggers; j++) if (rfxbuilder->triggers[j].when == 0) found = j;
3545  if (found == filled_triggers) filled_triggers++;
3546  if (!strlen(rfxbuilder->triggers[found].code)) {
3547  tmp = lives_strconcat(rfxbuilder->triggers[found].code, array[1], NULL);
3548  } else {
3549  tmp = lives_strconcat(rfxbuilder->triggers[found].code, "\n", array[1], NULL);
3550  }
3551  lives_free(rfxbuilder->triggers[found].code);
3552  rfxbuilder->triggers[found].when = 0;
3553  rfxbuilder->triggers[found].code = lives_strdup(tmp);
3554  lives_free(tmp);
3555  } else if ((tnum = atoi(array[0]) + 1) <= rfxbuilder->num_params && tnum > 0) {
3556  // find tnum trigger and concatenate code
3557  found = filled_triggers;
3558 
3559  for (j = 0; j < filled_triggers && found == filled_triggers; j++) if (rfxbuilder->triggers[j].when == tnum) found = j;
3560  if (found == filled_triggers) filled_triggers++;
3561 
3562  if (!strlen(rfxbuilder->triggers[found].code)) {
3563  tmp = lives_strconcat(rfxbuilder->triggers[found].code, array[1], NULL);
3564  } else {
3565  tmp = lives_strconcat(rfxbuilder->triggers[found].code, "\n", array[1], NULL);
3566  }
3567  lives_free(rfxbuilder->triggers[found].code);
3568  rfxbuilder->triggers[found].when = tnum;
3569  rfxbuilder->triggers[found].code = lives_strdup(tmp);
3570  lives_free(tmp);
3571  }
3572  lives_strfreev(array);
3573  }
3574  lives_list_free_all(&list);
3575  }
3576 
3577  if ((list = get_script_section("pre", script_file, FALSE))) {
3578  listlen = lives_list_length(list);
3579  for (i = 0; i < listlen; i++) {
3580  tmp = lives_strconcat(rfxbuilder->pre_code, lives_list_nth_data(list, i), NULL);
3581  lives_free(rfxbuilder->pre_code);
3582  rfxbuilder->pre_code = tmp;
3583  }
3584  lives_list_free_all(&list);
3585  }
3586 
3587  if ((list = get_script_section("loop", script_file, FALSE))) {
3588  listlen = lives_list_length(list);
3589  for (i = 0; i < listlen; i++) {
3590  tmp = lives_strconcat(rfxbuilder->loop_code, lives_list_nth_data(list, i), NULL);
3591  lives_free(rfxbuilder->loop_code);
3592  rfxbuilder->loop_code = tmp;
3593  }
3594  lives_list_free_all(&list);
3595  }
3596 
3597  if ((list = get_script_section("post", script_file, FALSE))) {
3598  listlen = lives_list_length(list);
3599  for (i = 0; i < listlen; i++) {
3600  tmp = lives_strconcat(rfxbuilder->post_code, lives_list_nth_data(list, i), NULL);
3601  lives_free(rfxbuilder->post_code);
3602  rfxbuilder->post_code = tmp;
3603  }
3604  lives_list_free_all(&list);
3605  }
3606 
3607  return TRUE;
3608 }
3609 
3610 
3611 LiVESList *get_script_section(const char *section, const char *file, boolean strip) {
3612  char *com = lives_strdup_printf("\"%s\" -get \"%s\" \"%s\"", EXEC_RFX_BUILDER, section, file);
3613  LiVESList *list = get_plugin_result(com, "\n", FALSE, strip);
3614  lives_free(com);
3615  return list;
3616 }
3617 
3618 
3624 /* LiVESList *get_script_section_from_text(const char *section, const char *text, boolean strip) { */
3625 /* LiVESList *list; */
3626 /* // TODO */
3627 /* return list; */
3628 /* } */
3629 
3630 
3631 void on_rebuild_rfx_activate(LiVESMenuItem * menuitem, livespointer user_data) {
3632  char *com;
3633  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
3634 
3635  if (!check_builder_programs()) return;
3636 
3637  do_threaded_dialog(_("Rebuilding RFX scripts"), FALSE);
3638 
3639  switch (status) {
3640  case RFX_STATUS_CUSTOM:
3641  d_print(_("Rebuilding custom RFX scripts..."));
3642  com = lives_strdup_printf("%s build_rfx_plugins custom", prefs->backend_sync);
3643  lives_system(com, FALSE);
3644  lives_free(com);
3645  break;
3646  case RFX_STATUS_TEST:
3647  d_print(_("Rebuilding test RFX scripts..."));
3648  com = lives_strdup_printf("%s build_rfx_plugins test", prefs->backend_sync);
3649  lives_system(com, FALSE);
3650  lives_free(com);
3651  break;
3652  default:
3653  break;
3654  }
3655 
3656  d_print(_("recreating dynamic menu entries..."));
3659  add_rfx_effects(status);
3661  d_print_done();
3665 }
3666 
3667 
3668 boolean check_builder_programs(void) {
3669 #ifdef IS_MINGW
3670  return TRUE;
3671 #endif
3672 
3673  // check our plugin builder routines are executable
3674  char loc[32];
3675  char *msg;
3676 
3677  get_location(EXEC_RFX_BUILDER, loc, 32);
3678  if (!strlen(loc)) {
3679  msg = lives_strdup_printf(
3680  _("\n\nLiVES was unable to find the program %s.\nPlease check this program is in your path and executable.\n"),
3682  do_error_dialog(msg);
3683  lives_free(msg);
3684  return FALSE;
3685  }
3687  if (!strlen(loc)) {
3688  msg = lives_strdup_printf(
3689  _("\n\nLiVES was unable to find the program %s.\nPlease check this program is in your path and executable.\n"),
3691  do_error_dialog(msg);
3692  lives_free(msg);
3693  return FALSE;
3694  }
3695  return TRUE;
3696 }
3697 
3698 
3699 void on_delete_rfx_activate(LiVESMenuItem * menuitem, livespointer user_data) {
3700  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
3701  int ret;
3702  char *rfx_script_file, *rfx_exec_dir, *rfx_script_dir;
3703  char *script_name = prompt_for_script_name(NULL, status);
3704  char *msg;
3705 
3706  if (!script_name) return; // user cancelled
3707 
3708  if (strlen(script_name)) {
3709  switch (status) {
3710  case RFX_STATUS_TEST:
3711  rfx_exec_dir = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_TEST, NULL);
3712  rfx_script_dir = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS, NULL);
3713  rfx_script_file = lives_build_filename(rfx_script_dir, script_name, NULL);
3714  break;
3715  case RFX_STATUS_CUSTOM:
3716  rfx_exec_dir = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_CUSTOM, NULL);
3717  rfx_script_dir = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS, NULL);
3718  rfx_script_file = lives_build_filename(rfx_script_dir, script_name, NULL);
3719  break;
3720  default:
3721  // we will not delete builtins
3722  lives_free(script_name);
3723  return;
3724  }
3725  lives_free(script_name);
3726 
3727  // double check with user
3728  msg = lives_strdup_printf(_("\n\nReally delete RFX script\n%s ?\n\n"), rfx_script_file);
3729  if (!do_warning_dialog(msg)) {
3730  lives_free(msg);
3731  lives_free(rfx_script_file);
3732  lives_free(rfx_script_dir);
3733  lives_free(rfx_exec_dir);
3734  return;
3735  }
3736  lives_free(msg);
3737 
3738  d_print(_("Deleting rfx script %s..."), rfx_script_file);
3739 
3740  if (!(ret = lives_rm(rfx_script_file))) {
3741  lives_rmdir(rfx_exec_dir, TRUE);
3742  d_print_done();
3743  on_rebuild_rfx_activate(NULL, LIVES_INT_TO_POINTER(status));
3744  } else {
3745  d_print_failed();
3746  msg = lives_strdup_printf(_("\n\nFailed to delete the script\n%s\nError code was %d\n"), rfx_script_file, ret);
3748  do_error_dialog(msg);
3750  lives_free(msg);
3751  }
3752  lives_free(rfx_script_file);
3753  lives_free(rfx_script_dir);
3754  lives_free(rfx_exec_dir);
3755  }
3756 }
3757 
3758 
3759 void on_promote_rfx_activate(LiVESMenuItem * menuitem, livespointer user_data) {
3760  char *rfx_script_from = NULL;
3761  char *rfx_script_to = NULL;
3762  char *rfx_dir_from = NULL;
3763  char *rfx_dir_to = NULL;
3764  char *script_name = prompt_for_script_name(NULL, RFX_STATUS_TEST);
3765  char *msg;
3766  int ret = 0;
3767  boolean failed = TRUE;
3768 
3769  if (!script_name) return; // user cancelled
3770 
3771  if (strlen(script_name)) {
3772  rfx_dir_from = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS, NULL);
3773  rfx_script_from = lives_build_filename(rfx_dir_from, script_name, NULL);
3774 
3775  rfx_dir_to = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS, NULL);
3776  rfx_script_to = lives_build_filename(rfx_dir_to, script_name, NULL);
3777 
3778  if (lives_file_test(rfx_script_to, LIVES_FILE_TEST_EXISTS)) {
3779  char *msg = lives_strdup_printf(
3780  _("\nCustom script file:\n%s\nalready exists.\nPlease delete it first, or rename the test script.\n"),
3781  script_name);
3782  do_error_dialog(msg);
3783  lives_free(msg); lives_free(rfx_dir_from); lives_free(rfx_script_from);
3784  lives_free(rfx_dir_to); lives_free(rfx_script_to); lives_free(script_name);
3785  return;
3786  }
3787 
3788  d_print(_("Promoting rfx test plugin %s to custom..."), script_name);
3789  lives_free(script_name);
3790 
3791  lives_mkdir_with_parents(rfx_dir_to, capable->umask);
3792 
3793  if (!(ret = rename(rfx_script_from, rfx_script_to))) {
3794  d_print_done();
3795  on_rebuild_rfx_activate(NULL, LIVES_INT_TO_POINTER(RFX_STATUS_CUSTOM));
3796  on_rebuild_rfx_activate(NULL, LIVES_INT_TO_POINTER(RFX_STATUS_TEST));
3797  failed = FALSE;
3798  }
3799  }
3800 
3801  if (failed) {
3802  lives_rmdir(rfx_dir_to, FALSE);
3803  d_print_failed();
3804  msg = lives_strdup_printf(_("\n\nFailed to move the plugin script from\n%s to\n%s\nReturn code was %d (%s)\n"),
3805  rfx_script_from, rfx_script_to, errno, strerror(errno));
3807  do_error_dialog(msg);
3809  lives_free(msg);
3810  } else lives_rmdir(rfx_dir_from, FALSE);
3811 
3812  if (rfx_script_from) {
3813  lives_free(rfx_dir_from);
3814  lives_free(rfx_script_from);
3815  lives_free(rfx_dir_to);
3816  lives_free(rfx_script_to);
3817  }
3818 }
3819 
3820 
3821 void on_export_rfx_activate(LiVESMenuItem * menuitem, livespointer user_data) {
3822  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
3823 
3824  char *script_name = prompt_for_script_name(NULL, status);
3825  char *rfx_script_from, *filename;
3826  char *tmp, *tmp2;
3827 
3828  if (!script_name || !*script_name) return; // user cancelled
3829 
3830  filename = choose_file(NULL, script_name, NULL, LIVES_FILE_CHOOSER_ACTION_SAVE, _("Export Script"), NULL);
3831 
3832  if (!filename) return;
3833 
3834  rfx_script_from = lives_build_filename(prefs->config_datadir,
3835  PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS, script_name, NULL);
3836 
3837  d_print(_("Copying %s to %s..."), rfx_script_from, filename);
3838 
3839  lives_cp((tmp = lives_filename_from_utf8(rfx_script_from, -1, NULL, NULL, NULL)),
3840  (tmp2 = lives_filename_from_utf8(filename, -1, NULL, NULL, NULL)));
3841 
3842  if (THREADVAR(com_failed)) d_print_failed();
3843  else d_print_done();
3844  lives_free(tmp); lives_free(tmp2);
3845  lives_free(rfx_script_from); lives_free(filename); lives_free(script_name);
3846 }
3847 
3848 
3849 void on_import_rfx_activate(LiVESMenuItem * menuitem, livespointer user_data) {
3850  lives_rfx_status_t status = (lives_rfx_status_t)LIVES_POINTER_TO_INT(user_data);
3851 
3852  char *rfx_script_to, *rfx_dir_to;
3853  char *tmp, *tmp2, *tmpx;
3854  char basename[PATH_MAX];
3855 
3856  char *filename = choose_file(NULL, NULL, NULL, LIVES_FILE_CHOOSER_ACTION_OPEN, _("Import Script"), NULL);
3857 
3858  if (!filename) return;
3859 
3860  lives_snprintf(basename, PATH_MAX, "%s", filename);
3861  get_basename(basename);
3862 
3863  THREADVAR(com_failed) = FALSE;
3864 
3865  switch (status) {
3866  case RFX_STATUS_TEST:
3867  rfx_dir_to = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS, NULL);
3868  lives_mkdir_with_parents((tmp = lives_filename_from_utf8(rfx_dir_to, -1, NULL, NULL, NULL)), capable->umask);
3869  lives_free(tmp);
3870 
3871  rfx_script_to = lives_build_filename(rfx_dir_to, basename, NULL);
3872  lives_free(rfx_dir_to);
3873  break;
3874  case RFX_STATUS_CUSTOM:
3875  rfx_dir_to = lives_build_path(prefs->config_datadir, PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS, NULL);
3876  lives_mkdir_with_parents((tmp = lives_filename_from_utf8(rfx_dir_to, -1, NULL, NULL, NULL)), capable->umask);
3877 
3878  lives_free(tmp);
3879  rfx_script_to = lives_build_filename(rfx_dir_to, basename, NULL);
3880  lives_free(rfx_dir_to);
3881  break;
3882  default:
3883  rfx_script_to = lives_build_filename(prefs->prefix_dir, PLUGIN_SCRIPTS_DIR,
3884  PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS, basename, NULL);
3885  break;
3886  }
3887 
3888  if (THREADVAR(com_failed)) {
3889  lives_free(rfx_script_to);
3890  lives_free(filename);
3891  return;
3892  }
3893 
3894  if (lives_file_test(rfx_script_to, LIVES_FILE_TEST_EXISTS)) {
3895  // needs switch...eventually
3897  (_("\nCustom script file:\n%s\nalready exists.\n"
3898  "Please delete it first, or rename the import script.\n"), basename)));
3899  lives_free(tmpx); lives_free(rfx_script_to); lives_free(filename);
3900  return;
3901  }
3902 
3903  d_print(_("Copying %s to %s..."), filename, rfx_script_to);
3904 
3905  lives_cp((tmp = lives_filename_from_utf8(filename, -1, NULL, NULL, NULL)),
3906  (tmp2 = lives_filename_from_utf8(rfx_script_to, -1, NULL, NULL, NULL)));
3907 
3908  lives_free(tmp);
3909  lives_free(tmp2);
3910  if (THREADVAR(com_failed)) d_print_failed();
3911  else {
3912  d_print_done();
3913  on_rebuild_rfx_activate(NULL, LIVES_INT_TO_POINTER(status));
3914  }
3915  lives_free(rfx_script_to);
3916  lives_free(filename);
3917 }
3918 
3919 
3920 char *prompt_for_script_name(const char *sname, lives_rfx_status_t status) {
3921  // show dialog to get script name of rfx plugin dependant on type
3922  // set type to RFX_STATUS_ANY to let user pick type as well
3923  // return value should be lives_free'd after use
3924  // beware: if the user cancels, return value is NULL
3925 
3926  // sname is suggested name, set it to NULL to prompt for a name from
3927  // status list
3928 
3929  // in copy mode, there are extra entries and the selected script will be copied
3930  // to test
3931 
3932  // in rename mode a test script will be copied to another test script
3933 
3934  char *name = NULL;
3935  char *from_name;
3936  char *from_status;
3937  char *rfx_script_from;
3938  char *rfx_script_to;
3939 
3940  rfx_build_window_t *rfxbuilder;
3941 
3942  LiVESWidget *vbox;
3943  LiVESWidget *hbox;
3944  LiVESWidget *label;
3945  LiVESWidget *script_combo = NULL;
3946  LiVESWidget *name_entry = NULL;
3947  LiVESWidget *script_combo_entry = NULL;
3948  LiVESWidget *status_combo = NULL;
3949  LiVESWidget *status_combo_entry = NULL;
3950  LiVESWidget *dialog;
3951 
3952  LiVESList *status_list = NULL;
3953 
3954  boolean copy_mode = FALSE;
3955  boolean rename_mode = FALSE;
3956  boolean OK;
3957 
3958  if (status == RFX_STATUS_COPY) {
3959  copy_mode = TRUE;
3960  status_list = lives_list_append(status_list, lives_strdup(mainw->string_constants[LIVES_STRING_CONSTANT_BUILTIN]));
3961  status_list = lives_list_append(status_list, lives_strdup(mainw->string_constants[LIVES_STRING_CONSTANT_CUSTOM]));
3962  status_list = lives_list_append(status_list, lives_strdup(mainw->string_constants[LIVES_STRING_CONSTANT_TEST]));
3963  }
3964 
3965  dialog = lives_standard_dialog_new(NULL, FALSE, -1, -1);
3966 
3967  vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
3968 
3969  hbox = lives_hbox_new(FALSE, 0);
3970  lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
3971 
3972  vbox = lives_vbox_new(FALSE, 0);
3973  lives_box_pack_start(LIVES_BOX(hbox), vbox, FALSE, FALSE, widget_opts.packing_width);
3974 
3975  add_fill_to_box(LIVES_BOX(vbox));
3976 
3977  hbox = lives_hbox_new(FALSE, 0);
3978  lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
3979 
3980  add_fill_to_box(LIVES_BOX(vbox));
3981 
3982  if (copy_mode) {
3983  lives_window_set_title(LIVES_WINDOW(dialog), _("Copy RFX Script"));
3984 
3985  status_combo = lives_standard_combo_new(_("_From type: "), status_list, LIVES_BOX(hbox), NULL);
3986 
3987  status_combo_entry = lives_combo_get_entry(LIVES_COMBO(status_combo));
3988 
3989  lives_list_free_all(&status_list);
3990  } else {
3991  if (status == RFX_STATUS_RENAME) {
3992  lives_window_set_title(LIVES_WINDOW(dialog), _("Rename Test RFX Script"));
3993  label = lives_standard_label_new(_("From script: "));
3994  rename_mode = TRUE;
3995  status = RFX_STATUS_TEST;
3996  } else {
3997  lives_window_set_title(LIVES_WINDOW(dialog), _("RFX Script Name"));
3998  label = lives_standard_label_new(_("Script name: "));
3999  }
4000  lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, 0);
4001  }
4002 
4003  if (!sname || copy_mode || rename_mode) {
4004  script_combo = lives_standard_combo_new(copy_mode ? _("Script:") : NULL, NULL, LIVES_BOX(hbox), NULL);
4005  name_entry = script_combo_entry = lives_combo_get_entry(LIVES_COMBO(script_combo));
4006  }
4007  if (sname || copy_mode || rename_mode) {
4008  // name_entry becomes a normal lives_entry
4009  if (copy_mode || rename_mode) {
4010  hbox = lives_hbox_new(FALSE, 0);
4011  lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
4012  }
4013 
4014  name_entry = lives_standard_entry_new(copy_mode ? _("New name:") : rename_mode ? _("New script name:") : NULL,
4015  sname, -1, 128, LIVES_BOX(hbox), NULL);
4016 
4017  if (copy_mode) {
4018  lives_signal_sync_connect(LIVES_GUI_OBJECT(status_combo), LIVES_WIDGET_CHANGED_SIGNAL,
4019  LIVES_GUI_CALLBACK(on_script_status_changed), (livespointer)script_combo);
4020  }
4021  }
4022  lives_widget_grab_focus(name_entry);
4023  lives_entry_set_activates_default(LIVES_ENTRY(name_entry), TRUE);
4024 
4025  lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_CANCEL, NULL, LIVES_RESPONSE_CANCEL);
4026 
4027  copy_script_okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_OK, NULL, LIVES_RESPONSE_OK);
4028 
4029  lives_button_grab_default_special(copy_script_okbutton);
4030 
4031  lives_widget_show_all(dialog);
4032 
4033  if (status_combo) on_script_status_changed(LIVES_COMBO(status_combo), (livespointer)script_combo);
4034  else if (script_combo) populate_script_combo(LIVES_COMBO(script_combo), status);
4035 
4036  do {
4037  OK = TRUE;
4038  if (lives_dialog_run(LIVES_DIALOG(dialog)) == LIVES_RESPONSE_OK) {
4039  if (name) lives_free(name);
4040  name = lives_strdup(lives_entry_get_text(LIVES_ENTRY(name_entry)));
4041  if (copy_mode) {
4042  if (find_rfx_plugin_by_name(name, RFX_STATUS_TEST) > -1 ||
4045  do_error_dialog(_("\n\nThere is already a plugin with this name.\nName must be unique.\n"));
4046  OK = FALSE;
4047  }
4048  //copy selected script to test
4049  else {
4050  from_name = lives_strdup(lives_entry_get_text(LIVES_ENTRY(script_combo_entry)));
4051  from_status = lives_strdup(lives_entry_get_text(LIVES_ENTRY(status_combo_entry)));
4052  if (!strcmp(from_status, mainw->string_constants[LIVES_STRING_CONSTANT_BUILTIN])) status = RFX_STATUS_BUILTIN;
4053  else {
4054  if (!strcmp(from_status, mainw->string_constants[LIVES_STRING_CONSTANT_CUSTOM])) status = RFX_STATUS_CUSTOM;
4055  else status = RFX_STATUS_TEST;
4056  }
4057 
4058  if ((rfxbuilder = make_rfx_build_window(from_name, status)) == NULL) {
4059  // invalid name
4060  OK = FALSE;
4061  }
4062 
4063  lives_free(from_name);
4064  lives_free(from_status);
4065 
4066  if (OK) {
4067  lives_entry_set_text(LIVES_ENTRY(rfxbuilder->name_entry), name);
4068  rfxbuilder->mode = RFX_BUILDER_MODE_COPY;
4069  lives_widget_show(rfxbuilder->dialog);
4070  }
4071  }
4072  }
4073  if (rename_mode) {
4074  LiVESList *nmlist = NULL;
4075  char *xname = ensure_extension(name, LIVES_FILE_EXT_RFX_SCRIPT);
4076 
4077  if (name && lives_list_find((nmlist = get_script_list(status)), xname)) {
4078  do_error_dialog(_("\n\nThere is already a test script with this name.\nScript name must be unique.\n"));
4079  OK = FALSE;
4080  } else {
4081  int ret;
4082  from_name = lives_strdup(lives_entry_get_text(LIVES_ENTRY(script_combo_entry)));
4083  rfx_script_from = lives_build_filename(prefs->config_datadir,
4084  PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS, from_name, NULL);
4085  rfx_script_to = lives_build_filename(prefs->config_datadir,
4087  d_print(_("Renaming RFX test script %s to %s..."), from_name, xname);
4088  lives_free(from_name);
4089 
4090  if ((ret = rename(rfx_script_from, rfx_script_to))) {
4091  d_print_failed();
4093  do_error_dialogf(_("\n\nFailed to move the plugin script from\n%s to\n%s\n"
4094  "Return code was %d\n"),
4095  rfx_script_from, rfx_script_to, ret);
4097  } else {
4098  d_print_done();
4099  }
4100  lives_free(rfx_script_from);
4101  lives_free(rfx_script_to);
4102  }
4103  if (nmlist) {
4104  lives_list_free_all(&nmlist);
4105  }
4106  lives_free(xname);
4107  }
4108  }
4109  } while (!OK);
4110 
4111  lives_widget_destroy(dialog);
4112  return name;
4113 }
4114 
4115 
4116 static void populate_script_combo(LiVESCombo * script_combo, lives_rfx_status_t status) {
4117  LiVESList *list = NULL;
4118  lives_combo_populate(script_combo, (list = get_script_list(status)));
4119  if (list) {
4120  lives_combo_set_active_index(script_combo, 0);
4121  lives_widget_set_sensitive(copy_script_okbutton, TRUE);
4122  lives_list_free_all(&list);
4123  } else {
4124  lives_combo_set_active_string(script_combo, "");
4125  lives_widget_set_sensitive(copy_script_okbutton, FALSE);
4126  }
4127 }
4128 
4129 
4130 static void on_script_status_changed(LiVESCombo * status_combo, livespointer user_data) {
4131  const char *text = lives_combo_get_active_text(status_combo);
4132  LiVESWidget *script_combo = (LiVESWidget *)user_data;
4133 
4134  if (!script_combo || !LIVES_IS_COMBO(script_combo)) return;
4135 
4136  if (!(strcmp(text, mainw->string_constants[LIVES_STRING_CONSTANT_BUILTIN]))) {
4137  populate_script_combo(LIVES_COMBO(script_combo), RFX_STATUS_BUILTIN);
4138  } else {
4139  if (!(strcmp(text, mainw->string_constants[LIVES_STRING_CONSTANT_CUSTOM]))) {
4140  populate_script_combo(LIVES_COMBO(script_combo), RFX_STATUS_CUSTOM);
4141  } else {
4142  if (!(strcmp(text, mainw->string_constants[LIVES_STRING_CONSTANT_TEST]))) {
4143  populate_script_combo(LIVES_COMBO(script_combo), RFX_STATUS_TEST);
4144  }
4145  }
4146  }
4147 }
4148 
4149 
4151  LiVESList *script_list = NULL;
4152 
4153  switch (status) {
4154  case RFX_STATUS_TEST:
4156  break;
4157  case RFX_STATUS_CUSTOM:
4159  break;
4160  case RFX_STATUS_BUILTIN:
4161  case RFX_STATUS_COPY:
4163  break;
4164  default:
4165  break;
4166  }
4167  return script_list;
4168 }
4169 
4170 static int rfx_slot_count = 0;
4171 
4173  // scan render plugin directories, create a rfx array, and add each to the appropriate menu area
4174  LiVESList *rfx_builtin_list = NULL, *rfx_custom_list = NULL, *rfx_test_list = NULL;
4175 
4176  lives_rfx_t *rfx = NULL;
4177  lives_rfx_t *rendered_fx;
4178 
4179 #if LIVES_HAS_IMAGE_MENU_ITEM
4180  LiVESWidget *rfx_image;
4181 #endif
4182  int i, plugin_idx;
4183 
4184  int rfx_builtin_list_length, rfx_custom_list_length, rfx_test_list_length;
4185  int rfx_list_length, old_list_length;
4186 
4187  // reset / reload values
4188  if (status == RFX_STATUS_ANY)
4190  if (status != RFX_STATUS_TEST)
4192  if (status != RFX_STATUS_CUSTOM)
4194 
4195  rfx_builtin_list_length = mainw->num_rendered_effects_builtin;
4196  rfx_custom_list_length = mainw->num_rendered_effects_custom;
4197  rfx_test_list_length = mainw->num_rendered_effects_test;
4198 
4199  old_list_length = rfx_builtin_list_length + rfx_custom_list_length + rfx_test_list_length;
4200 
4201  if (status != RFX_STATUS_TEST) {
4203  }
4204 
4205  if (status != RFX_STATUS_ANY) {
4207  + mainw->num_rendered_effects_test; i++) {
4208  if (mainw->rendered_fx[i].status == status) {
4209  if (mainw->rendered_fx[i].menuitem) {
4211  mainw->rendered_fx[i].menuitem = NULL;
4212  }
4213  }
4214  }
4216  }
4217 
4218  if (status == RFX_STATUS_CUSTOM) {
4225 
4231 
4237  }
4238 
4239  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4240 
4241  // reset / reload values
4242  if (status == RFX_STATUS_ANY)
4244  if (status != RFX_STATUS_TEST)
4246  if (status != RFX_STATUS_CUSTOM)
4248 
4249  //if (status != RFX_STATUS_TEST) make_custom_submenus();
4250 
4251  if (status != RFX_STATUS_CUSTOM) {
4252  //mainw->run_test_rfx_menu = lives_standard_menu_new();
4253  rfx_test_list = get_plugin_list(PLUGIN_RENDERED_EFFECTS_TEST, FALSE, NULL, NULL);
4254  rfx_test_list_length = lives_list_length(rfx_test_list);
4255  }
4256 
4257  if (status != RFX_STATUS_TEST) {
4258  rfx_custom_list = get_plugin_list(PLUGIN_RENDERED_EFFECTS_CUSTOM, FALSE, NULL, NULL);
4259  rfx_custom_list_length = lives_list_length(rfx_custom_list);
4260  }
4261 
4262  if (prefs->load_rfx_builtin) {
4263  if (status == RFX_STATUS_ANY) {
4264  if (!(rfx_builtin_list = get_plugin_list(PLUGIN_RENDERED_EFFECTS_BUILTIN, FALSE, NULL, NULL))) {
4266  } else {
4267  rfx_builtin_list_length = lives_list_length(rfx_builtin_list);
4268  }
4269  }
4270  }
4271 
4272  rfx_list_length = rfx_builtin_list_length + rfx_custom_list_length + rfx_test_list_length;
4273 
4274  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4275 
4276  rendered_fx = (lives_rfx_t *)lives_calloc((rfx_list_length + 1), sizeof(lives_rfx_t));
4277 
4278  if (status != RFX_STATUS_ANY) {
4279  // add others to rendered_fx
4280  for (i = 0; i <= old_list_length; i++) {
4281  if (mainw->rendered_fx[i].status != status) {
4282  rfx_copy(&rendered_fx[rfx_slot_count++], &mainw->rendered_fx[i], FALSE);
4283  }
4284  }
4286  mainw->rendered_fx = NULL;
4287  } else {
4288  rendered_fx[0].name = lives_strdup("realtime_fx");
4289  rendered_fx[0].menu_text = (_("_Apply Real Time Effects to Selection"));
4290  rendered_fx[0].action_desc = (_("Applying Current Real Time Effects to"));
4291 
4292  rendered_fx[0].props = 0;
4293  rendered_fx[0].rfx_version[0] = 0;
4294  rendered_fx[0].num_params = 0;
4295  rendered_fx[0].num_in_channels = 1;
4296  rendered_fx[0].menuitem = NULL;
4297  rendered_fx[0].params = NULL;
4298  rendered_fx[0].flags = 0;
4299  rendered_fx[0].gui_strings = NULL;
4300  rendered_fx[0].onchange_strings = NULL;
4301  rendered_fx[0].status = RFX_STATUS_WEED;
4302  rendered_fx[0].is_template = FALSE;
4303  rendered_fx[0].min_frames = 1;
4304  rendered_fx[0].source = NULL;
4305  rendered_fx[0].source_type = LIVES_RFX_SOURCE_RFX;
4306  rfx_slot_count = 1;
4307  }
4308 
4309  if (rfx_list_length) {
4310  LiVESList *define = NULL;
4311  LiVESList *description = NULL;
4312  LiVESList *props = NULL;
4313  LiVESList *rfx_list = rfx_builtin_list;
4314 
4316 
4317  char *type = lives_strdup(PLUGIN_RENDERED_EFFECTS_BUILTIN);
4318  char *plugin_name;
4319  char *def = NULL;
4320  char delim[2];
4321 
4322  int offset = 0;
4323 
4324  for (plugin_idx = 0; plugin_idx < rfx_list_length; plugin_idx++) {
4325  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4326 #ifndef BG_LOAD
4328 #endif
4329  if (plugin_idx == rfx_builtin_list_length) {
4330  lives_free(type);
4331  type = lives_strdup(PLUGIN_RENDERED_EFFECTS_CUSTOM);
4332  xstatus = RFX_STATUS_CUSTOM;
4333  rfx_list = rfx_custom_list;
4334  offset = rfx_builtin_list_length;
4335  }
4336  if (plugin_idx == rfx_builtin_list_length + rfx_custom_list_length) {
4337  lives_free(type);
4338  type = lives_strdup(PLUGIN_RENDERED_EFFECTS_TEST);
4339  xstatus = RFX_STATUS_TEST;
4340  rfx_list = rfx_test_list;
4341  offset += rfx_custom_list_length;
4342  }
4343 
4344  if (status != RFX_STATUS_ANY && xstatus != status) continue;
4345 
4346  plugin_name = lives_strdup((char *)lives_list_nth_data(rfx_list, plugin_idx - offset));
4347 
4348 #ifndef BG_LOAD
4349  if (mainw->splash_window) {
4350  splash_msg((tmp = lives_strdup_printf(_("Loading rendered effect %s..."), plugin_name)), SPLASH_LEVEL_LOAD_RFX);
4351  lives_free(tmp);
4352  }
4353 #endif
4354 
4355 #ifdef DEBUG_RENDER_FX
4356  g_print("Checking plugin %s\n", plugin_name);
4357 #endif
4358 
4359  if ((define = plugin_request_by_line(type, plugin_name, "get_define")) == NULL) {
4360 #ifdef DEBUG_RENDER_FX
4361  g_print("No get_define in %s\n", plugin_name);
4362 #endif
4363  lives_free(plugin_name);
4364  continue;
4365  }
4366 
4367  def = lives_strdup((char *)lives_list_nth_data(define, 0));
4368  lives_list_free_all(&define);
4369 
4370  if (strlen(def) < 2) {
4371 #ifdef DEBUG_RENDER_FX
4372  g_print("Invalid get_define in %s\n", plugin_name);
4373 #endif
4374  lives_free(plugin_name);
4375  lives_free(def);
4376  continue;
4377  }
4379 #ifdef DEBUG_RENDER_FX
4380  g_print("Invalid version %s instead of %s in %s\n", def + 1, RFX_VERSION, plugin_name);
4381 #endif
4382  lives_free(plugin_name);
4383  lives_free(def);
4384  continue;
4385  }
4386 
4387  delim[0] = def[0];
4388  delim[1] = 0;
4389 
4390  if ((description = plugin_request_common(type, plugin_name, "get_description", delim, TRUE)) &&
4391  (props = plugin_request_common(type, plugin_name, "get_capabilities", delim, FALSE)) &&
4392  lives_list_length(description) > 3) {
4393  rfx = &rendered_fx[rfx_slot_count++];
4394  rfx->name = lives_strdup(plugin_name);
4395  lives_memcpy(rfx->delim, delim, 2);
4396  rfx->menu_text = lives_strdup((char *)lives_list_nth_data(description, 0));
4397  rfx->action_desc = lives_strdup((char *)lives_list_nth_data(description, 1));
4398  if (!(rfx->min_frames = atoi((char *)lives_list_nth_data(description, 2)))) rfx->min_frames = 1;
4399  rfx->num_in_channels = atoi((char *)lives_list_nth_data(description, 3));
4400  rfx->status = xstatus;
4401  lives_snprintf(rfx->rfx_version, 64, "%s", def + 1);
4402  rfx->props = atoi((char *)lives_list_nth_data(props, 0));
4403  rfx->num_params = 0;
4404  rfx->is_template = FALSE;
4405  rfx->params = NULL;
4406  rfx->source = NULL;
4408  rfx->flags = 0;
4409  rfx->gui_strings = NULL;
4410  rfx->onchange_strings = NULL;
4411  rfx->is_template = FALSE;
4412  if (!check_rfx_for_lives(rfx)) rfx_slot_count--;
4413  }
4414 
4415  lives_free(plugin_name);
4416  if (props) {
4417  lives_list_free_all(&props);
4418  props = NULL;
4419  }
4420  if (description) {
4421  lives_list_free_all(&description);
4422  description = NULL;
4423  }
4424  lives_free(def);
4425  }
4426 
4427  if (rfx_builtin_list) lives_list_free_all(&rfx_builtin_list);
4428  if (rfx_custom_list) lives_list_free_all(&rfx_custom_list);
4429  if (rfx_test_list) lives_list_free_all(&rfx_test_list);
4430 
4431  lives_free(type);
4432  }
4433 
4434  lives_freep((void **)&mainw->rendered_fx);
4435 
4436  rfx_slot_count--;
4437 
4438  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4439 
4440  // sort menu text by alpha order (apart from [0]) and create mainw->rendered_fx
4441  sort_rfx_array(rendered_fx, rfx_slot_count); // each rendered_fx is copied and free()d
4442  lives_free(rendered_fx);
4443 
4444  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4445 
4446  // now we need to add to the effects menu and set a callback
4447  for (rfx = &mainw->rendered_fx[(plugin_idx = 1)]; plugin_idx <= rfx_slot_count; rfx = &mainw->rendered_fx[++plugin_idx]) {
4448  if (status != RFX_STATUS_ANY && rfx->status != status) continue;
4449 
4450  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4451 
4452  render_fx_get_params(rfx, rfx->name, rfx->status);
4453  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4454  rfx->source = NULL;
4455  rfx->flags = 0;
4456  rfx->gui_strings = NULL;
4457  rfx->onchange_strings = NULL;
4458  rfx->menuitem = NULL;
4459 
4460  switch (rfx->status) {
4461  case RFX_STATUS_BUILTIN:
4463  case RFX_STATUS_CUSTOM:
4465  case RFX_STATUS_TEST:
4466  mainw->num_rendered_effects_test++; break;
4467  default: break;
4468  }
4469  }
4470 
4471  if (status != RFX_STATUS_ANY) {
4475  add_rfx_effects2(status);
4476  }
4477  }
4478 }
4479 
4480 
4482  LiVESWidget *menuitem;
4483  lives_rfx_t *rfx;
4484  char txt[64]; // menu text
4485  int plugin_idx, tool_posn = RFX_TOOL_MENU_POSN;
4486 
4487  if (status == RFX_STATUS_ANY) {
4488  // recreate effects menu
4490 
4491  lives_widget_set_sensitive(menuitem, FALSE);
4492  lives_widget_set_tooltip_text(menuitem, _("See: VJ - show VJ keys. Set the realtime effects, and then apply them here."));
4493 
4494  lives_widget_add_accelerator(menuitem, LIVES_WIDGET_ACTIVATE_SIGNAL, mainw->accel_group,
4495  LIVES_KEY_e, LIVES_CONTROL_MASK, LIVES_ACCEL_VISIBLE);
4496 
4497  lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4498  LIVES_GUI_CALLBACK(on_realfx_activate), &mainw->rendered_fx[0]);
4499 
4500  mainw->rendered_fx[0].menuitem = menuitem;
4502 
4503  if (!LIVES_IS_PLAYING && mainw->current_file > 0 &&
4505  (cfile->achans > 0 && prefs->audio_src == AUDIO_SRC_INT && has_audio_filters(AF_TYPE_ANY)) ||
4506  mainw->agen_key != 0)) {
4507  lives_widget_set_sensitive(menuitem, TRUE);
4508  } else lives_widget_set_sensitive(menuitem, FALSE);
4509  }
4510 
4514  }
4515 
4516  if (status != RFX_STATUS_TEST) make_custom_submenus();
4517 
4518  if (status == RFX_STATUS_TEST && mainw->run_test_rfx_menu) {
4519  lives_menu_item_set_submenu(LIVES_MENU_ITEM(mainw->run_test_rfx_submenu), NULL);
4521  }
4522 
4523  if (status != RFX_STATUS_TEST) {
4526 
4529  }
4530 
4531  if (status == RFX_STATUS_ANY && mainw->rendered_fx[0].menuitem) {
4534  }
4535 
4536  if (status != RFX_STATUS_TEST) {
4541  }
4542 
4543  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4544 
4545  if (status != RFX_STATUS_TEST) {
4546  // recreate menus for effects, utilities, generators
4549 
4552 
4555 
4557  if (!mainw->multitrack)
4559  else
4560  lives_menu_item_set_submenu(LIVES_MENU_ITEM(mainw->multitrack->gens_submenu), mainw->gens_menu);
4561 
4565 
4566  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4567 
4569  }
4570 
4571  if (rfx_slot_count) {
4572  for (rfx = &mainw->rendered_fx[(plugin_idx = 1)]; plugin_idx <= rfx_slot_count; rfx = &mainw->rendered_fx[++plugin_idx]) {
4573  if (rfx->status == RFX_STATUS_TEST) {
4574  if (status == RFX_STATUS_CUSTOM) continue;
4575  } else if (status == RFX_STATUS_TEST) continue;
4576 
4577  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4578 
4579  lives_snprintf(txt, 61, "_%s", _(rfx->menu_text));
4580  if (rfx->num_params) lives_strappend(txt, 64, "...");
4582  rfx->menuitem = menuitem;
4583 
4584  if ((rfx->props & RFX_PROPS_MAY_RESIZE && rfx->num_in_channels == 1) || rfx->min_frames < 0) {
4585  // add resizing effects to tools menu
4586  if (!strcmp(rfx->name, "resize")) {
4588  mainw->resize_menuitem = menuitem;
4589  } else continue;
4590  }
4591 
4592  switch (rfx->status) {
4593  case RFX_STATUS_BUILTIN:
4594  if (rfx->min_frames >= 0) {
4595  if (status == RFX_STATUS_CUSTOM) continue;
4596  lives_menu_shell_insert(LIVES_MENU_SHELL(mainw->tools_menu), menuitem, tool_posn++);
4597  } else {
4598  lives_container_add(LIVES_CONTAINER(mainw->utilities_menu), menuitem);
4599  }
4600  break;
4601  case RFX_STATUS_CUSTOM:
4602  if (rfx->min_frames >= 0) {
4603  lives_container_add(LIVES_CONTAINER(mainw->custom_tools_menu), menuitem);
4605  } else {
4606  lives_container_add(LIVES_CONTAINER(mainw->custom_utilities_menu), menuitem);
4608  }
4609  break;
4610  case RFX_STATUS_TEST:
4611  lives_container_add(LIVES_CONTAINER(mainw->run_test_rfx_menu), menuitem);
4612  break;
4613  default:
4614  break;
4615  }
4616 
4617  if (menuitem != mainw->resize_menuitem) {
4618  if (!rfx->params) {
4619  lives_signal_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4620  LIVES_GUI_CALLBACK(on_render_fx_activate), (livespointer)rfx);
4621  } else {
4622  lives_signal_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4623  LIVES_GUI_CALLBACK(on_render_fx_pre_activate), (livespointer)rfx);
4624  }
4625  } else {
4627  = lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4628  LIVES_GUI_CALLBACK(on_render_fx_pre_activate), (livespointer)rfx);
4629  }
4630 
4631  if (rfx->min_frames >= 0) lives_widget_set_sensitive(menuitem, FALSE);
4632  } else {
4633  if (rfx->num_in_channels == 0) {
4634  // non-realtime generator
4635  switch (rfx->status) {
4636  case RFX_STATUS_BUILTIN:
4637  lives_container_add(LIVES_CONTAINER(mainw->gens_menu), menuitem); break;
4638  case RFX_STATUS_CUSTOM:
4639  lives_container_add(LIVES_CONTAINER(mainw->custom_gens_menu), menuitem);
4640  mainw->has_custom_gens = TRUE; break;
4641  case RFX_STATUS_TEST:
4642  lives_container_add(LIVES_CONTAINER(mainw->run_test_rfx_menu), menuitem); break;
4643  default: break;
4644  }
4645  lives_signal_sync_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4646  LIVES_GUI_CALLBACK(on_render_fx_pre_activate), (livespointer)rfx);
4647  } else {
4648 #if LIVES_HAS_IMAGE_MENU_ITEM
4649  rfx_image = NULL;
4650  if (rfx->props & RFX_PROPS_SLOW) {
4651  rfx_image = lives_image_new_from_stock(LIVES_STOCK_NO, LIVES_ICON_SIZE_MENU);
4652  } else {
4653  rfx_image = lives_image_new_from_stock(LIVES_STOCK_YES, LIVES_ICON_SIZE_MENU);
4654  }
4655  lives_image_menu_item_set_image(LIVES_IMAGE_MENU_ITEM(menuitem), rfx_image);
4656 #endif
4657  if (rfx->num_in_channels == 1) {
4658  lives_container_add(LIVES_CONTAINER(mainw->effects_menu), menuitem);
4659  }
4660  if (!rfx->params) {
4661  lives_signal_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4662  LIVES_GUI_CALLBACK(on_render_fx_activate), (livespointer)rfx);
4663  } else {
4664  lives_signal_connect(LIVES_GUI_OBJECT(menuitem), LIVES_WIDGET_ACTIVATE_SIGNAL,
4665  LIVES_GUI_CALLBACK(on_render_fx_pre_activate), (livespointer)rfx);
4666  }
4667  if (rfx->min_frames >= 0) lives_widget_set_sensitive(menuitem, FALSE);
4668  // *INDENT-OFF*
4669  }}}}
4670  // *INDENT-ON*
4671 
4672  if (status != RFX_STATUS_ANY) threaded_dialog_spin(0.);
4673 
4674  update_rfx_menus();
4675 
4676  if (status != RFX_STATUS_ANY) {
4680  }
4681 }
4682 
4683 
4684 void update_rfx_menus(void) {
4685  if (prefs->show_gui) {
4686  if (!mainw->has_custom_effects) {
4689  } else {
4693  }
4694 
4695  if (mainw->has_custom_tools) {
4697  } else {
4700  }
4701 
4702  if (mainw->has_custom_utilities) {
4704  }
4705 
4707 
4708  if (!mainw->has_custom_utilities) {
4710  }
4711 
4712  if (!mainw->has_custom_tools) {
4714  }
4715 
4716  if (mainw->has_custom_gens) {
4718  }
4720  if (mainw->multitrack) lives_widget_show_all(mainw->multitrack->gens_submenu);
4721  }
4722 
4726  } else {
4729  }
4730 
4731  if (mainw->num_rendered_effects_test > 0) {
4738  } else {
4744  }
4746 }
4747 
lives_freep
boolean lives_freep(void **ptr)
Definition: utils.c:1411
widget_opts_t::packing_width
int packing_width
horizontal pixels between widgets
Definition: widget-helper.h:1410
RFX_PROPS_SLOW
#define RFX_PROPS_SLOW
hint to GUI
Definition: plugins.h:634
mainwindow::custom_effects_submenu
LiVESWidget * custom_effects_submenu
Definition: mainwindow.h:1418
rfx_build_window_t::spinbutton_param_max
LiVESWidget * spinbutton_param_max
Definition: rfx-builder.h:163
rfx_build_window_t::param_window_button
LiVESWidget * param_window_button
Definition: rfx-builder.h:118
lives_spin_button_set_range
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_range(LiVESSpinButton *button, double min, double max)
Definition: widget-helper.c:5129
on_rebuild_rfx_activate
void on_rebuild_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
parse text and return non empty lines between <section> and </section>
Definition: rfx-builder.c:3631
lives_text_view_get_text
char * lives_text_view_get_text(LiVESTextView *textview)
Definition: widget-helper.c:11706
RFX_CODE_TYPE_LOOP
@ RFX_CODE_TYPE_LOOP
Definition: rfx-builder.h:83
LIVES_IS_PLAYING
#define LIVES_IS_PLAYING
Definition: main.h:840
widget_opts_t::transient
LiVESWindow * transient
transient window for dialogs, if NULL then use the default (READ / WRITE)
Definition: widget-helper.h:1423
get_plugin_list
LiVESList * get_plugin_list(const char *plugin_type, boolean allow_nonex, const char *plugdir, const char *filter_ext)
Definition: plugins.c:115
lives_signal_connect
ulong lives_signal_connect(LiVESWidget *, const char *signal_name, ulong funcptr, livespointer data)
RFX_BUILD_TYPE_EFFECT0
@ RFX_BUILD_TYPE_EFFECT0
Definition: rfx-builder.h:69
lives_combo_set_active_string
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_string(LiVESCombo *combo, const char *active_str)
Definition: widget-helper.c:12290
on_new_rfx_activate
void on_new_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:62
on_promote_rfx_activate
void on_promote_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:3759
rfx_build_window_t::max_spin_f
ulong max_spin_f
Definition: rfx-builder.h:211
rfx_build_window_t::copy_params
lives_param_t * copy_params
store our parameters while editing
Definition: rfx-builder.h:185
lives_param_t::transition
boolean transition
Definition: plugins.h:564
lives_dialog_add_button_from_stock
LiVESWidget * lives_dialog_add_button_from_stock(LiVESDialog *dialog, const char *stock_id, const char *label, int response_id)
Definition: widget-helper.c:9892
PLUGIN_RENDERED_EFFECTS_TEST
#define PLUGIN_RENDERED_EFFECTS_TEST
Definition: plugins.h:473
lives_colRGB48_t::red
uint16_t red
Definition: main.h:317
get_script_list
LiVESList * get_script_list(lives_rfx_status_t status)
Definition: rfx-builder.c:4150
_palette::normal_back
LiVESWidgetColor normal_back
Definition: mainwindow.h:324
PLUGIN_RENDERED_EFFECTS_BUILTIN
#define PLUGIN_RENDERED_EFFECTS_BUILTIN
external rendered fx plugins (RFX plugins)
Definition: plugins.h:469
PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS
#define PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS
rfx scripts for the SDK
Definition: plugins.h:476
lives_list_strcmp_index
int lives_list_strcmp_index(LiVESList *list, livesconstpointer data, boolean case_sensitive)
Definition: utils.c:4678
lives_free
#define lives_free
Definition: machinestate.h:52
RFX_WINSIZE_V
#define RFX_WINSIZE_V
Definition: mainwindow.h:177
PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS
#define PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS
Definition: plugins.h:480
rfx_build_window_t::trigger_button
LiVESWidget * trigger_button
Definition: rfx-builder.h:122
lives_rfx_t::is_template
boolean is_template
Definition: plugins.h:656
rfx_build_window_t::spinbutton_param_min
LiVESWidget * spinbutton_param_min
Definition: rfx-builder.h:162
rfx_trigger_t::code
char * code
Definition: rfx-builder.h:63
lives_widget_add_accelerator
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)
Definition: widget-helper.c:2953
RFX_STATUS_RENAME
@ RFX_STATUS_RENAME
indicates a copy operation to test
Definition: plugins.h:622
plugin_request_by_line
LIVES_GLOBAL_INLINE LiVESList * plugin_request_by_line(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:59
on_rename_rfx_activate
void on_rename_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:109
rfx_build_window_t::paramw_kw_combo
LiVESWidget * paramw_kw_combo
Definition: rfx-builder.h:151
rfx_build_window_t::loop_code
char * loop_code
Definition: rfx-builder.h:175
mainwindow::promote_test_rfx
LiVESWidget * promote_test_rfx
for future use
Definition: mainwindow.h:1251
lives_malloc
#define lives_malloc
Definition: machinestate.h:46
choose_file
char * choose_file(const char *dir, const char *fname, char **const filt, LiVESFileChooserAction act, const char *title, LiVESWidget *extra_widget)
Definition: interface.c:4080
find_rfx_plugin_by_name
int find_rfx_plugin_by_name(const char *name, short status)
Definition: plugins.c:3177
add_rfx_effects
void add_rfx_effects(lives_rfx_status_t status)
add dynamic menu entries
Definition: rfx-builder.c:4172
lives_window_set_title
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_title(LiVESWindow *window, const char *title)
Definition: widget-helper.c:2620
has_audio_filters
boolean has_audio_filters(lives_af_t af_type)
Definition: effects-weed.c:3859
rfx_build_window_t::copy_triggers
rfx_trigger_t * copy_triggers
store triggers while editing
Definition: rfx-builder.h:194
RFX_CODE_TYPE_STRDEF
@ RFX_CODE_TYPE_STRDEF
Definition: rfx-builder.h:85
mainwindow::rte_separator
LiVESWidget * rte_separator
Definition: mainwindow.h:1428
lives_10pow
uint64_t lives_10pow(int pow) GNU_CONST
Definition: utils.c:1438
lives_widget_destroy
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
Definition: widget-helper.c:1553
SCR_HEIGHT_SAFETY
#define SCR_HEIGHT_SAFETY
Definition: mainwindow.h:90
lives_widget_grab_focus
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_grab_focus(LiVESWidget *widget)
Definition: widget-helper.c:4712
lives_standard_button_new_with_label
#define lives_standard_button_new_with_label(l, w, h)
Definition: widget-helper.h:1043
lives_standard_spin_button_new
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)
Definition: widget-helper.c:9397
lives_widget_get_state
WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetState lives_widget_get_state(LiVESWidget *widget)
Definition: widget-helper.c:5498
mainwindow::custom_effects_menu
LiVESWidget * custom_effects_menu
Definition: mainwindow.h:1417
lives_spin_button_set_value
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_value(LiVESSpinButton *button, double value)
Definition: widget-helper.c:5119
version
const char * version(void)
lives_spin_button_get_value_as_int
WIDGET_HELPER_GLOBAL_INLINE int lives_spin_button_get_value_as_int(LiVESSpinButton *button)
Definition: widget-helper.c:5091
lives_dialog_get_content_area
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_dialog_get_content_area(LiVESDialog *dialog)
Definition: widget-helper.c:2479
_prefs::show_gui
boolean show_gui
Definition: preferences.h:290
rfx_build_window_t::type_utility_radiobutton
LiVESWidget * type_utility_radiobutton
Definition: rfx-builder.h:112
lives_param_t::onchange
boolean onchange
is there a trigger ?
Definition: plugins.h:595
rfx_build_window_t::remove_entry_button
LiVESWidget * remove_entry_button
Definition: rfx-builder.h:168
lives_menu_item_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_menu_item_new(void)
Definition: widget-helper.c:6389
mainwindow::current_file
int current_file
Definition: mainwindow.h:727
lives_event_box_set_above_child
WIDGET_HELPER_GLOBAL_INLINE boolean lives_event_box_set_above_child(LiVESEventBox *ebox, boolean set)
Definition: widget-helper.c:2296
mainwindow::splash_window
LiVESWidget * splash_window
splash window
Definition: mainwindow.h:1595
lives_cp
int lives_cp(const char *from, const char *to)
Definition: utils.c:4414
lives_rfx_t::status
lives_rfx_status_t status
Definition: plugins.h:631
rfx_build_window_t::type_effect0_radiobutton
LiVESWidget * type_effect0_radiobutton
Definition: rfx-builder.h:110
rfx_build_window_t::param_name_entry
LiVESWidget * param_name_entry
Definition: rfx-builder.h:138
get_script_section
LiVESList * get_script_section(const char *section, const char *file, boolean strip)
Definition: rfx-builder.c:3611
LIVES_PARAM_STRING
@ LIVES_PARAM_STRING
Definition: plugins.h:505
LIVES_EXPAND_EXTRA
#define LIVES_EXPAND_EXTRA
Definition: widget-helper.h:1317
_palette::style
int style
Definition: mainwindow.h:297
lives_realloc
#define lives_realloc
Definition: machinestate.h:49
cfile
#define cfile
Definition: main.h:1833
lives_widget_hide
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_hide(LiVESWidget *widget)
Definition: widget-helper.c:1514
RFX_WINSIZE_H
#define RFX_WINSIZE_H
size of the fx dialog windows scrollwindow
Definition: mainwindow.h:175
effects.h
RFX_BUILDER_MODE_EDIT
@ RFX_BUILDER_MODE_EDIT
Definition: rfx-builder.h:91
RFX_DEF_NUM_MAX
#define RFX_DEF_NUM_MAX
default param max when not defined
Definition: paramwindow.h:17
lives_label_set_mnemonic_widget
WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_mnemonic_widget(LiVESLabel *label, LiVESWidget *widget)
Definition: widget-helper.c:6086
lives_table_attach
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_attach(LiVESTable *table, LiVESWidget *child, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom, LiVESAttachOptions xoptions, LiVESAttachOptions yoptions, uint32_t xpad, uint32_t ypad)
Definition: widget-helper.c:7035
lives_rfx_t::name
char * name
the name of the executable (so we can run it !)
Definition: plugins.h:626
lives_rfx_t::action_desc
char * action_desc
for Weed "Applying $s"
Definition: plugins.h:628
lives_widget_reparent
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_reparent(LiVESWidget *widget, LiVESWidget *new_parent)
Definition: widget-helper.c:1721
get_colRGB24_param
void get_colRGB24_param(void *value, lives_colRGB48_t *rgb)
Definition: plugins.c:3093
_palette::normal_fore
LiVESWidgetColor normal_fore
Definition: mainwindow.h:325
set_bool_param
void set_bool_param(void *value, boolean _const)
Definition: plugins.c:3103
lives_rfx_t::params
lives_param_t * params
Definition: plugins.h:649
lives_label_set_text
WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_text(LiVESLabel *label, const char *text)
Definition: widget-helper.c:6064
lives_standard_dialog_new
LiVESWidget * lives_standard_dialog_new(const char *title, boolean add_std_buttons, int width, int height)
Definition: widget-helper.c:9971
rfx_build_window_t::param_strdef_button
LiVESWidget * param_strdef_button
Definition: rfx-builder.h:156
RFX_BUILD_TYPE_UTILITY
@ RFX_BUILD_TYPE_UTILITY
Definition: rfx-builder.h:71
rfx_build_window_t::table_rows
int table_rows
Definition: rfx-builder.h:130
prefs
_prefs * prefs
Definition: preferences.h:847
rfx_build_window_t::param_label_entry
LiVESWidget * param_label_entry
Definition: rfx-builder.h:139
rfx_build_window_t::spinbutton_param_dp
LiVESWidget * spinbutton_param_dp
Definition: rfx-builder.h:159
mainwindow::custom_effects_separator
LiVESWidget * custom_effects_separator
Definition: mainwindow.h:1419
lives_dialog_run
WIDGET_HELPER_GLOBAL_INLINE LiVESResponseType lives_dialog_run(LiVESDialog *dialog)
Definition: widget-helper.c:1783
set_int_param
void set_int_param(void *value, int _const)
Definition: plugins.c:3114
rfx_build_window_t::properties_button
LiVESWidget * properties_button
Definition: rfx-builder.h:116
rfx_build_window_t::spinbutton_param_group
LiVESWidget * spinbutton_param_group
Definition: rfx-builder.h:160
LIVES_PARAM_COLRGB24
@ LIVES_PARAM_COLRGB24
Definition: plugins.h:504
DEF_DIALOG_WIDTH
#define DEF_DIALOG_WIDTH
Definition: mainwindow.h:185
mainwindow::num_rendered_effects_builtin
int num_rendered_effects_builtin
Definition: mainwindow.h:856
on_edit_rfx_activate
void on_edit_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:71
lives_rfx_t::menu_text
char * menu_text
for Weed, this is the filter_class "name"
Definition: plugins.h:627
DEF_DIALOG_HEIGHT
#define DEF_DIALOG_HEIGHT
Definition: mainwindow.h:186
lives_layout_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_new(LiVESBox *box)
Definition: widget-helper.c:7732
RFX_BUILDER_MODE_COPY
@ RFX_BUILDER_MODE_COPY
Definition: rfx-builder.h:92
lives_text_view_get_buffer
WIDGET_HELPER_GLOBAL_INLINE LiVESTextBuffer * lives_text_view_get_buffer(LiVESTextView *tview)
Definition: widget-helper.c:3950
rfx_build_window_t
Definition: rfx-builder.h:95
rfx_build_window_t::script_name
char * script_name
Definition: rfx-builder.h:207
add_hsep_to_box
LiVESWidget * add_hsep_to_box(LiVESBox *box)
Definition: widget-helper.c:12355
rfx_build_window_t::post_button
LiVESWidget * post_button
Definition: rfx-builder.h:121
sensitize_rfx
void sensitize_rfx(void)
Definition: main.c:5036
rfx_build_window_t::oname
char * oname
Definition: rfx-builder.h:208
rfx_build_window_t::paramw_rest_entry
LiVESWidget * paramw_rest_entry
Definition: rfx-builder.h:150
_palette::menu_and_bars_fore
LiVESWidgetColor menu_and_bars_fore
Definition: mainwindow.h:328
lives_fx_cat_to_text
char * lives_fx_cat_to_text(lives_fx_cat_t cat, boolean plural)
Definition: effects.c:40
LIVES_FX_CAT_VIDEO_GENERATOR
@ LIVES_FX_CAT_VIDEO_GENERATOR
Definition: effects.h:13
_prefs::backend_sync
char backend_sync[PATH_MAX *4]
Definition: preferences.h:410
rfx_build_window_t::param_step_label
LiVESWidget * param_step_label
Definition: rfx-builder.h:145
lives_button_grab_default_special
boolean lives_button_grab_default_special(LiVESWidget *button)
Definition: widget-helper.c:7587
lives_widget_set_no_show_all
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_no_show_all(LiVESWidget *widget, boolean set)
Definition: widget-helper.c:4868
prompt_for_script_name
char * prompt_for_script_name(const char *sname, lives_rfx_status_t status)
Definition: rfx-builder.c:3920
rfx_build_window_t::paramw_rest_label
LiVESWidget * paramw_rest_label
Definition: rfx-builder.h:154
rfx_build_window_t::num_reqs
int num_reqs
Definition: rfx-builder.h:181
_palette::menu_and_bars
LiVESWidgetColor menu_and_bars
Definition: mainwindow.h:327
get_token_count
size_t get_token_count(const char *string, int delim)
Definition: utils.c:5430
rfx_build_window_t::param_type_combo
LiVESWidget * param_type_combo
Definition: rfx-builder.h:140
sizdbl
ssize_t sizdbl
Definition: main.c:102
widget_opts_t::apply_theme
int apply_theme
theming variation for widget (0 -> no theme, 1 -> normal colours, 2+ -> theme variants)
Definition: widget-helper.h:1409
add_fill_to_box
LiVESWidget * add_fill_to_box(LiVESBox *box)
Definition: widget-helper.c:12377
lives_scrolled_window_get_vadjustment
WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment * lives_scrolled_window_get_vadjustment(LiVESScrolledWindow *swindow)
Definition: widget-helper.c:6254
LIVES_RFX_SOURCE_RFX
@ LIVES_RFX_SOURCE_RFX
Definition: plugins.h:513
lives_widget_queue_draw
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw(LiVESWidget *widget)
Definition: widget-helper.c:1580
get_int_param
int get_int_param(void *value)
Definition: plugins.c:3079
lives_text_view_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_text_view_new(void)
Definition: widget-helper.c:3932
rfx_build_window_t::mode
lives_rfx_builder_mode_t mode
Definition: rfx-builder.h:202
lives_widget_is_sensitive
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_sensitive(LiVESWidget *widget)
Definition: widget-helper.c:4885
RFX_STATUS_ANY
@ RFX_STATUS_ANY
indicates free choice of statuses
Definition: plugins.h:615
update_rfx_menus
void update_rfx_menus(void)
Definition: rfx-builder.c:4684
mainwindow::run_test_rfx_menu
LiVESWidget * run_test_rfx_menu
Definition: mainwindow.h:1416
STYLE_3
#define STYLE_3
style is lightish - allow themeing of widgets with dark text, otherwise use menu bg
Definition: mainwindow.h:301
set_double_param
void set_double_param(void *value, double _const)
Definition: plugins.c:3119
rfx_build_window_t::spinbutton_param_def
LiVESWidget * spinbutton_param_def
Definition: rfx-builder.h:161
rfx_build_window_t::spinbutton_param_step
LiVESWidget * spinbutton_param_step
Definition: rfx-builder.h:164
rfx_build_window_t::param_def_combo
LiVESWidget * param_def_combo
Definition: rfx-builder.h:149
lives_container_set_border_width
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_set_border_width(LiVESContainer *container, uint32_t width)
Definition: widget-helper.c:4947
lives_entry_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_entry_new(void)
Definition: widget-helper.c:6140
rfx_build_window_t::spinbutton_min_frames
LiVESWidget * spinbutton_min_frames
Definition: rfx-builder.h:107
PLUGIN_SCRIPTS_DIR
#define PLUGIN_SCRIPTS_DIR
Definition: mainwindow.h:596
LIVES_FX_CAT_TRANSITION
@ LIVES_FX_CAT_TRANSITION
Definition: effects.h:20
make_version_hash
uint64_t make_version_hash(const char *ver)
Definition: utils.c:3500
lives_colRGB48_t::blue
uint16_t blue
Definition: main.h:319
LIVES_PARAM_NUM
@ LIVES_PARAM_NUM
Definition: plugins.h:502
lives_param_t::dp
int dp
decimals, 0 for int and bool
Definition: plugins.h:575
do_error_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
mainwindow::effects_menu
LiVESWidget * effects_menu
Definition: mainwindow.h:1401
lives_standard_entry_new
LiVESWidget * lives_standard_entry_new(const char *labeltext, const char *txt, int dispwidth, int maxchars, LiVESBox *box, const char *tooltip)
Definition: widget-helper.c:9688
lives_rfx_t::onchange_strings
LiVESList * onchange_strings
rfxscript for constructing the params, param window and onchange triggers
Definition: plugins.h:655
lives_window_add_accel_group
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_add_accel_group(LiVESWindow *window, LiVESAccelGroup *group)
Definition: widget-helper.c:2968
end_threaded_dialog
void end_threaded_dialog(void)
Definition: dialogs.c:3883
mainwindow::resize_menuitem
LiVESWidget * resize_menuitem
Definition: mainwindow.h:1436
threaded_dialog_spin
void threaded_dialog_spin(double fraction)
Definition: dialogs.c:3823
mainwindow::custom_utilities_submenu
LiVESWidget * custom_utilities_submenu
Definition: mainwindow.h:1426
rfx_build_window_t::post_code
char * post_code
Definition: rfx-builder.h:176
TRUE
#define TRUE
Definition: videoplugin.h:59
sizint
ssize_t sizint
type sizes
Definition: main.c:102
lives_rfx_t::num_in_channels
int num_in_channels
Definition: plugins.h:630
mainwindow::export_custom_rfx
LiVESWidget * export_custom_rfx
Definition: mainwindow.h:1246
rfx_build_window_t::onum_triggers
int onum_triggers
Definition: rfx-builder.h:196
capability::umask
mode_t umask
Definition: main.h:597
mainwindow::string_constants
char * string_constants[NUM_LIVES_STRING_CONSTANTS]
Definition: mainwindow.h:1539
on_render_fx_activate
void on_render_fx_activate(LiVESMenuItem *menuitem, lives_rfx_t *rfx)
Definition: paramwindow.c:222
rfx_build_window_t::min_frames_label
LiVESWidget * min_frames_label
Definition: rfx-builder.h:126
rfx_build_window_t::reqs
char * reqs[RFXBUILD_MAX_REQ]
Definition: rfx-builder.h:180
lives_memset
#define lives_memset
Definition: machinestate.h:61
RFX_PROPS_BATCHG
#define RFX_PROPS_BATCHG
is a batch generator
Definition: plugins.h:636
rfx_build_window_t::edit_entry_button
LiVESWidget * edit_entry_button
Definition: rfx-builder.h:167
rfxbuilder_to_script
boolean rfxbuilder_to_script(rfx_build_window_t *rfxbuilder)
Definition: rfx-builder.c:2952
mainwindow::edit_test_rfx
LiVESWidget * edit_test_rfx
Definition: mainwindow.h:1248
mainwindow::rename_test_rfx
LiVESWidget * rename_test_rfx
Definition: mainwindow.h:1249
THREADVAR
#define THREADVAR(var)
Definition: machinestate.h:531
lives_table_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_table_new(uint32_t rows, uint32_t cols, boolean homogeneous)
Definition: widget-helper.c:6931
rfx_build_window_t::action_desc_entry
LiVESWidget * action_desc_entry
Definition: rfx-builder.h:105
set_colRGB24_param
void set_colRGB24_param(void *value, short red, short green, short blue)
Definition: plugins.c:3149
lives_standard_combo_new
LiVESWidget * lives_standard_combo_new(const char *labeltext, LiVESList *list, LiVESBox *box, const char *tooltip)
Definition: widget-helper.c:9544
lives_rfx_t
Definition: plugins.h:625
rfx_build_window_t::trigger_when_entry
LiVESWidget * trigger_when_entry
Definition: rfx-builder.h:158
on_import_rfx_activate
void on_import_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:3849
RFX_CODE_TYPE_STRING_LIST
@ RFX_CODE_TYPE_STRING_LIST
Definition: rfx-builder.h:86
lives_param_t::max
double max
for string this is max characters
Definition: plugins.h:579
lives_combo_populate
boolean lives_combo_populate(LiVESCombo *combo, LiVESList *list)
Definition: widget-helper.c:7509
lives_widget_set_bg_color
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_bg_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
Definition: widget-helper.c:2056
rfx_build_window_t::params_button
LiVESWidget * params_button
Definition: rfx-builder.h:117
RFX_STATUS_WEED
@ RFX_STATUS_WEED
indicates an internal RFX, created from a weed instance
Definition: plugins.h:616
widget_opts_t::last_label
LiVESWidget * last_label
commonly adjusted values //////
Definition: widget-helper.h:1406
on_export_rfx_activate
void on_export_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:3821
lives_widget_unparent
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_unparent(LiVESWidget *widget)
Definition: widget-helper.c:11295
rfx_copy
void rfx_copy(lives_rfx_t *dest, lives_rfx_t *src, boolean full)
Definition: plugins.c:2931
RFXBUILD_MAX_PARAMS
#define RFXBUILD_MAX_PARAMS
maximum parameters
Definition: rfx-builder.h:44
lives_layout_hbox_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_hbox_new(LiVESLayout *layout)
Definition: widget-helper.c:7757
lives_grid_remove_row
WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_remove_row(LiVESGrid *grid, int posn)
Definition: widget-helper.c:6796
RFX_BUILD_TYPE_EFFECT1
@ RFX_BUILD_TYPE_EFFECT1
Definition: rfx-builder.h:67
rfx_build_window_t::langc_combo
LiVESWidget * langc_combo
Definition: rfx-builder.h:113
rfx_build_window_t::codetype
lives_rfx_code_type_t codetype
Definition: rfx-builder.h:132
_prefs::audio_src
int audio_src
Definition: preferences.h:204
capable
capability * capable
Definition: main.h:627
RFXBUILD_MAX_REQ
#define RFXBUILD_MAX_REQ
maximum requirements
Definition: rfx-builder.h:41
lives_toggle_button_get_active
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
Definition: widget-helper.c:4472
rfx_build_window_t::prop_batchg
LiVESWidget * prop_batchg
Definition: rfx-builder.h:124
rfx_trigger_t::when
int when
Definition: rfx-builder.h:62
d_print
void d_print(const char *fmt,...)
Definition: utils.c:2542
lives_param_t
Definition: plugins.h:538
EXEC_RFX_BUILDER
#define EXEC_RFX_BUILDER
Definition: rfx-builder.h:10
RFX_MAXSTRINGLEN
#define RFX_MAXSTRINGLEN
length of max string (not including terminating NULL) for LiVES-perl
Definition: plugins.h:498
_prefs::prefix_dir
char prefix_dir[PATH_MAX]
Definition: preferences.h:74
rfx_build_window_t::plugin_version
int plugin_version
Definition: rfx-builder.h:216
RFX_CODE_TYPE_PRE
@ RFX_CODE_TYPE_PRE
Definition: rfx-builder.h:82
lives_rfx_t::props
uint32_t props
Definition: plugins.h:633
rfx_build_window_t::paramw_spsub_combo
LiVESWidget * paramw_spsub_combo
Definition: rfx-builder.h:153
lives_table_resize
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_resize(LiVESTable *table, uint32_t rows, uint32_t cols)
Definition: widget-helper.c:7011
lives_general_button_clicked
void lives_general_button_clicked(LiVESButton *button, livespointer data_to_free)
Definition: widget-helper.c:12306
get_basename
void get_basename(char *filename)
Definition: utils.c:3194
mainwindow::custom_tools_menu
LiVESWidget * custom_tools_menu
Definition: mainwindow.h:1420
lives_rfx_t::num_params
int num_params
Definition: plugins.h:644
lives_widget_object_ref
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_ref(livespointer object)
increase refcount by one
Definition: widget-helper.c:797
PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS
#define PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS
in the config directory
Definition: plugins.h:479
mainwindow::msg
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
mainwindow::num_rendered_effects_custom
int num_rendered_effects_custom
Definition: mainwindow.h:857
lives_spin_button_get_value
WIDGET_HELPER_GLOBAL_INLINE double lives_spin_button_get_value(LiVESSpinButton *button)
Definition: widget-helper.c:5083
_prefs::load_rfx_builtin
boolean load_rfx_builtin
Definition: preferences.h:449
d_print_file_error_failed
void d_print_file_error_failed(void)
Definition: utils.c:2625
_palette::white
LiVESWidgetColor white
Definition: mainwindow.h:306
rfx_build_window_t::pre_button
LiVESWidget * pre_button
Definition: rfx-builder.h:119
lives_standard_label_new
LiVESWidget * lives_standard_label_new(const char *text)
Definition: widget-helper.c:8601
EXEC_RFX_BUILDER_MULTI
#define EXEC_RFX_BUILDER_MULTI
this definition must match with smogrify
Definition: rfx-builder.h:16
lives_combo_set_active_index
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_index(LiVESCombo *combo, int index)
Definition: widget-helper.c:3883
lives_param_t::min
double min
Definition: plugins.h:578
SPLASH_LEVEL_LOAD_RFX
#define SPLASH_LEVEL_LOAD_RFX
Definition: mainwindow.h:1601
on_copy_rfx_activate
void on_copy_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:95
interface.h
lives_vbox_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vbox_new(boolean homogeneous, int spacing)
Definition: widget-helper.c:3267
lives_standard_button_new
#define lives_standard_button_new(w, h)
Definition: widget-helper.h:1042
check_builder_programs
boolean check_builder_programs(void)
Definition: rfx-builder.c:3668
rfx_build_window_t::triggers
rfx_trigger_t * triggers
Definition: rfx-builder.h:193
do_rendered_fx_dialog
LIVES_GLOBAL_INLINE void do_rendered_fx_dialog(void)
Definition: dialogs.c:3368
d_print_failed
void d_print_failed(void)
Definition: utils.c:2615
PLUGIN_RENDERED_EFFECTS_CUSTOM
#define PLUGIN_RENDERED_EFFECTS_CUSTOM
in the config directory
Definition: plugins.h:472
lives_param_t::list
LiVESList * list
for string list (choices)
Definition: plugins.h:582
lives_widget_get_parent
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_get_parent(LiVESWidget *widget)
Definition: widget-helper.c:4739
rfx_build_window_t::move_up_button
LiVESWidget * move_up_button
Definition: rfx-builder.h:169
lives_rfx_t::delim
char delim[2]
Definition: plugins.h:652
widget_opts_t::border_width
int border_width
border width in pixels
Definition: widget-helper.h:1416
get_location
void get_location(const char *exe, char *val, int maxlen)
Definition: utils.c:3407
get_double_param
double get_double_param(void *value)
Definition: plugins.c:3086
lives_combo_get_entry
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_combo_get_entry(LiVESCombo *widget)
Definition: widget-helper.c:12295
rfx_build_window_t::type
lives_rfx_build_type_t type
Definition: rfx-builder.h:96
rfx_build_window_t::spinbutton_version
LiVESWidget * spinbutton_version
Definition: rfx-builder.h:100
rfx_trigger_t
Definition: rfx-builder.h:61
do_warning_dialog
LIVES_GLOBAL_INLINE boolean do_warning_dialog(const char *text)
Definition: dialogs.c:564
rfx_build_window_t::prop_slow
LiVESWidget * prop_slow
Definition: rfx-builder.h:123
rfx_build_window_t::table_swap_row1
int table_swap_row1
Definition: rfx-builder.h:204
widget_opts_t::packing_height
int packing_height
vertical pixels between widgets
Definition: widget-helper.h:1411
lives_menu_item_set_submenu
WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_item_set_submenu(LiVESMenuItem *menuitem, LiVESWidget *menu)
Definition: widget-helper.c:6519
lives_rfx_t::menuitem
LiVESWidget * menuitem
the menu item which activates this effect
Definition: plugins.h:643
PREF_RFXDIALOG_H
#define PREF_RFXDIALOG_H
Definition: rfx-builder.h:54
mainwindow::accel_group
LiVESAccelGroup * accel_group
Definition: mainwindow.h:1228
plugin_request_common
LiVESList * plugin_request_common(const char *plugin_type, const char *plugin_name, const char *request, const char *delim, boolean allow_blanks)
Definition: plugins.c:69
palette
_palette * palette
interface colour settings
Definition: main.c:101
rfx_build_window_t::param_strlist_hbox
LiVESWidget * param_strlist_hbox
Definition: rfx-builder.h:148
widget_opts_t::non_modal
boolean non_modal
non-modal for dialogs
Definition: widget-helper.h:1422
lives_rfx_status_t
lives_rfx_status_t
Definition: plugins.h:611
lives_hbox_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hbox_new(boolean homogeneous, int spacing)
Definition: widget-helper.c:3253
mainwindow::custom_gens_submenu
LiVESWidget * custom_gens_submenu
Definition: mainwindow.h:1424
mainwindow::custom_utilities_separator
LiVESWidget * custom_utilities_separator
Definition: mainwindow.h:1427
lives_signal_handlers_disconnect_by_func
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_disconnect_by_func(livespointer instance, LiVESGuiCallback func, livespointer data)
Definition: widget-helper.c:1399
DEF_BUTTON_WIDTH
#define DEF_BUTTON_WIDTH
Definition: mainwindow.h:182
lives_fx_candidate_t::delegate
int delegate
offset in list of current delegate
Definition: plugins.h:688
FX_CANDIDATE_RESIZER
#define FX_CANDIDATE_RESIZER
Definition: plugins.h:695
lives_layout_row_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_layout_row_new(LiVESLayout *layout)
Definition: widget-helper.c:7791
lives_rfx_t::flags
uint32_t flags
Definition: plugins.h:645
lives_param_t::label
char * label
Definition: plugins.h:543
widget_opts_t::scale
double scale
scale factor for all sizes
Definition: widget-helper.h:1433
do_threaded_dialog
void do_threaded_dialog(const char *trans_text, boolean has_cancel)
Definition: dialogs.c:3849
splash_msg
void splash_msg(const char *msg, double pct)
Definition: gui.c:4687
subst
char * subst(const char *string, const char *from, const char *to)
Definition: utils.c:5484
lives_rfx_t::gui_strings
LiVESList * gui_strings
rfxscript for constructing the params, param window and onchange triggers
Definition: plugins.h:654
rfx_build_window_t::num_triggers
int num_triggers
upper limit is RFXBUILD_MAX_PARAMS, 0 == init
Definition: rfx-builder.h:195
lives_rmdir
int lives_rmdir(const char *dir, boolean force)
Definition: utils.c:4366
lives_strdup_printf
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
GUI_SCREEN_HEIGHT
#define GUI_SCREEN_HEIGHT
Definition: mainwindow.h:100
lives_calloc
#define lives_calloc
Definition: machinestate.h:67
paramwindow.h
array_to_string_list
LiVESList * array_to_string_list(char **array, int offset, int len)
Definition: plugins.c:2883
mainwindow::custom_utilities_menu
LiVESWidget * custom_utilities_menu
Definition: mainwindow.h:1425
rfx_build_window_t::paramw_sp_combo
LiVESWidget * paramw_sp_combo
Definition: rfx-builder.h:152
perform_rfxbuilder_checks
boolean perform_rfxbuilder_checks(rfx_build_window_t *rfxbuilder)
Definition: rfx-builder.c:2872
RFX_BUILD_TYPE_TOOL
@ RFX_BUILD_TYPE_TOOL
Definition: rfx-builder.h:70
lives_list_free_all
void lives_list_free_all(LiVESList **)
Definition: utils.c:4873
ensure_extension
char * ensure_extension(const char *fname, const char *ext) WARN_UNUSED
Definition: utils.c:3232
RFX_TABLE_TYPE_PARAMS
@ RFX_TABLE_TYPE_PARAMS
Definition: rfx-builder.h:76
rfx_build_window_t::param_wrap_checkbutton
LiVESWidget * param_wrap_checkbutton
Definition: rfx-builder.h:147
LIVES_MAIN_WINDOW_WIDGET
#define LIVES_MAIN_WINDOW_WIDGET
Definition: mainwindow.h:188
param_copy
void param_copy(lives_param_t *dest, lives_param_t *src, boolean full)
Definition: plugins.c:3020
rfx_build_window_t::field_delim
char * field_delim
Definition: rfx-builder.h:200
MAXINTLEN
#define MAXINTLEN
length in chars of G_MAXINT (for display only)
Definition: rfx-builder.h:25
rfx_build_window_t::hbox_bg
LiVESWidget * hbox_bg
Definition: rfx-builder.h:155
rfx_build_window_t::param_strdef_hbox
LiVESWidget * param_strdef_hbox
Definition: rfx-builder.h:157
lives_text_view_set_text
boolean lives_text_view_set_text(LiVESTextView *textview, const char *text, int len)
Definition: widget-helper.c:11715
check_rfx_for_lives
boolean check_rfx_for_lives(lives_rfx_t *rfx)
Definition: plugins.c:2661
rfx_build_window_t::table
LiVESWidget * table
Definition: rfx-builder.h:114
rfx_build_window_t::action_desc_hsep
LiVESWidget * action_desc_hsep
Definition: rfx-builder.h:106
rfx_build_window_t::action_desc_hbox
LiVESWidget * action_desc_hbox
Definition: rfx-builder.h:104
lives_colRGB48_t
Definition: main.h:316
lives_standard_menu_new
LiVESWidget * lives_standard_menu_new(void)
Definition: widget-helper.c:8438
lives_bin_get_child
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_bin_get_child(LiVESBin *bin)
Definition: widget-helper.c:5514
rfx_build_window_t::onum_params
int onum_params
Definition: rfx-builder.h:187
mainwindow::utilities_submenu
LiVESWidget * utilities_submenu
Definition: mainwindow.h:1412
_palette::black
LiVESWidgetColor black
Definition: mainwindow.h:307
rfx_build_window_t::move_down_button
LiVESWidget * move_down_button
Definition: rfx-builder.h:170
rfx_build_window_t::param_def_label
LiVESWidget * param_def_label
Definition: rfx-builder.h:142
add_rfx_effects2
void add_rfx_effects2(lives_rfx_status_t status)
Definition: rfx-builder.c:4481
hextodec
int hextodec(const char *string)
Definition: utils.c:5694
lives_memcpy
#define lives_memcpy
Definition: machinestate.h:55
lives_text_view_set_cursor_visible
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_cursor_visible(LiVESTextView *tview, boolean setting)
Definition: widget-helper.c:3977
mainwindow::has_custom_utilities
boolean has_custom_utilities
Definition: mainwindow.h:1608
lives_param_t::hidden
uint32_t hidden
Definition: plugins.h:546
LIVES_FILE_EXT_RFX_SCRIPT
#define LIVES_FILE_EXT_RFX_SCRIPT
Definition: mainwindow.h:515
lives_widget_set_sensitive
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive(LiVESWidget *widget, boolean state)
Definition: widget-helper.c:1477
lives_strappend
LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew)
Definition: machinestate.c:1436
lives_accel_group_new
WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup * lives_accel_group_new(void)
Definition: widget-helper.c:2915
RFX_STATUS_BUILTIN
@ RFX_STATUS_BUILTIN
factory presets
Definition: plugins.h:612
rfx_build_window_t::props
uint32_t props
Definition: rfx-builder.h:172
lives_text_view_set_editable
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_editable(LiVESTextView *tview, boolean setting)
Definition: widget-helper.c:3959
lives_param_t::name
char * name
Definition: plugins.h:540
lives_spin_button_set_digits
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_digits(LiVESSpinButton *button, uint32_t digits)
Definition: widget-helper.c:5156
rfx_build_window_t::onum_reqs
int onum_reqs
Definition: rfx-builder.h:182
mainwindow::multitrack
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
mainwindow::custom_tools_separator
LiVESWidget * custom_tools_separator
Definition: mainwindow.h:1422
lives_fx_candidate_t::func
ulong func
menuitem activation function for current delegate
Definition: plugins.h:689
render_fx_get_params
void render_fx_get_params(lives_rfx_t *rfx, const char *plugin_name, short status)
Definition: plugins.c:2707
CURRENT_CLIP_IS_VALID
#define CURRENT_CLIP_IS_VALID
Definition: main.h:809
rfx_build_window_t::has_init_trigger
boolean has_init_trigger
Definition: rfx-builder.h:198
DEF_BUTTON_HEIGHT
#define DEF_BUTTON_HEIGHT
Definition: mainwindow.h:183
rfx_build_window_t::entry2
LiVESWidget * entry2[RFXBUILD_MAX_TROWS]
Definition: rfx-builder.h:135
rfx_build_window_t::params
lives_param_t * params
store our parameters
Definition: rfx-builder.h:184
lives_entry_set_width_chars
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_width_chars(LiVESEntry *entry, int nchars)
Definition: widget-helper.c:6223
LIVES_PARAM_UNKNOWN
@ LIVES_PARAM_UNKNOWN
Definition: plugins.h:501
rfx_build_window_t::name_entry
LiVESWidget * name_entry
Definition: rfx-builder.h:99
lives_widget_queue_resize
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_resize(LiVESWidget *widget)
Definition: widget-helper.c:1605
on_delete_rfx_activate
void on_delete_rfx_activate(LiVESMenuItem *menuitem, livespointer user_data)
Definition: rfx-builder.c:3699
lives_image_new_from_stock
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_image_new_from_stock(const char *stock_id, LiVESIconSize size)
Definition: widget-helper.c:2412
sort_rfx_array
void sort_rfx_array(lives_rfx_t *in, int num)
Definition: plugins.c:2909
RFX_PROPS_MAY_RESIZE
#define RFX_PROPS_MAY_RESIZE
is a tool
Definition: plugins.h:635
do_write_failed_error_s_with_retry
LiVESResponseType do_write_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4058
lives_standard_menu_item_new_with_label
LiVESWidget * lives_standard_menu_item_new_with_label(const char *label)
Definition: widget-helper.c:8474
RFX_TEXT_MAGIC
#define RFX_TEXT_MAGIC
length at which entry turns into textview
Definition: paramwindow.h:16
on_render_fx_pre_activate
LIVES_GLOBAL_INLINE void on_render_fx_pre_activate(LiVESMenuItem *menuitem, lives_rfx_t *rfx)
Definition: paramwindow.c:656
rfx_build_window_t::pre_code
char * pre_code
Definition: rfx-builder.h:174
script_to_rfxbuilder
boolean script_to_rfxbuilder(rfx_build_window_t *rfxbuilder, const char *script_file)
Definition: rfx-builder.c:3279
AF_TYPE_ANY
@ AF_TYPE_ANY
Definition: effects.h:41
main.h
rfx_build_window_t::new_entry_button
LiVESWidget * new_entry_button
Definition: rfx-builder.h:166
RFX_STATUS_TEST
@ RFX_STATUS_TEST
test effects in the advanced menu
Definition: plugins.h:614
lives_menu_shell_insert
WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_shell_insert(LiVESMenuShell *menushell, LiVESWidget *child, int pos)
Definition: widget-helper.c:6620
lives_rfx_t::source_type
lives_rfx_source_t source_type
Definition: plugins.h:650
RFXBUILDER_SCRIPT_SUFFIX
#define RFXBUILDER_SCRIPT_SUFFIX
default script extension when saving
Definition: rfx-builder.h:19
LIVES_EXPAND_DEFAULT
#define LIVES_EXPAND_DEFAULT
Definition: widget-helper.h:1314
LIVES_STRING_CONSTANT_BUILTIN
@ LIVES_STRING_CONSTANT_BUILTIN
Definition: mainwindow.h:375
lives_combo_get_active_text
WIDGET_HELPER_GLOBAL_INLINE const char * lives_combo_get_active_text(LiVESCombo *combo)
Definition: widget-helper.c:3874
lives_text_buffer_get_start_iter
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_get_start_iter(LiVESTextBuffer *tbuff, LiVESTextIter *iter)
Definition: widget-helper.c:4080
lives_rfx_t::rfx_version
char rfx_version[64]
Definition: plugins.h:653
AUDIO_SRC_INT
#define AUDIO_SRC_INT
Definition: preferences.h:205
rfx_build_window_t::table_type
lives_rfx_table_type_t table_type
Definition: rfx-builder.h:128
rfx_build_window_t::num_paramw_hints
int num_paramw_hints
upper limit is RFXBUILD_MAX_PARAMW_HINTS-1
Definition: rfx-builder.h:190
mainw
mainwindow * mainw
Definition: main.c:103
rfx_build_window_t::type_effect2_radiobutton
LiVESWidget * type_effect2_radiobutton
Definition: rfx-builder.h:109
mainwindow::delete_custom_rfx
LiVESWidget * delete_custom_rfx
Definition: mainwindow.h:1247
rfx_build_window_t::loop_button
LiVESWidget * loop_button
Definition: rfx-builder.h:120
rfx_build_window_t::dialog
LiVESWidget * dialog
Definition: rfx-builder.h:98
get_bool_param
boolean get_bool_param(void *value)
Definition: plugins.c:3072
lives_fputs
int lives_fputs(const char *s, FILE *stream)
Definition: utils.c:359
RFX_TABLE_TYPE_REQUIREMENTS
@ RFX_TABLE_TYPE_REQUIREMENTS
Definition: rfx-builder.h:75
RFX_CODE_TYPE_POST
@ RFX_CODE_TYPE_POST
Definition: rfx-builder.h:84
lives_widget_set_events
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_events(LiVESWidget *widget, int events)
Definition: widget-helper.c:4830
mainwindow::has_custom_tools
boolean has_custom_tools
Definition: mainwindow.h:1608
lives_standard_scrolled_window_new
LiVESWidget * lives_standard_scrolled_window_new(int width, int height, LiVESWidget *child)
Definition: widget-helper.c:10272
lives_button_box_set_layout
WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_box_set_layout(LiVESButtonBox *bbox, LiVESButtonBoxStyle bstyle)
Definition: widget-helper.c:3355
lives_param_t::step_size
double step_size
Definition: plugins.h:562
lives_entry_set_text
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text)
Definition: widget-helper.c:6211
mainwindow::has_custom_effects
boolean has_custom_effects
Definition: mainwindow.h:1608
mainwindow::tools_menu
LiVESWidget * tools_menu
Definition: mainwindow.h:1402
rfx_build_window_t::url_entry
LiVESWidget * url_entry
Definition: rfx-builder.h:102
lives_entry_set_editable
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_editable(LiVESEntry *entry, boolean editable)
Definition: widget-helper.c:7422
rfx_build_window_t::onum_paramw_hints
int onum_paramw_hints
Definition: rfx-builder.h:191
lives_container_add
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_add(LiVESContainer *container, LiVESWidget *widget)
Definition: widget-helper.c:4929
lives_entry_set_activates_default
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_activates_default(LiVESEntry *entry, boolean act)
Definition: widget-helper.c:6159
perform_param_checks
boolean perform_param_checks(rfx_build_window_t *rfxbuilder, int index, int rows)
Definition: rfx-builder.c:2933
lives_system
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
lives_scrolled_window_get_hadjustment
WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment * lives_scrolled_window_get_hadjustment(LiVESScrolledWindow *swindow)
Definition: widget-helper.c:6245
lives_widget_show_all
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
Definition: widget-helper.c:1523
mainwindow::num_rendered_effects_test
int num_rendered_effects_test
Definition: mainwindow.h:858
lives_vbutton_box_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vbutton_box_new(void)
Definition: widget-helper.c:3342
RFX_TABLE_TYPE_TRIGGERS
@ RFX_TABLE_TYPE_TRIGGERS
Definition: rfx-builder.h:77
mainwindow::fx_candidates
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
lives_toggle_button_set_active
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_active(LiVESToggleButton *button, boolean active)
Definition: widget-helper.c:4483
widget_opts
widget_opts_t widget_opts
Definition: widget-helper.h:1442
lives_entry_get_text
WIDGET_HELPER_GLOBAL_INLINE const char * lives_entry_get_text(LiVESEntry *entry)
Definition: widget-helper.c:6203
rfx_build_window_t::param_min_label
LiVESWidget * param_min_label
Definition: rfx-builder.h:143
mainwindow::gens_menu
LiVESWidget * gens_menu
Definition: mainwindow.h:1413
lives_text_buffer_place_cursor
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_place_cursor(LiVESTextBuffer *tbuff, LiVESTextIter *iter)
Definition: widget-helper.c:4098
PATH_MAX
#define PATH_MAX
Definition: main.h:255
widget_opts_t::expand
lives_expand_t expand
how much space to apply between widgets
Definition: widget-helper.h:1408
lives_button_set_label
WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_set_label(LiVESButton *button, const char *label)
Definition: widget-helper.c:4345
add_vsep_to_box
LiVESWidget * add_vsep_to_box(LiVESBox *box)
Definition: widget-helper.c:12365
lives_colRGB48_t::green
uint16_t green
Definition: main.h:318
RFX_BUILD_TYPE_EFFECT2
@ RFX_BUILD_TYPE_EFFECT2
Definition: rfx-builder.h:68
lives_signal_handler_unblock
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_unblock(livespointer instance, unsigned long handler_id)
Definition: widget-helper.c:947
lives_param_t::wrap
boolean wrap
Definition: plugins.h:571
lives_rfx_t::source
void * source
points to the source (e.g. a weed_plant_t)
Definition: plugins.h:651
rfx_build_window_t::paramw_hints
char * paramw_hints[RFXBUILD_MAX_PARAMS]
Definition: rfx-builder.h:189
GUI_SCREEN_WIDTH
#define GUI_SCREEN_WIDTH
Definition: mainwindow.h:99
rfx_build_window_t::author_entry
LiVESWidget * author_entry
Definition: rfx-builder.h:101
get_plugin_result
LiVESList * get_plugin_result(const char *command, const char *delim, boolean allow_blanks, boolean strip)
Definition: plugins.c:30
rfx_build_window_t::type_tool_radiobutton
LiVESWidget * type_tool_radiobutton
Definition: rfx-builder.h:111
has_video_filters
boolean has_video_filters(boolean analysers_only)
Definition: effects-weed.c:3886
lives_standard_check_button_new
LiVESWidget * lives_standard_check_button_new(const char *labeltext, boolean active, LiVESBox *box, const char *tooltip)
Definition: widget-helper.c:9048
rfx_build_window_t::code_textview
LiVESWidget * code_textview
Definition: rfx-builder.h:165
d_print_done
void d_print_done(void)
Definition: utils.c:2620
mainwindow::custom_tools_submenu
LiVESWidget * custom_tools_submenu
Definition: mainwindow.h:1421
mainwindow::custom_gens_menu
LiVESWidget * custom_gens_menu
Definition: mainwindow.h:1423
LIVES_STRING_CONSTANT_TEST
@ LIVES_STRING_CONSTANT_TEST
Definition: mainwindow.h:377
RFX_BUILDER_MODE_NEW
@ RFX_BUILDER_MODE_NEW
Definition: rfx-builder.h:90
lives_text_view_set_wrap_mode
WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_wrap_mode(LiVESTextView *tview, LiVESWrapMode wrapmode)
Definition: widget-helper.c:3986
rfx_build_window_t::param_wrap_hbox
LiVESWidget * param_wrap_hbox
Definition: rfx-builder.h:146
rfx_build_window_t::rfx_version
char * rfx_version
Definition: rfx-builder.h:215
lives_widget_set_fg_color
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_fg_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
Definition: widget-helper.c:2079
lives_widget_object_unref
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_unref(livespointer object)
decrease refcount by one: if refcount==0, object is destroyed
Definition: widget-helper.c:815
rfx_build_window_t::param_dp_label
LiVESWidget * param_dp_label
Definition: rfx-builder.h:141
mainwindow::utilities_menu
LiVESWidget * utilities_menu
Definition: mainwindow.h:1411
mainwindow::agen_key
volatile int agen_key
which fx key is generating audio [1 based] (or 0 for none)
Definition: mainwindow.h:1649
mainwindow::run_test_rfx_submenu
LiVESWidget * run_test_rfx_submenu
Definition: mainwindow.h:1415
LIVES_FX_CAT_EFFECT
@ LIVES_FX_CAT_EFFECT
Definition: effects.h:24
rfx_build_window_t::table_swap_row2
int table_swap_row2
Definition: rfx-builder.h:205
MAXFLOATLEN
#define MAXFLOATLEN
length in chars of G_MAXFLOAT (for display only)
Definition: rfx-builder.h:22
lives_signal_handler_block
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_block(livespointer instance, unsigned long handler_id)
Definition: widget-helper.c:933
_prefs::config_datadir
char config_datadir[PATH_MAX]
kept in locale encoding (general config files) (default ~/.local/share/lives)
Definition: preferences.h:64
lives_param_t::def
void * def
default values
Definition: plugins.h:581
rfx_build_window_t::def_spin_f
ulong def_spin_f
Definition: rfx-builder.h:212
lives_widget_set_can_default
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_can_default(LiVESWidget *widget, boolean state)
Definition: widget-helper.c:4805
on_realfx_activate
void on_realfx_activate(LiVESMenuItem *menuitem, livespointer xrfx)
Definition: effects.c:799
rfx_build_window_t::entry
LiVESWidget * entry[RFXBUILD_MAX_TROWS]
Definition: rfx-builder.h:134
FALSE
#define FALSE
Definition: videoplugin.h:60
rfx_build_window_t::min_spin_f
ulong min_spin_f
Definition: rfx-builder.h:210
LIVES_PARAM_BOOL
@ LIVES_PARAM_BOOL
Definition: plugins.h:503
RFX_VERSION
#define RFX_VERSION
must match whatever is in RFX_BUILDER
Definition: rfx-builder.h:13
rfx_build_window_t::entry3
LiVESWidget * entry3[RFXBUILD_MAX_TROWS]
Definition: rfx-builder.h:136
check_file
boolean check_file(const char *file_name, boolean check_exists)
check if file exists
Definition: utils.c:4312
make_custom_submenus
void make_custom_submenus(void)
Definition: gui.c:126
rfx_build_window_t::num_params
int num_params
upper limit is RFXBUILD_MAX_PARAMS-1
Definition: rfx-builder.h:186
lives_widget_set_text_color
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_text_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
Definition: widget-helper.c:2101
rfx-builder.h
mainwindow::has_custom_gens
boolean has_custom_gens
Definition: mainwindow.h:1608
RFX_TABLE_TYPE_PARAM_WINDOW
@ RFX_TABLE_TYPE_PARAM_WINDOW
Definition: rfx-builder.h:78
_
#define _(String)
Definition: support.h:44
lives_param_t::group
int group
Definition: plugins.h:572
RFX_STATUS_COPY
@ RFX_STATUS_COPY
indicates a copy operation to test
Definition: plugins.h:621
rfx_build_window_t::menu_text_entry
LiVESWidget * menu_text_entry
Definition: rfx-builder.h:103
rfx_build_window_t::requirements_button
LiVESWidget * requirements_button
Definition: rfx-builder.h:115
STYLE_1
#define STYLE_1
turn on theming if set
Definition: mainwindow.h:299
lives_widget_set_tooltip_text
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_set_tooltip_text(LiVESWidget *widget, const char *tip_text)
Definition: widget-helper.c:4641
rfx_build_window_t::edit_param
int edit_param
Definition: rfx-builder.h:178
do_error_dialogf
LiVESResponseType do_error_dialogf(const char *fmt,...)
Definition: dialogs.c:735
lives_param_t::use_mnemonic
boolean use_mnemonic
Definition: plugins.h:545
LIVES_PARAM_STRING_LIST
@ LIVES_PARAM_STRING_LIST
Definition: plugins.h:506
lives_rm
int lives_rm(const char *file)
Definition: utils.c:4395
RFX_TOOL_MENU_POSN
#define RFX_TOOL_MENU_POSN
where do we add the builtin tools in the tools menu
Definition: mainwindow.h:699
lives_menu_add_separator
LiVESWidget * lives_menu_add_separator(LiVESMenu *menu)
Definition: widget-helper.c:11910
lives_param_t::type
lives_param_type_t type
Definition: plugins.h:573
mainwindow::delete_test_rfx
LiVESWidget * delete_test_rfx
Definition: mainwindow.h:1250
lives_event_box_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_event_box_new(void)
Definition: widget-helper.c:2284
lives_widget_set_base_color
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_base_color(LiVESWidget *widget, LiVESWidgetState state, const LiVESWidgetColor *color)
Definition: widget-helper.c:2126
lives_widget_show
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show(LiVESWidget *widget)
Definition: widget-helper.c:1505
lives_widget_context_update
boolean lives_widget_context_update(void)
Definition: widget-helper.c:11878
SCR_WIDTH_SAFETY
#define SCR_WIDTH_SAFETY
sepwin/screen size safety margins in pixels
Definition: mainwindow.h:89
mainwindow::gens_submenu
LiVESWidget * gens_submenu
Definition: mainwindow.h:1414
lives_rfx_t::min_frames
int min_frames
for Weed, 1
Definition: plugins.h:629
lives_standard_radio_button_new
LiVESWidget * lives_standard_radio_button_new(const char *labeltext, LiVESSList **rbgroup, LiVESBox *box, const char *tooltip)
Definition: widget-helper.c:9265
MAINW_MSG_SIZE
#define MAINW_MSG_SIZE
mainw->msg bytesize
Definition: mainwindow.h:702
rfx_build_window_t::param_max_label
LiVESWidget * param_max_label
Definition: rfx-builder.h:144
rfx_build_window_t::type_effect1_radiobutton
LiVESWidget * type_effect1_radiobutton
Definition: rfx-builder.h:108
RFX_STATUS_CUSTOM
@ RFX_STATUS_CUSTOM
custom effects in the custom menu
Definition: plugins.h:613
lives_image_menu_item_set_image
WIDGET_HELPER_GLOBAL_INLINE boolean lives_image_menu_item_set_image(LiVESImageMenuItem *item, LiVESWidget *image)
Definition: widget-helper.c:6556
PREF_RFXDIALOG_W
#define PREF_RFXDIALOG_W
Definition: rfx-builder.h:53
lives_param_t::desc
char * desc
Definition: plugins.h:541
lives_editable_select_region
WIDGET_HELPER_GLOBAL_INLINE boolean lives_editable_select_region(LiVESEditable *editable, int start_pos, int end_pos)
Definition: widget-helper.c:6131
mainwindow::rendered_fx
lives_rfx_t * rendered_fx
rendered fx
Definition: mainwindow.h:855
lives_box_pack_start
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_start(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill, uint32_t padding)
Definition: widget-helper.c:3281
LIVES_STRING_CONSTANT_CUSTOM
@ LIVES_STRING_CONSTANT_CUSTOM
Definition: mainwindow.h:376