1 // lbindings.c
2 // LiVES (lives-exe)
3 // (c) G. Finch <salsaman+lives@gmail.com> 2015 - 2019
4 // Released under the GPL 3 or later
5 // see file ../COPYING for licensing details
6 
7 #define NEED_ENDIAN_TEST
8 
9 #include "main.h"
10 #include "interface.h"
11 #include "callbacks.h"
12 #include "rte_window.h"
13 #include "effects-weed.h"
14 #include "effects.h"
15 
16 #include "liblives.hpp"
17 
18 typedef boolean Boolean;
19 
20 #include <libOSC/libosc.h>
21 #include <libOSC/OSC-client.h>
22 
23 typedef struct {
24   // c
25   ulong id;
26   char *msg;
27 } msginfo;
28 
29 typedef struct {
30   // i, c
31   ulong id;
32   int val;
33   char *string;
34 } lset;
35 
36 typedef struct {
37   // i,v
38   ulong id;
39   int arglen;
40   const void *vargs;
41 } oscdata;
42 
43 typedef struct {
44   // c, d, i
45   ulong id;
46   char *fname;
47   double stime;
48   int frames;
49 } opfidata;
50 
51 typedef struct {
52   // c, c, i
53   ulong id;
54   char *dir;
55   char *title;
56   int preview_type;
57 } fprev;
58 
59 typedef struct {
60   // b
61   ulong id;
62   boolean setting;
63 } sintdata;
64 
65 typedef struct {
66   ulong id;
67 } udata;
68 
69 typedef struct {
70   // i, i, i
71   ulong id;
72   int key;
73   int mode;
74   int idx;
75 } fxmapdata;
76 
77 typedef struct {
78   // c, b
79   // boolean pref
80   ulong id;
81   char *prefidx;
82   boolean val;
83 } bpref;
84 
85 typedef struct {
86   // i, b
87   // boolean pref
88   ulong id;
89   int integ;
90   boolean val;
91 } ibpref;
92 
93 typedef struct {
94   // c, i, b
95   // bitmapped pref
96   ulong id;
97   char *prefidx;
98   int bitfield;
99   boolean val;
100 } bmpref;
101 
102 typedef struct {
103   // c, i
104   // int pref
105   ulong id;
106   char *prefidx;
107   int val;
108 } ipref;
109 
110 typedef struct {
111   // i, i
112   // int pref
113   ulong id;
114   char *prefidx;
115   int integ;
116   int val;
117 } iipref;
118 
119 typedef struct {
120   // i, b, b
121   ulong id;
122   int clip;
123   boolean ign_sel;
124   boolean with_audio;
125 } iblock;
126 
127 typedef struct {
128   ulong id;
129   track_rect *block;
130   int track;
131   double time;
132 } mblockdata;
133 
134 /////////////////////////////////////////
135 /// extern functions with no headers
136 
137 boolean lives_osc_cb_saveset(void *context, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra);
138 boolean lives_osc_cb_play(void *context, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra);
139 
140 boolean lives_osc_cb_clip_goto(void *context, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra);
141 boolean lives_osc_cb_bgclip_goto(void *context, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra);
142 
143 
144 /// osc utils
145 
padup(char ** str,int arglen)146 int padup(char **str, int arglen) {
147   int newlen = pad4(arglen);
148   char *ostr = *str;
149   *str = (char *)lives_calloc(newlen, 1);
150   lives_memcpy(*str, ostr, arglen);
151   lives_free(ostr);
152   return newlen;
153 }
154 
155 
add_int_arg(char ** str,int arglen,int val)156 int add_int_arg(char **str, int arglen, int val) {
157   int newlen = arglen + 4;
158   char *ostr = *str;
159   *str = (char *)lives_calloc(newlen, 1);
160   lives_memcpy(*str, ostr, arglen);
161   if (!IS_BIG_ENDIAN) {
162     (*str)[arglen] = (unsigned char)((val & 0xFF000000) >> 3);
163     (*str)[arglen + 1] = (unsigned char)((val & 0x00FF0000) >> 2);
164     (*str)[arglen + 2] = (unsigned char)((val & 0x0000FF00) >> 1);
165     (*str)[arglen + 3] = (unsigned char)(val & 0x000000FF);
166   } else {
167     lives_memcpy(*str + arglen, &val, 4);
168   }
169   lives_free(ostr);
170   return newlen;
171 }
172 
173 
add_string_arg(char ** str,int arglen,const char * val)174 static int add_string_arg(char **str, int arglen, const char *val) {
175   int newlen = arglen + strlen(val) + 1;
176   char *ostr = *str;
177   *str = (char *)lives_calloc(newlen, 1);
178   lives_memcpy(*str, ostr, arglen);
179   lives_memcpy(*str + arglen, val, strlen(val));
180   lives_free(ostr);
181   return newlen;
182 }
183 
184 
185 /////////// value return functions ///////////////////////
186 
ext_caller_return_int(ulong caller_id,int ret)187 static void ext_caller_return_int(ulong caller_id, int ret) {
188   // this is for the C++ binding
189   char *msgstring = lives_strdup_printf("%lu %d", caller_id, ret);
190   if (mainw != NULL) binding_cb(LIVES_CALLBACK_PRIVATE, msgstring, mainw->id);
191   lives_free(msgstring);
192 }
193 
194 
ext_caller_return_ulong(ulong caller_id,ulong ret)195 static void ext_caller_return_ulong(ulong caller_id, ulong ret) {
196   // this is for the C++ binding
197   char *msgstring = lives_strdup_printf("%lu %lu", caller_id, ret);
198   if (mainw != NULL) binding_cb(LIVES_CALLBACK_PRIVATE, msgstring, mainw->id);
199   lives_free(msgstring);
200 }
201 
202 
ext_caller_return_string(ulong caller_id,const char * ret)203 static void ext_caller_return_string(ulong caller_id, const char *ret) {
204   // this is for the C++ binding
205   char *msgstring = lives_strdup_printf("%lu %s", caller_id, ret);
206   if (mainw != NULL) binding_cb(LIVES_CALLBACK_PRIVATE, msgstring, mainw->id);
207   lives_free(msgstring);
208 }
209 
210 
211 ///////////////////////////////////////////////////////////////
212 /// utility functions for liblives /////
213 
get_unique_ids(void)214 ulong *get_unique_ids(void) {
215   // return array of unique_id (ulong) for all "real" clips
216   int i = 0;
217   ulong *uids = NULL;
218   LiVESList *list;
219   if (mainw != NULL && !mainw->go_away) {
220     pthread_mutex_lock(&mainw->clip_list_mutex);
221     list = mainw->cliplist;
222     uids = (ulong *)lives_malloc((lives_list_length(mainw->cliplist) + 1) * sizeof(ulong));
223     while (list != NULL) {
224       int uid = 0;
225       int cnum = LIVES_POINTER_TO_INT(list->data);
226       if (mainw->files[cnum] != NULL) uid = mainw->files[cnum]->unique_id;
227       list = list->next;
228       if (uid == 0) continue;
229       uids[i++] = uid;
230     }
231     uids[i] = 0;
232     pthread_mutex_unlock(&mainw->clip_list_mutex);
233   }
234   return uids;
235 }
236 
237 
cnum_for_uid(ulong uid)238 int cnum_for_uid(ulong uid) {
239   LiVESList *list;
240   if (mainw != NULL && !mainw->go_away) {
241     pthread_mutex_lock(&mainw->clip_list_mutex);
242     list = mainw->cliplist;
243     while (list != NULL) {
244       int cnum = LIVES_POINTER_TO_INT(list->data);
245       if (mainw->files[cnum] != NULL && uid == mainw->files[cnum]->unique_id) {
246         pthread_mutex_unlock(&mainw->clip_list_mutex);
247         return cnum;
248       }
249       list = list->next;
250     }
251     pthread_mutex_unlock(&mainw->clip_list_mutex);
252   }
253   return -1;
254 }
255 
256 
start_player(void)257 boolean start_player(void) {
258   boolean ret;
259   int arglen = 1;
260   char **vargs = (char **)lives_malloc(sizeof(char *));
261   *vargs = lives_strdup(",");
262   arglen = padup(vargs, arglen);
263 
264   // this will set our idlefunc and return (TODO: don't set osc_auto)
265   ret = lives_osc_cb_play(NULL, arglen, (const void *)(*vargs), OSCTT_CurrentTime(), NULL);
266   if (ret) {
267     while (!mainw->error && mainw->playing_file < 0) lives_usleep(prefs->sleep_time);
268     if (mainw->error) ret = FALSE;
269   }
270 
271   lives_free(*vargs);
272   lives_free(vargs);
273   return ret;
274 }
275 
276 enum {
277   const_domain_notify,
278   const_domain_response,
279   const_domain_grav,
280   const_domain_insert_mode
281 };
282 
283 
trans_rev(int consta,int a,int b)284 LIVES_LOCAL_INLINE int trans_rev(int consta, int a, int b) {
285   if (consta == a) return b;
286   else return consta;
287 }
288 
289 
trans_constant(int consta,int domain)290 static int trans_constant(int consta, int domain) {
291   int nconsta;
292   if (domain == const_domain_notify) {
293     nconsta = trans_rev(consta, LIVES_CALLBACK_FRAME_SYNCH, LIVES_OSC_NOTIFY_FRAME_SYNCH);
294     if (nconsta != consta) return nconsta;
295     nconsta = trans_rev(consta, LIVES_CALLBACK_PLAYBACK_STARTED, LIVES_OSC_NOTIFY_PLAYBACK_STARTED);
296     if (nconsta != consta) return nconsta;
297     nconsta = trans_rev(consta, LIVES_CALLBACK_PLAYBACK_STOPPED, LIVES_OSC_NOTIFY_PLAYBACK_STOPPED);
298     if (nconsta != consta) return nconsta;
299     nconsta = trans_rev(consta, LIVES_CALLBACK_PLAYBACK_STOPPED_RD, LIVES_OSC_NOTIFY_PLAYBACK_STOPPED_RD);
300     if (nconsta != consta) return nconsta;
301     nconsta = trans_rev(consta, LIVES_CALLBACK_RECORD_STARTED, LIVES_OSC_NOTIFY_RECORD_STARTED);
302     if (nconsta != consta) return nconsta;
303     nconsta = trans_rev(consta, LIVES_CALLBACK_RECORD_STOPPED, LIVES_OSC_NOTIFY_RECORD_STOPPED);
304     if (nconsta != consta) return nconsta;
305     nconsta = trans_rev(consta, LIVES_CALLBACK_APP_QUIT, LIVES_OSC_NOTIFY_QUIT);
306     if (nconsta != consta) return nconsta;
307     nconsta = trans_rev(consta, LIVES_CALLBACK_CLIP_OPENED, LIVES_OSC_NOTIFY_CLIP_OPENED);
308     if (nconsta != consta) return nconsta;
309     nconsta = trans_rev(consta, LIVES_CALLBACK_CLIP_CLOSED, LIVES_OSC_NOTIFY_CLIP_CLOSED);
310     if (nconsta != consta) return nconsta;
311     nconsta = trans_rev(consta, LIVES_CALLBACK_CLIPSET_OPENED, LIVES_OSC_NOTIFY_CLIPSET_OPENED);
312     if (nconsta != consta) return nconsta;
313     nconsta = trans_rev(consta, LIVES_CALLBACK_CLIPSET_SAVED, LIVES_OSC_NOTIFY_CLIPSET_SAVED);
314     if (nconsta != consta) return nconsta;
315     nconsta = trans_rev(consta, LIVES_CALLBACK_MODE_CHANGED, LIVES_OSC_NOTIFY_MODE_CHANGED);
316     if (nconsta != consta) return nconsta;
317   }
318   if (domain == const_domain_response) {
319     if (consta == LIVES_RESPONSE_NONE) return LIVES_DIALOG_RESPONSE_NONE;
320     if (consta == LIVES_RESPONSE_OK) return LIVES_DIALOG_RESPONSE_OK;
321     if (consta == LIVES_RESPONSE_CANCEL) return LIVES_DIALOG_RESPONSE_CANCEL;
322     if (consta == LIVES_RESPONSE_ACCEPT) return LIVES_DIALOG_RESPONSE_ACCEPT;
323     if (consta == LIVES_RESPONSE_YES) return LIVES_DIALOG_RESPONSE_YES;
324     if (consta == LIVES_RESPONSE_NO) return LIVES_DIALOG_RESPONSE_NO;
325 
326     // positive values for custom responses
327     if (consta == LIVES_RESPONSE_INVALID) return LIVES_DIALOG_RESPONSE_INVALID;
328     if (consta == LIVES_RESPONSE_RETRY) return LIVES_DIALOG_RESPONSE_RETRY;
329     if (consta == LIVES_RESPONSE_ABORT) return LIVES_DIALOG_RESPONSE_ABORT;
330     if (consta == LIVES_RESPONSE_RESET) return LIVES_DIALOG_RESPONSE_RESET;
331     if (consta == LIVES_RESPONSE_SHOW_DETAILS) return LIVES_DIALOG_RESPONSE_SHOW_DETAILS;
332   }
333 
334   if (domain == const_domain_grav) {
335     if (consta == LIVES_GRAVITY_NORMAL) return GRAV_MODE_NORMAL;
336     if (consta == LIVES_GRAVITY_LEFT) return GRAV_MODE_LEFT;
337     if (consta == LIVES_GRAVITY_RIGHT) return GRAV_MODE_RIGHT;
338   }
339 
340   if (domain == const_domain_insert_mode) {
341     if (consta == LIVES_INSERT_MODE_NORMAL) return INSERT_MODE_NORMAL;
342   }
343 
344   return consta;
345 }
346 
347 
get_first_fx_matched(const char * package,const char * fxname,const char * author,int version)348 int get_first_fx_matched(const char *package, const char *fxname, const char *author, int version) {
349   int *allvals = weed_get_indices_from_template(package, fxname, author, version);
350   int fval = allvals[0];
351   lives_free(allvals);
352   return fval;
353 }
354 
355 
356 // 1 based key here
get_num_mapped_modes_for_key(int key)357 int get_num_mapped_modes_for_key(int key) {
358   return rte_key_getmaxmode(key) + 1;
359 }
360 
361 
get_current_mode_for_key(int key)362 int get_current_mode_for_key(int key) {
363   return rte_key_getmode(key);
364 }
365 
366 
get_rte_key_is_enabled(int key)367 boolean get_rte_key_is_enabled(int key) {
368   return rte_key_is_enabled(key);
369 }
370 
371 
372 //// interface callers
373 
call_osc_show_info(livespointer text)374 static boolean call_osc_show_info(livespointer text) {
375   // function that is picked up on idle
376   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
377     do_info_dialog(text);
378   }
379   lives_free(text);
380   return FALSE;
381 }
382 
383 
call_osc_show_blocking_info(livespointer data)384 static boolean call_osc_show_blocking_info(livespointer data) {
385   // function that is picked up on idle
386   int ret = LIVES_RESPONSE_INVALID;
387   msginfo *minfo = (msginfo *)data;
388   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
389     ret = do_info_dialog(minfo->msg);
390     ret = trans_constant(ret, const_domain_notify);
391   }
392   ext_caller_return_int(minfo->id, ret);
393   lives_free(minfo->msg);
394   lives_free(data);
395   return FALSE;
396 }
397 
398 
call_osc_save_set(livespointer data)399 static boolean call_osc_save_set(livespointer data) {
400   // function that is picked up on idle
401   boolean ret = FALSE;
402   oscdata *oscd = (oscdata *)data;
403   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
404     ret = lives_osc_cb_saveset(NULL, oscd->arglen, oscd->vargs, OSCTT_CurrentTime(), NULL);
405   }
406   ext_caller_return_int(oscd->id, (int)ret);
407   lives_free((char *) * ((char **)(oscd->vargs)));
408   lives_free((char **)(oscd->vargs));
409   lives_free(data);
410   return FALSE;
411 }
412 
413 
call_file_choose_with_preview(livespointer data)414 static boolean call_file_choose_with_preview(livespointer data) {
415   LiVESWidget *chooser;
416   fprev *fdata = (fprev *)data;
417 
418   char *fname = NULL, *rstr = NULL;
419 
420   int preview_type;
421   int response;
422 
423   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
424     if (fdata->preview_type == LIVES_FILE_CHOOSER_VIDEO_AUDIO) preview_type = LIVES_FILE_SELECTION_VIDEO_AUDIO;
425     else preview_type = LIVES_FILE_SELECTION_AUDIO_ONLY;
426     chooser = choose_file_with_preview(fdata->dir, fdata->title, NULL, preview_type);
427     response = lives_dialog_run(LIVES_DIALOG(chooser));
428     end_fs_preview();
429 
430     if (response == LIVES_RESPONSE_ACCEPT) {
431       fname = lives_file_chooser_get_filename(LIVES_FILE_CHOOSER(chooser));
432     }
433     if (fname == NULL) fname = lives_strdup("");
434 
435     on_filechooser_cancel_clicked(chooser);
436 
437     if (fdata->dir != NULL) lives_free(fdata->dir);
438     if (fdata->title != NULL) lives_free(fdata->title);
439 
440     rstr = lives_strdup_printf("%s %d", fname, mainw->open_deint);
441   }
442   ext_caller_return_string(fdata->id, rstr);
443   if (rstr != NULL) lives_free(rstr);
444   if (fdata != NULL) lives_free(fdata);
445   if (fname != NULL) free(fname);
446   if (data != NULL) lives_free(data);
447   return FALSE;
448 }
449 
450 
call_choose_set(livespointer data)451 static boolean call_choose_set(livespointer data) {
452   udata *ud = (udata *)data;
453   if (mainw != NULL && !mainw->was_set && !mainw->go_away && !mainw->is_processing) {
454     char *setname = on_load_set_activate(NULL, (livespointer)1);
455     if (setname == NULL) setname = lives_strdup("");
456     ext_caller_return_string(ud->id, setname);
457     lives_free(setname);
458   } else ext_caller_return_string(ud->id, "");
459   lives_free(data);
460   return FALSE;
461 }
462 
463 
call_set_set_name(livespointer data)464 static boolean call_set_set_name(livespointer data) {
465   ulong uid = (ulong)data;
466   boolean ret = FALSE;
467 
468   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !LIVES_IS_PLAYING) {
469     ret = set_new_set_name(mainw->multitrack);
470   } else ext_caller_return_int(uid, (int)ret);
471   return FALSE;
472 }
473 
474 
call_open_file(livespointer data)475 static boolean call_open_file(livespointer data) {
476   opfidata *opfi = (opfidata *)data;
477   ulong uid = 0l;
478   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
479     uid = open_file_sel(opfi->fname, opfi->stime, opfi->frames);
480     if (opfi->fname != NULL) lives_free(opfi->fname);
481   }
482   ext_caller_return_ulong(opfi->id, uid);
483   lives_free(opfi->fname);
484   lives_free(data);
485   return FALSE;
486 }
487 
488 
call_reload_set(livespointer data)489 static boolean call_reload_set(livespointer data) {
490   msginfo *mdata = (msginfo *)data;
491   boolean resp = FALSE;
492   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
493     mainw->osc_auto = 1;
494     if (!strlen(mdata->msg)) {
495       lives_free(mdata->msg);
496       mdata->msg = on_load_set_activate(NULL, (livespointer)1);
497       if (mdata->msg == NULL) mdata->msg = lives_strdup("");
498     }
499     if (!is_legal_set_name(mdata->msg, TRUE, TRUE)) {
500       mainw->osc_auto = 0;
501       resp = FALSE;
502     } else {
503       mainw->osc_auto = 0;
504       resp = reload_set(mdata->msg);
505     }
506   }
507   lives_free(mdata->msg);
508   ext_caller_return_int(mdata->id, resp);
509   lives_free(data);
510   return FALSE;
511 }
512 
513 
call_set_interactive(livespointer data)514 static boolean call_set_interactive(livespointer data) {
515   sintdata *sint = (sintdata *)data;
516   if (mainw != NULL && !mainw->go_away) {
517     prefs->interactive = sint->setting;
518     set_interactive(prefs->interactive);
519     ext_caller_return_int(sint->id, TRUE);
520   } else ext_caller_return_int(sint->id, FALSE);
521   lives_free(data);
522   return FALSE;
523 }
524 
525 
call_set_sepwin(livespointer data)526 static boolean call_set_sepwin(livespointer data) {
527   sintdata *sint = (sintdata *)data;
528   if (mainw != NULL && !mainw->go_away) {
529     if (mainw->sep_win != sint->setting)
530       on_sepwin_pressed(NULL, NULL);
531     ext_caller_return_int(sint->id, TRUE);
532   } else ext_caller_return_int(sint->id, FALSE);
533   lives_free(data);
534   return FALSE;
535 }
536 
537 
call_set_fullscreen(livespointer data)538 static boolean call_set_fullscreen(livespointer data) {
539   sintdata *sint = (sintdata *)data;
540   if (mainw != NULL && !mainw->go_away) {
541     if (mainw->fs != sint->setting)
542       on_full_screen_pressed(NULL, NULL);
543     ext_caller_return_int(sint->id, TRUE);
544   } else ext_caller_return_int(sint->id, FALSE);
545   lives_free(data);
546   return FALSE;
547 }
548 
549 
call_set_fullscreen_sepwin(livespointer data)550 static boolean call_set_fullscreen_sepwin(livespointer data) {
551   sintdata *sint = (sintdata *)data;
552   if (mainw != NULL && !mainw->go_away) {
553     if (mainw->sep_win != sint->setting)
554       on_sepwin_pressed(NULL, NULL);
555     if (mainw->fs != sint->setting)
556       on_full_screen_pressed(NULL, NULL);
557     ext_caller_return_int(sint->id, TRUE);
558   } else ext_caller_return_int(sint->id, FALSE);
559   lives_free(data);
560   return FALSE;
561 }
562 
563 
call_set_ping_pong(livespointer data)564 static boolean call_set_ping_pong(livespointer data) {
565   sintdata *sint = (sintdata *)data;
566   if (mainw != NULL && !mainw->go_away) {
567     if (mainw->ping_pong != sint->setting)
568       lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mainw->loop_ping_pong), !mainw->ping_pong);
569     ext_caller_return_int(sint->id, TRUE);
570   } else ext_caller_return_int(sint->id, FALSE);
571   lives_free(data);
572   return FALSE;
573 }
574 
575 
call_set_pref_bool(livespointer data)576 static boolean call_set_pref_bool(livespointer data) {
577   bpref *bdata = (bpref *)data;
578   if (mainw != NULL && !mainw->go_away) {
579     pref_factory_bool(bdata->prefidx, bdata->val, TRUE);
580     ext_caller_return_int(bdata->id, TRUE);
581   } else ext_caller_return_int(bdata->id, FALSE);
582   lives_free(bdata->prefidx);
583   lives_free(data);
584   return FALSE;
585 }
586 
587 
call_set_pref_int(livespointer data)588 static boolean call_set_pref_int(livespointer data) {
589   ipref *idata = (ipref *)data;
590   if (mainw != NULL && !mainw->go_away) {
591     pref_factory_int(idata->prefidx, idata->val, TRUE);
592     ext_caller_return_int(idata->id, TRUE);
593   } else ext_caller_return_int(idata->id, FALSE);
594   lives_free(data);
595   return FALSE;
596 }
597 
598 
call_set_pref_bitmapped(livespointer data)599 static boolean call_set_pref_bitmapped(livespointer data) {
600   bmpref *bmdata = (bmpref *)data;
601   if (mainw != NULL && !mainw->go_away) {
602     pref_factory_bitmapped(bmdata->prefidx, bmdata->bitfield, bmdata->val, TRUE);
603     ext_caller_return_int(bmdata->id, TRUE);
604   } else ext_caller_return_int(bmdata->id, FALSE);
605   lives_free(data);
606   return FALSE;
607 }
608 
609 
call_set_gravity(livespointer data)610 static boolean call_set_gravity(livespointer data) {
611   iipref *idata = (iipref *)data;
612   if (mainw != NULL && !mainw->go_away && mainw->multitrack != NULL) {
613     lives_mt_grav_mode_t grav = trans_constant(idata->val, const_domain_grav);
614     mainw->multitrack->opts.grav_mode = grav;
615     update_grav_mode(mainw->multitrack);
616   } else ext_caller_return_int(idata->id, FALSE);
617   lives_free(idata);
618   return FALSE;
619 }
620 
621 
call_set_insert_mode(livespointer data)622 static boolean call_set_insert_mode(livespointer data) {
623   iipref *idata = (iipref *)data;
624   if (mainw != NULL && !mainw->go_away && mainw->multitrack != NULL) {
625     lives_mt_insert_mode_t mode = trans_constant(idata->val, const_domain_insert_mode);
626     mainw->multitrack->opts.insert_mode = mode;
627     update_insert_mode(mainw->multitrack);
628   } else ext_caller_return_int(idata->id, FALSE);
629   lives_free(idata);
630   return FALSE;
631 }
632 
633 
call_mt_set_track(livespointer data)634 static boolean call_mt_set_track(livespointer data) {
635   iipref *idata = (iipref *)data;
636   if (mainw != NULL && !mainw->go_away && mainw->multitrack != NULL && (mt_track_is_video(mainw->multitrack, idata->val)
637       || mt_track_is_audio(mainw->multitrack, idata->val))) {
638     mainw->multitrack->current_track = idata->val;
639     track_select(mainw->multitrack);
640     ext_caller_return_int(idata->id, TRUE);
641   } else ext_caller_return_int(idata->id, FALSE);
642   lives_free(data);
643   return FALSE;
644 }
645 
646 
call_insert_vtrack(livespointer data)647 static boolean call_insert_vtrack(livespointer data) {
648   ibpref *ibdata = (ibpref *)data;
649   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !LIVES_IS_PLAYING && mainw->multitrack != NULL) {
650     int tnum;
651     if (!ibdata->val) tnum = add_video_track_behind(NULL, mainw->multitrack);
652     else tnum = add_video_track_front(NULL, mainw->multitrack);
653     ext_caller_return_int(ibdata->id, tnum);
654   } else ext_caller_return_int(ibdata->id, -1);
655   lives_free(data);
656   return FALSE;
657 }
658 
659 
call_mt_set_track_label(livespointer data)660 static boolean call_mt_set_track_label(livespointer data) {
661   lset *ldata = (lset *)data;
662   if (mainw != NULL && !mainw->go_away && mainw->multitrack != NULL && (mt_track_is_video(mainw->multitrack, ldata->val)
663       || mt_track_is_audio(mainw->multitrack, ldata->val))) {
664     if (ldata->string == NULL) {
665       int current_track = mainw->multitrack->current_track;
666       mainw->multitrack->current_track = ldata->val;
667       on_rename_track_activate(NULL, (livespointer)mainw->multitrack);
668       mainw->multitrack->current_track = current_track;
669     } else {
670       set_track_label_string(mainw->multitrack, ldata->val, ldata->string);
671     }
672     ext_caller_return_int(ldata->id, TRUE);
673   } else ext_caller_return_int(ldata->id, FALSE);
674   if (ldata->string != NULL) lives_free(ldata->string);
675   lives_free(data);
676   return FALSE;
677 }
678 
679 
call_set_if_mode(livespointer data)680 static boolean call_set_if_mode(livespointer data) {
681   iipref *idata = (iipref *)data;
682   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
683     if (idata->val == LIVES_INTERFACE_MODE_CLIPEDIT && mainw->multitrack != NULL) {
684       multitrack_delete(mainw->multitrack, FALSE);
685     }
686     if (idata->val == LIVES_INTERFACE_MODE_MULTITRACK && mainw->multitrack == NULL) {
687       on_multitrack_activate(NULL, NULL);
688       while (mainw->multitrack == NULL || !mainw->multitrack->is_ready) lives_usleep(prefs->sleep_time);
689     }
690     ext_caller_return_int(idata->id, TRUE);
691   } else ext_caller_return_int(idata->id, FALSE);
692   lives_free(data);
693   return FALSE;
694 }
695 
696 
call_switch_clip(livespointer data)697 static boolean call_switch_clip(livespointer data) {
698   iipref *idata = (iipref *)data;
699   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
700     switch_clip(idata->integ, idata->val, FALSE);
701     ext_caller_return_int(idata->id, TRUE);
702   } else ext_caller_return_int(idata->id, FALSE);
703   lives_free(data);
704   return FALSE;
705 }
706 
707 
call_set_current_time(livespointer data)708 static boolean call_set_current_time(livespointer data) {
709   opfidata *idata = (opfidata *)data;
710   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !mainw->preview && !LIVES_IS_PLAYING) {
711     if (mainw->multitrack != NULL) {
712       if (idata->stime >= 0.) {
713         if (idata->stime > mainw->multitrack->end_secs) set_timeline_end_secs(mainw->multitrack, idata->stime);
714         mt_tl_move(mainw->multitrack, idata->stime);
715       }
716     } else {
717       if (mainw->current_file > 0 && idata->stime >= 0. && idata->stime <= CLIP_TOTAL_TIME(mainw->current_file)) {
718         cfile->pointer_time = lives_ce_update_timeline(0, idata->stime);
719       }
720     }
721     ext_caller_return_int(idata->id, TRUE);
722   } else ext_caller_return_int(idata->id, FALSE);
723   lives_free(data);
724   return FALSE;
725 }
726 
727 
call_set_current_audio_time(livespointer data)728 static boolean call_set_current_audio_time(livespointer data) {
729   opfidata *idata = (opfidata *)data;
730   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !mainw->preview && mainw->playing_file > 0 &&
731       is_realtime_aplayer(prefs->audio_player) && mainw->multitrack == NULL && !(mainw->record &&
732           prefs->audio_src == AUDIO_SRC_EXT) &&
733       idata->stime >= 0. && idata->stime <= cfile->laudio_time) {
734     resync_audio((int)(idata->stime * cfile->fps + .5) + 1);
735     ext_caller_return_int(idata->id, TRUE);
736   } else ext_caller_return_int(idata->id, FALSE);
737   lives_free(data);
738   return FALSE;
739 }
740 
741 
call_unmap_effects(livespointer data)742 static boolean call_unmap_effects(livespointer data) {
743   ulong id = (ulong)data;
744   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
745     on_clear_all_clicked(NULL, NULL);
746     ext_caller_return_int(id, TRUE);
747   } else ext_caller_return_int(id, FALSE);
748   return FALSE;
749 }
750 
751 
call_stop_playback(livespointer data)752 static boolean call_stop_playback(livespointer data) {
753   ulong id = (ulong)data;
754   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
755     on_stop_activate(NULL, NULL); // should send play stop event
756     ext_caller_return_int(id, TRUE);
757   } else ext_caller_return_int(id, FALSE);
758   return FALSE;
759 }
760 
761 
call_quit_app(livespointer data)762 static boolean call_quit_app(livespointer data) {
763   if (mainw != NULL) {
764     mainw->only_close = mainw->no_exit = FALSE;
765     mainw->leave_recovery = FALSE;
766 
767     if (mainw->was_set) {
768       on_save_set_activate(NULL, mainw->set_name);
769     } else mainw->leave_files = FALSE;
770     lives_exit(0);
771   }
772   return FALSE;
773 }
774 
775 
call_map_effect(livespointer data)776 static boolean call_map_effect(livespointer data) {
777   fxmapdata *fxdata = (fxmapdata *)data;
778   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
779     char *hashname = make_weed_hashname(fxdata->idx, TRUE, FALSE, 0, FALSE);
780     int error = rte_switch_keymode(fxdata->key, fxdata->mode, hashname);
781     ext_caller_return_int(fxdata->id, (error == 0));
782     lives_free(hashname);
783   } else ext_caller_return_int(fxdata->id, FALSE);
784   lives_free(data);
785   return FALSE;
786 }
787 
788 
call_unmap_effect(livespointer data)789 static boolean call_unmap_effect(livespointer data) {
790   fxmapdata *fxdata = (fxmapdata *)data;
791   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && rte_keymode_valid(fxdata->key, fxdata->mode, TRUE)) {
792     int idx = fxdata->key * rte_getmodespk() + fxdata->mode;
793     on_clear_clicked(NULL, LIVES_INT_TO_POINTER(idx));
794     ext_caller_return_int(fxdata->id, TRUE);
795   } else ext_caller_return_int(fxdata->id, FALSE);
796   lives_free(data);
797   return FALSE;
798 }
799 
800 
call_fx_setmode(livespointer data)801 static boolean call_fx_setmode(livespointer data) {
802   fxmapdata *fxdata = (fxmapdata *)data;
803   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
804     boolean ret = rte_key_setmode(fxdata->key, fxdata->mode);
805     ext_caller_return_int(fxdata->id, (int)ret);
806   } else ext_caller_return_int(fxdata->id, FALSE);
807   lives_free(data);
808   return FALSE;
809 }
810 
811 
call_wipe_layout(livespointer data)812 static boolean call_wipe_layout(livespointer data) {
813   iblock *fxdata = (iblock *)data;
814   boolean force = fxdata->ign_sel;
815   char *lname = lives_strdup("");
816   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && mainw->multitrack != NULL) {
817     if (force) {
818       wipe_layout(mainw->multitrack);
819     } else {
820       lives_memset(mainw->recent_file, 0, 1);
821       check_for_layout_del(mainw->multitrack, FALSE);
822       if (strlen(mainw->recent_file)) {
823         lives_free(lname);
824         lname = strdup(mainw->recent_file);
825       }
826     }
827   }
828   ext_caller_return_string(fxdata->id, lname);
829   lives_free(lname);
830   lives_free(data);
831   return FALSE;
832 }
833 
834 
call_choose_layout(livespointer data)835 static boolean call_choose_layout(livespointer data) {
836   iblock *fxdata = (iblock *)data;
837   char *lname = lives_strdup("");
838   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && mainw->multitrack != NULL && strlen(mainw->set_name) > 0) {
839     lives_free(lname);
840     lname = get_eload_filename(mainw->multitrack, FALSE);
841     if (lname == NULL) lname = lives_strdup("");
842   }
843   ext_caller_return_string(fxdata->id, lname);
844   lives_free(lname);
845   lives_free(data);
846   return FALSE;
847 }
848 
849 
call_render_layout(livespointer data)850 static boolean call_render_layout(livespointer data) {
851   iblock *bdata = (iblock *)data;
852   ulong uid = 0l;
853   boolean ret;
854 
855   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && mainw->multitrack != NULL) {
856     ulong new_uid = mainw->files[mainw->multitrack->render_file]->unique_id;
857     boolean ra = mainw->multitrack->opts.render_audp;
858     boolean rn = mainw->multitrack->opts.normalise_audp;
859 
860     mainw->multitrack->opts.render_audp = bdata->with_audio;
861     mainw->multitrack->opts.normalise_audp = bdata->ign_sel;
862 
863     ret = on_render_activate(LIVES_MENU_ITEM(1), mainw->multitrack);
864     if (ret) uid = new_uid;
865 
866     mainw->multitrack->opts.render_audp = ra;
867     mainw->multitrack->opts.normalise_audp = rn;
868 
869   }
870   ext_caller_return_ulong(bdata->id, uid);
871   lives_free(data);
872   return FALSE;
873 }
874 
875 
call_reload_layout(livespointer data)876 static boolean call_reload_layout(livespointer data) {
877   msginfo *mdata = (msginfo *)data;
878   boolean resp = FALSE;
879   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && mainw->multitrack != NULL && strlen(mainw->set_name) > 0) {
880     if (!strlen(mdata->msg)) {
881       lives_free(mdata->msg);
882       mdata->msg = get_eload_filename(mainw->multitrack, FALSE);
883       if (mdata->msg == NULL) mdata->msg = lives_strdup("");
884     }
885     if (strlen(mainw->msg)) {
886       mainw->multitrack->force_load_name = mainw->msg;
887       resp = on_load_event_list_activate(NULL, mainw->multitrack);
888       mainw->multitrack->force_load_name = NULL;
889     }
890   }
891   lives_free(mdata->msg);
892   ext_caller_return_int(mdata->id, resp);
893   lives_free(mdata);
894   return resp;
895 }
896 
897 
call_save_layout(livespointer data)898 static boolean call_save_layout(livespointer data) {
899   msginfo *mdata = (msginfo *)data;
900   boolean resp = FALSE;
901 
902   char *lname = lives_strdup("");
903 
904   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
905     if (mdata->msg != NULL) {
906       if (mainw->multitrack != NULL) lives_snprintf(mainw->multitrack->layout_name, PATH_MAX, "%s", mdata->msg);
907       else lives_snprintf(mainw->stored_layout_name, PATH_MAX, "%s", mdata->msg);
908     }
909     resp = on_save_event_list_activate(NULL, mainw->multitrack);
910     if (resp) {
911       lives_free(lname);
912       lname = lives_strdup(mainw->recent_file);
913     }
914   }
915 
916   lives_free(mdata->msg);
917   ext_caller_return_string(mdata->id, lname);
918   lives_free(lname);
919   lives_free(mdata);
920   return resp;
921 }
922 
923 
call_set_current_fps(livespointer data)924 static boolean call_set_current_fps(livespointer data) {
925   opfidata *idata = (opfidata *)data;
926   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && LIVES_IS_PLAYING && mainw->multitrack == NULL) {
927     lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_pb_fps), idata->stime);
928     ext_caller_return_int(idata->id, (int)TRUE);
929   } else ext_caller_return_int(idata->id, (int)FALSE);
930   lives_free(data);
931   return FALSE;
932 }
933 
934 
call_set_current_frame(livespointer data)935 static boolean call_set_current_frame(livespointer data) {
936   ibpref *bdata = (ibpref *)data;
937   boolean ret;
938 
939   char **vargs;
940 
941   int arglen = 2;
942 
943   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
944       mainw->is_processing ||
945       LIVES_IS_PLAYING) return FALSE;
946 
947   vargs = (char **)lives_malloc(sizeof(char *));
948 
949   *vargs = lives_strdup(",i");
950   arglen = padup(vargs, arglen);
951   arglen = add_int_arg(vargs, arglen, bdata->val);
952 
953   if (!bdata->val)
954     ret = lives_osc_cb_clip_goto(NULL, arglen, (const void *)(*vargs), OSCTT_CurrentTime(), NULL);
955   else
956     ret = lives_osc_cb_bgclip_goto(NULL, arglen, (const void *)(*vargs), OSCTT_CurrentTime(), NULL);
957 
958   ext_caller_return_int(bdata->id, (int)ret);
959   lives_free(data);
960   lives_free((char *)*vargs);
961   lives_free(vargs);
962   return FALSE;
963 }
964 
965 
call_select_all(livespointer data)966 static boolean call_select_all(livespointer data) {
967   iipref *idata = (iipref *)data;
968   int cnum = idata->val;
969 
970   if (mainw != NULL) {
971     lives_clip_t *sfile = mainw->files[cnum];
972     boolean selwidth_locked = mainw->selwidth_locked;
973 
974     if (!mainw->go_away && !mainw->is_processing && sfile != NULL) {
975       mainw->selwidth_locked = FALSE;
976       if (cnum == mainw->current_file) on_select_all_activate(NULL, NULL);
977       else {
978         sfile->start = sfile->frames > 0 ? 1 : 0;
979         sfile->end = sfile->frames;
980       }
981       mainw->selwidth_locked = selwidth_locked;
982       ext_caller_return_int(idata->id, (int)TRUE);
983     } else ext_caller_return_int(idata->id, (int)FALSE);
984   } else ext_caller_return_int(idata->id, (int)FALSE);
985   lives_free(data);
986   return FALSE;
987 }
988 
989 
call_select_start(livespointer data)990 static boolean call_select_start(livespointer data) {
991   iipref *idata = (iipref *)data;
992 
993   int cnum = idata->val;
994   int frame = idata->integ;
995 
996   if (mainw != NULL) {
997     lives_clip_t *sfile = mainw->files[cnum];
998     boolean selwidth_locked = mainw->selwidth_locked;
999     if (!mainw->go_away && !mainw->is_processing && sfile != NULL) {
1000       mainw->selwidth_locked = FALSE;
1001       if (cnum == mainw->current_file) lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_start), frame);
1002       else {
1003         if (frame > sfile->frames) frame = sfile->frames;
1004         if (sfile->end < frame) sfile->end = frame;
1005         sfile->start = frame;
1006       }
1007       mainw->selwidth_locked = selwidth_locked;
1008       ext_caller_return_int(idata->id, (int)TRUE);
1009     } else ext_caller_return_int(idata->id, (int)FALSE);
1010   } else ext_caller_return_int(idata->id, (int)FALSE);
1011   lives_free(data);
1012   return FALSE;
1013 }
1014 
1015 
call_select_end(livespointer data)1016 static boolean call_select_end(livespointer data) {
1017   iipref *idata = (iipref *)data;
1018 
1019   int cnum = idata->val;
1020   int frame = idata->integ;
1021   if (mainw != NULL) {
1022     lives_clip_t *sfile = mainw->files[cnum];
1023     boolean selwidth_locked = mainw->selwidth_locked;
1024 
1025     if (!mainw->go_away && !mainw->is_processing && sfile != NULL) {
1026       mainw->selwidth_locked = FALSE;
1027       if (cnum == mainw->current_file) lives_spin_button_set_value(LIVES_SPIN_BUTTON(mainw->spinbutton_end), frame);
1028       else {
1029         if (frame > sfile->frames) frame = sfile->frames;
1030         if (sfile->start > frame) sfile->start = frame;
1031         sfile->end = frame;
1032       }
1033       mainw->selwidth_locked = selwidth_locked;
1034       ext_caller_return_int(idata->id, (int)TRUE);
1035     } else ext_caller_return_int(idata->id, (int)FALSE);
1036   } else ext_caller_return_int(idata->id, (int)FALSE);
1037   lives_free(data);
1038   return FALSE;
1039 }
1040 
1041 
call_insert_block(livespointer data)1042 static boolean call_insert_block(livespointer data) {
1043   iblock *idata = (iblock *)data;
1044   boolean ins_audio;
1045   boolean ign_ins_sel;
1046 
1047   ulong block_uid;
1048 
1049   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !LIVES_IS_PLAYING && mainw->multitrack != NULL) {
1050     mainw->multitrack->clip_selected = idata->clip - 1;
1051     mt_clip_select(mainw->multitrack, TRUE);
1052 
1053     ins_audio = mainw->multitrack->opts.insert_audio;
1054     ign_ins_sel = mainw->multitrack->opts.ign_ins_sel;
1055 
1056     mainw->multitrack->opts.insert_audio = idata->with_audio;
1057     mainw->multitrack->opts.ign_ins_sel = idata->ign_sel;
1058 
1059     multitrack_insert(NULL, mainw->multitrack);
1060 
1061     mainw->multitrack->opts.ign_ins_sel = ign_ins_sel;
1062     mainw->multitrack->opts.insert_audio = ins_audio;
1063 
1064     block_uid = mt_get_last_block_uid(mainw->multitrack);
1065     ext_caller_return_ulong(idata->id, block_uid);
1066   } else ext_caller_return_ulong(idata->id, 0l);
1067   lives_free(data);
1068   return FALSE;
1069 }
1070 
1071 
call_remove_block(livespointer data)1072 static boolean call_remove_block(livespointer data) {
1073   mblockdata *rdata = (mblockdata *)data;
1074 
1075   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !LIVES_IS_PLAYING && mainw->multitrack != NULL) {
1076     track_rect *oblock = mainw->multitrack->block_selected;
1077     mainw->multitrack->block_selected = rdata->block;
1078     delete_block_cb(NULL, (livespointer)mainw->multitrack);
1079     if (oblock != rdata->block) mainw->multitrack->block_selected = oblock;
1080     ext_caller_return_int(rdata->id, (int)TRUE);
1081   } else ext_caller_return_int(rdata->id, (int)FALSE);
1082   lives_free(data);
1083   return FALSE;
1084 }
1085 
1086 
call_move_block(livespointer data)1087 static boolean call_move_block(livespointer data) {
1088   mblockdata *mdata = (mblockdata *)data;
1089 
1090   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !LIVES_IS_PLAYING && mainw->multitrack != NULL) {
1091     track_rect *bsel = mainw->multitrack->block_selected;
1092     int track = get_track_for_block(mdata->block);
1093     ulong block_uid = mdata->block->uid;
1094     track_rect *nblock = move_block(mainw->multitrack, mdata->block, mdata->time, track, mdata->track);
1095     mainw->multitrack->block_selected = bsel;
1096     if (nblock == NULL) ext_caller_return_int(mdata->id, (int)FALSE);
1097     else {
1098       nblock->uid = block_uid;
1099       ext_caller_return_int(mdata->id, (int)TRUE);
1100     }
1101   }
1102   lives_free(data);
1103   return FALSE;
1104 }
1105 
1106 
call_fx_enable(livespointer data)1107 static boolean call_fx_enable(livespointer data) {
1108   fxmapdata *fxdata = (fxmapdata *)data;
1109   boolean nstate = (boolean)fxdata->mode;
1110   boolean ret = FALSE;
1111 
1112   if (mainw != NULL && !mainw->go_away && !mainw->is_processing) {
1113     int grab = mainw->last_grabbable_effect;
1114     int effect_key = fxdata->key;
1115 
1116     if (nstate) {
1117       // fx is on
1118       if (!(mainw->rte & (GU641 << (effect_key - 1)))) {
1119         weed_plant_t *filter = rte_keymode_get_filter(effect_key, rte_key_getmode(effect_key));
1120         if (filter == NULL) ret = FALSE;
1121         else {
1122           int count = enabled_in_channels(filter, FALSE);
1123           if (!LIVES_IS_PLAYING && count == 0) {
1124             // TODO: use osc, but don't set osc_auto
1125             // return value first because...
1126             ext_caller_return_int(fxdata->id, (int)TRUE);
1127             // ...we are going to hang here until playback ends
1128             ret = rte_key_toggle(effect_key);
1129             return FALSE;
1130           } else {
1131             ret = rte_key_toggle(effect_key);
1132             mainw->last_grabbable_effect = grab;
1133           }
1134         }
1135       }
1136     } else {
1137       if (mainw->rte & (GU641 << (effect_key - 1))) {
1138         ret = rte_key_toggle(effect_key);
1139       }
1140     }
1141   }
1142   ext_caller_return_int(fxdata->id, (int)ret);
1143   lives_free(data);
1144   return FALSE;
1145 }
1146 
1147 
call_set_loop_mode(livespointer data)1148 static boolean call_set_loop_mode(livespointer data) {
1149   iipref *idata = (iipref *)data;
1150   int lmode = idata->val;
1151 
1152   if (mainw != NULL && !mainw->go_away) {
1153     if (lmode == LIVES_LOOP_MODE_NONE) {
1154       if (mainw->loop_cont) on_loop_button_activate(NULL, NULL);
1155       if (mainw->loop) lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mainw->loop_video), !mainw->loop);
1156     } else {
1157       if (lmode & LIVES_LOOP_MODE_CONTINUOUS) {
1158         if (!mainw->loop_cont) on_loop_button_activate(NULL, NULL);
1159       } else if (mainw->loop_cont) on_loop_button_activate(NULL, NULL);
1160 
1161       if (lmode & LIVES_LOOP_MODE_FIT_AUDIO) {
1162         if (mainw->loop) lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mainw->loop_video), !mainw->loop);
1163       } else if (!mainw->loop) lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mainw->loop_video), !mainw->loop);
1164     }
1165     ext_caller_return_int(idata->id, (int)TRUE);
1166   } else ext_caller_return_int(idata->id, (int)FALSE);
1167   lives_free(data);
1168   return FALSE;
1169 }
1170 
1171 
call_resync_fps(livespointer data)1172 static boolean call_resync_fps(livespointer data) {
1173   iipref *idata = (iipref *)data;
1174   if (mainw != NULL && LIVES_IS_PLAYING) {
1175     fps_reset_callback(NULL, NULL, 0, (LiVESXModifierType)0, NULL);
1176     ext_caller_return_int(idata->id, (int)TRUE);
1177   } else ext_caller_return_int(idata->id, (int)FALSE);
1178   lives_free(data);
1179   return FALSE;
1180 }
1181 
1182 
call_cancel_proc(livespointer data)1183 static boolean call_cancel_proc(livespointer data) {
1184   iipref *idata = (iipref *)data;
1185   if (mainw == NULL || mainw->current_file == -1 || cfile == NULL || mainw->proc_ptr == NULL ||
1186       !lives_widget_is_visible(mainw->proc_ptr->cancel_button)) {
1187     ext_caller_return_int(idata->id, (int)FALSE);
1188   } else {
1189     on_cancel_keep_button_clicked(NULL, NULL);
1190     ext_caller_return_int(idata->id, (int)TRUE);
1191   }
1192   lives_free(data);
1193   return FALSE;
1194 }
1195 
1196 
1197 //////////////////////////////////////////////////////////////////
1198 
1199 /// idlefunc hooks
1200 
idle_show_info(const char * text,boolean blocking,ulong id)1201 boolean idle_show_info(const char *text, boolean blocking, ulong id) {
1202   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1203       mainw->is_processing ||
1204       LIVES_IS_PLAYING) return FALSE;
1205   if (text == NULL) return FALSE;
1206   if (!blocking) lives_idle_add(call_osc_show_info, (livespointer)text);
1207   else {
1208     msginfo *minfo = (msginfo *)lives_malloc(sizeof(msginfo));
1209     minfo->msg = lives_strdup(text);
1210     minfo->id = id;
1211     lives_idle_add(call_osc_show_blocking_info, (livespointer)minfo);
1212   }
1213   return TRUE;
1214 }
1215 
1216 
idle_switch_clip(int type,int cnum,ulong id)1217 boolean idle_switch_clip(int type, int cnum, ulong id) {
1218   iipref *info;
1219 
1220   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1221                         !LIVES_IS_PLAYING))) ||
1222       mainw->go_away || mainw->is_processing) return FALSE;
1223   if (mainw->multitrack != NULL) return FALSE;
1224 
1225   info = (iipref *)lives_malloc(sizeof(iipref));
1226   info->id = id;
1227   info->val = cnum;
1228   info->integ = type;
1229   lives_idle_add(call_switch_clip, (livespointer)info);
1230   return TRUE;
1231 }
1232 
1233 
idle_mt_set_track(int tnum,ulong id)1234 boolean idle_mt_set_track(int tnum, ulong id) {
1235   iipref *info;
1236 
1237   if (mainw == NULL || mainw->preview || mainw->go_away || mainw->is_processing) return FALSE;
1238   if (mainw->multitrack == NULL) return FALSE;
1239 
1240   info = (iipref *)lives_malloc(sizeof(iipref));
1241   info->id = id;
1242   info->val = tnum;
1243   lives_idle_add(call_mt_set_track, (livespointer)info);
1244   return TRUE;
1245 }
1246 
1247 
idle_set_track_label(int tnum,const char * label,ulong id)1248 boolean idle_set_track_label(int tnum, const char *label, ulong id) {
1249   lset *data;
1250 
1251   if (mainw == NULL || mainw->preview || mainw->go_away || mainw->is_processing) return FALSE;
1252   if (mainw->multitrack == NULL) return FALSE;
1253 
1254   data = (lset *)lives_malloc(sizeof(lset));
1255   data->id = id;
1256   data->val = tnum;
1257   if (label != NULL) data->string = lives_strdup(label);
1258   else data->string = NULL;
1259   lives_idle_add(call_mt_set_track_label, (livespointer)data);
1260   return TRUE;
1261 }
1262 
1263 
idle_insert_vtrack(boolean in_front,ulong id)1264 boolean idle_insert_vtrack(boolean in_front, ulong id) {
1265   ibpref *data;
1266 
1267   if (mainw == NULL || !LIVES_IS_PLAYING) return FALSE;
1268   if (mainw->multitrack != NULL) return FALSE;
1269 
1270   data = (ibpref *)lives_malloc(sizeof(ibpref));
1271   data->val = in_front;
1272   lives_idle_add(call_insert_vtrack, (livespointer)data);
1273   return TRUE;
1274 }
1275 
1276 
idle_set_current_time(double time,ulong id)1277 boolean idle_set_current_time(double time, ulong id) {
1278   opfidata *info;
1279 
1280   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1281       mainw->is_processing ||
1282       LIVES_IS_PLAYING) return FALSE;
1283 
1284   info = (opfidata *)lives_malloc(sizeof(opfidata));
1285   info->id = id;
1286   info->stime = time;
1287   lives_idle_add(call_set_current_time, (livespointer)info);
1288   return TRUE;
1289 }
1290 
1291 
idle_set_current_audio_time(double time,ulong id)1292 boolean idle_set_current_audio_time(double time, ulong id) {
1293   opfidata *info;
1294 
1295   if (mainw != NULL && !mainw->go_away && !mainw->is_processing && !mainw->preview && mainw->playing_file > 0 &&
1296       is_realtime_aplayer(prefs->audio_player) && mainw->multitrack == NULL && !(mainw->record &&
1297           prefs->audio_src == AUDIO_SRC_EXT) &&
1298       time >= 0. && time <= cfile->laudio_time) {
1299     info = (opfidata *)lives_malloc(sizeof(opfidata));
1300     info->id = id;
1301     info->stime = time;
1302     lives_idle_add(call_set_current_audio_time, (livespointer)info);
1303     return TRUE;
1304   }
1305   return FALSE;
1306 }
1307 
1308 
idle_unmap_effects(ulong id)1309 boolean idle_unmap_effects(ulong id) {
1310   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1311                         !LIVES_IS_PLAYING))) ||
1312       mainw->go_away || mainw->is_processing) return FALSE;
1313 
1314   lives_idle_add(call_unmap_effects, (livespointer)id);
1315 
1316   return TRUE;
1317 }
1318 
1319 
idle_stop_playback(ulong id)1320 boolean idle_stop_playback(ulong id) {
1321   if (mainw == NULL || mainw->go_away || mainw->is_processing) return FALSE;
1322 
1323   lives_idle_add(call_stop_playback, (livespointer)id);
1324 
1325   return TRUE;
1326 }
1327 
1328 
idle_quit(pthread_t * gtk_thread)1329 boolean idle_quit(pthread_t *gtk_thread) {
1330   if (mainw == NULL) return FALSE;
1331 
1332   lives_idle_add(call_quit_app, NULL);
1333 
1334   pthread_join(*gtk_thread, NULL);
1335 
1336   return TRUE;
1337 }
1338 
1339 
idle_save_set(const char * name,boolean force_append,ulong id)1340 boolean idle_save_set(const char *name, boolean force_append, ulong id) {
1341   oscdata *data;
1342   char **vargs;
1343 
1344   int arglen = 3;
1345 
1346   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1347       mainw->is_processing ||
1348       LIVES_IS_PLAYING) return FALSE;
1349 
1350   vargs = (char **)lives_malloc(sizeof(char *));
1351 
1352   *vargs = lives_strdup(",si");
1353   arglen = padup(vargs, arglen);
1354   arglen = add_string_arg(vargs, arglen, name);
1355   arglen = add_int_arg(vargs, arglen, force_append);
1356 
1357   data = (oscdata *)lives_malloc(sizeof(oscdata));
1358   data->id = id;
1359   data->arglen = arglen;
1360   data->vargs = vargs;
1361   lives_idle_add(call_osc_save_set, (livespointer)data);
1362 
1363   return TRUE;
1364 }
1365 
1366 
idle_choose_file_with_preview(const char * dirname,const char * title,int preview_type,ulong id)1367 boolean idle_choose_file_with_preview(const char *dirname, const char *title, int preview_type, ulong id) {
1368   fprev *data;
1369 
1370   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1371       mainw->is_processing ||
1372       LIVES_IS_PLAYING) return FALSE;
1373 
1374   data = (fprev *)lives_malloc(sizeof(fprev));
1375   data->id = id;
1376 
1377   if (dirname != NULL && strlen(dirname) > 0) data->dir = lives_strdup(dirname);
1378   else data->dir = NULL;
1379 
1380   if (title != NULL && strlen(title) > 0) data->title = lives_strdup(title);
1381   else data->title = NULL;
1382 
1383   data->preview_type = preview_type;
1384   lives_idle_add(call_file_choose_with_preview, (livespointer)data);
1385   return TRUE;
1386 }
1387 
1388 
idle_choose_set(ulong id)1389 boolean idle_choose_set(ulong id) {
1390   udata *data;
1391 
1392   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1393       mainw->is_processing ||
1394       LIVES_IS_PLAYING) return FALSE;
1395   if (mainw->was_set) return FALSE;
1396 
1397   data = (udata *)lives_malloc(sizeof(udata));
1398   data->id = id;
1399   lives_idle_add(call_choose_set, (livespointer)data);
1400   return TRUE;
1401 }
1402 
1403 
idle_set_set_name(ulong id)1404 boolean idle_set_set_name(ulong id) {
1405   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1406       mainw->is_processing ||
1407       mainw->playing_file) return FALSE;
1408   lives_idle_add(call_set_set_name, (livespointer)id);
1409   return TRUE;
1410 }
1411 
1412 
idle_open_file(const char * fname,double stime,int frames,ulong id)1413 boolean idle_open_file(const char *fname, double stime, int frames, ulong id) {
1414   opfidata *data;
1415 
1416   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1417       mainw->is_processing ||
1418       LIVES_IS_PLAYING) return FALSE;
1419   if (fname == NULL || strlen(fname) == 0) return FALSE;
1420 
1421   data = (opfidata *)lives_malloc(sizeof(opfidata));
1422   data->id = id;
1423   data->fname = lives_strdup(fname);
1424   data->stime = stime;
1425   data->frames = frames;
1426 
1427   lives_idle_add(call_open_file, (livespointer)data);
1428   return TRUE;
1429 }
1430 
1431 
idle_reload_set(const char * setname,ulong id)1432 boolean idle_reload_set(const char *setname, ulong id) {
1433   msginfo *data;
1434 
1435   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1436       mainw->is_processing ||
1437       LIVES_IS_PLAYING) return FALSE;
1438   if (mainw->was_set) return FALSE;
1439 
1440   if (setname == NULL) return FALSE;
1441 
1442   if (strlen(setname) && !is_legal_set_name(setname, TRUE, TRUE)) return FALSE;
1443 
1444   data = (msginfo *)lives_malloc(sizeof(msginfo));
1445   data->id = id;
1446   data->msg = lives_strdup(setname);
1447 
1448   lives_idle_add(call_reload_set, (livespointer)data);
1449   return TRUE;
1450 }
1451 
1452 
idle_set_interactive(boolean setting,ulong id)1453 boolean idle_set_interactive(boolean setting, ulong id) {
1454   sintdata *data;
1455 
1456   if (mainw == NULL || mainw->go_away) return FALSE;
1457 
1458   data = (sintdata *)lives_malloc(sizeof(sintdata));
1459   data->id = id;
1460   data->setting = setting;
1461   lives_idle_add(call_set_interactive, (livespointer)data);
1462   return TRUE;
1463 }
1464 
1465 
idle_set_sepwin(boolean setting,ulong id)1466 boolean idle_set_sepwin(boolean setting, ulong id) {
1467   sintdata *data;
1468 
1469   if (mainw == NULL || mainw->go_away) return FALSE;
1470 
1471   data = (sintdata *)lives_malloc(sizeof(sintdata));
1472   data->id = id;
1473   data->setting = setting;
1474   lives_idle_add(call_set_sepwin, (livespointer)data);
1475   return TRUE;
1476 }
1477 
1478 
idle_set_fullscreen(boolean setting,ulong id)1479 boolean idle_set_fullscreen(boolean setting, ulong id) {
1480   sintdata *data;
1481 
1482   if (mainw == NULL || mainw->go_away) return FALSE;
1483 
1484   data = (sintdata *)lives_malloc(sizeof(sintdata));
1485   data->id = id;
1486   data->setting = setting;
1487   lives_idle_add(call_set_fullscreen, (livespointer)data);
1488   return TRUE;
1489 }
1490 
1491 
idle_set_fullscreen_sepwin(boolean setting,ulong id)1492 boolean idle_set_fullscreen_sepwin(boolean setting, ulong id) {
1493   sintdata *data;
1494 
1495   if (mainw == NULL || mainw->go_away) return FALSE;
1496 
1497   data = (sintdata *)lives_malloc(sizeof(sintdata));
1498   data->id = id;
1499   data->setting = setting;
1500   lives_idle_add(call_set_fullscreen_sepwin, (livespointer)data);
1501   return TRUE;
1502 }
1503 
1504 
idle_set_ping_pong(boolean setting,ulong id)1505 boolean idle_set_ping_pong(boolean setting, ulong id) {
1506   sintdata *data;
1507 
1508   if (mainw == NULL || mainw->go_away) return FALSE;
1509 
1510   data = (sintdata *)lives_malloc(sizeof(sintdata));
1511   data->id = id;
1512   data->setting = setting;
1513   lives_idle_add(call_set_ping_pong, (livespointer)data);
1514   return TRUE;
1515 }
1516 
1517 
idle_set_gravity(int grav,ulong id)1518 boolean idle_set_gravity(int grav, ulong id) {
1519   iipref *data;
1520 
1521   if (mainw == NULL || mainw->go_away) return FALSE;
1522 
1523   data = (iipref *)lives_malloc(sizeof(iipref));
1524   data->id = id;
1525   data->val = grav;
1526   lives_idle_add(call_set_gravity, (livespointer)data);
1527   return TRUE;
1528 }
1529 
1530 
idle_set_insert_mode(int mode,ulong id)1531 boolean idle_set_insert_mode(int mode, ulong id) {
1532   iipref *data;
1533 
1534   if (mainw == NULL || mainw->go_away) return FALSE;
1535 
1536   data = (iipref *)lives_malloc(sizeof(iipref));
1537   data->id = id;
1538   data->val = mode;
1539   lives_idle_add(call_set_insert_mode, (livespointer)data);
1540   return TRUE;
1541 }
1542 
1543 
idle_map_fx(int key,int mode,int idx,ulong id)1544 boolean idle_map_fx(int key, int mode, int idx, ulong id) {
1545   fxmapdata *data;
1546 
1547   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1548                         !LIVES_IS_PLAYING))) ||
1549       mainw->go_away || mainw->is_processing) return FALSE;
1550 
1551   data = (fxmapdata *)lives_malloc(sizeof(fxmapdata));
1552   data->key = key;
1553   data->mode = mode;
1554   data->idx = idx;
1555   data->id = id;
1556   lives_idle_add(call_map_effect, (livespointer)data);
1557   return TRUE;
1558 }
1559 
1560 
idle_unmap_fx(int key,int mode,ulong id)1561 boolean idle_unmap_fx(int key, int mode, ulong id) {
1562   fxmapdata *data;
1563 
1564   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1565                         !LIVES_IS_PLAYING))) ||
1566       mainw->go_away || mainw->is_processing) return FALSE;
1567 
1568   if (!rte_keymode_valid(key, mode, TRUE)) return FALSE;
1569 
1570   data = (fxmapdata *)lives_malloc(sizeof(fxmapdata));
1571   data->key = key;
1572   data->mode = mode;
1573   data->id = id;
1574   lives_idle_add(call_unmap_effect, (livespointer)data);
1575   return TRUE;
1576 }
1577 
1578 
idle_fx_setmode(int key,int mode,ulong id)1579 boolean idle_fx_setmode(int key, int mode, ulong id) {
1580   fxmapdata *data;
1581 
1582   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1583                         !LIVES_IS_PLAYING))) ||
1584       mainw->go_away || mainw->is_processing) return FALSE;
1585 
1586   data = (fxmapdata *)lives_malloc(sizeof(fxmapdata));
1587   data->key = key;
1588   data->mode = mode;
1589   data->id = id;
1590 
1591   lives_idle_add(call_fx_setmode, (livespointer)data);
1592   return TRUE;
1593 }
1594 
1595 
idle_fx_enable(int key,boolean setting,ulong id)1596 boolean idle_fx_enable(int key, boolean setting, ulong id) {
1597   fxmapdata *data;
1598 
1599   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1600                         !LIVES_IS_PLAYING))) ||
1601       mainw->go_away || mainw->is_processing) return FALSE;
1602 
1603   data = (fxmapdata *)lives_malloc(sizeof(fxmapdata));
1604   data->key = key;
1605   data->mode = setting;
1606   data->id = id;
1607 
1608   lives_idle_add(call_fx_enable, (livespointer)data);
1609   return TRUE;
1610 }
1611 
1612 
idle_set_pref_bool(const char * prefidx,boolean val,ulong id)1613 boolean idle_set_pref_bool(const char *prefidx, boolean val, ulong id) {
1614   bpref *data;
1615 
1616   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1617                         !LIVES_IS_PLAYING))) ||
1618       mainw->go_away) return FALSE;
1619 
1620   data = (bpref *)lives_malloc(sizeof(bpref));
1621   data->id = id;
1622   data->prefidx = lives_strdup(prefidx);
1623   data->val = val;
1624   lives_idle_add(call_set_pref_bool, (livespointer)data);
1625   return TRUE;
1626 }
1627 
1628 
idle_set_pref_int(const char * prefidx,int val,ulong id)1629 boolean idle_set_pref_int(const char *prefidx, int val, ulong id) {
1630   iipref *data;
1631 
1632   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1633                         !LIVES_IS_PLAYING))) ||
1634       mainw->go_away) return FALSE;
1635 
1636   data = (iipref *)lives_malloc(sizeof(iipref));
1637   data->id = id;
1638   data->prefidx = lives_strdup(prefidx);
1639   data->val = val;
1640   lives_idle_add(call_set_pref_int, (livespointer)data);
1641   return TRUE;
1642 }
1643 
1644 
idle_set_pref_bitmapped(const char * prefidx,int bitfield,boolean val,ulong id)1645 boolean idle_set_pref_bitmapped(const char *prefidx, int bitfield, boolean val, ulong id) {
1646   bmpref *data;
1647 
1648   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1649                         !LIVES_IS_PLAYING))) ||
1650       mainw->go_away) return FALSE;
1651 
1652   data = (bmpref *)lives_malloc(sizeof(bmpref));
1653   data->id = id;
1654   data->prefidx = lives_strdup(prefidx);
1655   data->bitfield = bitfield;
1656   data->val = val;
1657   lives_idle_add(call_set_pref_bitmapped, (livespointer)data);
1658   return TRUE;
1659 }
1660 
1661 
idle_set_if_mode(lives_interface_mode_t mode,ulong id)1662 boolean idle_set_if_mode(lives_interface_mode_t mode, ulong id) {
1663   iipref *data;
1664 
1665   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1666       mainw->is_processing ||
1667       LIVES_IS_PLAYING) return FALSE;
1668 
1669   data = (iipref *)lives_malloc(sizeof(iipref));
1670   data->id = id;
1671   data->val = (int)mode;
1672   lives_idle_add(call_set_if_mode, (livespointer)data);
1673   return TRUE;
1674 }
1675 
1676 
idle_insert_block(int clipno,boolean ign_sel,boolean with_audio,ulong id)1677 boolean idle_insert_block(int clipno, boolean ign_sel, boolean with_audio, ulong id) {
1678   iblock *data;
1679 
1680   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1681       mainw->is_processing ||
1682       LIVES_IS_PLAYING) return FALSE;
1683   if (mainw->multitrack == NULL) return FALSE;
1684 
1685   data = (iblock *)lives_malloc(sizeof(iblock));
1686   data->id = id;
1687   data->clip = clipno;
1688   data->ign_sel = ign_sel;
1689   data->with_audio = with_audio;
1690   lives_idle_add(call_insert_block, (livespointer)data);
1691   return TRUE;
1692 }
1693 
1694 
idle_remove_block(ulong uid,ulong id)1695 boolean idle_remove_block(ulong uid, ulong id) {
1696   mblockdata *data;
1697   track_rect *tr;
1698 
1699   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1700       mainw->is_processing ||
1701       LIVES_IS_PLAYING) return FALSE;
1702   if (mainw->multitrack == NULL) return FALSE;
1703 
1704   tr = find_block_by_uid(mainw->multitrack, uid);
1705   if (tr == NULL) return FALSE;
1706 
1707   data = (mblockdata *)lives_malloc(sizeof(mblockdata));
1708   data->id = id;
1709   data->block = tr;
1710   lives_idle_add(call_remove_block, (livespointer)data);
1711   return TRUE;
1712 }
1713 
1714 
idle_move_block(ulong uid,int track,double time,ulong id)1715 boolean idle_move_block(ulong uid, int track, double time, ulong id) {
1716   mblockdata *data;
1717   track_rect *tr;
1718 
1719   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1720       mainw->is_processing ||
1721       LIVES_IS_PLAYING) return FALSE;
1722   if (mainw->multitrack == NULL) return FALSE;
1723 
1724   tr = find_block_by_uid(mainw->multitrack, uid);
1725   if (tr == NULL) return FALSE;
1726 
1727   if (track >= lives_list_length(mainw->multitrack->video_draws) ||
1728       track < -mainw->multitrack->opts.back_audio_tracks) return FALSE;
1729 
1730   if (time < 0.) return FALSE;
1731 
1732   data = (mblockdata *)lives_malloc(sizeof(mblockdata));
1733   data->id = id;
1734   data->block = tr;
1735   data->track = track;
1736   data->time = time;
1737   lives_idle_add(call_move_block, (livespointer)data);
1738   return TRUE;
1739 }
1740 
1741 
idle_wipe_layout(boolean force,ulong id)1742 boolean idle_wipe_layout(boolean force, ulong id) {
1743   iblock *data;
1744 
1745   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1746       mainw->is_processing ||
1747       LIVES_IS_PLAYING) return FALSE;
1748   if (mainw->multitrack == NULL) return FALSE;
1749 
1750   data = (iblock *)lives_malloc(sizeof(iblock));
1751   data->ign_sel = force;
1752   data->id = id;
1753   lives_idle_add(call_wipe_layout, (livespointer)data);
1754   return TRUE;
1755 }
1756 
1757 
idle_choose_layout(ulong id)1758 boolean idle_choose_layout(ulong id) {
1759   iblock *data;
1760 
1761   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1762       mainw->is_processing ||
1763       LIVES_IS_PLAYING) return FALSE;
1764   if (mainw->multitrack == NULL) return FALSE;
1765 
1766   data = (iblock *)lives_malloc(sizeof(iblock));
1767   data->id = id;
1768   lives_idle_add(call_choose_layout, (livespointer)data);
1769   return TRUE;
1770 }
1771 
1772 
idle_reload_layout(const char * lname,ulong id)1773 boolean idle_reload_layout(const char *lname, ulong id) {
1774   msginfo *data;
1775 
1776   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1777       mainw->is_processing ||
1778       LIVES_IS_PLAYING) return FALSE;
1779   if (mainw->multitrack == NULL) return FALSE;
1780 
1781   data = (msginfo *)lives_malloc(sizeof(msginfo));
1782   data->id = id;
1783   data->msg = lives_strdup(lname);
1784   lives_idle_add(call_reload_layout, (livespointer)data);
1785   return TRUE;
1786 }
1787 
1788 
idle_save_layout(const char * lname,ulong id)1789 boolean idle_save_layout(const char *lname, ulong id) {
1790   msginfo *data;
1791 
1792   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1793       mainw->is_processing ||
1794       LIVES_IS_PLAYING) return FALSE;
1795   if (mainw->multitrack == NULL) return FALSE;
1796 
1797   data = (msginfo *)lives_malloc(sizeof(msginfo));
1798   data->id = id;
1799   if (lname != NULL) data->msg = lives_strdup(lname);
1800   else data->msg = NULL;
1801   lives_idle_add(call_save_layout, (livespointer)data);
1802   return TRUE;
1803 }
1804 
1805 
idle_render_layout(boolean with_aud,boolean normalise_aud,ulong id)1806 boolean idle_render_layout(boolean with_aud, boolean normalise_aud, ulong id) {
1807   iblock *data;
1808 
1809   if (mainw == NULL || (mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL)) || mainw->go_away ||
1810       mainw->is_processing ||
1811       LIVES_IS_PLAYING) return FALSE;
1812   if (mainw->multitrack == NULL) return FALSE;
1813 
1814   data = (iblock *)lives_malloc(sizeof(iblock));
1815   data->with_audio = with_aud;
1816   data->ign_sel = normalise_aud;
1817   data->id = id;
1818   lives_idle_add(call_render_layout, (livespointer)data);
1819   return TRUE;
1820 }
1821 
1822 
idle_select_all(int cnum,ulong id)1823 boolean idle_select_all(int cnum, ulong id) {
1824   iipref *data;
1825 
1826   if (mainw == NULL || ((mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1827                          !LIVES_IS_PLAYING))) &&
1828                         mainw->multitrack == NULL) || mainw->go_away ||
1829       mainw->is_processing) return FALSE;
1830 
1831   data = (iipref *)lives_malloc(sizeof(iipref));
1832   data->id = id;
1833   data->val = cnum;
1834   lives_idle_add(call_select_all, (livespointer)data);
1835   return TRUE;
1836 }
1837 
1838 
idle_select_start(int cnum,int frame,ulong id)1839 boolean idle_select_start(int cnum, int frame, ulong id) {
1840   iipref *data;
1841 
1842   if (mainw == NULL || ((mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1843                          !LIVES_IS_PLAYING))) &&
1844                         mainw->multitrack == NULL) || mainw->go_away ||
1845       mainw->is_processing) return FALSE;
1846 
1847   data = (iipref *)lives_malloc(sizeof(iipref));
1848   data->id = id;
1849   data->val = cnum;
1850   data->integ = frame;
1851   lives_idle_add(call_select_start, (livespointer)data);
1852   return TRUE;
1853 }
1854 
1855 
idle_select_end(int cnum,int frame,ulong id)1856 boolean idle_select_end(int cnum, int frame, ulong id) {
1857   iipref *data;
1858 
1859   if (mainw == NULL || ((mainw->preview || (mainw->multitrack == NULL && mainw->event_list != NULL && (!mainw->record ||
1860                          !LIVES_IS_PLAYING))) &&
1861                         mainw->multitrack == NULL) || mainw->go_away ||
1862       mainw->is_processing) return FALSE;
1863 
1864   data = (iipref *)lives_malloc(sizeof(iipref));
1865   data->id = id;
1866   data->val = cnum;
1867   data->integ = frame;
1868   lives_idle_add(call_select_end, (livespointer)data);
1869   return TRUE;
1870 }
1871 
1872 
idle_set_current_fps(double fps,ulong id)1873 boolean idle_set_current_fps(double fps, ulong id) {
1874   opfidata *data;
1875 
1876   if (mainw == NULL || !LIVES_IS_PLAYING) return FALSE;
1877 
1878   if (mainw->multitrack != NULL) return FALSE;
1879 
1880   data = (opfidata *)lives_malloc(sizeof(opfidata));
1881   data->id = id;
1882   data->stime = fps;
1883   lives_idle_add(call_set_current_fps, (livespointer)data);
1884   return TRUE;
1885 }
1886 
1887 
idle_set_current_frame(int frame,boolean bg,ulong id)1888 boolean idle_set_current_frame(int frame, boolean bg, ulong id) {
1889   ibpref *data;
1890 
1891   if (mainw == NULL || !LIVES_IS_PLAYING) return FALSE;
1892   if (mainw->multitrack != NULL) return FALSE;
1893 
1894   data = (ibpref *)lives_malloc(sizeof(ibpref));
1895   data->integ = frame;
1896   data->val = bg;
1897   lives_idle_add(call_set_current_frame, (livespointer)data);
1898   return TRUE;
1899 }
1900 
1901 
idle_set_loop_mode(int mode,ulong id)1902 boolean idle_set_loop_mode(int mode, ulong id) {
1903   iipref *data;
1904 
1905   if (mainw == NULL || mainw->go_away) return FALSE;
1906 
1907   data = (iipref *)lives_malloc(sizeof(iipref));
1908   data->id = id;
1909   data->val = mode;
1910   lives_idle_add(call_set_loop_mode, (livespointer)data);
1911   return TRUE;
1912 }
1913 
1914 
idle_resync_fps(ulong id)1915 boolean idle_resync_fps(ulong id) {
1916   iipref *data;
1917 
1918   if (mainw == NULL || !LIVES_IS_PLAYING) return FALSE;
1919 
1920   data = (iipref *)lives_malloc(sizeof(iipref));
1921   data->id = id;
1922   lives_idle_add(call_resync_fps, (livespointer)data);
1923   return TRUE;
1924 }
1925 
1926 
idle_cancel_proc(ulong id)1927 boolean idle_cancel_proc(ulong id) {
1928   iipref *data;
1929 
1930   if (mainw == NULL || mainw->current_file == -1 || cfile == NULL || mainw->proc_ptr == NULL ||
1931       !lives_widget_is_visible(mainw->proc_ptr->cancel_button)) return FALSE;
1932 
1933   data = (iipref *)lives_malloc(sizeof(iipref));
1934   data->id = id;
1935   lives_idle_add(call_cancel_proc, (livespointer)data);
1936   return TRUE;
1937 }
1938 
1939