1 // paramspecial.c
2 // LiVES
3 // (c) G. Finch 2004 - 2019 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6
7 // dynamic window generation from parameter arrays :-)
8 // special widgets
9
10 #include "main.h"
11 #include "resample.h"
12 #include "effects.h"
13 #include "paramwindow.h"
14 #include "framedraw.h"
15 #include "callbacks.h"
16
17 static lives_special_aspect_t aspect;
18 static lives_special_fontchooser_t fchooser;
19 static lives_special_framedraw_rect_t framedraw;
20 static LiVESList *fileread;
21 static LiVESList *filewrite;
22 static LiVESList *passwd_widgets;
23
24 static boolean special_inited = FALSE;
25
26
reset_framedraw_preview(void)27 void reset_framedraw_preview(void) {invalidate_preview(&framedraw);}
28
29
init_special(void)30 void init_special(void) {
31 if (special_inited) return;
32
33 special_inited = TRUE;
34 fchooser.nwidgets = 0;
35 aspect.nwidgets = 0;
36
37 framedraw.xstart_param = framedraw.ystart_param = framedraw.xend_param = framedraw.yend_param = NULL;
38 framedraw.stdwidgets = 0;
39 framedraw.extra_params = NULL;
40 framedraw.num_extra = 0;
41 framedraw.added = FALSE;
42 framedraw.type = LIVES_PARAM_SPECIAL_TYPE_NONE;
43 mergealign.start_param = mergealign.end_param = NULL;
44 passwd_widgets = NULL;
45 fileread = NULL;
46 filewrite = NULL;
47 }
48
49
paramspecial_get_aspect()50 const lives_special_aspect_t *paramspecial_get_aspect() {return &aspect;}
51
52
add_to_special(const char * sp_string,lives_rfx_t * rfx)53 void add_to_special(const char *sp_string, lives_rfx_t *rfx) {
54 int num_widgets = get_token_count(sp_string, '|') - 2;
55 char **array = lives_strsplit(sp_string, "|", num_widgets + 2);
56
57 // TODO - assert only one of each of these
58
59 if (!strcmp(array[0], "aspect")) {
60 aspect.width_param = &rfx->params[atoi(array[1])];
61 aspect.height_param = &rfx->params[atoi(array[2])];
62 } else if (!strcmp(array[0], "fontchooser")) {
63 #if GTK_CHECK_VERSION(3, 2, 0)
64 fchooser.font_param = &rfx->params[atoi(array[1])];
65 fchooser.size_param = &rfx->params[atoi(array[2])];
66 if (!*((char *)fchooser.font_param->value))
67 set_rfx_param_by_name_string(rfx, fchooser.font_param->name, widget_opts.font_name, TRUE);
68 #endif
69 } else if (!strcmp(array[0], "mergealign")) {
70 mergealign.start_param = &rfx->params[atoi(array[1])];
71 mergealign.end_param = &rfx->params[atoi(array[2])];
72 mergealign.rfx = rfx;
73 } else if (!strcmp(array[0], "framedraw")) {
74 if (fx_dialog[1]) {
75 lives_strfreev(array);
76 return;
77 }
78 framedraw.rfx = rfx;
79 if (!strcmp(array[1], "rectdemask")) {
80 framedraw.type = LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK;
81 framedraw.xstart_param = &rfx->params[atoi(array[2])];
82 framedraw.ystart_param = &rfx->params[atoi(array[3])];
83 framedraw.xend_param = &rfx->params[atoi(array[4])];
84 framedraw.yend_param = &rfx->params[atoi(array[5])];
85 framedraw.stdwidgets = 4;
86 } else if (!strcmp(array[1], "multirect") || !strcmp(array[1], "multrect")) { // allow for spelling errors in earlier RFX
87 framedraw.type = LIVES_PARAM_SPECIAL_TYPE_RECT_MULTIRECT;
88 framedraw.xstart_param = &rfx->params[atoi(array[2])];
89 framedraw.ystart_param = &rfx->params[atoi(array[3])];
90 framedraw.xend_param = &rfx->params[atoi(array[4])];
91 framedraw.yend_param = &rfx->params[atoi(array[5])];
92 framedraw.stdwidgets = 4;
93 } else if (!strcmp(array[1], "singlepoint")) {
94 framedraw.type = LIVES_PARAM_SPECIAL_TYPE_SINGLEPOINT;
95 framedraw.xstart_param = &rfx->params[atoi(array[2])];
96 framedraw.ystart_param = &rfx->params[atoi(array[3])];
97 framedraw.stdwidgets = 2;
98 } else if (!strcmp(array[1], "scaledpoint")) {
99 framedraw.type = LIVES_PARAM_SPECIAL_TYPE_SCALEDPOINT;
100 framedraw.xstart_param = &rfx->params[atoi(array[2])];
101 framedraw.ystart_param = &rfx->params[atoi(array[3])];
102 framedraw.scale_param = &rfx->params[atoi(array[4])];
103 framedraw.stdwidgets = 3;
104 }
105
106 if (num_widgets > framedraw.stdwidgets) framedraw.extra_params =
107 (int *)lives_malloc(((framedraw.num_extra = (num_widgets - framedraw.stdwidgets))) * sizint);
108
109 for (int i = 0; i < num_widgets; i++) {
110 int pnum = atoi(array[i + 2]);
111 if (rfx->status == RFX_STATUS_WEED) {
112 if (mainw->multitrack) {
113 if (rfx->params[pnum].multi == PVAL_MULTI_PER_CHANNEL) {
114 /// handling for "value per channel" parameters in multitrack
115 if ((rfx->params[pnum].hidden & HIDDEN_MULTI) == HIDDEN_MULTI) {
116 if (mainw->multitrack->track_index != -1) {
117 rfx->params[pnum].hidden ^= HIDDEN_MULTI; // multivalues allowed
118 } else {
119 rfx->params[pnum].hidden |= HIDDEN_MULTI; // multivalues hidden
120 // *INDENT-OFF*
121 }}}}}
122 // *INDENT-ON*
123 if (i >= framedraw.stdwidgets) framedraw.extra_params[i - framedraw.stdwidgets] = pnum;
124 }
125
126 if (mainw->multitrack) {
127 mainw->multitrack->framedraw = &framedraw;
128 lives_widget_set_bg_color(mainw->multitrack->fd_frame, LIVES_WIDGET_STATE_NORMAL, &palette->light_red);
129 }
130 }
131
132 // can be multiple of each of these
133
134 else if (!strcmp(array[0], "fileread")) {
135 int idx = atoi(array[1]);
136 fileread = lives_list_append(fileread, (livespointer)&rfx->params[idx]);
137
138 // ensure we get an entry and not a text_view
139 if ((int)rfx->params[idx].max > RFX_TEXT_MAGIC) rfx->params[idx].max = (double)RFX_TEXT_MAGIC;
140 } else if (!strcmp(array[0], "filewrite")) {
141 int idx = atoi(array[1]);
142 filewrite = lives_list_append(filewrite, (livespointer)&rfx->params[idx]);
143 rfx->params[idx].edited = TRUE;
144
145 // ensure we get an entry and not a text_view
146 if ((int)rfx->params[idx].max > RFX_TEXT_MAGIC) rfx->params[idx].max = (double)RFX_TEXT_MAGIC;
147 } else if (!strcmp(array[0], "password")) {
148 int idx = atoi(array[1]);
149 passwd_widgets = lives_list_append(passwd_widgets, (livespointer)&rfx->params[idx]);
150
151 // ensure we get an entry and not a text_view
152 if ((int)rfx->params[idx].max > RFX_TEXT_MAGIC) rfx->params[idx].max = (double)RFX_TEXT_MAGIC;
153 }
154
155 lives_strfreev(array);
156 }
157
158
fd_tweak(lives_rfx_t * rfx)159 void fd_tweak(lives_rfx_t *rfx) {
160 if (rfx->props & RFX_PROPS_MAY_RESIZE) {
161 if (framedraw.type != LIVES_PARAM_SPECIAL_TYPE_NONE) {
162 // for effects which can resize, and have a special framedraw, we will use original sized image
163 lives_widget_hide(mainw->framedraw_preview);
164 lives_widget_set_sensitive(mainw->framedraw_spinbutton, TRUE);
165 lives_widget_set_sensitive(mainw->framedraw_scale, TRUE);
166 }
167 }
168 if (framedraw.type != LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK) {
169 lives_widget_set_no_show_all(mainw->framedraw_maskbox, TRUE);
170 }
171 }
172
173
fd_connect_spinbutton(lives_rfx_t * rfx)174 void fd_connect_spinbutton(lives_rfx_t *rfx) {framedraw_connect_spinbutton(&framedraw, rfx);}
175
176
passwd_toggle_vis(LiVESToggleButton * b,livespointer entry)177 static void passwd_toggle_vis(LiVESToggleButton * b, livespointer entry) {
178 lives_entry_set_visibility(LIVES_ENTRY(entry), lives_toggle_button_get_active(b));
179 }
180
reset_aspect(LiVESButton * button,livespointer user_data)181 static void reset_aspect(LiVESButton * button, livespointer user_data) {
182 if (lives_lock_button_get_locked(button)) {
183 lives_special_aspect_t *aspect = (lives_special_aspect_t *)user_data;
184 double width = lives_spin_button_get_value(LIVES_SPIN_BUTTON(aspect->width_param->widgets[0]));
185 double height = lives_spin_button_get_value(LIVES_SPIN_BUTTON(aspect->height_param->widgets[0]));
186 aspect->ratio = width / height;
187 }
188 }
189
190 #if GTK_CHECK_VERSION(3, 2, 0)
font_set_cb(LiVESFontButton * button,livespointer data)191 static void font_set_cb(LiVESFontButton * button, livespointer data) {
192 lives_rfx_t *rfx = (lives_rfx_t *)data;
193 char *fname = lives_font_chooser_get_font(LIVES_FONT_CHOOSER(button));
194 LingoFontDescription *lfd = lives_font_chooser_get_font_desc(LIVES_FONT_CHOOSER(button));
195 int size = lingo_font_description_get_size(lfd);
196
197 lives_signal_handler_block(fchooser.font_param->widgets[0], fchooser.entry_func);
198 lives_entry_set_text(LIVES_ENTRY(fchooser.font_param->widgets[0]), fname);
199 after_param_text_changed(fchooser.font_param->widgets[0], rfx);
200 lives_signal_handler_unblock(fchooser.font_param->widgets[0], fchooser.entry_func);
201
202 lives_signal_handler_block(fchooser.size_param->widgets[0], fchooser.size_paramfunc);
203 lives_spin_button_set_value(LIVES_SPIN_BUTTON(fchooser.size_param->widgets[0]), size / LINGO_SCALE);
204 lives_signal_handler_unblock(fchooser.size_param->widgets[0], fchooser.size_paramfunc);
205
206 lives_free(fname);
207 lingo_font_description_free(lfd);
208 }
209
text_size_cb(LiVESSpinButton * button,livespointer data)210 static void text_size_cb(LiVESSpinButton * button, livespointer data) {
211 int sval = lives_spin_button_get_value_as_int(button);
212 LingoFontDescription *lfd =
213 lives_font_chooser_get_font_desc(LIVES_FONT_CHOOSER(fchooser.font_param->widgets[1]));
214 lingo_font_description_set_size(lfd, sval * LINGO_SCALE);
215 lives_font_chooser_set_font_desc(LIVES_FONT_CHOOSER(fchooser.font_param->widgets[1]), lfd);
216 lingo_font_description_free(lfd);
217 }
218
font_entry_cb(LiVESEntry * entry,livespointer data)219 static void font_entry_cb(LiVESEntry * entry, livespointer data) {
220 LiVESFontButton *button = (LiVESFontButton *)fchooser.font_param->widgets[1];
221 //lives_font_chooser_set_font(LIVES_FONT_CHOOSER(button), lives_entry_get_text(entry));
222 text_size_cb(LIVES_SPIN_BUTTON(fchooser.size_param->widgets[0]), data);
223 font_set_cb(button, data);
224 }
225 #endif
226
227
check_for_special_type(lives_rfx_t * rfx,lives_param_t * param,LiVESBox * pbox)228 void check_for_special_type(lives_rfx_t *rfx, lives_param_t *param, LiVESBox * pbox) {
229 LiVESList *slist;
230 // check if this parameter is part of a special window
231 // as we are drawing the paramwindow
232
233 if (param == framedraw.xstart_param) {
234 param->special_type = framedraw.type;
235 param->special_type_index = 0;
236 }
237 if (param == framedraw.ystart_param) {
238 param->special_type = framedraw.type;
239 param->special_type_index = 1;
240 }
241 if (mainw->current_file > -1) {
242 if (param == framedraw.xend_param) {
243 param->special_type = framedraw.type;
244 param->special_type_index = 2;
245 }
246 if (param == framedraw.yend_param) {
247 param->special_type = framedraw.type;
248 param->special_type_index = 3;
249 }
250
251 if (param == aspect.width_param) {
252 param->special_type = LIVES_PARAM_SPECIAL_TYPE_ASPECT_RATIO;
253 param->special_type_index = 0;
254 }
255
256 if (param == aspect.height_param) {
257 param->special_type = LIVES_PARAM_SPECIAL_TYPE_ASPECT_RATIO;
258 param->special_type_index = 1;
259 }
260
261 if (param == fchooser.font_param) {
262 param->special_type = LIVES_PARAM_SPECIAL_TYPE_FONT_CHOOSER;
263 param->special_type_index = 0;
264 }
265 if (param == fchooser.size_param) {
266 param->special_type = LIVES_PARAM_SPECIAL_TYPE_FONT_CHOOSER;
267 param->special_type_index = 1;
268 }
269 }
270
271 slist = fileread;
272 while (slist) {
273 if (param == (lives_param_t *)(slist->data)) {
274 param->special_type = LIVES_PARAM_SPECIAL_TYPE_FILEREAD;
275 }
276 slist = slist->next;
277 }
278
279 slist = filewrite;
280 while (slist) {
281 if (param == (lives_param_t *)(slist->data)) {
282 param->special_type = LIVES_PARAM_SPECIAL_TYPE_FILEWRITE;
283 }
284 slist = slist->next;
285 }
286
287 // password fields
288 slist = passwd_widgets;
289 while (slist) {
290 if (param == (lives_param_t *)(slist->data)) {
291 param->special_type = LIVES_PARAM_SPECIAL_TYPE_PASSWORD;
292 }
293 slist = slist->next;
294 }
295 }
296
297
check_for_special(lives_rfx_t * rfx,lives_param_t * param,LiVESBox * pbox)298 void check_for_special(lives_rfx_t *rfx, lives_param_t *param, LiVESBox * pbox) {
299 LiVESWidget *checkbutton;
300 LiVESWidget *widget = param->widgets[0];
301 LiVESWidget *hbox;
302 LiVESWidget *box;
303 LiVESWidget *buttond;
304 LiVESList *slist;
305
306 // check if this parameter is part of a special window
307 // as we are drawing the paramwindow
308
309 if (param == framedraw.xstart_param) {
310 param->special_type = framedraw.type;
311 param->special_type_index = 0;
312 if (framedraw.type == LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK)
313 lives_spin_button_set_value(LIVES_SPIN_BUTTON(widget), 0.);
314 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
315 LIVES_GUI_CALLBACK(after_framedraw_widget_changed), &framedraw);
316 }
317 if (param == framedraw.ystart_param) {
318 param->special_type = framedraw.type;
319 param->special_type_index = 1;
320 if (framedraw.type == LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK)
321 lives_spin_button_set_value(LIVES_SPIN_BUTTON(widget), 0.);
322 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
323 LIVES_GUI_CALLBACK(after_framedraw_widget_changed), &framedraw);
324 }
325 if (mainw->current_file > -1) {
326 if (param == framedraw.xend_param) {
327 param->special_type = framedraw.type;
328 param->special_type_index = 2;
329 if (framedraw.type == LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK)
330 lives_spin_button_set_value(LIVES_SPIN_BUTTON(widget), (double)cfile->hsize);
331 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
332 LIVES_GUI_CALLBACK(after_framedraw_widget_changed), &framedraw);
333 }
334 if (param == framedraw.yend_param) {
335 param->special_type = framedraw.type;
336 param->special_type_index = 3;
337 if (framedraw.type == LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK)
338 lives_spin_button_set_value(LIVES_SPIN_BUTTON(widget), (double)cfile->vsize);
339 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
340 LIVES_GUI_CALLBACK(after_framedraw_widget_changed), &framedraw);
341 }
342
343 if (framedraw.stdwidgets > 0 && !framedraw.added) {
344 if (framedraw.xstart_param && framedraw.xstart_param->widgets[0] &&
345 framedraw.ystart_param && framedraw.ystart_param->widgets[0]) {
346 if (framedraw.stdwidgets == 2 || (framedraw.stdwidgets == 3 && framedraw.scale_param &&
347 framedraw.scale_param->widgets[0]) || (framedraw.xend_param
348 && framedraw.xend_param->widgets[0] &&
349 framedraw.yend_param && framedraw.yend_param->widgets[0])) {
350 if (!mainw->multitrack) {
351 framedraw_connect(&framedraw, cfile->hsize, cfile->vsize, rfx); // turn passive preview->active
352 framedraw_add_reset(LIVES_VBOX(LIVES_WIDGET(pbox)), &framedraw);
353 } else {
354 mainw->framedraw = mainw->play_image;
355 }
356 framedraw.added = TRUE;
357 }
358 }
359 }
360
361 if (param == aspect.width_param) {
362 if (CURRENT_CLIP_HAS_VIDEO) lives_spin_button_set_value(LIVES_SPIN_BUTTON(widget), cfile->hsize);
363 aspect.width_func = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
364 LIVES_GUI_CALLBACK(after_aspect_width_changed), NULL);
365 aspect.nwidgets++;
366 }
367
368 if (param == aspect.height_param) {
369 if (CURRENT_CLIP_HAS_VIDEO) lives_spin_button_set_value(LIVES_SPIN_BUTTON(widget), cfile->vsize);
370 aspect.height_func = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
371 LIVES_GUI_CALLBACK(after_aspect_height_changed), NULL);
372 aspect.nwidgets++;
373 }
374
375 #if GTK_CHECK_VERSION(3, 2, 0)
376 if (param == fchooser.font_param) {
377 LiVESWidget *tbox = widget;
378 int idx;
379 box = lives_widget_get_parent(widget);
380 while (box && !LIVES_IS_HBOX(box)) {
381 tbox = box;
382 box = lives_widget_get_parent(box);
383 }
384 if (!box) return;
385 idx = get_box_child_index(LIVES_BOX(box), tbox);
386 param->widgets[1] = buttond = lives_standard_font_chooser_new();
387 lives_font_chooser_set_font(LIVES_FONT_CHOOSER(param->widgets[1]), param->value);
388
389 lives_box_pack_start(LIVES_BOX(box), buttond, TRUE, TRUE, 0);
390 lives_box_reorder_child(LIVES_BOX(box), buttond, idx);
391 if (lives_widget_is_visible(widget)) lives_widget_show_all(buttond);
392
393 lives_widget_object_ref(tbox);
394 lives_widget_unparent(tbox);
395
396 if (!lives_widget_is_sensitive(widget)) lives_widget_set_sensitive(buttond, FALSE);
397 lives_widget_set_show_hide_with(widget, buttond);
398 lives_widget_set_sensitive_with(widget, buttond);
399
400 lives_widget_destroy_with(buttond, tbox);
401
402 lives_signal_sync_connect(LIVES_GUI_OBJECT(param->widgets[1]), LIVES_WIDGET_FONT_SET_SIGNAL,
403 LIVES_GUI_CALLBACK(font_set_cb), (livespointer)rfx);
404
405 fchooser.entry_func = lives_signal_sync_connect(LIVES_GUI_OBJECT(widget),
406 LIVES_WIDGET_CHANGED_SIGNAL,
407 LIVES_GUI_CALLBACK(font_entry_cb), (livespointer)rfx);
408
409 if (fchooser.nwidgets == 1) {
410 double fsize = get_double_param(fchooser.size_param);
411 lives_entry_set_text(LIVES_ENTRY(param->widgets[0]), param->value);
412 font_entry_cb(LIVES_ENTRY(param->widgets[0]), (livespointer)rfx);
413 lives_spin_button_set_value(LIVES_SPIN_BUTTON(fchooser.size_param->widgets[0]), fsize);
414 text_size_cb(LIVES_SPIN_BUTTON(fchooser.size_param->widgets[0]), (livespointer)rfx);
415 }
416 fchooser.nwidgets++;
417 }
418
419 if (param == fchooser.size_param) {
420 fchooser.size_paramfunc = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget),
421 LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
422 LIVES_GUI_CALLBACK(text_size_cb), (livespointer)rfx);
423 if (fchooser.nwidgets == 1) {
424 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), get_double_param(param->value));
425 text_size_cb(LIVES_SPIN_BUTTON(fchooser.size_param->widgets[0]), (livespointer)rfx);
426 }
427 fchooser.nwidgets++;
428 }
429 #endif
430
431 if ((param == aspect.width_param || param == aspect.height_param) && aspect.nwidgets == 2) {
432 boolean expand = widget_opts.expand == LIVES_EXPAND_EXTRA;
433 char *labeltext = (_("Maintain _Aspect Ratio"));
434
435 aspect.no_reset = TRUE;
436 aspect.lockbutton = lives_standard_lock_button_new(TRUE, ASPECT_BUTTON_WIDTH,
437 ASPECT_BUTTON_HEIGHT, labeltext, NULL);
438 lives_free(labeltext);
439
440 lives_signal_sync_connect(aspect.lockbutton, LIVES_WIDGET_CLICKED_SIGNAL,
441 LIVES_GUI_CALLBACK(reset_aspect), (livespointer)&aspect);
442
443 reset_aspect(LIVES_BUTTON(aspect.lockbutton), &aspect);
444
445 hbox = lives_hbox_new(FALSE, 0);
446 lives_widget_apply_theme(hbox, LIVES_WIDGET_STATE_NORMAL);
447
448 if (!LIVES_IS_HBOX(pbox)) {
449 hbox = lives_hbox_new(FALSE, 0);
450 lives_widget_show(hbox);
451 lives_box_pack_start(LIVES_BOX(LIVES_WIDGET(pbox)), hbox, FALSE, FALSE, widget_opts.packing_height * 2);
452 lives_box_pack_end(LIVES_BOX(hbox), aspect.lockbutton, expand, FALSE, 0);
453 } else {
454 lives_box_pack_start(LIVES_BOX(LIVES_WIDGET(pbox)), hbox, FALSE, FALSE, widget_opts.packing_width * 1.5);
455 lives_box_pack_start(LIVES_BOX(hbox), aspect.lockbutton, expand, FALSE, 0);
456 }
457
458 if (expand) add_fill_to_box(LIVES_BOX(hbox));
459 }
460 }
461
462 slist = fileread;
463 while (slist) {
464 if (param == (lives_param_t *)(slist->data)) {
465 char *def_dir;
466 if (!widget) continue;
467
468 box = lives_widget_get_parent(widget);
469
470 while (box && !LIVES_IS_HBOX(box)) {
471 box = lives_widget_get_parent(box);
472 }
473
474 if (!box) return;
475
476 def_dir = lives_get_current_dir();
477
478 if (LIVES_IS_ENTRY(widget)) {
479 if (*(lives_entry_get_text(LIVES_ENTRY(widget)))) {
480 char dirnamex[PATH_MAX];
481 lives_snprintf(dirnamex, PATH_MAX, "%s", lives_entry_get_text(LIVES_ENTRY(widget)));
482 get_dirname(dirnamex);
483 lives_free(def_dir);
484 def_dir = lives_strdup(dirnamex);
485 }
486 }
487
488 param->widgets[2] = buttond = lives_standard_file_button_new(FALSE, def_dir);
489 lives_free(def_dir);
490 lives_box_pack_start(LIVES_BOX(box), buttond, FALSE, FALSE, widget_opts.packing_width);
491
492 lives_signal_sync_connect(buttond, LIVES_WIDGET_CLICKED_SIGNAL, LIVES_GUI_CALLBACK(on_filesel_button_clicked),
493 (livespointer)widget);
494
495 if (!lives_widget_is_sensitive(widget)) lives_widget_set_sensitive(buttond, FALSE);
496 lives_widget_set_show_hide_with(widget, buttond);
497 lives_widget_set_sensitive_with(widget, buttond);
498
499 if (LIVES_IS_ENTRY(widget)) {
500 lives_entry_set_editable(LIVES_ENTRY(widget), FALSE);
501 if (param->widgets[1] &&
502 LIVES_IS_LABEL(param->widgets[1]) &&
503 lives_label_get_mnemonic_widget(LIVES_LABEL(param->widgets[1])) != NULL)
504 lives_label_set_mnemonic_widget(LIVES_LABEL(param->widgets[1]), buttond);
505 lives_entry_set_max_length(LIVES_ENTRY(widget), PATH_MAX);
506 }
507 }
508
509 slist = slist->next;
510 }
511
512 slist = filewrite;
513 while (slist) {
514 if (param == (lives_param_t *)(slist->data)) {
515
516 if (!widget) continue;
517
518 box = lives_widget_get_parent(widget);
519
520 while (box && !LIVES_IS_HBOX(box)) {
521 box = lives_widget_get_parent(box);
522 }
523
524 if (!box) return;
525
526 param->widgets[2] = buttond = lives_standard_file_button_new(FALSE, NULL);
527
528 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(buttond), FILESEL_TYPE_KEY, (livespointer)LIVES_FILE_SELECTION_SAVE);
529 lives_box_pack_start(LIVES_BOX(box), buttond, FALSE, FALSE, widget_opts.packing_width);
530 lives_signal_sync_connect(buttond, LIVES_WIDGET_CLICKED_SIGNAL, LIVES_GUI_CALLBACK(on_filesel_button_clicked),
531 (livespointer)widget);
532
533 if (!lives_widget_is_sensitive(widget)) lives_widget_set_sensitive(buttond, FALSE);
534 lives_widget_set_show_hide_with(widget, buttond);
535 lives_widget_set_sensitive_with(widget, buttond);
536
537 if (LIVES_IS_ENTRY(widget)) {
538 lives_entry_set_editable(LIVES_ENTRY(widget), TRUE);
539 if (param->widgets[1] &&
540 LIVES_IS_LABEL(param->widgets[1]) &&
541 lives_label_get_mnemonic_widget(LIVES_LABEL(param->widgets[1])) != NULL)
542 lives_label_set_mnemonic_widget(LIVES_LABEL(param->widgets[1]), buttond);
543 lives_entry_set_max_length(LIVES_ENTRY(widget), PATH_MAX);
544 }
545 }
546
547 slist = slist->next;
548 }
549
550 // password fields
551
552 for (slist = passwd_widgets; slist; slist = slist->next) {
553 if (param == (lives_param_t *)(slist->data)) {
554 if (!widget) continue;
555
556 lives_entry_set_visibility(LIVES_ENTRY(widget), FALSE);
557
558 box = lives_widget_get_parent(widget);
559
560 while (box && !LIVES_IS_BOX(box)) {
561 box = lives_widget_get_parent(box);
562 }
563
564 if (!box) continue;
565
566 if (!LIVES_IS_HBOX(box)) {
567 hbox = lives_hbox_new(FALSE, 0);
568 lives_box_pack_start(LIVES_BOX(LIVES_WIDGET(box)), hbox, FALSE, FALSE, widget_opts.packing_height);
569 } else hbox = box;
570
571 param->widgets[2] = checkbutton = lives_standard_check_button_new(_("Display Password"), FALSE, LIVES_BOX(hbox), NULL);
572
573 lives_button_set_focus_on_click(LIVES_BUTTON(checkbutton), FALSE);
574
575 if (!lives_widget_is_sensitive(widget)) lives_widget_set_sensitive(checkbutton, FALSE);
576 lives_widget_show_all(hbox);
577
578 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
579 LIVES_GUI_CALLBACK(passwd_toggle_vis), (livespointer)widget);
580 }
581 }
582 }
583
584
after_aspect_width_changed(LiVESSpinButton * spinbutton,livespointer user_data)585 void after_aspect_width_changed(LiVESSpinButton * spinbutton, livespointer user_data) {
586 if (lives_lock_button_get_locked(LIVES_BUTTON(aspect.lockbutton))) {
587 int width = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
588 double height = (double)width / aspect.ratio;
589 LiVESWidget *spbutton = aspect.height_param->widgets[0];
590 lives_signal_handler_block(spbutton, aspect.height_func);
591 aspect.width_param->change_blocked = TRUE;
592 height = lives_spin_button_get_snapval(LIVES_SPIN_BUTTON(spbutton), height);
593 lives_spin_button_set_value(LIVES_SPIN_BUTTON(spbutton), height);
594 lives_spin_button_update(LIVES_SPIN_BUTTON(spbutton));
595 lives_signal_handler_unblock(spbutton, aspect.height_func);
596 aspect.width_param->change_blocked = FALSE;
597 }
598 }
599
600
after_aspect_height_changed(LiVESToggleButton * spinbutton,livespointer user_data)601 void after_aspect_height_changed(LiVESToggleButton * spinbutton, livespointer user_data) {
602 if (lives_lock_button_get_locked(LIVES_BUTTON(aspect.lockbutton))) {
603 int height = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
604 double width = (double)height * aspect.ratio;
605 LiVESWidget *spbutton = aspect.width_param->widgets[0];
606 lives_signal_handler_block(spbutton, aspect.width_func);
607 aspect.height_param->change_blocked = TRUE;
608 width = lives_spin_button_get_snapval(LIVES_SPIN_BUTTON(spbutton), width);
609 lives_spin_button_set_value(LIVES_SPIN_BUTTON(spbutton), width);
610 lives_spin_button_update(LIVES_SPIN_BUTTON(spbutton));
611 lives_signal_handler_unblock(spbutton, aspect.width_func);
612 aspect.height_param->change_blocked = FALSE;
613 }
614 }
615
616
check_filewrite_overwrites(void)617 boolean check_filewrite_overwrites(void) {
618 // check all writeable files which were user edited (param->edited), to make sure we don't overwrite without permission
619 // if the value was set by the file button we would have checked there, and param->edited will be FALSE
620
621 if (filewrite) {
622 LiVESList *slist = filewrite;
623 while (slist) {
624 lives_param_t *param = (lives_param_t *)(slist->data);
625 if (param->edited) {
626 // check for overwrite
627 if (LIVES_IS_ENTRY(param->widgets[0])) {
628 if (*(lives_entry_get_text(LIVES_ENTRY(param->widgets[0])))) {
629 if (!check_file(lives_entry_get_text(LIVES_ENTRY(param->widgets[0])), TRUE)) {
630 return FALSE;
631 // *INDENT-OFF*
632 }}}}
633 slist = slist->next;
634 }}
635 // *INDENT-ON*
636
637 return TRUE;
638 }
639
640
special_cleanup(boolean is_ok)641 boolean special_cleanup(boolean is_ok) {
642 // free some memory now
643 if (special_inited) {
644 if (is_ok && !check_filewrite_overwrites()) return FALSE;
645 aspect.no_reset = FALSE;
646
647 mainw->framedraw = mainw->framedraw_reset = NULL;
648 mainw->framedraw_spinbutton = NULL;
649
650 if (mainw->fd_layer) weed_layer_free(mainw->fd_layer);
651 mainw->fd_layer = NULL;
652
653 if (mainw->fd_layer_orig) weed_layer_free(mainw->fd_layer_orig);
654 mainw->fd_layer_orig = NULL;
655
656 mainw->framedraw_preview = NULL;
657
658 if (framedraw.extra_params) lives_free(framedraw.extra_params);
659 framedraw.extra_params = NULL;
660
661 framedraw.type = LIVES_PARAM_SPECIAL_TYPE_NONE;
662
663 if (fileread) lives_list_free(fileread);
664 fileread = NULL;
665
666 if (filewrite) lives_list_free(filewrite);
667 filewrite = NULL;
668
669 if (passwd_widgets) lives_list_free(passwd_widgets);
670 passwd_widgets = NULL;
671
672 fchooser.nwidgets = 0;
673
674 framedraw.added = FALSE;
675 special_inited = FALSE;
676 }
677 return TRUE;
678 }
679
680
set_aspect_ratio_widgets(lives_param_t * w,lives_param_t * h)681 LIVES_GLOBAL_INLINE void set_aspect_ratio_widgets(lives_param_t *w, lives_param_t *h) {
682 aspect.width_param = w;
683 aspect.height_param = h;
684 }
685
686
setmergealign(void)687 void setmergealign(void) {
688 lives_param_t *param;
689 int cb_frames = clipboard->frames;
690
691 if (prefs->ins_resample && clipboard->fps != cfile->fps) {
692 cb_frames = count_resampled_frames(clipboard->frames, clipboard->fps, cfile->fps);
693 }
694
695 if (cfile->end - cfile->start + 1 > (cb_frames * ((merge_opts && merge_opts->spinbutton_loops) ?
696 lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(merge_opts->spinbutton_loops)) : 1))
697 && !merge_opts->loop_to_fit) {
698 // set special transalign widgets to their default values
699 if (mergealign.start_param && mergealign.start_param->widgets[0] && LIVES_IS_SPIN_BUTTON
700 (mergealign.start_param->widgets[0]) && (param = mergealign.start_param)->type == LIVES_PARAM_NUM) {
701 if (param->dp) {
702 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), get_double_param(param->def));
703 } else {
704 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)get_int_param(param->def));
705 }
706 }
707 if (mergealign.end_param && mergealign.end_param->widgets[0] && LIVES_IS_SPIN_BUTTON
708 (mergealign.end_param->widgets[0]) && (param = mergealign.end_param)->type == LIVES_PARAM_NUM) {
709 if (param->dp) {
710 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), get_double_param(param->def));
711 } else {
712 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)get_int_param(param->def));
713 }
714 }
715 } else {
716 if (merge_opts->align_start) {
717 // set special transalign widgets to min/max values
718 if (mergealign.start_param && mergealign.start_param->widgets[0] && LIVES_IS_SPIN_BUTTON
719 (mergealign.start_param->widgets[0]) && (param = mergealign.start_param)->type == LIVES_PARAM_NUM) {
720 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)param->min);
721 }
722 if (mergealign.end_param && mergealign.end_param->widgets[0] && LIVES_IS_SPIN_BUTTON
723 (mergealign.end_param->widgets[0]) && (param = mergealign.end_param)->type == LIVES_PARAM_NUM) {
724 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)param->max);
725 }
726 } else {
727 // set special transalign widgets to max/min values
728 if (mergealign.start_param && mergealign.start_param->widgets[0] && LIVES_IS_SPIN_BUTTON
729 (mergealign.start_param->widgets[0]) && (param = mergealign.start_param)->type == LIVES_PARAM_NUM) {
730 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)param->max);
731 }
732 if (mergealign.end_param && mergealign.end_param->widgets[0] && LIVES_IS_SPIN_BUTTON
733 (mergealign.end_param->widgets[0]) && (param = mergealign.end_param)->type == LIVES_PARAM_NUM) {
734 lives_spin_button_set_value(LIVES_SPIN_BUTTON(param->widgets[0]), (double)param->min);
735 // *INDENT-OFF*
736 }}}
737 // *INDENT-OFF*
738 }
739
740
mt_framedraw(lives_mt * mt,weed_layer_t * layer)741 LiVESPixbuf *mt_framedraw(lives_mt * mt, weed_layer_t *layer) {
742 LiVESPixbuf *pixbuf = NULL;
743
744 if (framedraw.added) {
745 switch (framedraw.type) {
746 case LIVES_PARAM_SPECIAL_TYPE_RECT_MULTIRECT:
747 if (mt->track_index == -1) {
748 // TODO - hide widgets
749 } else {
750 //
751 }
752 break;
753
754 default:
755 break;
756 }
757
758 // draw on top of layer
759 framedraw_redraw(&framedraw, layer);
760 }
761 return pixbuf;
762 }
763
764
is_perchannel_multi(lives_rfx_t * rfx,int i)765 boolean is_perchannel_multi(lives_rfx_t *rfx, int i) {
766 // updated for weed spec 1.1
767 if (rfx->params[i].multi == PVAL_MULTI_PER_CHANNEL) return TRUE;
768 return FALSE;
769 }
770
771