1 // ce_thumbs.c
2 // LiVES
3 // (c) G. Finch 2013 - 2019 <salsaman+lives@gmail.com>
4 // Released under the GNU GPL 3 or later
5 // see file ../COPYING for licensing details
6
7 // clip thumbnails window for dual head mode
8
9 // TODO - buttons for some keys ?
10
11 // TODO - drag fx order : check for data conx
12
13 // TODO - user defined screen mapping areas
14
15 #include "main.h"
16 #include "effects-weed.h"
17 #include "effects.h"
18 #include "paramwindow.h"
19 #include "ce_thumbs.h"
20 #include "callbacks.h"
21
22 static LiVESWidget **fxcombos;
23 static LiVESWidget **pscrolls;
24 static LiVESWidget **combo_entries;
25 static LiVESWidget **key_checks;
26 static LiVESWidget **rb_fx_areas;
27 static LiVESWidget **rb_clip_areas;
28 static LiVESWidget **clip_boxes;
29 static LiVESWidget *param_hbox;
30 static LiVESWidget *top_hbox;
31
32 static ulong *ch_fns;
33 static ulong *combo_fns;
34 static ulong *rb_clip_fns;
35 static ulong *rb_fx_fns;
36
37 static int rte_keys_virtual;
38 static int n_screen_areas;
39 static int n_clip_boxes;
40
41 static int next_screen_area;
42
43 static void ce_thumbs_remove_param_boxes(boolean remove_pinned);
44 static void ce_thumbs_remove_param_box(int key);
45
46
ce_thumbs_set_interactive(boolean interactive)47 void ce_thumbs_set_interactive(boolean interactive) {
48 int i;
49
50 if (!interactive) {
51 for (i = 0; i < rte_keys_virtual; i++) {
52 lives_widget_set_sensitive(fxcombos[i], FALSE);
53 lives_widget_set_sensitive(key_checks[i], FALSE);
54 }
55 } else {
56 for (i = 0; i < rte_keys_virtual; i++) {
57 lives_widget_set_sensitive(fxcombos[i], TRUE);
58 if (rte_key_getmaxmode(i + 1) > 0) {
59 lives_widget_set_sensitive(key_checks[i], TRUE);
60 // *INDENT-OFF*
61 }}}
62 // *INDENT-ON*
63 }
64
65
66 #if LIVES_HAS_GRID_WIDGET
switch_clip_cb(LiVESWidget * eventbox,LiVESXEventButton * event,livespointer user_data)67 static boolean switch_clip_cb(LiVESWidget * eventbox, LiVESXEventButton * event, livespointer user_data) {
68 int i = LIVES_POINTER_TO_INT(user_data);
69 if (!LIVES_IS_PLAYING) return FALSE;
70 if (!LIVES_IS_INTERACTIVE) return FALSE;
71 switch_clip(0, i, FALSE);
72 return FALSE;
73 }
74
75
ce_thumbs_fx_changed(LiVESCombo * combo,livespointer user_data)76 static void ce_thumbs_fx_changed(LiVESCombo * combo, livespointer user_data) {
77 // callback after user switches fx via combo
78 int key = LIVES_POINTER_TO_INT(user_data);
79 int mode, cmode;
80
81 if ((mode = lives_combo_get_active_index(combo)) == -1) return; // -1 is returned after we set our own text (without the type)
82 cmode = rte_key_getmode(key + 1);
83
84 if (cmode == mode) return;
85
86 lives_widget_grab_focus(combo_entries[key]);
87
88 rte_key_setmode(key + 1, mode);
89 }
90 #endif
91
92
ce_thumbs_set_key_check_state(void)93 void ce_thumbs_set_key_check_state(void) {
94 // set (delayed) keycheck state
95 for (int i = 0; i < prefs->rte_keys_virtual; i++) {
96 lives_signal_handler_block(key_checks[i], ch_fns[i]);
97 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[i]),
98 LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(key_checks[i]),
99 "active")));
100 if (!lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(key_checks[i])) && pscrolls[i]) ce_thumbs_remove_param_box(i);
101 lives_signal_handler_unblock(key_checks[i], ch_fns[i]);
102 }
103 }
104
105
ce_thumbs_set_keych(int key,boolean on)106 void ce_thumbs_set_keych(int key, boolean on) {
107 // set key check from other source
108 if (key >= rte_keys_virtual) return;
109 lives_signal_handler_block(key_checks[key], ch_fns[key]);
110 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[key]), on);
111 if (!on && pscrolls[key]) ce_thumbs_remove_param_box(key);
112 lives_signal_handler_unblock(key_checks[key], ch_fns[key]);
113 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(key_checks[key]), "active", LIVES_INT_TO_POINTER(on));
114 }
115
116
ce_thumbs_set_mode_combo(int key,int mode)117 void ce_thumbs_set_mode_combo(int key, int mode) {
118 // set combo from other source : need to add params after
119 if (key >= rte_keys_virtual || mode < 0) return;
120 lives_signal_handler_block(fxcombos[key], combo_fns[key]);
121 lives_combo_set_active_index(LIVES_COMBO(fxcombos[key]), mode);
122 ce_thumbs_remove_param_box(key);
123 lives_signal_handler_unblock(fxcombos[key], combo_fns[key]);
124 }
125
126
pin_toggled(LiVESToggleButton * t,livespointer pkey)127 static void pin_toggled(LiVESToggleButton * t, livespointer pkey) {
128 int key = LIVES_POINTER_TO_INT(pkey);
129 boolean state = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[key]), "pinned"));
130 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pscrolls[key]), "pinned", LIVES_INT_TO_POINTER(!state));
131 }
132
133 #if LIVES_HAS_GRID_WIDGET
134
clip_area_toggled(LiVESToggleButton * t,livespointer parea)135 static void clip_area_toggled(LiVESToggleButton * t, livespointer parea) {
136 int area = LIVES_POINTER_TO_INT(parea);
137 if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(rb_clip_areas[area]))) {
138 mainw->active_sa_clips = area;
139 ce_thumbs_highlight_current_clip();
140 }
141 }
142
143 #endif
144
145 #define SPARE_CLIP_BOXES 100
146
start_ce_thumb_mode(void)147 void start_ce_thumb_mode(void) {
148 #if LIVES_HAS_GRID_WIDGET
149
150 LiVESWidget *thumb_image = NULL;
151 LiVESWidget *vbox, *vbox2, *vbox3;
152 LiVESWidget *usibl = NULL, *sibl = NULL;
153 LiVESWidget *hbox, *hbox2;
154 LiVESWidget *tscroll, *cscroll;
155 LiVESWidget *label;
156 LiVESWidget *arrow;
157
158 LiVESWidget *tgrid = lives_grid_new();
159
160 LiVESWidget *align;
161
162 LiVESPixbuf *thumbnail;
163
164 LiVESList *cliplist = mainw->cliplist;
165 LiVESList *fxlist = NULL;
166
167 GSList *rb_fx_areas_group = NULL;
168 GSList *rb_clip_areas_group = NULL;
169
170 char filename[PATH_MAX];
171 char *tmp;
172
173 int width = CLIP_THUMB_WIDTH, height = CLIP_THUMB_HEIGHT;
174 int modes = rte_getmodespk();
175 int cpw;
176
177 int count = -1, rcount = 0;
178
179 int i, j;
180
181 rte_keys_virtual = prefs->rte_keys_virtual;
182 n_screen_areas = mainw->n_screen_areas;
183 n_clip_boxes = lives_list_length(mainw->cliplist) + SPARE_CLIP_BOXES;
184
185 next_screen_area = SCREEN_AREA_NONE;
186
187 lives_grid_set_row_spacing(LIVES_GRID(tgrid), 0);
188 lives_grid_set_column_spacing(LIVES_GRID(tgrid), 0);
189
190 //lives_container_set_border_width (LIVES_CONTAINER (tgrid), width);
191
192 // dual monitor mode, the gui monitor can show clip thumbnails
193
194 top_hbox = lives_hbox_new(FALSE, 0);
195 lives_widget_object_ref(mainw->top_vbox);
196 lives_widget_unparent(mainw->top_vbox);
197
198 lives_container_add(LIVES_CONTAINER(LIVES_MAIN_WINDOW_WIDGET), top_hbox);
199 lives_widget_queue_draw(LIVES_MAIN_WINDOW_WIDGET);
200 //lives_box_pack_start(LIVES_BOX(mainw->top_vbox), top_hbox, TRUE, TRUE, 0);
201
202 if (palette->style & STYLE_1) lives_widget_set_bg_color(top_hbox, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
203
204 // fx area
205 vbox = lives_vbox_new(FALSE, widget_opts.packing_height);
206
207 tscroll = lives_standard_scrolled_window_new(width, height, vbox);
208 lives_box_pack_start(LIVES_BOX(top_hbox), tscroll, FALSE, TRUE, 0);
209 lives_scrolled_window_set_policy(LIVES_SCROLLED_WINDOW(tscroll), LIVES_POLICY_NEVER, LIVES_POLICY_AUTOMATIC);
210 lives_widget_set_hexpand(tscroll, FALSE);
211
212 fxcombos = (LiVESWidget **)lives_malloc((rte_keys_virtual) * modes * sizeof(LiVESWidget *));
213 pscrolls = (LiVESWidget **)lives_malloc((rte_keys_virtual) * modes * sizeof(LiVESWidget *));
214 combo_entries = (LiVESWidget **)lives_malloc((rte_keys_virtual) * modes * sizeof(LiVESWidget *));
215 key_checks = (LiVESWidget **)lives_malloc((rte_keys_virtual) * modes * sizeof(LiVESWidget *));
216
217 rb_fx_areas = (LiVESWidget **)lives_malloc((n_screen_areas) * modes * sizeof(LiVESWidget *));
218 rb_clip_areas = (LiVESWidget **)lives_malloc((n_screen_areas) * modes * sizeof(LiVESWidget *));
219
220 clip_boxes = (LiVESWidget **)lives_malloc((n_clip_boxes) * modes * sizeof(LiVESWidget *));
221
222 ch_fns = (ulong *)lives_malloc((rte_keys_virtual) * sizeof(ulong));
223 combo_fns = (ulong *)lives_malloc((rte_keys_virtual) * sizeof(ulong));
224 rb_clip_fns = (ulong *)lives_malloc((n_screen_areas) * sizeof(ulong));
225 rb_fx_fns = (ulong *)lives_malloc((n_screen_areas) * sizeof(ulong));
226
227 for (i = 0; i < n_clip_boxes; i++) {
228 clip_boxes[i] = NULL;
229 }
230
231 for (i = 0; i < rte_keys_virtual; i++) {
232 pscrolls[i] = NULL;
233
234 fxlist = NULL;
235
236 for (j = 0; j <= rte_key_getmaxmode(i + 1); j++) {
237 fxlist = lives_list_append(fxlist, rte_keymode_get_filter_name(i + 1, j, FALSE));
238 }
239
240 hbox = lives_hbox_new(FALSE, 0);
241 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
242
243 tmp = lives_strdup_printf(_("Mapped to ctrl-%d"), i + 1);
244 key_checks[i] = lives_standard_check_button_new(NULL, (mainw->rte & (GU641 << i)), LIVES_BOX(hbox), tmp);
245 lives_free(tmp);
246
247 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[i]), mainw->rte & (GU641 << i));
248 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(key_checks[i]), "active",
249 LIVES_INT_TO_POINTER(lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(key_checks[i]))));
250
251 ch_fns[i] = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(key_checks[i]), LIVES_WIDGET_TOGGLED_SIGNAL,
252 LIVES_GUI_CALLBACK(rte_on_off_callback_hook), LIVES_INT_TO_POINTER(i + 1));
253
254 fxcombos[i] = lives_standard_combo_new(NULL, fxlist, LIVES_BOX(hbox), NULL);
255
256 if (fxlist) {
257 lives_list_free_all(&fxlist);
258 lives_combo_set_active_index(LIVES_COMBO(fxcombos[i]), rte_key_getmode(i + 1));
259 } else {
260 lives_widget_set_sensitive(key_checks[i], FALSE);
261 }
262
263 combo_entries[i] = lives_combo_get_entry(LIVES_COMBO(fxcombos[i]));
264
265 lives_entry_set_editable(LIVES_ENTRY(combo_entries[i]), FALSE);
266
267 combo_fns[i] = lives_signal_sync_connect(LIVES_GUI_OBJECT(fxcombos[i]), LIVES_WIDGET_CHANGED_SIGNAL,
268 LIVES_GUI_CALLBACK(ce_thumbs_fx_changed), LIVES_INT_TO_POINTER(i));
269 }
270
271 add_vsep_to_box(LIVES_BOX(top_hbox));
272
273 // rhs vbox
274 vbox2 = lives_vbox_new(FALSE, 0);
275 lives_box_pack_start(LIVES_BOX(top_hbox), vbox2, TRUE, TRUE, 0);
276
277 // rhs top hbox
278 hbox2 = lives_hbox_new(FALSE, widget_opts.packing_width);
279 lives_box_pack_start(LIVES_BOX(vbox2), hbox2, TRUE, TRUE, 0);
280
281 // vbox for arrows and areas
282 vbox3 = lives_vbox_new(FALSE, 0);
283 lives_box_pack_start(LIVES_BOX(hbox2), vbox3, FALSE, TRUE, 0);
284
285 // add arrows
286 hbox = lives_hbox_new(FALSE, 0);
287 lives_widget_set_hexpand(hbox, FALSE);
288
289 lives_box_pack_start(LIVES_BOX(vbox3), hbox, FALSE, TRUE, 0);
290 arrow = lives_arrow_new(LIVES_ARROW_LEFT, LIVES_SHADOW_NONE);
291 lives_box_pack_start(LIVES_BOX(hbox), arrow, FALSE, TRUE, 0);
292
293 label = lives_standard_label_new(_("Effects"));
294 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, TRUE, 0);
295 add_fill_to_box(LIVES_BOX(hbox));
296 label = lives_standard_label_new(_("Clips"));
297 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, TRUE, 0);
298
299 arrow = lives_arrow_new(LIVES_ARROW_RIGHT, LIVES_SHADOW_NONE);
300 lives_box_pack_start(LIVES_BOX(hbox), arrow, FALSE, TRUE, 0);
301
302 // screen areas
303 vbox = lives_vbox_new(FALSE, widget_opts.packing_height);
304 tscroll = lives_standard_scrolled_window_new(width, height, vbox);
305
306 lives_box_pack_start(LIVES_BOX(vbox3), tscroll, FALSE, TRUE, 0);
307 lives_scrolled_window_set_policy(LIVES_SCROLLED_WINDOW(tscroll), LIVES_POLICY_NEVER, LIVES_POLICY_AUTOMATIC);
308 lives_widget_set_hexpand(tscroll, FALSE);
309
310 for (i = 0; i < n_screen_areas; i++) {
311 hbox = lives_hbox_new(FALSE, 0);
312 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
313
314 // radiobuttons for fx
315 rb_fx_areas[i] = lives_standard_radio_button_new("", &rb_fx_areas_group, LIVES_BOX(hbox),
316 (tmp = lives_strdup_printf(_("Show / apply effects to %s\n"),
317 mainw->screen_areas[i].name)));
318 lives_free(tmp);
319
320 if (i != SCREEN_AREA_FOREGROUND) lives_widget_set_sensitive(rb_fx_areas[i], FALSE);
321
322 label = lives_standard_label_new(mainw->screen_areas[i].name);
323 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, TRUE, 0);
324
325 // radiobuttons for fx
326 rb_clip_areas[i] = lives_standard_radio_button_new("",
327 &rb_clip_areas_group, LIVES_BOX(hbox),
328 (tmp = lives_strdup_printf(_("Select clip for %s\n"),
329 mainw->screen_areas[i].name)));
330 lives_free(tmp);
331
332 rb_clip_fns[i] = lives_signal_sync_connect(LIVES_GUI_OBJECT(rb_clip_areas[i]), LIVES_WIDGET_TOGGLED_SIGNAL,
333 LIVES_GUI_CALLBACK(clip_area_toggled), LIVES_INT_TO_POINTER(i));
334 }
335
336 add_vsep_to_box(LIVES_BOX(hbox2));
337
338 cscroll = lives_standard_scrolled_window_new(width, height, tgrid);
339 lives_scrolled_window_set_policy(LIVES_SCROLLED_WINDOW(cscroll), LIVES_POLICY_NEVER, LIVES_POLICY_AUTOMATIC);
340 lives_box_pack_start(LIVES_BOX(hbox2), cscroll, TRUE, TRUE, 0);
341
342 ////
343 add_hsep_to_box(LIVES_BOX(vbox2));
344
345 // insert a scrolled window for param boxes
346 param_hbox = lives_hbox_new(FALSE, 0);
347
348 tscroll = lives_standard_scrolled_window_new(width, height, param_hbox);
349 lives_scrolled_window_set_policy(LIVES_SCROLLED_WINDOW(tscroll), LIVES_POLICY_AUTOMATIC, LIVES_POLICY_AUTOMATIC);
350
351 lives_box_pack_start(LIVES_BOX(vbox2), tscroll, TRUE, TRUE, 0);
352
353 lives_widget_hide(mainw->eventbox);
354 if (prefs->show_msg_area) lives_widget_hide(mainw->message_box);
355 lives_widget_show_all(top_hbox);
356
357 lives_widget_context_update(); // need size of cscroll to fit thumbs
358
359 cpw = (lives_widget_get_allocation_width(tscroll) - widget_opts.border_width * 2) / (width * 1.5) - 2;
360
361 // add thumbs to grid
362
363 while (cliplist) {
364 count++;
365
366 i = LIVES_POINTER_TO_INT(cliplist->data);
367 if (i == mainw->scrap_file || i == mainw->ascrap_file ||
368 (!IS_NORMAL_CLIP(i) &&
369 mainw->files[i]->clip_type != CLIP_TYPE_YUV4MPEG && mainw->files[i]->clip_type != CLIP_TYPE_VIDEODEV) ||
370 !CLIP_HAS_VIDEO(i)) {
371 cliplist = cliplist->next;
372 continue;
373 }
374
375 // make a small thumbnail, add it to the clips box
376 thumbnail = make_thumb(NULL, i, width, height, mainw->files[i]->start, LIVES_INTERP_NORMAL, TRUE);
377
378 clip_boxes[count] = lives_event_box_new();
379 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(clip_boxes[count]), "clipno", LIVES_INT_TO_POINTER(i));
380 lives_widget_set_size_request(clip_boxes[count], width * 1.5, height * 1.5);
381
382 if (palette->style & STYLE_1) {
383 lives_widget_set_bg_color(clip_boxes[count], LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
384 lives_widget_set_bg_color(clip_boxes[count], LIVES_WIDGET_STATE_PRELIGHT, &palette->menu_and_bars);
385 }
386
387 lives_widget_add_events(clip_boxes[count], LIVES_BUTTON_PRESS_MASK);
388
389 align = lives_alignment_new(.5, .5, 0., 0.);
390
391 thumb_image = lives_image_new();
392 lives_image_set_from_pixbuf(LIVES_IMAGE(thumb_image), thumbnail);
393 if (thumbnail) lives_widget_object_unref(thumbnail);
394 lives_container_add(LIVES_CONTAINER(clip_boxes[count]), align);
395
396 if (rcount > 0) {
397 if (rcount == cpw - 1) rcount = 0;
398 else {
399 lives_grid_attach_next_to(LIVES_GRID(tgrid), clip_boxes[count], sibl, LIVES_POS_RIGHT, 1, 1);
400 sibl = clip_boxes[count];
401 }
402 }
403
404 if (rcount == 0) {
405 lives_grid_attach_next_to(LIVES_GRID(tgrid), clip_boxes[count], usibl, LIVES_POS_BOTTOM, 1, 1);
406 sibl = usibl = clip_boxes[count];
407 }
408
409 lives_snprintf(filename, PATH_MAX, "%s", (tmp = lives_path_get_basename(mainw->files[i]->name)));
410 lives_free(tmp);
411 get_basename(filename);
412 lives_widget_set_tooltip_text(clip_boxes[count], filename);
413
414 //if (palette->style&STYLE_3) lives_widget_set_fg_color (label, LIVES_WIDGET_STATE_PRELIGHT, &palette->info_text);
415 //if (palette->style&STYLE_4) lives_widget_set_fg_color (label, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
416
417 lives_container_add(LIVES_CONTAINER(align), thumb_image);
418
419 rcount++;
420
421 lives_signal_sync_connect(LIVES_GUI_OBJECT(clip_boxes[count]), LIVES_WIDGET_BUTTON_PRESS_EVENT,
422 LIVES_GUI_CALLBACK(switch_clip_cb), LIVES_INT_TO_POINTER(i));
423
424 cliplist = cliplist->next;
425 }
426
427 if (prefs->open_maximised) {
428 lives_window_maximize(LIVES_WINDOW(LIVES_MAIN_WINDOW_WIDGET));
429 }
430
431 lives_widget_show_all(top_hbox);
432
433 ce_thumbs_liberate_clip_area(mainw->num_tr_applied > 0 ? SCREEN_AREA_BACKGROUND : SCREEN_AREA_FOREGROUND);
434 ce_thumbs_set_clip_area();
435
436 mainw->ce_thumbs = TRUE;
437
438 #endif
439 }
440
441
end_ce_thumb_mode(void)442 void end_ce_thumb_mode(void) {
443 mainw->ce_thumbs = FALSE;
444 ce_thumbs_remove_param_boxes(TRUE);
445 lives_widget_destroy(top_hbox);
446 lives_container_add(LIVES_CONTAINER(LIVES_MAIN_WINDOW_WIDGET), mainw->top_vbox);
447 lives_widget_show(mainw->eventbox);
448 if (prefs->show_msg_area) lives_widget_show(mainw->message_box);
449 lives_free(fxcombos); lives_free(pscrolls); lives_free(combo_entries);
450 lives_free(key_checks); lives_free(rb_fx_areas); lives_free(rb_clip_areas);
451 lives_free(clip_boxes); lives_free(ch_fns); lives_free(rb_clip_fns);
452 lives_free(rb_fx_fns);
453 }
454
455
ce_thumbs_add_param_box(int key,boolean remove)456 void ce_thumbs_add_param_box(int key, boolean remove) {
457 // when an effect with params is applied, show the parms in a box
458 weed_plant_t *inst;
459 lives_rfx_t *rfx;
460
461 LiVESWidget *vbox;
462 LiVESWidget *hbox;
463 LiVESWidget *label;
464 LiVESWidget *pin_check;
465
466 char *fname, *tmp, *tmp2;
467
468 int mode = rte_key_getmode(key + 1);
469
470 if (key >= rte_keys_virtual) return;
471
472 if (remove) {
473 // remove old boxes unless pinned
474 ce_thumbs_remove_param_boxes(FALSE);
475 }
476
477 inst = rte_keymode_get_instance(key + 1, mode);
478
479 rfx = weed_to_rfx(inst, FALSE); // rfx will inherit the refcount
480 rfx->min_frames = -1;
481
482 // here we just check if we have any params to display
483 if (!make_param_box(NULL, rfx)) {
484 rfx_free(rfx);
485 lives_free(rfx);
486 return;
487 }
488
489 vbox = lives_vbox_new(FALSE, 0);
490
491 pscrolls[key] = lives_standard_scrolled_window_new(-1, -1, vbox);
492 lives_scrolled_window_set_policy(LIVES_SCROLLED_WINDOW(pscrolls[key]), LIVES_POLICY_NEVER, LIVES_POLICY_AUTOMATIC);
493 lives_widget_set_hexpand(pscrolls[key], FALSE);
494
495 lives_box_pack_start(LIVES_BOX(param_hbox), pscrolls[key], TRUE, TRUE, 0);
496
497 fname = weed_instance_get_filter_name(inst, TRUE);
498 label = lives_standard_label_new(fname);
499 lives_free(fname);
500
501 hbox = lives_hbox_new(FALSE, 0);
502 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
503
504 add_fill_to_box(LIVES_BOX(hbox));
505 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, widget_opts.packing_height);
506 add_fill_to_box(LIVES_BOX(hbox));
507
508 /* TRANSLATORS - "pin" as in "pinned to window" */
509 pin_check = lives_standard_check_button_new((tmp = (_("_Pin"))), FALSE, LIVES_BOX(hbox),
510 (tmp2 = (_("Pin the parameter box to the window"))));
511
512 lives_free(tmp); lives_free(tmp2);
513
514 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(pin_check), LIVES_WIDGET_TOGGLED_SIGNAL,
515 LIVES_GUI_CALLBACK(pin_toggled), LIVES_INT_TO_POINTER(key));
516
517 on_fx_pre_activate(rfx, TRUE, vbox);
518
519 // record the key so we know whose parameters to record later
520 weed_set_int_value((weed_plant_t *)rfx->source, WEED_LEAF_HOST_KEY, key);
521
522 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pscrolls[key]), "pinned", LIVES_INT_TO_POINTER(FALSE));
523 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pscrolls[key]), "update", LIVES_INT_TO_POINTER(FALSE));
524 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pscrolls[key]), RFX_KEY, rfx);
525 lives_widget_show_all(param_hbox);
526 }
527
528
ce_thumbs_remove_param_box(int key)529 static void ce_thumbs_remove_param_box(int key) {
530 // remove a single param box from the param_hbox
531 lives_rfx_t *rfx;
532 if (key >= rte_keys_virtual) return;
533 if (!pscrolls[key]) return;
534 rfx = (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[key]), RFX_KEY);
535 on_paramwindow_button_clicked(NULL, rfx); // free rfx and unref the inst (must be done before destroying the pscrolls[key]
536 lives_widget_destroy(pscrolls[key]);
537 pscrolls[key] = NULL;
538 lives_widget_queue_draw(param_hbox);
539 }
540
541
ce_thumbs_remove_param_boxes(boolean remove_pinned)542 static void ce_thumbs_remove_param_boxes(boolean remove_pinned) {
543 // remove all param boxes, (except any which are "pinned")
544 for (int i = 0; i < rte_keys_virtual; i++) {
545 if (pscrolls[i]) {
546 if (remove_pinned || !LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[i]), "pinned")))
547 ce_thumbs_remove_param_box(i);
548 }
549 }
550 }
551
552
ce_thumbs_register_rfx_change(int key,int mode)553 void ce_thumbs_register_rfx_change(int key, int mode) {
554 // register a param box to be updated visually, from an asynchronous source - either from a A->V data connection or from osc
555 if (key >= rte_keys_virtual || !pscrolls[key]) return;
556 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pscrolls[key]), "update", LIVES_INT_TO_POINTER(TRUE));
557 }
558
559
ce_thumbs_apply_rfx_changes(void)560 void ce_thumbs_apply_rfx_changes(void) {
561 // apply asynch updates
562 lives_rfx_t *rfx;
563
564 for (int i = 0; i < rte_keys_virtual; i++) {
565 if (pscrolls[i]) {
566 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[i]), "update"))) {
567 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pscrolls[i]), "update", LIVES_INT_TO_POINTER(FALSE));
568 rfx = (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[i]), RFX_KEY);
569 update_visual_params(rfx, FALSE);
570 // *INDENT-OFF*
571 }}}
572 // *INDENT-ON*
573 }
574
575
ce_thumbs_update_params(int key,int i,LiVESList * list)576 void ce_thumbs_update_params(int key, int i, LiVESList * list) {
577 // called only from weed_set_blend_factor() and from setting param in rte_window
578 lives_rfx_t *rfx;
579 if (key >= rte_keys_virtual) return;
580
581 if (pscrolls[key]) {
582 rfx = (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[key]), RFX_KEY);
583 mainw->block_param_updates = TRUE;
584 set_param_from_list(list, &rfx->params[key], 0, TRUE, TRUE);
585 mainw->block_param_updates = FALSE;
586 }
587 }
588
589
ce_thumbs_update_visual_params(int key)590 void ce_thumbs_update_visual_params(int key) {
591 // param change in rte_window - set params box here
592 lives_rfx_t *rfx;
593 if (key >= rte_keys_virtual) return;
594
595 if (pscrolls[key]) {
596 rfx = (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[key]), RFX_KEY);
597 update_visual_params(rfx, FALSE);
598 }
599 }
600
601
ce_thumbs_check_for_rte(lives_rfx_t * rfx,lives_rfx_t * rte_rfx,int key)602 void ce_thumbs_check_for_rte(lives_rfx_t *rfx, lives_rfx_t *rte_rfx, int key) {
603 // param change in ce_thumbs, update rte_window
604 for (int i = 0; i < rte_keys_virtual; i++) {
605 if (pscrolls[i] && i == key &&
606 rfx == (lives_rfx_t *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(pscrolls[key]), RFX_KEY)) {
607 update_visual_params(rte_rfx, FALSE);
608 break;
609 }
610 }
611 }
612
613
ce_thumbs_reset_combo(int key)614 void ce_thumbs_reset_combo(int key) {
615 // called from rte_window when the mapping is changed
616
617 LiVESList *fxlist = NULL;
618 int mode;
619
620 if (key >= rte_keys_virtual) return;
621 for (int j = 0; j <= rte_key_getmaxmode(key + 1); j++) {
622 fxlist = lives_list_append(fxlist, rte_keymode_get_filter_name(key + 1, j, FALSE));
623 }
624 lives_combo_populate(LIVES_COMBO(fxcombos[key]), fxlist);
625 if (fxlist) {
626 weed_plant_t *inst;
627 lives_widget_set_sensitive(key_checks[key], TRUE);
628 lives_list_free_all(&fxlist);
629 mode = rte_key_getmode(key + 1);
630 ce_thumbs_set_mode_combo(key, mode);
631 if ((inst = rte_keymode_get_instance(key + 1, mode)) != NULL) {
632 ce_thumbs_add_param_box(key, TRUE);
633 weed_instance_unref(inst);
634 }
635 } else {
636 lives_widget_set_sensitive(key_checks[key], FALSE);
637 lives_combo_set_active_string(LIVES_COMBO(fxcombos[key]), "");
638 }
639 }
640
641
ce_thumbs_reset_combos(void)642 void ce_thumbs_reset_combos(void) {
643 // called from rte_window when the mapping is cleared
644 for (int i = 0; i < rte_keys_virtual; i++) {
645 ce_thumbs_reset_combo(i);
646 }
647 }
648
649
ce_thumbs_set_clip_area(void)650 void ce_thumbs_set_clip_area(void) {
651 int i;
652 for (i = 0; i < n_screen_areas; i++) lives_signal_handler_block(rb_clip_areas[i], rb_clip_fns[i]);
653 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rb_clip_areas[mainw->active_sa_clips]), TRUE);
654 for (i = 0; i < n_screen_areas; i++) lives_signal_handler_unblock(rb_clip_areas[i], rb_clip_fns[i]);
655 ce_thumbs_highlight_current_clip();
656 }
657
658
ce_thumbs_set_fx_area(int area)659 void ce_thumbs_set_fx_area(int area) {
660 //register int i;
661 //for (i=0;i<n_screen_areas;i++) lives_signal_handler_block(rb_fx_areas[i],rb_fx_fns[i]);
662 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(rb_fx_areas[area]), TRUE);
663 //for (i=0;i<n_screen_areas;i++) lives_signal_handler_unblock(rb_fx_areas[i],rb_fx_fns[i]);
664 mainw->active_sa_fx = area;
665 }
666
667
ce_thumbs_update_current_clip(void)668 void ce_thumbs_update_current_clip(void) {
669 mainw->ce_upd_clip = TRUE;
670 }
671
672
ce_thumbs_highlight_current_clip(void)673 void ce_thumbs_highlight_current_clip(void) {
674 // unprelight all clip boxes, prelight current clip (fg or bg)
675 boolean match = FALSE;
676 int clipno;
677
678 for (int i = 0; i < n_clip_boxes; i++) {
679 if (!clip_boxes[i]) break;
680 if (!match) {
681 clipno = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(clip_boxes[i]), "clipno"));
682 switch (mainw->active_sa_clips) {
683 case SCREEN_AREA_FOREGROUND:
684 if (clipno == mainw->current_file) match = TRUE;
685 break;
686 case SCREEN_AREA_BACKGROUND:
687 if (clipno == mainw->blend_file) match = TRUE;
688 if (mainw->blend_file == -1 && clipno == mainw->current_file) match = TRUE;
689 break;
690 default: break;
691 }
692 if (match) {
693 lives_widget_set_state(clip_boxes[i], LIVES_WIDGET_STATE_PRELIGHT);
694 continue;
695 }
696 }
697 lives_widget_set_state(clip_boxes[i], LIVES_WIDGET_STATE_NORMAL);
698 }
699 }
700
701
ce_thumbs_liberate_clip_area(int area)702 void ce_thumbs_liberate_clip_area(int area) {
703 lives_widget_set_sensitive(rb_clip_areas[area], TRUE);
704 ce_thumbs_set_clip_area();
705 }
706
707
ce_thumbs_liberate_clip_area_register(int area)708 void ce_thumbs_liberate_clip_area_register(int area) {
709 next_screen_area = area;
710 }
711
712
ce_thumbs_apply_liberation(void)713 void ce_thumbs_apply_liberation(void) {
714 if (next_screen_area != SCREEN_AREA_NONE)
715 ce_thumbs_liberate_clip_area(next_screen_area);
716 next_screen_area = SCREEN_AREA_NONE;
717 }
718
719