1 // machinestate.h
2 // (c) G. Finch 2019 - 2020 <salsaman+lives@gmail.com>
3 // released under the GNU GPL 3 or later
4 // see file ../COPYING for licensing details
5 
6 // functions for dealing with externalities
7 
8 /// TODO - split into: memory, files, sysops, threads
9 
10 #ifndef _MACHINESTATE_H_
11 #define _MACHINESTATE_H_
12 
13 #include <sys/time.h>
14 #include <time.h>
15 
16 #define EXTRA_BYTES DEF_ALIGN
17 
18 typedef void *(*malloc_f)(size_t);
19 typedef void (*free_f)(void *);
20 typedef void *(*free_and_return_f)(void *); // like free() but returns NULL
21 typedef void *(*memcpy_f)(void *, const void *, size_t);
22 typedef int (*memcmp_f)(const void *, const void *, size_t);
23 typedef void *(*memset_f)(void *, int, size_t);
24 typedef void *(*memmove_f)(void *, const void *, size_t);
25 typedef void *(*realloc_f)(void *, size_t);
26 typedef void *(*calloc_f)(size_t, size_t);
27 typedef void *(*malloc_and_copy_f)(size_t, const void *);
28 typedef void (*unmalloc_and_copy_f)(size_t, void *);
29 
30 #define USE_RPMALLOC
31 
32 #ifdef USE_RPMALLOC
33 #include "rpmalloc.h"
34 #endif
35 
36 boolean init_memfuncs(void);
37 
38 void lives_free_check(void *p);
39 
40 #ifdef USE_RPMALLOC
41 void *quick_calloc(size_t n, size_t s);
42 void quick_free(void *p);
43 #endif
44 
45 #ifndef lives_malloc
46 #define lives_malloc malloc
47 #endif
48 #ifndef lives_realloc
49 #define lives_realloc realloc
50 #endif
51 #ifndef lives_free
52 #define lives_free free
53 #endif
54 #ifndef lives_memcpy
55 #define lives_memcpy memcpy
56 #endif
57 #ifndef lives_memcmp
58 #define lives_memcmp memcmp
59 #endif
60 #ifndef lives_memset
61 #define lives_memset memset
62 #endif
63 #ifndef lives_memmove
64 #define lives_memmove memmove
65 #endif
66 #ifndef lives_calloc
67 #define lives_calloc calloc
68 #endif
69 
70 #ifdef _lives_malloc
71 #undef _lives_malloc
72 #endif
73 #ifdef _lives_malloc_and_copy
74 #undef _lives_malloc_and_copy
75 #endif
76 #ifdef _lives_realloc
77 #undef _lives_realloc
78 #endif
79 #ifdef _lives_free
80 #undef _lives_free
81 #endif
82 #ifdef _lives_memcpy
83 #undef _lives_memcpy
84 #endif
85 #ifdef _lives_memcmp
86 #undef _lives_memcmp
87 #endif
88 #ifdef _lives_memset
89 #undef _lives_memset
90 #endif
91 #ifdef _lives_memmove
92 #undef _lives_memmove
93 #endif
94 #ifdef _lives_calloc
95 #undef _lives_calloc
96 #endif
97 
98 #ifndef USE_STD_MEMFUNCS
99 // here we can define optimised mem ory functions to used by setting the symbols _lives_malloc, _lives_free, etc.
100 // at the end of the header we check if the values have been set and update lives_malloc from _lives_malloc, etc.
101 // the same values are passed into realtime fx plugins via Weed function overloading
102 #if defined (HAVE_OPENCV) || defined (HAVE_OPENCV4)
103 #ifndef NO_OPENCV_MEMFUNCS
104 #define _lives_malloc(sz)  alignPtr(sz, DEF_ALIGN);
105 #define _lives_free    fastFree
106 #define _lives_realloc proxy_realloc
107 #endif
108 #endif
109 
110 #ifndef __cplusplus
111 
112 #ifdef ENABLE_ORC
113 #ifndef NO_ORC_MEMFUNCS
114 #define _lives_memcpy lives_orc_memcpy
115 #endif
116 #endif
117 
118 #else
119 
120 #ifdef ENABLE_OIL
121 #ifndef NO_OIL_MEMFUNCS
122 #define _lives_memcpy(dest, src, n) {if (n >= 32 && n <= OIL_MEMCPY_MAX_BYTES) { \
123       oil_memcpy((uint8_t *)dest, (const uint8_t *)src, n);		\
124       return dest;\							\
125     }
126 #endif
127 #endif
128 
129 #endif // __cplusplus
130 #endif // USE_STD_MEMFUNCS
131 
132 #define __STDC_FORMAT_MACROS
133 #include <inttypes.h>
134 
135 #undef PRId64
136 #undef PRIu64
137 
138 #ifdef IS_MINGW
139 #define LONGSIZE 32
140 #else
141 
142 #ifdef __WORDSIZE
143 #define LONGSIZE __WORDSIZE
144 #else
145 #if defined __x86_64__
146 # define LONGSIZE	64
147 #ifndef __WORDSIZE_COMPAT32
148 # define __WORDSIZE_COMPAT32	1
149 #endif
150 #else
151 # define LONGSIZE	32
152 #endif // x86
153 #endif // __WORDSIZE
154 #endif // mingw
155 
156 #ifdef __PRI64_PREFIX
157 #undef __PRI64_PREFIX
158 #endif
159 
160 # if LONGSIZE == 64
161 #  define __PRI64_PREFIX	"l"
162 # else
163 #  define __PRI64_PREFIX	"ll"
164 # endif
165 
166 #undef PRId64
167 #undef PRIu64
168 
169 # define PRId64		__PRI64_PREFIX "d"
170 # define PRIu64		__PRI64_PREFIX "u"
171 
172 /// TODO: this file should be split into at least: memory functions, thread functions, file utils
173 
174 void *lives_free_and_return(void *p);
175 void *lives_calloc_safety(size_t nmemb, size_t xsize) GNU_ALIGNED(DEF_ALIGN);
176 void *lives_recalloc(void *p, size_t nmemb, size_t omemb, size_t xsize) GNU_ALIGNED(DEF_ALIGN);
177 
178 size_t get_max_align(size_t req_size, size_t align_max);
179 
180 /// disk/storage status values
181 typedef enum {
182   LIVES_STORAGE_STATUS_UNKNOWN = 0,
183   LIVES_STORAGE_STATUS_NORMAL,
184   LIVES_STORAGE_STATUS_WARNING,
185   LIVES_STORAGE_STATUS_CRITICAL,
186   LIVES_STORAGE_STATUS_OVERFLOW,
187   LIVES_STORAGE_STATUS_OVER_QUOTA,
188   LIVES_STORAGE_STATUS_OFFLINE
189 } lives_storage_status_t;
190 
191 //void shoatend(void);
192 
193 #define WEED_LEAF_MD5SUM "md5sum"
194 
195 // weed plants with type >= 16384 are reserved for custom use, so let's take advantage of that
196 #define WEED_PLANT_LIVES 31337
197 
198 #define WEED_LEAF_LIVES_SUBTYPE "subtype"
199 #define WEED_LEAF_LIVES_MESSAGE_STRING "message_string"
200 
201 #define LIVES_WEED_SUBTYPE_MESSAGE 1
202 #define LIVES_WEED_SUBTYPE_WIDGET 2
203 #define LIVES_WEED_SUBTYPE_TUNABLE 3
204 #define LIVES_WEED_SUBTYPE_PROC_THREAD 4
205 
206 typedef weed_plantptr_t lives_proc_thread_t;
207 
208 weed_plant_t *lives_plant_new(int subtype);
209 weed_plant_t *lives_plant_new_with_index(int subtype, int64_t index);
210 
211 void *_ext_malloc(size_t n) GNU_MALLOC;
212 void *_ext_malloc_and_copy(size_t, const void *) GNU_MALLOC_SIZE(1);
213 void _ext_unmalloc_and_copy(size_t, void *);
214 void _ext_free(void *);
215 void *_ext_free_and_return(void *);
216 void *_ext_memcpy(void *, const void *, size_t);
217 void *_ext_memset(void *, int, size_t);
218 void *_ext_memmove(void *, const void *, size_t);
219 void *_ext_realloc(void *, size_t) GNU_MALLOC_SIZE(2);
220 void *_ext_calloc(size_t, size_t) GNU_MALLOC_SIZE2(1, 2) GNU_ALIGN(2);
221 
222 #define OVERRIDE_MEMFUNCS
223 static void *(*_lsd_memcpy)(void *dest, const void *src, size_t n) = _ext_memcpy;
224 static void *(*_lsd_memset)(void *s, int c, size_t n) = _ext_memset;
225 static void (*_lsd_free)(void *ptr) = rpfree;
226 #define OVERRIDE_CALLOC_ALIGNED
_lsd_calloc_aligned_(void ** memptr,size_t nmemb,size_t size)227 static int _lsd_calloc_aligned_(void **memptr, size_t nmemb, size_t size) {
228   return !memptr ? 0 : (!(*memptr = (rpaligned_calloc)(64, nmemb, size))) ? ENOMEM : 0;
229 }
230 
231 void lives_get_randbytes(void *ptr, size_t size);
232 
233 #if !HAVE_GETENTROPY
234 #define LSD_RANDFUNC(ptr, size) (lives_get_randbytes((ptr), (size)))
235 #endif
236 
237 #include "lsd.h"
238 #undef OVERRIDE_MEMFUNCS
239 
240 #ifdef __GNUC__
241 #define LIVES_GNU
242 #define lives_malloc_auto(size) __builtin_alloc(size)
243 #define lives_malloc_auto_aligned(size, align) __builtin_alloc_with_align(size, align)
244 #endif
245 
246 size_t lives_strlen(const char *) GNU_HOT GNU_PURE;
247 boolean lives_strcmp(const char *, const char *) GNU_HOT GNU_PURE;
248 boolean lives_strncmp(const char *, const char *, size_t) GNU_HOT GNU_PURE;
249 char *lives_strdup_quick(const char *s);
250 int lives_strcmp_ordered(const char *, const char *) GNU_HOT GNU_PURE;
251 char *lives_concat(char *, char *) GNU_HOT;
252 char *lives_concat_sep(char *st, const char *sep, char *x);
253 char *lives_strstop(char *, const char term) GNU_HOT;
254 int lives_strappend(const char *string, int len, const char *xnew);
255 const char *lives_strappendf(const char *string, int len, const char *fmt, ...);
256 
257 void swab2(const void *from, const void *to, size_t granularity) 	GNU_HOT;
258 void swab4(const void *from, const void *to, size_t granularity) 	GNU_HOT;
259 void swab8(const void *from, const void *to, size_t granularity) 	GNU_HOT;
260 void reverse_bytes(char *buff, size_t count, size_t granularity) 	GNU_HOT GNU_FLATTEN;
261 boolean reverse_buffer(uint8_t *buff, size_t count, size_t chunk) 	GNU_HOT;
262 
263 uint64_t nxtval(uint64_t val, uint64_t lim, boolean less);
264 uint64_t autotune_u64_end(weed_plant_t **tuner, uint64_t val);
265 void autotune_u64(weed_plant_t *tuner,  uint64_t min, uint64_t max, int ntrials, double cost);
266 
267 void init_random(void);
268 void lives_srandom(unsigned int seed);
269 uint64_t lives_random(void);
270 
271 uint64_t fastrand(void) GNU_HOT;
272 void fastrand_add(uint64_t entropy);
273 double fastrand_dbl(double range);
274 uint32_t fastrand_int(uint32_t range);
275 
276 uint64_t gen_unique_id(void);
277 
278 #ifdef ENABLE_ORC
279 void *lives_orc_memcpy(void *dest, const void *src, size_t n);
280 #endif
281 
282 #ifdef ENABLE_OIL
283 void *lives_oil_memcpy(void *dest, const void *src, size_t n);
284 #endif
285 
286 void *proxy_realloc(void *ptr, size_t new_size);
287 
288 char *get_md5sum(const char *filename);
289 
290 char *lives_format_storage_space_string(uint64_t space);
291 lives_storage_status_t get_storage_status(const char *dir, uint64_t warn_level, int64_t *dsval, int64_t resvd);
292 uint64_t get_ds_free(const char *dir);
293 
294 lives_proc_thread_t disk_monitor_start(const char *dir);
295 boolean disk_monitor_running(const char *dir);
296 int64_t disk_monitor_check_result(const char *dir);
297 int64_t disk_monitor_wait_result(const char *dir, ticks_t timeout);
298 void disk_monitor_forget(void);
299 
300 char *get_mountpoint_for(const char *dir);
301 
302 ticks_t lives_get_relative_ticks(ticks_t origsecs, ticks_t orignsecs);
303 ticks_t lives_get_current_ticks(void);
304 char *lives_datetime(uint64_t secs, boolean use_local);
305 char *lives_datetime_rel(const char *datetime);
306 
307 #define lives_nanosleep(nanosec) {struct timespec ts; ts.tv_sec = (uint64_t)nanosec / ONE_BILLION; \
308     ts.tv_nsec = (uint64_t)nanosec - ts.tv_sec * ONE_BILLION; while (nanosleep(&ts, &ts) == -1 && \
309 								     errno != ETIMEDOUT);}
310 #define lives_nanosleep_until_nonzero(condition) {while (!(condition)) lives_nanosleep(1000);}
311 
312 int check_dev_busy(char *devstr);
313 
314 off_t get_file_size(int fd);
315 off_t sget_file_size(const char *name);
316 
317 void reget_afilesize(int fileno);
318 off_t reget_afilesize_inner(int fileno);
319 
320 off_t get_dir_size(const char *dirname);
321 
322 boolean compress_files_in_dir(const char *dir, int method, void *data);
323 LiVESResponseType send_to_trash(const char *item);
324 
325 /// extras we can check for, may consume more time
326 #define EXTRA_DETAILS_CHECK_MISSING	       	(1ul << 0)
327 #define EXTRA_DETAILS_DIRSIZE			(1ul << 1)
328 #define EXTRA_DETAILS_EMPTY_DIRS	       	(1ul << 2)
329 #define EXTRA_DETAILS_SYMLINK		       	(1ul << 3)
330 #define EXTRA_DETAILS_ACCESSIBLE	       	(1ul << 4)
331 #define EXTRA_DETAILS_WRITEABLE			(1ul << 5)
332 #define EXTRA_DETAILS_EXECUTABLE       		(1ul << 6)
333 #define EXTRA_DETAILS_CLIPHDR			(1ul << 7)
334 
335 /// derived values
336 #define EXTRA_DETAILS_MD5SUM			(1ul << 33)
337 
338 typedef struct {
339   ///< if we can retrieve some kind of uinque id, we set it here
340   ///< may be useful in future for dictionary lookups
341   uint64_t uniq;
342   lives_struct_def_t *lsd;
343   char *name;
344   uint64_t type; /// e.g. LIVES_FILE_TYPE_FILE
345   off_t size; // -1 not checked, -2 unreadable
346   uint64_t mode;
347   uint64_t uid; /// userid as uint64_t
348   uint64_t gid;
349   uint64_t blk_size;
350   uint64_t atime_sec;
351   uint64_t atime_nsec;
352   uint64_t mtime_sec;
353   uint64_t mtime_nsec;
354   uint64_t ctime_sec;
355   uint64_t ctime_nsec;
356   char *md5sum; /// only filled if EXTRA_DETAILS_MD5 is set, otherwis NULL
357   char *extra_details;  /// intialized to NULL, set to at least ""
358   LiVESWidget *widgets[16]; ///< caller set widgets for presentation, e.g. labels, spinners. final entry must be followed by NULL
359 } lives_file_dets_t;
360 
361 #ifdef PRODUCE_LOG
362 // disabled by default
363 void lives_log(const char *what);
364 #endif
365 
366 uint32_t lives_string_hash(const char *string) GNU_PURE GNU_HOT;
367 uint32_t fast_hash(const char *key) GNU_PURE GNU_HOT;
368 char *lives_chomp(char *string);
369 char *lives_strtrim(const char *buff);
370 
371 int check_for_bad_ffmpeg(void);
372 
373 void update_effort(int nthings, boolean badthings);
374 void reset_effort(void);
375 
376 //// threadpool API
377 
378 typedef void *(*lives_funcptr_t)(void *);
379 
380 typedef struct _lives_thread_data_t lives_thread_data_t;
381 
382 typedef struct {
383   lives_proc_thread_t var_tinfo;
384   lives_thread_data_t *var_mydata;
385   boolean var_com_failed;
386   int var_write_failed, var_read_failed;
387   boolean var_chdir_failed;
388   char *var_read_failed_file, *var_write_failed_file, *var_bad_aud_file;
389   int var_rowstride_alignment;   // used to align the rowstride bytesize in create_empty_pixel_data
390   int var_rowstride_alignment_hint;
391   int var_last_sws_block;
392   boolean var_no_gui;
393 } lives_threadvars_t;
394 
395 struct _lives_thread_data_t {
396   LiVESWidgetContext *ctx;
397   int64_t idx;
398   lives_threadvars_t vars;
399 };
400 
401 typedef struct {
402   lives_funcptr_t func;
403   void *arg;
404   uint64_t flags;
405   volatile uint64_t busy;
406   volatile uint64_t done;
407   void *ret;
408   volatile boolean sync_ready;
409 } thrd_work_t;
410 
411 #define WEED_LEAF_NOTIFY "notify"
412 #define WEED_LEAF_DONE "done"
413 #define WEED_LEAF_THREADFUNC "tfunction"
414 #define WEED_LEAF_THREAD_PROCESSING "t_processing"
415 #define WEED_LEAF_THREAD_CANCELLABLE "t_can_cancel"
416 #define WEED_LEAF_THREAD_CANCELLED "t_cancelled"
417 #define WEED_LEAF_RETURN_VALUE "return_value"
418 #define WEED_LEAF_DONTCARE "dontcare"  ///< tell proc_thread with return value that we n o longer need return val.
419 #define WEED_LEAF_DONTCARE_MUTEX "dontcare_mutex" ///< ensures we can set dontcare without it finishing while doing so
420 
421 #define WEED_LEAF_SIGNALLED "signalled"
422 #define WEED_LEAF_SIGNAL_DATA "signal_data"
423 
424 #define WEED_LEAF_THREAD_PARAM "thrd_param"
425 #define _WEED_LEAF_THREAD_PARAM(n) WEED_LEAF_THREAD_PARAM  n
426 #define WEED_LEAF_THREAD_PARAM0 _WEED_LEAF_THREAD_PARAM("0")
427 #define WEED_LEAF_THREAD_PARAM1 _WEED_LEAF_THREAD_PARAM("1")
428 #define WEED_LEAF_THREAD_PARAM2 _WEED_LEAF_THREAD_PARAM("2")
429 
430 #define LIVES_THRDFLAG_AUTODELETE	(1 << 0)
431 #define LIVES_THRDFLAG_TUNING		(1 << 1)
432 #define LIVES_THRDFLAG_WAIT_SYNC	(1 << 2)
433 
434 typedef LiVESList lives_thread_t;
435 typedef uint64_t lives_thread_attr_t;
436 
437 #define LIVES_THRDATTR_NONE		0
438 #define LIVES_THRDATTR_AUTODELETE	(1 << 0)
439 #define LIVES_THRDATTR_PRIORITY		(1 << 1)
440 #define LIVES_THRDATTR_WAIT_SYNC	(1 << 2)
441 #define LIVES_THRDATTR_FG_THREAD	(1 << 3)
442 #define LIVES_THRDATTR_NO_GUI		(1 << 4)
443 
444 void lives_threadpool_init(void);
445 void lives_threadpool_finish(void);
446 int lives_thread_create(lives_thread_t *thread, lives_thread_attr_t attr, lives_funcptr_t func, void *arg);
447 uint64_t lives_thread_join(lives_thread_t work, void **retval);
448 
449 // lives_proc_thread_t //////////////////////////////////////////////////////////////////////////////////////////////////////////
450 
451 #define _RV_ WEED_LEAF_RETURN_VALUE
452 
453 typedef uint64_t funcsig_t;
454 
455 typedef int(*funcptr_int_t)();
456 typedef double(*funcptr_dbl_t)();
457 typedef int(*funcptr_bool_t)();
458 typedef char *(*funcptr_string_t)();
459 typedef int64_t(*funcptr_int64_t)();
460 typedef weed_funcptr_t(*funcptr_funcptr_t)();
461 typedef void *(*funcptr_voidptr_t)();
462 typedef weed_plant_t(*funcptr_plantptr_t)();
463 
464 #define GETARG(type, n) WEED_LEAF_GET(info, _WEED_LEAF_THREAD_PARAM(n), type)
465 
466 #define ARGS1(t1) GETARG(t1, "0")
467 #define ARGS2(t1, t2) ARGS1(t1), GETARG(t2, "1")
468 #define ARGS3(t1, t2, t3) ARGS2(t1, t2), GETARG(t3, "2")
469 #define ARGS4(t1, t2, t3, t4) ARGS3(t1, t2, t3), GETARG(t4, "3")
470 #define ARGS5(t1, t2, t3, t4, t5) ARGS4(t1, t2, t3, t4), GETARG(t5, "4")
471 #define ARGS6(t1, t2, t3, t4, t5, t6) ARGS5(t1, t2, t3, t4, t5), GETARG(t6, "5")
472 #define ARGS7(t1, t2, t3, t4, t5, t6, t7) ARGS6(t1, t2, t3, t4, t5, t6), GETARG(t7, "6")
473 #define ARGS8(t1, t2, t3, t4, t5, t6, t7, t8) ARGS7(t1, t2, t3, t4, t5, t6, t7), GETARG(t8, "7")
474 #define ARGS9(t1, t2, t3, t4, t5, t6, t7, t8, t9) ARGS8(t1, t2, t3, t4, t5, t6, t7. t8), GETARG(t9, "8")
475 #define ARGS10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) ARGS9(t1, t2, t3, t4, t5, t6, t7, t8, t9), GETARG(t10, "9")
476 
477 #define CALL_VOID_10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) (*thefunc->func)(ARGS10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10))
478 #define CALL_VOID_9(t1, t2, t3, t4, t5, t6, t7, t8, t9) (*thefunc->func)(ARGS9(t1, t2, t3, t4, t5, t6, t7, t8, t9))
479 #define CALL_VOID_8(t1, t2, t3, t4, t5, t6, t7, t8) (*thefunc->func)(ARGS8(t1, t2, t3, t4, t5, t6, t7, t8))
480 #define CALL_VOID_7(t1, t2, t3, t4, t5, t6, t7) (*thefunc->func)(ARGS7(t1, t2, t3, t4, t5, t6, t7))
481 #define CALL_VOID_6(t1, t2, t3, t4, t5, t6) (*thefunc->func)(ARGS6(t1, t2, t3, t4, t5, t6))
482 #define CALL_VOID_5(t1, t2, t3, t4, t5) (*thefunc->func)(ARGS5(t1, t2, t3, t4, t5))
483 #define CALL_VOID_4(t1, t2, t3, t4) (*thefunc->func)(ARGS4(t1, t2, t3, t4))
484 #define CALL_VOID_3(t1, t2, t3) (*thefunc->func)(ARGS3(t1, t2, t3))
485 #define CALL_VOID_2(t1, t2) (*thefunc->func)(ARGS2(t1, t2))
486 #define CALL_VOID_1(t1) (*thefunc->func)(ARGS1(t1))
487 #define CALL_VOID_0() (*thefunc->func)()
488 
489 #define CALL_10(ret, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) weed_set_##ret##_value(info, _RV_, \
490 										     (*thefunc->func##ret)(ARGS10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t19)))
491 #define CALL_9(ret, t1, t2, t3, t4, t5, t6, t7, t8, t9) weed_set_##ret##_value(info, _RV_, \
492 									       (*thefunc->func##ret)(ARGS9(t1, t2, t3, t4, t5, t6, t7, t8, t9)))
493 #define CALL_8(ret, t1, t2, t3, t4, t5, t6, t7, t8) weed_set_##ret##_value(info, _RV_, \
494 									   (*thefunc->func##ret)(ARGS8(t1, t2, t3, t4, t5, t6, t7, t7)))
495 #define CALL_7(ret, t1, t2, t3, t4, t5, t6, t7) weed_set_##ret##_value(info, _RV_, \
496 								       (*thefunc->func##ret)(ARGS7(t1, t2, t3, t4, t5, t6, t7)))
497 #define CALL_6(ret, t1, t2, t3, t4, t5, t6) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)(ARGS6(t1, t2, t3, t4, t5, t6)))
498 #define CALL_5(ret, t1, t2, t3, t4, t5) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)(ARGS5(t1, t2, t3, t4, t5)))
499 #define CALL_4(ret, t1, t2, t3, t4) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)(ARGS4(t1, t2, t3, t4)))
500 #define CALL_3(ret, t1, t2, t3) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)(ARGS3(t1, t2, t3)))
501 #define CALL_2(ret, t1, t2) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)(ARGS2(t1, t2)))
502 #define CALL_1(ret, t1) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)(ARGS1(t1)))
503 #define CALL_0(ret) weed_set_##ret##_value(info, _RV_, (*thefunc->func##ret)())
504 
505 typedef union {
506   weed_funcptr_t func;
507   funcptr_int_t funcint;
508   funcptr_dbl_t funcdouble;
509   funcptr_bool_t funcboolean;
510   funcptr_int64_t funcint64;
511   funcptr_string_t funcstring;
512   funcptr_funcptr_t funcfuncptr;
513   funcptr_voidptr_t funcvoidptr;
514   funcptr_plantptr_t funcplantptr;
515 } allfunc_t;
516 
517 lives_proc_thread_t lives_proc_thread_create(lives_thread_attr_t, lives_funcptr_t, int return_type, const char *args_fmt,
518     ...);
519 
520 void lives_proc_thread_free(lives_proc_thread_t lpt);
521 
522 /// returns FALSE while the thread is running, TRUE once it has finished
523 boolean lives_proc_thread_check(lives_proc_thread_t);
524 int lives_proc_thread_signalled(lives_proc_thread_t tinfo);
525 int64_t lives_proc_thread_signalled_idx(lives_proc_thread_t tinfo);
526 
527 lives_thread_data_t *get_thread_data(void);
528 lives_threadvars_t *get_threadvars(void);
529 lives_thread_data_t *lives_thread_data_create(uint64_t idx);
530 
531 #define THREADVAR(var) (get_threadvars()->var_##var)
532 
533 /// only threads with no return value can possibly be cancellable. For threads with a value, use
534 /// lives_proc_thread_dontcare()
535 void lives_proc_thread_set_cancellable(lives_proc_thread_t);
536 boolean lives_proc_thread_get_cancellable(lives_proc_thread_t);
537 boolean lives_proc_thread_cancel(lives_proc_thread_t);
538 boolean lives_proc_thread_cancelled(lives_proc_thread_t);
539 
540 /// tell a threead with return value that we no longer need the value so it can free itself
541 boolean lives_proc_thread_dontcare(lives_proc_thread_t);
542 
543 void lives_proc_thread_sync_ready(lives_proc_thread_t);
544 
545 // WARNING !! version without a return value will free tinfo !
546 void lives_proc_thread_join(lives_proc_thread_t);
547 
548 // with return value should free proc_thread
549 int lives_proc_thread_join_int(lives_proc_thread_t);
550 double lives_proc_thread_join_double(lives_proc_thread_t);
551 int lives_proc_thread_join_boolean(lives_proc_thread_t);
552 char *lives_proc_thread_join_string(lives_proc_thread_t);
553 weed_funcptr_t lives_proc_thread_join_funcptr(lives_proc_thread_t);
554 void *lives_proc_thread_join_voidptr(lives_proc_thread_t);
555 weed_plantptr_t lives_proc_thread_join_plantptr(lives_proc_thread_t) ;
556 int64_t lives_proc_thread_join_int64(lives_proc_thread_t);
557 
558 void resubmit_proc_thread(lives_proc_thread_t, lives_thread_attr_t);
559 
560 void *fg_run_func(lives_proc_thread_t lpt, void *retval);
561 void *main_thread_execute(lives_funcptr_t func, int return_type, void *retval, const char *args_fmt, ...);
562 
563 void free_fdets_list(LiVESList **);
564 lives_proc_thread_t dir_to_file_details(LiVESList **, const char *dir,
565                                         const char *orig_loc, uint64_t extra);
566 lives_proc_thread_t ordfile_to_file_details(LiVESList **listp, const char *ofname,
567     const char *orig_loc, uint64_t extra);
568 
569 ///// cmdline
570 char *grep_in_cmd(const char *cmd, int mstart, int npieces, const char *mphrase, int ridx, int rlen);
571 
572 /// x11
573 char *get_wid_for_name(const char *wname);
574 boolean hide_x11_window(const char *wid);
575 boolean unhide_x11_window(const char *wid);
576 boolean activate_x11_window(const char *wid);
577 boolean show_desktop_panel(void);
578 boolean hide_desktop_panel(void);
579 boolean get_x11_visible(const char *wname);
580 
581 int get_window_stack_level(LiVESXWindow *, int *nwins);
582 
583 #define WM_XFWM4 "Xfwm4"
584 #define WM_XFCE4_PANEL "xfce4-panel"
585 #define WM_XFCE4_SSAVE "xfce4-ssave"
586 #define WM_XFCE4_COLOR "xfce4-color-settings"
587 #define WM_XFCE4_DISP "xfce4-display-settings"
588 #define WM_XFCE4_POW "xfce4-power-manager-settings"
589 #define WM_XFCE4_SETTINGS "xfce4-settings-manager"
590 #define WM_XFCE4_TERMINAL "xfce4-terminal"
591 #define WM_XFCE4_TASKMGR "xfce4-taskmanager"
592 #define WM_XFCE4_SSHOT "xfce4-screenshooter"
593 
594 #define WM_KWIN "KWin"
595 #define WM_KWIN_PANEL ""
596 #define WM_KWIN_SSAVE ""
597 #define WM_KWIN_COLOR ""
598 #define WM_KWIN_DISP ""
599 #define WM_KWIN_POW ""
600 #define WM_KWIN_SETTINGS "systemseettings5"
601 #define WM_KWIN_TERMINAL "Konsole"
602 #define WM_KWIN_TASKMGR "systemmonitor"
603 #define WM_KWIN_SSHOT ""
604 
605 #define XDG_CURRENT_DESKTOP "XDG_CURRENT_DESKTOP"
606 #define XDG_SESSION_TYPE "XDG_SESSION_TYPE"
607 
608 boolean get_wm_caps(void);
609 boolean get_distro_dets(void);
610 boolean get_machine_dets(void);
611 int get_num_cpus(void);
612 double get_disk_load(const char *mp);
613 int64_t get_cpu_load(int cpun); ///< percent * 1 million
614 
615 char *get_systmp(const char *suff, boolean is_dir);
616 char *get_worktmp(const char *prefix);
617 char *get_worktmpfile(const char *prefix);
618 
619 boolean check_snap(const char *prog);
620 
621 #endif
622