1 // rte_window.c
2 // LiVES (lives-exe)
3 // (c) G. Finch 2005 - 2018 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6 
7 #include "main.h"
8 #include "rte_window.h"
9 #include "effects.h"
10 #include "paramwindow.h"
11 #include "ce_thumbs.h"
12 
13 static int old_rte_keys_virtual = 0;
14 
15 static LiVESWidget **key_checks;
16 static LiVESWidget **key_grabs;
17 static LiVESWidget **mode_radios;
18 static LiVESWidget **combos;
19 static LiVESWidget **combo_entries;
20 static LiVESWidget *dummy_radio;
21 static LiVESWidget **nlabels;
22 static LiVESWidget **type_labels;
23 static LiVESWidget **param_buttons;
24 static LiVESWidget **conx_buttons;
25 static LiVESWidget **clear_buttons;
26 static LiVESWidget **info_buttons;
27 static LiVESWidget *clear_all_button;
28 static LiVESWidget *save_keymap_button;
29 static LiVESWidget *load_keymap_button;
30 
31 static LiVESWidget *datacon_dialog = NULL;
32 
33 static ulong *ch_fns;
34 static ulong *gr_fns;
35 static ulong *mode_ra_fns;
36 
37 static int keyw = -1, modew = -1;
38 
39 static LiVESList *hash_list = NULL;
40 static LiVESList *name_list = NULL;
41 static LiVESList *extended_name_list = NULL;
42 
43 static boolean ca_canc;
44 
45 static char *empty_string = "";
46 
47 //////////////////////////////////////////////////////////////////////////////
48 
49 static void set_param_and_con_buttons(int key, int mode);
50 static void check_clear_all_button(void);
51 
52 static boolean rte_window_is_hidden = TRUE;
53 
54 
rte_window_hidden(void)55 boolean rte_window_hidden(void) {
56   return rte_window_is_hidden;
57 }
58 
59 
rte_window_set_interactive(boolean interactive)60 void rte_window_set_interactive(boolean interactive) {
61   register int i, j;
62   int modes = rte_getmodespk();
63   int idx;
64 
65   if (!interactive) {
66     lives_widget_set_sensitive(clear_all_button, FALSE);
67     lives_widget_set_sensitive(save_keymap_button, FALSE);
68     lives_widget_set_sensitive(load_keymap_button, FALSE);
69     for (i = 0; i < prefs->rte_keys_virtual; i++) {
70       for (j = modes - 1; j >= 0; j--) {
71         idx = i * modes + j;
72         lives_widget_set_sensitive(conx_buttons[idx], FALSE);
73         lives_widget_set_sensitive(param_buttons[idx], FALSE);
74         lives_widget_set_sensitive(combos[idx], FALSE);
75         lives_widget_set_sensitive(clear_buttons[idx], FALSE);
76         lives_widget_set_sensitive(mode_radios[idx], FALSE);
77       }
78       lives_widget_set_sensitive(key_checks[i], FALSE);
79       lives_widget_set_sensitive(key_grabs[i], FALSE);
80     }
81   } else {
82     for (i = 0; i < prefs->rte_keys_virtual; i++) {
83       for (j = modes - 1; j >= 0; j--) {
84         idx = i * modes + j;
85         set_param_and_con_buttons(i, j);
86       }
87     }
88     check_clear_all_button();
89     lives_widget_set_sensitive(save_keymap_button, TRUE);
90     lives_widget_set_sensitive(load_keymap_button, TRUE);
91   }
92 }
93 
94 
rtew_set_key_check_state(void)95 void rtew_set_key_check_state(void) {
96   // set (delayed) keycheck state
97   register int i;
98   for (i = 0; i < prefs->rte_keys_virtual; i++) {
99     lives_signal_handler_block(key_checks[i], ch_fns[i]);
100     lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[i]),
101                                    LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(key_checks[i]),
102                                        "active")));
103     lives_signal_handler_unblock(key_checks[i], ch_fns[i]);
104   }
105 }
106 
107 
type_label_set_text(int key,int mode)108 void type_label_set_text(int key, int mode) {
109   int modes = rte_getmodespk();
110   int idx = key * modes + mode;
111   char *type = rte_keymode_get_type(key + 1, mode), *tmp;
112 
113   if (*type) {
114     lives_label_set_text(LIVES_LABEL(type_labels[idx]), (tmp = lives_strdup_printf(_("Type: %s"), type)));
115     lives_free(tmp);
116     lives_widget_set_sensitive(info_buttons[idx], TRUE);
117     lives_widget_set_sensitive(clear_buttons[idx], TRUE);
118     lives_widget_set_sensitive(mode_radios[idx], TRUE);
119     lives_widget_set_sensitive(nlabels[idx], TRUE);
120     lives_widget_set_sensitive(type_labels[idx], TRUE);
121   } else {
122     lives_label_set_text(LIVES_LABEL(type_labels[idx]), NULL);
123     lives_widget_set_sensitive(info_buttons[idx], FALSE);
124     lives_widget_set_sensitive(clear_buttons[idx], FALSE);
125     lives_widget_set_sensitive(mode_radios[idx], FALSE);
126     lives_widget_set_sensitive(nlabels[idx], FALSE);
127     lives_widget_set_sensitive(type_labels[idx], FALSE);
128   }
129   lives_free(type);
130 }
131 
132 
on_clear_all_clicked(LiVESButton * button,livespointer user_data)133 boolean on_clear_all_clicked(LiVESButton *button, livespointer user_data) {
134   int modes = rte_getmodespk();
135   register int i, j;
136 
137   ca_canc = FALSE;
138 
139   // prompt for "are you sure ?"
140   if (user_data) if (!do_warning_dialog(_("\n\nUnbind all effects from all keys/modes.\n\nAre you sure ?\n\n"))) {
141       ca_canc = TRUE;
142       return FALSE;
143     }
144 
145   pconx_delete_all();
146   cconx_delete_all();
147 
148   for (i = 0; i < prefs->rte_keys_virtual; i++) {
149     if (rte_window) {
150       lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[i]), FALSE);
151       lives_widget_object_set_data(LIVES_WIDGET_OBJECT(key_checks[i]), "active", LIVES_INT_TO_POINTER(FALSE));
152     }
153     for (j = modes - 1; j >= 0; j--) {
154       weed_delete_effectkey(i + 1, j);
155       if (rte_window) {
156         rtew_combo_set_text(i, j, "");
157       }
158     }
159     if (mainw->ce_thumbs) ce_thumbs_reset_combo(i);
160   }
161 
162   if (button) lives_widget_set_sensitive(LIVES_WIDGET(button), FALSE);
163 
164   return FALSE;
165 }
166 
167 
save_keymap2_file(char * kfname)168 static boolean save_keymap2_file(char *kfname) {
169   // save perkey defaults
170   int slen;
171   int version = 1;
172   int modes = rte_getmodespk();
173   int kfd;
174   int retval;
175   int i, j;
176 
177   char *hashname, *tmp;
178 
179   do {
180     retval = 0;
181     kfd = lives_create_buffered(kfname, DEF_FILE_PERMS);
182     if (kfd == -1) {
183       retval = do_write_failed_error_s_with_retry(kfname, lives_strerror(errno));
184     } else {
185       lives_write_le_buffered(kfd, &version, 4, TRUE);
186       for (i = 1; i <= prefs->rte_keys_virtual; i++) {
187         if (THREADVAR(write_failed) == kfd + 1) break;
188         for (j = 0; j < modes; j++) {
189           if (rte_keymode_valid(i, j, TRUE)) {
190             lives_write_le_buffered(kfd, &i, 4, TRUE);
191             if (THREADVAR(write_failed) == kfd + 1) break;
192             // TODO: use newer version with separator
193             hashname = lives_strdup_printf("Weed%s",
194                                            (tmp = make_weed_hashname(rte_keymode_get_filter_idx(i, j), TRUE, FALSE, 0, FALSE)));
195             lives_free(tmp);
196             slen = lives_strlen(hashname);
197             lives_write_le_buffered(kfd, &slen, 4, TRUE);
198             lives_write_buffered(kfd, hashname, slen, TRUE);
199             lives_free(hashname);
200             write_key_defaults(kfd, i - 1, j);
201           }
202         }
203       }
204 
205       lives_close_buffered(kfd);
206 
207       if (THREADVAR(write_failed) == kfd + 1) {
208         THREADVAR(write_failed) = 0;
209         retval = do_write_failed_error_s_with_retry(kfname, NULL);
210       }
211     }
212   } while (retval == LIVES_RESPONSE_RETRY);
213 
214   if (retval == LIVES_RESPONSE_CANCEL) return FALSE;
215   return TRUE;
216 }
217 
218 
save_keymap3_file(char * kfname)219 static boolean save_keymap3_file(char *kfname) {
220   // save data connections
221 
222   char *hashname;
223 
224   int version = 1;
225 
226   int slen;
227   int kfd;
228   int retval;
229   int count = 0, totcons, nconns;
230 
231   register int i, j;
232 
233   do {
234     retval = 0;
235     kfd = lives_create_buffered(kfname, DEF_FILE_PERMS);
236     if (kfd == -1) {
237       retval = do_write_failed_error_s_with_retry(kfname, lives_strerror(errno));
238     } else {
239       THREADVAR(write_failed) = FALSE;
240 
241       lives_write_le_buffered(kfd, &version, 4, TRUE);
242 
243       if (mainw->cconx) {
244         lives_cconnect_t *cconx = mainw->cconx;
245         int nchans;
246 
247         while (cconx) {
248           count++;
249           cconx = cconx->next;
250         }
251 
252         lives_write_le_buffered(kfd, &count, 4, TRUE);
253         if (THREADVAR(write_failed)) goto write_failed1;
254 
255         cconx = mainw->cconx;
256         while (cconx) {
257           totcons = 0;
258           j = 0;
259 
260           lives_write_le_buffered(kfd, &cconx->okey, 4, TRUE);
261           if (THREADVAR(write_failed)) goto write_failed1;
262 
263           lives_write_le_buffered(kfd, &cconx->omode, 4, TRUE);
264           if (THREADVAR(write_failed)) goto write_failed1;
265 
266           // TODO: use newer version with separator
267           hashname = make_weed_hashname(rte_keymode_get_filter_idx(cconx->okey + 1, cconx->omode), TRUE, FALSE, 0, FALSE);
268           slen = lives_strlen(hashname);
269           lives_write_le_buffered(kfd, &slen, 4, TRUE);
270           lives_write_buffered(kfd, hashname, slen, TRUE);
271           lives_free(hashname);
272 
273           nchans = cconx->nchans;
274           lives_write_le_buffered(kfd, &nchans, 4, TRUE);
275           if (THREADVAR(write_failed)) goto write_failed1;
276 
277           for (i = 0; i < nchans; i++) {
278             lives_write_le_buffered(kfd, &cconx->chans[i], 4, TRUE);
279             if (THREADVAR(write_failed)) goto write_failed1;
280 
281             nconns = cconx->nconns[i];
282             lives_write_le_buffered(kfd, &nconns, 4, TRUE);
283             if (THREADVAR(write_failed)) goto write_failed1;
284 
285             totcons += nconns;
286 
287             while (j < totcons) {
288               lives_write_le_buffered(kfd, &cconx->ikey[j], 4, TRUE);
289               if (THREADVAR(write_failed)) goto write_failed1;
290 
291               lives_write_le_buffered(kfd, &cconx->imode[j], 4, TRUE);
292               if (THREADVAR(write_failed)) goto write_failed1;
293 
294               // TODO: use newer version with separator
295               hashname =
296                 make_weed_hashname(rte_keymode_get_filter_idx(cconx->ikey[j] + 1, cconx->imode[j]), TRUE, FALSE, 0, FALSE);
297               slen = lives_strlen(hashname);
298               lives_write_le_buffered(kfd, &slen, 4, TRUE);
299               lives_write_buffered(kfd, hashname, slen, TRUE);
300               lives_free(hashname);
301 
302               lives_write_le_buffered(kfd, &cconx->icnum[j], 4, TRUE);
303               if (THREADVAR(write_failed)) goto write_failed1;
304 
305               j++;
306             }
307           }
308 
309           cconx = cconx->next;
310         }
311       } else {
312         lives_write_le_buffered(kfd, &count, 4, TRUE);
313         if (THREADVAR(write_failed)) goto write_failed1;
314       }
315 
316       if (mainw->pconx) {
317         lives_pconnect_t *pconx = mainw->pconx;
318 
319         int nparams;
320 
321         count = 0;
322 
323         while (pconx) {
324           count++;
325           pconx = pconx->next;
326         }
327 
328         lives_write_le_buffered(kfd, &count, 4, TRUE);
329         if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
330 
331         pconx = mainw->pconx;
332         while (pconx) {
333           totcons = 0;
334           j = 0;
335 
336           lives_write_le_buffered(kfd, &pconx->okey, 4, TRUE);
337           if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
338 
339           lives_write_le_buffered(kfd, &pconx->omode, 4, TRUE);
340           if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
341 
342           // TODO: use newer version with separator
343           hashname =
344             make_weed_hashname(rte_keymode_get_filter_idx(pconx->okey + 1, pconx->omode), TRUE, FALSE, 0, FALSE);
345           slen = lives_strlen(hashname);
346           lives_write_le_buffered(kfd, &slen, 4, TRUE);
347           lives_write_buffered(kfd, hashname, slen, TRUE);
348           lives_free(hashname);
349 
350           nparams = pconx->nparams;
351           lives_write_le_buffered(kfd, &nparams, 4, TRUE);
352           if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
353 
354           for (i = 0; i < nparams; i++) {
355             lives_write_le_buffered(kfd, &pconx->params[i], 4, TRUE);
356             if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
357 
358             nconns = pconx->nconns[i];
359             lives_write_le_buffered(kfd, &nconns, 4, TRUE);
360             if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
361 
362             totcons += nconns;
363 
364             while (j < totcons) {
365               lives_write_le_buffered(kfd, &pconx->ikey[j], 4, TRUE);
366               if (THREADVAR(write_failed)) goto write_failed1;
367 
368               lives_write_le_buffered(kfd, &pconx->imode[j], 4, TRUE);
369               if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
370 
371               // TODO: use newer version with separator
372               hashname =
373                 make_weed_hashname(rte_keymode_get_filter_idx(pconx->ikey[j] + 1, pconx->imode[j]), TRUE, FALSE, 0, FALSE);
374               slen = lives_strlen(hashname);
375               lives_write_le_buffered(kfd, &slen, 4, TRUE);
376               lives_write_buffered(kfd, hashname, slen, TRUE);
377               lives_free(hashname);
378 
379               lives_write_le_buffered(kfd, &pconx->ipnum[j], 4, TRUE);
380               if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
381 
382               lives_write_le_buffered(kfd, &pconx->autoscale[j], 4, TRUE);
383               if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
384 
385               j++;
386             }
387           }
388 
389           pconx = pconx->next;
390         }
391       } else {
392         lives_write_le_buffered(kfd, &count, 4, TRUE);
393         if (THREADVAR(write_failed) == kfd + 1) goto write_failed1;
394       }
395 
396 write_failed1:
397       lives_close_buffered(kfd);
398 
399       if (THREADVAR(write_failed) == kfd + 1) {
400         THREADVAR(write_failed) = 0;
401         retval = do_write_failed_error_s_with_retry(kfname, NULL);
402       }
403     }
404   } while (retval == LIVES_RESPONSE_RETRY);
405 
406   if (retval == LIVES_RESPONSE_CANCEL) return FALSE;
407   return TRUE;
408 }
409 
410 
on_save_keymap_clicked(LiVESButton * button,livespointer user_data)411 static boolean on_save_keymap_clicked(LiVESButton *button, livespointer user_data) {
412   // format is binary
413   // (4 bytes key) (4 bytes hlen) (hlen bytes hashname) then a dump of the weed plant default values
414 
415   // if we have data connections, we will save a second file
416 
417   char *keymap_file2 = lives_build_filename(prefs->config_datadir, DEF_KEYMAP_FILE2, NULL); // perkey defs
418   char *keymap_file3 = lives_build_filename(prefs->config_datadir, DEF_KEYMAP_FILE3, NULL); // data connections
419 
420   LiVESResponseType retval = LIVES_RESPONSE_NONE;
421 
422   if (button) {
423     if (!do_warning_dialog(_("\n\nClick 'OK' to save this keymap as your default\n\n"))) {
424       lives_free(keymap_file3);
425       lives_free(keymap_file2);
426       return FALSE;
427     }
428     d_print(_("Saving keymap to %s\n"), keymap_file2);
429   } else {
430     d_print(_("\nUpdating keymap file %s..."), keymap_file2);
431   }
432 
433   // if we have default values, save them
434   if (!save_keymap2_file(keymap_file2)) {
435     lives_rm(keymap_file2);
436     retval = LIVES_RESPONSE_CANCEL;
437   }
438 
439   // if we have data connections, save them
440   if (mainw->pconx || mainw->cconx) {
441     if (!save_keymap3_file(keymap_file3)) {
442       lives_rm(keymap_file3);
443       retval = LIVES_RESPONSE_CANCEL;
444     }
445   } else lives_rm(keymap_file3);
446 
447   lives_free(keymap_file3);
448   lives_free(keymap_file2);
449 
450   if (retval == LIVES_RESPONSE_CANCEL) d_print_file_error_failed();
451   else d_print_done();
452 
453   return FALSE;
454 }
455 
456 
on_save_rte_defs_activate(LiVESMenuItem * menuitem,livespointer user_data)457 void on_save_rte_defs_activate(LiVESMenuItem *menuitem, livespointer user_data) {
458   char *msg;
459 
460   int fd;
461   int retval;
462   int numfx;
463 
464   register int i;
465 
466   if (!prefs->fxdefsfile) {
467     prefs->fxdefsfile = lives_build_filename(prefs->config_datadir, FX_DEFS_FILENAME, NULL);
468   }
469 
470   if (!prefs->fxsizesfile) {
471     prefs->fxsizesfile = lives_build_filename(prefs->config_datadir, FX_SIZES_FILENAME, NULL);
472   }
473 
474   d_print(_("Saving real time effect defaults to %s..."), prefs->fxdefsfile);
475 
476   numfx = rte_get_numfilters();
477 
478   do {
479     do_threaded_dialog(_("Saving real time effect defaults..."), FALSE);
480     retval = LIVES_RESPONSE_NONE;
481     if ((fd = lives_create_buffered(prefs->fxdefsfile, DEF_FILE_PERMS)) == -1) {
482       end_threaded_dialog();
483       msg = lives_strdup_printf(_("\n\nUnable to write defaults file\n%s\nError code %d\n"), prefs->fxdefsfile, errno);
484       retval = do_abort_cancel_retry_dialog(msg);
485       lives_free(msg);
486     } else {
487       msg = lives_strdup_printf("%s\n", FX_DEFS_VERSIONSTRING_1_1);
488       lives_write_buffered(fd, msg, lives_strlen(msg), TRUE);
489       lives_free(msg);
490 
491       if (THREADVAR(write_failed) == fd + 1) {
492         THREADVAR(write_failed) = 0;
493         end_threaded_dialog();
494         retval = do_write_failed_error_s_with_retry(prefs->fxdefsfile, NULL);
495       } else {
496         // break on file write error
497         for (i = 0; i < numfx; i++) {
498           if (!write_filter_defaults(fd, i)) {
499             end_threaded_dialog();
500             retval = do_write_failed_error_s_with_retry(prefs->fxdefsfile, NULL);
501             break;
502           }
503         }
504       }
505       lives_close_buffered(fd);
506     }
507   } while (retval == LIVES_RESPONSE_RETRY);
508 
509   if (retval == LIVES_RESPONSE_CANCEL) {
510     d_print_file_error_failed();
511     return;
512   }
513 
514   threaded_dialog_spin(0.);
515 
516   do {
517     retval = LIVES_RESPONSE_NONE;
518     if ((fd = lives_create_buffered(prefs->fxsizesfile, DEF_FILE_PERMS)) == -1) {
519       end_threaded_dialog();
520       retval = do_write_failed_error_s_with_retry(prefs->fxsizesfile, lives_strerror(errno));
521       lives_free(msg);
522     } else {
523       msg = lives_strdup_printf("%s\n", FX_SIZES_VERSIONSTRING_2);
524       lives_write_buffered(fd, msg, lives_strlen(msg), TRUE);
525       lives_free(msg);
526       if (THREADVAR(write_failed) == fd + 1) {
527         THREADVAR(write_failed) = 0;
528         end_threaded_dialog();
529         retval = do_write_failed_error_s_with_retry(prefs->fxsizesfile, NULL);
530       } else {
531         for (i = 0; i < numfx; i++) {
532           if (!write_generator_sizes(fd, i)) {
533             end_threaded_dialog();
534             retval = do_write_failed_error_s_with_retry(prefs->fxsizesfile, NULL);
535             break;
536           }
537         }
538       }
539       lives_close_buffered(fd);
540     }
541     if (retval == LIVES_RESPONSE_RETRY) do_threaded_dialog(_("Saving real time effect defaults..."), FALSE);
542   } while (retval == LIVES_RESPONSE_RETRY);
543 
544   if (retval == LIVES_RESPONSE_CANCEL) {
545     d_print_file_error_failed();
546     return;
547   }
548 
549   d_print_done();
550   end_threaded_dialog();
551 
552   return;
553 }
554 
555 
load_rte_defs(void)556 void load_rte_defs(void) {
557   ssize_t bytes;
558   char *buf, *msg;
559   size_t msglen;
560   int fd;
561   int retval;
562 
563   if (!prefs->fxdefsfile) {
564     prefs->fxdefsfile = lives_build_filename(prefs->config_datadir, FX_DEFS_FILENAME, NULL);
565   }
566 
567   if (lives_file_test(prefs->fxdefsfile, LIVES_FILE_TEST_EXISTS)) {
568     do {
569       retval = 0;
570       if ((fd = lives_open_buffered_rdonly(prefs->fxdefsfile)) == -1) {
571         retval = do_read_failed_error_s_with_retry(prefs->fxdefsfile, lives_strerror(errno));
572       } else {
573         THREADVAR(read_failed) = FALSE;
574         d_print(_("Loading real time effect defaults from %s..."), prefs->fxdefsfile);
575 
576         msg = lives_strdup_printf("%s\n", FX_DEFS_VERSIONSTRING_1_1);
577         msglen = lives_strlen(msg);
578         buf = lives_malloc(msglen + 1);
579         bytes = lives_read_buffered(fd, buf, msglen, TRUE);
580         if (bytes == (ssize_t)msglen && !lives_strncmp((char *)buf, msg, msglen)) {
581           if (read_filter_defaults(fd)) {
582             d_print_done();
583           } else {
584             d_print_file_error_failed();
585             retval = do_read_failed_error_s_with_retry(prefs->fxdefsfile, NULL);
586           }
587         } else {
588           d_print_file_error_failed();
589           if (bytes < (ssize_t)msglen) {
590             retval = do_read_failed_error_s_with_retry(prefs->fxdefsfile, NULL);
591           }
592         }
593 
594         lives_close_buffered(fd);
595 
596         lives_free(buf);
597         lives_free(msg);
598       }
599     } while (retval == LIVES_RESPONSE_RETRY);
600   }
601 
602   if (!prefs->fxsizesfile) {
603     prefs->fxsizesfile = lives_build_filename(prefs->config_datadir, FX_SIZES_FILENAME, NULL);
604   }
605 
606   if (lives_file_test(prefs->fxsizesfile, LIVES_FILE_TEST_EXISTS)) {
607     do {
608       retval = 0;
609       if ((fd = lives_open_buffered_rdonly(prefs->fxsizesfile)) == -1) {
610         retval = do_read_failed_error_s_with_retry(prefs->fxsizesfile, lives_strerror(errno));
611         if (retval == LIVES_RESPONSE_CANCEL) return;
612       } else {
613         d_print(_("Loading generator default sizes from %s..."), prefs->fxsizesfile);
614 
615         msg = lives_strdup_printf("%s\n", FX_SIZES_VERSIONSTRING_2);
616         msglen = lives_strlen(msg);
617         buf = lives_malloc(msglen + 1);
618         bytes = lives_read_buffered(fd, buf, msglen, TRUE);
619         if (bytes == (ssize_t)msglen && !strncmp((char *)buf, msg, msglen)) {
620           if (read_generator_sizes(fd)) {
621             d_print_done();
622           } else {
623             d_print_file_error_failed();
624             retval = do_read_failed_error_s_with_retry(prefs->fxsizesfile, NULL);
625           }
626         } else {
627           d_print_file_error_failed();
628           if (bytes < (ssize_t)msglen) {
629             retval = do_read_failed_error_s_with_retry(prefs->fxsizesfile, NULL);
630           }
631         }
632         lives_close_buffered(fd);
633 
634         lives_free(buf);
635         lives_free(msg);
636       }
637     } while (retval == LIVES_RESPONSE_RETRY);
638   }
639 
640   return;
641 }
642 
643 
check_clear_all_button(void)644 static void check_clear_all_button(void) {
645   int modes = rte_getmodespk();
646   int i, j;
647   boolean hasone = FALSE;
648 
649   for (i = 0; i < prefs->rte_keys_virtual; i++) {
650     for (j = modes - 1; j >= 0; j--) {
651       if (rte_keymode_valid(i + 1, j, TRUE)) hasone = TRUE;
652     }
653   }
654 
655   lives_widget_set_sensitive(LIVES_WIDGET(clear_all_button), hasone);
656 }
657 
658 
read_perkey_defaults(int kfd,int key,int mode,int version)659 static boolean read_perkey_defaults(int kfd, int key, int mode, int version) {
660   boolean ret = TRUE;
661   int nparams;
662   ssize_t bytes = lives_read_le_buffered(kfd, &nparams, 4, TRUE);
663 
664   if (nparams > 65536) {
665     lives_printerr("Too many params, file is probably broken.\n");
666     return FALSE;
667   }
668 
669   if (bytes < sizint) {
670     return FALSE;
671   }
672 
673   if (nparams > 0) {
674     ret = read_key_defaults(kfd, nparams, key, mode, version);
675   }
676   return ret;
677 }
678 
679 
load_datacons(const char * fname,uint8_t ** badkeymap)680 static boolean load_datacons(const char *fname, uint8_t **badkeymap) {
681   weed_plant_t **ochans, **ichans, **iparams;
682 
683   weed_plant_t *filter;
684 
685   ssize_t bytes;
686 
687   char *hashname;
688 
689   boolean ret = TRUE;
690   boolean is_valid, is_valid2;
691   boolean eof = FALSE;
692 
693   int kfd;
694 
695   int retval;
696 
697   int hlen;
698 
699   int version, nchans, nparams, nconns, ncconx, npconx;
700 
701   int nichans, nochans, niparams, noparams, error;
702 
703   int okey, omode, ocnum, opnum, ikey, imode, icnum, ipnum, autoscale;
704 
705   int maxmodes = rte_getmodespk();
706 
707   register int i, j, k, count;
708 
709   do {
710     retval = 0;
711     if ((kfd = lives_open_buffered_rdonly(fname)) == -1) {
712       retval = do_read_failed_error_s_with_retry(fname, lives_strerror(errno));
713     } else {
714       THREADVAR(read_failed) = FALSE;
715 
716       bytes = lives_read_le_buffered(kfd, &version, 4, TRUE);
717       if (bytes < 4) {
718         eof = TRUE;
719         break;
720       }
721 
722       bytes = lives_read_le_buffered(kfd, &ncconx, 4, TRUE);
723       if (bytes < 4) {
724         eof = TRUE;
725         break;
726       }
727 
728       for (count = 0; count < ncconx; count++) {
729         is_valid = TRUE;
730 
731         bytes = lives_read_le_buffered(kfd, &okey, 4, TRUE);
732         if (bytes < 4) {
733           eof = TRUE;
734           break;
735         }
736 
737         if (okey < 0 || okey >= prefs->rte_keys_virtual) is_valid = FALSE;
738 
739         bytes = lives_read_le_buffered(kfd, &omode, 4, TRUE);
740         if (bytes < 4) {
741           eof = TRUE;
742           break;
743         }
744 
745         bytes = lives_read_le_buffered(kfd, &hlen, 4, TRUE);
746         if (bytes < 4) {
747           eof = TRUE;
748           break;
749         }
750 
751         hashname = (char *)lives_malloc(hlen + 1);
752 
753         if (!hashname) {
754           eof = TRUE;
755           break;
756         }
757 
758         bytes = lives_read_buffered(kfd, hashname, hlen, TRUE);
759         if (bytes < hlen) {
760           eof = TRUE;
761           lives_free(hashname);
762           break;
763         }
764 
765         lives_memset(hashname + hlen, 0, 1);
766 
767         if (omode < 0 || omode >= maxmodes) is_valid = FALSE;
768 
769         if (is_valid) {
770           // if we had bad/missing fx, adjust the omode value
771           for (i = 0; i < omode; i++) omode -= badkeymap[okey][omode];
772         }
773 
774         if (omode < 0 || omode >= maxmodes) is_valid = FALSE;
775 
776         if (is_valid) {
777           int fidx = rte_keymode_get_filter_idx(okey + 1, omode);
778           if (fidx == -1) is_valid = FALSE;
779           else {
780             // TODO: use newer version with separator
781             char *hashname2 = make_weed_hashname(fidx, TRUE, FALSE, 0, FALSE);
782             if (strcmp(hashname, hashname2)) is_valid = FALSE;
783             lives_free(hashname2);
784             if (!is_valid) {
785               hashname2 = make_weed_hashname(fidx, TRUE, TRUE, 0, FALSE);
786               if (!strcmp(hashname, hashname2)) is_valid = TRUE;
787               lives_free(hashname2);
788             }
789           }
790         }
791 
792         lives_free(hashname);
793 
794         bytes = lives_read_le_buffered(kfd, &nchans, 4, TRUE);
795         if (bytes < 4) {
796           eof = TRUE;
797           break;
798         }
799 
800         for (i = 0; i < nchans; i++) {
801           is_valid2 = is_valid;
802 
803           bytes = lives_read_le_buffered(kfd, &ocnum, 4, TRUE);
804           if (bytes < 4) {
805             eof = TRUE;
806             break;
807           }
808 
809           // check ocnum
810           filter = rte_keymode_get_filter(okey + 1, omode);
811           nochans = weed_leaf_num_elements(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES);
812           if (ocnum >= nochans) is_valid2 = FALSE;
813           else {
814             ochans = weed_get_plantptr_array(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, &error);
815             if (!has_alpha_palette(ochans[ocnum], filter)) is_valid2 = FALSE;
816             lives_free(ochans);
817           }
818 
819           bytes = lives_read_le_buffered(kfd, &nconns, 4, TRUE);
820           if (bytes < 4) {
821             eof = TRUE;
822             break;
823           }
824 
825           for (j = 0; j < nconns; j++) {
826             bytes = lives_read_le_buffered(kfd, &ikey, 4, TRUE);
827             if (bytes < 4) {
828               eof = TRUE;
829               break;
830             }
831 
832             bytes = lives_read_le_buffered(kfd, &imode, 4, TRUE);
833             if (bytes < 4) {
834               eof = TRUE;
835               break;
836             }
837 
838             bytes = lives_read_le_buffered(kfd, &hlen, 4, TRUE);
839             if (bytes < 4) {
840               eof = TRUE;
841               break;
842             }
843 
844             hashname = (char *)lives_malloc(hlen + 1);
845 
846             if (!hashname) {
847               eof = TRUE;
848               break;
849             }
850 
851             bytes = lives_read_buffered(kfd, hashname, hlen, TRUE);
852             if (bytes < hlen) {
853               eof = TRUE;
854               lives_free(hashname);
855               break;
856             }
857 
858             lives_memset(hashname + hlen, 0, 1);
859 
860             if (imode < 0 || (ikey >= 0 && imode >= maxmodes)) is_valid2 = FALSE;
861 
862             if (is_valid2) {
863               // if we had bad/missing fx, adjust the omode value
864               for (k = 0; k < imode; k++) imode -= badkeymap[ikey][imode];
865             }
866 
867             if (imode < 0 || (ikey >= 0 && imode >= maxmodes)) is_valid2 = FALSE;
868 
869             if (is_valid2) {
870               int fidx = rte_keymode_get_filter_idx(ikey + 1, imode);
871               if (fidx == -1) is_valid2 = FALSE;
872               else {
873                 // TODO: use newer version with separator
874                 char *hashname2 = make_weed_hashname(fidx, TRUE, FALSE, 0, FALSE);
875                 if (strcmp(hashname, hashname2)) is_valid2 = FALSE;
876                 lives_free(hashname2);
877                 if (!is_valid2) {
878                   hashname2 = make_weed_hashname(fidx, TRUE, TRUE, 0, FALSE);
879                   if (!strcmp(hashname, hashname2)) is_valid2 = TRUE;
880                   lives_free(hashname2);
881                 }
882               }
883             }
884 
885             lives_free(hashname);
886 
887             bytes = lives_read_le_buffered(kfd, &icnum, 4, TRUE);
888             if (bytes < 4) {
889               eof = TRUE;
890               break;
891             }
892 
893             // check icnum
894             filter = rte_keymode_get_filter(ikey + 1, imode);
895             nichans = weed_leaf_num_elements(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES);
896             if (icnum >= nichans) is_valid2 = FALSE;
897             else {
898               ichans = weed_get_plantptr_array(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, &error);
899               if (!has_alpha_palette(ichans[icnum], filter)) is_valid2 = FALSE;
900               lives_free(ichans);
901             }
902 
903             if (is_valid2) cconx_add_connection(okey, omode, ocnum, ikey, imode, icnum);
904           }
905 
906           if (eof) break;
907         }
908 
909         if (eof) break;
910       }
911 
912       if (eof) break;
913 
914       // params
915 
916       bytes = lives_read_le_buffered(kfd, &npconx, 4, TRUE);
917       if (bytes < 4) {
918         eof = TRUE;
919         break;
920       }
921 
922       for (count = 0; count < npconx; count++) {
923         is_valid = TRUE;
924 
925         bytes = lives_read_le_buffered(kfd, &okey, 4, TRUE);
926         if (bytes < 4) {
927           eof = TRUE;
928           break;
929         }
930 
931         if (okey < 0 || okey >= prefs->rte_keys_virtual) is_valid = FALSE;
932 
933         bytes = lives_read_le_buffered(kfd, &omode, 4, TRUE);
934         if (bytes < 4) {
935           eof = TRUE;
936           break;
937         }
938 
939         bytes = lives_read_le_buffered(kfd, &hlen, 4, TRUE);
940         if (bytes < 4) {
941           eof = TRUE;
942           break;
943         }
944 
945         hashname = (char *)lives_malloc(hlen + 1);
946 
947         if (!hashname) {
948           eof = TRUE;
949           break;
950         }
951 
952         bytes = lives_read_buffered(kfd, hashname, hlen, TRUE);
953         if (bytes < hlen) {
954           eof = TRUE;
955           lives_free(hashname);
956           break;
957         }
958 
959         lives_memset(hashname + hlen, 0, 1);
960 
961         if (omode < 0 || omode >= maxmodes) is_valid = FALSE;
962 
963         if (is_valid) {
964           // if we had bad/missing fx, adjust the omode value
965           for (i = 0; i < omode; i++) omode -= badkeymap[okey][omode];
966         }
967 
968         if (omode < 0 || omode >= maxmodes) is_valid = FALSE;
969 
970         if (is_valid) {
971           int fidx = rte_keymode_get_filter_idx(okey + 1, omode);
972           if (fidx == -1) is_valid = FALSE;
973           else {
974             // TODO: use newer version with separator
975             char *hashname2 = make_weed_hashname(fidx, TRUE, FALSE, 0, FALSE);
976             if (strcmp(hashname, hashname2)) is_valid = FALSE;
977             lives_free(hashname2);
978             if (!is_valid) {
979               hashname2 = make_weed_hashname(fidx, TRUE, TRUE, 0, FALSE);
980               if (!strcmp(hashname, hashname2)) is_valid = TRUE;
981               lives_free(hashname2);
982             }
983           }
984         }
985 
986         lives_free(hashname);
987 
988         bytes = lives_read_le_buffered(kfd, &nparams, 4, TRUE);
989         if (bytes < 4) {
990           eof = TRUE;
991           break;
992         }
993 
994         for (i = 0; i < nparams; i++) {
995           is_valid2 = is_valid;
996 
997           bytes = lives_read_le_buffered(kfd, &opnum, 4, TRUE);
998           if (bytes < 4) {
999             eof = TRUE;
1000             break;
1001           }
1002 
1003           // check opnum
1004           filter = rte_keymode_get_filter(okey + 1, omode);
1005           noparams = weed_leaf_num_elements(filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES);
1006           if (opnum >= noparams) is_valid2 = FALSE;
1007 
1008           bytes = lives_read_le_buffered(kfd, &nconns, 4, TRUE);
1009           if (bytes < 4) {
1010             eof = TRUE;
1011             break;
1012           }
1013 
1014           for (j = 0; j < nconns; j++) {
1015             bytes = lives_read_le_buffered(kfd, &ikey, 4, TRUE);
1016             if (bytes < 4) {
1017               eof = TRUE;
1018               break;
1019             }
1020 
1021             bytes = lives_read_le_buffered(kfd, &imode, 4, TRUE);
1022             if (bytes < 4) {
1023               eof = TRUE;
1024               break;
1025             }
1026 
1027             bytes = lives_read_le_buffered(kfd, &hlen, 4, TRUE);
1028             if (bytes < 4) {
1029               eof = TRUE;
1030               break;
1031             }
1032 
1033             hashname = (char *)lives_malloc(hlen + 1);
1034 
1035             if (!hashname) {
1036               eof = TRUE;
1037               break;
1038             }
1039 
1040             bytes = lives_read_buffered(kfd, hashname, hlen, TRUE);
1041             if (bytes < hlen) {
1042               eof = TRUE;
1043               lives_free(hashname);
1044               break;
1045             }
1046 
1047             lives_memset(hashname + hlen, 0, 1);
1048 
1049             if (imode < 0 || (ikey >= 0 && imode >= maxmodes)) is_valid2 = FALSE;
1050 
1051             if (is_valid2 && ikey >= 0) {
1052               // if we had bad/missing fx, adjust the omode value
1053               for (k = 0; k < imode; k++) imode -= badkeymap[ikey][imode];
1054             }
1055 
1056             if (imode < 0 || (ikey >= 0 && imode >= maxmodes)) is_valid2 = FALSE;
1057 
1058             if (is_valid2 && ikey >= 0) {
1059               int fidx = rte_keymode_get_filter_idx(ikey + 1, imode);
1060               if (fidx == -1) is_valid2 = FALSE;
1061               else {
1062                 // TODO: use newer version with separator
1063                 char *hashname2 = make_weed_hashname(fidx, TRUE, FALSE, 0, FALSE);
1064                 if (strcmp(hashname, hashname2)) is_valid2 = FALSE;
1065                 lives_free(hashname2);
1066                 if (!is_valid2) {
1067                   hashname2 = make_weed_hashname(fidx, TRUE, TRUE, 0, FALSE);
1068                   if (!strcmp(hashname, hashname2)) is_valid2 = TRUE;
1069                   lives_free(hashname2);
1070                 }
1071               }
1072             }
1073 
1074             lives_free(hashname);
1075 
1076             bytes = lives_read_le_buffered(kfd, &ipnum, 4, TRUE);
1077             if (bytes < 4) {
1078               eof = TRUE;
1079               break;
1080             }
1081 
1082             if (ikey >= 0) {
1083               // check ipnum
1084               filter = rte_keymode_get_filter(ikey + 1, imode);
1085               niparams = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
1086               if (ipnum >= niparams) is_valid2 = FALSE;
1087               else {
1088                 if (ipnum >= 0) {
1089                   iparams = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, &error);
1090                   if (weed_plant_has_leaf(iparams[ipnum], WEED_LEAF_HOST_INTERNAL_CONNECTION)) is_valid2 = FALSE;
1091                   lives_free(iparams);
1092                 }
1093               }
1094             }
1095 
1096             bytes = lives_read_le_buffered(kfd, &autoscale, 4, TRUE);
1097             if (bytes < 4) {
1098               eof = TRUE;
1099               break;
1100             }
1101 
1102             if (is_valid2) {
1103               pconx_add_connection(okey, omode, opnum, ikey, imode, ipnum, autoscale);
1104             }
1105           }
1106 
1107           if (eof) break;
1108         }
1109 
1110         if (eof) break;
1111       }
1112 
1113       lives_close_buffered(kfd);
1114     }
1115   } while (retval == LIVES_RESPONSE_RETRY);
1116 
1117   if (retval == LIVES_RESPONSE_CANCEL) {
1118     d_print_cancelled();
1119     return FALSE;
1120   }
1121 
1122   return ret;
1123 }
1124 
1125 
set_param_and_con_buttons(int key,int mode)1126 static void set_param_and_con_buttons(int key, int mode) {
1127   weed_plant_t *filter = rte_keymode_get_filter(key + 1, mode);
1128 
1129   int modes = rte_getmodespk();
1130   int idx = key * modes + mode;
1131 
1132   if (filter) {
1133     lives_widget_set_sensitive(conx_buttons[idx], TRUE);
1134     if (num_in_params(filter, TRUE, TRUE) > 0) lives_widget_set_sensitive(param_buttons[idx], TRUE);
1135     else lives_widget_set_sensitive(param_buttons[idx], FALSE);
1136     lives_widget_set_sensitive(combos[idx], TRUE);
1137     if (combos[idx + 1] && mode < modes - 1) lives_widget_set_sensitive(combos[idx + 1], TRUE);
1138   } else {
1139     lives_widget_set_sensitive(conx_buttons[idx], FALSE);
1140     lives_widget_set_sensitive(param_buttons[idx], FALSE);
1141     if (mode == 0 || rte_keymode_get_filter(key + 1, mode - 1))
1142       lives_widget_set_sensitive(combos[idx], TRUE);
1143     else
1144       lives_widget_set_sensitive(combos[idx], FALSE);
1145   }
1146 
1147   type_label_set_text(key, mode);
1148 }
1149 
1150 
on_load_keymap_clicked(LiVESButton * button,livespointer user_data)1151 boolean on_load_keymap_clicked(LiVESButton *button, livespointer user_data) {
1152   // show file errors at this level
1153   FILE *kfile = NULL;
1154 
1155   LiVESList *list = NULL, *new_list = NULL;
1156 
1157   size_t linelen;
1158   ssize_t bytes;
1159 
1160   char buff[65536];
1161   char *msg, *tmp;
1162   char *whole = lives_strdup(""), *whole2;
1163   char *hashname, *hashname_new = NULL;
1164 
1165   char *line = NULL;
1166   char *whashname;
1167 
1168   char *keymap_file = lives_build_filename(prefs->config_datadir, DEF_KEYMAP_FILE_OLD, NULL); // only for back. compat
1169   char *keymap_file2 = lives_build_filename(prefs->config_datadir, DEF_KEYMAP_FILE2, NULL); // perkey defs
1170   char *keymap_file3 = lives_build_filename(prefs->config_datadir, DEF_KEYMAP_FILE3, NULL); // data connections
1171 
1172   int *def_modes = NULL;
1173   uint8_t **badkeymap = NULL;
1174 
1175   boolean notfound = FALSE;
1176   boolean has_error = FALSE;
1177   boolean eof = FALSE;
1178 
1179   int modes = rte_getmodespk();
1180   int kfd = -1;
1181   int version;
1182   int hlen;
1183   int retval;
1184 
1185   int key, mode;
1186   int update = 0;
1187 
1188   int i;
1189 
1190   if (lives_file_test(keymap_file2, LIVES_FILE_TEST_EXISTS)) {
1191     // per key defaults / newer style keymap
1192     lives_free(keymap_file);
1193     keymap_file = keymap_file2;
1194   } else {
1195     lives_freep((void **)&keymap_file2);
1196   }
1197 
1198   d_print(_("Loading default keymap from %s..."), keymap_file);
1199 
1200   if (!lives_file_test(keymap_file, LIVES_FILE_TEST_EXISTS)) {
1201     d_print(_("file not found, skipping.\n"));
1202     lives_freep((void **)&keymap_file);
1203     lives_freep((void **)&keymap_file2);
1204     lives_freep((void **)&keymap_file3);
1205     return FALSE;
1206   } else {
1207     do {
1208       retval = 0;
1209 
1210       if (keymap_file2) {
1211         if ((kfd = lives_open_buffered_rdonly(keymap_file)) < 0) has_error = TRUE;
1212       } else {
1213         if (!(kfile = fopen(keymap_file, "r"))) {
1214           has_error = TRUE;
1215         }
1216       }
1217 
1218       if (has_error) {
1219         msg = lives_strdup_printf(_("\n\nUnable to read from keymap file\n%s\nError code %d\n"), keymap_file, errno);
1220         retval = do_abort_cancel_retry_dialog(msg);
1221         lives_free(msg);
1222 
1223         if (retval == LIVES_RESPONSE_CANCEL) {
1224           lives_free(keymap_file);
1225           d_print_file_error_failed();
1226           return FALSE;
1227         }
1228       }
1229     } while (retval == LIVES_RESPONSE_RETRY);
1230 
1231     on_clear_all_clicked(NULL, user_data);
1232 
1233     if (ca_canc) {
1234       // user cancelled
1235       mainw->error = FALSE;
1236       d_print_cancelled();
1237       return FALSE;
1238     }
1239   }
1240 
1241   def_modes = (int *)lives_malloc(prefs->rte_keys_virtual * sizint);
1242   for (i = 0; i < prefs->rte_keys_virtual; i++) def_modes[i] = -1;
1243 
1244   badkeymap = (uint8_t **)lives_malloc(prefs->rte_keys_virtual * sizeof(uint8_t *));
1245   for (i = 0; i < prefs->rte_keys_virtual; i++) {
1246     badkeymap[i] = (uint8_t *)lives_calloc(modes, 1);
1247   }
1248 
1249   if (!keymap_file2) {
1250     // version 1 file
1251     while (fgets(buff, 65536, kfile)) {
1252       if (*buff) {
1253         line = (lives_strstrip(buff));
1254         if ((linelen = lives_strlen(line))) {
1255           whole2 = lives_strconcat(whole, line, NULL);
1256           if (whole2 != whole) lives_free(whole);
1257           whole = whole2;
1258           if (linelen < (size_t)65535) {
1259             list = lives_list_append(list, lives_strdup(whole));
1260             lives_free(whole);
1261             whole = lives_strdup("");
1262 	    // *INDENT-OFF*
1263           }}}}
1264     // *INDENT-ON*
1265 
1266     fclose(kfile);
1267 
1268     if (!strcmp((char *)lives_list_nth_data(list, 0), "LiVES keymap file version 2") ||
1269         !strcmp((char *)lives_list_nth_data(list, 0), "LiVES keymap file version 1")) update = 1;
1270     else {
1271       if (!strcmp((char *)lives_list_nth_data(list, 0), "LiVES keymap file version 3")) update = 2;
1272       else {
1273         goto cleanup1;
1274       }
1275     }
1276   } else {
1277     // newer style
1278     // read version
1279     bytes = lives_read_le_buffered(kfd, &version, 4, TRUE);
1280     if (bytes < sizint) {
1281       eof = TRUE;
1282     }
1283   }
1284 
1285   lives_free(whole);
1286 
1287   for (i = 1; (!keymap_file2 && i < lives_list_length(list)) || (keymap_file2 && !eof); i++) {
1288     char **array;
1289 
1290     if (!keymap_file2) {
1291       // old style
1292 
1293       line = (char *)lives_list_nth_data(list, i);
1294 
1295       if (get_token_count(line, '|') < 2) {
1296         d_print(_("Invalid line %d in %s\n"), i, keymap_file2 ? keymap_file2 : keymap_file);
1297         continue;
1298       }
1299 
1300       array = lives_strsplit(line, "|", -1);
1301 
1302       if (!strcmp(array[0], "defaults")) {
1303         lives_strfreev(array);
1304         array = lives_strsplit(line, "|", 2);
1305         lives_freep((void **)&prefs->fxdefsfile);
1306         prefs->fxdefsfile = lives_strdup(array[1]);
1307         lives_strfreev(array);
1308         continue;
1309       }
1310 
1311       if (!strcmp(array[0], "sizes")) {
1312         lives_strfreev(array);
1313         array = lives_strsplit(line, "|", 2);
1314         lives_freep((void **)&prefs->fxsizesfile);
1315         prefs->fxsizesfile = lives_strdup(array[1]);
1316         lives_strfreev(array);
1317         continue;
1318       }
1319 
1320       key = atoi(array[0]);
1321 
1322       hashname = lives_strdup(array[1]);
1323       lives_strfreev(array);
1324 
1325       if (update > 0) {
1326         if (update == 1) hashname_new = lives_strdup_printf("%d|Weed%s1\n", key, hashname);
1327         if (update == 2) hashname_new = lives_strdup_printf("%d|Weed%s\n", key, hashname);
1328         new_list = lives_list_append(new_list, hashname_new);
1329         lives_free(hashname);
1330         continue;
1331       }
1332     } else {
1333       // newer style
1334       // file format is: (4 bytes int)key(4 bytes int)hlen(hlen bytes)hashname
1335 
1336       //read key and hashname
1337       bytes = lives_read_le_buffered(kfd, &key, 4, TRUE);
1338       if (bytes < 4) {
1339         eof = TRUE;
1340         break;
1341       }
1342 
1343       bytes = lives_read_le_buffered(kfd, &hlen, 4, TRUE);
1344       if (bytes < 4) {
1345         eof = TRUE;
1346         break;
1347       }
1348 
1349       hashname = (char *)lives_malloc(hlen + 1);
1350 
1351       if (!hashname) {
1352         eof = TRUE;
1353         break;
1354       }
1355 
1356       bytes = lives_read_buffered(kfd, hashname, hlen, TRUE);
1357       if (bytes < hlen) {
1358         g_print("keyl %d wanted %d got %ld\n", i, hlen, bytes);
1359         eof = TRUE;
1360         lives_free(hashname);
1361         break;
1362       }
1363 
1364       lives_memset(hashname + hlen, 0, 1);
1365 
1366       array = lives_strsplit(hashname, "|", -1);
1367       lives_free(hashname);
1368       hashname = lives_strdup(array[0]);
1369       lives_strfreev(array);
1370     }
1371 
1372     if (key < 1 || key > prefs->rte_keys_virtual) {
1373       d_print((tmp = lives_strdup_printf(_("Invalid key %d in %s\n"), key, keymap_file)));
1374       LIVES_ERROR(tmp);
1375       lives_free(tmp);
1376       notfound = TRUE;
1377       lives_free(hashname);
1378       if (keymap_file2) {
1379         // read param defaults
1380         if (!read_perkey_defaults(kfd, -1, -1, version)) break; // file read error
1381       }
1382       continue;
1383     }
1384 
1385     def_modes[key - 1]++;
1386 
1387     if (strncmp(hashname, "Weed", 4) || lives_strlen(hashname) < 5) {
1388       d_print((tmp = lives_strdup_printf(_("Invalid effect %s in %s\n"), hashname, keymap_file)));
1389       LIVES_ERROR(tmp);
1390       lives_free(tmp);
1391       notfound = TRUE;
1392       lives_free(hashname);
1393       badkeymap[key - 1][def_modes[key - 1]]++;
1394       if (keymap_file2) {
1395         // read param defaults
1396         if (!read_perkey_defaults(kfd, -1, -1, version)) break; // file read error
1397       }
1398       def_modes[key - 1]--;
1399       continue;
1400     }
1401 
1402     // ignore "Weed"
1403     whashname = hashname + 4;
1404 
1405     if ((mode = weed_add_effectkey(key, whashname, TRUE)) == -1) {
1406       // could not locate effect
1407       if (!prefs->startup_phase) {
1408         d_print((tmp = lives_strdup_printf(_("Unknown effect %s in\n%s\n"), whashname, keymap_file)));
1409         LIVES_WARN(tmp);
1410         lives_free(tmp);
1411       }
1412       notfound = TRUE;
1413       lives_free(hashname);
1414       badkeymap[key - 1][def_modes[key - 1]]++;
1415       if (keymap_file2) {
1416         // read param defaults
1417         if (!read_perkey_defaults(kfd, -1, -1, version)) break; // file read error
1418       }
1419       def_modes[key - 1]--;
1420       continue;
1421     }
1422 
1423     lives_free(hashname);
1424 
1425     if (mode == -2) {
1426       d_print((tmp = lives_strdup_printf
1427                      (_("This version of LiVES cannot mix generators/non-generators on the same key (%d) !\n"), key)));
1428       LIVES_ERROR(tmp);
1429       lives_free(tmp);
1430       badkeymap[key - 1][def_modes[key - 1]]++;
1431       if (keymap_file2) {
1432         // read param defaults
1433         if (!read_perkey_defaults(kfd, -1, -1, version)) break; // file read error
1434       }
1435       def_modes[key - 1]--;
1436       continue;
1437     }
1438     if (mode == -3) {
1439       d_print((tmp = lives_strdup_printf(_("Too many effects bound to key %d.\n"), key)));
1440       LIVES_ERROR(tmp);
1441       lives_free(tmp);
1442       if (keymap_file2) {
1443         // read param defaults
1444         if (!read_perkey_defaults(kfd, -1, -1, version)) break; // file read error
1445       }
1446       def_modes[key - 1]--;
1447       continue;
1448     }
1449     if (rte_window) {
1450       int idx = (key - 1) * modes + mode;
1451       int fx_idx = rte_keymode_get_filter_idx(key, mode);
1452 
1453       rtew_combo_set_text(key - 1, mode, (tmp = rte_keymode_get_filter_name(key, mode, FALSE)));
1454       lives_free(tmp);
1455 
1456       if (fx_idx != -1) {
1457         hashname = (char *)lives_list_nth_data(hash_list, fx_idx);
1458         lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combos[idx]), "hashname", hashname);
1459       } else lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combos[idx]), "hashname", empty_string);
1460 
1461       // set parameters button sensitive/insensitive
1462       set_param_and_con_buttons(key - 1, mode);
1463     }
1464 
1465     if (keymap_file2) {
1466       // read param defaults
1467       if (!read_perkey_defaults(kfd, key - 1, def_modes[key - 1], version)) break; // file read error
1468     }
1469   }
1470 
1471   if (!keymap_file2) {
1472     lives_list_free_all(&list);
1473 
1474     if (update > 0) {
1475       d_print(_("update required.\n"));
1476       on_save_keymap_clicked(NULL, NULL);
1477       lives_list_free_all(&new_list);
1478       on_load_keymap_clicked(NULL, NULL);
1479     } else d_print_done();
1480   } else {
1481     if (kfd != -1) lives_close_buffered(kfd);
1482     if (prefs->startup_phase && notfound) {
1483       on_save_keymap_clicked(NULL, NULL);
1484     }
1485     d_print_done();
1486   }
1487 
1488   if (update == 0) {
1489     if (lives_file_test(keymap_file3, LIVES_FILE_TEST_EXISTS)) {
1490       d_print(_("Loading data connection map from %s..."), keymap_file3);
1491 
1492       if (load_datacons(keymap_file3, badkeymap)) d_print_done();
1493     }
1494 
1495     if (mainw->is_ready) {
1496       check_clear_all_button();
1497       if (notfound) do_warning_dialog(_("\n\nSome effects could not be located.\n\n"));
1498     } else load_rte_defs(); // file errors shown inside
1499   }
1500 
1501 cleanup1:
1502 
1503   if (badkeymap) {
1504     for (i = 0; i < prefs->rte_keys_virtual; i++) {
1505       lives_free(badkeymap[i]);
1506     }
1507 
1508     lives_free(badkeymap);
1509   }
1510   lives_freep((void **)&keymap_file); // frees keymap_file2 if applicable
1511   lives_freep((void **)&keymap_file3);
1512   lives_freep((void **)&def_modes);
1513   if (mainw->ce_thumbs) ce_thumbs_reset_combos();
1514   if (rte_window) check_clear_all_button();
1515 
1516   return FALSE;
1517 }
1518 
1519 
on_rte_info_clicked(LiVESButton * button,livespointer user_data)1520 void on_rte_info_clicked(LiVESButton * button, livespointer user_data) {
1521   weed_plant_t *filter;
1522 
1523   LiVESWidget *dialog;
1524 
1525   LiVESWidget *vbox;
1526   LiVESWidget *hbox;
1527   LiVESWidget *label;
1528   LiVESWidget *textview;
1529   LiVESWidget *scrolledwindow;
1530   LiVESWidget *ok_button;
1531 
1532   char *filter_name, *filter_author, *filter_copyright;
1533   char *filter_extra_authors = NULL;
1534   char *filter_description;
1535   char *url, *license, *type;
1536   char *plugin_name, *plname, *package_name;
1537   char *tmp;
1538 
1539   boolean has_desc = FALSE;
1540   boolean has_url = FALSE;
1541   boolean has_license = FALSE;
1542   boolean has_copyright = FALSE;
1543 
1544   int filter_version;
1545   int weed_error;
1546 
1547   int key_mode = LIVES_POINTER_TO_INT(user_data);
1548   int modes = rte_getmodespk();
1549   int key = (int)(key_mode / modes);
1550   int mode = key_mode - key * modes;
1551   int window_width = RFX_WINSIZE_H;
1552 
1553   ////////////////////////
1554 
1555   if (!rte_keymode_valid(key + 1, mode, TRUE)) return;
1556 
1557   type = rte_keymode_get_type(key + 1, mode);
1558 
1559   plugin_name = rte_keymode_get_plugin_name(key + 1, mode);
1560   filter = rte_keymode_get_filter(key + 1, mode);
1561   filter_name = weed_get_string_value(filter, WEED_LEAF_NAME, &weed_error);
1562   package_name = weed_filter_get_package_name(filter);
1563   filter_author = weed_get_string_value(filter, WEED_LEAF_AUTHOR, &weed_error);
1564   if (weed_plant_has_leaf(filter, WEED_LEAF_EXTRA_AUTHORS)) filter_extra_authors = weed_get_string_value(filter,
1565         WEED_LEAF_EXTRA_AUTHORS, &weed_error);
1566   if (weed_plant_has_leaf(filter, WEED_LEAF_COPYRIGHT)) {
1567     filter_copyright = weed_get_string_value(filter, WEED_LEAF_COPYRIGHT, &weed_error);
1568     has_copyright = TRUE;
1569   }
1570   if (weed_plant_has_leaf(filter, WEED_LEAF_DESCRIPTION)) {
1571     filter_description = weed_get_string_value(filter, WEED_LEAF_DESCRIPTION, &weed_error);
1572     has_desc = TRUE;
1573   }
1574   if (weed_plant_has_leaf(filter, WEED_LEAF_URL)) {
1575     url = weed_get_string_value(filter, WEED_LEAF_URL, &weed_error);
1576     has_url = TRUE;
1577   }
1578 
1579   if (weed_plant_has_leaf(filter, WEED_LEAF_LICENSE)) {
1580     license = weed_get_string_value(filter, WEED_LEAF_LICENSE, &weed_error);
1581     has_license = TRUE;
1582   }
1583 
1584   filter_version = weed_get_int_value(filter, WEED_LEAF_VERSION, &weed_error);
1585 
1586   tmp = lives_strdup_printf(_("Information for %s"), filter_name);
1587 
1588   dialog = lives_standard_dialog_new(tmp, FALSE, RTE_INFO_WIDTH, RTE_INFO_HEIGHT);
1589 
1590   lives_free(tmp);
1591 
1592   vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
1593 
1594   widget_opts.justify = LIVES_JUSTIFY_CENTER;
1595   label = lives_standard_label_new((tmp = lives_strdup_printf(_("Effect name: %s"), filter_name)));
1596   lives_free(tmp);
1597   lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1598 
1599   label = lives_standard_label_new((tmp = lives_strdup_printf(_("Type: %s"), type)));
1600   lives_free(tmp);
1601   lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1602 
1603   plname = lives_strdup_printf("%s.%s", plugin_name, DLL_NAME);
1604   label = lives_standard_label_new((tmp = lives_strdup_printf(_("Plugin name: %s"), plname)));
1605   lives_free(tmp); lives_free(plname);
1606   lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1607 
1608   if (package_name) {
1609     label = lives_standard_label_new((tmp = lives_strdup_printf(_("Package name: %s"), package_name)));
1610     lives_free(tmp);
1611     lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1612   }
1613 
1614   label = lives_standard_label_new((tmp = lives_strdup_printf(_("Author: %s"), filter_author)));
1615   lives_free(tmp);
1616   lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1617 
1618   if (filter_extra_authors) {
1619     label = lives_standard_label_new((tmp = lives_strdup_printf(_("and: %s"), filter_extra_authors)));
1620     lives_free(tmp);
1621     lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1622   }
1623 
1624   if (has_url) {
1625     label = lives_standard_label_new((tmp = lives_strdup_printf(_("URL: %s"), url)));
1626     lives_free(tmp);
1627     lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1628   }
1629 
1630   label = lives_standard_label_new((tmp = lives_strdup_printf(_("Version: %d"), filter_version)));
1631   lives_free(tmp);
1632   lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1633 
1634   if (has_desc) {
1635     hbox = lives_hbox_new(FALSE, widget_opts.packing_width);
1636     lives_box_pack_start(LIVES_BOX(vbox), hbox, TRUE, FALSE, widget_opts.packing_height);
1637 
1638     label = lives_standard_label_new(_("Description: "));
1639     lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, widget_opts.packing_height);
1640 
1641     widget_opts.justify = LIVES_JUSTIFY_DEFAULT;
1642     textview = lives_standard_text_view_new(filter_description, NULL);
1643     widget_opts.justify = LIVES_JUSTIFY_CENTER;
1644 
1645     widget_opts.expand = LIVES_EXPAND_EXTRA_WIDTH | LIVES_EXPAND_DEFAULT_HEIGHT;
1646     scrolledwindow = lives_standard_scrolled_window_new(window_width * 2, RFX_WINSIZE_V / 2, textview);
1647     lives_box_pack_start(LIVES_BOX(hbox), scrolledwindow, TRUE, TRUE, widget_opts.packing_height);
1648     widget_opts.expand = LIVES_EXPAND_DEFAULT;
1649     if (palette->style & STYLE_1) {
1650       lives_widget_set_text_color(textview, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
1651       lives_widget_set_base_color(textview, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
1652       lives_widget_set_bg_color(lives_bin_get_child(LIVES_BIN(scrolledwindow)),
1653                                 LIVES_WIDGET_STATE_NORMAL, &palette->nice1);
1654     }
1655   }
1656 
1657   if (has_license) {
1658     label = lives_standard_label_new((tmp = lives_strdup_printf(_("License: %s"), license)));
1659     lives_free(tmp);
1660     lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1661   }
1662 
1663   if (has_copyright) {
1664     label = lives_standard_label_new((tmp = lives_strdup_printf(_("Copyright: %s"), filter_copyright)));
1665     lives_free(tmp);
1666     lives_box_pack_start(LIVES_BOX(vbox), label, TRUE, FALSE, widget_opts.packing_height);
1667   }
1668 
1669   widget_opts.justify = LIVES_JUSTIFY_DEFAULT;
1670 
1671   add_fill_to_box(LIVES_BOX(vbox));
1672 
1673   ok_button = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_CLOSE, _("_Close Window"),
1674               LIVES_RESPONSE_OK);
1675 
1676   lives_button_grab_default_special(ok_button);
1677 
1678   lives_signal_connect(LIVES_GUI_OBJECT(ok_button), LIVES_WIDGET_CLICKED_SIGNAL,
1679                        LIVES_GUI_CALLBACK(lives_general_button_clicked), NULL);
1680 
1681   lives_free(filter_name);
1682   lives_free(filter_author);
1683   lives_freep((void **)&filter_extra_authors);
1684   lives_freep((void **)&package_name);
1685   if (has_desc) lives_free(filter_description);
1686   if (has_url) lives_free(url);
1687   if (has_license) lives_free(license);
1688   if (has_copyright) lives_free(filter_copyright);
1689   lives_free(plugin_name);
1690   lives_free(type);
1691 
1692   lives_widget_show_all(dialog);
1693   lives_window_center(LIVES_WINDOW(dialog));
1694 }
1695 
1696 
on_clear_clicked(LiVESButton * button,livespointer user_data)1697 void on_clear_clicked(LiVESButton * button, livespointer user_data) {
1698   // this is for the "delete" buttons, c.f. clear_all
1699 
1700   int idx = LIVES_POINTER_TO_INT(user_data);
1701   int modes = rte_getmodespk();
1702   int key = (int)(idx / modes);
1703   int mode = idx - key * modes;
1704 
1705   int newmode;
1706 
1707   register int i;
1708 
1709   weed_delete_effectkey(key + 1, mode);
1710 
1711   pconx_delete(FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, key, mode, FX_DATA_WILDCARD);
1712   pconx_delete(key, mode, FX_DATA_WILDCARD, -1, FX_DATA_WILDCARD, FX_DATA_WILDCARD);
1713 
1714   cconx_delete(FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, key, mode, FX_DATA_WILDCARD);
1715   cconx_delete(key, mode, FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD);
1716 
1717   newmode = rte_key_getmode(key + 1);
1718 
1719   if (mainw->ce_thumbs) ce_thumbs_set_mode_combo(key, newmode);
1720 
1721   if (rte_window) {
1722     rtew_set_mode_radio(key, newmode);
1723   }
1724 
1725   for (i = mode; i < rte_getmodespk() - 1; i++) {
1726     pconx_remap_mode(key, i + 1, i);
1727     cconx_remap_mode(key, i + 1, i);
1728 
1729     if (rte_window) {
1730       int fx_idx = rte_keymode_get_filter_idx(key, mode);
1731       idx = key * modes + i;
1732       rtew_combo_set_text(key, i, lives_entry_get_text(LIVES_ENTRY(combo_entries[idx + 1])));
1733 
1734       if (fx_idx != -1) {
1735         char *hashname = (char *)lives_list_nth_data(hash_list, fx_idx);
1736         lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combos[idx]), "hashname", hashname);
1737       } else lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combos[idx]), "hashname", empty_string);
1738 
1739       // set parameters button sensitive/insensitive
1740       set_param_and_con_buttons(key, i);
1741     }
1742   }
1743   idx++;
1744 
1745   if (rte_window) {
1746     rtew_combo_set_text(key, i, "");
1747     lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combos[idx]), "hashname", empty_string);
1748 
1749     // set parameters button sensitive/insensitive
1750     set_param_and_con_buttons(key, i);
1751   }
1752 
1753   if (!rte_keymode_valid(key + 1, 0, TRUE)) {
1754     if (rte_window) rtew_set_keych(key, FALSE);
1755     if (mainw->ce_thumbs) ce_thumbs_set_keych(key, FALSE);
1756   }
1757   if (rte_window) check_clear_all_button();
1758 
1759   if (mainw->ce_thumbs) ce_thumbs_reset_combo(key);
1760 }
1761 
1762 
on_datacon_clicked(LiVESButton * button,livespointer user_data)1763 static void on_datacon_clicked(LiVESButton * button, livespointer user_data) {
1764   int idx = LIVES_POINTER_TO_INT(user_data);
1765   int modes = rte_getmodespk();
1766   int key = (int)(idx / modes);
1767   int mode = idx - key * modes;
1768 
1769   //if (datacon_dialog!=NULL) on_datacon_cancel_clicked(NULL,NULL);
1770   datacon_dialog = make_datacon_window(key, mode);
1771 }
1772 
1773 
check_string_choice_params(weed_plant_t * inst)1774 void check_string_choice_params(weed_plant_t *inst) {
1775   int nparams;
1776   weed_plant_t **in_params = weed_instance_get_in_params(inst, &nparams);
1777   weed_plant_t *gui, *tgui;
1778   for (int i = 0; i < nparams; i++) {
1779     if ((gui = weed_param_get_gui(in_params[i], FALSE)) != NULL && weed_plant_has_leaf(gui, WEED_LEAF_CHOICES)) {
1780       tgui = weed_paramtmpl_get_gui(weed_param_get_template(in_params[i]), TRUE);
1781       weed_leaf_copy(tgui, WEED_LEAF_CHOICES, gui, WEED_LEAF_CHOICES);
1782     }
1783   }
1784 }
1785 
1786 
on_params_clicked(LiVESButton * button,livespointer user_data)1787 static void on_params_clicked(LiVESButton * button, livespointer user_data) {
1788   int idx = LIVES_POINTER_TO_INT(user_data);
1789   int modes = rte_getmodespk();
1790   int key = (int)(idx / modes);
1791   int mode = idx - key * modes;
1792 
1793   weed_plant_t *inst;
1794   lives_rfx_t *rfx;
1795 
1796   filter_mutex_lock(key);
1797   if ((inst = rte_keymode_get_instance(key + 1, mode)) == NULL) {
1798     // create a new detached instance for the dialog
1799     weed_plant_t *filter = rte_keymode_get_filter(key + 1, mode);
1800     if (!filter) {
1801       filter_mutex_unlock(key);
1802       return;
1803     }
1804     inst = weed_instance_from_filter(filter);
1805     weed_set_boolean_value(inst, WEED_LEAF_HOST_NORECORD, WEED_TRUE);
1806 
1807     // do some fiddly stuff to show the key defs.
1808     filter_mutex_unlock(key);
1809     weed_reinit_effect(inst, TRUE);
1810     filter_mutex_lock(key);
1811     check_string_choice_params(inst);
1812     apply_key_defaults(inst, key, mode);
1813     filter_mutex_unlock(key);
1814     weed_reinit_effect(inst, TRUE);
1815     filter_mutex_lock(key);
1816   } else weed_instance_ref(inst);
1817 
1818   filter_mutex_unlock(key);
1819 
1820   if (fx_dialog[1]) {
1821     lives_widget_destroy(fx_dialog[1]->dialog);
1822     rfx = fx_dialog[1]->rfx;
1823     on_paramwindow_button_clicked(NULL, rfx);
1824     lives_freep((void **)&fx_dialog[1]);
1825   }
1826 
1827   rfx = weed_to_rfx(inst, FALSE);
1828   rfx->min_frames = -1;
1829   keyw = key;
1830   modew = mode;
1831 
1832   widget_opts.non_modal = TRUE;
1833   on_fx_pre_activate(rfx, TRUE, NULL);
1834   widget_opts.non_modal = FALSE;
1835 
1836   // record the key so we know whose parameters to record later
1837   weed_set_int_value((weed_plant_t *)rfx->source, WEED_LEAF_HOST_KEY, key);
1838 
1839   fx_dialog[1]->key = key;
1840   fx_dialog[1]->mode = mode;
1841   fx_dialog[1]->rfx = rfx;
1842   weed_instance_unref(inst);
1843 }
1844 
1845 
on_rtew_delete_event(LiVESWidget * widget,LiVESXEventDelete * event,livespointer user_data)1846 boolean on_rtew_delete_event(LiVESWidget * widget, LiVESXEventDelete * event, livespointer user_data) {
1847   old_rte_keys_virtual = prefs->rte_keys_virtual;
1848   lives_widget_set_sensitive(mainw->mt_menu, TRUE);
1849   lives_widget_set_sensitive(mainw->rte_defs_menu, TRUE);
1850   if (!user_data) {
1851     // first time around we come here, and just hide the window
1852     if (mainw->play_window && !mainw->fs && (prefs->play_monitor == widget_opts.monitor + 1 || capable->nmonitors == 1)) {
1853       lives_window_set_transient_for(LIVES_WINDOW(mainw->play_window), get_transient_full());
1854     }
1855     lives_widget_hide(rte_window);
1856     rte_window_is_hidden = TRUE;
1857   } else {
1858     // when we reshow it we check if the number of fx keys has changed. If so we come back to this branch
1859     // and recreate the window from scratch
1860     lives_list_free_all(&hash_list);
1861     lives_list_free_all(&name_list);
1862     lives_list_free_all(&extended_name_list);
1863 
1864     lives_free(key_checks);
1865     lives_free(key_grabs);
1866     lives_free(mode_radios);
1867     lives_free(combo_entries);
1868     lives_free(combos);
1869     lives_free(ch_fns);
1870     lives_free(mode_ra_fns);
1871     lives_free(gr_fns);
1872     lives_free(nlabels);
1873     lives_free(type_labels);
1874     lives_free(info_buttons);
1875     lives_free(param_buttons);
1876     lives_free(conx_buttons);
1877     lives_free(clear_buttons);
1878   }
1879   return FALSE;
1880 }
1881 
1882 
on_rtew_ok_clicked(LiVESButton * button,livespointer user_data)1883 static boolean on_rtew_ok_clicked(LiVESButton * button, livespointer user_data) {
1884   on_rtew_delete_event(NULL, NULL, NULL);
1885   return TRUE;
1886 }
1887 
1888 
do_mix_error(void)1889 LIVES_LOCAL_INLINE void do_mix_error(void) {
1890   widget_opts.non_modal = TRUE;
1891   do_error_dialog(_("\n\nThis version of LiVES does not allowing mixing of "
1892                     "generators and non-generators on the same key.\n\n"));
1893   widget_opts.non_modal = FALSE;
1894   return;
1895 }
1896 
1897 
1898 enum {
1899   EXTENDED_NAME_COLUMN,
1900   NAME_COLUMN,
1901   HASH_COLUMN,
1902   NUM_COLUMNS
1903 };
1904 
rtew_combo_set_text(int key,int mode,const char * txt)1905 void rtew_combo_set_text(int key, int mode, const char *txt) {
1906   // key is zero based
1907   int key_mode = key * rte_getmodespk() + mode;
1908   lives_entry_set_text(LIVES_ENTRY(combo_entries[key_mode]), txt);
1909   type_label_set_text(key, mode);
1910 }
1911 
1912 
fx_changed(LiVESCombo * combo,livespointer user_data)1913 void fx_changed(LiVESCombo * combo, livespointer user_data) {
1914   LiVESTreeIter iter1;
1915   LiVESTreeModel *model;
1916 
1917   char *txt;
1918   char *tmp;
1919   char *hashname1;
1920   char *hashname2 = (char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "hashname");
1921 
1922   int key_mode = LIVES_POINTER_TO_INT(user_data);
1923   int modes = rte_getmodespk();
1924   int key = (int)(key_mode / modes);
1925   int mode = key_mode - key * modes;
1926 
1927   int i, error;
1928 
1929   if (lives_combo_get_active_index(combo) == -1) return; // -1 is returned after we set our own text (without the type)
1930 
1931   lives_combo_get_active_iter(combo, &iter1);
1932   model = lives_combo_get_model(combo);
1933 
1934   lives_tree_model_get(model, &iter1, HASH_COLUMN, &hashname1, -1);
1935   if (!hashname1) {
1936     lives_entry_set_text(LIVES_ENTRY(combo_entries[key_mode]), (tmp = rte_keymode_get_filter_name(key + 1, mode, FALSE)));
1937     lives_free(tmp);
1938     return;
1939   }
1940 
1941   if (!strcmp(hashname1, hashname2)) {
1942     lives_free(hashname1);
1943     return;
1944   }
1945 
1946   if (!rte_keymode_valid(key + 1, mode, TRUE)) {
1947     for (i = mode - 1; i >= 0; i--) {
1948       if (rte_keymode_valid(key + 1, i, TRUE)) {
1949         mode = i + 1;
1950         i = -1;
1951       }
1952       if (i == 0) mode = 0;
1953     }
1954   }
1955 
1956   lives_widget_grab_focus(combo_entries[key_mode]);
1957 
1958   if ((error = rte_switch_keymode(key + 1, mode, hashname1)) < 0) {
1959     lives_entry_set_text(LIVES_ENTRY(combo_entries[key_mode]), (tmp = rte_keymode_get_filter_name(key + 1, mode, FALSE)));
1960     lives_free(tmp);
1961 
1962     if (error == -2) do_mix_error();
1963     if (error == -1) {
1964       d_print(_("LiVES could not locate the effect %s.\n"), rte_keymode_get_filter_name(key + 1, mode, FALSE));
1965     }
1966     return;
1967   }
1968 
1969   // prevents a segfault
1970   lives_combo_get_active_iter(combo, &iter1);
1971   model = lives_combo_get_model(combo);
1972 
1973   lives_tree_model_get(model, &iter1, NAME_COLUMN, &txt, -1);
1974   rtew_combo_set_text(key, mode, txt);
1975   lives_free(txt);
1976 
1977   lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo), "hashname", hashname1);
1978 
1979   // set parameters button sensitive/insensitive
1980   set_param_and_con_buttons(key, mode);
1981 
1982   check_clear_all_button();
1983 
1984   pconx_delete(FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, key, mode, FX_DATA_WILDCARD_KEEP_ACTIVATED);
1985   pconx_delete(key, mode, FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD);
1986 
1987   cconx_delete(FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, key, mode, FX_DATA_WILDCARD);
1988   cconx_delete(key, mode, FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD, FX_DATA_WILDCARD);
1989 
1990   if (mainw->ce_thumbs) ce_thumbs_reset_combos();
1991 }
1992 
1993 static LiVESTreeStore *tstore = NULL;
1994 
rte_window_fx_model(void)1995 static LiVESTreeModel *rte_window_fx_model(void) {
1996   weed_plant_t *pinfo;
1997   LiVESTreeIter iter1, iter2, iter3;
1998 
1999   LiVESList *list = extended_name_list;
2000   LiVESList *pname_list = name_list;
2001   LiVESList *phash_list = hash_list;
2002 
2003   lives_fx_cat_t cat;
2004 
2005   char *pkg = NULL, *pkgstring, *fxname, *typestr;
2006 
2007   int fx_idx = 0;
2008 
2009   if (tstore) return (LiVESTreeModel *)tstore;
2010 
2011   tstore = lives_tree_store_new(NUM_COLUMNS, LIVES_COL_TYPE_STRING, LIVES_COL_TYPE_STRING, LIVES_COL_TYPE_STRING);
2012   while (list) {
2013     weed_plant_t *filter = get_weed_filter(weed_get_idx_for_hashname((char *)phash_list->data, TRUE));
2014     if (!prefs->show_dev_opts && ((weed_filter_hints_unstable(filter)
2015                                    && !prefs->unstable_fx) ||
2016                                   weed_get_boolean_value(filter, WEED_LEAF_HOST_MENU_HIDE, NULL) == WEED_TRUE
2017                                   || ((enabled_in_channels(filter, FALSE) > 1 &&
2018                                        !has_video_chans_in(filter, FALSE)) ||
2019                                       (weed_filter_hints_hidden(filter)
2020                                        || weed_filter_is_converter(filter))
2021                                       || enabled_in_channels(filter, TRUE) == 1000000))) {
2022       list = list->next;
2023       fx_idx++;
2024       pname_list = pname_list->next;
2025       phash_list = phash_list->next;
2026       continue; // skip audio transitions, compositors and hidden entries
2027     }
2028 
2029     fxname = lives_strdup((const char *)pname_list->data);
2030     cat = weed_filter_categorise(filter,
2031                                  enabled_in_channels(filter, TRUE),
2032                                  enabled_out_channels(filter, TRUE));
2033     typestr = lives_fx_cat_to_text(cat, TRUE);
2034 
2035     pinfo = weed_get_plantptr_value(filter, WEED_LEAF_PLUGIN_INFO, NULL);
2036     if (weed_plant_has_leaf(pinfo, WEED_LEAF_PACKAGE_NAME))
2037       pkgstring = weed_get_string_value(pinfo, WEED_LEAF_PACKAGE_NAME, NULL);
2038     else pkgstring = NULL;
2039 
2040     if (pkgstring) {
2041       // package effect
2042       if (pkg && lives_strcmp(pkg, pkgstring)) {
2043         // new package
2044         lives_freep((void **)&pkg);
2045       }
2046 
2047       if (!pkg) {
2048         // add package to menu
2049         pkg = pkgstring;
2050 
2051         /* TRANSLATORS: example " - LADSPA plugins -" */
2052         pkgstring = lives_strdup_printf(_(" - %s plugins -"), pkg);
2053         lives_tree_store_prepend(tstore, &iter1, NULL);
2054         lives_tree_store_set(tstore, &iter1, EXTENDED_NAME_COLUMN, pkgstring, -1);
2055         lives_free(pkgstring);
2056       }
2057       // add to package submenu
2058 
2059       // get a new or existing iterator for the category (set in iter2)
2060       lives_tree_store_find_iter(tstore, EXTENDED_NAME_COLUMN, typestr, &iter1, &iter2);
2061       lives_tree_store_append(tstore, &iter3, &iter2);
2062       lives_tree_store_set(tstore, &iter3, EXTENDED_NAME_COLUMN, list->data, NAME_COLUMN, fxname,
2063                            HASH_COLUMN, lives_list_nth_data(hash_list, fx_idx), -1);
2064     } else {
2065       //if (pkg) lives_freep((void **)&pkg);
2066       // get a new or existing iterator for the category
2067       lives_tree_store_find_iter(tstore, EXTENDED_NAME_COLUMN, typestr, NULL, &iter1);
2068 
2069       lives_tree_store_append(tstore, &iter2, &iter1);   /* Acquire an iterator */
2070       lives_tree_store_set(tstore, &iter2, EXTENDED_NAME_COLUMN, list->data, NAME_COLUMN, fxname,
2071                            HASH_COLUMN, lives_list_nth_data(hash_list, fx_idx), -1);
2072     }
2073     lives_free(fxname);
2074     lives_free(typestr);
2075 
2076     list = list->next;
2077     fx_idx++;
2078     pname_list = pname_list->next;
2079     phash_list = phash_list->next;
2080   }
2081 
2082   lives_freep((void **)&pkg);
2083 
2084   return (LiVESTreeModel *)tstore;
2085 }
2086 
2087 
create_rte_window(void)2088 LiVESWidget *create_rte_window(void) {
2089   LiVESWidget *irte_window = rte_window;
2090   LiVESWidget *table;
2091   LiVESWidget *hbox;
2092   LiVESWidget *hbox2;
2093 
2094   LiVESWidget *vbox, *vbox2;
2095   LiVESWidget *label;
2096   LiVESWidget *combo;
2097   LiVESWidget *ok_button;
2098   LiVESWidget *top_vbox;
2099   LiVESWidget *hbuttonbox;
2100 
2101   LiVESWidget *scrolledwindow;
2102 
2103   LiVESSList *mode_group = NULL;
2104   LiVESSList *grab_group = NULL;
2105 
2106   LiVESAccelGroup *rtew_accel_group;
2107 
2108   LiVESTreeModel *model;
2109 
2110   char *tmp, *tmp2, *labelt;
2111 
2112   int modes = rte_getmodespk();
2113 
2114   int idx;
2115 
2116   int winsize_h;
2117   int winsize_v;
2118 
2119   register int i, j;
2120 
2121   ///////////////////////////////////////////////////////////////////////////
2122 
2123   lives_set_cursor_style(LIVES_CURSOR_BUSY, NULL);
2124   lives_widget_context_update();
2125   mainw->no_context_update = TRUE;
2126 
2127   winsize_h = GUI_SCREEN_WIDTH - SCR_WIDTH_SAFETY;
2128   winsize_v = GUI_SCREEN_HEIGHT - SCR_HEIGHT_SAFETY;
2129 
2130   if (irte_window) {
2131     if (prefs->rte_keys_virtual != old_rte_keys_virtual) {
2132       // number of fx keys changed, rebuild the window
2133       mainw->no_context_update = FALSE;
2134       return refresh_rte_window();
2135     }
2136     goto rte_window_ready;
2137   }
2138 
2139   key_checks = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * sizeof(LiVESWidget *));
2140   key_grabs = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * sizeof(LiVESWidget *));
2141   mode_radios = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2142   combo_entries = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2143   combos = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2144   info_buttons = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2145   param_buttons = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2146   conx_buttons = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2147   clear_buttons = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2148   nlabels = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2149   type_labels = (LiVESWidget **)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(LiVESWidget *));
2150 
2151   ch_fns = (ulong *)lives_malloc((prefs->rte_keys_virtual) * sizeof(ulong));
2152   gr_fns = (ulong *)lives_malloc((prefs->rte_keys_virtual) * sizeof(ulong));
2153   mode_ra_fns = (ulong *)lives_malloc((prefs->rte_keys_virtual) * modes * sizeof(ulong));
2154 
2155   irte_window = lives_window_new(LIVES_WINDOW_TOPLEVEL);
2156   lives_window_set_transient_for(LIVES_WINDOW(irte_window), LIVES_WINDOW(LIVES_MAIN_WINDOW_WIDGET));
2157 
2158   if (palette->style & STYLE_1) {
2159     lives_widget_set_bg_color(irte_window, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
2160     lives_widget_set_text_color(irte_window, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars_fore);
2161   }
2162   lives_window_set_title(LIVES_WINDOW(irte_window), _("Real Time Effect Mapping"));
2163   lives_window_add_accel_group(LIVES_WINDOW(irte_window), mainw->accel_group);
2164 
2165   table = lives_table_new(prefs->rte_keys_virtual, modes + 1, FALSE);
2166 
2167   lives_table_set_row_spacings(LIVES_TABLE(table), 16 * widget_opts.scale);
2168   lives_table_set_col_spacings(LIVES_TABLE(table), 4 * widget_opts.scale);
2169 
2170   // dummy button for "no grab", we dont show this...there is a button instead
2171   dummy_radio = lives_radio_button_new(grab_group);
2172   grab_group = lives_radio_button_get_group(LIVES_RADIO_BUTTON(dummy_radio));
2173   lives_widget_set_no_show_all(dummy_radio, TRUE);
2174 
2175   if (!name_list) name_list = weed_get_all_names(FX_LIST_NAME);
2176   if (!extended_name_list) extended_name_list = weed_get_all_names(FX_LIST_EXTENDED_NAME);
2177   if (!hash_list) hash_list = weed_get_all_names(FX_LIST_HASHNAME);
2178 
2179   model = rte_window_fx_model();
2180 
2181   for (i = 0; i < prefs->rte_keys_virtual * modes; i++) {
2182     // create combo entry model
2183     combos[i] = NULL;
2184   }
2185 
2186   for (i = 0; i < prefs->rte_keys_virtual; i++) {
2187     hbox = lives_hbox_new(FALSE, 0);
2188     lives_table_attach(LIVES_TABLE(table), hbox, i, i + 1, 0, 1,
2189                        (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
2190                        (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL), 0, 0);
2191     lives_container_set_border_width(LIVES_CONTAINER(hbox), widget_opts.border_width);
2192 
2193     if (i < 9) labelt = lives_strdup_printf("%d", i + 1);
2194     else  {
2195       switch (i) {
2196       case 9:
2197         labelt = (_("minus")); break;
2198       case 10:
2199         labelt = (_("equals")); break;
2200       default:
2201         labelt = lives_strdup("????");
2202         break;
2203       }
2204     }
2205 
2206     widget_opts.use_markup = TRUE;
2207     label = lives_standard_label_new((tmp = lives_strdup_printf(_("<big><b>Ctrl-%s</b></big>"), labelt)));
2208     widget_opts.use_markup = FALSE;
2209     lives_free(labelt);
2210     lives_free(tmp);
2211 
2212     lives_box_pack_start(LIVES_BOX(hbox), label, TRUE, FALSE, widget_opts.packing_width);
2213 
2214     hbox2 = lives_hbox_new(FALSE, 0);
2215 
2216     //key_checks[i] = lives_standard_check_button_new(_("Key active"), (mainw->rte & (GU641 << i)), LIVES_BOX(hbox2), NULL);
2217     key_checks[i] = lives_standard_switch_new(_("Key active"), (mainw->rte & (GU641 << i)), LIVES_BOX(hbox2), NULL);
2218 
2219     lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, widget_opts.packing_width);
2220 
2221     lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[i]), mainw->rte & (GU641 << i));
2222     lives_widget_object_set_data(LIVES_WIDGET_OBJECT(key_checks[i]), "active",
2223                                  LIVES_INT_TO_POINTER(lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(key_checks[i]))));
2224 
2225     ch_fns[i] = lives_signal_connect_after(LIVES_GUI_OBJECT(key_checks[i]), LIVES_WIDGET_TOGGLED_SIGNAL,
2226                                            LIVES_GUI_CALLBACK(rte_on_off_callback_hook), LIVES_INT_TO_POINTER(i + 1));
2227 
2228     hbox2 = lives_hbox_new(FALSE, 0);
2229     lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, widget_opts.packing_width);
2230 
2231     key_grabs[i] = lives_standard_radio_button_new((tmp = (_("Key grab"))), &grab_group, LIVES_BOX(hbox2),
2232                    (tmp2 = (_("Grab keyboard for this effect key"))));
2233     lives_free(tmp);
2234     lives_free(tmp2);
2235     lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_grabs[i]), mainw->rte_keys == i);
2236 
2237     gr_fns[i] = lives_signal_connect_after(LIVES_GUI_OBJECT(key_grabs[i]), LIVES_WIDGET_TOGGLED_SIGNAL,
2238                                            LIVES_GUI_CALLBACK(grabkeys_callback_hook), LIVES_INT_TO_POINTER(i));
2239 
2240     mode_group = NULL;
2241 
2242     for (j = 0; j < modes; j++) {
2243       idx = i * modes + j;
2244       hbox = lives_hbox_new(FALSE, 0);
2245       lives_table_attach(LIVES_TABLE(table), hbox, i, i + 1, j + 1, j + 2,
2246                          (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL),
2247                          (LiVESAttachOptions)(LIVES_EXPAND | LIVES_FILL), 0, 0);
2248       lives_container_set_border_width(LIVES_CONTAINER(hbox), widget_opts.border_width * 1.5);
2249 
2250       hbox2 = lives_hbox_new(FALSE, 0);
2251 
2252       lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, widget_opts.packing_width);
2253 
2254       mode_radios[idx] = lives_standard_radio_button_new(_("Mode active"), &mode_group, LIVES_BOX(hbox2), NULL);
2255 
2256       if (rte_key_getmode(i + 1) == j) lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(mode_radios[idx]), TRUE);
2257 
2258       mode_ra_fns[idx] = lives_signal_connect_after(LIVES_GUI_OBJECT(mode_radios[idx]), LIVES_WIDGET_TOGGLED_SIGNAL,
2259                          LIVES_GUI_CALLBACK(rtemode_callback_hook), LIVES_INT_TO_POINTER(idx));
2260 
2261 
2262       type_labels[idx] = lives_standard_label_new("");
2263 
2264       lives_label_set_line_wrap(LIVES_LABEL(type_labels[idx]), TRUE);
2265       lives_label_set_line_wrap_mode(LIVES_LABEL(type_labels[idx]), LINGO_WRAP_WORD_CHAR);
2266       lives_label_seT_lines(LIVES_LABEL(type_labels[idx]), 3);
2267       lives_label_set_ellipsize(LIVES_LABEL(type_labels[idx]), LIVES_ELLIPSIZE_END);
2268 
2269       info_buttons[idx] = lives_standard_button_new_with_label(_("Info"),
2270                           DEF_BUTTON_WIDTH / 3, DEF_BUTTON_HEIGHT);
2271       param_buttons[idx] = lives_standard_button_new_with_label(_("Set Parameters"),
2272                            DEF_BUTTON_WIDTH, DEF_BUTTON_HEIGHT);
2273       lives_widget_set_valign(param_buttons[idx], LIVES_ALIGN_CENTER);
2274       conx_buttons[idx] = lives_standard_button_new_with_label(_("Set Connections"),
2275                           DEF_BUTTON_WIDTH, DEF_BUTTON_HEIGHT);
2276       lives_widget_set_valign(conx_buttons[idx], LIVES_ALIGN_CENTER);
2277       clear_buttons[idx] = lives_standard_button_new_with_label(_("Clear"),
2278                            DEF_BUTTON_WIDTH / 3, DEF_BUTTON_HEIGHT);
2279 
2280       vbox = lives_vbox_new(FALSE, 0);
2281       lives_box_pack_start(LIVES_BOX(hbox), vbox, FALSE, FALSE, 0);
2282 
2283       vbox2 = lives_vbox_new(FALSE, 0);
2284       lives_box_pack_end(LIVES_BOX(hbox), vbox2, FALSE, FALSE, widget_opts.packing_width);
2285 
2286       lives_container_set_border_width(LIVES_CONTAINER(vbox), 0);
2287 
2288       hbox = lives_hbox_new(FALSE, 0);
2289 
2290       lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
2291 
2292       nlabels[idx] = lives_standard_label_new(_("Effect name:"));
2293 
2294       lives_box_pack_start(LIVES_BOX(hbox), nlabels[idx], FALSE, FALSE, widget_opts.packing_width);
2295 
2296       combos[idx] = combo = lives_standard_combo_new_with_model(model, LIVES_BOX(hbox));
2297       lives_combo_set_entry_text_column(LIVES_COMBO(combo), EXTENDED_NAME_COLUMN);
2298 
2299       lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo), "hashname", empty_string);
2300 
2301       lives_box_pack_start(LIVES_BOX(vbox2), info_buttons[idx], FALSE, FALSE, widget_opts.packing_height);
2302       lives_box_pack_start(LIVES_BOX(vbox2), clear_buttons[idx], FALSE, FALSE, widget_opts.packing_height);
2303 
2304       combo_entries[idx] = lives_combo_get_entry(LIVES_COMBO(combo));
2305 
2306       lives_entry_set_text(LIVES_ENTRY(combo_entries[idx]), (tmp = rte_keymode_get_filter_name(i + 1, j, FALSE)));
2307       lives_free(tmp);
2308 
2309       lives_entry_set_editable(LIVES_ENTRY(combo_entries[idx]), FALSE);
2310 
2311       hbox = lives_hbox_new(FALSE, 0);
2312       lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
2313 
2314       lives_signal_sync_connect(LIVES_GUI_OBJECT(combo), LIVES_WIDGET_CHANGED_SIGNAL,
2315                                 LIVES_GUI_CALLBACK(fx_changed), LIVES_INT_TO_POINTER(i * rte_getmodespk() + j));
2316 
2317       lives_signal_sync_connect(LIVES_GUI_OBJECT(info_buttons[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
2318                                 LIVES_GUI_CALLBACK(on_rte_info_clicked), LIVES_INT_TO_POINTER(idx));
2319 
2320       lives_signal_sync_connect(LIVES_GUI_OBJECT(clear_buttons[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
2321                                 LIVES_GUI_CALLBACK(on_clear_clicked), LIVES_INT_TO_POINTER(idx));
2322 
2323       lives_signal_sync_connect(LIVES_GUI_OBJECT(param_buttons[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
2324                                 LIVES_GUI_CALLBACK(on_params_clicked), LIVES_INT_TO_POINTER(idx));
2325 
2326       lives_signal_sync_connect(LIVES_GUI_OBJECT(conx_buttons[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
2327                                 LIVES_GUI_CALLBACK(on_datacon_clicked), LIVES_INT_TO_POINTER(idx));
2328 
2329       lives_box_pack_start(LIVES_BOX(hbox), type_labels[idx], FALSE, FALSE, widget_opts.packing_width);
2330       lives_box_pack_start(LIVES_BOX(hbox), conx_buttons[idx], FALSE, FALSE, widget_opts.packing_width);
2331       lives_box_pack_start(LIVES_BOX(hbox), param_buttons[idx], FALSE, FALSE, widget_opts.packing_width);
2332 
2333       // set parameters button sensitive/insensitive
2334       set_param_and_con_buttons(i, j);
2335     }
2336   }
2337 
2338   scrolledwindow = lives_standard_scrolled_window_new(winsize_h, winsize_v, table);
2339 
2340   top_vbox = lives_vbox_new(FALSE, 0);
2341 
2342   lives_box_pack_start(LIVES_BOX(top_vbox), dummy_radio, FALSE, FALSE, 0);
2343   lives_box_pack_start(LIVES_BOX(top_vbox), scrolledwindow, TRUE, TRUE, widget_opts.packing_height);
2344 
2345   lives_container_add(LIVES_CONTAINER(irte_window), top_vbox);
2346 
2347   hbuttonbox = lives_hbox_new(FALSE, 0);
2348   lives_box_pack_start(LIVES_BOX(top_vbox), hbuttonbox, FALSE, TRUE, 0);
2349 
2350   add_fill_to_box(LIVES_BOX(hbuttonbox));
2351   lives_widget_apply_theme(hbuttonbox, LIVES_WIDGET_STATE_NORMAL);
2352 
2353   clear_all_button = lives_dialog_add_button_from_stock(NULL, LIVES_STOCK_CLEAR, _("_Clear all effects"),
2354                      LIVES_RESPONSE_RESET);
2355 
2356   lives_box_pack_start(LIVES_BOX(hbuttonbox), clear_all_button, TRUE, TRUE, widget_opts.packing_width);
2357 
2358   save_keymap_button = lives_dialog_add_button_from_stock(NULL, LIVES_STOCK_SAVE_AS, _("_Save as default keymap"),
2359                        LIVES_RESPONSE_ACCEPT);
2360 
2361   lives_box_pack_start(LIVES_BOX(hbuttonbox), save_keymap_button, TRUE, TRUE, widget_opts.packing_width);
2362 
2363   load_keymap_button = lives_dialog_add_button_from_stock(NULL, LIVES_STOCK_OPEN, _("_Load default keymap"),
2364                        LIVES_RESPONSE_BROWSE);
2365 
2366   lives_box_pack_start(LIVES_BOX(hbuttonbox), load_keymap_button, TRUE, TRUE, widget_opts.packing_width);
2367 
2368   ok_button = lives_dialog_add_button_from_stock(NULL, LIVES_STOCK_CLOSE, _("Close _window"),
2369               LIVES_RESPONSE_OK);
2370 
2371   lives_box_pack_start(LIVES_BOX(hbuttonbox), ok_button, TRUE, TRUE, widget_opts.packing_width);
2372 
2373   add_fill_to_box(LIVES_BOX(hbuttonbox));
2374 
2375   lives_widget_set_size_request(clear_all_button, DLG_BUTTON_WIDTH, DLG_BUTTON_HEIGHT);
2376   lives_widget_set_margin(clear_all_button, widget_opts.border_width);
2377 
2378   lives_widget_set_size_request(save_keymap_button, DLG_BUTTON_WIDTH, DLG_BUTTON_HEIGHT);
2379   lives_widget_set_margin(save_keymap_button, widget_opts.border_width);
2380 
2381   lives_widget_set_size_request(load_keymap_button, DLG_BUTTON_WIDTH, DLG_BUTTON_HEIGHT);
2382   lives_widget_set_margin(load_keymap_button, widget_opts.border_width);
2383 
2384   lives_widget_set_size_request(ok_button, DLG_BUTTON_WIDTH, DLG_BUTTON_HEIGHT);
2385   lives_widget_set_margin(ok_button, widget_opts.border_width);
2386 
2387   rtew_accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
2388   lives_window_add_accel_group(LIVES_WINDOW(irte_window), rtew_accel_group);
2389 
2390   lives_widget_add_accelerator(ok_button, LIVES_WIDGET_CLICKED_SIGNAL, rtew_accel_group,
2391                                LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
2392 
2393   lives_signal_connect(LIVES_GUI_OBJECT(irte_window), LIVES_WIDGET_DELETE_EVENT,
2394                        LIVES_GUI_CALLBACK(on_rtew_ok_clicked), NULL);
2395 
2396   lives_signal_sync_connect(LIVES_GUI_OBJECT(ok_button), LIVES_WIDGET_CLICKED_SIGNAL,
2397                             LIVES_GUI_CALLBACK(on_rtew_ok_clicked), NULL);
2398 
2399   lives_signal_connect(LIVES_GUI_OBJECT(save_keymap_button), LIVES_WIDGET_CLICKED_SIGNAL,
2400                        LIVES_GUI_CALLBACK(on_save_keymap_clicked), NULL);
2401 
2402   lives_signal_connect(LIVES_GUI_OBJECT(load_keymap_button), LIVES_WIDGET_CLICKED_SIGNAL,
2403                        LIVES_GUI_CALLBACK(on_load_keymap_clicked),
2404                        LIVES_INT_TO_POINTER(1));
2405 
2406   lives_signal_connect(LIVES_GUI_OBJECT(clear_all_button), LIVES_WIDGET_CLICKED_SIGNAL,
2407                        LIVES_GUI_CALLBACK(on_clear_all_clicked),
2408                        LIVES_INT_TO_POINTER(1));
2409 
2410 rte_window_ready:
2411   // TODO: ignore button clicks until window is fully shown
2412 
2413   rte_window_is_hidden = FALSE;
2414 
2415   //lives_window_set_modal(LIVES_WINDOW(irte_window), TRUE);
2416   lives_widget_show_all(irte_window);
2417 
2418   if (prefs->open_maximised) {
2419     lives_window_maximize(LIVES_WINDOW(irte_window));
2420   }
2421 
2422   lives_widget_show_now(irte_window);
2423 
2424   lives_widget_set_sensitive(mainw->mt_menu, FALSE);
2425   lives_widget_set_sensitive(mainw->rte_defs_menu, FALSE);
2426 
2427   lives_set_cursor_style(LIVES_CURSOR_NORMAL, NULL);
2428   lives_set_cursor_style(LIVES_CURSOR_NORMAL, irte_window);
2429   mainw->no_context_update = FALSE;
2430   return irte_window;
2431 }
2432 
2433 
refresh_rte_window(void)2434 LiVESWidget *refresh_rte_window(void) {
2435   if (rte_window) {
2436     lives_set_cursor_style(LIVES_CURSOR_BUSY, NULL);
2437     lives_set_cursor_style(LIVES_CURSOR_BUSY, rte_window);
2438     lives_widget_context_update();
2439     on_rtew_delete_event(NULL, NULL, NULL);
2440     lives_widget_destroy(rte_window);
2441     rte_window = create_rte_window();
2442     rte_window_set_interactive(prefs->interactive);
2443   }
2444   return rte_window;
2445 }
2446 
2447 
on_assign_rte_keys_activate(LiVESMenuItem * menuitem,livespointer user_data)2448 void on_assign_rte_keys_activate(LiVESMenuItem * menuitem, livespointer user_data) {
2449   if (rte_window && !rte_window_is_hidden) {
2450     on_rtew_delete_event(NULL, NULL, NULL);
2451   } else {
2452     rte_window = create_rte_window();
2453     rte_window_set_interactive(prefs->interactive);
2454     lives_widget_show(rte_window);
2455     if (mainw->play_window && !mainw->fs && (prefs->play_monitor == widget_opts.monitor + 1 || capable->nmonitors == 1)) {
2456       lives_widget_hide(mainw->play_window);
2457       lives_window_set_transient_for(LIVES_WINDOW(mainw->play_window), LIVES_WINDOW(rte_window));
2458       lives_widget_show(mainw->play_window);
2459     }
2460   }
2461 }
2462 
2463 
rtew_set_keych(int key,boolean on)2464 void rtew_set_keych(int key, boolean on) {
2465   lives_signal_handler_block(key_checks[key], ch_fns[key]);
2466   lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_checks[key]), on);
2467   lives_signal_handler_unblock(key_checks[key], ch_fns[key]);
2468   lives_widget_object_set_data(LIVES_WIDGET_OBJECT(key_checks[key]), "active", LIVES_INT_TO_POINTER(on));
2469 }
2470 
2471 
rtew_set_keygr(int key)2472 void rtew_set_keygr(int key) {
2473   if (key >= 0) {
2474     lives_signal_handler_block(key_grabs[key], gr_fns[key]);
2475     lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(key_grabs[key]), TRUE);
2476     lives_signal_handler_unblock(key_grabs[key], gr_fns[key]);
2477   } else {
2478     lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(dummy_radio), TRUE);
2479   }
2480 }
2481 
2482 
rtew_set_mode_radio(int key,int mode)2483 void rtew_set_mode_radio(int key, int mode) {
2484   int modes = rte_getmodespk();
2485   lives_signal_handler_block(mode_radios[key * modes + mode], mode_ra_fns[key * modes + mode]);
2486   lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(mode_radios[key * modes + mode]), TRUE);
2487   lives_signal_handler_unblock(mode_radios[key * modes + mode], mode_ra_fns[key * modes + mode]);
2488 }
2489 
2490 
update_pwindow(int key,int i,LiVESList * list)2491 void update_pwindow(int key, int i, LiVESList * list) {
2492   // called only from weed_set_blend_factor() and from setting param in ce_thumbs
2493 
2494   weed_plant_t *inst;
2495   lives_rfx_t *rfx;
2496   int keyw, modew;
2497 
2498   if (fx_dialog[1]) {
2499     keyw = fx_dialog[1]->key;
2500     modew = fx_dialog[1]->mode;
2501     if (key == keyw) {
2502       if (!(inst = rte_keymode_get_instance(key + 1, modew))) return;
2503       weed_instance_unref(inst);
2504       rfx = fx_dialog[1]->rfx;
2505       mainw->block_param_updates = TRUE;
2506       set_param_from_list(list, &rfx->params[i], 0, TRUE, TRUE);
2507       mainw->block_param_updates = FALSE;
2508     }
2509   }
2510 }
2511 
2512 
rte_set_defs_activate(LiVESMenuItem * menuitem,livespointer user_data)2513 void rte_set_defs_activate(LiVESMenuItem * menuitem, livespointer user_data) {
2514   int idx = LIVES_POINTER_TO_INT(user_data);
2515   weed_plant_t *filter = get_weed_filter(idx);
2516   lives_rfx_t *rfx;
2517 
2518   if (fx_dialog[1]) {
2519     rfx = fx_dialog[1]->rfx;
2520     on_paramwindow_button_clicked(NULL, rfx);
2521     lives_widget_destroy(fx_dialog[1]->dialog);
2522     lives_freep((void **)&fx_dialog[1]);
2523   }
2524 
2525   rfx = weed_to_rfx(filter, TRUE);
2526   rfx->min_frames = -1;
2527   on_fx_pre_activate(rfx, TRUE, NULL);
2528 }
2529 
2530 
rte_set_key_defs(LiVESButton * button,lives_rfx_t * rfx)2531 void rte_set_key_defs(LiVESButton * button, lives_rfx_t *rfx) {
2532   int key, mode;
2533   if (mainw->textwidget_focus) {
2534     LiVESWidget *textwidget = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mainw->textwidget_focus),
2535                               TEXTWIDGET_KEY);
2536     after_param_text_changed(textwidget, rfx);
2537   }
2538 
2539   if (rfx->num_params > 0) {
2540     key = fx_dialog[1]->key;
2541     mode = fx_dialog[1]->mode;
2542     set_key_defaults((weed_plant_t *)rfx->source, key, mode);
2543   }
2544 }
2545 
2546 
rte_set_defs_ok(LiVESButton * button,lives_rfx_t * rfx)2547 void rte_set_defs_ok(LiVESButton * button, lives_rfx_t *rfx) {
2548   weed_plant_t *ptmpl, *filter;
2549 
2550   lives_colRGB48_t *rgbp;
2551 
2552   register int i;
2553 
2554   if (mainw->textwidget_focus) {
2555     LiVESWidget *textwidget = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mainw->textwidget_focus),
2556                               TEXTWIDGET_KEY);
2557     after_param_text_changed(textwidget, rfx);
2558   }
2559 
2560   if (rfx->num_params > 0) {
2561     filter = weed_instance_get_filter((weed_plant_t *)rfx->source, TRUE);
2562     for (i = 0; i < rfx->num_params; i++) {
2563       ptmpl = weed_filter_in_paramtmpl(filter, i, FALSE);
2564       if (weed_paramtmpl_value_irrelevant(ptmpl)) continue;
2565       switch (rfx->params[i].type) {
2566       case LIVES_PARAM_COLRGB24:
2567         rgbp = (lives_colRGB48_t *)rfx->params[i].value;
2568         update_weed_color_value(filter, i, rgbp->red, rgbp->green, rgbp->blue, 0, rfx);
2569         break;
2570       case LIVES_PARAM_STRING:
2571         weed_set_string_value(ptmpl, WEED_LEAF_HOST_DEFAULT, (char *)rfx->params[i].value);
2572         break;
2573       case LIVES_PARAM_STRING_LIST:
2574         weed_set_int_array(ptmpl, WEED_LEAF_HOST_DEFAULT, 1, (int *)rfx->params[i].value);
2575         break;
2576       case LIVES_PARAM_NUM:
2577         if (weed_leaf_seed_type(ptmpl, WEED_LEAF_DEFAULT) == WEED_SEED_DOUBLE)
2578           weed_set_double_array(ptmpl, WEED_LEAF_HOST_DEFAULT, 1,
2579                                 (double *)rfx->params[i].value);
2580         else weed_set_int_array(ptmpl, WEED_LEAF_HOST_DEFAULT, 1, (int *)rfx->params[i].value);
2581         break;
2582       case LIVES_PARAM_BOOL:
2583         weed_set_boolean_array(ptmpl, WEED_LEAF_HOST_DEFAULT, 1, (int *)rfx->params[i].value);
2584         break;
2585       default:
2586         break;
2587 	// *INDENT-OFF*
2588       }}}
2589   // *INDENT-ON*
2590 }
2591 
2592 
rte_set_defs_cancel(LiVESButton * button,lives_rfx_t * rfx)2593 void rte_set_defs_cancel(LiVESButton * button, lives_rfx_t *rfx) {
2594   on_paramwindow_button_clicked(button, rfx);
2595   lives_freep((void **)&fx_dialog[1]);
2596 }
2597 
2598 
rte_reset_defs_clicked(LiVESButton * button,lives_rfx_t * rfx)2599 void rte_reset_defs_clicked(LiVESButton * button, lives_rfx_t *rfx) {
2600   weed_plant_t **ptmpls, **inp, **xinp;
2601   weed_plant_t **ctmpls;
2602 
2603   weed_plant_t *filter, *inst;
2604 
2605   LiVESList *child_list;
2606 
2607   LiVESWidget *pbox, *cancelbutton;
2608 
2609   boolean is_generic_defs = FALSE;
2610   boolean add_pcons = FALSE;
2611 
2612   int nchans;
2613 
2614   int poffset = 0, ninpar, x;
2615 
2616   int i;
2617 
2618   cancelbutton = fx_dialog[1]->cancelbutton;
2619 
2620   if (cancelbutton) is_generic_defs = TRUE;
2621 
2622   inst = (weed_plant_t *)rfx->source;
2623 
2624   filter = weed_instance_get_filter(inst, TRUE);
2625 
2626   if (rfx->num_params > 0) {
2627     if (is_generic_defs) {
2628       // for generic, reset from plugin supplied defs
2629       ptmpls = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
2630       for (i = 0; i < rfx->num_params; i++) {
2631         if (weed_plant_has_leaf(ptmpls[i], WEED_LEAF_HOST_DEFAULT)) weed_leaf_delete(ptmpls[i], WEED_LEAF_HOST_DEFAULT);
2632       }
2633       lives_free(ptmpls);
2634     }
2635 
2636     inp = weed_params_create(filter, TRUE);
2637 
2638 resetdefs1:
2639     filter = weed_instance_get_filter(inst, FALSE);
2640 
2641     // reset params back to default defaults
2642     weed_in_parameters_free(inst);
2643 
2644     ninpar = num_in_params(filter, FALSE, FALSE);
2645     if (ninpar == 0) xinp = NULL;
2646 
2647     xinp = (weed_plant_t **)lives_malloc((ninpar + 1) * sizeof(weed_plant_t *));
2648     x = 0;
2649     for (i = poffset; i < poffset + ninpar; i++) xinp[x++] = inp[i];
2650     xinp[x] = NULL;
2651     poffset += ninpar;
2652 
2653     weed_set_plantptr_array(inst, WEED_LEAF_IN_PARAMETERS, weed_flagset_array_count(xinp, TRUE), xinp);
2654     lives_free(xinp);
2655 
2656     if (weed_plant_has_leaf(inst, WEED_LEAF_HOST_NEXT_INSTANCE)) {
2657       // handle compound fx
2658       inst = weed_get_plantptr_value(inst, WEED_LEAF_HOST_NEXT_INSTANCE, NULL);
2659       add_pcons = TRUE;
2660       goto resetdefs1;
2661     }
2662 
2663     lives_free(inp);
2664 
2665     inst = (weed_plant_t *)rfx->source;
2666     filter = weed_instance_get_filter(inst, TRUE);
2667 
2668     if (add_pcons) {
2669       add_param_connections(inst);
2670     }
2671 
2672     rfx_params_free(rfx);
2673     lives_free(rfx->params);
2674 
2675     rfx->params = weed_params_to_rfx(rfx->num_params, inst, FALSE);
2676   }
2677 
2678   if (is_generic_defs) {
2679     if (weed_plant_has_leaf(filter, WEED_LEAF_HOST_FPS)) weed_leaf_delete(filter, WEED_LEAF_HOST_FPS);
2680 
2681     if (weed_plant_has_leaf(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES)) {
2682       ctmpls = weed_get_plantptr_array(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
2683       nchans = weed_leaf_num_elements(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES);
2684       for (i = 0; i < nchans; i++) {
2685         if (weed_plant_has_leaf(ctmpls[i], WEED_LEAF_HOST_WIDTH)) weed_leaf_delete(ctmpls[i], WEED_LEAF_HOST_WIDTH);
2686         if (weed_plant_has_leaf(ctmpls[i], WEED_LEAF_HOST_HEIGHT)) weed_leaf_delete(ctmpls[i], WEED_LEAF_HOST_HEIGHT);
2687       }
2688     }
2689   } else {
2690     int key = fx_dialog[1]->key;
2691     int mode = fx_dialog[1]->mode;
2692     set_key_defaults(inst, key, mode);
2693   }
2694 
2695   if (!LIVES_IS_WIDGET(fx_dialog[1]->dialog)) return;
2696   pbox = lives_dialog_get_content_area(LIVES_DIALOG(fx_dialog[1]->dialog));
2697 
2698   // redraw the window
2699   child_list = lives_container_get_children(LIVES_CONTAINER(pbox));
2700   // remove focus from any widget we are ripping out
2701   lives_container_set_focus_child(LIVES_CONTAINER(pbox), NULL);
2702   for (i = 0; i < lives_list_length(child_list); i++) {
2703     LiVESWidget *widget = (LiVESWidget *)lives_list_nth_data(child_list, i);
2704     if (lives_widget_is_ancestor(LIVES_WIDGET(button), widget)) continue;
2705     lives_widget_destroy(widget);
2706   }
2707 
2708   if (child_list) lives_list_free(child_list);
2709 
2710   make_param_box(LIVES_VBOX(pbox), rfx);
2711   lives_widget_show_all(pbox);
2712 
2713   lives_widget_queue_draw(fx_dialog[1]->dialog);
2714 }
2715 
2716 
load_default_keymap(void)2717 void load_default_keymap(void) {
2718   // called on startup
2719   if (!hash_list) hash_list = weed_get_all_names(FX_LIST_HASHNAME);
2720   on_load_keymap_clicked(NULL, NULL);
2721   threaded_dialog_spin(0.);
2722 }
2723