LiVES  3.2.0
effects-data.c
Go to the documentation of this file.
1 // effects-data.c
2 // LiVES (lives-exe)
3 // (c) G. Finch 2005 - 2019 (salsaman+lives@gmail.com)
4 // Released under the GPL 3 or later
5 // see file ../COPYING for licensing details
6 
7 // functions for chaining and data passing between fx plugins
8 
9 //#define DEBUG_PCONX
10 
11 #include "main.h"
12 #include "effects.h"
13 #include "ce_thumbs.h"
14 #include "omc-learn.h"
15 
16 static lives_pconnect_t *spconx;
17 static lives_cconnect_t *scconx;
18 
19 static boolean do_chan_connected_query(lives_conx_w *, int okey, int omode, int ocnum, boolean is_same_key);
20 static boolean do_param_connected_query(lives_conx_w *, int okey, int omode, int opnum, boolean is_same_key);
21 static void do_param_incompatible_error(lives_conx_w *);
22 
23 static void ptable_row_add_standard_widgets(lives_conx_w *, int idx);
24 static void ptable_row_add_variable_widgets(lives_conx_w *, int idx, int row, int pidx);
25 
26 static void ctable_row_add_standard_widgets(lives_conx_w *, int idx);
27 static void ctable_row_add_variable_widgets(lives_conx_w *, int idx, int row, int cidx);
28 
29 static void padd_clicked(LiVESWidget *button, livespointer user_data);
30 static void cadd_clicked(LiVESWidget *button, livespointer user_data);
31 
32 static void dfxp_changed(LiVESWidget *, livespointer conxwp);
33 
34 static weed_plant_t *active_dummy = NULL;
35 
36 static LiVESTreeModel *pmodel;
37 static LiVESTreeModel *cmodel;
38 
39 static char *lctext;
40 
41 #define BW (40. * widget_opts.scale)
42 #define BH (40. * widget_opts.scale)
43 
44 #ifdef DEBUG_PCONX
45 static void dump_connections(void) {
46  lives_pconnect_t *pconx = mainw->pconx;
47  while (pconx) {
48  int p = 0;
49  for (int i = 0; i < pconx->nparams; i++) {
50  int pnum = pconx->params[i];
51  for (int j = 0; j < pconx->nconns[i + 1]; j++) {
52  p++;
53  // *INDENT-OFF*
54  }}
55  // *INDENT-ON*
56  pconx = pconx->next;
57  }
58 }
59 #endif
60 
61 static char *get_param_name(weed_plant_t *param, int pnum, boolean is_in) {
62  char *name = weed_get_string_value(param, WEED_LEAF_NAME, NULL);
63  if (!*name) {
64  lives_free(name);
65  name = NULL;
66  }
67  if (!name) {
68  if (is_in) name = lives_strdup_printf(_("In param %d"), pnum);
69  else name = lives_strdup_printf(_("Out param %d"), pnum);
70  }
71  return name;
72 }
73 
74 
75 static char *get_chan_name(weed_plant_t *chan, int cnum, boolean is_in) {
76  char *name = weed_get_string_value(chan, WEED_LEAF_NAME, NULL);
77  if (!*name) {
78  lives_free(name);
79  name = NULL;
80  }
81  if (!name) {
82  if (is_in) name = lives_strdup_printf(_("In channel %d"), cnum);
83  else name = lives_strdup_printf(_("Out channel %d"), cnum);
84  }
85  return name;
86 }
87 
88 
89 static void switch_fx_state(int hotkey) {
90  // switch effect state when a connection to ACTIVATE is present
91  uint32_t last_grabbable_effect = mainw->last_grabbable_effect;
92  // use -hotkey to indicate auto
93  rte_key_toggle(-hotkey);
94  mainw->last_grabbable_effect = last_grabbable_effect;
95 }
96 
97 
98 void override_if_active_input(int hotkey) {
99  // if we have a connection to ACTIVATE, allow override if the user changes the state from the kbd
100  lives_pconnect_t *pconx = mainw->pconx;
101 
102  int totcons;
103  int imode = rte_key_getmode(hotkey);
104 
105  int i, j;
106 
107  while (pconx) {
108  totcons = 0;
109  j = 0;
110  for (i = 0; i < pconx->nparams; i++) {
111  totcons += pconx->nconns[i];
112  for (; j < totcons; j++) {
113  if (pconx->ikey[j] == hotkey && pconx->imode[j] == imode && pconx->ipnum[j] == FX_DATA_PARAM_ACTIVE) {
114  // out param is "ACTIVATED"
115  // abuse "autoscale" for this
116  pconx->autoscale[j] = TRUE;
117  return;
118  // *INDENT-OFF*
119  }}}
120  pconx = pconx->next;
121  // *INDENT-ON*
122  }
123 }
124 
125 
127  // if we activate an effect and it is connected to ACTIVATE another effect, end any user override
128  lives_pconnect_t *pconx = mainw->pconx;
129 
130  int totcons;
131  int omode = rte_key_getmode(hotkey);
132 
133  int j;
134 
135  while (pconx) {
136  if (pconx->okey == hotkey && pconx->omode == omode) {
137  totcons = 0;
138  j = 0;
139  for (int i = 0; i < pconx->nparams; i++) {
140  totcons += pconx->nconns[i];
141  for (; j < totcons; j++) {
142  if (pconx->ipnum[j] == FX_DATA_PARAM_ACTIVE) {
143  // abuse "autoscale" for this
144  pconx->autoscale[j] = FALSE;
145  // *INDENT-OFF*
146  }}}}
147  // *INDENT-ON*
148  pconx = pconx->next;
149  }
150 }
151 
152 
153 void pconx_delete_all(void) {
154  lives_pconnect_t *pconx = mainw->pconx, *pconx_next;
155  int i;
156 
157  for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_lock(&mainw->fx_mutex[i]);
158 
159  while (pconx) {
160  pconx_next = pconx->next;
161  lives_free(pconx->params); lives_free(pconx->nconns); lives_free(pconx->last_boolval);
162  lives_free(pconx->ikey); lives_free(pconx->imode); lives_free(pconx->ipnum);
163  lives_free(pconx->autoscale); lives_free(pconx);
164  pconx = pconx_next;
165  }
166  mainw->pconx = NULL;
167 
168  for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_unlock(&mainw->fx_mutex[i]);
169 }
170 
171 
172 static lives_pconnect_t *pconx_new(int okey, int omode) {
173  lives_pconnect_t *pconx = (lives_pconnect_t *)lives_calloc(sizeof(struct _lives_pconnect_t), 1);
174  pconx->okey = okey;
175  pconx->omode = omode;
176  return pconx;
177 }
178 
179 
180 static lives_pconnect_t *pconx_copy(lives_pconnect_t *spconx) {
181  lives_pconnect_t *pconx = NULL, *dpconx, *last_dpconx;
182 
183  int totcons = 0;
184 
185  int j = 0;
186 
187  while (spconx) {
188  dpconx = pconx_new(spconx->okey, spconx->omode);
189  if (!pconx) pconx = dpconx;
190  else last_dpconx->next = dpconx;
191 
192  dpconx->nparams = spconx->nparams;
193 
194  dpconx->nconns = (int *)lives_malloc(dpconx->nparams * sizint);
195  dpconx->params = (int *)lives_malloc(dpconx->nparams * sizint);
196  dpconx->last_boolval = (int *)lives_malloc(dpconx->nparams * sizint);
197 
198  dpconx->ikey = dpconx->imode = dpconx->ipnum = NULL;
199  dpconx->autoscale = NULL;
200 
201  j = 0;
202 
203  for (int i = 0; i < dpconx->nparams; i++) {
204  dpconx->params[i] = spconx->params[i];
205  dpconx->nconns[i] = spconx->nconns[i];
206  dpconx->last_boolval[i] = spconx->last_boolval[i];
207  totcons += dpconx->nconns[i];
208 
209  dpconx->ikey = (int *)lives_realloc(dpconx->ikey, totcons * sizint);
210  dpconx->imode = (int *)lives_realloc(dpconx->imode, totcons * sizint);
211  dpconx->ipnum = (int *)lives_realloc(dpconx->ipnum, totcons * sizint);
212  dpconx->autoscale = (boolean *)lives_realloc(dpconx->autoscale, totcons * sizint);
213 
214  while (j < totcons) {
215  dpconx->ikey[j] = spconx->ikey[j];
216  dpconx->imode[j] = spconx->imode[j];
217  dpconx->ipnum[j] = spconx->ipnum[j];
218  dpconx->autoscale[j] = spconx->autoscale[j];
219  j++;
220  }
221  }
222 
223  spconx = spconx->next;
224  last_dpconx = dpconx;
225  }
226 
227  return pconx;
228 }
229 
230 
231 char *pconx_list(int okey, int omode, int opnum) {
232  char *st1 = lives_strdup(""), *st2;
233  lives_pconnect_t *pconx = mainw->pconx;
234  int totcons = 0;
235 
236  while (pconx) {
237  if (pconx->okey == okey && pconx->omode == omode) {
238  for (int i = 0; i < pconx->nparams; i++) {
239  if (pconx->params[i] == opnum) {
240  for (int j = totcons; j < totcons + pconx->nconns[i]; j++) {
241  if (!*st1)
242  st2 = lives_strdup_printf("%d %d %d %d", pconx->ikey[j] + 1, pconx->imode[j] + 1, pconx->ipnum[j],
243  pconx->autoscale[j]);
244  else
245  st2 = lives_strdup_printf("%s %d %d %d %d", st1, pconx->ikey[j] + 1, pconx->imode[j] + 1,
246  pconx->ipnum[j], pconx->autoscale[j]);
247  lives_free(st1);
248  st1 = st2;
249  }
250  return st1;
251  }
252  totcons += pconx->nconns[i];
253  }
254  return st1;
255  }
256  pconx = pconx->next;
257  }
258  return st1;
259 }
260 
261 
262 void pconx_delete(int okey, int omode, int opnum, int ikey, int imode, int ipnum) {
263  lives_pconnect_t *pconx = mainw->pconx, *pconx_next, *pconx_prev = NULL;
264 
265  int i, j = 0, k;
266  int totcons = 0, maxcons = 0;
267 
268  if (okey >= 0 && okey != FX_DATA_WILDCARD)
269  for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++)
270  pthread_mutex_lock(&mainw->fx_mutex[i]);
271 
272  while (pconx) {
273  pconx_next = pconx->next;
274 
275 #ifdef DEBUG_PCONX
276  g_print("Deletion check, want %d / %d, found %d / %d\n", okey, omode, pconx->okey, pconx->omode);
277 #endif
278  if ((okey == FX_DATA_WILDCARD || pconx->okey == okey) && (omode == FX_DATA_WILDCARD || pconx->omode == omode)) {
279 
280 #ifdef DEBUG_PCONX
281  g_print("GOT MATCH\n");
282 #endif
283  if (opnum == FX_DATA_WILDCARD && ikey == FX_DATA_WILDCARD && imode == FX_DATA_WILDCARD
284  && ipnum == FX_DATA_WILDCARD) {
285  //g_print("rem all cons from %d %d to any param\n",okey,omode);
286 
287  // delete entire node
288  lives_free(pconx->params); lives_free(pconx->last_boolval); lives_free(pconx->nconns);
289  lives_free(pconx->ikey); lives_free(pconx->imode); lives_free(pconx->ipnum);
290  lives_free(pconx->autoscale); lives_free(pconx);
291  if (mainw->pconx == pconx) mainw->pconx = pconx_next;
292  else pconx_prev->next = pconx_next;
293  if (okey >= 0 && okey != FX_DATA_WILDCARD) for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++)
294  pthread_mutex_unlock(&mainw->fx_mutex[i]);
295  return;
296  }
297 
298  maxcons = 0;
299  totcons = 0;
300  j = 0;
301 
302  for (i = 0; i < pconx->nparams; i++) {
303  maxcons += pconx->nconns[i];
304  }
305 
306  for (i = 0; pconx && i < pconx->nparams; i++) {
307 #ifdef DEBUG_PCONX
308  g_print("Checking oparams, want %d, got %d with %d connections\n", opnum, pconx->params[i], pconx->nconns[i]);
309 #endif
310  totcons += pconx->nconns[i];
311 
312  if (opnum != FX_DATA_WILDCARD && pconx->params[i] != opnum) {
313  j = totcons;
314  continue;
315  }
316 
317  for (; j < totcons; j++) {
318 #ifdef DEBUG_PCONX
319  g_print("For inputs, want %d / %d (%d), found %d / %d (%d)\n", ikey, imode, ipnum, pconx->ikey[j], pconx->imode[j],
320  pconx->ipnum[j]);
321 #endif
322  if ((ikey == FX_DATA_WILDCARD || pconx->ikey[j] == ikey)
323  && (imode == FX_DATA_WILDCARD || pconx->imode[j] == imode)
324  && (ipnum == FX_DATA_WILDCARD
325  || (ipnum == FX_DATA_WILDCARD_KEEP_ACTIVATED && pconx->ipnum[j] != FX_DATA_PARAM_ACTIVE)
326  || pconx->ipnum[j] == ipnum)) {
327 #ifdef DEBUG_PCONX
328  g_print("removing connection to %d / %d param (%d)\n", ikey, imode, ipnum);
329 #endif
330  maxcons--;
331  for (k = j; k < maxcons; k++) {
332  pconx->ikey[k] = pconx->ikey[k + 1];
333  pconx->imode[k] = pconx->imode[k + 1];
334  pconx->ipnum[k] = pconx->ipnum[k + 1];
335  pconx->autoscale[k] = pconx->autoscale[k + 1];
336  }
337 
338  pconx->ikey = (int *)lives_realloc(pconx->ikey, maxcons * sizint);
339  pconx->imode = (int *)lives_realloc(pconx->imode, maxcons * sizint);
340  pconx->ipnum = (int *)lives_realloc(pconx->ipnum, maxcons * sizint);
341  pconx->autoscale = (boolean *)lives_realloc(pconx->autoscale, maxcons * sizint);
342 
343  pconx->nconns[i]--;
344 
345  if (pconx->nconns[i] == 0) {
346  pconx->nparams--;
347  for (k = i; k < pconx->nparams; k++) {
348  pconx->params[k] = pconx->params[k + 1];
349  pconx->last_boolval[k] = pconx->last_boolval[k + 1];
350  pconx->nconns[k] = pconx->nconns[k + 1];
351  }
352 
353  if (pconx->nparams == 0) {
354  // delete entire node
355  lives_free(pconx->params); lives_free(pconx->nconns); lives_free(pconx->ikey);
356  lives_free(pconx->imode); lives_free(pconx->ipnum); lives_free(pconx->last_boolval);
357  lives_free(pconx->autoscale);
358  lives_free(pconx);
359  if (mainw->pconx == pconx) {
360  mainw->pconx = pconx_next;
361  pconx = NULL;
362  } else {
363  pconx = pconx_prev;
364  pconx->next = pconx_next;
365  }
366  } else {
367  pconx->nconns = (int *)lives_realloc(pconx->nconns, pconx->nparams * sizint);
368  // *INDENT-OFF*
369  }}}}}}
370  // *INDENT-ON*
371 
372  pconx_prev = pconx;
373  pconx = pconx_next;
374  }
375  if (okey >= 0 && okey != FX_DATA_WILDCARD)
376  for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_unlock(&mainw->fx_mutex[i]);
377 }
378 
379 
380 void pconx_remap_mode(int key, int omode, int nmode) {
381  lives_pconnect_t *pconx = mainw->pconx;
382 
383  register int i, j, totcons;
384 
385  while (pconx) {
386  if (pconx->okey == key && pconx->omode == omode) {
387  pconx->omode = nmode;
388  }
389  j = 0;
390  totcons = 0;
391  for (i = 0; i < pconx->nparams; i++) {
392  totcons += pconx->nconns[i];
393  for (; j < totcons; j++) {
394  if (pconx->ikey[j] == key && pconx->imode[j] == omode) {
395  pconx->imode[j] = nmode;
396  // *INDENT-OFF*
397  }}}
398  // *INDENT-ON*
399  pconx = pconx->next;
400  }
401 }
402 
403 
404 static void pconx_append(lives_pconnect_t *pconx) {
405  lives_pconnect_t *opconx = mainw->pconx;
406  lives_pconnect_t *last_pconx = opconx;
407 
408  while (opconx) {
409  last_pconx = opconx;
410  opconx = opconx->next;
411  }
412 
413  if (last_pconx) last_pconx->next = pconx;
414  if (!mainw->pconx) mainw->pconx = pconx;
415 }
416 
417 
418 static lives_pconnect_t *pconx_find(int okey, int omode) {
419  //
420  lives_pconnect_t *pconx = mainw->pconx;
421  while (pconx) {
422  if (pconx->okey == okey && pconx->omode == omode) {
423  return pconx;
424  }
425  pconx = pconx->next;
426  }
427  return NULL;
428 }
429 
430 
431 static int pconx_get_numcons(lives_conx_w * conxwp, int pnum) {
432  // get displayed number
433  int totcons = 0;
434 
435  if (pnum != FX_DATA_WILDCARD) return conxwp->dispp[pnum + EXTRA_PARAMS_OUT];
436 
437  for (int j = 0; j < conxwp->num_params; j++) {
438  totcons += conxwp->dispp[j];
439  }
440 
441  return totcons;
442 }
443 
444 
445 static int pconx_get_nconns(lives_pconnect_t *pconx, int pnum) {
446  // get actual number of connections
447  int totcons = 0;
448 
449  if (!pconx) return 0;
450 
451  for (int j = 0; j < pconx->nparams; j++) {
452  if (pnum != FX_DATA_WILDCARD) {
453  if (pconx->params[j] == pnum) return pconx->nconns[j];
454  } else totcons += pconx->nconns[j];
455  }
456  return totcons;
457 }
458 
459 
460 static lives_pconnect_t *pconx_add_connection_private(int okey, int omode, int opnum, int ikey, int imode, int ipnum,
461  boolean autoscale) {
462  lives_pconnect_t *pconx;
463  int posn = 0, totcons = 0;
464  int i, j;
465 
466  // delete any existing connection to the input param
468  pconx = pconx_find(okey, omode);
469 
470  if (ikey >= 0) for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_lock(&mainw->fx_mutex[i]);
471 
472  if (!pconx) {
473  // add whole new node
474  pconx = pconx_new(okey, omode);
475  pconx_append(pconx);
476  } else {
477  // see if already in params
478  for (i = 0; i < pconx->nparams; i++) {
479  if (pconx->params[i] == opnum) {
480  // located !
481  // add connection to existing
482 
483  for (j = 0; j < pconx->nparams; j++) {
484  if (j < i) {
485  // calc posn
486  posn += pconx->nconns[j];
487  }
488  totcons += pconx->nconns[j];
489  }
490 
491  // if already there, do not add again, just update autoscale
492  for (j = posn; j < posn + pconx->nconns[i]; j++) {
493  if (pconx->ikey[j] == ikey && pconx->imode[j] == imode && pconx->ipnum[j] == ipnum) {
494  pconx->autoscale[j] = autoscale;
495  if (ikey >= 0) for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_unlock(&mainw->fx_mutex[i]);
496  return pconx;
497  }
498 
499  // add in order key/mode/chan
500  if (pconx->ikey[j] > ikey || (pconx->ikey[j] == ikey && pconx->imode[j] > imode) ||
501  (pconx->ikey[j] == ikey && pconx->imode[j] == imode && pconx->ipnum[j] > ipnum)) break;
502  }
503 
504  // increment nconns for this param
505  pconx->nconns[i]++;
506 
507  totcons++;
508 
509  posn = j;
510 
511  // make space for new
512  pconx->ikey = (int *)lives_realloc(pconx->ikey, totcons * sizint);
513  pconx->imode = (int *)lives_realloc(pconx->imode, totcons * sizint);
514  pconx->ipnum = (int *)lives_realloc(pconx->ipnum, totcons * sizint);
515  pconx->autoscale = (boolean *)lives_realloc(pconx->autoscale, totcons * sizint);
516 
517  // move up 1
518  for (j = totcons - 1; j > posn; j--) {
519  pconx->ikey[j] = pconx->ikey[j - 1];
520  pconx->imode[j] = pconx->imode[j - 1];
521  pconx->ipnum[j] = pconx->ipnum[j - 1];
522  pconx->autoscale[j] = pconx->autoscale[j - 1];
523  }
524 
525  // insert at posn
526  pconx->ikey[posn] = ikey;
527  pconx->imode[posn] = imode;
528  pconx->ipnum[posn] = ipnum;
529  pconx->autoscale[posn] = autoscale;
530 
531  if (ikey >= 0) for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_unlock(&mainw->fx_mutex[i]);
532 
533  return pconx;
534  }
535  }
536 
537  // so, we have data for key/mode but this is a new param to be mapped
538 
539  for (i = 0; i < pconx->nparams; i++) {
540  totcons += pconx->nconns[i];
541  }
542 
543  totcons++;
544 
545  pconx->nparams++;
546  posn = pconx->nparams;
547 
548  // make space for new
549  pconx->nconns = (int *)lives_realloc(pconx->nconns, posn * sizint);
550  pconx->params = (int *)lives_realloc(pconx->params, posn * sizint);
551  pconx->last_boolval = (int *)lives_realloc(pconx->last_boolval, posn * sizint);
552 
553  pconx->ikey = (int *)lives_realloc(pconx->ikey, totcons * sizint);
554  pconx->imode = (int *)lives_realloc(pconx->imode, totcons * sizint);
555  pconx->ipnum = (int *)lives_realloc(pconx->ipnum, totcons * sizint);
556  pconx->autoscale = (boolean *)lives_realloc(pconx->autoscale, totcons * sizint);
557 
558  pconx->params[posn - 1] = opnum;
559 
560  pconx->last_boolval[posn - 1] = WEED_FALSE; // TODO ***: get value from default
561 
562  pconx->nconns[posn - 1] = 1;
563 
564  posn = totcons - 1;
565 
566  // insert at posn
567  pconx->ikey[posn] = ikey;
568  pconx->imode[posn] = imode;
569  pconx->ipnum[posn] = ipnum;
570  pconx->autoscale[posn] = autoscale;
571 
572 #ifdef DEBUG_PCONX
573  g_print("added another pconx from %d %d %d to %d %d %d\n", okey, omode, opnum, ikey, imode, ipnum);
574  dump_connections();
575 #endif
576 
577  if (ikey >= 0) for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_unlock(&mainw->fx_mutex[i]);
578 
579  return pconx;
580  }
581 
582  // add new
583 
584  totcons = pconx_get_nconns(pconx, FX_DATA_WILDCARD) + 1;
585  pconx->nparams++;
586 
587  pconx->nconns = (int *)lives_realloc(pconx->params, pconx->nparams * sizint);
588  pconx->nconns[pconx->nparams - 1] = 1;
589 
590  pconx->params = (int *)lives_realloc(pconx->params, pconx->nparams * sizint);
591  pconx->params[pconx->nparams - 1] = opnum;
592 
593  pconx->last_boolval = (int *)lives_realloc(pconx->last_boolval, pconx->nparams * sizint);
594  pconx->last_boolval[pconx->nparams - 1] = WEED_FALSE; // TODO: ****
595 
596  pconx->ikey = (int *)lives_realloc(pconx->ikey, totcons * sizint);
597  pconx->ikey[totcons - 1] = ikey;
598 
599  pconx->imode = (int *)lives_realloc(pconx->imode, totcons * sizint);
600  pconx->imode[totcons - 1] = imode;
601 
602  pconx->ipnum = (int *)lives_realloc(pconx->ipnum, totcons * sizint);
603  pconx->ipnum[totcons - 1] = ipnum;
604 
605  pconx->autoscale = (boolean *)lives_realloc(pconx->autoscale, totcons * sizint);
606  pconx->autoscale[totcons - 1] = autoscale;
607 
608 #ifdef DEBUG_PCONX
609  g_print("added new pconx from %d %d %d to %d %d %d (%d)\n", okey, omode, opnum, ikey, imode, ipnum, autoscale);
610 #endif
611 
612  if (ikey >= 0) for (i = 0; i < FX_KEYS_MAX_VIRTUAL; i++) pthread_mutex_unlock(&mainw->fx_mutex[i]);
613 
614  return pconx;
615 }
616 
617 
618 void pconx_add_connection(int okey, int omode, int opnum, int ikey, int imode, int ipnum, boolean autoscale) {
619  pconx_add_connection_private(okey, omode, opnum, ikey, imode, ipnum, autoscale);
620 }
621 
622 
623 static weed_plant_t *pconx_get_out_param(boolean use_filt, int ikey, int imode, int ipnum, int *okey, int *omode, int *opnum,
624  int *autoscale) {
625  // walk all pconx and find one which has ikey/imode/ipnum as destination
626  // then all we need do is copy the "value" leaf
627 
628  // use_filt is TRUE if we should use the filter template (otherwise we use the instance)
629 
630  // TODO: OMC
631 
632  lives_pconnect_t *pconx = mainw->pconx;
633  weed_plant_t *inst = NULL, *filter = NULL;
634  int totcons, i, j;
635 
636  while (pconx) {
637  if (!use_filt) {
638  if (mainw->is_rendering) return NULL;
639  else {
640  inst = rte_keymode_get_instance(pconx->okey + 1, pconx->omode);
641  }
642  if (inst) filter = weed_instance_get_filter(inst, TRUE); // inst could be NULL if we connected to "Activated"
643  else filter = NULL;
644  } else {
645  inst = NULL;
646  filter = rte_keymode_get_filter(pconx->okey + 1, pconx->omode);
647  if (!filter) {
648  pconx = pconx->next;
649  continue;
650  }
651  }
652  totcons = 0;
653  j = 0;
654  for (i = 0; i < pconx->nparams; i++) {
655  totcons += pconx->nconns[i];
656  for (; j < totcons; j++) {
657  if (pconx->ikey[j] == ikey && pconx->imode[j] == imode && pconx->ipnum[j] == ipnum) {
658  weed_plant_t *param = NULL;
659 
660  // out param is "ACTIVATED"
661  if (pconx->params[i] == FX_DATA_PARAM_ACTIVE) {
662  weed_plant_t *gui = weed_instance_get_gui(inst, FALSE);
663  pthread_mutex_lock(&mainw->fxd_active_mutex);
664  if (!active_dummy) {
665  active_dummy = weed_plant_new(WEED_PLANT_PARAMETER);
666  weed_set_plantptr_value(active_dummy, WEED_LEAF_TEMPLATE, NULL);
667  }
668 
669  weed_set_boolean_value(active_dummy, WEED_LEAF_VALUE, inst != NULL
670  && (!gui || !weed_plant_has_leaf(gui, WEED_LEAF_EASE_OUT)));
671  param = active_dummy;
672  pthread_mutex_unlock(&mainw->fxd_active_mutex);
673  } else {
674  if (use_filt) {
675  weed_plant_t **outparams = weed_get_plantptr_array(filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES, NULL);
676  if (pconx->params[i] < weed_leaf_num_elements(filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES)) {
677  param = outparams[pconx->params[i]];
678  }
679  lives_free(outparams);
680  } else {
681  if (!inst) return NULL;
682  param = weed_inst_out_param(inst, pconx->params[i]);
683  }
684  }
685  if (okey) *okey = pconx->okey;
686  if (omode) *omode = pconx->omode;
687  if (opnum) *opnum = pconx->params[i];
688  if (autoscale) *autoscale = pconx->autoscale[j];
689  if (inst) weed_instance_unref(inst);
690  return param;
691  }
692  }
693  }
694  pconx = pconx->next;
695  if (inst) weed_instance_unref(inst);
696  }
697 
698  return NULL;
699 }
700 
701 
702 static boolean params_compatible(weed_plant_t *sparam, weed_plant_t *dparam) {
703  // allowed conversions
704  // type -> type
705 
706  // bool -> double, bool -> int, bool -> string, (bool -> int64)
707  // int -> double, int -> string, (int -> int64)
708  // double -> string
709  // (int64 -> string)
710 
711  // int[3x]/double[3x] -> colourRGB
712  // int[4x]/double[4x] -> colourRGBA
713  //
714 
715  weed_plant_t *dptmpl = NULL;
716 
717  int dtype = 0, stype = 0;
718  int ndvals = 0, nsvals = 0;
719  int ptype, dflags = 0;
720 
721  if (dparam == active_dummy) {
722  dptmpl = NULL;
723  dtype = WEED_SEED_BOOLEAN;
724  ndvals = 1;
725  } else {
726  if (WEED_PLANT_IS_PARAMETER(dparam)) {
727  dptmpl = weed_get_plantptr_value(dparam, WEED_LEAF_TEMPLATE, NULL);
728  dtype = weed_leaf_seed_type(dparam, WEED_LEAF_VALUE);
729  ndvals = weed_leaf_num_elements(dparam, WEED_LEAF_VALUE);
730  } else {
731  dptmpl = dparam;
732  dtype = weed_leaf_seed_type(dparam, WEED_LEAF_DEFAULT);
733  ndvals = weed_leaf_num_elements(dparam, WEED_LEAF_DEFAULT);
734  }
735  }
736 
737  if (sparam == active_dummy) {
738  stype = WEED_SEED_BOOLEAN;
739  nsvals = 1;
740  } else {
741  if (WEED_PLANT_IS_PARAMETER(sparam)) {
742  stype = weed_leaf_seed_type(sparam, WEED_LEAF_VALUE);
743  nsvals = weed_leaf_num_elements(sparam, WEED_LEAF_VALUE);
744  } else {
745  stype = weed_leaf_seed_type(sparam, WEED_LEAF_DEFAULT);
746  nsvals = weed_leaf_num_elements(sparam, WEED_LEAF_DEFAULT);
747  }
748  }
749 
750  if (dptmpl) {
751  ptype = weed_paramtmpl_get_type(dptmpl);
752  dflags = weed_paramtmpl_get_flags(dptmpl);
753 
754  if (ptype == WEED_PARAM_COLOR) {
755  int cspace = weed_get_int_value(dptmpl, WEED_LEAF_COLORSPACE, NULL);
756  if (cspace == WEED_COLORSPACE_RGB) {
757  if (!(nsvals & 3)) return FALSE;
758  } else if (nsvals & 3) return FALSE;
759  }
760  }
761 
762  if (ndvals > nsvals) {
763  if (!((dflags & WEED_PARAMETER_VARIABLE_SIZE) && !(dflags & WEED_PARAMETER_VALUE_PER_CHANNEL))) return FALSE;
764  }
765 
766  if (dtype == stype) return TRUE;
767 
768  switch (stype) {
769  case WEED_SEED_DOUBLE:
770  if (dtype == WEED_SEED_STRING) return TRUE;
771  return FALSE;
772  case WEED_SEED_INT:
773  if (dtype == WEED_SEED_DOUBLE || dtype == WEED_SEED_STRING) return TRUE;
774  return FALSE;
775  case WEED_SEED_BOOLEAN:
776  if (dtype == WEED_SEED_DOUBLE || dtype == WEED_SEED_INT || dtype == WEED_SEED_STRING) return TRUE;
777  return FALSE;
778  default:
779  return FALSE;
780  }
781 
782  return FALSE;
783 }
784 
785 
786 static boolean pconx_convert_value_data(weed_plant_t *inst, int pnum, int key, weed_plant_t *dparam, int okey,
787  weed_plant_t *sparam, boolean autoscale, boolean is_audio_thread, boolean * toggle_fx) {
788  // try to convert values of various type, if we succeed, copy the "value" and return TRUE (if changed)
789  weed_plant_t *dptmpl = NULL, *sptmpl;
790 
791  double ratio;
792 
793  int dtype = 0, stype, nsvals, ndvals = 0;
794  int ondvals = 0;
795  int nsmin = 0, nsmax = 0;
796  int minct = 0, maxct = 0;
797  int sminct = 0, smaxct = 0;
798  int nmax = 0, nmin = 0;
799  boolean retval = FALSE;
800 
801  int i;
802 
803  if (toggle_fx) *toggle_fx = FALSE;
804 
805  if (dparam == sparam && (dparam != active_dummy || !active_dummy)) return FALSE;
806 
807  if (sparam == active_dummy) {
808  nsvals = 1;
809  sptmpl = NULL;
810  stype = WEED_SEED_BOOLEAN;
811  }
812 
813  nsvals = weed_leaf_num_elements(sparam, WEED_LEAF_VALUE);
814  if (nsvals == 0) return FALSE;
815  sptmpl = weed_param_get_template(sparam);
816  stype = weed_leaf_seed_type(sparam, WEED_LEAF_VALUE);
817 
818  if (dparam != active_dummy) {
819  ondvals = ndvals = weed_leaf_num_elements(dparam, WEED_LEAF_VALUE);
820  dptmpl = weed_param_get_template(dparam);
821  dtype = weed_leaf_seed_type(dparam, WEED_LEAF_VALUE);
822  } else {
823  dtype = WEED_SEED_BOOLEAN;
824  ondvals = ndvals = 1;
825  dptmpl = NULL;
826  }
827 
828  if (!params_compatible(sparam, dparam)) return FALSE;
829 
830  if (ndvals > nsvals) ndvals = nsvals;
831 
832  if (dparam != active_dummy && sparam != active_dummy) {// && autoscale) {
833  if (weed_plant_has_leaf(sptmpl, WEED_LEAF_MIN) && weed_plant_has_leaf(sptmpl, WEED_LEAF_MAX)) {
834  nsmin = weed_leaf_num_elements(sptmpl, WEED_LEAF_MIN);
835  nsmax = weed_leaf_num_elements(sptmpl, WEED_LEAF_MAX);
836  }
837  }
838 
839  if (dptmpl && weed_plant_has_leaf(dptmpl, WEED_LEAF_MAX)) {
840  nmax = weed_leaf_num_elements(dptmpl, WEED_LEAF_MAX);
841  nmin = weed_leaf_num_elements(dptmpl, WEED_LEAF_MIN);
842  }
843 
844  switch (stype) {
845  case WEED_SEED_STRING:
846  switch (dtype) {
847  case WEED_SEED_STRING: {
848  char **valsS, **valss;
849  if ((valsS = weed_get_string_array(sparam, WEED_LEAF_VALUE, NULL)) == NULL) return retval;
850  if ((valss = weed_get_string_array(dparam, WEED_LEAF_VALUE, NULL)) == NULL) return retval;
851 
852  if (ndvals > ondvals) valss = (char **)lives_realloc(valss, ndvals * sizeof(char *));
853 
854  for (i = 0; i < ndvals; i++) {
855  if (i >= ondvals || strcmp(valss[i], valsS[i])) {
856  retval = TRUE;
857  if (i < ondvals) lives_free(valss[i]);
858  valss[i] = valsS[i];
859  } else lives_free(valsS[i]);
860  }
861  if (!retval) {
862  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
863  lives_free(valss);
864  lives_free(valsS);
865  return FALSE;
866  }
867 
868  weed_set_string_array(dparam, WEED_LEAF_VALUE, ndvals, valss);
869 
870  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
871  lives_free(valss);
872  lives_free(valsS);
873  }
874  return TRUE;
875  default:
876  return retval;
877  }
878  case WEED_SEED_DOUBLE:
879  switch (dtype) {
880  case WEED_SEED_DOUBLE: {
881  double *valsD = weed_get_double_array(sparam, WEED_LEAF_VALUE, NULL);
882  double *valsd = weed_get_double_array(dparam, WEED_LEAF_VALUE, NULL);
883 
884  double *maxd = weed_get_double_array(dptmpl, WEED_LEAF_MAX, NULL);
885  double *mind = weed_get_double_array(dptmpl, WEED_LEAF_MIN, NULL);
886 
887  double *mins = NULL, *maxs = NULL;
888 
889  if (autoscale) {
890  mins = weed_get_double_array(sptmpl, WEED_LEAF_MIN, NULL);
891  maxs = weed_get_double_array(sptmpl, WEED_LEAF_MAX, NULL);
892  }
893 
894  if (ndvals > ondvals) valsd = (double *)lives_realloc(valsd, ndvals * sizeof(double));
895 
896  for (i = 0; i < ndvals; i++) {
897  if (autoscale) {
898  ratio = (valsD[i] - mins[sminct]) / (maxs[smaxct] - mins[sminct]);
899  valsD[i] = mind[minct] + (maxd[maxct] - mind[minct]) * ratio;
900  if (++smaxct == nsmax) smaxct = 0;
901  if (++sminct == nsmin) sminct = 0;
902 
903  if (valsD[i] > maxd[maxct]) valsD[i] = maxd[maxct];
904  if (valsD[i] < mind[minct]) valsD[i] = mind[minct];
905  }
906 
907  if (i >= ondvals || valsd[i] != valsD[i]) {
908  retval = TRUE;
909  valsd[i] = valsD[i];
910  }
911  if (++maxct == nmax) maxct = 0;
912  if (++minct == nmin) minct = 0;
913  }
914 
915  if (mins) {
916  lives_free(mins);
917  lives_free(maxs);
918  }
919 
920  if (retval) {
921  if (inst && mainw->record && !mainw->record_paused && LIVES_IS_PLAYING && (prefs->rec_opts & REC_EFFECTS)) {
922  // if we are recording, add this change to our event_list
923  rec_param_change(inst, pnum);
924  }
925 
926  weed_set_double_array(dparam, WEED_LEAF_VALUE, ndvals, valsd);
927  }
928  lives_free(maxd); lives_free(mind); lives_free(valsD); lives_free(valsd);
929  }
930  return retval;
931 
932  case WEED_SEED_STRING: {
933  char *opstring, *tmp, *bit;
934  double *valsd = weed_get_double_array(sparam, WEED_LEAF_VALUE, NULL);
935  char **valss, *vals;
936 
937  if (ndvals == 1) {
938  opstring = lives_strdup("");
939  vals = weed_get_string_value(dparam, WEED_LEAF_VALUE, NULL);
940  for (i = 0; i < nsvals; i++) {
941  bit = lives_strdup_printf("%.4f", valsd[i]);
942  if (!*opstring)
943  tmp = lives_strconcat(opstring, bit, NULL);
944  else
945  tmp = lives_strconcat(opstring, " ", bit, NULL);
946  lives_free(bit);
947  lives_free(opstring);
948  opstring = tmp;
949  }
950  if (strcmp(vals, opstring)) {
951  weed_set_string_value(dparam, WEED_LEAF_VALUE, opstring);
952  retval = TRUE;
953  }
954  lives_free(vals); lives_free(valsd); lives_free(opstring);
955  return retval;
956  }
957 
958  valss = weed_get_string_array(dparam, WEED_LEAF_VALUE, NULL);
959 
960  if (ndvals > ondvals) valss = (char **)lives_realloc(valsd, ndvals * sizeof(char *));
961 
962  for (i = 0; i < ndvals; i++) {
963  bit = lives_strdup_printf("%.4f", valsd[i]);
964  if (i >= ondvals || strcmp(valss[i], bit)) {
965  retval = TRUE;
966  if (i < ondvals) lives_free(valss[i]);
967  valss[i] = bit;
968  } else lives_free(bit);
969  }
970  if (!retval) {
971  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
972  lives_free(valss);
973  lives_free(valsd);
974  return FALSE;
975  }
976 
977  weed_set_string_array(dparam, WEED_LEAF_VALUE, ndvals, valss);
978 
979  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
980  lives_free(valss);
981  lives_free(valsd);
982  }
983  return TRUE;
984  default: break;
985  }
986 
987  break;
988 
989  case WEED_SEED_INT:
990  switch (dtype) {
991  case WEED_SEED_STRING: {
992  char *opstring, *tmp, *bit;
993  int *valsi = weed_get_int_array(sparam, WEED_LEAF_VALUE, NULL);
994 
995  char **valss, *vals;
996 
997  if (ndvals == 1) {
998  opstring = lives_strdup("");
999  vals = weed_get_string_value(dparam, WEED_LEAF_VALUE, NULL);
1000  for (i = 0; i < nsvals; i++) {
1001  bit = lives_strdup_printf("%d", valsi[i]);
1002  if (!*opstring)
1003  tmp = lives_strconcat(opstring, bit, NULL);
1004  else
1005  tmp = lives_strconcat(opstring, " ", bit, NULL);
1006  lives_free(bit);
1007  lives_free(opstring);
1008  opstring = tmp;
1009  }
1010  if (strcmp(vals, opstring)) {
1011  weed_set_string_value(dparam, WEED_LEAF_VALUE, opstring);
1012  retval = TRUE;
1013  }
1014  lives_free(vals); lives_free(valsi); lives_free(opstring);
1015  return retval;
1016  }
1017 
1018  valss = weed_get_string_array(dparam, WEED_LEAF_VALUE, NULL);
1019 
1020  if (ndvals > ondvals) valss = (char **)lives_realloc(valss, ndvals * sizeof(char *));
1021 
1022  for (i = 0; i < ndvals; i++) {
1023  bit = lives_strdup_printf("%d", valsi[i]);
1024  if (i >= ondvals || strcmp(valss[i], bit)) {
1025  retval = TRUE;
1026  if (i < ondvals) lives_free(valss[i]);
1027  valss[i] = bit;
1028  } else lives_free(bit);
1029  }
1030  if (!retval) {
1031  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
1032  lives_free(valss); lives_free(valsi);
1033  return FALSE;
1034  }
1035 
1036  weed_set_string_array(dparam, WEED_LEAF_VALUE, ndvals, valss);
1037 
1038  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
1039  lives_free(valss);
1040  lives_free(valsi);
1041  }
1042  return retval;
1043  case WEED_SEED_DOUBLE: {
1044  int *valsi = weed_get_int_array(sparam, WEED_LEAF_VALUE, NULL);
1045  double *valsd = weed_get_double_array(dparam, WEED_LEAF_VALUE, NULL);
1046 
1047  double *maxd = weed_get_double_array(dptmpl, WEED_LEAF_MAX, NULL);
1048  double *mind = weed_get_double_array(dptmpl, WEED_LEAF_MIN, NULL);
1049  double vald;
1050 
1051  int *mins = NULL, *maxs = NULL;
1052 
1053  if (autoscale) {
1054  mins = weed_get_int_array(sptmpl, WEED_LEAF_MIN, NULL);
1055  maxs = weed_get_int_array(sptmpl, WEED_LEAF_MAX, NULL);
1056  }
1057 
1058  if (ndvals > ondvals) valsd = (double *)lives_realloc(valsd, ndvals * sizeof(double));
1059 
1060  for (i = 0; i < ndvals; i++) {
1061  if (autoscale) {
1062  ratio = (double)(valsi[i] - mins[sminct]) / (double)(maxs[smaxct] - mins[sminct]);
1063  vald = mind[minct] + (maxd[maxct] - mind[minct]) * ratio;
1064  if (++smaxct == nsmax) smaxct = 0;
1065  if (++sminct == nsmin) sminct = 0;
1066 
1067  if (vald > maxd[maxct]) vald = maxd[maxct];
1068  if (vald < mind[minct]) vald = mind[minct];
1069  } else vald = (double)valsi[i];
1070 
1071  if (i >= ondvals || valsd[i] != vald) {
1072  retval = TRUE;
1073  valsd[i] = vald;
1074  }
1075  if (++maxct == nmax) maxct = 0;
1076  if (++minct == nmin) minct = 0;
1077  }
1078 
1079  if (mins) {
1080  lives_free(mins);
1081  lives_free(maxs);
1082  }
1083 
1084  if (retval) {
1085  if (inst && mainw->record && !mainw->record_paused && LIVES_IS_PLAYING && (prefs->rec_opts & REC_EFFECTS)) {
1086  // if we are recording, add this change to our event_list
1087  rec_param_change(inst, pnum);
1088  }
1089 
1090  weed_set_double_array(dparam, WEED_LEAF_VALUE, ndvals, valsd);
1091  }
1092  lives_free(maxd); lives_free(mind);
1093  lives_free(valsi); lives_free(valsd);
1094  }
1095  return retval;
1096 
1097  case WEED_SEED_INT: {
1098  int *valsI, *valsi, *maxi, *mini;
1099  int *mins = NULL, *maxs = NULL;
1100 
1101  if ((valsI = weed_get_int_array(sparam, WEED_LEAF_VALUE, NULL)) == NULL) return retval;
1102  if ((valsi = weed_get_int_array(dparam, WEED_LEAF_VALUE, NULL)) == NULL) return retval;
1103  if ((maxi = weed_get_int_array(dptmpl, WEED_LEAF_MAX, NULL)) == NULL) return retval;
1104  if ((mini = weed_get_int_array(dptmpl, WEED_LEAF_MIN, NULL)) == NULL) return retval;
1105 
1106  if (autoscale) {
1107  mins = weed_get_int_array(sptmpl, WEED_LEAF_MIN, NULL);
1108  maxs = weed_get_int_array(sptmpl, WEED_LEAF_MAX, NULL);
1109  }
1110 
1111  if (ndvals > ondvals) valsi = (int *)lives_realloc(valsi, ndvals * sizeof(int));
1112 
1113  for (i = 0; i < ndvals; i++) {
1114  if (autoscale) {
1115  ratio = (double)(valsI[i] - mins[sminct]) / (double)(maxs[smaxct] - mins[sminct]);
1116  valsI[i] = myround(mini[minct] + (double)(maxi[maxct] - mini[minct]) * ratio);
1117  if (++smaxct == nsmax) smaxct = 0;
1118  if (++sminct == nsmin) sminct = 0;
1119 
1120  if (valsI[i] > maxi[maxct]) valsI[i] = maxi[maxct];
1121  if (valsI[i] < mini[minct]) valsI[i] = mini[minct];
1122  }
1123 
1124  if (i >= ondvals || valsi[i] != valsI[i]) {
1125  retval = TRUE;
1126  valsi[i] = valsI[i];
1127  }
1128  if (++maxct == nmax) maxct = 0;
1129  if (++minct == nmin) minct = 0;
1130  }
1131 
1132  if (mins) {
1133  lives_free(mins);
1134  lives_free(maxs);
1135  }
1136 
1137  if (retval) {
1139  // if we are recording, add this change to our event_list
1140  rec_param_change(inst, pnum);
1141  }
1142 
1143  weed_set_int_array(dparam, WEED_LEAF_VALUE, ndvals, valsi);
1144  }
1145  lives_free(maxi); lives_free(mini);
1146  lives_free(valsI); lives_free(valsi);
1147  }
1148  return retval;
1149  }
1150  break;
1151 
1152  case WEED_SEED_BOOLEAN: {
1153  int *valsb;
1154  if (dparam == active_dummy) {
1155  // ACTIVATE / DEACTIVATE
1156  if (!autoscale) { // autoscale is now "user override"
1157  int valb = weed_get_boolean_value(sparam, WEED_LEAF_VALUE, NULL);
1158  if ((valb == WEED_TRUE && (mainw->rte & (GU641 << (key))) == 0) ||
1159  (valb == WEED_FALSE && (mainw->rte & (GU641 << (key)))) != 0) {
1160  if (toggle_fx) *toggle_fx = TRUE;
1161  }
1162  }
1163  return retval;
1164  }
1165  valsb = weed_get_boolean_array(sparam, WEED_LEAF_VALUE, NULL);
1166  switch (dtype) {
1167  case WEED_SEED_STRING: {
1168  char *opstring, *tmp, *bit;
1169  char **valss, *vals;
1170 
1171  if (ndvals == 1) {
1172  opstring = lives_strdup("");
1173  vals = weed_get_string_value(dparam, WEED_LEAF_VALUE, NULL);
1174  for (i = 0; i < nsvals; i++) {
1175  bit = lives_strdup_printf("%d", valsb[i]);
1176  if (!*opstring)
1177  tmp = lives_strconcat(opstring, bit, NULL);
1178  else
1179  tmp = lives_strconcat(opstring, " ", bit, NULL);
1180  lives_free(bit);
1181  lives_free(opstring);
1182  opstring = tmp;
1183  }
1184  if (strcmp(vals, opstring)) {
1185  weed_set_string_value(dparam, WEED_LEAF_VALUE, opstring);
1186  retval = TRUE;
1187  }
1188  lives_free(vals); lives_free(valsb); lives_free(opstring);
1189  return retval;
1190  }
1191 
1192  valss = weed_get_string_array(dparam, WEED_LEAF_VALUE, NULL);
1193  if (ndvals > ondvals) valss = (char **)lives_realloc(valss, ndvals * sizeof(char *));
1194 
1195  for (i = 0; i < ndvals; i++) {
1196  bit = lives_strdup_printf("%d", valsb[i]);
1197  if (i >= ondvals || strcmp(valss[i], bit)) {
1198  retval = TRUE;
1199  if (i < ondvals) lives_free(valss[i]);
1200  valss[i] = bit;
1201  } else lives_free(bit);
1202  }
1203  if (!retval) {
1204  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
1205  lives_free(valss);
1206  lives_free(valsb);
1207  return FALSE;
1208  }
1209 
1210  weed_set_string_array(dparam, WEED_LEAF_VALUE, ndvals, valss);
1211 
1212  for (i = 0; i < ndvals; i++) lives_free(valss[i]);
1213  lives_free(valss);
1214  lives_free(valsb);
1215  }
1216  return retval;
1217  case WEED_SEED_DOUBLE: {
1218  double *valsd = weed_get_double_array(dparam, WEED_LEAF_VALUE, NULL);
1219  double *maxd = weed_get_double_array(dptmpl, WEED_LEAF_MAX, NULL);
1220  double *mind = weed_get_double_array(dptmpl, WEED_LEAF_MIN, NULL);
1221  double vald;
1222 
1223  if (ndvals > ondvals) valsd = (double *)lives_realloc(valsd, ndvals * sizeof(double));
1224 
1225  for (i = 0; i < ndvals; i++) {
1226  if (autoscale) {
1227  if (valsb[i] == WEED_TRUE) vald = maxd[maxct];
1228  else vald = mind[minct];
1229  } else {
1230  vald = (double)valsb[i];
1231  if (vald > maxd[maxct]) vald = maxd[maxct];
1232  if (vald < mind[minct]) vald = mind[minct];
1233  }
1234  if (i >= ondvals || valsd[i] != vald) {
1235  retval = TRUE;
1236  valsd[i] = vald;
1237  }
1238  if (++maxct == nmax) maxct = 0;
1239  if (++minct == nmin) minct = 0;
1240  }
1241  if (retval) {
1242  if (inst && mainw->record && !mainw->record_paused && LIVES_IS_PLAYING && (prefs->rec_opts & REC_EFFECTS)) {
1243  // if we are recording, add this change to our event_list
1244  rec_param_change(inst, pnum);
1245  }
1246 
1247  weed_set_double_array(dparam, WEED_LEAF_VALUE, ndvals, valsd);
1248  }
1249  lives_free(maxd); lives_free(mind);
1250  lives_free(valsb); lives_free(valsd);
1251  }
1252  return retval;
1253  case WEED_SEED_INT: {
1254  int *valsi = weed_get_int_array(dparam, WEED_LEAF_VALUE, NULL);
1255  int *maxi = weed_get_int_array(dptmpl, WEED_LEAF_MAX, NULL);
1256  int *mini = weed_get_int_array(dptmpl, WEED_LEAF_MIN, NULL);
1257 
1258  if (ndvals > ondvals) valsi = (int *)lives_realloc(valsi, ndvals * sizeof(int));
1259 
1260  for (i = 0; i < ndvals; i++) {
1261  if (autoscale) {
1262  if (valsb[i] == WEED_TRUE) valsb[i] = maxi[maxct];
1263  else valsb[i] = mini[minct];
1264  } else {
1265  if (valsb[i] > maxi[maxct]) valsb[i] = maxi[maxct];
1266  if (valsb[i] < mini[minct]) valsb[i] = mini[maxct];
1267  }
1268  if (i >= ondvals || valsi[i] != valsb[i]) {
1269  retval = TRUE;
1270  valsi[i] = valsb[i];
1271  }
1272  if (++maxct == nmax) maxct = 0;
1273  if (++minct == nmin) minct = 0;
1274  }
1275  if (retval) {
1276  if (inst && mainw->record && !mainw->record_paused && LIVES_IS_PLAYING && (prefs->rec_opts & REC_EFFECTS)) {
1277  // if we are recording, add this change to our event_list
1278  rec_param_change(inst, pnum);
1279  }
1280 
1281  weed_set_int_array(dparam, WEED_LEAF_VALUE, ndvals, valsi);
1282  }
1283  lives_free(maxi); lives_free(mini);
1284  lives_free(valsi); lives_free(valsb);
1285  }
1286  return retval;
1287 
1288  case WEED_SEED_BOOLEAN: {
1289  int *valsB = weed_get_boolean_array(dparam, WEED_LEAF_VALUE, NULL);
1290 
1291  if (ndvals > ondvals) valsB = (int *)lives_realloc(valsB, ndvals * sizeof(int));
1292 
1293  for (i = 0; i < ndvals; i++) {
1294  if (i >= ondvals || valsB[i] != valsb[i]) {
1295  retval = TRUE;
1296  valsB[i] = valsb[i];
1297  }
1298  }
1299  if (retval) {
1300  if (inst && mainw->record && !mainw->record_paused && LIVES_IS_PLAYING && (prefs->rec_opts & REC_EFFECTS)) {
1301  // if we are recording, add this change to our event_list
1302  rec_param_change(inst, pnum);
1303  }
1304  weed_set_boolean_array(dparam, WEED_LEAF_VALUE, ndvals, valsB);
1305  }
1306  lives_free(valsb);
1307  lives_free(valsB);
1308  }
1309  return retval;
1310  default:
1311  lives_free(valsb);
1312  break;
1313  }
1314  break;
1315  }
1316  default: break;
1317  }
1318 
1319  return retval;
1320 }
1321 
1322 
1323 int pconx_chain_data_omc(weed_plant_t *inst, int okey, int omode) {
1324  // push anything to connected OMC macros
1325  lives_pconnect_t *pconx = mainw->pconx;
1326 
1327  char *valstr = NULL;
1328 
1329  int totcons, pidx;
1330  int actions = 0;
1331 
1332  boolean cbval, lbval;
1333 
1334  int i, j;
1335 
1336  if (!inst) return 0;
1337 
1338  if (mainw->event_list && !mainw->record && !mainw->record_paused) return 0;
1339 
1340  // check for any inkeys == FX_DATA_KEY_OMC_MACRO and matching okey, omode
1341  // for each match we construct a string and send it to the OMC learner
1342 
1343  while (pconx) {
1344  if (pconx->okey == okey && pconx->omode == omode) {
1345  totcons = 0;
1346  j = 0;
1347  for (i = 0; i < pconx->nparams; i++) {
1348  totcons += pconx->nconns[i];
1349  pidx = pconx->params[i];
1350  lbval = pconx->last_boolval[i];
1351  for (; j < totcons; j++) {
1352  if (pconx->ikey[j] == FX_DATA_KEY_OMC_MACRO) {
1353  // out param is "ACTIVATED"
1354  if (pidx >= 0) {
1355  weed_plant_t *oparam = weed_inst_out_param(inst, pidx);
1356  switch (weed_leaf_seed_type(oparam, WEED_LEAF_VALUE)) {
1357  case WEED_SEED_BOOLEAN:
1358  cbval = weed_get_boolean_value(oparam, WEED_LEAF_VALUE, NULL);
1359  if (cbval == WEED_TRUE && lbval == WEED_FALSE) {
1360  // state changed, so trigger act
1361  valstr = lives_strdup_printf("%d", cbval);
1362  }
1363  pconx->last_boolval[i] = cbval;
1364  break;
1365  default: break;
1366  }
1367  } else {
1368  valstr = lives_strdup_printf("%d", WEED_TRUE);
1369  pconx->last_boolval[i] = WEED_TRUE;
1370  }
1371  }
1372  if (valstr) {
1373  // construct string to pass
1374  char *msgstring = lives_strdup_printf("%d %d %d %s", OMC_INTERNAL, pconx->imode[j], pconx->ipnum[j], valstr);
1375  lives_free(valstr);
1376  valstr = NULL;
1377  omc_process_string(OMC_INTERNAL, (const char *)msgstring, FALSE, NULL);
1378  actions++;
1379  lives_free(msgstring);
1380  // *INDENT-OFF*
1381  }}}}
1382  // *INDENT-ON*
1383 
1384  pconx = pconx->next;
1385  }
1386  return actions;
1387 }
1388 
1389 
1390 boolean pconx_chain_data(int key, int mode, boolean is_audio_thread) {
1391  weed_plant_t **inparams = NULL;
1392  weed_plant_t *oparam, *inparam = NULL;
1393  weed_plant_t *inst = NULL;
1394 
1395  boolean changed, reinit_inst = FALSE;
1396 
1397  int nparams = 0, start = 0;
1398  int autoscale;
1399  int pflags;
1400  int okey, omode;
1401  boolean toggle_fx = FALSE;
1402  int i;
1403 
1404  if (mainw->is_rendering) return FALSE;
1405 
1406  if (key == FX_DATA_KEY_PLAYBACK_PLUGIN) {
1407  // playback plugin
1408  if (!mainw->vpp) return FALSE;
1409  inparams = mainw->vpp->play_params;
1410  nparams = mainw->vpp->num_play_params;
1411  } else {
1412  filter_mutex_lock(key);
1413  inst = rte_keymode_get_instance(key + 1, mode);
1414  if (!inst) filter_mutex_unlock(key);
1415  start = -EXTRA_PARAMS_IN;
1416  }
1417 
1418  if (inst) {
1419  if (weed_plant_has_leaf(inst, WEED_LEAF_IN_PARAMETERS))
1420  inparams = weed_get_plantptr_array_counted(inst, WEED_LEAF_IN_PARAMETERS, &nparams);
1421  } else {
1422  if (rte_keymode_get_filter_idx(key + 1, mode) == -1) return FALSE;
1423  }
1424 
1425 
1426  for (i = start; i < nparams; i++) {
1427  //g_print("NOW at %d %d\n ", key, mode);
1428  if ((oparam = pconx_get_out_param(FALSE, key, mode, i, &okey, &omode, NULL, &autoscale))) {
1429  //#define DEBUG_PCONX
1430 #ifdef DEBUG_PCONX
1431  g_print("got pconx to %d %d %d\n", key, mode, i);
1432 #endif
1433  if (i == FX_DATA_PARAM_ACTIVE) {
1434  pthread_mutex_lock(&mainw->fxd_active_mutex);
1435  if (!active_dummy) {
1436  active_dummy = weed_plant_new(WEED_PLANT_PARAMETER);
1437  weed_set_plantptr_value(active_dummy, WEED_LEAF_TEMPLATE, NULL);
1438  }
1439  inparam = active_dummy;
1440  pthread_mutex_unlock(&mainw->fxd_active_mutex);
1441  } else inparam = inparams[i];
1442 
1444  filter_mutex_lock(okey);
1445  if (oparam != active_dummy) {
1446  weed_plant_t *oinst = rte_keymode_get_instance(okey + 1, omode);
1447  if (!oinst) {
1448  filter_mutex_unlock(okey);
1449  if (inst) {
1450  weed_instance_unref(inst);
1451  filter_mutex_unlock(key);
1452  }
1453  return FALSE;
1454  }
1455  weed_instance_unref(oinst);
1456  }
1457 
1458  changed = pconx_convert_value_data(inst, i, key, key == FX_DATA_KEY_PLAYBACK_PLUGIN
1459  ? (weed_plant_t *)pp_get_param(mainw->vpp->play_params, i)
1460  : inparam, okey, oparam, autoscale, is_audio_thread, &toggle_fx);
1461 
1462  if (toggle_fx) {
1463  if (is_audio_thread) {
1464  // in the audio thread, don't activate / dectivate video fx. It could cause an underflow if it takes too long
1465  // let the video thread handle it
1466  weed_plant_t *filter = rte_keymode_get_filter(key + 1, rte_key_getmode(key + 1));
1467  if (!is_pure_audio(filter, FALSE)) {
1468  if (inst) {
1469  weed_instance_unref(inst);
1470  inst = NULL;
1471  filter_mutex_unlock(key);
1472  }
1473  filter_mutex_unlock(okey);
1474  return FALSE;
1475  }
1476  }
1477  if (inst) {
1478  weed_instance_unref(inst);
1479  inst = NULL;
1480  filter_mutex_unlock(key);
1481  }
1482  switch_fx_state(key + 1);
1483  filter_mutex_unlock(okey);
1484  } else {
1485  filter_mutex_unlock(okey);
1486  if (changed && inst && key > -1) {
1487  // only store value if it changed; for int, double or colour, store old value too
1488 
1489  //copyto = set_copy_to(inst, i, TRUE);
1491  // if we are recording, add this change to our event_list
1492  rec_param_change(inst, i);
1493  //if (copyto != -1) rec_param_change(inst, copyto);
1494  }
1495 
1496  pflags = weed_get_int_value(inparams[i], WEED_LEAF_FLAGS, NULL);
1497  if (pflags & WEED_PARAMETER_REINIT_ON_VALUE_CHANGE) reinit_inst = TRUE;
1498 
1499  if (fx_dialog[1] && !reinit_inst) {
1500  lives_rfx_t *rfx = fx_dialog[1]->rfx;
1501  if (!rfx->is_template) {
1502  int keyw = fx_dialog[1]->key;
1503  int modew = fx_dialog[1]->mode;
1504  if (keyw == key && modew == mode)
1505  // ask the main thread to update the param window
1506  mainw->vrfx_update = rfx;
1507  }
1508  }
1510  // *INDENT-OFF*
1511  }}}}
1512  // *INDENT-ON*
1513 
1514  if (inst) {
1515  weed_instance_unref(inst);
1516  inst = NULL;
1517  filter_mutex_unlock(key);
1518  }
1519 
1520  if (key != FX_DATA_KEY_PLAYBACK_PLUGIN && inparams) lives_free(inparams);
1521  return reinit_inst;
1522 }
1523 
1524 
1525 boolean pconx_chain_data_internal(weed_plant_t *inst) {
1526  // special version for compound fx internal connections
1527  weed_plant_t **in_params;
1528 
1529  boolean autoscale, reinit_inst = FALSE;
1530 
1531  int nparams = 0, pflags, i;
1532 
1533  nparams = num_in_params(inst, FALSE, FALSE);
1534  if (!nparams) return FALSE;
1535 
1536  in_params = weed_get_plantptr_array(inst, WEED_LEAF_IN_PARAMETERS, NULL);
1537 
1538  for (i = 0; i < nparams; i++) {
1539  if (weed_plant_has_leaf(in_params[i], WEED_LEAF_HOST_INTERNAL_CONNECTION)) {
1540  autoscale = FALSE;
1541  if (weed_plant_has_leaf(in_params[i], WEED_LEAF_HOST_INTERNAL_CONNECTION_AUTOSCALE) &&
1542  weed_get_boolean_value(in_params[i],
1543  WEED_LEAF_HOST_INTERNAL_CONNECTION_AUTOSCALE, NULL) == WEED_TRUE) autoscale = TRUE;
1544  if (pconx_convert_value_data(inst, i, -1, in_params[i], -1, weed_get_plantptr_value(in_params[i],
1545  WEED_LEAF_HOST_INTERNAL_CONNECTION, NULL), autoscale, FALSE, NULL)) {
1546 
1547  pflags = weed_get_int_value(in_params[i], WEED_LEAF_FLAGS, NULL);
1548  if (pflags & WEED_PARAMETER_REINIT_ON_VALUE_CHANGE) reinit_inst = TRUE;
1549  }
1550  }
1551  }
1552 
1553  lives_free(in_params);
1554  return reinit_inst;
1555 }
1556 
1557 // alpha channs
1558 
1559 
1560 void cconx_delete_all(void) {
1561  lives_cconnect_t *cconx = mainw->cconx, *cconx_next;
1562  while (cconx) {
1563  cconx_next = cconx->next;
1564  if (cconx->nchans > 0) {
1565  lives_free(cconx->chans);
1566  lives_free(cconx->nconns);
1567  lives_free(cconx->ikey);
1568  lives_free(cconx->imode);
1569  lives_free(cconx->icnum);
1570  }
1571  lives_free(cconx);
1572  cconx = cconx_next;
1573  }
1574  mainw->cconx = NULL;
1575 }
1576 
1577 
1578 static lives_cconnect_t *cconx_new(int okey, int omode) {
1579  lives_cconnect_t *cconx = (lives_cconnect_t *)lives_calloc(sizeof(struct _lives_cconnect_t), 1);
1580  cconx->next = NULL;
1581  cconx->okey = okey;
1582  cconx->omode = omode;
1583  cconx->nchans = 0;
1584  cconx->nconns = NULL;
1585  return cconx;
1586 }
1587 
1588 
1589 static lives_cconnect_t *cconx_copy(lives_cconnect_t *scconx) {
1590  lives_cconnect_t *cconx = NULL, *dcconx, *last_dcconx;
1591 
1592  int totcons = 0;
1593 
1594  register int i, j = 0;
1595 
1596  while (scconx) {
1597  dcconx = cconx_new(scconx->okey, scconx->omode);
1598  if (!cconx) cconx = dcconx;
1599  else last_dcconx->next = dcconx;
1600 
1601  dcconx->nchans = scconx->nchans;
1602 
1603  dcconx->nconns = (int *)lives_malloc(dcconx->nchans * sizint);
1604  dcconx->chans = (int *)lives_malloc(dcconx->nchans * sizint);
1605 
1606  dcconx->ikey = dcconx->imode = dcconx->icnum = NULL;
1607 
1608  j = 0;
1609 
1610  for (i = 0; i < dcconx->nchans; i++) {
1611  dcconx->chans[i] = scconx->chans[i];
1612  dcconx->nconns[i] = scconx->nconns[i];
1613  totcons += dcconx->nconns[i];
1614 
1615  dcconx->ikey = (int *)lives_realloc(dcconx->ikey, totcons * sizint);
1616  dcconx->imode = (int *)lives_realloc(dcconx->imode, totcons * sizint);
1617  dcconx->icnum = (int *)lives_realloc(dcconx->icnum, totcons * sizint);
1618 
1619  while (j < totcons) {
1620  dcconx->ikey[j] = scconx->ikey[j];
1621  dcconx->imode[j] = scconx->imode[j];
1622  dcconx->icnum[j] = scconx->icnum[j];
1623  j++;
1624  }
1625  }
1626 
1627  scconx = scconx->next;
1628  last_dcconx = dcconx;
1629  }
1630 
1631  return cconx;
1632 }
1633 
1634 
1635 char *cconx_list(int okey, int omode, int ocnum) {
1636  char *st1 = lives_strdup(""), *st2;
1637  lives_cconnect_t *cconx = mainw->cconx;
1638  int totcons = 0;
1639 
1640  while (cconx) {
1641  if (cconx->okey == okey && cconx->omode == omode) {
1642  for (int i = 0; i < cconx->nchans; i++) {
1643  if (cconx->chans[i] == ocnum) {
1644  for (int j = totcons; j < totcons + cconx->nconns[i]; j++) {
1645  if (!*st1) st2 = lives_strdup_printf("%d %d %d", cconx->ikey[j] + 1, cconx->imode[j] + 1, cconx->icnum[j]);
1646  else
1647  st2 = lives_strdup_printf("%s %d %d %d", st1, cconx->ikey[j] + 1, cconx->imode[j] + 1, cconx->icnum[j]);
1648  lives_free(st1);
1649  st1 = st2;
1650  }
1651  return st1;
1652  }
1653  totcons += cconx->nconns[i];
1654  }
1655  return st1;
1656  }
1657  cconx = cconx->next;
1658  }
1659  return st1;
1660 }
1661 
1662 
1663 void cconx_delete(int okey, int omode, int ocnum, int ikey, int imode, int icnum) {
1664  lives_cconnect_t *cconx = mainw->cconx, *cconx_next, *cconx_prev = NULL;
1665 
1666  register int i, j = 0, k;
1667 
1668  int totcons = 0, maxcons = 0;
1669 
1670  while (cconx) {
1671  cconx_next = cconx->next;
1672  if (okey == FX_DATA_WILDCARD || (cconx->okey == okey && cconx->omode == omode)) {
1673  if (ikey == FX_DATA_WILDCARD) {
1674  // delete entire node
1675  lives_free(cconx->chans); lives_free(cconx->nconns); lives_free(cconx->ikey);
1676  lives_free(cconx->imode); lives_free(cconx->icnum); lives_free(cconx);
1677  if (mainw->cconx == cconx) mainw->cconx = cconx_next;
1678  else cconx_prev->next = cconx_next;
1679  return;
1680  }
1681 
1682  maxcons = 0;
1683  totcons = 0;
1684  j = 0;
1685 
1686  for (i = 0; i < cconx->nchans; i++) {
1687  maxcons += cconx->nconns[i];
1688  }
1689 
1690  for (i = 0; cconx && i < cconx->nchans; i++) {
1691  totcons += cconx->nconns[i];
1692 
1693  if (okey != FX_DATA_WILDCARD && cconx->chans[i] != ocnum) {
1694  j = totcons;
1695  continue;
1696  }
1697 
1698  for (; j < totcons; j++) {
1699  if (cconx->ikey[j] == ikey && cconx->imode[j] == imode && (icnum == FX_DATA_WILDCARD || cconx->icnum[j] == icnum)) {
1700  maxcons--;
1701  for (k = j; k < maxcons; k++) {
1702  cconx->ikey[k] = cconx->ikey[k + 1];
1703  cconx->imode[k] = cconx->imode[k + 1];
1704  cconx->icnum[k] = cconx->icnum[k + 1];
1705  }
1706 
1707  cconx->ikey = (int *)lives_realloc(cconx->ikey, maxcons * sizint);
1708  cconx->imode = (int *)lives_realloc(cconx->imode, maxcons * sizint);
1709  cconx->icnum = (int *)lives_realloc(cconx->icnum, maxcons * sizint);
1710 
1711  cconx->nconns[i]--;
1712 
1713  if (cconx->nconns[i] == 0) {
1714  cconx->nchans--;
1715  for (k = i; k < cconx->nchans; k++) {
1716  cconx->chans[k] = cconx->chans[k + 1];
1717  cconx->nconns[k] = cconx->nconns[k + 1];
1718  }
1719 
1720  if (cconx->nchans == 0) {
1721  // delete entire node
1722  lives_free(cconx->chans); lives_free(cconx->nconns); lives_free(cconx->ikey);
1723  lives_free(cconx->imode); lives_free(cconx->icnum); lives_free(cconx);
1724  if (mainw->cconx == cconx) {
1725  mainw->cconx = cconx_next;
1726  cconx = NULL;
1727  } else {
1728  cconx = cconx_prev;
1729  cconx->next = cconx_next;
1730  }
1731  } else {
1732  cconx->nconns = (int *)lives_realloc(cconx->nconns, cconx->nchans * sizint);
1733  }
1734  // *INDENT-OFF*
1735  }}}}}
1736  // *INDENT-ON*
1737 
1738  cconx_prev = cconx;
1739  cconx = cconx_next;
1740  }
1741 }
1742 
1743 
1744 void cconx_remap_mode(int key, int omode, int nmode) {
1745  lives_cconnect_t *cconx = mainw->cconx;
1746 
1747  register int i, j, totcons;
1748 
1749  while (cconx) {
1750  if (cconx->okey == key && cconx->omode == omode) {
1751  cconx->omode = nmode;
1752  }
1753  j = 0;
1754  totcons = 0;
1755  for (i = 0; i < cconx->nchans; i++) {
1756  totcons += cconx->nconns[i];
1757  for (; j < totcons; j++) {
1758  if (cconx->ikey[j] == key && cconx->imode[j] == omode) {
1759  cconx->imode[j] = nmode;
1760  }
1761  }
1762  }
1763  cconx = cconx->next;
1764  }
1765 }
1766 
1767 
1768 static void cconx_append(lives_cconnect_t *cconx) {
1769  lives_cconnect_t *occonx = mainw->cconx;
1770  lives_cconnect_t *last_cconx = occonx;
1771 
1772  while (occonx) {
1773  last_cconx = occonx;
1774  occonx = occonx->next;
1775  }
1776 
1777  if (last_cconx) last_cconx->next = cconx;
1778  if (!mainw->cconx) mainw->cconx = cconx;
1779 }
1780 
1781 
1782 static lives_cconnect_t *cconx_find(int okey, int omode) {
1783  lives_cconnect_t *cconx = mainw->cconx;
1784  while (cconx) {
1785  if (cconx->okey == okey && cconx->omode == omode) {
1786  return cconx;
1787  }
1788  cconx = cconx->next;
1789  }
1790  return NULL;
1791 }
1792 
1793 
1794 static int cconx_get_numcons(lives_conx_w * conxwp, int cnum) {
1795  // get displayed number
1796  int totcons = 0;
1797 
1798  register int j;
1799 
1800  if (cnum != FX_DATA_WILDCARD) return conxwp->dispc[cnum];
1801 
1802  for (j = 0; j < conxwp->num_alpha; j++) {
1803  totcons += conxwp->dispc[j];
1804  }
1805 
1806  return totcons;
1807 }
1808 
1809 
1810 static int cconx_get_nconns(lives_cconnect_t *cconx, int cnum) {
1811  // get actual number of connections
1812 
1813  int totcons = 0, j;
1814 
1815  if (!cconx) return 0;
1816 
1817  for (j = 0; j < cconx->nchans; j++) {
1818  if (cnum != FX_DATA_WILDCARD) {
1819  if (cconx->chans[j] == cnum) return cconx->nconns[j];
1820  } else totcons += cconx->nconns[j];
1821  }
1822  return totcons;
1823 }
1824 
1825 
1826 static lives_cconnect_t *cconx_add_connection_private(int okey, int omode, int ocnum, int ikey, int imode, int icnum) {
1827  lives_cconnect_t *cconx;
1828  int posn = 0, totcons = 0, i, j;
1829 
1830  // delete any existing connection to the input channel
1831  cconx_delete(FX_DATA_WILDCARD, 0, 0, ikey, imode, icnum);
1832  cconx = cconx_find(okey, omode);
1833 
1834  if (!cconx) {
1835  // add whole new node
1836  cconx = cconx_new(okey, omode);
1837  cconx_append(cconx);
1838  } else {
1839  // see if already in chans
1840 
1841  for (i = 0; i < cconx->nchans; i++) {
1842 
1843  if (cconx->chans[i] == ocnum) {
1844  // add connection to existing
1845 
1846  for (j = 0; j < cconx->nchans; j++) {
1847  if (j < i) {
1848  // calc posn
1849  posn += cconx->nconns[j];
1850  }
1851  totcons += cconx->nconns[j];
1852  }
1853 
1854  // if already there, do not add again
1855  for (j = posn; j < posn + cconx->nconns[i]; j++) {
1856  if (cconx->ikey[j] == ikey && cconx->imode[j] == imode && cconx->icnum[j] == icnum) {
1857  return cconx;
1858  }
1859 
1860  // add in order key/mode/chan
1861  if (cconx->ikey[j] > ikey || (cconx->ikey[j] == ikey && cconx->imode[j] > imode) ||
1862  (cconx->ikey[j] == ikey && cconx->imode[j] == imode && cconx->icnum[j] > icnum)) break;
1863  }
1864 
1865  posn = j; // we will insert here
1866  cconx->nconns[i]++;
1867  totcons++;
1868 
1869  // make space for new
1870  cconx->ikey = (int *)lives_realloc(cconx->ikey, totcons * sizint);
1871  cconx->imode = (int *)lives_realloc(cconx->imode, totcons * sizint);
1872  cconx->icnum = (int *)lives_realloc(cconx->icnum, totcons * sizint);
1873 
1874  // move up 1
1875  for (j = totcons - 1; j > posn; j--) {
1876  cconx->ikey[j] = cconx->ikey[j - 1];
1877  cconx->imode[j] = cconx->imode[j - 1];
1878  cconx->icnum[j] = cconx->icnum[j - 1];
1879  }
1880 
1881  // insert at posn
1882  cconx->ikey[posn] = ikey;
1883  cconx->imode[posn] = imode;
1884  cconx->icnum[posn] = icnum;
1885 
1886  return cconx;
1887  }
1888  }
1889 
1890  // so, we have data for key/mode but this is a new channel to be mapped
1891 
1892  for (i = 0; i < cconx->nchans; i++) {
1893  totcons += cconx->nconns[i];
1894  }
1895 
1896  totcons++;
1897 
1898  cconx->nchans++;
1899  posn = cconx->nchans;
1900 
1901  // make space for new
1902  cconx->nconns = (int *)lives_realloc(cconx->nconns, posn * sizint);
1903  cconx->chans = (int *)lives_realloc(cconx->chans, posn * sizint);
1904 
1905  cconx->ikey = (int *)lives_realloc(cconx->ikey, totcons * sizint);
1906  cconx->imode = (int *)lives_realloc(cconx->imode, totcons * sizint);
1907  cconx->icnum = (int *)lives_realloc(cconx->icnum, totcons * sizint);
1908 
1909  cconx->chans[posn - 1] = ocnum;
1910 
1911  cconx->nconns[posn - 1] = 1;
1912 
1913  posn = totcons - 1;
1914 
1915  // insert at posn
1916  cconx->ikey[posn] = ikey;
1917  cconx->imode[posn] = imode;
1918  cconx->icnum[posn] = icnum;
1919 
1920 #ifdef DEBUG_CCONX
1921  g_print("added another cconx from %d %d %d to %d %d %d\n", okey, omode, ocnum, ikey, imode, icnum);
1922 #endif
1923 
1924  return cconx;
1925  }
1926 
1927  // add new
1928 
1929  totcons = cconx_get_nconns(cconx, FX_DATA_WILDCARD) + 1;
1930  cconx->nchans++;
1931 
1932  cconx->nconns = (int *)lives_realloc(cconx->chans, cconx->nchans * sizint);
1933  cconx->nconns[cconx->nchans - 1] = 1;
1934 
1935  cconx->chans = (int *)lives_realloc(cconx->chans, cconx->nchans * sizint);
1936  cconx->chans[cconx->nchans - 1] = ocnum;
1937 
1938  cconx->ikey = (int *)lives_realloc(cconx->ikey, totcons * sizint);
1939  cconx->ikey[totcons - 1] = ikey;
1940 
1941  cconx->imode = (int *)lives_realloc(cconx->imode, totcons * sizint);
1942  cconx->imode[totcons - 1] = imode;
1943 
1944  cconx->icnum = (int *)lives_realloc(cconx->icnum, totcons * sizint);
1945  cconx->icnum[totcons - 1] = icnum;
1946 
1947 #ifdef DEBUG_CCONX
1948  g_print("added new cconx from %d %d %d to %d %d %d\n", okey, omode, ocnum, ikey, imode, icnum);
1949 #endif
1950  return cconx;
1951 }
1952 
1953 
1954 void cconx_add_connection(int okey, int omode, int ocnum, int ikey, int imode, int icnum) {
1955  cconx_add_connection_private(okey, omode, ocnum, ikey, imode, icnum);
1956 }
1957 
1958 
1959 static weed_plant_t *cconx_get_out_alpha(boolean use_filt, int ikey, int imode, int icnum, int *okey, int *omode, int *ocnum) {
1960  // walk all cconx and find one which has ikey/imode/icnum as destination
1961  // then all we need do is convert the pixel_data
1962 
1963  lives_cconnect_t *cconx = mainw->cconx;
1964  weed_plant_t *inst = NULL, *filter = NULL, *orig_inst = NULL;
1965  int totcons, i, j;
1966 
1967  while (cconx) {
1968  if (!use_filt) {
1969  if (mainw->is_rendering) {
1970  inst = get_new_inst_for_keymode(cconx->okey, cconx->omode);
1971  } else {
1972  inst = rte_keymode_get_instance(cconx->okey + 1, cconx->omode);
1973  }
1974  if (!inst) {
1975  cconx = cconx->next;
1976  continue;
1977  }
1978  filter = weed_instance_get_filter(inst, TRUE);
1979  } else {
1980  inst = NULL;
1981  filter = rte_keymode_get_filter(cconx->okey + 1, cconx->omode);
1982  if (!filter) {
1983  cconx = cconx->next;
1984  continue;
1985  }
1986  }
1987  if (!weed_plant_has_leaf(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES)) {
1988  if (inst) weed_instance_unref(inst);
1989  cconx = cconx->next;
1990  continue;
1991  }
1992  orig_inst = inst;
1993  totcons = 0;
1994  j = 0;
1995  for (i = 0; i < cconx->nchans; i++) {
1996  totcons += cconx->nconns[i];
1997  for (; j < totcons; j++) {
1998  if (cconx->ikey[j] == ikey && cconx->imode[j] == imode && cconx->icnum[j] == icnum) {
1999  weed_plant_t **outchans;
2000  weed_plant_t *channel = NULL;
2001  if (use_filt) {
2002  outchans = weed_get_plantptr_array(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
2003  if (cconx->chans[i] < weed_leaf_num_elements(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES)) {
2004  channel = outchans[cconx->chans[i]];
2005  }
2006  } else {
2007  while (weed_plant_has_leaf(inst, WEED_LEAF_HOST_NEXT_INSTANCE)) inst = weed_get_plantptr_value(inst,
2009  outchans = weed_get_plantptr_array(inst, WEED_LEAF_OUT_CHANNELS, NULL);
2010  if (cconx->chans[i] < weed_leaf_num_elements(inst, WEED_LEAF_OUT_CHANNELS)) {
2011  channel = outchans[cconx->chans[i]];
2012  }
2013  }
2014  lives_free(outchans);
2015  if (okey) *okey = cconx->okey;
2016  if (omode) *omode = cconx->omode;
2017  if (ocnum) *ocnum = cconx->chans[i];
2018  if (orig_inst) weed_instance_unref(orig_inst);
2019  return channel;
2020  }
2021  }
2022  }
2023  cconx = cconx->next;
2024  weed_instance_unref(inst);
2025  }
2026 
2027  return NULL;
2028 }
2029 
2030 
2031 boolean cconx_convert_pixel_data(weed_plant_t *dchan, weed_plant_t *schan) {
2032  // convert pixel_data by possibly converting the type (palette)
2033 
2034  // return TRUE if we need to reinit the instance (because channel palette changed)
2035 
2036  // we set boolean "host_orig_pdata" if we steal the schan pdata (so do not free....)
2037 
2038  int iwidth, iheight, ipal, irow;
2039  int owidth, oheight, opal, orow, oflags;
2040  boolean pal_ok, needs_reinit = FALSE;
2041 
2042  weed_plant_t *dtmpl = weed_get_plantptr_value(dchan, WEED_LEAF_TEMPLATE, NULL);
2043 
2044  uint8_t *spdata, *dpdata;
2045 
2046  int i;
2047 
2048  ipal = weed_get_int_value(schan, WEED_LEAF_CURRENT_PALETTE, NULL);
2049  if (!weed_palette_is_alpha(ipal)) return FALSE;
2050 
2051  iwidth = weed_get_int_value(schan, WEED_LEAF_WIDTH, NULL);
2052  iheight = weed_get_int_value(schan, WEED_LEAF_HEIGHT, NULL);
2053  irow = weed_get_int_value(schan, WEED_LEAF_ROWSTRIDES, NULL);
2054 
2055  owidth = weed_get_int_value(dchan, WEED_LEAF_WIDTH, NULL);
2056  oheight = weed_get_int_value(dchan, WEED_LEAF_HEIGHT, NULL);
2057  opal = weed_get_int_value(dchan, WEED_LEAF_CURRENT_PALETTE, NULL);
2058  orow = weed_get_int_value(dchan, WEED_LEAF_ROWSTRIDES, NULL);
2059 
2060  spdata = (uint8_t *)weed_get_voidptr_value(schan, WEED_LEAF_PIXEL_DATA, NULL);
2061 
2062 #ifdef DEBUG_CCONX
2063  g_print("spd is %p %d %d %d %d %d %d %d %d\n", spdata, ipal, opal, iwidth, owidth, iheight, oheight, irow, orow);
2064  if (spdata) g_print("spd2 is %p %d\n", spdata, spdata[0]);
2065 #endif
2066  if (ipal == opal && iwidth == owidth && iheight == oheight && irow == orow) {
2068  weed_set_voidptr_value(dchan, WEED_LEAF_PIXEL_DATA, spdata);
2070  weed_set_boolean_value(dchan, WEED_LEAF_HOST_ORIG_PDATA, WEED_TRUE);
2071  return FALSE;
2072  }
2073 
2075  if (ipal == opal) pal_ok = TRUE;
2076  else {
2078  int num_palettes = weed_leaf_num_elements(dtmpl, WEED_LEAF_PALETTE_LIST);
2079  int *palettes = weed_get_int_array(dtmpl, WEED_LEAF_PALETTE_LIST, NULL);
2080  if (best_palette_match(palettes, num_palettes, ipal) == ipal) pal_ok = TRUE;
2081  else pal_ok = FALSE;
2082  oflags = weed_get_int_value(dtmpl, WEED_LEAF_FLAGS, NULL);
2083  if (ipal != opal && (oflags & WEED_CHANNEL_REINIT_ON_PALETTE_CHANGE)) needs_reinit = TRUE;
2084  lives_free(palettes);
2085  }
2086 
2088 
2089  weed_set_int_value(dchan, WEED_LEAF_WIDTH, iwidth);
2090  weed_set_int_value(dchan, WEED_LEAF_HEIGHT, iheight);
2091  weed_set_int_value(dchan, WEED_LEAF_CURRENT_PALETTE, ipal);
2092 
2093  if (pal_ok) {
2094  weed_set_voidptr_value(dchan, WEED_LEAF_PIXEL_DATA, (void *)spdata);
2095  weed_set_int_value(dchan, WEED_LEAF_ROWSTRIDES, irow);
2096 
2098  weed_set_boolean_value(dchan, WEED_LEAF_HOST_ORIG_PDATA, WEED_TRUE);
2099 #ifdef DEBUG_CCONX
2100  if (spdata) g_print("spd3 is %p %d\n", spdata, spdata[0]);
2101 #endif
2102  return FALSE;
2103  }
2104 
2106  dpdata = (uint8_t *)weed_get_voidptr_value(dchan, WEED_LEAF_PIXEL_DATA, NULL);
2107 
2108  orow = weed_get_int_value(dchan, WEED_LEAF_ROWSTRIDES, NULL);
2109 
2110  if (irow == orow) {
2111  lives_memcpy((void *)dpdata, (void *)spdata, irow * iheight);
2112  } else {
2113  int ipwidth = iwidth * weed_palette_get_bits_per_macropixel(ipal) / 8;
2114  for (i = 0; i < iheight; i++) {
2115  lives_memcpy((void *)dpdata, (void *)spdata, ipwidth);
2116  spdata += irow;
2117  dpdata += orow;
2118  }
2119  }
2120 
2121  convert_layer_palette(dchan, opal, 0);
2122 
2123  if (needs_reinit) return TRUE;
2124 
2125  return FALSE;
2126 }
2127 
2128 
2129 boolean cconx_chain_data(int key, int mode) {
2130  // ret TRUE if we should reinit inst (because of palette change)
2131 
2132  weed_plant_t *ichan, *ochan;
2133  weed_plant_t *inst = NULL;
2134 
2135  boolean needs_reinit = FALSE;
2136 
2137  int i = 0;
2138 
2139  if (key > -1) {
2140  if (mainw->is_rendering) {
2141  if ((inst = get_new_inst_for_keymode(key, mode)) == NULL) {
2142  return FALSE;
2143  }
2144  } else {
2145  if ((inst = rte_keymode_get_instance(key + 1, mode)) == NULL) {
2146  return FALSE;
2147  }
2148  }
2149  } else if (key == FX_DATA_KEY_PLAYBACK_PLUGIN) {
2150  if (!mainw->vpp || mainw->vpp->num_alpha_chans == 0) return FALSE;
2151  }
2152 
2153  while ((ichan = (key == FX_DATA_KEY_PLAYBACK_PLUGIN ? (weed_plant_t *)pp_get_chan(mainw->vpp->play_params, i)
2154  : get_enabled_channel(inst, i, TRUE))) != NULL) {
2155  if ((ochan = cconx_get_out_alpha(FALSE, key, mode, i++, NULL, NULL, NULL))) {
2156  filter_mutex_lock(key);
2157  if (cconx_convert_pixel_data(ichan, ochan)) needs_reinit = TRUE;
2158  filter_mutex_unlock(key);
2159  }
2160  }
2161  //if (inst) weed_instance_unref(inst);
2162  return needs_reinit;
2163 }
2164 
2165 
2166 boolean cconx_chain_data_internal(weed_plant_t *ichan) {
2167  // special version for compound fx internal connections
2168  boolean needs_reinit = FALSE;
2169 
2170  if (weed_plant_has_leaf(ichan, WEED_LEAF_HOST_INTERNAL_CONNECTION)) {
2171  weed_plant_t *ochan = weed_get_plantptr_value(ichan, WEED_LEAF_HOST_INTERNAL_CONNECTION, NULL);
2172  if (cconx_convert_pixel_data(ichan, ochan)) needs_reinit = TRUE;
2173  }
2174  return needs_reinit;
2175 }
2176 
2177 
2178 boolean feeds_to_video_filters(int okey, int omode) {
2179  weed_plant_t *filter;
2180  char **array;
2181  char *chlist;
2182  int nparams, niparams;
2183  int ikey, imode, i, j;
2184 
2185  filter = rte_keymode_get_filter(okey + 1, omode);
2186 
2187  nparams = num_out_params(filter);
2188 
2189  for (i = 0; i < nparams; i++) {
2190  chlist = pconx_list(okey, omode, i);
2191  niparams = get_token_count(chlist, ' ') / 4;
2192  array = lives_strsplit(chlist, " ", niparams * 4);
2193  for (j = 0; j < niparams; j += 4) {
2194  ikey = atoi(array[j]);
2195  imode = atoi(array[j + 1]);
2196  if (imode != rte_key_getmode(ikey + 1)) continue;
2197  filter = rte_keymode_get_filter(ikey + 1, imode);
2198  if (has_video_chans_in(filter, TRUE) || has_video_chans_out(filter, TRUE)) {
2199  lives_strfreev(array);
2200  lives_free(chlist);
2201  return TRUE;
2202  }
2203  }
2204  lives_strfreev(array);
2205  lives_free(chlist);
2206  }
2207 
2208  for (i = 0; i < nparams; i++) {
2209  chlist = cconx_list(okey, omode, i);
2210  niparams = get_token_count(chlist, ' ') / 3;
2211  array = lives_strsplit(chlist, " ", niparams * 3);
2212  for (j = 0; j < niparams; j += 3) {
2213  ikey = atoi(array[j]);
2214  imode = atoi(array[j + 1]);
2215  if (imode != rte_key_getmode(ikey + 1)) continue;
2216  lives_strfreev(array);
2217  lives_free(chlist);
2218  return TRUE;
2219  }
2220  lives_strfreev(array);
2221  lives_free(chlist);
2222  }
2223 
2224  return FALSE;
2225 }
2226 
2227 
2228 boolean feeds_to_audio_filters(int okey, int omode) {
2229  weed_plant_t *filter;
2230  char **array;
2231  char *chlist;
2232  int nparams, niparams;
2233  int ikey, imode;
2234  int i, j;
2235 
2236  filter = rte_keymode_get_filter(okey + 1, omode);
2237 
2238  nparams = num_out_params(filter);
2239 
2240  for (i = 0; i < nparams; i++) {
2241  chlist = pconx_list(okey, omode, i);
2242  niparams = get_token_count(chlist, ' ') / 4;
2243  array = lives_strsplit(chlist, " ", niparams * 4);
2244  for (j = 0; j < niparams; j += 4) {
2245  ikey = atoi(array[j]);
2246  if (ikey < 0) continue;
2247  imode = atoi(array[j + 1]);
2248  if (imode != rte_key_getmode(ikey + 1)) continue;
2249  filter = rte_keymode_get_filter(ikey + 1, imode);
2250  if (has_audio_chans_in(filter, TRUE) || has_audio_chans_out(filter, TRUE)) {
2251  lives_strfreev(array);
2252  lives_free(chlist);
2253  return TRUE;
2254  }
2255  }
2256  lives_strfreev(array);
2257  lives_free(chlist);
2258  }
2259 
2260  for (i = 0; i < nparams; i++) {
2261  chlist = cconx_list(okey, omode, i);
2262  niparams = get_token_count(chlist, ' ') / 3;
2263  array = lives_strsplit(chlist, " ", niparams * 3);
2264  for (j = 0; j < niparams; j += 3) {
2265  ikey = atoi(array[j]);
2266  if (ikey < 0) continue;
2267  imode = atoi(array[j + 1]);
2268  if (imode != rte_key_getmode(ikey + 1)) continue;
2269  filter = rte_keymode_get_filter(ikey + 1, imode);
2270  if (has_audio_chans_in(filter, TRUE) || has_audio_chans_out(filter, TRUE)) {
2271  lives_strfreev(array);
2272  lives_free(chlist);
2273  return TRUE;
2274  }
2275  }
2276  lives_strfreev(array);
2277  lives_free(chlist);
2278  }
2279 
2280  return FALSE;
2281 }
2282 
2283 
2285 
2286 // channel/param connection window
2287 
2288 enum {
2294 };
2295 
2296 
2297 static void disconbutton_clicked(LiVESButton * button, livespointer user_data) {
2298  // disconnect all channels/params
2299  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2300 
2301  int totparams, totchans;
2302  int pidx, pidx_last, cidx, cidx_last;
2303 
2304  register int i;
2305 
2306  totparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2307  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2308 
2309  for (i = 0; i < totchans; i++) {
2310  lives_combo_set_active_index(LIVES_COMBO(conxwp->cfxcombo[i]), 0);
2311 
2312  if (i == 0) lives_widget_set_sensitive(conxwp->del_button[i], FALSE);
2313  else {
2314  cidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->ccombo[i]), "cidx"));
2315  cidx_last = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->ccombo[i - 1]), "cidx"));
2316  lives_widget_set_sensitive(conxwp->del_button[i], cidx == cidx_last);
2317  }
2318  }
2319 
2320  for (i = 0; i < totparams; i++) {
2321  lives_combo_set_active_index(LIVES_COMBO(conxwp->pfxcombo[i]), 0);
2322 
2323  if (i == 0) lives_widget_set_sensitive(conxwp->del_button[i + totchans], FALSE);
2324  else {
2325  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[i]), "pidx"));
2326  pidx_last = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[i - 1]), "pidx"));
2327  lives_widget_set_sensitive(conxwp->del_button[i + totchans], pidx == pidx_last);
2328  }
2329  }
2330 }
2331 
2332 
2333 static void apbutton_clicked(LiVESButton * button, livespointer user_data) {
2334  // autoconnect each param with a compatible one in the target
2335  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2336 
2337  LiVESWidget *combo;
2338 
2339  LiVESTreeIter iter;
2340  LiVESTreeModel *model;
2341  LiVESTreePath *tpath;
2342 
2343  weed_plant_t **iparams, **oparams;
2344  weed_plant_t *filter, *param, *oparam;
2345 
2346  int fidx, key, mode, totchans;
2347  int niparams, ours, addn, stparam;
2348 
2349  int i, k = 1;
2350 
2351  // get filter from last connection from first parameter
2352 
2353  ours = pconx_get_numcons(conxwp, -EXTRA_PARAMS_OUT) + pconx_get_numcons(conxwp, 0) - 1;
2354 
2355  combo = (LiVESWidget *)conxwp->pfxcombo[ours];
2356 
2357  if (!lives_combo_get_active_iter(LIVES_COMBO(combo), &iter)) return;
2358  model = lives_combo_get_model(LIVES_COMBO(combo));
2359 
2360  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
2361 
2362  if (key == FX_DATA_KEY_OMC_MACRO) {
2363  // match with OMC macro
2364  //
2365  //
2366  return;
2367  }
2368 
2369  fidx = rte_keymode_get_filter_idx(key, mode);
2370 
2371  if (fidx == -1) return;
2372 
2373  tpath = lives_tree_model_get_path(model, &iter);
2374  lives_tree_model_get_iter(model, &iter, tpath);
2375 
2376  // find the receiving filter/instance
2377  filter = get_weed_filter(fidx);
2378 
2379  iparams = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
2380  niparams = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
2381 
2382 #ifdef COMBO_LIST_LIMIT
2383  if (niparams + EXTRA_PARAMS_IN > COMBO_LIST_LIMIT) {
2384  niparams = COMBO_LIST_LIMIT - EXTRA_PARAMS_IN;
2385  }
2386 #endif
2387 
2388  oparams = weed_get_plantptr_array(rte_keymode_get_filter(conxwp->okey + 1, conxwp->omode),
2389  WEED_LEAF_OUT_PARAMETER_TEMPLATES, NULL);
2390 
2391  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2392 
2393  // get first param connected
2394  stparam = conxwp->idx[totchans + ours];
2395 
2396  if (conxwp->ikeys[totchans + ours] < 0) {
2397  // first out not connected, we will add this back in
2398  ours -= pconx_get_numcons(conxwp, 0);
2399  k = 0;
2400  } else stparam++;
2401 
2402  // set all pcombo with params
2403  for (i = stparam; i < niparams; i++) {
2404 
2405  param = iparams[i];
2406 
2407  if (weed_plant_has_leaf(param, WEED_LEAF_HOST_INTERNAL_CONNECTION)) continue;
2408 
2409  if (pconx_get_out_param(TRUE, key - 1, mode, i, NULL, NULL, NULL, NULL)) continue;
2410 
2411  oparam = oparams[k];
2412 
2413  if (!params_compatible(oparam, param)) continue;
2414 
2415  addn = pconx_get_numcons(conxwp, k);
2416 
2417  ours += addn;
2418 
2419  combo = conxwp->pcombo[ours];
2420 
2421  if (conxwp->ikeys[ours + totchans] >= 0) {
2422  // add another if needed
2423  padd_clicked(conxwp->add_button[ours + totchans], (livespointer)conxwp);
2424  ours++;
2425  }
2426 
2427  combo = conxwp->pfxcombo[ours];
2428  model = lives_combo_get_model(LIVES_COMBO(combo));
2429  lives_tree_model_get_iter(model, &iter, tpath);
2430  lives_combo_set_active_iter(LIVES_COMBO(combo), &iter);
2432 
2433  lives_combo_set_active_index(LIVES_COMBO(conxwp->pcombo[ours]), i + EXTRA_PARAMS_IN);
2434 
2435  if (++k >= conxwp->num_params - EXTRA_PARAMS_OUT) break;
2436  }
2437 
2438  lives_tree_path_free(tpath);
2439 
2440  lives_free(iparams);
2441  lives_free(oparams);
2442 }
2443 
2444 
2445 static void acbutton_clicked(LiVESButton * button, livespointer user_data) {
2446  // autoconnect each channel with a compatible one in the target
2447  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2448 
2449  LiVESWidget *combo;
2450 
2451  LiVESTreeIter iter;
2452  LiVESTreeModel *model;
2453  LiVESTreePath *tpath;
2454 
2455  weed_plant_t **ichans, **ochans;
2456  weed_plant_t *filter, *chan, *ochan;
2457 
2458  int fidx, key, mode;
2459  int nichans, nochans, ours, addn, stchan;
2460 
2461  int i, j = 0, k = 1;
2462 
2463  // get filter from last connection from first parameter
2464 
2465  ours = cconx_get_numcons(conxwp, 0) - 1;
2466 
2467  combo = (LiVESWidget *)conxwp->cfxcombo[ours];
2468 
2469  if (!lives_combo_get_active_iter(LIVES_COMBO(combo), &iter)) return;
2470  model = lives_combo_get_model(LIVES_COMBO(combo));
2471 
2472  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
2473  fidx = rte_keymode_get_filter_idx(key, mode);
2474 
2475  if (fidx == -1) return;
2476 
2477  tpath = lives_tree_model_get_path(model, &iter);
2478  lives_tree_model_get_iter(model, &iter, tpath);
2479 
2480  // find the receiving filter/instance
2481  filter = get_weed_filter(fidx);
2482 
2483  ichans = weed_get_plantptr_array(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, NULL);
2484  nichans = weed_leaf_num_elements(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES);
2485 
2486  ochans = weed_get_plantptr_array(rte_keymode_get_filter(conxwp->okey + 1, conxwp->omode),
2487  WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
2488  nochans = weed_leaf_num_elements(rte_keymode_get_filter(conxwp->okey + 1, conxwp->omode),
2489  WEED_LEAF_OUT_CHANNEL_TEMPLATES);
2490 
2491  // get first param connected
2492  stchan = conxwp->idx[ours];
2493 
2494  if (conxwp->ikeys[ours] < 0) {
2495  // first out not connected, we will add this back in
2496  ours -= cconx_get_numcons(conxwp, 0);
2497  k = 0;
2498  } else {
2499  stchan++;
2500 
2501  for (i = 0; i < nichans; i++) {
2502  j++;
2503  chan = ichans[i];
2504  if (!has_alpha_palette(chan, filter)) continue;
2505  if (i == conxwp->idx[ours]) break;
2506  }
2507  }
2508 
2509  // set all ccombo with chans
2510  for (i = stchan; i < nichans; i++) {
2511 
2512  chan = ichans[i];
2513 
2514  if (!has_alpha_palette(chan, filter)) continue;
2515 
2516  if (cconx_get_out_alpha(TRUE, key - 1, mode, i, NULL, NULL, NULL)) continue;
2517 
2518  ochan = ochans[k];
2519 
2520  if (!has_alpha_palette(ochan, filter)) {
2521  if (++k >= nochans) break;
2522  continue;
2523  }
2524 
2525  addn = cconx_get_numcons(conxwp, k);
2526 
2527  ours += addn;
2528 
2529  combo = conxwp->ccombo[ours];
2530 
2531  if (conxwp->ikeys[ours] >= 0) {
2532  // add another if needed
2533  cadd_clicked(conxwp->add_button[ours], (livespointer)conxwp);
2534  ours++;
2535  }
2536 
2537  combo = conxwp->cfxcombo[ours];
2538  model = lives_combo_get_model(LIVES_COMBO(combo));
2539  lives_tree_model_get_iter(model, &iter, tpath);
2540  lives_combo_set_active_iter(LIVES_COMBO(combo), &iter);
2542 
2543  lives_combo_set_active_index(LIVES_COMBO(conxwp->ccombo[ours]), j++);
2544 
2545  if (++k >= nochans) break;
2546  }
2547 
2548  lives_tree_path_free(tpath);
2549 
2550  lives_free(ichans);
2551  lives_free(ochans);
2552 }
2553 
2554 
2555 static void padd_clicked(LiVESWidget * button, livespointer user_data) {
2556  // add another param row below the add button
2557  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2558 
2559  int totparams, totchans;
2560  int ours = -1, pidx;
2561 #if LIVES_TABLE_IS_GRID
2562  int trows;
2563 #else
2564  LiVESWidget *hbox[5], *hboxb[5], *achbox, *comhbox;
2565 #endif
2566 
2567  int i;
2568 
2569  totparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2570  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2571 
2572  for (i = 0; i < totparams; i++) {
2573  if (conxwp->add_button[i + totchans] == button) {
2574  ours = i;
2575  break;
2576  }
2577  }
2578 
2579  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[ours]), "pidx"));
2580 
2581  totparams++;
2582 
2583  conxwp->pclabel = (LiVESWidget **)lives_realloc(conxwp->pclabel, (totchans + totparams) * sizeof(LiVESWidget *));
2584 
2585  conxwp->add_button = (LiVESWidget **)lives_realloc(conxwp->add_button, (totchans + totparams) * sizeof(LiVESWidget *));
2586  conxwp->del_button = (LiVESWidget **)lives_realloc(conxwp->del_button, (totchans + totparams) * sizeof(LiVESWidget *));
2587  conxwp->clabel = (LiVESWidget **)lives_realloc(conxwp->clabel, (totchans + totparams) * sizeof(LiVESWidget *));
2588 
2589  conxwp->ikeys = (int *)lives_realloc(conxwp->ikeys, (totchans + totparams) * sizint);
2590  conxwp->imodes = (int *)lives_realloc(conxwp->imodes, (totchans + totparams) * sizint);
2591  conxwp->idx = (int *)lives_realloc(conxwp->idx, (totchans + totparams) * sizint);
2592 
2593  conxwp->pfxcombo = (LiVESWidget **)lives_realloc(conxwp->pfxcombo, totparams * sizeof(LiVESWidget *));
2594  conxwp->pcombo = (LiVESWidget **)lives_realloc(conxwp->pcombo, totparams * sizeof(LiVESWidget *));
2595 
2596  conxwp->dpp_func = (ulong *)lives_realloc(conxwp->dpp_func, totparams * sizeof(ulong));
2597  conxwp->acheck_func = (ulong *)lives_realloc(conxwp->acheck_func, totparams * sizeof(ulong));
2598 
2599  conxwp->acheck = (LiVESWidget **)lives_realloc(conxwp->acheck, totparams * sizeof(LiVESWidget *));
2600 
2601  conxwp->trowsp++;
2602 
2603  for (i = conxwp->trowsp - 3; i > ours; i--) {
2604  conxwp->del_button[i + 1] = conxwp->del_button[i];
2605  conxwp->add_button[i + 1] = conxwp->add_button[i];
2606  conxwp->clabel[i + 1] = conxwp->clabel[i];
2607  }
2608 
2609 #if !LIVES_TABLE_IS_GRID
2610  lives_table_resize(LIVES_TABLE(conxwp->tablep), conxwp->trowsp, 7);
2611 
2612  // add parent widgets to new row
2613 
2614  for (i = 0; i < 5; i++) {
2615  hbox[i] = lives_hbox_new(FALSE, 0);
2616 
2617  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox[i], i, i + 1, conxwp->trowsp - 1, conxwp->trowsp,
2618  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
2619  (LiVESAttachOptions)(0), 0, 0);
2620 
2621  }
2622 
2623  ptable_row_add_standard_widgets(conxwp, totparams - 1);
2624 #else
2625  lives_grid_insert_row(LIVES_GRID(conxwp->tablep), ours + 2);
2626  trows = conxwp->trowsp;
2627  conxwp->trowsp = ours + 3;
2628  ptable_row_add_standard_widgets(conxwp, ours + 1);
2629  conxwp->trowsp = trows;
2630 #endif
2631 
2632  // subtract 1 from trowsp because of title row
2633  for (i = conxwp->trowsp - 3; i > ours; i--) {
2634 #if !LIVES_TABLE_IS_GRID
2635 
2636  // reparent widgets from row i to row i+1
2637  hboxb[0] = lives_widget_get_parent(conxwp->pclabel[i]);
2638  lives_widget_reparent(conxwp->pclabel[i], hbox[0]);
2639  hbox[0] = hboxb[0];
2640 
2641  hboxb[2] = lives_widget_get_parent(conxwp->pfxcombo[i]);
2642  lives_widget_reparent(conxwp->pfxcombo[i], hbox[2]);
2643  hbox[2] = hboxb[2];
2644 
2645  comhbox = lives_widget_get_parent(conxwp->pcombo[i]);
2646  hboxb[3] = lives_widget_get_parent(comhbox);
2647  lives_widget_reparent(comhbox, hbox[3]);
2648  hbox[3] = hboxb[3];
2649 
2650  if (conxwp->acheck[i]) {
2651  achbox = lives_widget_get_parent(conxwp->acheck[i]);
2652  hboxb[4] = lives_widget_get_parent(achbox);
2653  lives_widget_reparent(achbox, hbox[4]);
2654  hbox[4] = hboxb[4];
2655  }
2656 
2657 #endif
2658 
2659  conxwp->pclabel[i + 1] = conxwp->pclabel[i];
2660 
2661  conxwp->pfxcombo[i + 1] = conxwp->pfxcombo[i];
2662  conxwp->pcombo[i + 1] = conxwp->pcombo[i];
2663 
2664  conxwp->acheck[i + 1] = conxwp->acheck[i];
2665  conxwp->acheck_func[i + 1] = conxwp->acheck_func[i];
2666 
2667  conxwp->ikeys[i + 1] = conxwp->ikeys[i];
2668  conxwp->imodes[i + 1] = conxwp->imodes[i];
2669  conxwp->idx[i + 1] = conxwp->idx[i];
2670 
2671  conxwp->dpp_func[i + 1] = conxwp->dpp_func[i];
2672  }
2673 
2674  ptable_row_add_variable_widgets(conxwp, ours + 1, ours + 2, pidx);
2675 
2676  conxwp->ikeys[ours + 1] = conxwp->imodes[ours + 1] = conxwp->idx[i + 1] = 0;
2677 
2678  conxwp->dispp[pidx + EXTRA_PARAMS_OUT]++;
2679 
2680  lives_widget_set_sensitive(conxwp->del_button[ours + 1], TRUE);
2682 
2683  lives_widget_show_all(conxwp->tablep);
2684 }
2685 
2686 
2687 static void pdel_clicked(LiVESWidget * button, livespointer user_data) {
2688  // remove the param row at the del button
2689  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2690 
2691  int totparams, totchans;
2692  int ours = -1, pidx;
2693 
2694 #if !LIVES_TABLE_IS_GRID
2695  LiVESWidget *comhbox;
2696  LiVESWidget *hbox[4], *hboxb[4], *achbox;
2697  int pidx_next;
2698 #endif
2699 
2700  register int i;
2701 
2702 #if !LIVES_TABLE_IS_GRID
2703  hbox[3] = NULL;
2704 #endif
2705 
2706  totparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2707  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2708 
2709  for (i = 0; i < totparams; i++) {
2710  if (conxwp->del_button[i + totchans] == button) {
2711  ours = i;
2712  break;
2713  }
2714  }
2715 
2716  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[ours]), "pidx"));
2717 
2718  lives_combo_set_active_index(LIVES_COMBO(conxwp->pfxcombo[ours]), 0);
2719 
2720  if (conxwp->dispp[pidx + EXTRA_PARAMS_OUT] <= 1) {
2721  // last one for this param, dont delete, just clear
2722  lives_widget_set_sensitive(conxwp->del_button[totchans + ours], FALSE);
2723  return;
2724  }
2725 
2726  if (ours > 0) {
2727  if (lives_widget_get_sensitive(conxwp->del_button[totchans + ours - 1])
2728  && lives_widget_get_sensitive(conxwp->add_button[totchans + ours])) {
2729  lives_widget_set_sensitive(conxwp->add_button[totchans + ours - 1], TRUE);
2730  }
2731  }
2732 
2733  conxwp->dispp[pidx + EXTRA_PARAMS_OUT]--;
2734 
2735  // force callback for pfxcombo before destroying it
2737  totparams--;
2738 
2739 #if !LIVES_TABLE_IS_GRID
2740  hbox[0] = lives_widget_get_parent(conxwp->pclabel[totchans + ours]);
2741  hbox[1] = lives_widget_get_parent(conxwp->pfxcombo[ours]);
2742 
2743  comhbox = lives_widget_get_parent(conxwp->pcombo[ours]);
2744  hbox[2] = lives_widget_get_parent(comhbox);
2745 
2746  lives_widget_destroy(conxwp->pfxcombo[ours]);
2747  lives_widget_destroy(conxwp->pcombo[ours]);
2748  lives_widget_destroy(comhbox);
2749 #endif
2750 
2751  conxwp->trowsp--;
2752 
2753  // subtract 1 from trowsp because of title row
2754  for (i = ours; i < conxwp->trowsp - 1; i++) {
2755 #if !LIVES_TABLE_IS_GRID
2756 
2757  // reparent widgets from row i to row i+1
2758 
2759  hboxb[0] = lives_widget_get_parent(conxwp->pclabel[totchans + i + 1]);
2760 
2761  if (i == ours) {
2762  pidx_next = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[i + 1]), "pidx"));
2763  if (pidx_next != pidx) {
2764  // secondary param
2765  lives_widget_destroy(conxwp->pclabel[totchans + i]);
2766  lives_widget_reparent(conxwp->pclabel[totchans + i + 1], hbox[0]);
2767  conxwp->pclabel[totchans + i] = conxwp->pclabel[totchans + i + 1];
2768  } else {
2769  // primary param
2770  lives_widget_destroy(conxwp->pclabel[totchans + i + 1]);
2771  }
2772  } else {
2773  lives_widget_reparent(conxwp->pclabel[totchans + i + 1], hbox[0]);
2774  conxwp->pclabel[totchans + i] = conxwp->pclabel[totchans + i + 1];
2775  }
2776 
2777  hbox[0] = hboxb[0];
2778 
2779  hboxb[1] = lives_widget_get_parent(conxwp->pfxcombo[i + 1]);
2780  lives_widget_reparent(conxwp->pfxcombo[i + 1], hbox[1]);
2781  hbox[1] = hboxb[1];
2782 
2783  comhbox = lives_widget_get_parent(conxwp->pcombo[i + 1]);
2784  hboxb[2] = lives_widget_get_parent(comhbox);
2785  lives_widget_reparent(comhbox, hbox[2]);
2786  hbox[2] = hboxb[2];
2787 
2788  if (conxwp->acheck[i]) {
2789  if (!hbox[3]) {
2790  achbox = lives_widget_get_parent(conxwp->acheck[i]);
2791  hbox[3] = lives_widget_get_parent(achbox);
2792  lives_widget_destroy(achbox);
2793  }
2794  achbox = lives_widget_get_parent(conxwp->acheck[i + 1]);
2795  hboxb[3] = lives_widget_get_parent(achbox);
2796  lives_widget_reparent(achbox, hbox[3]);
2797  hbox[3] = hboxb[3];
2798  }
2799 
2800  lives_widget_set_sensitive(conxwp->del_button[totchans + i],
2801  lives_widget_get_sensitive(conxwp->del_button[totchans + i + 1]));
2802 
2803 #else
2804  conxwp->add_button[i] = conxwp->add_button[i + 1];
2805  conxwp->del_button[i] = conxwp->del_button[i + 1];
2806  conxwp->clabel[i] = conxwp->clabel[i + 1];
2807  conxwp->pclabel[i] = conxwp->pclabel[i + 1];
2808 
2809  if (i == ours) {
2811  lives_label_set_text(LIVES_LABEL(conxwp->pclabel[i + 1]), lives_label_get_text(LIVES_LABEL(conxwp->pclabel[i])));
2813  }
2814 #endif
2815  conxwp->pfxcombo[i] = conxwp->pfxcombo[i + 1];
2816  conxwp->pcombo[i] = conxwp->pcombo[i + 1];
2817 
2818  conxwp->acheck[i] = conxwp->acheck[i + 1];
2819  conxwp->acheck_func[i] = conxwp->acheck_func[i + 1];
2820 
2821  conxwp->ikeys[i] = conxwp->ikeys[i + 1];
2822  conxwp->imodes[i] = conxwp->imodes[i + 1];
2823  conxwp->idx[i] = conxwp->idx[i + 1];
2824 
2825  conxwp->dpp_func[i] = conxwp->dpp_func[i + 1];
2826  }
2827 
2828 #if !LIVES_TABLE_IS_GRID
2829  lives_widget_destroy(conxwp->clabel[conxwp->trowsp - 1 + totchans]);
2830  lives_widget_destroy(conxwp->add_button[conxwp->trowsp - 1 + totchans]);
2831  lives_widget_destroy(conxwp->del_button[conxwp->trowsp - 1 + totchans]);
2832 
2833  // destroy (empty) last row parent widgets
2834  lives_widget_destroy(hbox[0]);
2835  lives_widget_destroy(hbox[1]);
2836  lives_widget_destroy(hbox[2]);
2837  lives_widget_destroy(hbox[3]);
2838 
2839  lives_table_resize(LIVES_TABLE(conxwp->tablep), conxwp->trowsp, 7);
2840 #else
2841  lives_grid_remove_row(LIVES_GRID(conxwp->tablep), ours + 1);
2842 #endif
2843 
2844  conxwp->pclabel = (LiVESWidget **)lives_realloc(conxwp->pclabel, (totchans + totparams) * sizeof(LiVESWidget *));
2845 
2846  conxwp->add_button = (LiVESWidget **)lives_realloc(conxwp->add_button, (totchans + totparams) * sizeof(LiVESWidget *));
2847  conxwp->del_button = (LiVESWidget **)lives_realloc(conxwp->del_button, (totchans + totparams) * sizeof(LiVESWidget *));
2848  conxwp->clabel = (LiVESWidget **)lives_realloc(conxwp->clabel, (totchans + totparams) * sizeof(LiVESWidget *));
2849 
2850  conxwp->ikeys = (int *)lives_realloc(conxwp->ikeys, (totchans + totparams) * sizint);
2851  conxwp->imodes = (int *)lives_realloc(conxwp->imodes, (totchans + totparams) * sizint);
2852  conxwp->idx = (int *)lives_realloc(conxwp->idx, (totchans + totparams) * sizint);
2853 
2854  conxwp->pfxcombo = (LiVESWidget **)lives_realloc(conxwp->pfxcombo, totparams * sizeof(LiVESWidget *));
2855  conxwp->pcombo = (LiVESWidget **)lives_realloc(conxwp->pcombo, totparams * sizeof(LiVESWidget *));
2856 
2857  conxwp->dpp_func = (ulong *)lives_realloc(conxwp->dpp_func, totparams * sizeof(ulong));
2858  conxwp->acheck_func = (ulong *)lives_realloc(conxwp->acheck_func, totparams * sizeof(ulong));
2859 
2860  conxwp->acheck = (LiVESWidget **)lives_realloc(conxwp->acheck, totparams * sizeof(LiVESWidget *));
2861 }
2862 
2863 
2864 static void cadd_clicked(LiVESWidget * button, livespointer user_data) {
2865  // add another channel row below the add button
2866  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2867 
2868 #if LIVES_TABLE_IS_GRID
2869  int trows;
2870 #else
2871  LiVESWidget *hbox[4], *hboxb[4], *comhbox;
2872 #endif
2873 
2874  int totparams, totchans;
2875  int ours = -1, cidx;
2876 
2877  register int i;
2878 
2879  totparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2880  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
2881 
2882  for (i = 0; i < totchans; i++) {
2883  if (conxwp->add_button[i] == button) {
2884  ours = i;
2885  break;
2886  }
2887  }
2888 
2889  cidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->cfxcombo[ours]), "cidx"));
2890 
2891  conxwp->dispc[cidx]++;
2892 
2893  totchans++;
2894 
2895  conxwp->pclabel = (LiVESWidget **)lives_realloc(conxwp->pclabel, (totchans + totparams) * sizeof(LiVESWidget *));
2896 
2897  conxwp->add_button = (LiVESWidget **)lives_realloc(conxwp->add_button, (totchans + totparams) * sizeof(LiVESWidget *));
2898  conxwp->del_button = (LiVESWidget **)lives_realloc(conxwp->del_button, (totchans + totparams) * sizeof(LiVESWidget *));
2899  conxwp->clabel = (LiVESWidget **)lives_realloc(conxwp->clabel, (totchans + totparams) * sizeof(LiVESWidget *));
2900 
2901  conxwp->ikeys = (int *)lives_realloc(conxwp->ikeys, (totchans + totparams) * sizint);
2902  conxwp->imodes = (int *)lives_realloc(conxwp->imodes, (totchans + totparams) * sizint);
2903  conxwp->idx = (int *)lives_realloc(conxwp->idx, (totchans + totparams) * sizint);
2904 
2905  conxwp->cfxcombo = (LiVESWidget **)lives_realloc(conxwp->cfxcombo, totchans * sizeof(LiVESWidget *));
2906  conxwp->ccombo = (LiVESWidget **)lives_realloc(conxwp->ccombo, totchans * sizeof(LiVESWidget *));
2907 
2908  conxwp->dpc_func = (ulong *)lives_realloc(conxwp->dpc_func, totchans * sizeof(ulong));
2909 
2910  conxwp->trowsc++;
2911 
2912  for (i = conxwp->trowsc - 3; i > ours; i--) {
2913  conxwp->del_button[i + 1] = conxwp->del_button[i];
2914  conxwp->add_button[i + 1] = conxwp->add_button[i];
2915  conxwp->clabel[i + 1] = conxwp->clabel[i];
2916  }
2917 
2918 #if !LIVES_TABLE_IS_GRID
2919  lives_table_resize(LIVES_TABLE(conxwp->tablec), conxwp->trowsc, 6);
2920 
2921  // add parent widgets to new row
2922 
2923  for (i = 0; i < 4; i++) {
2924  hbox[i] = lives_hbox_new(FALSE, 0);
2925 
2926  lives_table_attach(LIVES_TABLE(conxwp->tablec), hbox[i], i, i + 1, conxwp->trowsc - 1, conxwp->trowsc,
2927  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
2928  (LiVESAttachOptions)(0), 0, 0);
2929  }
2930 
2931  ctable_row_add_standard_widgets(conxwp, totchans - 1);
2932 #else
2933  lives_grid_insert_row(LIVES_GRID(conxwp->tablec), ours + 2);
2934  trows = conxwp->trowsc;
2935  conxwp->trowsc = ours + 3;
2936  ctable_row_add_standard_widgets(conxwp, ours + 1);
2937  conxwp->trowsc = trows;
2938 #endif
2939 
2940  // subtract 1 from trowsp because of title row
2941  for (i = conxwp->trowsc - 3; i > ours; i--) {
2942 #if !LIVES_TABLE_IS_GRID
2943 
2944  // reparent widgets from row i to row i+1
2945  hboxb[0] = lives_widget_get_parent(conxwp->pclabel[i]);
2946  lives_widget_reparent(conxwp->pclabel[i], hbox[0]);
2947  hbox[0] = hboxb[0];
2948 
2949  hboxb[2] = lives_widget_get_parent(conxwp->cfxcombo[i]);
2950  lives_widget_reparent(conxwp->cfxcombo[i], hbox[2]);
2951  hbox[2] = hboxb[2];
2952 
2953  comhbox = lives_widget_get_parent(conxwp->ccombo[i]);
2954  hboxb[3] = lives_widget_get_parent(comhbox);
2955  lives_widget_reparent(comhbox, hbox[3]);
2956  hbox[3] = hboxb[3];
2957 
2958 #endif
2959 
2960  conxwp->pclabel[i + 1] = conxwp->pclabel[i];
2961 
2962  conxwp->cfxcombo[i + 1] = conxwp->cfxcombo[i];
2963  conxwp->ccombo[i + 1] = conxwp->ccombo[i];
2964 
2965  conxwp->ikeys[i + 1] = conxwp->ikeys[i];
2966  conxwp->imodes[i + 1] = conxwp->imodes[i];
2967  conxwp->idx[i + 1] = conxwp->idx[i];
2968 
2969  conxwp->dpc_func[i + 1] = conxwp->dpc_func[i];
2970  }
2971 
2972  ctable_row_add_variable_widgets(conxwp, ours + 1, ours + 2, cidx);
2973 
2974  conxwp->ikeys[ours + 1] = -1;
2975  conxwp->imodes[ours + 1] = conxwp->idx[i + 1] = 0;
2976 
2977  conxwp->dispc[cidx]++;
2978 
2979  lives_widget_set_sensitive(conxwp->del_button[ours + 1], TRUE);
2981 
2982  lives_widget_show_all(conxwp->tablec);
2983 }
2984 
2985 
2986 static void cdel_clicked(LiVESWidget * button, livespointer user_data) {
2987  // remove the channel row at the del button
2988  lives_conx_w *conxwp = (lives_conx_w *)user_data;
2989 
2990  int totparams, totchans;
2991  int ours = -1, cidx;
2992 
2993 #if !LIVES_TABLE_IS_GRID
2994  LiVESWidget *hbox[3], *comhbox;
2995  LiVESWidget *hboxb[3];
2996  int cidx_next;
2997 #endif
2998 
2999  register int i;
3000 
3001  totparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3002  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3003 
3004  for (i = 0; i < totchans; i++) {
3005  if (conxwp->del_button[i] == button) {
3006  ours = i;
3007  break;
3008  }
3009  }
3010 
3011  cidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->ccombo[ours]), "cidx"));
3012 
3013  lives_combo_set_active_index(LIVES_COMBO(conxwp->cfxcombo[ours]), 0);
3014 
3015  if (conxwp->dispc[cidx] <= 1) {
3016  // last one, dont delete, just clear
3018  return;
3019  }
3020 
3021  // force callback for cfxcombo before destroying it
3023 
3024  conxwp->dispc[cidx]--;
3025 
3026  totchans--;
3027 
3028 #if !LIVES_TABLE_IS_GRID
3029  hbox[0] = lives_widget_get_parent(conxwp->pclabel[ours]);
3030  hbox[1] = lives_widget_get_parent(conxwp->cfxcombo[ours]);
3031 
3032  comhbox = lives_widget_get_parent(conxwp->ccombo[ours]);
3033  hbox[2] = lives_widget_get_parent(comhbox);
3034 
3035  lives_widget_destroy(conxwp->cfxcombo[ours]);
3036  lives_widget_destroy(conxwp->ccombo[ours]);
3037  lives_widget_destroy(comhbox);
3038 #endif
3039 
3040  conxwp->trowsc--;
3041 
3042  // subtract 1 from trowsc because of title row
3043  for (i = ours; i < conxwp->trowsc - 1; i++) {
3044 #if !LIVES_TABLE_IS_GRID
3045 
3046  // reparent widgets from row i to row i+1
3047 
3048  hboxb[0] = lives_widget_get_parent(conxwp->pclabel[i + 1]);
3049 
3050  if (i == ours) {
3051  cidx_next = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->ccombo[i + 1]), "cidx"));
3052  if (cidx_next != cidx) {
3053  // secondary chan
3054  lives_widget_destroy(conxwp->pclabel[i]);
3055  lives_widget_reparent(conxwp->pclabel[i + 1], hbox[0]);
3056  conxwp->pclabel[i] = conxwp->pclabel[i + 1];
3057  } else {
3058  // primary chan
3059  lives_widget_destroy(conxwp->pclabel[i + 1]);
3060  }
3061  } else {
3062  lives_widget_reparent(conxwp->pclabel[i + 1], hbox[0]);
3063  conxwp->pclabel[i] = conxwp->pclabel[i + 1];
3064  }
3065 
3066  hbox[0] = hboxb[0];
3067 
3068  hboxb[1] = lives_widget_get_parent(conxwp->cfxcombo[i + 1]);
3069  lives_widget_reparent(conxwp->cfxcombo[i + 1], hbox[1]);
3070  hbox[1] = hboxb[1];
3071 
3072  comhbox = lives_widget_get_parent(conxwp->ccombo[i + 1]);
3073  hboxb[2] = lives_widget_get_parent(comhbox);
3074  lives_widget_reparent(comhbox, hbox[2]);
3075  hbox[2] = hboxb[2];
3076 
3078  lives_widget_get_sensitive(conxwp->del_button[i + 1]));
3079 
3080 #else
3081  conxwp->add_button[i] = conxwp->add_button[i + 1];
3082  conxwp->del_button[i] = conxwp->del_button[i + 1];
3083  conxwp->clabel[i] = conxwp->clabel[i + 1];
3084  conxwp->pclabel[i] = conxwp->pclabel[i + 1];
3085 
3086  if (i == ours) {
3088  lives_label_set_text(LIVES_LABEL(conxwp->pclabel[i + 1]), lives_label_get_text(LIVES_LABEL(conxwp->pclabel[i])));
3090  }
3091 #endif
3092  conxwp->cfxcombo[i] = conxwp->cfxcombo[i + 1];
3093  conxwp->ccombo[i] = conxwp->ccombo[i + 1];
3094 
3095  conxwp->ikeys[i] = conxwp->ikeys[i + 1];
3096  conxwp->imodes[i] = conxwp->imodes[i + 1];
3097  conxwp->idx[i] = conxwp->idx[i + 1];
3098 
3099  conxwp->dpc_func[i] = conxwp->dpc_func[i + 1];
3100  }
3101 
3102 #if !LIVES_TABLE_IS_GRID
3103  lives_widget_destroy(conxwp->clabel[conxwp->trowsc - 1]);
3104  lives_widget_destroy(conxwp->add_button[conxwp->trowsc - 1]);
3105  lives_widget_destroy(conxwp->del_button[conxwp->trowsc - 1]);
3106 
3107  // destroy (empty) last row parent widgets
3108  lives_widget_destroy(hbox[0]);
3109  lives_widget_destroy(hbox[1]);
3110  lives_widget_destroy(hbox[2]);
3111 
3112  lives_table_resize(LIVES_TABLE(conxwp->tablec), conxwp->trowsc, 6);
3113 #else
3114  lives_grid_remove_row(LIVES_GRID(conxwp->tablec), ours + 1);
3115 #endif
3116 
3117  if (ours == totchans) {
3118  if (lives_widget_get_sensitive(conxwp->del_button[ours - 1]))
3119  lives_widget_set_sensitive(conxwp->add_button[ours - 1], TRUE);
3120  }
3121 
3122  conxwp->pclabel = (LiVESWidget **)lives_realloc(conxwp->pclabel, (totchans + totparams) * sizeof(LiVESWidget *));
3123 
3124  conxwp->add_button = (LiVESWidget **)lives_realloc(conxwp->add_button, (totchans + totparams) * sizeof(LiVESWidget *));
3125  conxwp->del_button = (LiVESWidget **)lives_realloc(conxwp->del_button, (totchans + totparams) * sizeof(LiVESWidget *));
3126  conxwp->clabel = (LiVESWidget **)lives_realloc(conxwp->clabel, (totchans + totparams) * sizeof(LiVESWidget *));
3127 
3128  conxwp->ikeys = (int *)lives_realloc(conxwp->ikeys, (totchans + totparams) * sizint);
3129  conxwp->imodes = (int *)lives_realloc(conxwp->imodes, (totchans + totparams) * sizint);
3130  conxwp->idx = (int *)lives_realloc(conxwp->idx, (totchans + totparams) * sizint);
3131 
3132  conxwp->cfxcombo = (LiVESWidget **)lives_realloc(conxwp->cfxcombo, totchans * sizeof(LiVESWidget *));
3133  conxwp->ccombo = (LiVESWidget **)lives_realloc(conxwp->ccombo, totchans * sizeof(LiVESWidget *));
3134 
3135  conxwp->dpc_func = (ulong *)lives_realloc(conxwp->dpc_func, totchans * sizeof(ulong));
3136 }
3137 
3138 
3139 static void dfxc_changed(LiVESWidget * combo, livespointer user_data) {
3140  lives_conx_w *conxw = (lives_conx_w *)user_data;
3141 
3142  LiVESTreeIter iter;
3143  LiVESTreeModel *model;
3144 
3145  weed_plant_t **ichans;
3146  weed_plant_t *filter, *chan;
3147 
3148  LiVESList *clist = NULL;
3149 
3150  char *channame;
3151 
3152  int fidx, cidx, key, mode;
3153  int nichans, nchans, ours = -1;
3154 
3155  int i, j = 0;
3156 
3157  if (!lives_combo_get_active_iter(LIVES_COMBO(combo), &iter)) return;
3158  model = lives_combo_get_model(LIVES_COMBO(combo));
3159 
3160  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
3161  fidx = rte_keymode_get_filter_idx(key, mode);
3162 
3163  nchans = cconx_get_numcons(conxw, FX_DATA_WILDCARD);
3164 
3165  for (i = 0; i < nchans; i++) {
3166  if (conxw->cfxcombo[i] == combo) {
3167  ours = i;
3168  break;
3169  }
3170  }
3171 
3172  cidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "cidx"));
3173 
3174  if (fidx == -1) {
3175  lives_combo_set_active_string(LIVES_COMBO(conxw->ccombo[ours]), "");
3176  lives_signal_handler_block(conxw->ccombo[ours], conxw->dpc_func[ours]);
3177  lives_combo_populate(LIVES_COMBO(conxw->ccombo[ours]), NULL);
3178  lives_signal_handler_unblock(conxw->ccombo[ours], conxw->dpc_func[ours]);
3179  if (conxw->acbutton && cconx_get_nconns(conxw->cconx, 0) == 0 && cidx == 0)
3181  lives_widget_set_sensitive(conxw->ccombo[ours], FALSE);
3182  return;
3183  }
3184 
3185  // find the receiving filter/instance
3186  filter = get_weed_filter(fidx);
3187 
3188  ichans = weed_get_plantptr_array(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, NULL);
3189  nichans = weed_leaf_num_elements(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES);
3190 
3191  // populate all ccombo with channels
3192  for (i = 0; i < nichans; i++) {
3193  chan = ichans[j++];
3194 
3195  if (!has_alpha_palette(chan, filter)) continue;
3196 
3197  channame = get_chan_name(chan, i, TRUE);
3198  clist = lives_list_append(clist, channame);
3199  }
3200 
3201  lives_free(ichans);
3202 
3203  lives_combo_set_active_string(LIVES_COMBO(conxw->ccombo[ours]), "");
3204  lives_signal_handler_block(conxw->ccombo[ours], conxw->dpc_func[ours]);
3205  lives_combo_populate(LIVES_COMBO(conxw->ccombo[ours]), clist);
3206  lives_signal_handler_unblock(conxw->ccombo[ours], conxw->dpc_func[ours]);
3207 
3208  if (cidx == 0) if (conxw->acbutton) lives_widget_set_sensitive(conxw->acbutton, TRUE);
3209  lives_widget_set_sensitive(conxw->ccombo[ours], TRUE);
3210 
3211  lives_list_free_all(&clist);
3212 }
3213 
3214 
3215 static void dfxp_changed(LiVESWidget * combo, livespointer user_data) {
3216  // filter was changed
3217 
3218  lives_conx_w *conxwp = (lives_conx_w *)user_data;
3219 
3220  LiVESTreeIter iter;
3221  LiVESTreeModel *model;
3222 
3223  weed_plant_t **iparams = NULL;
3224  weed_plant_t *filter, *param;
3225 
3226  LiVESList *plist = NULL;
3227 
3228  char *paramname;
3229 
3230  char *ptype, *range;
3231  char *array_type, *text;
3232 
3233  int defelems, pflags, stype;
3234  int fidx, key, mode, pidx;
3235  int niparams = 0, nparams;
3236  int ours = -1, i, j = 0;
3237 
3238  if (!lives_combo_get_active_iter(LIVES_COMBO(combo), &iter)) {
3239  return;
3240  }
3241 
3242  nparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3243 
3244  for (i = 0; i < nparams; i++) {
3245  if (conxwp->pfxcombo[i] == combo) {
3246  ours = i;
3247  break;
3248  }
3249  }
3250 
3251  model = lives_combo_get_model(LIVES_COMBO(combo));
3252 
3253  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
3254 
3255  if (key == FX_DATA_KEY_OMC_MACRO) {
3256  // match with OMC macro
3257  int nmatchparams = 0;
3258  weed_plant_t *ofilter;
3259  LiVESWidget *fxcombo = conxwp->pcombo[ours];
3260 
3261  // get type for out_param
3262  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(fxcombo), "pidx"));
3263  ofilter = conxwp->filter;
3264 
3265  if (pidx >= 0) {
3266  weed_plant_t **oparams = weed_get_plantptr_array(ofilter, WEED_LEAF_OUT_PARAMETER_TEMPLATES, NULL);
3267  weed_plant_t *oparam = oparams[pidx];
3268  lives_free(oparams);
3269  stype = weed_leaf_seed_type(oparam, WEED_LEAF_DEFAULT);
3270  } else {
3271  // invent an "ACTIVATED" param
3272  stype = WEED_SEED_BOOLEAN;
3273  }
3274 
3275  // check omc_macros[mode]; show all params with matching type
3276 
3277  // TODO...
3278 
3279  // if nothing matched, then
3280 
3281  // if out is boolean, we can link to ACTIVATE, we can choose FALSE -> TRUE (TODO: or TRUE -> FALSE)
3282  //
3283  if (nmatchparams == 0 && stype == WEED_SEED_BOOLEAN) {
3284  text = lives_strdup_printf(_("False to True -> TRIGGER (%s)"), weed_seed_type_to_text(WEED_SEED_BOOLEAN));
3285  plist = lives_list_append(plist, text);
3286  }
3287  } else {
3288  fidx = rte_keymode_get_filter_idx(key, mode);
3289 
3290  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "pidx"));
3291 
3292  if (fidx == -1) {
3293  // connection deleted
3294  LiVESWidget *acheck = conxwp->acheck[ours];
3295  if (acheck) {
3296  lives_signal_handler_block(acheck, conxwp->acheck_func[ours]);
3297  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(acheck), FALSE);
3299  lives_signal_handler_unblock(acheck, conxwp->acheck_func[ours]);
3300  }
3301 
3302  lives_combo_set_active_string(LIVES_COMBO(conxwp->pcombo[ours]), "");
3303  lives_signal_handler_block(conxwp->pcombo[ours], conxwp->dpp_func[ours]);
3304  lives_combo_populate(LIVES_COMBO(conxwp->pcombo[ours]), NULL);
3305  lives_signal_handler_unblock(conxwp->pcombo[ours], conxwp->dpp_func[ours]);
3306 
3307  if (conxwp->apbutton && pconx_get_nconns(conxwp->pconx, 0) == 0 && pidx == 0)
3309 
3310  lives_widget_set_sensitive(conxwp->pcombo[ours], FALSE);
3311 
3312  return;
3313  }
3314 
3315  // find the receiving filter/instance
3316  filter = get_weed_filter(fidx);
3317 
3318  if (weed_plant_has_leaf(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES)) {
3319  iparams = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
3320  niparams = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
3321 #ifdef COMBO_LIST_LIMIT
3322  if (niparams + EXTRA_PARAMS_IN > COMBO_LIST_LIMIT) {
3323  niparams = COMBO_LIST_LIMIT - EXTRA_PARAMS_IN;
3324  }
3325 #endif
3326  }
3327 
3328  // populate pcombo with all in params
3329  for (i = -EXTRA_PARAMS_IN; i < niparams; i++) {
3330  if (i == FX_DATA_PARAM_ACTIVE) {
3331  ptype = weed_seed_type_to_text(WEED_SEED_BOOLEAN);
3332  text = lives_strdup_printf(_("ACTIVATE (%s)"), ptype);
3333  } else {
3334  param = iparams[j++];
3335 
3336  if (weed_plant_has_leaf(param, WEED_LEAF_HOST_INTERNAL_CONNECTION)) continue;
3337 
3338  if (weed_plant_has_leaf(param, WEED_LEAF_GROUP) && weed_get_int_value(param, WEED_LEAF_GROUP, NULL) != 0) continue;
3339 
3340  paramname = get_param_name(param, j - 1, TRUE);
3341 
3342  ptype = weed_seed_type_to_text((stype = weed_leaf_seed_type(param, WEED_LEAF_DEFAULT)));
3343 
3344  pflags = weed_get_int_value(param, WEED_LEAF_FLAGS, NULL);
3345 
3346  if (pflags & WEED_PARAMETER_VARIABLE_SIZE) array_type = lives_strdup("[]");
3347  else if ((defelems = weed_leaf_num_elements(param, WEED_LEAF_DEFAULT)) > 1)
3348  array_type = lives_strdup_printf("[%d]", defelems);
3349  else array_type = lives_strdup("");
3350 
3351  if (weed_plant_has_leaf(param, WEED_LEAF_MAX) && weed_plant_has_leaf(param, WEED_LEAF_MIN)) {
3352  if (stype == WEED_SEED_INT) {
3353  range = lives_strdup_printf("Range: %d to %d",
3354  weed_get_int_value(param, WEED_LEAF_MIN, NULL), weed_get_int_value(param,
3355  WEED_LEAF_MAX, NULL));
3356  } else if (stype == WEED_SEED_DOUBLE) {
3357  range = lives_strdup_printf("Range: %f to %f",
3358  weed_get_double_value(param, WEED_LEAF_MIN, NULL), weed_get_double_value(param,
3359  WEED_LEAF_MAX, NULL));
3360  } else range = lives_strdup("");
3361  } else range = lives_strdup("");
3362 
3363  text = lives_strdup_printf("%s\n (%s%s) %s", paramname, ptype, array_type, range);
3364  lives_free(paramname);
3365  lives_free(array_type);
3366  lives_free(range);
3367  }
3368  lives_free(ptype);
3369  plist = lives_list_append(plist, text);
3370  }
3371 
3372  if (iparams) lives_free(iparams);
3373  }
3374 
3375  lives_combo_set_active_string(LIVES_COMBO(conxwp->pcombo[ours]), "");
3376  lives_signal_handler_block(conxwp->pcombo[ours], conxwp->dpp_func[ours]);
3377  lives_combo_populate(LIVES_COMBO(conxwp->pcombo[ours]), plist);
3378  lives_signal_handler_unblock(conxwp->pcombo[ours], conxwp->dpp_func[ours]);
3379 
3380  //lives_combo_set_active_string(LIVES_COMBO(conxwp->pcombo[ours]), "");
3381 
3382  if (!pidx) if (conxwp->apbutton) lives_widget_set_sensitive(conxwp->apbutton, TRUE);
3383 
3384  lives_widget_set_sensitive(conxwp->pcombo[ours], TRUE);
3385 
3386  lives_list_free_all(&plist);
3387 }
3388 
3389 
3390 int pconx_check_connection(weed_plant_t *ofilter, int opnum, int ikey, int imode, int ipnum, boolean setup,
3391  weed_plant_t **iparam_ret, int *idx_ret, int *okey, int *omode, int *oopnum) {
3392  weed_plant_t **oparams = NULL, **iparams;
3393  weed_plant_t *oparam, *iparam = NULL;
3394 
3395  int niparams, idx, i, j = 0;
3396 
3397  // TODO :: key FX_DATA_KEY_OMC_MACRO == OMC Macro
3398 
3399  if (opnum >= 0) {
3400  oparams = weed_get_plantptr_array(ofilter, WEED_LEAF_OUT_PARAMETER_TEMPLATES, NULL);
3401  oparam = oparams[opnum];
3402  lives_free(oparams);
3403  } else {
3404  // invent an "ACTIVATED" param
3405  pthread_mutex_lock(&mainw->fxd_active_mutex);
3406  if (active_dummy && WEED_PLANT_IS_PARAMETER(active_dummy)) {
3407  weed_plant_free(active_dummy);
3408  active_dummy = NULL;
3409  }
3410  if (!active_dummy) {
3411  active_dummy = weed_plant_new(WEED_PLANT_PARAMETER_TEMPLATE);
3412  weed_set_boolean_value(active_dummy, WEED_LEAF_DEFAULT, WEED_FALSE);
3413  }
3414  oparam = active_dummy;
3415  pthread_mutex_unlock(&mainw->fxd_active_mutex);
3416  }
3417 
3418  if (ipnum == FX_DATA_PARAM_ACTIVE) {
3419  // invent an "ACTIVATE" param
3420  pthread_mutex_lock(&mainw->fxd_active_mutex);
3421  if (active_dummy && WEED_PLANT_IS_PARAMETER(active_dummy)) {
3422  weed_plant_free(active_dummy);
3423  active_dummy = NULL;
3424  }
3425  if (!active_dummy) {
3426  active_dummy = weed_plant_new(WEED_PLANT_PARAMETER_TEMPLATE);
3427  weed_set_boolean_value(active_dummy, WEED_LEAF_DEFAULT, WEED_FALSE);
3428  }
3429  idx = ipnum;
3430  iparam = active_dummy;
3431  pthread_mutex_unlock(&mainw->fxd_active_mutex);
3432  } else {
3433  // find the receiving filter/instance
3434  int fidx = rte_keymode_get_filter_idx(ikey, imode);
3435  weed_plant_t *filter = get_weed_filter(fidx);
3436 
3437  iparams = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
3438  niparams = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
3439 
3440  for (i = 0; i < niparams; i++) {
3441  iparam = iparams[i];
3442  if (weed_plant_has_leaf(iparam, WEED_LEAF_HOST_INTERNAL_CONNECTION)) continue;
3443  if (weed_plant_has_leaf(iparam, WEED_LEAF_GROUP) && weed_get_int_value(iparam, WEED_LEAF_GROUP, NULL) != 0) continue;
3444  if (j == ipnum) break;
3445  j++;
3446  }
3447  idx = i;
3448  lives_free(iparams);
3449  }
3450 
3451  if (iparam_ret) *iparam_ret = iparam;
3452  if (idx_ret) *idx_ret = idx;
3453 
3454  if (!setup) {
3455  if (pconx_get_out_param(TRUE, ikey, imode, ipnum, okey, omode, oopnum, NULL)) {
3456  // dest param already has a connection
3457  return -1;
3458  }
3459  }
3460 
3461  if (!params_compatible(oparam, iparam)) {
3462  return -2;
3463  }
3464 
3465  return 0;
3466 }
3467 
3468 
3469 static void dpp_changed(LiVESWidget * combo, livespointer user_data) {
3470  // receiver param was set
3471 
3472  // 1) check if compatible
3473 
3474  // 2) maybe enable autoscale
3475 
3476  // 3) set text to just param name
3477  weed_plant_t *iparam;
3478 
3479  lives_conx_w *conxwp = (lives_conx_w *)user_data;
3480 
3481  LiVESWidget *acheck = NULL;
3482  LiVESWidget *fxcombo;
3483 
3484  LiVESTreeModel *model;
3485 
3486  LiVESTreeIter iter;
3487 
3488  char *paramname;
3489 
3490  boolean hasone = FALSE;
3491  boolean setup = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "setup"));
3492 
3493  int nparams, nchans;
3494  int okey, omode, opnum, ikey;
3495 
3496  int pidx, key, mode, ours = -1, ret;
3497  int idx = lives_combo_get_active_index(LIVES_COMBO(combo));
3498  int i, j;
3499 
3500  nparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3501  nchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3502 
3503  for (i = 0; i < nparams; i++) {
3504  if (conxwp->pcombo[i] == combo) {
3505  ours = i;
3506  break;
3507  }
3508  }
3509 
3510  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "pidx"));
3511 
3512  if (idx == -1) {
3513  // connection deleted
3514  if (setup) return;
3515  for (i = 0; i < nchans; i++) {
3516  if (lives_combo_get_active_index(LIVES_COMBO(conxwp->ccombo[i])) > -1) {
3517  hasone = TRUE;
3518  break;
3519  }
3520  }
3521  if (!hasone) {
3522  for (i = 0; i < nparams; i++) {
3523  if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[i]), "idx")) > -1) {
3524  hasone = TRUE;
3525  break;
3526  }
3527  }
3528  }
3529 
3530  if (!hasone) lives_widget_set_sensitive(conxwp->disconbutton, FALSE);
3531 
3532  ikey = conxwp->ikeys[nchans + ours];
3533 
3534  if (ikey >= 0) {
3535  //if (ikey > 0) ikey--;
3536  pconx_delete(conxwp->okey, conxwp->omode, pidx, ikey, conxwp->imodes[nchans + ours],
3537  conxwp->idx[nchans + ours]);
3538 
3539  conxwp->pconx = pconx_find(conxwp->okey, conxwp->omode);
3540  }
3541  conxwp->ikeys[nchans + ours] = -1;
3542  conxwp->imodes[nchans + ours] = 0;
3543  conxwp->idx[nchans + ours] = 0;
3544 
3545  lives_widget_set_sensitive(conxwp->del_button[nchans + ours], FALSE);
3546  lives_widget_set_sensitive(conxwp->add_button[nchans + ours], FALSE);
3547 
3548  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo), "idx", LIVES_INT_TO_POINTER(idx));
3549 
3550  return;
3551  }
3552 
3553  fxcombo = conxwp->pfxcombo[ours];
3554 
3555  if (!lives_combo_get_active_iter(LIVES_COMBO(fxcombo), &iter)) return;
3556 
3557  model = lives_combo_get_model(LIVES_COMBO(fxcombo));
3558 
3559  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
3560 
3561  idx -= EXTRA_PARAMS_IN;
3562 
3564  ret = pconx_check_connection(conxwp->filter, pidx, key, mode, idx, setup, &iparam, &j, &okey, &omode, &opnum);
3565 
3566  if (ret == -2) {
3567  do_param_incompatible_error(conxwp);
3568  lives_combo_set_active_string(LIVES_COMBO(combo), "");
3569  return;
3570  }
3571  if (ret == -1) {
3572  if (!do_param_connected_query(conxwp, okey, omode, opnum, conxwp->okey == okey)) {
3573  lives_combo_set_active_string(LIVES_COMBO(combo), "");
3574  return;
3575  } else {
3576  pconx_delete(okey, omode, opnum, key, mode, idx);
3577  }
3578  }
3579 
3581 
3582  idx += EXTRA_PARAMS_IN;
3583 
3584  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo), "idx", LIVES_INT_TO_POINTER(idx));
3585 
3586  acheck = conxwp->acheck[ours];
3587 
3588  if (acheck) {
3589  boolean hasrange = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(acheck), "available"));
3590 
3591  lives_signal_handler_block(acheck, conxwp->acheck_func[ours]);
3592  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(acheck), FALSE);
3593  lives_signal_handler_unblock(acheck, conxwp->acheck_func[ours]);
3594 
3595  if (hasrange) {
3597  if (lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(conxwp->allcheckc))) {
3598  lives_signal_handler_block(acheck, conxwp->acheck_func[ours]);
3599  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(acheck), TRUE);
3600  lives_signal_handler_unblock(acheck, conxwp->acheck_func[ours]);
3601  }
3602  }
3603  }
3604 
3605  if (iparam == active_dummy) {
3606  if (key == FX_DATA_KEY_OMC_MACRO) paramname = (_("TRIGGER"));
3607  else paramname = (_("ACTIVATE"));
3608  } else paramname = get_param_name(iparam, idx - EXTRA_PARAMS_IN, TRUE);
3609 
3610  lives_signal_handler_block(combo, conxwp->dpp_func[ours]);
3611  lives_combo_set_active_string(LIVES_COMBO(combo), paramname);
3612  lives_signal_handler_unblock(combo, conxwp->dpp_func[ours]);
3613 
3614  lives_free(paramname);
3615 
3616  lives_widget_set_sensitive(conxwp->del_button[nchans + ours], TRUE);
3617 
3618  if (setup) return;
3619 
3620  lives_widget_set_sensitive(conxwp->add_button[nchans + ours], TRUE);
3621 
3622  conxwp->pconx = pconx_add_connection_private(conxwp->okey, conxwp->omode, pidx, key - 1, mode, j,
3623  acheck ? lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(acheck)) : FALSE);
3624 
3625  conxwp->ikeys[nchans + ours] = key;
3626  conxwp->imodes[nchans + ours] = mode;
3627  conxwp->idx[nchans + ours] = j;
3628 
3630 }
3631 
3632 
3633 int cconx_check_connection(int ikey, int imode, int icnum, boolean setup, weed_plant_t **ichan_ret, int *idx_ret,
3634  int *okey, int *omode, int *ocnum) {
3635  weed_plant_t **ichans;
3636  weed_plant_t *filter, *ichan = NULL;
3637 
3638  int fidx, idx, nichans, i, j = 0;
3639 
3640  fidx = rte_keymode_get_filter_idx(ikey + 1, imode);
3641 
3642  // find the receiving filter/instance
3643  filter = get_weed_filter(fidx);
3644 
3645  ichans = weed_get_plantptr_array(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, NULL);
3646  nichans = weed_leaf_num_elements(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES);
3647 
3648  // find actual in channel number from list of alpha channels
3649  for (i = 0; i < nichans; i++) {
3650  ichan = ichans[i];
3651  if (!has_alpha_palette(ichan, filter)) continue;
3652  if (j == icnum) break;
3653  j++;
3654  }
3655 
3656  lives_free(ichans);
3657 
3658  idx = i;
3659 
3660  if (ichan_ret) *ichan_ret = ichan;
3661  if (idx_ret) *idx_ret = idx;
3662 
3663  if (!setup) {
3664  if (cconx_get_out_alpha(TRUE, ikey, imode, i, okey, omode, ocnum)) {
3665  // dest chan already has a connection
3666  return -1;
3667  }
3668  }
3669  return 0;
3670 }
3671 
3672 
3673 static void dpc_changed(LiVESWidget * combo, livespointer user_data) {
3674  lives_conx_w *conxwp = (lives_conx_w *)user_data;
3675  weed_plant_t *ichan;
3676  LiVESTreeModel *model;
3677  LiVESTreeIter iter;
3678  LiVESWidget *fxcombo;
3679 
3680  char *channame;
3681 
3682  boolean hasone = FALSE;
3683  boolean setup = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "setup"));
3684 
3685  int nchans, nparams;
3686  int key, mode, cidx, ours = -1, ret, j;
3687  int okey, omode, ocnum;
3688  int idx = lives_combo_get_active_index(LIVES_COMBO(combo));
3689  int i;
3690 
3691  nchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3692  nparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3693 
3694  for (i = 0; i < nchans; i++) {
3695  if (conxwp->ccombo[i] == combo) {
3696  ours = i;
3697  break;
3698  }
3699  }
3700 
3701  cidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo), "cidx"));
3702 
3703  if (idx == -1) {
3704  for (i = 0; i < nchans; i++) {
3705  if (lives_combo_get_active_index(LIVES_COMBO(conxwp->ccombo[i])) > -1) {
3706  hasone = TRUE;
3707  break;
3708  }
3709  }
3710  if (!hasone) for (i = 0; i < nparams; i++) {
3711  if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[i]), "idx")) > -1) {
3712  hasone = TRUE;
3713  break;
3714  }
3715  }
3716 
3717  if (!hasone) lives_widget_set_sensitive(conxwp->disconbutton, FALSE);
3718 
3719  if (conxwp->ikeys[ours] >= 0) cconx_delete(conxwp->okey, conxwp->omode, cidx,
3720  conxwp->ikeys[ours], conxwp->imodes[ours], conxwp->idx[ours]);
3721  conxwp->cconx = cconx_find(conxwp->okey, conxwp->omode);
3722 
3723  conxwp->ikeys[ours] = -1;
3724  conxwp->imodes[ours] = 0;
3725  conxwp->idx[ours] = 0;
3726 
3728 
3729  return;
3730  }
3731 
3732  fxcombo = conxwp->cfxcombo[ours];
3733 
3734  if (!lives_combo_get_active_iter(LIVES_COMBO(fxcombo), &iter)) return;
3735 
3736  model = lives_combo_get_model(LIVES_COMBO(fxcombo));
3737  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
3738 
3739  // check if connection can be made
3740  ret = cconx_check_connection(key, mode, idx, setup, &ichan, &j, &okey, &omode, &ocnum);
3741 
3742  if (ret == -1) {
3743  // dest chan already has a connection
3744  if (!do_chan_connected_query(conxwp, okey, omode, ocnum, conxwp->okey == okey)) {
3745  lives_combo_set_active_string(LIVES_COMBO(combo), "");
3746  return;
3747  } else {
3748  cconx_delete(okey, omode, ocnum, key, mode, idx);
3749  }
3750  }
3751 
3752  lives_signal_handler_block(combo, conxwp->dpc_func[ours]);
3753  channame = get_chan_name(ichan, idx, TRUE);
3754  lives_combo_set_active_string(LIVES_COMBO(combo), channame);
3755  lives_signal_handler_unblock(combo, conxwp->dpc_func[ours]);
3756 
3757  lives_free(channame);
3758 
3759  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo), "idx", LIVES_INT_TO_POINTER(idx));
3760 
3761  lives_widget_set_sensitive(conxwp->del_button[ours], TRUE);
3762 
3763  if (setup) return;
3764 
3765  conxwp->cconx = cconx_add_connection_private(conxwp->okey, conxwp->omode, cidx, key - 1, mode, j);
3766 
3767  conxwp->ikeys[ours] = key;
3768  conxwp->imodes[ours] = mode;
3769  conxwp->idx[ours] = j;
3770 
3772 }
3773 
3774 
3775 static void on_allcheck_toggled(LiVESToggleButton * button, livespointer user_data) {
3776  lives_conx_w *conxwp = (lives_conx_w *)user_data;
3777  boolean on = lives_toggle_button_get_active(button);
3778  int nparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3779 
3780  for (int i = EXTRA_PARAMS_OUT; i < nparams; i++) {
3781  if (conxwp->acheck[i]) {
3782  if (lives_widget_is_sensitive(conxwp->acheck[i]))
3783  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(conxwp->acheck[i]), on);
3784  }
3785  }
3786 }
3787 
3788 
3789 static void on_acheck_toggled(LiVESToggleButton * acheck, livespointer user_data) {
3790  lives_conx_w *conxwp = (lives_conx_w *)user_data;
3791  weed_plant_t **iparams;
3792  weed_plant_t *param, *filter;
3793  LiVESTreeModel *model;
3794  LiVESTreeIter iter;
3795  LiVESWidget *fxcombo;
3796 
3797  boolean on = lives_toggle_button_get_active(acheck);
3798  int ours = -1, fidx, key, mode, niparams, nparams, nchans, nx = 0;
3799  int idx, pidx, i, j = 0;
3800 
3801  if (EXTRA_PARAMS_OUT > 0) nx = pconx_get_numcons(conxwp, -EXTRA_PARAMS_OUT);
3802 
3803  nparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3804  nchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3805 
3806  for (i = nx; i < nparams; i++) {
3807  if (conxwp->acheck[i] == (LiVESWidget *)acheck) {
3808  ours = i;
3809  break;
3810  }
3811  }
3812 
3813  idx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[ours]), "idx"));
3814 
3815  fxcombo = conxwp->pfxcombo[ours];
3816 
3817  model = lives_combo_get_model(LIVES_COMBO(fxcombo));
3818  lives_combo_get_active_iter(LIVES_COMBO(fxcombo), &iter);
3819 
3820  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
3821 
3822  if (key < 0) return;
3823 
3824  if (key == FX_DATA_KEY_OMC_MACRO) {
3825  // match with OMC macro
3826 
3827 
3828  return;
3829  } else {
3830  if (idx >= EXTRA_PARAMS_IN) {
3831  fidx = rte_keymode_get_filter_idx(key, mode);
3832 
3833  // find the receiving filter/instance
3834  filter = get_weed_filter(fidx);
3835 
3836  iparams = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
3837  niparams = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
3838 
3839 #ifdef COMBO_LIST_LIMIT
3840  if (niparams + EXTRA_PARAMS_IN > COMBO_LIST_LIMIT) {
3841  niparams = COMBO_LIST_LIMIT - EXTRA_PARAMS_IN;
3842  }
3843 #endif
3844 
3845  for (i = 0; i < niparams; i++) {
3846  param = iparams[j];
3847  if (weed_plant_has_leaf(param, WEED_LEAF_HOST_INTERNAL_CONNECTION)) continue;
3848  if (j == idx) break;
3849  j++;
3850  }
3851 
3852  j = i;
3853 
3854  lives_free(iparams);
3855  } else j = idx - EXTRA_PARAMS_IN;
3856  }
3857 
3858  pidx = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(acheck), "pidx"));
3859  conxwp->pconx = pconx_add_connection_private(conxwp->okey, conxwp->omode, pidx, key - 1, mode, j, on);
3860 
3861  conxwp->ikeys[nchans + ours] = key;
3862  conxwp->imodes[nchans + ours] = mode;
3863  conxwp->idx[nchans + ours] = j;
3864 }
3865 
3866 
3867 static LiVESTreeModel *inparam_fx_model(boolean is_chans, int key) {
3868  LiVESTreeStore *tstore;
3869  LiVESTreeIter iter1, iter2;
3870  weed_plant_t *filter;
3871  char *fxname, *keystr, *text;
3872  boolean key_added;
3873  int idx, nmodes = rte_getmodespk(), i, j;
3874 
3875  tstore = lives_tree_store_new(EFD_NUM_COLUMNS, LIVES_COL_TYPE_STRING, LIVES_COL_TYPE_STRING, LIVES_COL_TYPE_INT,
3876  LIVES_COL_TYPE_INT);
3877 
3878  lives_tree_store_append(tstore, &iter1, NULL); /* Acquire an iterator */
3879  lives_tree_store_set(tstore, &iter1,
3882  KEYVAL_COLUMN, 0, MODEVAL_COLUMN, 0, -1);
3883 
3884  if (!is_chans) {
3885  // add OMC Macros
3886  keystr = (_("OMC Macros"));
3887  lives_tree_store_append(tstore, &iter1, NULL); /* Acquire an iterator */
3888  lives_tree_store_set(tstore, &iter1, KEY_COLUMN, keystr, NAME_COLUMN, keystr, KEYVAL_COLUMN, 0, MODEVAL_COLUMN, 0, -1);
3889 
3890  for (i = 0; get_omc_macro(i); i++) {
3891  if (i != OSC_NOTIFY) continue; // TODO
3892  text = get_omc_macro(i)->macro_text;
3893  lives_tree_store_append(tstore, &iter2, &iter1);
3894  lives_tree_store_set(tstore, &iter2, KEY_COLUMN, text, NAME_COLUMN, text,
3896  }
3897 
3898  lives_free(keystr);
3899  }
3900 
3901  // go through all keys
3902  for (i = 1; i <= FX_KEYS_MAX_VIRTUAL; i++) {
3903  if (i == key + 1) continue;
3904 
3905  key_added = FALSE;
3906  keystr = lives_strdup_printf(_("Key slot %d"), i);
3907 
3908  for (j = 0; j < nmodes; j++) {
3909  if ((idx = rte_keymode_get_filter_idx(i, j)) == -1) continue;
3910 
3911  filter = get_weed_filter(idx);
3912 
3913  if (is_chans)
3914  if (num_alpha_channels(filter, FALSE) == 0) continue;
3915 
3916  fxname = weed_get_string_value(filter, WEED_LEAF_NAME, NULL);
3917  text = lives_strdup_printf("(%d,%d) %s", i, j + 1, fxname);
3918 
3919  if (!key_added) {
3920  // add key
3921  lives_tree_store_append(tstore, &iter1, NULL); /* Acquire an iterator */
3922  lives_tree_store_set(tstore, &iter1, KEY_COLUMN, keystr, NAME_COLUMN, keystr, KEYVAL_COLUMN, 0, MODEVAL_COLUMN, 0, -1);
3923  key_added = TRUE;
3924  }
3925  lives_tree_store_append(tstore, &iter2, &iter1);
3926  lives_tree_store_set(tstore, &iter2, KEY_COLUMN, text, NAME_COLUMN, text, KEYVAL_COLUMN, i, MODEVAL_COLUMN, j, -1);
3927 
3928  lives_free(fxname);
3929  lives_free(text);
3930  }
3931 
3932  lives_free(keystr);
3933  }
3934 
3935  return (LiVESTreeModel *)tstore;
3936 }
3937 
3938 
3939 static void ptable_row_add_variable_widgets(lives_conx_w * conxwp, int idx, int row, int pidx) {
3940  weed_plant_t **oparams, *param;
3941 
3942  LiVESWidget *hbox, *hbox2;
3943  LiVESWidget *fx_entry;
3944 
3945  boolean hasrange = FALSE;
3946 
3947  int stype, totchans;
3948 
3949  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
3950 
3951  hbox = lives_hbox_new(FALSE, 0);
3952 
3953  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 0, 1, row, row + 1,
3954  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
3955  (LiVESAttachOptions)(0), 0, 0);
3956 
3957  conxwp->pclabel[idx + totchans] = lives_standard_label_new(NULL);
3958  lives_box_pack_start(LIVES_BOX(hbox), conxwp->pclabel[idx + totchans], FALSE, FALSE, widget_opts.packing_width);
3959 
3960  hbox = lives_hbox_new(FALSE, 0);
3961 
3962  conxwp->pfxcombo[idx] = lives_standard_combo_new_with_model(pmodel, LIVES_BOX(hbox));
3963 
3964  lives_combo_set_entry_text_column(LIVES_COMBO(conxwp->pfxcombo[idx]), NAME_COLUMN);
3965 
3966  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 2, 3, row, row + 1,
3967  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
3968  (LiVESAttachOptions)(0), 0, 0);
3969 
3970  fx_entry = lives_combo_get_entry(LIVES_COMBO(conxwp->pfxcombo[idx]));
3971  lives_entry_set_width_chars(LIVES_ENTRY(fx_entry), SHORTER_ENTRY_WIDTH);
3973  lives_entry_set_editable(LIVES_ENTRY(fx_entry), FALSE);
3974 
3975  hbox = lives_hbox_new(FALSE, 0);
3976 
3977  hbox2 = lives_hbox_new(FALSE, 0);
3978  lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, 0);
3979 
3980  conxwp->pcombo[idx] = lives_standard_combo_new("", NULL, LIVES_BOX(hbox2), NULL);
3981  lives_entry_set_width_chars(LIVES_ENTRY(lives_combo_get_entry(LIVES_COMBO(conxwp->pcombo[idx]))), SHORTER_ENTRY_WIDTH);
3982  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[idx]), "idx", LIVES_INT_TO_POINTER(-1));
3983  lives_widget_set_sensitive(conxwp->pcombo[idx], FALSE);
3984 
3985  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 3, 4, row, row + 1,
3986  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
3987  (LiVESAttachOptions)(0), 0, 0);
3988 
3989  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->pfxcombo[idx]), LIVES_WIDGET_CHANGED_SIGNAL,
3990  LIVES_GUI_CALLBACK(dfxp_changed), (livespointer)conxwp);
3991 
3992  conxwp->dpp_func[idx] = lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->pcombo[idx]), LIVES_WIDGET_CHANGED_SIGNAL,
3993  LIVES_GUI_CALLBACK(dpp_changed), (livespointer)conxwp);
3994 
3995  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(conxwp->pcombo[idx]), "pidx", LIVES_INT_TO_POINTER(pidx));
3996 
3997  if (pidx < 0) {
3998  conxwp->acheck[idx] = NULL;
3999  } else {
4000  if (weed_plant_has_leaf(conxwp->filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES)) {
4001  oparams = weed_get_plantptr_array(conxwp->filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES, NULL);
4002 
4003  param = oparams[pidx];
4004  stype = weed_leaf_seed_type(param, WEED_LEAF_DEFAULT);
4005 
4006  if (weed_plant_has_leaf(param, WEED_LEAF_MAX) && weed_plant_has_leaf(param, WEED_LEAF_MIN) && (stype == WEED_SEED_INT ||
4007  stype == WEED_SEED_DOUBLE))
4008  hasrange = TRUE;
4009 
4010  lives_free(oparams);
4011  }
4012 
4013  hbox = lives_hbox_new(FALSE, 0);
4014 
4015  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 4, 5, row, row + 1,
4016  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
4017  (LiVESAttachOptions)(0), 0, 0);
4018 
4019  hbox2 = lives_hbox_new(FALSE, 0);
4020  lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, 0);
4021 
4022  conxwp->acheck[idx] = lives_standard_check_button_new(_("Autoscale"), FALSE, LIVES_BOX(hbox2), NULL);
4023 
4024  lives_widget_set_sensitive(conxwp->acheck[idx], FALSE);
4025  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(conxwp->acheck[idx]), "available", LIVES_INT_TO_POINTER(hasrange));
4026 
4027  conxwp->acheck_func[idx] = lives_signal_sync_connect_after(LIVES_GUI_OBJECT(conxwp->acheck[idx]), LIVES_WIDGET_TOGGLED_SIGNAL,
4028  LIVES_GUI_CALLBACK(on_acheck_toggled), (livespointer)conxwp);
4029 
4030  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(conxwp->acheck[idx]), "pidx", LIVES_INT_TO_POINTER(pidx));
4031  }
4032 }
4033 
4034 
4035 static void ctable_row_add_variable_widgets(lives_conx_w * conxwp, int idx, int row, int cidx) {
4036  LiVESWidget *hbox, *hbox2;
4037  LiVESWidget *fx_entry;
4038 
4039  hbox = lives_hbox_new(FALSE, 0);
4040 
4041  lives_table_attach(LIVES_TABLE(conxwp->tablec), hbox, 0, 1, row, row + 1,
4042  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
4043  (LiVESAttachOptions)(0), 0, 0);
4044 
4045  conxwp->pclabel[idx] = lives_standard_label_new(NULL);
4046  lives_box_pack_start(LIVES_BOX(hbox), conxwp->pclabel[idx], FALSE, FALSE, widget_opts.packing_width);
4047 
4048  hbox = lives_hbox_new(FALSE, 0);
4049 
4050  conxwp->cfxcombo[idx] = lives_standard_combo_new_with_model(cmodel, LIVES_BOX(hbox));
4051 
4052  lives_combo_set_entry_text_column(LIVES_COMBO(conxwp->cfxcombo[idx]), NAME_COLUMN);
4053 
4054  lives_table_attach(LIVES_TABLE(conxwp->tablec), hbox, 2, 3, row, row + 1,
4055  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
4056  (LiVESAttachOptions)(0), 0, 0);
4057 
4058  fx_entry = lives_combo_get_entry(LIVES_COMBO(conxwp->cfxcombo[idx]));
4059  lives_entry_set_width_chars(LIVES_ENTRY(fx_entry), SHORTER_ENTRY_WIDTH);
4061  lives_entry_set_editable(LIVES_ENTRY(fx_entry), FALSE);
4062 
4063  hbox = lives_hbox_new(FALSE, 0);
4064 
4065  hbox2 = lives_hbox_new(FALSE, 0);
4066  lives_box_pack_start(LIVES_BOX(hbox), hbox2, FALSE, FALSE, 0);
4067 
4068  conxwp->ccombo[idx] = lives_standard_combo_new("", NULL, LIVES_BOX(hbox2), NULL);
4069  lives_entry_set_width_chars(LIVES_ENTRY(lives_combo_get_entry(LIVES_COMBO(conxwp->ccombo[idx]))), SHORTER_ENTRY_WIDTH);
4070  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(conxwp->ccombo[idx]), "idx", LIVES_INT_TO_POINTER(-1));
4071  lives_widget_set_sensitive(conxwp->ccombo[idx], FALSE);
4072 
4073  lives_table_attach(LIVES_TABLE(conxwp->tablec), hbox, 3, 4, row, row + 1,
4074  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
4075  (LiVESAttachOptions)(0), 0, 0);
4076 
4077  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->cfxcombo[idx]), LIVES_WIDGET_CHANGED_SIGNAL,
4078  LIVES_GUI_CALLBACK(dfxc_changed), (livespointer)conxwp);
4079 
4080  conxwp->dpc_func[idx] = lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->ccombo[idx]), LIVES_WIDGET_CHANGED_SIGNAL,
4081  LIVES_GUI_CALLBACK(dpc_changed), (livespointer)conxwp);
4082 
4083  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(conxwp->ccombo[idx]), "cidx", LIVES_INT_TO_POINTER(cidx));
4084 }
4085 
4086 
4087 static void ptable_row_add_standard_widgets(lives_conx_w * conxwp, int idx) {
4088  LiVESWidget *hbox;
4089 
4090  hbox = lives_hbox_new(FALSE, 0);
4091 
4092  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 1, 2, conxwp->trowsp - 1, conxwp->trowsp,
4093  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND), (LiVESAttachOptions)(0), 0, 0);
4094 
4095  conxwp->clabel[idx] = lives_standard_label_new(lctext);
4096  lives_box_pack_start(LIVES_BOX(hbox), conxwp->clabel[idx], FALSE, FALSE, widget_opts.packing_width);
4097 
4098  conxwp->add_button[idx] = lives_standard_button_new_from_stock(LIVES_STOCK_ADD, NULL, BW, BH);
4100  _("Add another connection for this output parameter"));
4102 
4103  lives_table_attach(LIVES_TABLE(conxwp->tablep), conxwp->add_button[idx], 6, 7, conxwp->trowsp - 1,
4104  conxwp->trowsp, (LiVESAttachOptions)(0), (LiVESAttachOptions)(0), 0, 0);
4105 
4106  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->add_button[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
4107  LIVES_GUI_CALLBACK(padd_clicked), (livespointer)conxwp);
4108 
4109  conxwp->del_button[idx] = lives_standard_button_new_from_stock(LIVES_STOCK_REMOVE, NULL, BW, BH);
4110  lives_widget_set_tooltip_text(conxwp->del_button[idx], _("Delete this connection"));
4111 
4112  hbox = lives_hbox_new(FALSE, 0);
4113 
4114  lives_box_pack_start(LIVES_BOX(hbox), conxwp->del_button[idx], FALSE, FALSE, 0);
4115 
4116  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 5, 6, conxwp->trowsp - 1, conxwp->trowsp,
4117  (LiVESAttachOptions)(0), (LiVESAttachOptions)(0), 0, 0);
4118 
4119  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->del_button[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
4120  LIVES_GUI_CALLBACK(pdel_clicked), (livespointer)conxwp);
4121 
4123 }
4124 
4125 
4126 static void ctable_row_add_standard_widgets(lives_conx_w * conxwp, int idx) {
4127  LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
4128 
4129  lives_table_attach(LIVES_TABLE(conxwp->tablec), hbox, 1, 2, conxwp->trowsc - 1, conxwp->trowsc,
4130  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND), (LiVESAttachOptions)(0), 0, 0);
4131 
4132  conxwp->clabel[idx] = lives_standard_label_new(lctext);
4133  lives_box_pack_start(LIVES_BOX(hbox), conxwp->clabel[idx], FALSE, FALSE, widget_opts.packing_width);
4134 
4135  conxwp->add_button[idx] = lives_standard_button_new_from_stock(LIVES_STOCK_ADD, NULL, BW, BH);
4136  lives_widget_set_tooltip_text(conxwp->add_button[idx], _("Add another connection for this output channel"));
4137 
4138  lives_table_attach(LIVES_TABLE(conxwp->tablec), conxwp->add_button[idx], 5, 6, conxwp->trowsc - 1, conxwp->trowsc,
4139  (LiVESAttachOptions)(0), (LiVESAttachOptions)(0), 0, 0);
4140 
4141  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->add_button[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
4142  LIVES_GUI_CALLBACK(cadd_clicked), (livespointer)conxwp);
4143 
4144  conxwp->del_button[idx] = lives_standard_button_new_from_stock(LIVES_STOCK_REMOVE, NULL, BW, BH);
4145  lives_widget_set_tooltip_text(conxwp->del_button[idx], _("Delete this connection"));
4146 
4147  hbox = lives_hbox_new(FALSE, 0);
4148 
4149  lives_box_pack_start(LIVES_BOX(hbox), conxwp->del_button[idx], FALSE, FALSE, 0);
4150 
4151  lives_table_attach(LIVES_TABLE(conxwp->tablec), hbox, 4, 5, conxwp->trowsc - 1, conxwp->trowsc,
4152  (LiVESAttachOptions)(0),
4153  (LiVESAttachOptions)(0), 0, 0);
4154 
4155  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxwp->del_button[idx]), LIVES_WIDGET_CLICKED_SIGNAL,
4156  LIVES_GUI_CALLBACK(cdel_clicked), (livespointer)conxwp);
4157 
4159 }
4160 
4161 
4162 static LiVESWidget *conx_scroll_new(lives_conx_w * conxwp) {
4163  weed_plant_t *chan, *param;
4164 
4165  LiVESWidget *label;
4166  LiVESWidget *top_vbox;
4167  LiVESWidget *hbox;
4168  LiVESWidget *scrolledwindow;
4169 
4170  char *channame, *pname, *fname;
4171  char *ptype, *range;
4172  char *array_type, *text, *tmp;
4173 
4174  boolean isfirst;
4175 
4176  int defelems, pflags, stype;
4177 
4178  int totchans, totparams, nconns;
4179 
4180  register int i, j = 0, x = 0;
4181 
4182  for (i = 0; i < conxwp->num_alpha; i++) {
4183  nconns = cconx_get_nconns(conxwp->cconx, i);
4184  if (nconns == 0) nconns = 1;
4185  conxwp->dispc[i] = nconns;
4186  }
4187 
4188  for (i = -EXTRA_PARAMS_OUT; i < conxwp->num_params - EXTRA_PARAMS_OUT; i++) {
4189  nconns = pconx_get_nconns(conxwp->pconx, i);
4190  if (nconns == 0) nconns = 1;
4191  conxwp->dispp[i + EXTRA_PARAMS_OUT] = nconns;
4192  }
4193 
4194  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
4195  totparams = pconx_get_numcons(conxwp, FX_DATA_WILDCARD);
4196 
4197  conxwp->add_button = (LiVESWidget **)lives_malloc((totchans + totparams) * sizeof(LiVESWidget *));
4198  conxwp->del_button = (LiVESWidget **)lives_malloc((totchans + totparams) * sizeof(LiVESWidget *));
4199  conxwp->clabel = (LiVESWidget **)lives_malloc((totchans + totparams) * sizeof(LiVESWidget *));
4200  conxwp->pclabel = (LiVESWidget **)lives_malloc((totchans + totparams) * sizeof(LiVESWidget *));
4201 
4202  conxwp->cfxcombo = conxwp->ccombo = conxwp->pcombo = conxwp->pfxcombo = conxwp->acheck = NULL;
4203  conxwp->dpp_func = conxwp->dpc_func = conxwp->acheck_func = NULL;
4204 
4205  conxwp->ikeys = (int *)lives_malloc((totchans + totparams) * sizint);
4206  conxwp->imodes = (int *)lives_malloc((totchans + totparams) * sizint);
4207  conxwp->idx = (int *)lives_malloc((totchans + totparams) * sizint);
4208 
4209  for (i = 0; i < totchans + totparams; i++) {
4210  conxwp->ikeys[i] = -1;
4211  conxwp->imodes[i] = conxwp->idx[i] = 0;
4212  }
4213 
4214  lctext = (_("Connected to -->"));
4215 
4216  top_vbox = lives_vbox_new(FALSE, 0);
4217 
4218  scrolledwindow = lives_standard_scrolled_window_new(-1, -1, top_vbox);
4219 
4220  conxwp->trowsc = conxwp->trowsp = 0;
4221 
4222  fname = weed_get_string_value(conxwp->filter, WEED_LEAF_NAME, NULL);
4223 
4224  if (conxwp->num_alpha > 0) {
4225  weed_plant_t **ochans = weed_get_plantptr_array(conxwp->filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
4226 
4227  conxwp->dpc_func = (ulong *)lives_malloc(totchans * sizeof(ulong));
4228 
4229  conxwp->cfxcombo = (LiVESWidget **)lives_malloc(totchans * sizeof(LiVESWidget *));
4230 
4231  conxwp->ccombo = (LiVESWidget **)lives_malloc(totchans * sizeof(LiVESWidget *));
4232 
4233  tmp = lives_big_and_bold("%s - Alpha Channel Connections", fname);
4234 
4236  widget_opts.justify = LIVES_JUSTIFY_CENTER;
4237  label = lives_standard_label_new(tmp);
4240  lives_free(tmp);
4241 
4242  lives_box_pack_start(LIVES_BOX(top_vbox), label, FALSE, FALSE, widget_opts.packing_height);
4243 
4244  conxwp->tablec = lives_table_new(0, 6, FALSE);
4247  lives_box_pack_start(LIVES_BOX(top_vbox), conxwp->tablec, FALSE, FALSE, widget_opts.packing_height);
4248 
4249  conxwp->trowsc = 1;
4250 
4251  cmodel = inparam_fx_model(TRUE, conxwp->okey);
4252 
4253  for (i = 0; i < conxwp->num_alpha; i++) {
4254  chan = ochans[j++];
4255 
4256  if (!has_alpha_palette(chan, conxwp->filter)) {
4257  i--;
4258  continue;
4259  }
4260 
4261  lives_table_resize(LIVES_TABLE(conxwp->tablec), ++conxwp->trowsc, 6);
4262 
4263  nconns = conxwp->dispc[i];
4264 
4265  isfirst = TRUE;
4266 
4267  do {
4268  ctable_row_add_variable_widgets(conxwp, x, conxwp->trowsc - 1, i);
4269  ctable_row_add_standard_widgets(conxwp, x);
4270 
4271  if (isfirst) {
4272  channame = get_chan_name(chan, j - 1, FALSE);
4274  lives_label_set_text(LIVES_LABEL(conxwp->pclabel[x]), channame);
4276  lives_free(channame);
4277  isfirst = FALSE;
4278  }
4279 
4280  x++;
4281 
4282  if (nconns > 1) {
4283  lives_table_resize(LIVES_TABLE(conxwp->tablec), ++conxwp->trowsc, 6);
4284  }
4285 
4286  } while (--nconns > 0);
4287  }
4288 
4289  lives_free(ochans);
4290  }
4291 
4292  if (conxwp->num_alpha > 0 && conxwp->num_params > 0) {
4293  add_hsep_to_box(LIVES_BOX(top_vbox));
4294  }
4295 
4296  if (conxwp->num_params > 0) {
4297  weed_plant_t **oparams = NULL;
4298 
4299  pmodel = inparam_fx_model(FALSE, conxwp->okey);
4300 
4301  if (weed_plant_has_leaf(conxwp->filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES))
4302  oparams = weed_get_plantptr_array(conxwp->filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES, NULL);
4303 
4304  conxwp->pfxcombo = (LiVESWidget **)lives_malloc(totparams * sizeof(LiVESWidget *));
4305  conxwp->pcombo = (LiVESWidget **)lives_malloc(totparams * sizeof(LiVESWidget *));
4306 
4307  conxwp->dpp_func = (ulong *)lives_malloc(totparams * sizeof(ulong));
4308  conxwp->acheck_func = (ulong *)lives_malloc(totparams * sizeof(ulong));
4309 
4310  conxwp->acheck = (LiVESWidget **)lives_malloc(totparams * sizeof(LiVESWidget *));
4311 
4312  tmp = lives_big_and_bold("%s - Parameter Data Connections", fname);
4313 
4315  widget_opts.justify = LIVES_JUSTIFY_CENTER;
4316  label = lives_standard_label_new(tmp);
4319  lives_free(tmp);
4320 
4321  lives_box_pack_start(LIVES_BOX(top_vbox), label, FALSE, FALSE, widget_opts.packing_height);
4322 
4323  conxwp->tablep = lives_table_new(1, 7, FALSE);
4326  lives_box_pack_start(LIVES_BOX(top_vbox), conxwp->tablep, FALSE, FALSE, widget_opts.packing_height);
4327 
4328  conxwp->trowsp = 1;
4329  x = 0;
4330 
4331  hbox = lives_hbox_new(FALSE, 0);
4332 
4333  lives_table_attach(LIVES_TABLE(conxwp->tablep), hbox, 4, 5, 0, 1,
4334  (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
4335  (LiVESAttachOptions)(0), 0, 0);
4336 
4337  conxwp->allcheckc = lives_standard_check_button_new(_("Autoscale All"), TRUE, LIVES_BOX(hbox), NULL);
4339 
4340  lives_signal_sync_connect_after(LIVES_GUI_OBJECT(conxwp->allcheckc), LIVES_WIDGET_TOGGLED_SIGNAL,
4341  LIVES_GUI_CALLBACK(on_allcheck_toggled),
4342  (livespointer)conxwp);
4343 
4344  if (EXTRA_PARAMS_OUT > 0) {
4345  lives_table_resize(LIVES_TABLE(conxwp->tablep), ++conxwp->trowsp, 7);
4346 
4347  nconns = conxwp->dispp[0];
4348 
4349  isfirst = TRUE;
4350 
4351  do {
4352  // TODO: for OMC, adjust the pmodel for each oparam type
4353 
4354  ptable_row_add_variable_widgets(conxwp, x, conxwp->trowsp - 1, -EXTRA_PARAMS_OUT);
4355  ptable_row_add_standard_widgets(conxwp, x + totchans);
4356 
4357  //lives_widget_set_sensitive(conxwp->add_button[x + totchans], FALSE);
4358 
4359  if (isfirst) {
4360  /* TRANSLATORS - as in "Effect ACTIVATED" */
4361  pname = (_("ACTIVATED"));
4362  ptype = weed_seed_type_to_text(WEED_SEED_BOOLEAN);
4363 
4364  text = lives_strdup_printf("%s (%s)", pname, ptype);
4366  lives_label_set_text(LIVES_LABEL(conxwp->pclabel[x + totchans]), text);
4368  lives_free(text);
4369  lives_free(pname);
4370  lives_free(ptype);
4371 
4372  isfirst = FALSE;
4373  }
4374 
4375  x++;
4376 
4377  if (nconns > 1) {
4378  lives_table_resize(LIVES_TABLE(conxwp->tablep), ++conxwp->trowsp, 7);
4379  }
4380  } while (--nconns > 0);
4381  }
4382 
4383  for (i = 0; i < conxwp->num_params - EXTRA_PARAMS_OUT; i++) {
4384  lives_table_resize(LIVES_TABLE(conxwp->tablep), ++conxwp->trowsp, 7);
4385 
4386  nconns = conxwp->dispp[i + EXTRA_PARAMS_OUT];
4387 
4388  isfirst = TRUE;
4389 
4390  do {
4391  ptable_row_add_variable_widgets(conxwp, x, conxwp->trowsp - 1, i);
4392  ptable_row_add_standard_widgets(conxwp, x + totchans);
4393 
4394  if (isfirst) {
4395  param = oparams[i];
4396 
4397  pname = get_param_name(param, i, FALSE);
4398 
4399  ptype = weed_seed_type_to_text((stype = weed_leaf_seed_type(param, WEED_LEAF_DEFAULT)));
4400 
4401  pflags = weed_get_int_value(param, WEED_LEAF_FLAGS, NULL);
4402 
4403  if (pflags & WEED_PARAMETER_VARIABLE_SIZE) array_type = lives_strdup("[]");
4404  else if ((defelems = weed_leaf_num_elements(param, WEED_LEAF_DEFAULT)) > 1)
4405  array_type = lives_strdup_printf("[%d]", defelems);
4406  else array_type = lives_strdup("");
4407 
4408  if (weed_plant_has_leaf(param, WEED_LEAF_MAX) && weed_plant_has_leaf(param, WEED_LEAF_MIN)) {
4409  if (stype == WEED_SEED_INT) {
4410  range = lives_strdup_printf("Range: %d to %d", weed_get_int_value(param, WEED_LEAF_MIN, NULL),
4411  weed_get_int_value(param,
4412  WEED_LEAF_MAX,
4413  NULL));
4414  } else if (stype == WEED_SEED_DOUBLE) {
4415  range = lives_strdup_printf("Range: %f to %f", weed_get_double_value(param, WEED_LEAF_MIN, NULL),
4416  weed_get_double_value(param,
4417  WEED_LEAF_MAX,
4418  NULL));
4419  } else range = lives_strdup("");
4420  } else range = lives_strdup("");
4421 
4422  text = lives_strdup_printf("%s\n (%s%s) %s", pname, ptype, array_type, range);
4424  lives_label_set_text(LIVES_LABEL(conxwp->pclabel[x + totchans]), text);
4426  lives_free(text);
4427  lives_free(pname);
4428  lives_free(ptype);
4429 
4430  isfirst = FALSE;
4431  }
4432 
4433  x++;
4434 
4435  if (nconns > 1) {
4436  lives_table_resize(LIVES_TABLE(conxwp->tablep), ++conxwp->trowsp, 7);
4437  }
4438  } while (--nconns > 0);
4439  }
4440 
4441  lives_free(oparams);
4442  }
4443 
4444  lives_free(fname);
4445 
4446  return scrolledwindow;
4447 }
4448 
4449 
4450 static void conxw_cancel_clicked(LiVESWidget * button, livespointer user_data) {
4451  lives_conx_w *conxwp = (lives_conx_w *)user_data;
4452 
4454  if (conxwp->pclabel) lives_free(conxwp->pclabel);
4455  if (conxwp->clabel) lives_free(conxwp->clabel);
4456  if (conxwp->cfxcombo) lives_free(conxwp->cfxcombo);
4457  if (conxwp->ccombo) lives_free(conxwp->ccombo);
4458  if (conxwp->pfxcombo) lives_free(conxwp->pfxcombo);
4459  if (conxwp->pcombo) lives_free(conxwp->pcombo);
4460  if (conxwp->acheck) lives_free(conxwp->acheck);
4461  if (conxwp->add_button) lives_free(conxwp->add_button);
4462  if (conxwp->del_button) lives_free(conxwp->del_button);
4463  if (conxwp->dpp_func) lives_free(conxwp->dpp_func);
4464  if (conxwp->dpc_func) lives_free(conxwp->dpc_func);
4465  if (conxwp->acheck_func) lives_free(conxwp->acheck_func);
4466 
4467  if (conxwp->dispp) lives_free(conxwp->dispp);
4468  if (conxwp->dispc) lives_free(conxwp->dispc);
4469 
4470  lives_free(conxwp->ikeys);
4471  lives_free(conxwp->imodes);
4472  lives_free(conxwp->idx);
4473 
4474  lives_free(lctext);
4475 
4476  pconx_delete_all();
4477  cconx_delete_all();
4478 
4479  if (!button) return;
4480 
4481  // restore old values
4482  mainw->pconx = spconx;
4483  mainw->cconx = scconx;
4484 
4485  lives_general_button_clicked(LIVES_BUTTON(button), NULL);
4486 }
4487 
4488 
4489 static void conxw_ok_clicked(LiVESWidget * button, livespointer user_data) {
4490  lives_cconnect_t *cconx_bak = mainw->cconx;
4491  lives_pconnect_t *pconx_bak = mainw->pconx;
4492 
4493  // let backup copy be freed
4494  mainw->pconx = spconx;
4495  mainw->cconx = scconx;
4496 
4497  conxw_cancel_clicked(NULL, user_data);
4498 
4499  mainw->cconx = cconx_bak;
4500  mainw->pconx = pconx_bak;
4501 
4502  lives_general_button_clicked(LIVES_BUTTON(button), NULL);
4503 }
4504 
4505 
4506 static void set_to_keymode_vals(LiVESCombo * combo, int xkey, int xmode) {
4507  LiVESTreeIter iter, piter;
4508  LiVESTreeModel *model;
4509 
4510  int key, mode;
4511 
4512  model = lives_combo_get_model(combo);
4513  if (!lives_tree_model_get_iter_first(model, &piter)) return;
4514 
4515  do {
4516  if (lives_tree_model_iter_children(model, &iter, &piter)) {
4517  do {
4518  lives_tree_model_get(model, &iter, KEYVAL_COLUMN, &key, MODEVAL_COLUMN, &mode, -1);
4519  if (key == (key > -0 ? xkey + 1 : key) && mode == xmode) goto iter_found;
4520  } while (lives_tree_model_iter_next(model, &iter));
4521  }
4522  } while (lives_tree_model_iter_next(model, &piter));
4523 
4524 iter_found:
4525  lives_combo_set_active_iter(combo, &iter);
4526 
4527 }
4528 
4529 
4530 static boolean show_existing(lives_conx_w * conxwp) {
4531  lives_cconnect_t *cconx = conxwp->cconx;
4532  lives_pconnect_t *pconx = conxwp->pconx;
4533 
4534  LiVESWidget *cfxcombo, *ccombo;
4535  LiVESWidget *pfxcombo, *pcombo;
4536  LiVESWidget *acheck;
4537 
4538  weed_plant_t **ochans, **ichans;
4539  weed_plant_t **iparams;
4540  weed_plant_t *ofilter = conxwp->filter, *filter;
4541  weed_plant_t *chan, *param;
4542 
4543  int ikey, imode, icnum, ipnum, nichans, niparams;
4544  int posn = 0, cidx, pidx, totchans = 0;
4545  int i, j, k, l;
4546 
4547  if (!cconx) goto show_ex_params;
4548 
4549  totchans = cconx_get_numcons(conxwp, FX_DATA_WILDCARD);
4550 
4551  ochans = weed_get_plantptr_array(ofilter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
4552 
4553  for (i = 0; i < cconx->nchans; i++) {
4554  // find the row
4555  l = 0;
4556 
4557  // total out channel connections (display order) up to here
4558  for (k = 0; k < i; k++) {
4559  chan = ochans[j++];
4560  if (!has_alpha_palette(chan, ofilter)) {
4561  k--;
4562  continue;
4563  }
4564  l += cconx_get_numcons(conxwp, k);
4565  }
4566 
4567  cidx = cconx->chans[i];
4568  for (j = posn; j < posn + cconx->nconns[i]; j++) {
4569  ikey = cconx->ikey[j];
4570  imode = cconx->imode[j];
4571 
4572  // row is l
4573  cfxcombo = conxwp->cfxcombo[l];
4574 
4575  // set it to the value which has ikey/imode
4576  set_to_keymode_vals(LIVES_COMBO(cfxcombo), ikey, imode);
4577 
4578  // set channel
4579  ccombo = conxwp->ccombo[l];
4580  icnum = cconx->icnum[j];
4581 
4582  filter = rte_keymode_get_filter(ikey + 1, imode);
4583  ichans = weed_get_plantptr_array(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, NULL);
4584  nichans = weed_leaf_num_elements(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES);
4585 
4586  cidx = 0;
4587 
4588  // find combo list index for ichan
4589  for (k = 0; k < nichans; k++) {
4590  chan = ichans[k];
4591  if (!has_alpha_palette(chan, filter)) continue;
4592  if (k == icnum) break;
4593  cidx++;
4594  }
4595 
4596  lives_free(ichans);
4597 
4598  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ccombo), "setup", LIVES_INT_TO_POINTER(TRUE));
4599 
4600  lives_signal_handler_block(ccombo, conxwp->dpc_func[l]);
4601  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ccombo), "idx", LIVES_INT_TO_POINTER(cidx));
4602  lives_combo_set_active_index(LIVES_COMBO(ccombo), cidx);
4603  lives_signal_handler_unblock(ccombo, conxwp->dpc_func[l]);
4604 
4605  conxwp->ikeys[l] = ikey;
4606  conxwp->imodes[l] = imode;
4607  conxwp->idx[l] = icnum;
4608 
4609  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ccombo), "setup", LIVES_INT_TO_POINTER(FALSE));
4612 
4613  l++;
4614  }
4615 
4616  posn += cconx->nconns[i];
4617  }
4618 
4619  lives_free(ochans);
4620 
4621 show_ex_params:
4622 
4623  if (!pconx) goto show_ex_done;
4624 
4625  posn = 0;
4626 
4627  for (i = 0; i < pconx->nparams; i++) {
4628  pidx = pconx->params[i];
4629 
4630  // find the row
4631  l = 0;
4632 
4633  // total out param connections (display order) up to here
4634  for (k = -EXTRA_PARAMS_OUT; k < pidx; k++) {
4635  l += pconx_get_numcons(conxwp, k);
4636  }
4637 
4638  for (j = posn; j < posn + pconx->nconns[i]; j++) {
4639  ikey = pconx->ikey[j];
4640  imode = pconx->imode[j];
4641 
4642  // row is l
4643  pfxcombo = conxwp->pfxcombo[l];
4644 
4645  // set it to the value which has ikey/imode
4646  set_to_keymode_vals(LIVES_COMBO(pfxcombo), ikey, imode);
4647 
4648  // set parameter
4649  pcombo = conxwp->pcombo[l];
4650  acheck = conxwp->acheck[l];
4651 
4652  if (j == posn + pconx->nconns[i] - 1)
4654 
4655  if (acheck) {
4656  boolean hasrange = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(acheck), "available"));
4657  if (hasrange) {
4659  lives_signal_handler_block(acheck, conxwp->acheck_func[l]);
4660  lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(acheck), pconx->autoscale[j]);
4661  lives_signal_handler_unblock(acheck, conxwp->acheck_func[l]);
4662  }
4663  }
4664 
4665  ipnum = pconx->ipnum[j];
4666 
4667  // TODO ****: OMC
4668 
4669  if (ipnum == FX_DATA_PARAM_ACTIVE) {
4670  pidx = FX_DATA_PARAM_ACTIVE;
4671  } else {
4672  filter = rte_keymode_get_filter(ikey + 1, imode);
4673  iparams = weed_get_plantptr_array(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, NULL);
4674  niparams = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
4675 
4676 #ifdef COMBO_LIST_LIMIT
4677  if (niparams + EXTRA_PARAMS_IN > COMBO_LIST_LIMIT) {
4678  niparams = COMBO_LIST_LIMIT - EXTRA_PARAMS_IN;
4679  }
4680 #endif
4681  pidx = 0;
4682 
4683  // find combo list index for iparam
4684  for (k = 0; k < niparams; k++) {
4685  param = iparams[k];
4686  if (weed_plant_has_leaf(param, WEED_LEAF_HOST_INTERNAL_CONNECTION)) continue;
4687  if (k == ipnum) break;
4688  pidx++;
4689  }
4690 
4691  lives_free(iparams);
4692  }
4693 
4694  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pcombo), "setup", LIVES_INT_TO_POINTER(TRUE));
4695 
4696  conxwp->ikeys[totchans + l] = ikey;
4697  conxwp->imodes[totchans + l] = imode;
4698  conxwp->idx[totchans + l] = ipnum;
4699 
4700  //lives_signal_handler_block(pcombo,conxwp->dpp_func[pidx]);
4701  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pcombo), "idx", LIVES_INT_TO_POINTER(pidx + EXTRA_PARAMS_IN));
4702  lives_combo_set_active_index(LIVES_COMBO(pcombo), pidx + EXTRA_PARAMS_IN);
4703  //lives_signal_handler_unblock(pcombo,conxwp->dpp_func[pidx]);
4704 
4705  lives_widget_object_set_data(LIVES_WIDGET_OBJECT(pcombo), "setup", LIVES_INT_TO_POINTER(FALSE));
4706 
4709 
4710  l++;
4711  }
4712 
4713  posn += pconx->nconns[i];
4714  }
4715 
4716 show_ex_done:
4717 
4718  return FALSE;
4719 }
4720 
4721 
4722 LiVESWidget *make_datacon_window(int key, int mode) {
4723  static lives_conx_w conxw;
4724 
4725  LiVESWidget *cbox, *abox;
4726  LiVESWidget *scrolledwindow;
4727 
4728  LiVESWidget *cancelbutton;
4729  LiVESWidget *okbutton;
4730 
4731  LiVESAccelGroup *accel_group;
4732 
4733  int winsize_h;
4734  int winsize_v;
4735 
4736  conxw.filter = rte_keymode_get_filter(key + 1, mode);
4737 
4738  if (!conxw.filter) return NULL;
4739 
4740  conxw.acbutton = conxw.apbutton = NULL;
4741 
4742  conxw.dispp = conxw.dispc = NULL;
4743 
4744  // save unaltered values
4745  spconx = pconx_copy(mainw->pconx);
4746  scconx = cconx_copy(mainw->cconx);
4747 
4748  conxw.cconx = cconx_find(key, mode);
4749  conxw.pconx = pconx_find(key, mode);
4750 
4751  conxw.okey = key;
4752  conxw.omode = mode;
4753 
4754  conxw.num_alpha = num_alpha_channels(conxw.filter, TRUE);
4755  conxw.num_params = weed_leaf_num_elements(conxw.filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES);
4756 
4757  conxw.num_params += EXTRA_PARAMS_OUT;
4758 
4759  if (conxw.num_params > 0)
4760  conxw.dispp = (int *)lives_malloc(conxw.num_params * sizint);
4761 
4762  conxw.ntabs = 0;
4763 
4764  winsize_h = GUI_SCREEN_WIDTH - SCR_WIDTH_SAFETY * 2;
4765  winsize_v = GUI_SCREEN_HEIGHT - SCR_HEIGHT_SAFETY;
4766 
4767  conxw.conx_dialog = lives_standard_dialog_new(_("Parameter and Alpha Channel Connections"), FALSE, winsize_h, winsize_v);
4768 
4769  accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
4770  lives_window_add_accel_group(LIVES_WINDOW(conxw.conx_dialog), accel_group);
4771 
4772  if (conxw.num_alpha > 0) {
4773  conxw.dispc = (int *)lives_malloc(conxw.num_alpha * sizint);
4774 
4775  conxw.acbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(conxw.conx_dialog), NULL, _("Auto Connect Channels"),
4776  LIVES_RESPONSE_NONE);
4778  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxw.acbutton), LIVES_WIDGET_CLICKED_SIGNAL,
4779  LIVES_GUI_CALLBACK(acbutton_clicked), (livespointer)&conxw);
4780  }
4781 
4782  if (conxw.num_params > EXTRA_PARAMS_OUT) {
4783  conxw.apbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(conxw.conx_dialog), NULL, _("Auto Connect Parameters"),
4784  LIVES_RESPONSE_NONE);
4786  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxw.apbutton), LIVES_WIDGET_CLICKED_SIGNAL,
4787  LIVES_GUI_CALLBACK(apbutton_clicked), (livespointer)&conxw);
4788  }
4789 
4790  conxw.disconbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(conxw.conx_dialog), NULL, _("_Disconnect All"),
4791  LIVES_RESPONSE_NONE);
4792  //lives_container_set_border_width(LIVES_CONTAINER(conxw.disconbutton), widget_opts.border_width);
4795 
4796  lives_signal_sync_connect(LIVES_GUI_OBJECT(conxw.disconbutton), LIVES_WIDGET_CLICKED_SIGNAL,
4797  LIVES_GUI_CALLBACK(disconbutton_clicked), (livespointer)&conxw);
4798 
4799  abox = lives_dialog_get_action_area(LIVES_DIALOG(conxw.conx_dialog));
4800  if (LIVES_IS_BOX(abox) && (conxw.num_alpha > 0 || conxw.num_params > 0)) add_fill_to_box(LIVES_BOX(abox));
4801 
4802  cbox = lives_dialog_get_content_area(LIVES_DIALOG(conxw.conx_dialog));
4803 
4804  scrolledwindow = conx_scroll_new(&conxw);
4805  show_existing(&conxw);
4806 
4807  lives_box_pack_start(LIVES_BOX(cbox), scrolledwindow, TRUE, TRUE, 0);
4808 
4809  if (conxw.num_params > EXTRA_PARAMS_OUT) {
4810  if (conxw.apbutton && pconx_get_nconns(conxw.pconx, 0) > 0)
4811  lives_widget_set_sensitive(conxw.apbutton, TRUE);
4812  }
4813  if (conxw.num_alpha > 0) {
4814  if (conxw.acbutton && cconx_get_nconns(conxw.cconx, 0) > 0)
4815  lives_widget_set_sensitive(conxw.acbutton, TRUE);
4816  }
4817 
4818  cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(conxw.conx_dialog), LIVES_STOCK_CANCEL, NULL,
4819  LIVES_RESPONSE_CANCEL);
4820 
4821  okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(conxw.conx_dialog), LIVES_STOCK_OK, NULL,
4822  LIVES_RESPONSE_OK);
4823 
4825 
4826  lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
4827  LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
4828 
4829  lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
4830  LIVES_GUI_CALLBACK(conxw_cancel_clicked),
4831  (livespointer)&conxw);
4832 
4833  lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
4834  LIVES_GUI_CALLBACK(conxw_ok_clicked),
4835  (livespointer)&conxw);
4836 
4837  lives_widget_show_all(conxw.conx_dialog);
4838 
4839  if (conxw.num_params == EXTRA_PARAMS_OUT && EXTRA_PARAMS_OUT > 0) {
4840  lives_widget_set_no_show_all(conxw.allcheckc, TRUE);
4841  lives_widget_hide(conxw.allcheckc);
4842  lives_widget_set_no_show_all(conxw.allcheck_label, TRUE);
4843  lives_widget_hide(conxw.allcheck_label);
4844  }
4845 
4846  return conxw.conx_dialog;
4847 }
4848 
4849 
4850 static boolean do_chan_connected_query(lives_conx_w * conxwp, int key, int mode, int cnum, boolean is_same) {
4851  weed_plant_t *filter = rte_keymode_get_filter(key + 1, mode);
4852  weed_plant_t *ctmpl, **ochans;
4853  char *cname, *msg, *fname = weed_filter_get_name(filter);
4854  boolean resp = FALSE;
4855  ochans = weed_get_plantptr_array(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, NULL);
4856  ctmpl = ochans[cnum];
4857  lives_free(ochans);
4858  cname = get_chan_name(ctmpl, cnum, TRUE);
4859  widget_opts.transient = LIVES_WINDOW(conxwp->conx_dialog);
4860  msg = lives_strdup_printf(_("Input channel is already connected from key %d, mode %d\n\n(%s:%s)\n\n"),
4861  key + 1, mode, fname, cname);
4862  if (!is_same)
4863  resp = do_yesno_dialogf(_("%sWould you like to replace the existing connection ?\n\n"), msg);
4864 
4865  else
4866  do_error_dialogf(_("%sYou need to remove this connection first before adding another.\n\n"), msg);
4867  widget_opts.transient = NULL;
4868  lives_free(msg); lives_free(cname); lives_free(fname);
4869  return resp;
4870 }
4871 
4872 
4873 static boolean do_param_connected_query(lives_conx_w * conxwp, int key, int mode, int pnum, boolean is_same) {
4874  weed_plant_t *filter = rte_keymode_get_filter(key + 1, mode);
4875  char *pname, *msg, *fname = weed_filter_get_name(filter);
4876  boolean resp = FALSE;
4877  if (pnum >= 0) {
4878  weed_plant_t *ptmpl = weed_filter_out_paramtmpl(filter, pnum);
4879  pname = get_param_name(ptmpl, pnum, TRUE);
4880  } else pname = (_("ACTIVATED"));
4881  widget_opts.transient = LIVES_WINDOW(conxwp->conx_dialog);
4882  msg = lives_strdup_printf(_("Input parameter is already connected from key %d, mode %d\n\n(%s:%s)\n\n"),
4883  key + 1, mode, fname, pname);
4884  if (!is_same)
4885  resp = do_yesno_dialogf(_("%sWould you like to replace the existing connection ?\n\n"), msg);
4886 
4887  else
4888  do_error_dialogf(_("%sYou need to remove this connection first before adding another.\n\n"), msg);
4889  widget_opts.transient = NULL;
4890  lives_free(msg); lives_free(pname); lives_free(fname);
4891  return resp;
4892 }
4893 
4894 
4895 static void do_param_incompatible_error(lives_conx_w * conxwp) {
4896  widget_opts.transient = LIVES_WINDOW(conxwp->conx_dialog);
4897  do_error_dialog(_("Input and output parameters are not compatible"));
4898  widget_opts.transient = NULL;
4899 }
4900 
weed_inst_out_param
weed_plant_t * weed_inst_out_param(weed_plant_t *inst, int param_num)
Definition: effects-weed.c:8771
FX_DATA_KEY_OMC_MACRO
#define FX_DATA_KEY_OMC_MACRO
Definition: effects-data.h:13
lives_conx_w::acheck
LiVESWidget ** acheck
Definition: effects-data.h:152
widget_opts_t::packing_width
int packing_width
horizontal pixels between widgets
Definition: widget-helper.h:1410
lives_combo_set_entry_text_column
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_entry_text_column(LiVESCombo *combo, int column)
Definition: widget-helper.c:3861
pconx_chain_data_omc
int pconx_chain_data_omc(weed_plant_t *inst, int okey, int omode)
Definition: effects-data.c:1323
LIVES_IS_PLAYING
#define LIVES_IS_PLAYING
Definition: main.h:840
lives_tree_model_get_path
WIDGET_HELPER_GLOBAL_INLINE LiVESTreePath * lives_tree_model_get_path(LiVESTreeModel *tmod, LiVESTreeIter *titer)
Definition: widget-helper.c:5738
widget_opts_t::transient
LiVESWindow * transient
transient window for dialogs, if NULL then use the default (READ / WRITE)
Definition: widget-helper.h:1423
lives_combo_set_active_string
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_string(LiVESCombo *combo, const char *active_str)
Definition: widget-helper.c:12290
cconx_convert_pixel_data
boolean cconx_convert_pixel_data(weed_plant_t *dchan, weed_plant_t *schan)
Definition: effects-data.c:2031
lives_dialog_add_button_from_stock
LiVESWidget * lives_dialog_add_button_from_stock(LiVESDialog *dialog, const char *stock_id, const char *label, int response_id)
Definition: widget-helper.c:9892
WEED_PLANT_IS_PARAMETER
#define WEED_PLANT_IS_PARAMETER(plant)
Definition: weed-effects-utils.h:46
lives_conx_w::pcombo
LiVESWidget ** pcombo
Definition: effects-data.h:150
pp_get_param
const weed_plant_t * pp_get_param(weed_plant_t **pparams, int idx)
Definition: plugins.c:1042
lives_free
#define lives_free
Definition: machinestate.h:52
lives_rfx_t::is_template
boolean is_template
Definition: plugins.h:656
lives_widget_add_accelerator
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_add_accelerator(LiVESWidget *widget, const char *accel_signal, LiVESAccelGroup *accel_group, uint32_t accel_key, LiVESXModifierType accel_mods, LiVESAccelFlags accel_flags)
Definition: widget-helper.c:2953
lives_malloc
#define lives_malloc
Definition: machinestate.h:46
FX_DATA_WILDCARD
#define FX_DATA_WILDCARD
Definition: effects-data.h:7
widget_opts_t::justify
LiVESJustification justify
justify for labels
Definition: widget-helper.h:1412
mainwindow::record
volatile boolean record
Definition: mainwindow.h:794
FX_DATA_WILDCARD_KEEP_ACTIVATED
#define FX_DATA_WILDCARD_KEEP_ACTIVATED
Definition: effects-data.h:8
lives_widget_destroy
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
Definition: widget-helper.c:1553
SCR_HEIGHT_SAFETY
#define SCR_HEIGHT_SAFETY
Definition: mainwindow.h:90
cconx_check_connection
int cconx_check_connection(int ikey, int imode, int icnum, boolean setup, weed_plant_t **ichan_ret, int *idx_ret, int *okey, int *omode, int *ocnum)
Definition: effects-data.c:3633
do_yesno_dialogf
boolean do_yesno_dialogf(const char *fmt,...)
Definition: dialogs.c:635
rte_keymode_get_filter
weed_plant_t * rte_keymode_get_filter(int key, int mode)
returns filter_class bound to key/mode (or NULL)
Definition: effects-weed.c:9465
pconx_check_connection
int pconx_check_connection(weed_plant_t *ofilter, int opnum, int ikey, int imode, int ipnum, boolean setup, weed_plant_t **iparam_ret, int *idx_ret, int *okey, int *omode, int *oopnum)
Definition: effects-data.c:3390
lives_tree_model_iter_children
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_iter_children(LiVESTreeModel *tmod, LiVESTreeIter *titer, LiVESTreeIter *parent)
Definition: widget-helper.c:5747
lives_conx_w::trowsc
int trowsc
Definition: effects-data.h:162
override_if_active_input
void override_if_active_input(int hotkey)
Definition: effects-data.c:98
lives_omc_macro_t::macro_text
char * macro_text
macro text
Definition: omc-learn.h:51
lives_conx_w::tablep
LiVESWidget * tablep
Definition: effects-data.h:159
lives_table_set_col_spacings
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_col_spacings(LiVESTable *table, uint32_t spacing)
Definition: widget-helper.c:6972
lives_dialog_get_content_area
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_dialog_get_content_area(LiVESDialog *dialog)
Definition: widget-helper.c:2479
lives_conx_w::add_button
LiVESWidget ** add_button
Definition: effects-data.h:153
lives_conx_w::num_params
int num_params
Definition: effects-data.h:135
weed_param_get_template
WEED_GLOBAL_INLINE weed_plant_t * weed_param_get_template(weed_plant_t *param)
Definition: weed-effects-utils.c:518
pconx_delete_all
void pconx_delete_all(void)
Definition: effects-data.c:153
mainwindow::vpp
_vid_playback_plugin * vpp
video plugin
Definition: mainwindow.h:1572
get_weed_filter
weed_plant_t * get_weed_filter(int idx)
Definition: effects-weed.c:11014
lives_realloc
#define lives_realloc
Definition: machinestate.h:49
FX_DATA_PARAM_ACTIVE
#define FX_DATA_PARAM_ACTIVE
activate || activated
Definition: effects-data.h:18
lives_widget_hide
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_hide(LiVESWidget *widget)
Definition: widget-helper.c:1514
effects.h
lives_conx_w::ikeys
int * ikeys
Definition: effects-data.h:169
lives_table_attach
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_attach(LiVESTable *table, LiVESWidget *child, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom, LiVESAttachOptions xoptions, LiVESAttachOptions yoptions, uint32_t xpad, uint32_t ypad)
Definition: widget-helper.c:7035
feeds_to_video_filters
boolean feeds_to_video_filters(int okey, int omode)
Definition: effects-data.c:2178
EFD_NUM_COLUMNS
@ EFD_NUM_COLUMNS
Definition: effects-data.c:2293
lives_widget_reparent
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_reparent(LiVESWidget *widget, LiVESWidget *new_parent)
Definition: widget-helper.c:1721
weed_filter_out_paramtmpl
weed_plant_t * weed_filter_out_paramtmpl(weed_plant_t *filter, int param_num)
Definition: effects-weed.c:8831
rte_keymode_get_filter_idx
int rte_keymode_get_filter_idx(int key, int mode)
returns filter_class index of key/mode (or -1 if no filter bound)
Definition: effects-weed.c:9416
LIVES_JUSTIFY_DEFAULT
#define LIVES_JUSTIFY_DEFAULT
Definition: widget-helper.h:1289
ce_thumbs_register_rfx_change
void ce_thumbs_register_rfx_change(int key, int mode)
Definition: ce_thumbs.c:553
lives_label_set_text
WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_text(LiVESLabel *label, const char *text)
Definition: widget-helper.c:6064
rte_key_toggle
LIVES_GLOBAL_INLINE boolean rte_key_toggle(int key)
Definition: effects.c:1224
lives_standard_dialog_new
LiVESWidget * lives_standard_dialog_new(const char *title, boolean add_std_buttons, int width, int height)
Definition: widget-helper.c:9971
prefs
_prefs * prefs
Definition: preferences.h:847
lives_conx_w::okey
int okey
Definition: effects-data.h:132
BH
#define BH
Definition: effects-data.c:42
omc_process_string
boolean omc_process_string(int supertype, const char *string, boolean learn, omclearn_w *omclw)
process a string (i.e. convert to an OSC message and pass to OSC subsys) only need to set omclw if le...
lives_conx_w::allcheckc
LiVESWidget * allcheckc
Definition: effects-data.h:155
has_alpha_palette
boolean has_alpha_palette(weed_plant_t *ctmpl, weed_plant_t *filter)
Definition: effects-weed.c:162
pconx_chain_data_internal
boolean pconx_chain_data_internal(weed_plant_t *inst)
Definition: effects-data.c:1525
REC_EFFECTS
#define REC_EFFECTS
Definition: preferences.h:199
WEED_LEAF_HOST_ORIG_PDATA
#define WEED_LEAF_HOST_ORIG_PDATA
Definition: effects-weed.h:60
add_hsep_to_box
LiVESWidget * add_hsep_to_box(LiVESBox *box)
Definition: widget-helper.c:12355
_prefs::rec_opts
int rec_opts
Definition: preferences.h:196
pp_get_chan
const weed_plant_t * pp_get_chan(weed_plant_t **pparams, int idx)
Definition: plugins.c:1054
weed_palette_is_alpha
LIVES_GLOBAL_INLINE boolean weed_palette_is_alpha(int pal)
Definition: colourspace.c:1427
lives_tree_model_iter_next
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_iter_next(LiVESTreeModel *tmod, LiVESTreeIter *titer)
Definition: widget-helper.c:5764
lives_conx_w::omode
int omode
Definition: effects-data.h:133
_fx_dialog::key
int key
Definition: mainwindow.h:1844
lives_button_grab_default_special
boolean lives_button_grab_default_special(LiVESWidget *button)
Definition: widget-helper.c:7587
best_palette_match
int best_palette_match(int *palette_list, int num_palettes, int palette)
check palette vs.
Definition: effects-weed.c:868
lives_widget_set_no_show_all
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_no_show_all(LiVESWidget *widget, boolean set)
Definition: widget-helper.c:4868
lives_conx_w::acheck_func
ulong * acheck_func
Definition: effects-data.h:175
cconx_chain_data_internal
boolean cconx_chain_data_internal(weed_plant_t *ichan)
Definition: effects-data.c:2166
get_token_count
size_t get_token_count(const char *string, int delim)
Definition: utils.c:5430
add_fill_to_box
LiVESWidget * add_fill_to_box(LiVESBox *box)
Definition: widget-helper.c:12377
num_out_params
int num_out_params(weed_plant_t *plant)
Definition: effects-weed.c:3960
fx_dialog
_fx_dialog * fx_dialog[2]
Definition: mainwindow.h:1851
num_in_params
int num_in_params(weed_plant_t *plant, boolean skip_hidden, boolean skip_internal)
Definition: effects-weed.c:3920
lives_widget_is_sensitive
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_sensitive(LiVESWidget *widget)
Definition: widget-helper.c:4885
_fx_dialog::rfx
lives_rfx_t * rfx
Definition: mainwindow.h:1843
lives_conx_w::ccombo
LiVESWidget ** ccombo
Definition: effects-data.h:151
mainwindow::event_list
weed_event_t * event_list
current event_list, for recording
Definition: mainwindow.h:803
lives_conx_w::cfxcombo
LiVESWidget ** cfxcombo
Definition: effects-data.h:148
lives_label_get_text
WIDGET_HELPER_GLOBAL_INLINE const char * lives_label_get_text(LiVESLabel *label)
Definition: widget-helper.c:6056
do_error_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
GU641
#define GU641
Definition: mainwindow.h:209
mainwindow::fx_mutex
pthread_mutex_t fx_mutex[FX_KEYS_MAX]
used to prevent fx processing when it is scheduled for deinit
Definition: mainwindow.h:1497
lives_window_add_accel_group
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_add_accel_group(LiVESWindow *window, LiVESAccelGroup *group)
Definition: widget-helper.c:2968
lives_combo_get_model
WIDGET_HELPER_GLOBAL_INLINE LiVESTreeModel * lives_combo_get_model(LiVESCombo *combo)
Definition: widget-helper.c:3763
lives_tree_model_get
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_get(LiVESTreeModel *tmod, LiVESTreeIter *titer,...)
Definition: widget-helper.c:5708
lives_tree_model_get_iter
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_get_iter(LiVESTreeModel *tmod, LiVESTreeIter *titer, LiVESTreePath *tpath)
Definition: widget-helper.c:5721
lives_conx_w::pclabel
LiVESWidget ** pclabel
Definition: effects-data.h:147
TRUE
#define TRUE
Definition: videoplugin.h:59
lives_big_and_bold
char * lives_big_and_bold(const char *fmt,...)
Definition: widget-helper.c:8648
sizint
ssize_t sizint
type sizes
Definition: main.c:102
weed_seed_type_to_text
char * weed_seed_type_to_text(uint32_t seed_type)
Definition: weed-effects-utils.c:680
mainwindow::string_constants
char * string_constants[NUM_LIVES_STRING_CONSTANTS]
Definition: mainwindow.h:1539
cconx_remap_mode
void cconx_remap_mode(int key, int omode, int nmode)
Definition: effects-data.c:1744
EXTRA_PARAMS_OUT
#define EXTRA_PARAMS_OUT
Activate.
Definition: effects-data.h:15
MODEVAL_COLUMN
@ MODEVAL_COLUMN
Definition: effects-data.c:2292
filter_mutex_lock
LIVES_GLOBAL_INLINE int filter_mutex_lock(int key)
Definition: effects-weed.c:96
lives_table_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_table_new(uint32_t rows, uint32_t cols, boolean homogeneous)
Definition: widget-helper.c:6931
lives_conx_w::clabel
LiVESWidget ** clabel
Definition: effects-data.h:146
cconx_list
char * cconx_list(int okey, int omode, int ocnum)
Definition: effects-data.c:1635
lives_standard_combo_new
LiVESWidget * lives_standard_combo_new(const char *labeltext, LiVESList *list, LiVESBox *box, const char *tooltip)
Definition: widget-helper.c:9544
end_override_if_activate_output
void end_override_if_activate_output(int hotkey)
Definition: effects-data.c:126
weed_layer_pixel_data_free
void weed_layer_pixel_data_free(weed_layer_t *layer)
free pixel_data from layer
Definition: colourspace.c:13819
lives_rfx_t
Definition: plugins.h:625
is_pure_audio
boolean is_pure_audio(weed_plant_t *plant, boolean count_opt)
TRUE if audio in or out and no vid in/out.
Definition: effects-weed.c:714
lives_tree_store_new
WIDGET_HELPER_GLOBAL_INLINE LiVESTreeStore * lives_tree_store_new(int ncols,...)
Definition: widget-helper.c:5808
lives_combo_populate
boolean lives_combo_populate(LiVESCombo *combo, LiVESList *list)
Definition: widget-helper.c:7509
lives_conx_w::filter
weed_plant_t * filter
Definition: effects-data.h:130
widget_opts_t::last_label
LiVESWidget * last_label
commonly adjusted values //////
Definition: widget-helper.h:1406
lives_conx_w::dpc_func
ulong * dpc_func
Definition: effects-data.h:173
lives_grid_remove_row
WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_remove_row(LiVESGrid *grid, int posn)
Definition: widget-helper.c:6796
lives_conx_w::conx_dialog
LiVESWidget * conx_dialog
Definition: effects-data.h:141
lives_toggle_button_get_active
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
Definition: widget-helper.c:4472
widget_opts_t::mnemonic_label
boolean mnemonic_label
if underscore in label text should be mnemonic accelerator
Definition: widget-helper.h:1420
_vid_playback_plugin::play_params
weed_plant_t ** play_params
Definition: plugins.h:194
lives_conx_w::pfxcombo
LiVESWidget ** pfxcombo
Definition: effects-data.h:149
_vid_playback_plugin::num_alpha_chans
int num_alpha_chans
Definition: plugins.h:197
rte_getmodespk
LIVES_GLOBAL_INLINE int rte_getmodespk(void)
Definition: effects.c:1219
lives_table_resize
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_resize(LiVESTable *table, uint32_t rows, uint32_t cols)
Definition: widget-helper.c:7011
filter_mutex_unlock
LIVES_GLOBAL_INLINE int filter_mutex_unlock(int key)
Definition: effects-weed.c:108
lives_tree_store_set
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_store_set(LiVESTreeStore *tstore, LiVESTreeIter *titer,...)
Definition: widget-helper.c:5851
lives_general_button_clicked
void lives_general_button_clicked(LiVESButton *button, livespointer data_to_free)
Definition: widget-helper.c:12306
lives_tree_path_free
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_path_free(LiVESTreePath *tpath)
Definition: widget-helper.c:5772
get_new_inst_for_keymode
weed_plant_t * get_new_inst_for_keymode(int key, int mode)
get new refcounted inst (during recording playback)
Definition: effects-weed.c:9225
lives_conx_w::dispp
int * dispp
Definition: effects-data.h:167
_lives_pconnect_t
Definition: effects-data.h:28
cconx_chain_data
boolean cconx_chain_data(int key, int mode)
Definition: effects-data.c:2129
lives_dialog_get_action_area
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_dialog_get_action_area(LiVESDialog *dialog)
Definition: widget-helper.c:2495
lives_combo_get_active_index
WIDGET_HELPER_GLOBAL_INLINE int lives_combo_get_active_index(LiVESCombo *combo)
Definition: widget-helper.c:3909
create_empty_pixel_data
boolean create_empty_pixel_data(weed_layer_t *layer, boolean black_fill, boolean may_contig)
creates pixel data for layer
Definition: colourspace.c:9058
lives_standard_label_new
LiVESWidget * lives_standard_label_new(const char *text)
Definition: widget-helper.c:8601
lives_combo_set_active_index
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_index(LiVESCombo *combo, int index)
Definition: widget-helper.c:3883
weed_paramtmpl_get_type
WEED_GLOBAL_INLINE int weed_paramtmpl_get_type(weed_plant_t *paramtmpl)
Definition: weed-effects-utils.c:312
lives_vbox_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vbox_new(boolean homogeneous, int spacing)
Definition: widget-helper.c:3267
lives_standard_combo_new_with_model
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_standard_combo_new_with_model(LiVESTreeModel *model, LiVESBox *box)
Definition: widget-helper.c:9681
weed_paramtmpl_get_flags
WEED_GLOBAL_INLINE int weed_paramtmpl_get_flags(weed_plant_t *paramtmpl)
Definition: weed-effects-utils.c:300
widget_opts_t::use_markup
boolean use_markup
whether markup should be used in labels
Definition: widget-helper.h:1421
cconx_add_connection
void cconx_add_connection(int okey, int omode, int ocnum, int ikey, int imode, int icnum)
add a new connection from out_chan okey/omode/ocnum to in_chan ikey/imode/icnum
Definition: effects-data.c:1954
FX_DATA_KEY_PLAYBACK_PLUGIN
#define FX_DATA_KEY_PLAYBACK_PLUGIN
Definition: effects-data.h:12
lives_widget_get_parent
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_get_parent(LiVESWidget *widget)
Definition: widget-helper.c:4739
lives_combo_get_entry
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_combo_get_entry(LiVESCombo *widget)
Definition: widget-helper.c:12295
lives_conx_w::dpp_func
ulong * dpp_func
Definition: effects-data.h:174
lives_conx_w::num_alpha
int num_alpha
Definition: effects-data.h:134
lives_conx_w::cconx
lives_cconnect_t * cconx
Definition: effects-data.h:138
widget_opts_t::packing_height
int packing_height
vertical pixels between widgets
Definition: widget-helper.h:1411
has_video_chans_out
boolean has_video_chans_out(weed_plant_t *filter, boolean count_opt)
Definition: effects-weed.c:676
lives_hbox_new
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hbox_new(boolean homogeneous, int spacing)
Definition: widget-helper.c:3253
cconx_delete_all
void cconx_delete_all(void)
Definition: effects-data.c:1560
ce_thumbs.h
OSC_NOTIFY
#define OSC_NOTIFY
Definition: mainwindow.h:671
OMC_INTERNAL
#define OMC_INTERNAL
Definition: omc-learn.h:126
rte_keymode_get_instance
weed_plant_t * rte_keymode_get_instance(int key, int mode)
returns refcounted filter_instance bound to key/mode (or NULL)
Definition: effects-weed.c:9450
lives_strdup_printf
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
GUI_SCREEN_HEIGHT
#define GUI_SCREEN_HEIGHT
Definition: mainwindow.h:100
lives_calloc
#define lives_calloc
Definition: machinestate.h:67
convert_layer_palette
boolean convert_layer_palette(weed_layer_t *layer, int outpl, int op_clamping)
Definition: colourspace.c:11945
weed_filter_get_name
WEED_GLOBAL_INLINE char * weed_filter_get_name(weed_plant_t *filter)
Definition: weed-effects-utils.c:240
lives_conx_w::dispc
int * dispc
Definition: effects-data.h:166
lives_list_free_all
void lives_list_free_all(LiVESList **)
Definition: utils.c:4873
lives_tree_store_append
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_store_append(LiVESTreeStore *tstore, LiVESTreeIter *titer, LiVESTreeIter *parent)
Definition: widget-helper.c:5831
mainwindow::is_rendering
boolean is_rendering
Definition: mainwindow.h:821
WEED_LEAF_HOST_INTERNAL_CONNECTION
#define WEED_LEAF_HOST_INTERNAL_CONNECTION
Definition: effects-weed.h:102
lives_conx_w::disconbutton
LiVESWidget * disconbutton
Definition: effects-data.h:144
num_alpha_channels
int num_alpha_channels(weed_plant_t *filter, boolean out)
Definition: effects-weed.c:321
FX_KEYS_MAX_VIRTUAL
#define FX_KEYS_MAX_VIRTUAL
must be >= FX_KEYS_PHYSICAL, and <=64 (number of bits in a 64bit int mask) (max number of keys accesi...
Definition: mainwindow.h:203
lives_conx_w::tablec
LiVESWidget * tablec
Definition: effects-data.h:158
_fx_dialog::mode
int mode
Definition: mainwindow.h:1845
lives_table_set_row_spacings
WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_row_spacings(LiVESTable *table, uint32_t spacing)
Definition: widget-helper.c:6959
pconx_remap_mode
void pconx_remap_mode(int key, int omode, int nmode)
Definition: effects-data.c:380
lives_conx_w::trowsp
int trowsp
Definition: effects-data.h:163
cconx_delete
void cconx_delete(int okey, int omode, int ocnum, int ikey, int imode, int icnum)
Definition: effects-data.c:1663
lives_conx_w
Definition: effects-data.h:129
lives_memcpy
#define lives_memcpy
Definition: machinestate.h:55
NAME_COLUMN
@ NAME_COLUMN
Definition: effects-data.c:2290
lives_widget_set_sensitive
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive(LiVESWidget *widget, boolean state)
Definition: widget-helper.c:1477
lives_accel_group_new
WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup * lives_accel_group_new(void)
Definition: widget-helper.c:2915
make_datacon_window
LiVESWidget * make_datacon_window(int key, int mode)
Definition: effects-data.c:4722
myround
#define myround(n)
Definition: main.h:300
lives_entry_set_width_chars
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_width_chars(LiVESEntry *entry, int nchars)
Definition: widget-helper.c:6223
lives_conx_w::ntabs
int ntabs
Definition: effects-data.h:136
lives_conx_w::apbutton
LiVESWidget * apbutton
Definition: effects-data.h:143
_lives_cconnect_t
Definition: effects-data.h:84
mainwindow::record_paused
volatile boolean record_paused
pause during recording
Definition: mainwindow.h:1557
mainwindow::last_grabbable_effect
uint32_t last_grabbable_effect
Definition: mainwindow.h:869
mainwindow::ce_thumbs
boolean ce_thumbs
Definition: mainwindow.h:1676
mainwindow::fxd_active_mutex
pthread_mutex_t fxd_active_mutex
prevent simultaneous writing to active_dummy by audio and video threads
Definition: mainwindow.h:1498
main.h
lives_grid_insert_row
WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_insert_row(LiVESGrid *grid, int posn)
Definition: widget-helper.c:6807
pconx_list
char * pconx_list(int okey, int omode, int opnum)
Definition: effects-data.c:231
get_enabled_channel
weed_plant_t * get_enabled_channel(weed_plant_t *inst, int which, boolean is_in)
for FILTER_INST
Definition: effects-weed.c:536
lives_conx_w::imodes
int * imodes
Definition: effects-data.h:170
get_omc_macro
const lives_omc_macro_t * get_omc_macro(int idx)
pconx_add_connection
void pconx_add_connection(int okey, int omode, int opnum, int ikey, int imode, int ipnum, boolean autoscale)
add a new connection from out_param okey/omode/opnum to in_param ikey/imode/ipnum
Definition: effects-data.c:618
mainw
mainwindow * mainw
Definition: main.c:103
mainwindow::pconx
lives_pconnect_t * pconx
list of out -> in param connections
Definition: mainwindow.h:1668
LIVES_STRING_CONSTANT_NONE
@ LIVES_STRING_CONSTANT_NONE
Definition: mainwindow.h:371
weed_instance_unref
LIVES_GLOBAL_INLINE int weed_instance_unref(weed_plant_t *inst)
Definition: effects-weed.c:6234
lives_standard_scrolled_window_new
LiVESWidget * lives_standard_scrolled_window_new(int width, int height, LiVESWidget *child)
Definition: widget-helper.c:10272
lives_entry_set_text
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text)
Definition: widget-helper.c:6211
lives_entry_set_editable
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_editable(LiVESEntry *entry, boolean editable)
Definition: widget-helper.c:7422
WEED_LEAF_HOST_NEXT_INSTANCE
#define WEED_LEAF_HOST_NEXT_INSTANCE
Definition: effects-weed.h:104
lives_widget_show_all
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
Definition: widget-helper.c:1523
has_video_chans_in
boolean has_video_chans_in(weed_plant_t *filter, boolean count_opt)
Definition: effects-weed.c:620
lives_toggle_button_set_active
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_active(LiVESToggleButton *button, boolean active)
Definition: widget-helper.c:4483
widget_opts
widget_opts_t widget_opts
Definition: widget-helper.h:1442
weed_instance_get_filter
weed_plant_t * weed_instance_get_filter(weed_plant_t *inst, boolean get_compound_parent)
Definition: effects-weed.c:180
mainwindow::rte
volatile uint64_t rte
current max for VJ mode == 64 effects on fg clip
Definition: mainwindow.h:867
lives_conx_w::del_button
LiVESWidget ** del_button
Definition: effects-data.h:154
EXTRA_PARAMS_IN
#define EXTRA_PARAMS_IN
Activated.
Definition: effects-data.h:16
lives_standard_button_new_from_stock
LiVESWidget * lives_standard_button_new_from_stock(const char *stock_id, const char *label, int width, int height)
Definition: widget-helper.c:4215
lives_signal_handler_unblock
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_unblock(livespointer instance, unsigned long handler_id)
Definition: widget-helper.c:947
KEY_COLUMN
@ KEY_COLUMN
Definition: effects-data.c:2289
omc-learn.h
GUI_SCREEN_WIDTH
#define GUI_SCREEN_WIDTH
Definition: mainwindow.h:99
has_audio_chans_out
boolean has_audio_chans_out(weed_plant_t *filter, boolean count_opt)
Definition: effects-weed.c:695
pconx_chain_data
boolean pconx_chain_data(int key, int mode, boolean is_audio_thread)
Definition: effects-data.c:1390
lives_standard_check_button_new
LiVESWidget * lives_standard_check_button_new(const char *labeltext, boolean active, LiVESBox *box, const char *tooltip)
Definition: widget-helper.c:9048
lives_widget_get_sensitive
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_sensitive(LiVESWidget *widget)
Definition: widget-helper.c:1497
lives_combo_set_active_iter
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_iter(LiVESCombo *combo, LiVESTreeIter *iter)
Definition: widget-helper.c:3892
rte_key_getmode
int rte_key_getmode(int key)
returns current active mode for a key (or -1)
Definition: effects-weed.c:9424
ulong
#define ulong
Definition: main.h:178
mainwindow::cconx
lives_cconnect_t * cconx
list of out -> in alpha channel connections
Definition: mainwindow.h:1669
WEED_LEAF_HOST_INTERNAL_CONNECTION_AUTOSCALE
#define WEED_LEAF_HOST_INTERNAL_CONNECTION_AUTOSCALE
Definition: effects-weed.h:103
lives_signal_handler_block
WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_block(livespointer instance, unsigned long handler_id)
Definition: widget-helper.c:933
has_audio_chans_in
boolean has_audio_chans_in(weed_plant_t *filter, boolean count_opt)
Definition: effects-weed.c:640
lives_conx_w::pconx
lives_pconnect_t * pconx
Definition: effects-data.h:139
lives_conx_w::acbutton
LiVESWidget * acbutton
Definition: effects-data.h:142
FALSE
#define FALSE
Definition: videoplugin.h:60
mainwindow::vrfx_update
volatile lives_rfx_t * vrfx_update
single access for updating alarm list
Definition: mainwindow.h:1510
_
#define _(String)
Definition: support.h:44
lives_widget_set_tooltip_text
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_set_tooltip_text(LiVESWidget *widget, const char *tip_text)
Definition: widget-helper.c:4641
do_error_dialogf
LiVESResponseType do_error_dialogf(const char *fmt,...)
Definition: dialogs.c:735
weed_palette_get_bits_per_macropixel
LIVES_GLOBAL_INLINE int weed_palette_get_bits_per_macropixel(int pal)
Definition: colourspace.c:1411
weed_instance_get_gui
WEED_GLOBAL_INLINE weed_plant_t * weed_instance_get_gui(weed_plant_t *inst, int create_if_not_exists)
Definition: weed-effects-utils.c:158
rec_param_change
void rec_param_change(weed_plant_t *inst, int pnum)
record a parameter value change in our event_list
Definition: effects-weed.c:9000
SHORTER_ENTRY_WIDTH
#define SHORTER_ENTRY_WIDTH
Definition: widget-helper.h:32
lives_tree_model_get_iter_first
WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_get_iter_first(LiVESTreeModel *tmod, LiVESTreeIter *titer)
Definition: widget-helper.c:5730
SCR_WIDTH_SAFETY
#define SCR_WIDTH_SAFETY
sepwin/screen size safety margins in pixels
Definition: mainwindow.h:89
lives_widget_context_update
boolean lives_widget_context_update(void)
Definition: widget-helper.c:11878
feeds_to_audio_filters
boolean feeds_to_audio_filters(int okey, int omode)
Definition: effects-data.c:2228
lives_conx_w::allcheck_label
LiVESWidget * allcheck_label
Definition: effects-data.h:156
lives_combo_get_active_iter
WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_get_active_iter(LiVESCombo *combo, LiVESTreeIter *iter)
Definition: widget-helper.c:3901
KEYVAL_COLUMN
@ KEYVAL_COLUMN
Definition: effects-data.c:2291
lives_conx_w::idx
int * idx
Definition: effects-data.h:171
BW
#define BW
Definition: effects-data.c:41
pconx_delete
void pconx_delete(int okey, int omode, int opnum, int ikey, int imode, int ipnum)
Definition: effects-data.c:262
_vid_playback_plugin::num_play_params
int num_play_params
Definition: plugins.h:196
lives_box_pack_start
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_start(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill, uint32_t padding)
Definition: widget-helper.c:3281