LiVES  3.2.0
machinestate.c
Go to the documentation of this file.
1 // machinestate.c
2 // LiVES
3 // (c) G. Finch 2019 - 2020 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING for licensing details
6 
7 // functions for dealing with externalities
8 
9 #include <sys/statvfs.h>
10 #include "main.h"
11 #include "callbacks.h"
12 
13 LIVES_LOCAL_INLINE char *mini_popen(char *cmd);
14 
15 #if IS_X86_64
16 
17 static void cpuid(unsigned int ax, unsigned int *p) {
18  __asm __volatile
19  ("movl %%ebx, %%esi\n\tcpuid\n\txchgl %%ebx, %%esi"
20  : "=a"(p[0]), "=S"(p[1]), "=c"(p[2]), "=d"(p[3])
21  : "0"(ax));
22 }
23 
24 static int get_cacheline_size(void) {
25  unsigned int cacheline = -1;
26  unsigned int regs[4], regs2[4];
27  cpuid(0x00000000, regs);
28  if (regs[0] >= 0x00000001) {
29  cpuid(0x00000001, regs2);
30  cacheline = ((regs2[1] >> 8) & 0xFF) * 8;
31  //has_sse2 = (regs2[3] & 0x4000000) ? TRUE : FALSE;
32  }
33  return cacheline;
34 }
35 
36 #endif
37 
38 static uint64_t fastrand_val = 0;
39 
40 LIVES_GLOBAL_INLINE uint64_t fastrand(void) {
41  fastrand_val ^= (fastrand_val << 13); fastrand_val ^= (fastrand_val >> 7);
42  fastrand_val = ((fastrand_val & 0xFFFFFFFF00000000) >> 32) | ((fastrand_val & 0xFFFFFFFF) << 32);
43  fastrand_val ^= (fastrand_val << 17);
44  return fastrand_val;
45 }
46 
47 LIVES_GLOBAL_INLINE void fastrand_add(uint64_t entropy) {fastrand_val += entropy;}
48 
49 LIVES_GLOBAL_INLINE double fastrand_dbl(double range) {
50  static const double divd = (double)(0xFFFFFFFFFFFFFFFF); return (double)fastrand() / divd * range;
51 }
52 
54 LIVES_GLOBAL_INLINE uint32_t fastrand_int(uint32_t range) {return (uint32_t)(fastrand_dbl((double)(++range)));}
55 
56 LIVES_GLOBAL_INLINE void lives_srandom(unsigned int seed) {srandom(seed);}
57 
58 LIVES_GLOBAL_INLINE uint64_t lives_random(void) {return random();}
59 
60 void lives_get_randbytes(void *ptr, size_t size) {
61  if (size <= 8) {
62  uint64_t rbytes = gen_unique_id();
63  lives_memcpy(ptr, &rbytes, size);
64  }
65 }
66 
67 
68 uint64_t gen_unique_id(void) {
69  static uint64_t last_rnum = 0;
70  uint64_t rnum;
71 #if HAVE_GETENTROPY
72  int randres = getentropy(&rnum, 8);
73 #else
74  int randres = 1;
75 #endif
76  if (randres) {
77  fastrand_val = lives_random();
78  fastrand();
79  fastrand_val ^= lives_get_current_ticks();
80  rnum = fastrand();
81  }
83  // a number < 1 billion is approx. 2 ^ 30 / 2 ^ 64 or about 1 chance in 17 trillion
84  // the chance of it happening the first time is thus minscule
85  // and the chance of it happening twice by chance is so unlikely we should discount it
86  if (rnum < BILLIONS(1) && last_rnum < BILLIONS(1)) abort();
87  last_rnum = rnum;
88  return rnum;
89 }
90 
91 
92 void init_random() {
93  uint32_t rseed;
94 #ifdef HAVE_GETENTROPY
95  if (getentropy(&rseed, 4)) rseed = (gen_unique_id() & 0xFFFFFFFF);
96 #else
97  rseed = (gen_unique_id() & 0xFFFFFFFF);
98 #endif
99  lives_srandom(rseed);
100  fastrand_val = gen_unique_id();
101 }
102 
103 
105 
106 struct _decomp {
107  uint64_t value;
108  int i, j;
109 };
110 
111 struct _decomp_tab {
112  uint64_t value;
113  int i, j;
114  struct _decomp_tab *lower, *higher;
115 };
116 
117 static struct _decomp_tab nxttbl[64][25];
118 static boolean nxttab_inited = FALSE;
119 
120 void make_nxttab(void) {
121  LiVESList *preplist = NULL, *dccl, *dccl_last = NULL;
122  uint64_t val6 = 1ul, val;
123  struct _decomp *dcc;
124  int max2pow, xi, xj;
125  if (nxttab_inited) return;
126  for (int j = 0; j < 25; j++) {
127  val = val6;
128  max2pow = 64 - ((j * 10 + 7) >> 2);
129  dccl = preplist;
130  for (int i = 0; i < max2pow; i++) {
131  dcc = (struct _decomp *)lives_malloc(sizeof(struct _decomp));
132  dcc->value = val;
133  dcc->i = i;
134  dcc->j = j;
135  if (!preplist) dccl = preplist = lives_list_append(preplist, dcc);
136  else {
137  LiVESList *dccl2 = lives_list_append(NULL, (livespointer)dcc);
138  for (; dccl; dccl = dccl->next) {
139  dcc = (struct _decomp *)dccl->data;
140  if (dcc->value > val) break;
141  dccl_last = dccl;
142  }
143  if (!dccl) {
144  dccl_last->next = dccl2;
145  dccl2->prev = dccl_last;
146  dccl2->next = NULL;
147  dccl = dccl2;
148  } else {
149  dccl2->next = dccl;
150  dccl2->prev = dccl->prev;
151  if (dccl->prev) dccl->prev->next = dccl2;
152  else preplist = dccl2;
153  dccl->prev = dccl2;
154  }
155  }
156  val *= 2;
157  }
158  val6 *= 6;
159  }
160  for (dccl = preplist; dccl; dccl = dccl->next) {
161  dcc = (struct _decomp *)dccl->data;
162  xi = dcc->i;
163  xj = dcc->j;
164  nxttbl[xi][xj].value = dcc->value;
165  nxttbl[xi][xj].i = xi;
166  nxttbl[xi][xj].j = xj;
167  if (dccl->prev) {
168  dcc = (struct _decomp *)dccl->prev->data;
169  nxttbl[xi][xj].lower = &(nxttbl[dcc->i][dcc->j]);
170  } else nxttbl[xi][xj].lower = NULL;
171  if (dccl->next) {
172  dcc = (struct _decomp *)dccl->next->data;
173  nxttbl[xi][xj].higher = &(nxttbl[dcc->i][dcc->j]);
174  } else nxttbl[xi][xj].higher = NULL;
175  }
176  lives_list_free_all(&preplist);
177  nxttab_inited = TRUE;
178 }
179 
180 
181 
182 void autotune_u64(weed_plant_t *tuner, uint64_t min, uint64_t max, int ntrials, double cost) {
183  if (tuner) {
184  double tc = cost;
185  int trials = weed_get_int_value(tuner, "trials", NULL);
186  if (trials == 0) {
187  weed_set_int_value(tuner, "ntrials", ntrials);
188  weed_set_int64_value(tuner, "min", min);
189  weed_set_int64_value(tuner, "max", max);
190  } else tc += weed_get_double_value(tuner, "tcost", NULL);
191  weed_set_double_value(tuner, "tcost", tc);
192  weed_set_int64_value(tuner, "tstart", lives_get_current_ticks());
193  }
194 }
195 
196 #define NCYCS 16
197 
198 uint64_t nxtval(uint64_t val, uint64_t lim, boolean less) {
199  // to avoid only checking powers of 2, we want some number which is (2 ** i) * (6 ** j)
200  // which gives a nice range of results
201  uint64_t oval = val;
202  int i = 0, j = 0;
203  if (!nxttab_inited) make_nxttab();
206  if (val & 1) {
207  if (less) val--;
208  else val++;
209  }
210  for (; !(val % 6) && val > 0; j++, val /= 6);
212  for (; val > 1; i++, val /= 2) {
213  if (val & 1) {
214  if (less) val--;
215  else val++;
216  }
217  }
218  val = nxttbl[i][j].value;
219  if (less) {
220  if (val == oval) {
221  if (nxttbl[i][j].lower) val = nxttbl[i][j].lower->value;
222  } else {
223  while (nxttbl[i][j].higher->value < oval) {
224  int xi = nxttbl[i][j].higher->i;
225  val = nxttbl[i][j].value;
226  j = nxttbl[i][j].higher->j;
227  i = xi;
228  }
229  }
230  return val > lim ? val : lim;
231  }
232  if (val == oval) {
233  if (nxttbl[i][j].higher) val = nxttbl[i][j].higher->value;
234  } else {
235  while (nxttbl[i][j].lower && nxttbl[i][j].lower->value > oval) {
236  int xi = nxttbl[i][j].lower->i;
237  j = nxttbl[i][j].lower->j;
238  i = xi;
239  val = nxttbl[i][j].value;
240  }
241  }
242  return val < lim ? val : lim;
243 }
244 
245 
246 static const char *get_tunert(int idx) {
247  switch (idx) {
248  case 2: return "orc_memcpy cutoff";
249  case 3: return "read buffer size (small)";
250  case 4: return "read buffer size (small / medium)";
251  case 5: return "read buffer size (medium)";
252  case 6: return "read buffer size (large)";
253  default: break;
254  }
255  return "unknown variable";
256 }
257 
258 
259 uint64_t autotune_u64_end(weed_plant_t **tuner, uint64_t val) {
260  if (!tuner || !*tuner) return val;
261  else {
262  ticks_t tottime = lives_get_current_ticks();
263  int ntrials, trials;
264  int64_t max;
265  int64_t min = weed_get_int64_value(*tuner, "min", NULL);
266 
267  if (val < min) {
268  val = min;
269  weed_set_int_value(*tuner, "trials", 0);
270  weed_set_int64_value(*tuner, "tottime", 0);
271  weed_set_double_value(*tuner, "tcost", 0);
272  return val;
273  }
274  max = weed_get_int64_value(*tuner, "max", NULL);
275  if (val > max) {
276  val = max;
277  weed_set_int_value(*tuner, "trials", 0);
278  weed_set_int64_value(*tuner, "tottime", 0);
279  weed_set_double_value(*tuner, "tcost", 0);
280  return val;
281  }
282 
283  ntrials = weed_get_int_value(*tuner, "ntrials", NULL);
284  trials = weed_get_int_value(*tuner, "trials", NULL);
285 
286  weed_set_int_value(*tuner, "trials", ++trials);
287  tottime += (weed_get_int64_value(*tuner, "tottime", NULL)) - weed_get_int64_value(*tuner, "tstart", NULL);
288  weed_set_int64_value(*tuner, "tottime", tottime);
289 
290  if (trials >= ntrials) {
291  int cycs = weed_get_int_value(*tuner, "cycles", NULL) + 1;
292  if (cycs < NCYCS) {
293  double tcost = (double)weed_get_double_value(*tuner, "tcost", NULL);
294  double totcost = (double)tottime * tcost;
295  double avcost = totcost / (double)(cycs * ntrials);
296  double ccosts, ccostl;
297  boolean smfirst = FALSE;
298  char *key1 = lives_strdup_printf("tottrials_%lu", val);
299  char *key2 = lives_strdup_printf("totcost_%lu", val);
300 
301  weed_set_int_value(*tuner, key1, weed_get_int_value(*tuner, key1, NULL) + trials);
302  weed_set_double_value(*tuner, key2, weed_get_double_value(*tuner, key2, NULL) + totcost);
303 
304  lives_free(key1);
305  lives_free(key2);
306 
307  if (cycs & 1) smfirst = TRUE;
308  weed_set_int_value(*tuner, "cycles", cycs);
309 
310  weed_set_int_value(*tuner, "trials", 0);
311  weed_set_int64_value(*tuner, "tottime", 0);
312  weed_set_double_value(*tuner, "tcost", 0);
313 
314  if (smfirst) {
315  if (val > max || weed_plant_has_leaf(*tuner, "smaller")) {
316  ccosts = weed_get_double_value(*tuner, "smaller", NULL);
317  if (val > max || (ccosts < avcost)) {
318  weed_set_double_value(*tuner, "larger", avcost);
319  weed_leaf_delete(*tuner, "smaller");
320  if (val > max) return max;
321  return nxtval(val, min, TRUE); // TRUE to get smaller val
322  }
323  }
324  }
325 
326  if (val < min || weed_plant_has_leaf(*tuner, "larger")) {
327  ccostl = weed_get_double_value(*tuner, "larger", NULL);
328  if (val < min || (ccostl < avcost)) {
329  weed_set_double_value(*tuner, "smaller", avcost);
330  weed_leaf_delete(*tuner, "larger");
331  if (val < min) return min;
332  return nxtval(val, max, FALSE);
333  }
334  }
335 
336  if (!smfirst) {
337  if (val > max || weed_plant_has_leaf(*tuner, "smaller")) {
338  ccosts = weed_get_double_value(*tuner, "smaller", NULL);
339  if (val > max || (ccosts < avcost)) {
340  weed_set_double_value(*tuner, "larger", avcost);
341  weed_leaf_delete(*tuner, "smaller");
342  if (val > max) return max;
343  return nxtval(val, min, TRUE);
344  }
345  }
346 
347  if (!weed_plant_has_leaf(*tuner, "larger")) {
348  weed_set_double_value(*tuner, "smaller", avcost);
349  weed_leaf_delete(*tuner, "larger");
350  return nxtval(val, max, FALSE);
351  }
352  }
353 
354  if (!weed_plant_has_leaf(*tuner, "smaller")) {
355  weed_set_double_value(*tuner, "larger", avcost);
356  weed_leaf_delete(*tuner, "smaller");
357  return nxtval(val, min, TRUE);
358  }
359 
360  if (smfirst) {
361  if (!weed_plant_has_leaf(*tuner, "larger")) {
362  weed_set_double_value(*tuner, "smaller", avcost);
363  weed_leaf_delete(*tuner, "larger");
364  return nxtval(val, max, FALSE);
365  }
366  }
367 
368  weed_leaf_delete(*tuner, "smaller");
369  weed_leaf_delete(*tuner, "larger");
370  if (!smfirst) {
371  return nxtval(nxtval(val, max, FALSE), max, FALSE);
372  } else {
373  return nxtval(nxtval(val, min, TRUE), min, TRUE);
374  }
375  } else {
376  weed_size_t nleaves;
377  char **res = weed_plant_list_leaves(*tuner, &nleaves);
378  uint64_t bestval = val, xval;
379  const char *key1 = "totcost_";
380  char *key2;
381  double avcost, costmin = 0.;
382  boolean gotcost = FALSE;
383  int j;
384 
385  for (int i = 1; i < nleaves; i++) {
386  if (!strncmp(res[i], key1, 8)) {
387  xval = strtoul((const char *)(res[i] + 8), NULL, 10);
388  key2 = lives_strdup_printf("totrials_%lu", xval);
389  for (j = i + 1; j < nleaves; j++) {
390  if (!strcmp(res[j], key2)) break;
391  }
392  if (j == nleaves) {
393  for (j = 0; j < i; j++) {
394  if (!strcmp(res[j], key2)) break;
395  }
396  }
397  if ((avcost = weed_get_double_value(*tuner, res[i], NULL)
398  / (double)weed_get_int_value(*tuner, res[j], NULL)) < costmin
399  || !gotcost) {
400  costmin = avcost;
401  bestval = xval;
402  gotcost = TRUE;
403  }
404  lives_free(key2);
405  }
406  }
407  val = bestval;
408  if (prefs->show_dev_opts)
409  g_printerr("value of %s tuned to %lu\n",
410  get_tunert(weed_get_int64_value(*tuner, WEED_LEAF_INDEX, NULL)), val);
411  // TODO: store value so we can recalibrate again later
412  //tuned = (struct tuna *)lives_malloc(sizeof(tuna));
413  //tuna->wptpp = tuner;
414  //tuna->id = weed_get_in
415  //lives_list_prepend(tunables, tuned);
416  weed_plant_free(*tuner);
417  *tuner = NULL;
418  for (j = 0; j < nleaves; lives_free(res[j++]));
419  lives_free(res);
420  }
421  return val;
422  }
423  weed_set_int64_value(*tuner, "tottime", tottime);
424  }
425  return val;
426 }
427 
428 
430 #define OIL_MEMCPY_MAX_BYTES 12288 // this can be tuned to provide optimal performance
431 
432 #ifdef ENABLE_ORC
433 livespointer lives_orc_memcpy(livespointer dest, livesconstpointer src, size_t n) {
434  static size_t maxbytes = OIL_MEMCPY_MAX_BYTES;
435  static weed_plant_t *tuner = NULL;
436  static boolean tuned = FALSE;
437  static pthread_mutex_t tuner_mutex = PTHREAD_MUTEX_INITIALIZER;
438  boolean haslock = FALSE;
439  if (n == 0) return dest;
440  if (n < 32) return memcpy(dest, src, n);
441 
442  if (!mainw->multitrack && !LIVES_IS_PLAYING) {
443  if (!tuned && !tuner) tuner = lives_plant_new_with_index(LIVES_WEED_SUBTYPE_TUNABLE, 2);
444  if (tuner) {
445  if (!pthread_mutex_trylock(&tuner_mutex)) {
446  haslock = TRUE;
447  }
448  }
449  }
450 
451  if (maxbytes > 0 ? n <= maxbytes : n >= -maxbytes) {
464  if (haslock) autotune_u64(tuner, -1024 * 1024, 1024 * 1024, 32, 1. / (double)n);
465  orc_memcpy((uint8_t *)dest, (const uint8_t *)src, n);
466 
467  if (haslock) {
468  maxbytes = autotune_u64_end(&tuner, maxbytes);
469  if (!tuner) tuned = TRUE;
470  pthread_mutex_unlock(&tuner_mutex);
471  }
472  return dest;
473  }
474  if (haslock) autotune_u64(tuner, -1024 * 1024, 1024 * 1024, 128, -1. / (double)n);
475  memcpy(dest, src, n);
476  if (haslock) {
477  maxbytes = autotune_u64_end(&tuner, maxbytes);
478  if (!tuner) tuned = TRUE;
479  pthread_mutex_unlock(&tuner_mutex);
480  }
481  return dest;
482 }
483 #endif
484 
485 
486 #ifdef ENABLE_OIL
487 livespointer lives_oil_memcpy(livespointer dest, livesconstpointer src, size_t n) {
488  static size_t maxbytes = OIL_MEMCPY_MAX_BYTES;
489  static weed_plant_t *tuner = NULL;
490  static boolean tuned = FALSE;
491  static pthread_mutex_t tuner_mutex = PTHREAD_MUTEX_INITIALIZER;
492  boolean haslock = FALSE;
493  if (n == 0) return dest;
494  if (n < 32) return memcpy(dest, src, n);
495 
496  if (!mainw->multitrack && !LIVES_IS_PLAYING) {
497  if (!tuned && !tuner) tuner = lives_plant_new_with_index(LIVES_WEED_SUBTYPE_TUNABLE, 2);
498  if (tuner) {
499  if (!pthread_mutex_trylock(&tuner_mutex)) {
500  haslock = TRUE;
501  }
502  }
503  }
504 
505  if (maxbytes > 0 ? n <= maxbytes : n >= -maxbytes) {
506  if (haslock) autotune_u64(tuner, -1024 * 1024, 1024 * 1024, 32, 1. / (double)n);
507  oil_memcpy((uint8_t *)dest, (const uint8_t *)src, n);
508 
509  if (haslock) {
510  maxbytes = autotune_u64_end(&tuner, maxbytes);
511  if (!tuner) tuned = TRUE;
512  pthread_mutex_unlock(&tuner_mutex);
513  }
514  return dest;
515  }
516  if (haslock) autotune_u64(tuner, -1024 * 1024, 1024 * 1024, 128, -1. / (double)n);
517  memcpy(dest, src, n);
518  if (haslock) {
519  maxbytes = autotune_u64_end(&tuner, maxbytes);
520  if (!tuner) tuned = TRUE;
521  pthread_mutex_unlock(&tuner_mutex);
522  }
523  return dest;
524 }
525 #endif
526 
527 #define _cpy_if_nonnull(d, s, size) (d ? lives_memcpy(d, s, size) : d)
528 
529 // functions with fixed pointers that we can pass to plugins ///
530 void *_ext_malloc(size_t n) {
531 #ifdef USE_RPMALLOC
532  return rpmalloc(n);
533 #else
534  return (n == 0 ? NULL : lives_malloc(n));
535 #endif
536 }
537 
538 
539 void *_ext_malloc_and_copy(size_t bsize, const void *block) {
540  if (!block || bsize == 0) return NULL;
541 #ifdef lives_malloc_and_copy
542  return lives_malloc_and_copy(bsize, block);
543 #endif
544  return (_cpy_if_nonnull(malloc(bsize), block, bsize));
545 }
546 
547 void _ext_unmalloc_and_copy(size_t bsize, void *p) {
548  if (!p || bsize == 0) return;
549 #ifdef lives_unmalloc_and_copy
550  lives_unmalloc_and_copy(bsize, p);
551 #else
552  _ext_free(p);
553 #endif
554 }
555 
556 void _ext_free(void *p) {
557 #ifdef USE_RPMALLOC
558  rpfree(p);
559 #else
560  if (p) lives_free(p);
561 #endif
562 }
563 
564 
565 void *_ext_free_and_return(void *p) {_ext_free(p); return NULL;}
566 
567 void *_ext_memcpy(void *dest, const void *src, size_t n) {return lives_memcpy(dest, src, n);}
568 
569 int _ext_memcmp(const void *s1, const void *s2, size_t n) {return lives_memcmp(s1, s2, n);}
570 
571 void *_ext_memset(void *p, int i, size_t n) {return lives_memset(p, i, n);}
572 
573 void *_ext_memmove(void *dest, const void *src, size_t n) {return lives_memmove(dest, src, n);}
574 
575 void *_ext_realloc(void *p, size_t n) {
576 #ifdef USE_RPMALLOC
577  return rprealloc(p, n);
578 #else
579  return lives_realloc(p, n);
580 }
581 #endif
582 }
583 
584 void *_ext_calloc(size_t nmemb, size_t msize) {
585 #ifdef USE_RPMALLOC
586  return quick_calloc(nmemb, msize);
587 #else
588  return lives_calloc(nmemb, msize);
589 }
590 #endif
591 }
592 
593 LIVES_GLOBAL_INLINE void *lives_free_and_return(void *p) {lives_free(p); return NULL;}
594 
595 
596 LIVES_GLOBAL_INLINE size_t get_max_align(size_t req_size, size_t align_max) {
597  size_t align = 1;
598  while (align < align_max && !(req_size & align)) align *= 2;
599  return align;
600 }
601 
602 
603 LIVES_GLOBAL_INLINE void *lives_calloc_safety(size_t nmemb, size_t xsize) {
604  void *p;
605  size_t totsize = nmemb * xsize;
606  if (!totsize) return NULL;
607  if (xsize < DEF_ALIGN) {
608  xsize = DEF_ALIGN;
609  nmemb = (totsize / xsize) + 1;
610  }
611  p = __builtin_assume_aligned(lives_calloc(nmemb + (EXTRA_BYTES / xsize), xsize), DEF_ALIGN);
612  return p;
613 }
614 
615 LIVES_GLOBAL_INLINE void *lives_recalloc(void *p, size_t nmemb, size_t omemb, size_t xsize) {
618  void *np = __builtin_assume_aligned(lives_calloc_safety(nmemb, xsize), DEF_ALIGN);
619  void *op = __builtin_assume_aligned(p, DEF_ALIGN);
620  if (omemb > nmemb) omemb = nmemb;
621  lives_memcpy(np, op, omemb * xsize);
622  lives_free(p);
623  return np;
624 }
625 
626 void quick_free(void *p) {rpfree(p);}
627 
628 void *quick_calloc(size_t n, size_t s) {return rpaligned_calloc(DEF_ALIGN, n, s);}
629 
630 boolean init_memfuncs(void) {
631 #ifdef USE_RPMALLOC
633 #endif
634  return TRUE;
635 }
636 
637 
638 boolean init_thread_memfuncs(void) {
639 #ifdef USE_RPMALLOC
641 #endif
642  return TRUE;
643 }
644 
645 
646 char *get_md5sum(const char *filename) {
648  char **array;
649  char *md5;
650  char *com = lives_strdup_printf("%s \"%s\"", EXEC_MD5SUM, filename);
652  lives_free(com);
653  if (THREADVAR(com_failed)) {
654  THREADVAR(com_failed) = FALSE;
655  return NULL;
656  }
657  array = lives_strsplit(mainw->msg, " ", 2);
658  md5 = lives_strdup(array[0]);
659  lives_strfreev(array);
660  return md5;
661 }
662 
663 
664 char *lives_format_storage_space_string(uint64_t space) {
665  char *fmt;
666 
667  if (space >= lives_10pow(18)) {
668  // TRANSLATORS: Exabytes
669  fmt = lives_strdup_printf(_("%.2f EB"), (double)space / (double)lives_10pow(18));
670  } else if (space >= lives_10pow(15)) {
671  // TRANSLATORS: Petabytes
672  fmt = lives_strdup_printf(_("%.2f PB"), (double)space / (double)lives_10pow(15));
673  } else if (space >= lives_10pow(12)) {
674  // TRANSLATORS: Terabytes
675  fmt = lives_strdup_printf(_("%.2f TB"), (double)space / (double)lives_10pow(12));
676  } else if (space >= lives_10pow(9)) {
677  // TRANSLATORS: Gigabytes
678  fmt = lives_strdup_printf(_("%.2f GB"), (double)space / (double)lives_10pow(9));
679  } else if (space >= lives_10pow(6)) {
680  // TRANSLATORS: Megabytes
681  fmt = lives_strdup_printf(_("%.2f MB"), (double)space / (double)lives_10pow(6));
682  } else if (space >= 1024) {
683  // TRANSLATORS: Kilobytes (1024 bytes)
684  fmt = lives_strdup_printf(_("%.2f KiB"), (double)space / 1024.);
685  } else {
686  fmt = lives_strdup_printf(_("%d bytes"), space);
687  }
688 
689  return fmt;
690 }
691 
692 
693 lives_storage_status_t get_storage_status(const char *dir, uint64_t warn_level, int64_t *dsval, int64_t ds_resvd) {
694  // WARNING: this will actually create the directory (since we dont know if its parents are needed)
695  // call with dsval set to ds_used to check for OVER_QUOTA
696  // dsval is overwritten and set to ds_free
697  int64_t ds;
699  if (dsval && prefs->disk_quota > 0 && *dsval > (int64_t)((double)prefs->disk_quota * prefs->quota_limit / 100.))
701  if (!is_writeable_dir(dir)) return status;
702  ds = (int64_t)get_ds_free(dir);
703  ds -= ds_resvd;
704  if (dsval) *dsval = ds;
705  if (ds <= 0) return LIVES_STORAGE_STATUS_OVERFLOW;
706  if (ds < prefs->ds_crit_level) return LIVES_STORAGE_STATUS_CRITICAL;
707  if (status != LIVES_STORAGE_STATUS_UNKNOWN) return status;
708  if (ds < warn_level) return LIVES_STORAGE_STATUS_WARNING;
710 }
711 
712 static lives_proc_thread_t running = NULL;
713 static char *running_for = NULL;
714 
715 boolean disk_monitor_running(const char *dir) {return (running != NULL && (!dir || !lives_strcmp(dir, running_for)));}
716 
720  dir);
721  mainw->dsu_valid = TRUE;
722  running_for = lives_strdup(dir);
723  return running;
724 }
725 
726 int64_t disk_monitor_check_result(const char *dir) {
727  // caller MUST check if mainw->ds_valid is TRUE, or recheck the results
728  int64_t bytes;
730  if (!lives_strcmp(dir, running_for)) {
731  if (!lives_proc_thread_check(running)) {
732  return -1;
733  }
734  bytes = lives_proc_thread_join_int64(running);
735  lives_proc_thread_free(running);
736  running = NULL;
737  } else bytes = (int64_t)get_dir_size(dir);
738  return bytes;
739 }
740 
741 
742 LIVES_GLOBAL_INLINE int64_t disk_monitor_wait_result(const char *dir, ticks_t timeout) {
743  // caller MUST check if mainw->ds_valid is TRUE, or recheck the results
744  lives_alarm_t alarm_handle = LIVES_NO_ALARM;
745  int64_t dsval;
746 
747  if (*running_for && !lives_strcmp(dir, running_for)) {
748  if (timeout) return -1;
749  return get_dir_size(dir);
750  }
751 
752  if (timeout < 0) timeout = LIVES_LONGEST_TIMEOUT;
753  if (timeout > 0) alarm_handle = lives_alarm_set(timeout);
754 
755  while ((dsval = disk_monitor_check_result(dir)) < 0
756  && (alarm_handle == LIVES_NO_ALARM || ((timeout = lives_alarm_check(alarm_handle)) > 0))) {
757  lives_nanosleep(1000);
758  }
759  if (alarm_handle != LIVES_NO_ALARM) {
760  lives_alarm_clear(alarm_handle);
761  if (!timeout) {
763  return -1;
764  }
765  }
766  return dsval;
767 }
768 
770  if (!disk_monitor_running(NULL)) return;
772  running = NULL;
773 }
774 
775 
776 uint64_t get_ds_free(const char *dir) {
777  // get free space in bytes for volume containing directory dir
778  // return 0 if we cannot create/write to dir
779 
780  // caller should test with is_writeable_dir() first before calling this
781  // since 0 is a valid return value
782 
783  // dir should be in locale encoding
784 
785  // WARNING: this may temporarily create the directory (since we dont know if its parents are needed)
786 
787  struct statvfs sbuf;
788 
789  uint64_t bytes = 0;
790  boolean must_delete = FALSE;
791 
792  if (!lives_file_test(dir, LIVES_FILE_TEST_IS_DIR)) must_delete = TRUE;
793  if (!is_writeable_dir(dir)) goto getfserr;
794 
795  // use statvfs to get fs details
796  if (statvfs(dir, &sbuf) == -1) goto getfserr;
797  if (sbuf.f_flag & ST_RDONLY) goto getfserr;
798 
799  // result is block size * blocks available
800  bytes = sbuf.f_bsize * sbuf.f_bavail;
801  if (!strcmp(dir, prefs->workdir)) {
802  capable->ds_free = bytes;
803  capable->ds_tot = sbuf.f_bsize * sbuf.f_blocks;
804  }
805 
806 getfserr:
807  if (must_delete) lives_rmdir(dir, FALSE);
808 
809  return bytes;
810 }
811 
812 
814  ticks_t ret = -1;
815 #if _POSIX_TIMERS
816  struct timespec ts;
817  clock_gettime(CLOCK_MONOTONIC, &ts);
818  ret = ((ts.tv_sec * ONE_BILLION + ts.tv_nsec) - (origsecs * ONE_BILLION + orignsecs)) / TICKS_TO_NANOSEC;
819 #else
820 #ifdef USE_MONOTONIC_TIME
821  ret = (lives_get_monotonic_time() - orignsecs) / 10;
822 #else
823  struct timeval tv;
824  gettimeofday(&tv, NULL);
825  ret = ((tv.tv_sec * ONE_MILLLION + tv.tv_usec) - (origsecs * ONE_MILLION + orignsecs / 1000)) * USEC_TO_TICKS;
826 #endif
827 #endif
828  mainw->wall_ticks = ret;
829  if (ret >= 0)
830  mainw->wall_ticks += (origsecs * ONE_BILLION + orignsecs) / TICKS_TO_NANOSEC;
831  return ret;
832 }
833 
834 
836  // return current (wallclock) time in ticks (units of 10 nanoseconds)
837  return lives_get_relative_ticks(0, 0);
838 }
839 
840 
841 #define SECS_IN_DAY 86400
842 char *lives_datetime_rel(const char *datetime) {
844  char *dtxt;
845  char *today = NULL, *yesterday = NULL;
846  struct timeval otv;
847  gettimeofday(&otv, NULL);
848  today = lives_datetime(otv.tv_sec, TRUE);
849  yesterday = lives_datetime(otv.tv_sec - SECS_IN_DAY, TRUE);
850  if (!lives_strncmp(datetime, today, 10)) dtxt = lives_strdup_printf(_("Today %s"), datetime + 11);
851  else if (!lives_strncmp(datetime, yesterday, 10))
852  dtxt = lives_strdup_printf(_("Yesterday %s"), datetime + 11);
853  else dtxt = (char *)datetime;
854  if (today) lives_free(today);
855  if (yesterday) lives_free(yesterday);
856  return dtxt;
857 }
858 
859 
860 char *lives_datetime(uint64_t secs, boolean use_local) {
861  char buf[128];
862  char *datetime = NULL;
863  struct tm *gm = use_local ? localtime((time_t *)&secs) : gmtime((time_t *)&secs);
864  ssize_t written;
865 
866  if (gm) {
867  written = (ssize_t)strftime(buf, 128, "%Y-%m-%d %H:%M:%S", gm);
868  if ((written > 0) && ((size_t)written < 128)) {
869  datetime = lives_strdup(buf);
870  }
871  }
872  return datetime;
873 }
874 
875 
876 boolean check_dev_busy(char *devstr) {
877  int ret;
878 #ifdef IS_SOLARIS
879  struct flock lock;
880  lock.l_start = 0;
881  lock.l_whence = SEEK_SET;
882  lock.l_len = 0;
883  lock.l_type = F_WRLCK;
884 #endif
885  int fd = open(devstr, O_RDONLY | O_NONBLOCK);
886  if (fd == -1) return FALSE;
887 #ifdef IS_SOLARIS
888  ret = fcntl(fd, F_SETLK, &lock);
889 #else
890  ret = flock(fd, LOCK_EX | LOCK_NB);
891 #endif
892  close(fd);
893  if (ret == -1) return FALSE;
894  return TRUE;
895 }
896 
897 
898 boolean compress_files_in_dir(const char *dir, int method, void *data) {
902 
905  char buff[65536];
906  char *com, *cwd;
907  boolean retval = FALSE;
908 
910  if (lives_file_test(dir, LIVES_FILE_TEST_IS_DIR)) {
911  boolean needs_norem = FALSE;
912  char *norem = lives_build_filename(dir, LIVES_FILENAME_NOREMOVE, NULL);
913  if (lives_file_test(norem, LIVES_FILE_TEST_EXISTS)) {
914  needs_norem = TRUE;
915  lives_rm(norem);
916  }
917  cwd = lives_get_current_dir();
918  THREADVAR(chdir_failed) = FALSE;
919  lives_chdir(dir, TRUE);
920  if (THREADVAR(chdir_failed)) {
921  THREADVAR(chdir_failed) = FALSE;
922  lives_chdir(cwd, TRUE);
923  lives_free(cwd);
924  lives_free(norem);
925  return FALSE;
926  }
927  com = lives_strdup_printf("%s * 2>&1", EXEC_GZIP);
928  lives_popen(com, TRUE, buff, 65536);
929  lives_free(com);
930  if (THREADVAR(com_failed)) THREADVAR(com_failed) = FALSE;
931  else retval = TRUE;
932  lives_chdir(cwd, TRUE);
933  lives_free(cwd);
934  if (needs_norem) {
935  lives_touch(norem);
936  lives_free(norem);
937  }
938  }
939  return retval;
940 }
941 
942 
943 off_t get_file_size(int fd) {
944  // get the size of file fd
945  struct stat filestat;
946  off_t fsize;
947  lives_file_buffer_t *fbuff;
948  fstat(fd, &filestat);
949  fsize = filestat.st_size;
950  //g_printerr("fssize for %d is %ld\n", fd, fsize);
951  if ((fbuff = find_in_file_buffers(fd)) != NULL) {
952  if (!fbuff->read) {
954  off_t f2size;
955  if ((f2size = (off_t)(fbuff->offset + fbuff->bytes)) > fsize) return f2size;
956  }
957  }
958  return fsize;
959 }
960 
961 
962 off_t sget_file_size(const char *name) {
963  off_t res;
964  struct stat xstat;
965  if (!name) return 0;
966  res = stat(name, &xstat);
967  if (res < 0) return res;
968  return xstat.st_size;
969 }
970 
971 
972 void reget_afilesize(int fileno) {
973  // re-get the audio file size
974  lives_clip_t *sfile = mainw->files[fileno];
975  boolean bad_header = FALSE;
976 
977  if (mainw->multitrack) return; // otherwise achans gets set to 0...
978 
979  sfile->afilesize = reget_afilesize_inner(fileno);
980 
981  if (sfile->afilesize == 0l) {
982  if (!sfile->opening && fileno != mainw->ascrap_file && fileno != mainw->scrap_file) {
983  if (sfile->arate != 0 || sfile->achans != 0 || sfile->asampsize != 0 || sfile->arps != 0) {
984  sfile->arate = sfile->achans = sfile->asampsize = sfile->arps = 0;
985  if (!save_clip_value(fileno, CLIP_DETAILS_ACHANS, &sfile->achans)) bad_header = TRUE;
986  if (!save_clip_value(fileno, CLIP_DETAILS_ARATE, &sfile->arps)) bad_header = TRUE;
987  if (!save_clip_value(fileno, CLIP_DETAILS_PB_ARATE, &sfile->arate)) bad_header = TRUE;
988  if (!save_clip_value(fileno, CLIP_DETAILS_ASAMPS, &sfile->asampsize)) bad_header = TRUE;
989  if (bad_header) do_header_write_error(fileno);
990  }
991  }
992  }
993 
994  if (mainw->is_ready && fileno > 0 && fileno == mainw->current_file) {
995  // force a redraw
997  }
998 }
999 
1000 
1001 off_t reget_afilesize_inner(int fileno) {
1002  // safe version that just returns the audio file size
1003  off_t filesize;
1004  char *afile = lives_get_audio_file_name(fileno);
1005  lives_sync(1);
1006  filesize = sget_file_size(afile);
1007  lives_free(afile);
1008  if (filesize < 0) filesize = 0;
1009  return filesize;
1010 }
1011 
1012 
1013 boolean is_empty_dir(const char *dirname) {
1014  DIR *tldir;
1015  struct dirent *tdirent;
1016  boolean empty = TRUE;
1017  if (!dirname) return TRUE;
1018  tldir = opendir(dirname);
1019  if (!tldir) return FALSE;
1020  while (empty && (tdirent = readdir(tldir))) {
1021  if (tdirent->d_name[0] == '.'
1022  && (!tdirent->d_name[1] || tdirent->d_name[1] == '.')) continue;
1023  empty = FALSE;
1024  }
1025  closedir(tldir);
1026  return empty;
1027 }
1028 
1029 
1030 char *get_mountpoint_for(const char *dir) {
1031  char *mp = NULL, *tmp, *com, *res;
1032  size_t lmatch = 0, slen;
1033  int j;
1034 
1035  if (!dir) return NULL;
1036  slen = lives_strlen(dir);
1037 
1038  com = lives_strdup("df -P");
1039  if ((res = mini_popen(com))) {
1040  int lcount = get_token_count(res, '\n');
1041  char **array0 = lives_strsplit(res, "\n", lcount);
1042  for (int l = 0; l < lcount; l++) {
1043  int pccount = get_token_count(array0[l], ' ');
1044  char **array1 = lives_strsplit(array0[l], " ", pccount);
1045  lives_chomp(array1[pccount - 1]);
1046  for (j = 0; array1[pccount - 1][j] && j < slen; j++) if (array1[pccount - 1][j] != dir[j]) break;
1047  if (j > lmatch && !array1[pccount - 1][j]) {
1048  lmatch = j;
1049  if (mp) lives_free(mp);
1050  tmp = lives_strdup(array1[0]);
1051  mp = lives_filename_to_utf8(tmp, -1, NULL, NULL, NULL);
1052  lives_free(tmp);
1053  }
1054  lives_strfreev(array1);
1055  }
1056  lives_strfreev(array0);
1057  lives_free(res);
1058  }
1059  return mp;
1060 }
1061 
1062 
1063 #ifdef IS_FREEBSD
1064 #define DU_BLOCKSIZE 1024
1065 #else
1066 #define DU_BLOCKSIZE 1
1067 #endif
1068 
1069 off_t get_dir_size(const char *dirname) {
1070  off_t dirsize = -1;
1071  if (!dirname || !*dirname || !lives_file_test(dirname, LIVES_FILE_TEST_IS_DIR)) return -1;
1073  char buff[PATH_MAX * 2];
1074  char *com = lives_strdup_printf("%s -sB %d \"%s\"", EXEC_DU, DU_BLOCKSIZE, dirname);
1075  lives_popen(com, TRUE, buff, PATH_MAX * 2);
1076  lives_free(com);
1077  if (THREADVAR(com_failed)) THREADVAR(com_failed) = FALSE;
1078  else dirsize = atol(buff) / DU_BLOCKSIZE;
1079  }
1080  return dirsize;
1081 }
1082 
1083 
1084 void free_fdets_list(LiVESList **listp) {
1085  LiVESList *list = *listp;
1086  lives_file_dets_t *filedets;
1087  for (; list && list->data; list = list->next) {
1088  filedets = (lives_file_dets_t *)list->data;
1089  lives_struct_free(filedets->lsd);
1090  list->data = NULL;
1091  }
1092  if (*listp) {
1093  lives_list_free(*listp);
1094  *listp = NULL;
1095  }
1096 }
1097 
1098 
1099 int stat_to_file_dets(const char *fname, lives_file_dets_t *fdets) {
1100  struct stat filestat;
1101  int ret = stat(fname, &filestat);
1102  if (ret) {
1103  if (prefs->show_dev_opts) {
1104  char *msg = lives_strdup_printf("\nstat failed for file %s\n", fname);
1105  perror(msg);
1106  lives_free(msg);
1107  }
1108  fdets->size = -2;
1109  fdets->type = LIVES_FILE_TYPE_UNKNOWN;
1110  return ret;
1111  }
1112  fdets->type = (uint64_t)((filestat.st_mode & S_IFMT) >> 12);
1113  fdets->size = filestat.st_size;
1114  fdets->mode = (uint64_t)(filestat.st_mode & 0x0FFF);
1115  fdets->uid = filestat.st_uid;
1116  fdets->gid = filestat.st_gid;
1117  fdets->blk_size = (uint64_t)filestat.st_blksize;
1118  fdets->atime_sec = filestat.st_atim.tv_sec;
1119  fdets->atime_nsec = filestat.st_atim.tv_nsec;
1120  fdets->mtime_sec = filestat.st_mtim.tv_sec;
1121  fdets->mtime_nsec = filestat.st_mtim.tv_nsec;
1122  fdets->ctime_sec = filestat.st_ctim.tv_sec;
1123  fdets->ctime_nsec = filestat.st_ctim.tv_nsec;
1124  return ret;
1125 }
1126 
1127 
1128 static char *file_to_file_details(const char *filename, lives_file_dets_t *fdets, lives_proc_thread_t tinfo, uint64_t extra) {
1129  char *tmp, *tmp2;
1130  char *extra_details = lives_strdup("");
1131 
1132  if (!stat_to_file_dets(filename, fdets)) {
1133  // if stat fails, we have set set size to -2, type to LIVES_FILE_TYPE_UNKNOWN
1134  // and here we set extra_details to ""
1135  if (tinfo && lives_proc_thread_cancelled(tinfo)) {
1136  lives_free(extra_details);
1137  return NULL;
1138  }
1139  if (LIVES_FILE_IS_DIRECTORY(fdets->type)) {
1140  boolean emptyd = FALSE;
1141  if (extra & EXTRA_DETAILS_EMPTY_DIRS) {
1142  if ((emptyd = is_empty_dir(filename))) {
1143  fdets->type |= LIVES_FILE_TYPE_FLAG_EMPTY;
1144  tmp2 = lives_strdup_printf("%s%s%s", extra_details, *extra_details ? ", " : "",
1145  (tmp = _("(empty)")));
1146  lives_free(tmp);
1147  lives_free(extra_details);
1148  extra_details = tmp2;
1149  }
1150  if (tinfo && lives_proc_thread_cancelled(tinfo)) {
1151  lives_free(extra_details);
1152  return NULL;
1153  }
1154  }
1155  if ((extra & EXTRA_DETAILS_DIRSIZE) &&
1157  && !emptyd && fdets->type == LIVES_FILE_TYPE_DIRECTORY) {
1158  fdets->size = get_dir_size(filename);
1159  }
1160 
1161  if (!emptyd && (extra & EXTRA_DETAILS_CLIPHDR)) {
1162  int clipno;
1163 
1164  clipno = create_nullvideo_clip("tmp");
1165 
1166  if (clipno && IS_VALID_CLIP(clipno)) {
1167  if (read_headers(clipno, filename, NULL)) {
1168  lives_clip_t *sfile = mainw->files[clipno];
1169  char *name = lives_strdup(sfile->name);
1170  extra_details =
1171  lives_strdup_printf("%s%s%s", extra_details, *extra_details ? ", " : "",
1172  (tmp = lives_strdup_printf
1173  (_("Source: %s, frames: %d, size: %d X %d, fps: %.3f"),
1174  name, sfile->frames, sfile->hsize,
1175  sfile->vsize, sfile->fps)));
1176  lives_free(tmp);
1177  lives_free(name);
1178  lives_freep((void **)&mainw->files[clipno]);
1179  if (mainw->first_free_file == ALL_USED || mainw->first_free_file > clipno)
1180  mainw->first_free_file = clipno;
1181  }
1183  // *INDENT-OFF*
1184  }}}
1185  if (extra & EXTRA_DETAILS_MD5SUM) {
1186  fdets->md5sum = get_md5sum(filename);
1187  }
1188  if (extra & EXTRA_DETAILS_SYMLINK) {
1189  if (lives_file_test(filename, LIVES_FILE_TEST_IS_SYMLINK))
1191  }
1192  if (extra & EXTRA_DETAILS_EXECUTABLE) {
1193  if (lives_file_test(filename, LIVES_FILE_TEST_IS_EXECUTABLE))
1195  }
1197  /* if (extra & EXTRA_DETAILS_WRITEABLE) { */
1198  /* if (LIVES_FILE_TEST_IS_EXECUTABLE(filename)) fdets->type |= LIVES_FILE_TYPE_FLAG_EXECUTABLE; */
1199  /* } */
1200  /* if (extra & EXTRA_DETAILS_ACCESSIBLE) { */
1201  /* if (LIVES_FILE_TEST_IS_EXECUTABLE(filename)) fdets->type |= LIVES_FILE_TYPE_FLAG_EXECUTABLE; */
1202  /* } */
1203  }
1204  // *INDENT-ON*
1205  else {
1207  if (extra & EXTRA_DETAILS_CHECK_MISSING) {
1208  if (!lives_file_test(filename, LIVES_FILE_TEST_EXISTS)) {
1210  tmp2 = lives_strdup_printf("%s%s%s", extra_details, *extra_details ? ", " : "",
1211  (tmp = _("(ABSENT)")));
1212  lives_free(tmp);
1213  lives_free(extra_details);
1214  extra_details = tmp2;
1215  }
1216  }
1217  }
1218  return extra_details;
1219 }
1220 
1221 
1227 void *_item_to_file_details(LiVESList **listp, const char *item,
1228  const char *orig_loc, uint64_t extra, int type) {
1229  // type 0 = dir
1230  // type 1 = ordfile
1231  lives_file_dets_t *fdets;
1232  lives_proc_thread_t tinfo = NULL;
1233  LiVESList *list;
1234  char *extra_details;
1235  const char *dir = NULL;
1236  char *subdirname;
1237  boolean empty = TRUE;
1238 
1239  tinfo = THREADVAR(tinfo);
1240  if (tinfo) lives_proc_thread_set_cancellable(tinfo);
1241 
1242  switch (type) {
1243  case 0: {
1244  DIR *tldir;
1245  struct dirent *tdirent;
1246  // dir
1247  dir = item;
1248  if (!dir) return NULL;
1249  tldir = opendir(dir);
1250  if (!tldir) {
1251  *listp = lives_list_append(*listp, NULL);
1252  return NULL;
1253  }
1254 
1255  while (1) {
1256  tdirent = readdir(tldir);
1257  if (lives_proc_thread_cancelled(tinfo) || !tdirent) {
1258  closedir(tldir);
1259  if (lives_proc_thread_cancelled(tinfo)) return NULL;
1260  break;
1261  }
1262  if (tdirent->d_name[0] == '.'
1263  && (!tdirent->d_name[1] || tdirent->d_name[1] == '.')) continue;
1265  fdets->name = lives_strdup(tdirent->d_name);
1266  //g_print("GOT %s\n", fdets->name);
1267  fdets->size = -1;
1268  *listp = lives_list_append(*listp, fdets);
1269  if (lives_proc_thread_cancelled(tinfo)) {
1270  closedir(tldir);
1271  return NULL;
1272  }
1273  }
1274  break;
1275  }
1276  case 1: {
1277  FILE *orderfile;
1278  char buff[PATH_MAX];
1279  const char *ofname = item;
1280 
1281  if (!(orderfile = fopen(ofname, "r"))) return NULL;
1282  while (1) {
1283  if (lives_proc_thread_cancelled(tinfo) || !orderfile) {
1284  if (orderfile) {
1285  fclose(orderfile);
1286  }
1287  return NULL;
1288  }
1289  if (!lives_fgets(buff, PATH_MAX, orderfile)) {
1290  fclose(orderfile);
1291  break;
1292  }
1293  lives_chomp(buff);
1294 
1296 
1297  fdets->name = lives_strdup(buff);
1298  fdets->size = -1;
1299  *listp = lives_list_append(*listp, fdets);
1300  if (lives_proc_thread_cancelled(tinfo)) {
1301  fclose(orderfile);
1302  return NULL;
1303  }
1304  }
1305  break;
1306  }
1307  default: return NULL;
1308  }
1309 
1310  if (*listp) empty = FALSE;
1311  *listp = lives_list_append(*listp, NULL);
1312 
1313  if (empty || lives_proc_thread_cancelled(tinfo)) return NULL;
1314 
1315  // listing done, now get details for each entry
1316  list = *listp;
1317  while (list && list->data) {
1318  if (lives_proc_thread_cancelled(tinfo)) return NULL;
1319 
1320  extra_details = lives_strdup("");
1321  fdets = (lives_file_dets_t *)list->data;
1322 
1323  if (orig_loc && *orig_loc) subdirname = lives_build_filename(orig_loc, fdets->name, NULL);
1324  else subdirname = lives_build_path(dir, fdets->name, NULL);
1325 
1326  // need to call even with no extra, because it gets size / type tc.
1327  if (!(extra_details = file_to_file_details(subdirname, fdets, tinfo, extra))) {
1328  lives_free(subdirname);
1329  lives_free(extra_details);
1330  return NULL;
1331  }
1332 
1333  lives_free(subdirname);
1334 
1335  if (tinfo && lives_proc_thread_cancelled(tinfo)) {
1336  lives_free(extra_details);
1337  return NULL;
1338  }
1339  fdets->extra_details = lives_strdup(extra_details);
1340  lives_free(extra_details);
1341  list = list->next;
1342  }
1343 
1344  return NULL;
1345 }
1346 
1353 lives_proc_thread_t dir_to_file_details(LiVESList **listp, const char *dir,
1354  const char *orig_loc, uint64_t extra) {
1356  listp, dir, orig_loc, extra, 0);
1357 }
1358 
1359 
1360 lives_proc_thread_t ordfile_to_file_details(LiVESList **listp, const char *ofname,
1361  const char *orig_loc, uint64_t extra) {
1363  listp, ofname, orig_loc, extra, 1);
1364 }
1365 
1366 
1367 #ifdef PRODUCE_LOG
1368 // disabled by default
1369 void lives_log(const char *what) {
1370  char *lives_log_file = lives_build_filename(prefs->workdir, LIVES_LOG_FILE, NULL);
1371  if (mainw->log_fd < 0) mainw->log_fd = open(lives_log_file, O_WRONLY | O_CREAT, DEF_FILE_PERMS);
1372  if (mainw->log_fd != -1) {
1373  char *msg = lives_strdup("%s|%d|", what, mainw->current_file);
1374  write(mainw->log_fd, msg, strlen(msg));
1375  lives_free(msg);
1376  }
1377  lives_free(lives_log_file);
1378 }
1379 #endif
1380 
1381 
1383  int i, fcount;
1384  char *fname_next;
1385  boolean maybeok = FALSE;
1386 
1387  fcount = get_frame_count(mainw->current_file, 1);
1388 
1389  for (i = 1; i <= fcount; i++) {
1390  fname_next = make_image_file_name(cfile, i, get_image_ext_for_type(cfile->img_type));
1391  if (sget_file_size(fname_next) > 0) {
1392  lives_free(fname_next);
1393  maybeok = TRUE;
1394  break;
1395  }
1396  lives_free(fname_next);
1397  }
1398 
1399  if (!maybeok) {
1402  _("Your version of mplayer/ffmpeg may be broken !\nSee http://bugzilla.mplayerhq.hu/show_bug.cgi?id=2071\n\n"
1403  "You can work around this temporarily by switching to jpeg output in Preferences/Decoding.\n\n"
1404  "Try running Help/Troubleshoot for more information."));
1406  return CANCEL_ERROR;
1407  }
1408  return CANCEL_NONE;
1409 }
1410 
1411 
1412 LIVES_GLOBAL_INLINE char *lives_concat_sep(char *st, const char *sep, char *x) {
1414  // uses realloc / memcpy, frees x
1415  char *tmp;
1416  if (st) {
1417  size_t s1 = lives_strlen(st), s2 = lives_strlen(x), s3 = lives_strlen(sep);
1418  tmp = (char *)lives_realloc(st, ++s2 + s1 + s3);
1419  lives_memcpy(tmp + s1, sep, s3);
1420  lives_memcpy(tmp + s1 + s3, x, s2);
1421  } else tmp = lives_strdup(x);
1422  lives_free(x);
1423  return tmp;
1424 }
1425 
1426 LIVES_GLOBAL_INLINE char *lives_concat(char *st, char *x) {
1428  // uses realloc / memcpy, frees x
1429  size_t s1 = lives_strlen(st), s2 = lives_strlen(x);
1430  char *tmp = (char *)lives_realloc(st, ++s2 + s1);
1431  lives_memcpy(tmp + s1, x, s2);
1432  lives_free(x);
1433  return tmp;
1434 }
1435 
1436 LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew) {
1438  size_t sz = lives_strlen(string);
1439  int newln = lives_snprintf((char *)(string + sz), len - sz, "%s", xnew);
1440  if (newln > len) newln = len;
1441  return --newln - sz; // returns strlen(xnew)
1442 }
1443 
1444 LIVES_GLOBAL_INLINE const char *lives_strappendf(const char *string, int len, const char *fmt, ...) {
1445  va_list xargs;
1446  char *text;
1447 
1448  va_start(xargs, fmt);
1449  text = lives_strdup_vprintf(fmt, xargs);
1450  va_end(xargs);
1451 
1452  lives_strappend(string, len, text);
1453  lives_free(text);
1454  return string;
1455 }
1456 
1459 #define hasNulByte(x) (((x) - 0x0101010101010101) & ~(x) & 0x8080808080808080)
1460 #define getnulpos(nulmask) ((nulmask & 2155905152ul) ? ((nulmask & 32896ul) ? ((nulmask & 128ul) ? 0 : 1) : \
1461  ((nulmask & 8388608ul) ? 2 : 3)) : (nulmask & 141287244169216ul) ? \
1462  ((nulmask & 549755813888ul) ? 4 : 5) : ((nulmask & 36028797018963968ul) ? 6 : 7))
1463 
1464 #define getnulpos_be(nulmask) ((nulmask & 9259542121117908992ul) ? ((nulmask & 9259400833873739776ul) ? \
1465  ((nulmask & 9223372036854775808ul) ? 0 : 1) : ((nulmask & 140737488355328ul) ? 2 : 3)) \
1466  : (nulmask & 2155872256ul) ? ((nulmask & 2147483648ul) ? 4 : 5) : ((nulmask & 32768ul) ? 6 : 7))
1467 
1468 LIVES_GLOBAL_INLINE size_t lives_strlen(const char *s) {
1469  if (!s) return 0;
1470 #ifndef STD_STRINGFUNCS
1471  else {
1472  uint64_t *pi = (uint64_t *)s, nulmask;
1473  if ((void *)pi == (void *)s) {
1474  while (!(nulmask = hasNulByte(*pi))) pi++;
1475  return (char *)pi - s + (capable->byte_order == LIVES_LITTLE_ENDIAN ? getnulpos(nulmask)
1476  : getnulpos_be(nulmask));
1477  }
1478  }
1479 #endif
1480  return strlen(s);
1481 }
1482 
1483 
1485  if (!s) return NULL;
1486 #ifndef STD_STRINGFUNCS
1487  else {
1488  uint64_t *pi = (uint64_t *)s, nulmask, stlen;
1489  if (!s) return NULL;
1490  if ((void *)pi == (void *)s) {
1491  while (!(nulmask = hasNulByte(*pi))) pi++;
1492  stlen = (char *)pi - s + 1
1493  + (capable->byte_order == LIVES_LITTLE_ENDIAN)
1494  ? getnulpos(nulmask) : getnulpos_be(nulmask);
1495  return lives_memcpy(lives_malloc(stlen), s, stlen);
1496  }
1497  }
1498 #endif
1499  return lives_strdup(s);
1500 }
1501 
1502 
1503 
1504 
1506 LIVES_GLOBAL_INLINE boolean lives_strcmp(const char *st1, const char *st2) {
1507  if (!st1 || !st2) return (st1 != st2);
1508  else {
1509 #ifdef STD_STRINGFUNCS
1510  return strcmp(st1, st2);
1511 #endif
1512  uint64_t d1, d2, *ip1 = (uint64_t *)st1, *ip2 = (uint64_t *)st2;
1513  while (1) {
1514  if ((void *)ip1 == (void *)st1 && (void *)ip2 == (void *)st2) {
1515  while (1) {
1516  if ((d1 = *(ip1++)) == (d2 = *(ip2++))) {if (hasNulByte(d1)) return FALSE;}
1517  else {
1518  if (!hasNulByte(d1 | d2)) return TRUE;
1519  break;
1520  }
1521  }
1522  st1 = (const char *)(--ip1); st2 = (const char *)(--ip2);
1523  }
1524  if (*st1 != *(st2++)) return TRUE;
1525  if (!(*(st1++))) return FALSE;
1526  }
1527  }
1528  return FALSE;
1529 }
1530 
1531 LIVES_GLOBAL_INLINE int lives_strcmp_ordered(const char *st1, const char *st2) {
1532  if (!st1 || !st2) return (st1 != st2);
1533  else {
1534 #ifdef STD_STRINGFUNCS
1535  return strcmp(st1, st2);
1536 #endif
1537  uint64_t d1, d2, *ip1 = (uint64_t *)st1, *ip2 = (uint64_t *)st2;
1538  while (1) {
1539  if ((void *)ip1 == (void *)st1 && (void *)ip2 == (void *)st2) {
1540  do {
1541  d1 = *(ip1++);
1542  d2 = *(ip2++);
1543  } while (d1 == d2 && !hasNulByte(d1));
1544  st1 = (const char *)(--ip1); st2 = (const char *)(--ip2);
1545  }
1546  if (*st1 != *st2 || !(*st1)) break;
1547  st1++; st2++;
1548  }
1549  }
1550  return (*st1 > *st2) - (*st1 < *st2);
1551 }
1552 
1554 LIVES_GLOBAL_INLINE boolean lives_strncmp(const char *st1, const char *st2, size_t len) {
1555  if (!st1 || !st2) return (st1 != st2);
1556  else {
1557 #ifdef STD_STRINGFUNCS
1558  return strncmp(st1, st2, len);
1559 #endif
1560  size_t xlen = len >> 3;
1561  uint64_t d1, d2, *ip1 = (uint64_t *)st1, *ip2 = (uint64_t *)st2;
1562  while (1) {
1563  if (xlen && (void *)ip1 == (void *)st1 && (void *)ip2 == (void *)st2) {
1564  do {
1565  d1 = *(ip1++);
1566  d2 = *(ip2++);
1567  } while (d1 == d2 && !hasNulByte(d1) && --xlen);
1568  if (xlen) {
1569  if (!hasNulByte(d2)) return TRUE;
1570  ip1--;
1571  ip2--;
1572  }
1573  st1 = (void *)ip1; st2 = (void *)ip2;
1574  len -= ((len >> 3) - xlen) << 3;
1575  }
1576  if (!(len--)) return FALSE;
1577  if (*st1 != *(st2++)) return TRUE;
1578  if (!(*(st1++))) return FALSE;
1579  }
1580  }
1581  return (*st1 != *st2);
1582 }
1583 
1584 #define HASHROOT 5381
1585 LIVES_GLOBAL_INLINE uint32_t lives_string_hash(const char *st) {
1586  if (st) for (uint32_t hash = HASHROOT;; hash += (hash << 5)
1587  + * (st++)) if (!(*st)) return hash;
1588  return 0;
1589 }
1590 
1591 
1592 // fast hash from: http://www.azillionmonkeys.com/qed/hash.html
1593 // (c) Paul Hsieh
1594 #define get16bits(d) (*((const uint16_t *) (d)))
1595 
1596 LIVES_GLOBAL_INLINE uint32_t fast_hash(const char *key) {
1598  if (key && *key) {
1599  int len = lives_strlen(key), rem = len & 3;
1600  uint32_t hash = len + HASHROOT, tmp;
1601  len >>= 2;
1602  for (; len > 0; len--) {
1603  hash += get16bits(key);
1604  tmp = (get16bits(key + 2) << 11) ^ hash;
1605  hash = (hash << 16) ^ tmp;
1606  key += 4;
1607  hash += hash >> 11;
1608  }
1609 
1610  /* Handle end cases */
1611  switch (rem) {
1612  case 3: hash += get16bits(key);
1613  hash ^= hash << 16;
1614  hash ^= ((int8_t)key[2]) << 18;
1615  hash += hash >> 11;
1616  break;
1617  case 2: hash += get16bits(key);
1618  hash ^= hash << 11; hash += hash >> 17;
1619  break;
1620  case 1: hash += (int8_t) * key;
1621  hash ^= hash << 10; hash += hash >> 1;
1622  break;
1623  default: break;
1624  }
1625 
1626  /* Force "avalanching" of final 127 bits */
1627  hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4;
1628  hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6;
1629  return hash;
1630  }
1631  return 0;
1632 }
1633 
1634 LIVES_GLOBAL_INLINE char *lives_strstop(char *st, const char term) {
1636  if (st && term) for (int i = 0; st[i]; i++) if (st[i] == term) {st[i] = 0; break;}
1637  return st;
1638 }
1639 
1640 
1643  if (buff) {
1644  size_t xs = lives_strlen(buff);
1645  if (xs && buff[xs - 1] == '\n') buff[--xs] = '\0'; // remove trailing newline
1646  }
1647  return buff;
1648 }
1649 
1650 
1651 LIVES_GLOBAL_INLINE char *lives_strtrim(const char *buff) {
1654  int i, j;
1655  if (!buff) return NULL;
1656  for (i = 0; buff[i] == '\n'; i++);
1657  for (j = i; buff[j]; j++) if (buff[j] == '\n') break;
1658  return lives_strndup(buff + i, j - i);
1659 }
1660 
1661 
1670 typedef weed_plantptr_t lives_proc_thread_t;
1671 
1673 
1674 static lives_proc_thread_t _lives_proc_thread_create(lives_thread_attr_t attr, lives_funcptr_t func,
1675  int return_type, const char *args_fmt, va_list xargs) {
1676  int p = 0;
1677  const char *c;
1678  weed_plant_t *thread_info = lives_plant_new(LIVES_WEED_SUBTYPE_PROC_THREAD);
1679  if (!thread_info) return NULL;
1680  weed_set_funcptr_value(thread_info, WEED_LEAF_THREADFUNC, func);
1681  if (return_type) {
1682  pthread_mutex_t *dcmutex = (pthread_mutex_t *)lives_malloc(sizeof(pthread_mutex_t));
1683  pthread_mutex_init(dcmutex, NULL);
1684  weed_set_voidptr_value(thread_info, WEED_LEAF_DONTCARE_MUTEX, dcmutex);
1685  weed_set_boolean_value(thread_info, WEED_LEAF_NOTIFY, WEED_TRUE);
1686  if (return_type > 0) weed_leaf_set(thread_info, WEED_LEAF_RETURN_VALUE, return_type, 0, NULL);
1687  }
1688  c = args_fmt;
1689  for (c = args_fmt; *c; c++) {
1690  char *pkey = lives_strdup_printf("%s%d", WEED_LEAF_THREAD_PARAM, p++);
1691  switch (*c) {
1692  case 'i': weed_set_int_value(thread_info, pkey, va_arg(xargs, int)); break;
1693  case 'd': weed_set_double_value(thread_info, pkey, va_arg(xargs, double)); break;
1694  case 'b': weed_set_boolean_value(thread_info, pkey, va_arg(xargs, int)); break;
1695  case 's': case 'S': weed_set_string_value(thread_info, pkey, va_arg(xargs, char *)); break;
1696  case 'I': weed_set_int64_value(thread_info, pkey, va_arg(xargs, int64_t)); break;
1697  case 'F': weed_set_funcptr_value(thread_info, pkey, va_arg(xargs, weed_funcptr_t)); break;
1698  case 'V': case 'v': weed_set_voidptr_value(thread_info, pkey, va_arg(xargs, void *)); break;
1699  case 'P': weed_set_plantptr_value(thread_info, pkey, va_arg(xargs, weed_plantptr_t)); break;
1700  default: weed_plant_free(thread_info); return NULL;
1701  }
1702  lives_free(pkey);
1703  }
1704 
1705  if (!(attr & LIVES_THRDATTR_FG_THREAD)) {
1706  resubmit_proc_thread(thread_info, attr);
1707  if (!return_type) return NULL;
1708  }
1709  return thread_info;
1710 }
1711 
1712 
1731  int return_type, const char *args_fmt, ...) {
1732  lives_proc_thread_t lpt;
1733  va_list xargs;
1734  va_start(xargs, args_fmt);
1735  lpt = _lives_proc_thread_create(attr, func, return_type, args_fmt, xargs);
1736  va_end(xargs);
1737  return lpt;
1738 }
1739 
1740 
1741 void *main_thread_execute(lives_funcptr_t func, int return_type, void *retval, const char *args_fmt, ...) {
1742  lives_proc_thread_t lpt;
1743  va_list xargs;
1744  void *ret;
1745  va_start(xargs, args_fmt);
1746  lpt = _lives_proc_thread_create(LIVES_THRDATTR_FG_THREAD, func, return_type, args_fmt, xargs);
1747  ret = lives_fg_run(lpt, retval);
1748  va_end(xargs);
1749  return ret;
1750 }
1751 
1752 
1753 static void call_funcsig(funcsig_t sig, lives_proc_thread_t info) {
1758  uint32_t ret_type = weed_leaf_seed_type(info, _RV_);
1759  allfunc_t *thefunc = (allfunc_t *)lives_malloc(sizeof(allfunc_t));
1760  char *msg;
1761 
1762  thefunc->func = weed_get_funcptr_value(info, WEED_LEAF_THREADFUNC, NULL);
1763 
1764 #define FUNCSIG_VOID 0X00000000
1765 #define FUNCSIG_INT 0X00000001
1766 #define FUNCSIG_DOUBLE 0X00000002
1767 #define FUNCSIG_STRING 0X00000004
1768 #define FUNCSIG_VOIDP 0X0000000D
1769 #define FUNCSIG_INT_INT64 0X00000015
1770 #define FUNCSIG_STRING_INT 0X00000041
1771 #define FUNCSIG_STRING_BOOL 0X00000043
1772 #define FUNCSIG_VOIDP_VOIDP 0X000000DD
1773 #define FUNCSIG_VOIDP_DOUBLE 0X000000D2
1774 #define FUNCSIG_PLANTP_BOOL 0X000000E3
1775 #define FUNCSIG_VOIDP_VOIDP_VOIDP 0X00000DDD
1776 #define FUNCSIG_PLANTP_VOIDP_INT64 0X00000ED5
1777  // 4p
1778 #define FUNCSIG_STRING_STRING_VOIDP_INT 0X000044D1
1779 #define FUNCSIG_INT_INT_BOOL_VOIDP 0X0000113D
1780  // 5p
1781 #define FUNCSIG_INT_INT_INT_BOOL_VOIDP 0X0001113D
1782 #define FUNCSIG_VOIDP_STRING_STRING_INT64_INT 0X000D4451
1783  // 6p
1784 #define FUNCSIG_STRING_STRING_VOIDP_INT_STRING_VOIDP 0X0044D14D
1785 
1786  // Note: C compilers don't care about the type / number of function args., (else it would be impossible to alias any function pointer)
1787  // just the type / number must be correct at runtime;
1788  // However it DOES care about the return type. The funcsigs are a guide so that the correct cast / number of args. can be
1789  // determined in the code., the first argument to the GETARG macro is set by this.
1790  // return_type determines which function flavour to call, e.g func, funcb, funci
1792 
1794 
1798 
1799  switch (sig) {
1800  case FUNCSIG_VOID:
1801  switch (ret_type) {
1802  case WEED_SEED_INT64: CALL_0(int64); break;
1803  default: CALL_VOID_0(); break;
1804  }
1805  break;
1806  case FUNCSIG_INT:
1807  switch (ret_type) {
1808  default: CALL_VOID_1(int); break;
1809  }
1810  break;
1811  case FUNCSIG_DOUBLE:
1812  switch (ret_type) {
1813  default: CALL_VOID_1(double); break;
1814  }
1815  break;
1816  case FUNCSIG_STRING:
1817  switch (ret_type) {
1818  case WEED_SEED_STRING: CALL_1(string, string); break;
1819  case WEED_SEED_INT64: CALL_1(int64, string); break;
1820  default: CALL_VOID_1(string); break;
1821  }
1822  break;
1823  case FUNCSIG_VOIDP:
1824  switch (ret_type) {
1825  case WEED_SEED_BOOLEAN: CALL_1(boolean, voidptr); break;
1826  case WEED_SEED_INT: CALL_1(int, voidptr); break;
1827  default: CALL_VOID_1(voidptr); break;
1828  }
1829  break;
1830  case FUNCSIG_INT_INT64:
1831  switch (ret_type) {
1832  default: CALL_VOID_2(int, int64); break;
1833  }
1834  break;
1835  case FUNCSIG_STRING_INT:
1836  switch (ret_type) {
1837  default: CALL_VOID_2(string, int); break;
1838  }
1839  break;
1840  case FUNCSIG_STRING_BOOL:
1841  switch (ret_type) {
1842  default: CALL_VOID_2(string, boolean); break;
1843  }
1844  break;
1845  case FUNCSIG_VOIDP_DOUBLE:
1846  switch (ret_type) {
1847  default: CALL_VOID_2(voidptr, double); break;
1848  }
1849  break;
1850  case FUNCSIG_VOIDP_VOIDP:
1851  switch (ret_type) {
1852  case WEED_SEED_BOOLEAN: CALL_2(boolean, voidptr, voidptr); break;
1853  default: CALL_VOID_2(voidptr, voidptr); break;
1854  }
1855  break;
1856  case FUNCSIG_PLANTP_BOOL:
1857  switch (ret_type) {
1858  default: CALL_VOID_2(plantptr, boolean); break;
1859  }
1860  break;
1862  switch (ret_type) {
1863  case WEED_SEED_BOOLEAN: CALL_3(boolean, voidptr, voidptr, voidptr); break;
1864  default: CALL_VOID_3(voidptr, voidptr, voidptr); break;
1865  }
1866  break;
1868  switch (ret_type) {
1869  case WEED_SEED_BOOLEAN: CALL_3(boolean, plantptr, voidptr, int64); break;
1870  default: CALL_VOID_3(plantptr, voidptr, int64); break;
1871  }
1872  break;
1874  switch (ret_type) {
1875  case WEED_SEED_STRING: CALL_4(string, string, string, voidptr, int); break;
1876  default: CALL_VOID_4(string, string, voidptr, int); break;
1877  }
1878  break;
1880  switch (ret_type) {
1881  case WEED_SEED_BOOLEAN: CALL_4(boolean, int, int, boolean, voidptr); break;
1882  default: CALL_VOID_4(int, int, boolean, voidptr); break;
1883  }
1884  break;
1886  switch (ret_type) {
1887  default: CALL_VOID_5(voidptr, string, string, int64, int); break;
1888  }
1889  break;
1891  switch (ret_type) {
1892  default: CALL_VOID_5(int, int, int, boolean, voidptr); break;
1893  }
1894  break;
1896  switch (ret_type) {
1897  case WEED_SEED_STRING: CALL_6(string, string, string, voidptr, int, string, voidptr); break;
1898  default: CALL_VOID_6(string, string, voidptr, int, string, voidptr); break;
1899  }
1900  break;
1901  default:
1902  msg = lives_strdup_printf("Unknown funcsig with tyte 0x%016lX called", sig);
1903  LIVES_FATAL(msg);
1904  lives_free(msg);
1905  break;
1906  }
1907 
1908  lives_free(thefunc);
1909 }
1910 
1912  volatile boolean *sync_ready = (volatile boolean *)weed_get_voidptr_value(tinfo, "sync_ready", NULL);
1913  if (sync_ready) *sync_ready = TRUE;
1914 }
1915 
1918  if (!tinfo) return TRUE;
1919  if (weed_plant_has_leaf(tinfo, WEED_LEAF_NOTIFY) && weed_get_boolean_value(tinfo, WEED_LEAF_DONE, NULL)
1920  == WEED_FALSE)
1921  return FALSE;
1922  return (weed_leaf_num_elements(tinfo, _RV_) > 0
1923  || weed_get_boolean_value(tinfo, WEED_LEAF_DONE, NULL) == WEED_TRUE);
1924 }
1925 
1928  return (weed_get_int_value(tinfo, WEED_LEAF_SIGNALLED, NULL) == WEED_TRUE);
1929 }
1930 
1933  lives_thread_data_t *tdata = (lives_thread_data_t *)weed_get_voidptr_value(tinfo, WEED_LEAF_SIGNAL_DATA, NULL);
1934  if (tdata) return tdata->idx;
1935  return 0;
1936 }
1937 
1939  weed_set_boolean_value(tinfo, WEED_LEAF_THREAD_CANCELLABLE, WEED_TRUE);
1940 }
1941 
1943  return weed_get_boolean_value(tinfo, WEED_LEAF_THREAD_CANCELLABLE, NULL) == WEED_TRUE ? TRUE : FALSE;
1944 }
1945 
1947  if (!lives_proc_thread_get_cancellable(tinfo)) return FALSE;
1948  weed_set_boolean_value(tinfo, WEED_LEAF_THREAD_CANCELLED, WEED_TRUE);
1949  lives_proc_thread_join(tinfo);
1950  return TRUE;
1951 }
1952 
1957  pthread_mutex_t *dcmutex = weed_get_voidptr_value(tinfo, WEED_LEAF_DONTCARE_MUTEX, NULL);
1958  if (dcmutex) {
1959  pthread_mutex_lock(dcmutex);
1960  if (!lives_proc_thread_check(tinfo)) {
1961  weed_set_boolean_value(tinfo, WEED_LEAF_DONTCARE, WEED_TRUE);
1962  pthread_mutex_unlock(dcmutex);
1963  } else {
1964  pthread_mutex_unlock(dcmutex);
1965  lives_proc_thread_join(tinfo);
1966  }
1967  }
1968  return TRUE;
1969 }
1970 
1972  return (tinfo && weed_get_boolean_value(tinfo, WEED_LEAF_THREAD_CANCELLED, NULL) == WEED_TRUE)
1973  ? TRUE : FALSE;
1974 }
1975 
1976 #define _join(stype) lives_nanosleep_until_nonzero(weed_leaf_num_elements(tinfo, _RV_)); \
1977  return weed_get_##stype##_value(tinfo, _RV_, NULL);
1978 
1980  // WARNING !! version without a return value will free tinfo !
1981  void *dcmutex;
1982  lives_nanosleep_until_nonzero((weed_get_boolean_value(tinfo, WEED_LEAF_DONE, NULL) == WEED_TRUE));
1983  dcmutex = weed_get_voidptr_value(tinfo, WEED_LEAF_DONTCARE_MUTEX, NULL);
1984  if (dcmutex) lives_free(dcmutex);
1985  weed_plant_free(tinfo);
1986 }
1995 
2000 static funcsig_t make_funcsig(lives_proc_thread_t func_info) {
2001  funcsig_t funcsig = 0;
2002  for (register int nargs = 0; nargs < 16; nargs++) {
2003  char *lname = lives_strdup_printf("%s%d", WEED_LEAF_THREAD_PARAM, nargs);
2004  int st = weed_leaf_seed_type(func_info, lname);
2005  lives_free(lname);
2006  if (!st) break;
2007  funcsig <<= 4;
2008  if (st < 12) funcsig |= st; // 1 == int, 2 == double, 3 == boolean (int), 4 == char *, 5 == int64_t
2009  else {
2010  switch (st) {
2011  case WEED_SEED_FUNCPTR: funcsig |= 0XC; break;
2012  case WEED_SEED_VOIDPTR: funcsig |= 0XD; break;
2013  case WEED_SEED_PLANTPTR: funcsig |= 0XE; break;
2014  default: funcsig |= 0XF; break;
2015  }
2016  }
2017  }
2018  return funcsig;
2019 }
2020 
2021 static void *_plant_thread_func(void *args) {
2023  uint32_t ret_type = weed_leaf_seed_type(info, _RV_);
2024  funcsig_t sig = make_funcsig(info);
2025  THREADVAR(tinfo) = info;
2026  if (weed_get_boolean_value(info, "no_gui", NULL) == WEED_TRUE) THREADVAR(no_gui) = TRUE;
2027  call_funcsig(sig, info);
2028 
2029  if (weed_get_boolean_value(info, WEED_LEAF_NOTIFY, NULL) == WEED_TRUE) {
2030  boolean dontcare;
2031  pthread_mutex_t *dcmutex = (pthread_mutex_t *)weed_get_voidptr_value(info, WEED_LEAF_DONTCARE_MUTEX, NULL);
2032  pthread_mutex_lock(dcmutex);
2033  dontcare = weed_get_boolean_value(info, WEED_LEAF_DONTCARE, NULL);
2034  weed_set_boolean_value(info, WEED_LEAF_DONE, WEED_TRUE);
2035  pthread_mutex_unlock(dcmutex);
2036  if (dontcare == WEED_TRUE) {
2037  lives_free(dcmutex);
2038  weed_plant_free(info);
2039  }
2040  } else if (!ret_type) weed_plant_free(info);
2041  return NULL;
2042 }
2043 
2044 
2045 void *fg_run_func(lives_proc_thread_t lpt, void *retval) {
2046  uint32_t ret_type = weed_leaf_seed_type(lpt, _RV_);
2047  funcsig_t sig = make_funcsig(lpt);
2048 
2049  call_funcsig(sig, lpt);
2050 
2051  switch (ret_type) {
2052  case WEED_SEED_INT: {
2053  int *ival = (int *)retval;
2054  *ival = weed_get_int_value(lpt, _RV_, NULL);
2055  weed_plant_free(lpt);
2056  return (void *)ival;
2057  }
2058  case WEED_SEED_BOOLEAN: {
2059  int *bval = (int *)retval;
2060  *bval = weed_get_boolean_value(lpt, _RV_, NULL);
2061  weed_plant_free(lpt);
2062  return (void *)bval;
2063  }
2064  case WEED_SEED_DOUBLE: {
2065  double *dval = (double *)retval;
2066  *dval = weed_get_double_value(lpt, _RV_, NULL);
2067  weed_plant_free(lpt);
2068  return (void *)dval;
2069  }
2070  case WEED_SEED_STRING: {
2071  char *chval = weed_get_string_value(lpt, _RV_, NULL);
2072  weed_plant_free(lpt);
2073  return (void *)chval;
2074  }
2075  case WEED_SEED_INT64: {
2076  int64_t *i64val = (int64_t *)retval;
2077  *i64val = weed_get_int64_value(lpt, _RV_, NULL);
2078  weed_plant_free(lpt);
2079  return (void *)i64val;
2080  }
2081  case WEED_SEED_VOIDPTR: {
2082  void *val;
2083  val = weed_get_voidptr_value(lpt, _RV_, NULL);
2084  weed_plant_free(lpt);
2085  return val;
2086  }
2087  case WEED_SEED_PLANTPTR: {
2088  weed_plant_t *pval;
2089  pval = weed_get_plantptr_value(lpt, _RV_, NULL);
2090  weed_plant_free(lpt);
2091  return (void *)pval;
2092  }
2094  default:
2095  weed_plant_free(lpt);
2096  break;
2097  }
2098  return NULL;
2099 }
2100 
2101 #undef _RV_
2102 
2108  lives_thread_t *thread = (lives_thread_t *)lives_calloc(1, sizeof(lives_thread_t));
2109  thrd_work_t *work;
2110 
2112  attr |= LIVES_THRDATTR_AUTODELETE;
2113  lives_thread_create(thread, attr, _plant_thread_func, (void *)thread_info);
2114  work = (thrd_work_t *)thread->data;
2115  if (attr & LIVES_THRDATTR_WAIT_SYNC) {
2116  weed_set_voidptr_value(thread_info, "sync_ready", (void *) & (work->sync_ready));
2117  }
2118  if (attr & LIVES_THRDATTR_NO_GUI) {
2119  weed_set_boolean_value(thread_info, "no_gui", WEED_TRUE);
2120  }
2121 }
2122 
2123 
2125 
2127 #ifndef VALGRIND_ON
2128 #define MINPOOLTHREADS 8
2129 #else
2130 #define MINPOOLTHREADS 2
2131 #endif
2132 static int npoolthreads;
2133 static pthread_t **poolthrds;
2134 static pthread_cond_t tcond = PTHREAD_COND_INITIALIZER;
2135 static pthread_mutex_t tcond_mutex = PTHREAD_MUTEX_INITIALIZER;
2136 static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
2137 static pthread_mutex_t twork_mutex = PTHREAD_MUTEX_INITIALIZER;
2138 static pthread_mutex_t twork_count_mutex = PTHREAD_MUTEX_INITIALIZER;
2139 static LiVESList *twork_first, *twork_last;
2140 static volatile int ntasks;
2141 static boolean threads_die;
2142 
2143 static LiVESList *allctxs = NULL;
2144 
2145 lives_thread_data_t *get_thread_data(void) {
2146  LiVESWidgetContext *ctx = lives_widget_context_get_thread_default();
2147  LiVESList *list = allctxs;
2148  if (!ctx) ctx = lives_widget_context_default();
2149  for (; list; list = list->next) {
2150  if (((lives_thread_data_t *)list->data)->ctx == ctx) return list->data;
2151  }
2152  return NULL;
2153 }
2154 
2155 
2157  static lives_threadvars_t *dummyvars = NULL;
2158  lives_thread_data_t *thrdat = get_thread_data();
2159  if (!thrdat) {
2160  if (!dummyvars) dummyvars = lives_calloc(1, sizeof(lives_threadvars_t));
2161  return dummyvars;
2162  }
2163  return &thrdat->vars;
2164 }
2165 
2166 static lives_thread_data_t *get_thread_data_by_id(uint64_t idx) {
2167  LiVESList *list = allctxs;
2168  for (; list; list = list->next) {
2169  if (((lives_thread_data_t *)list->data)->idx == idx) return list->data;
2170  }
2171  return NULL;
2172 }
2173 
2174 lives_thread_data_t *lives_thread_data_create(uint64_t idx) {
2175  lives_thread_data_t *tdata = (lives_thread_data_t *)lives_calloc(1, sizeof(lives_thread_data_t));
2176  if (idx != 0) tdata->ctx = lives_widget_context_new();
2177  else tdata->ctx = lives_widget_context_default();
2178  tdata->idx = idx;
2179  tdata->vars.var_rowstride_alignment = ALIGN_DEF;
2180  tdata->vars.var_last_sws_block = -1;
2181  tdata->vars.var_mydata = tdata;
2182  allctxs = lives_list_prepend(allctxs, (livespointer)tdata);
2183  return tdata;
2184 }
2185 
2186 
2187 static boolean gsrc_wrapper(livespointer data) {
2188  thrd_work_t *mywork = (thrd_work_t *)data;
2189  (*mywork->func)(mywork->arg);
2190  return FALSE;
2191 }
2192 
2193 
2194 boolean do_something_useful(lives_thread_data_t *tdata) {
2196  LiVESList *list;
2197  thrd_work_t *mywork;
2198  uint64_t myflags = 0;
2199 
2200  if (!tdata->idx) abort();
2201 
2202  pthread_mutex_lock(&twork_mutex);
2203  list = twork_last;
2204  if (LIVES_UNLIKELY(!list)) {
2205  pthread_mutex_unlock(&twork_mutex);
2206  return FALSE;
2207  }
2208 
2209  if (twork_first == list) twork_last = twork_first = NULL;
2210  else {
2211  twork_last = list->prev;
2212  twork_last->next = NULL;
2213  }
2214  pthread_mutex_unlock(&twork_mutex);
2215 
2216  mywork = (thrd_work_t *)list->data;
2217  mywork->busy = tdata->idx;
2218  myflags = mywork->flags;
2219 
2220  if (myflags & LIVES_THRDFLAG_WAIT_SYNC) {
2222  }
2223 
2224  lives_widget_context_invoke(tdata->ctx, gsrc_wrapper, mywork);
2225  //(*mywork->func)(mywork->arg);
2226 
2227  if (myflags & LIVES_THRDFLAG_AUTODELETE) {
2228  lives_free(mywork); lives_free(list);
2229  } else mywork->done = tdata->idx;
2230 
2231  pthread_mutex_lock(&twork_count_mutex);
2232  ntasks--;
2233  pthread_mutex_unlock(&twork_count_mutex);
2234  return TRUE;
2235 }
2236 
2237 
2238 static void *thrdpool(void *arg) {
2239  boolean skip_wait = FALSE;
2240  lives_thread_data_t *tdata = (lives_thread_data_t *)arg;
2243  }
2244 
2245  lives_widget_context_push_thread_default(tdata->ctx);
2246 
2247  while (!threads_die) {
2248  if (!skip_wait) {
2249  pthread_mutex_lock(&tcond_mutex);
2250  pthread_cond_wait(&tcond, &tcond_mutex);
2251  pthread_mutex_unlock(&tcond_mutex);
2252  }
2253  if (LIVES_UNLIKELY(threads_die)) break;
2254  skip_wait = do_something_useful(tdata);
2257  }
2258  }
2261  }
2262  return NULL;
2263 }
2264 
2265 
2266 LIVES_GLOBAL_INLINE weed_plant_t *lives_plant_new(int subtype) {
2267  weed_plant_t *plant = weed_plant_new(WEED_PLANT_LIVES);
2268  weed_set_int_value(plant, WEED_LEAF_LIVES_SUBTYPE, subtype);
2269  return plant;
2270 }
2271 
2272 
2273 LIVES_GLOBAL_INLINE weed_plant_t *lives_plant_new_with_index(int subtype, int64_t index) {
2274  weed_plant_t *plant = lives_plant_new(subtype);
2275  weed_set_int64_value(plant, WEED_LEAF_INDEX, index);
2276  return plant;
2277 }
2278 
2279 
2281  npoolthreads = MINPOOLTHREADS;
2282  if (prefs->nfx_threads > npoolthreads) npoolthreads = prefs->nfx_threads;
2283  poolthrds = (pthread_t **)lives_calloc(npoolthreads, sizeof(pthread_t *));
2284  threads_die = FALSE;
2285  twork_first = twork_last = NULL;
2286  ntasks = 0;
2287  for (int i = 0; i < npoolthreads; i++) {
2288  lives_thread_data_t *tdata = lives_thread_data_create(i + 1);
2289  poolthrds[i] = (pthread_t *)lives_malloc(sizeof(pthread_t));
2290  pthread_create(poolthrds[i], NULL, thrdpool, tdata);
2291  }
2292 }
2293 
2294 
2296  threads_die = TRUE;
2297  pthread_mutex_lock(&tcond_mutex);
2298  pthread_cond_broadcast(&tcond);
2299  pthread_mutex_unlock(&tcond_mutex);
2300  for (int i = 0; i < npoolthreads; i++) {
2301  lives_thread_data_t *tdata = get_thread_data_by_id(i + 1);
2302  pthread_cond_broadcast(&tcond);
2303  pthread_mutex_unlock(&tcond_mutex);
2304  pthread_join(*(poolthrds[i]), NULL);
2305  lives_widget_context_unref(tdata->ctx);
2306  lives_free(tdata);
2307  lives_free(poolthrds[i]);
2308  }
2309  lives_free(poolthrds);
2310  poolthrds = NULL;
2311  npoolthreads = 0;
2312  lives_list_free_all((LiVESList **)&twork_first);
2313  twork_first = twork_last = NULL;
2314  ntasks = 0;
2315 }
2316 
2317 
2319  LiVESList *list = (LiVESList *)thread;
2320  thrd_work_t *work = (thrd_work_t *)lives_calloc(1, sizeof(thrd_work_t));
2321  if (!thread) list = (LiVESList *)lives_calloc(1, sizeof(LiVESList));
2322  else list->next = list->prev = NULL;
2323  list->data = work;
2324  work->func = func;
2325  work->arg = arg;
2326 
2327  if (!thread || (attr & LIVES_THRDATTR_AUTODELETE))
2329  if (attr & LIVES_THRDATTR_WAIT_SYNC) {
2331  work->sync_ready = FALSE;
2332  }
2333 
2334  pthread_mutex_lock(&twork_mutex);
2335  if (!twork_first) {
2336  twork_first = twork_last = list;
2337  } else {
2338  if (!(attr & LIVES_THRDATTR_PRIORITY)) {
2339  twork_first->prev = list;
2340  list->next = twork_first;
2341  twork_first = list;
2342  } else {
2343  twork_last->next = list;
2344  list->prev = twork_last;
2345  twork_last = list;
2346  }
2347  }
2348  pthread_mutex_unlock(&twork_mutex);
2349  pthread_mutex_lock(&twork_count_mutex);
2350  ntasks++;
2351  pthread_mutex_unlock(&twork_count_mutex);
2352  pthread_mutex_lock(&tcond_mutex);
2353  pthread_cond_signal(&tcond);
2354  pthread_mutex_unlock(&tcond_mutex);
2355  pthread_mutex_lock(&pool_mutex);
2356  if (ntasks >= npoolthreads) {
2357  pthread_mutex_lock(&tcond_mutex);
2358  pthread_cond_broadcast(&tcond);
2359  pthread_mutex_unlock(&tcond_mutex);
2360  poolthrds = (pthread_t **)lives_realloc(poolthrds, (npoolthreads + MINPOOLTHREADS) * sizeof(pthread_t *));
2361  for (int i = npoolthreads; i < npoolthreads + MINPOOLTHREADS; i++) {
2362  lives_thread_data_t *tdata = lives_thread_data_create(i + 1);
2363  poolthrds[i] = (pthread_t *)lives_malloc(sizeof(pthread_t));
2364  pthread_create(poolthrds[i], NULL, thrdpool, tdata);
2365  pthread_mutex_lock(&tcond_mutex);
2366  pthread_cond_signal(&tcond);
2367  pthread_mutex_unlock(&tcond_mutex);
2368  }
2369  npoolthreads += MINPOOLTHREADS;
2370  }
2371  pthread_mutex_unlock(&pool_mutex);
2372  return 0;
2373 }
2374 
2375 
2376 uint64_t lives_thread_join(lives_thread_t work, void **retval) {
2377  thrd_work_t *task = (thrd_work_t *)work.data;
2378  uint64_t nthrd = 0;
2379  if (task->flags & LIVES_THRDFLAG_AUTODELETE) {
2380  LIVES_FATAL("lives_thread_join() called on an autodelete thread");
2381  return 0;
2382  }
2383 
2384  while (!task->busy) {
2385  pthread_mutex_lock(&tcond_mutex);
2386  pthread_cond_signal(&tcond);
2387  pthread_mutex_unlock(&tcond_mutex);
2388  if (task->busy) break;
2389  sched_yield();
2390  lives_nanosleep(1000);
2391  }
2392 
2393  if (!task->done) {
2394  pthread_mutex_lock(&tcond_mutex);
2395  pthread_cond_signal(&tcond);
2396  pthread_mutex_unlock(&tcond_mutex);
2397  }
2398 
2400  nthrd = task->done;
2401 
2402  if (retval) *retval = task->ret;
2403  lives_free(task);
2404  return nthrd;
2405 }
2406 
2407 
2409 #ifdef IS_MINGW
2410  return GetCurrentProcessId(),
2411 #else
2412  return getpid();
2413 #endif
2414 }
2415 
2417  return geteuid();
2418 }
2419 
2421  return getegid();
2422 }
2423 
2424 static uint16_t swabtab[65536];
2425 static boolean swabtab_inited = FALSE;
2426 
2427 static void init_swabtab(void) {
2428  for (int i = 0; i < 256; i++) {
2429  int z = i << 8;
2430  for (int j = 0; j < 256; j++) {
2431  swabtab[z++] = (j << 8) + i;
2432  }
2433  }
2434  swabtab_inited = TRUE;
2435 }
2436 
2437 union split8 {
2438  uint64_t u64;
2439  uint32_t u32[2];
2440 };
2441 
2442 union split4 {
2443  uint32_t u32;
2444  uint16_t u16[2];
2445 };
2446 
2447 // gran(ularity) may be 1, or 2
2448 LIVES_GLOBAL_INLINE void swab2(const void *from, const void *to, size_t gran) {
2449  uint16_t *s = (uint16_t *)from;
2450  uint16_t *d = (uint16_t *)to;
2451  if (gran == 2) {
2452  uint16_t tmp = *s;
2453  *s = *d;
2454  *d = tmp;
2455  return;
2456  }
2457  if (!swabtab_inited) init_swabtab();
2458  *d = swabtab[*s];
2459 }
2460 
2461 // gran(ularity) may be 1, 2 or 4
2462 LIVES_GLOBAL_INLINE void swab4(const void *from, const void *to, size_t gran) {
2463  union split4 *d = (union split4 *)to, s;
2464  uint16_t tmp;
2465 
2466  if (gran > 2) {
2467  lives_memcpy((void *)to, from, gran);
2468  return;
2469  }
2470  s.u32 = *(uint32_t *)from;
2471  tmp = s.u16[0];
2472  if (gran == 2) {
2473  d->u16[0] = s.u16[1];
2474  d->u16[1] = tmp;
2475  } else {
2476  swab2(&s.u16[1], &d->u16[0], 1);
2477  swab2(&tmp, &d->u16[1], 1);
2478  }
2479 }
2480 
2481 
2482 // gran(ularity) may be 1, 2 or 4
2483 LIVES_GLOBAL_INLINE void swab8(const void *from, const void *to, size_t gran) {
2484  union split8 *d = (union split8 *)to, s;
2485  uint32_t tmp;
2486  if (gran > 4) {
2487  lives_memcpy((void *)to, from, gran);
2488  return;
2489  }
2490  s.u64 = *(uint64_t *)from;
2491  tmp = s.u32[0];
2492  if (gran == 4) {
2493  d->u32[0] = s.u32[1];
2494  d->u32[1] = tmp;
2495  } else {
2496  swab4(&s.u32[1], &d->u32[0], gran);
2497  swab4(&tmp, &d->u32[1], gran);
2498  }
2499 }
2500 
2501 
2502 LIVES_GLOBAL_INLINE void reverse_bytes(char *buff, size_t count, size_t gran) {
2503  if (count == 2) swab2(buff, buff, 1);
2504  else if (count == 4) swab4(buff, buff, gran);
2505  else if (count == 8) swab8(buff, buff, gran);
2506 }
2507 
2508 
2509 boolean reverse_buffer(uint8_t *buff, size_t count, size_t chunk) {
2510  // reverse chunk sized bytes in buff, count must be a multiple of chunk
2511  ssize_t start = -1, end;
2512  size_t ocount = count;
2513 
2514  if (chunk < 8) {
2515  if ((chunk != 4 && chunk != 2 && chunk != 1) || (count % chunk) != 0) return FALSE;
2516  } else {
2517  if ((chunk & 0x01) || (count % chunk) != 0) return FALSE;
2518  else {
2519 #ifdef USE_RPMALLOC
2520  void *tbuff = rpmalloc(chunk);
2521 #else
2522  void *tbuff = lives_malloc(chunk);
2523 #endif
2524  start++;
2525  end = ocount - 1 - chunk;
2526  while (start + chunk < end) {
2527  lives_memcpy(tbuff, &buff[end], chunk);
2528  lives_memcpy(&buff[end], &buff[start], chunk);
2529  lives_memcpy(&buff[start], tbuff, chunk);
2530  start += chunk;
2531  end -= chunk;
2532  }
2533 #ifdef USE_RPMALLOC
2534  rpfree(tbuff);
2535 #else
2536  lives_free(tbuff);
2537 #endif
2538  return TRUE;
2539  }
2540  }
2541 
2543  count >>= 1;
2544 
2545  if (count >= 8 && (ocount & 0x07) == 0) {
2546  // start by swapping 8 bytes from each end
2547  uint64_t *buff8 = (uint64_t *)buff;
2548  if ((void *)buff8 == (void *)buff) {
2549  end = ocount >> 3;
2550  for (; count >= 8; count -= 8) {
2552  uint64_t tmp8 = buff8[--end];
2553  if (chunk == 8) {
2554  buff8[end] = buff8[++start];
2555  buff8[start] = tmp8;
2556  } else {
2557  swab8(&buff8[++start], &buff8[end], chunk);
2558  swab8(&tmp8, &buff8[start], chunk);
2559  }
2560  }
2561  if (count <= chunk / 2) return TRUE;
2562  start = (start + 1) << 3;
2563  start--;
2564  }
2565  }
2566 
2568  if (chunk >= 8) return FALSE;
2569 
2570  if (count >= 4 && (ocount & 0x03) == 0) {
2571  uint32_t *buff4 = (uint32_t *)buff;
2572  if ((void *)buff4 == (void *)buff) {
2573  if (start > 0) {
2574  end = (ocount - start) >> 2;
2575  start >>= 2;
2576  } else end = ocount >> 2;
2577  for (; count >= 4; count -= 4) {
2579  uint32_t tmp4 = buff4[--end];
2580  if (chunk == 4) {
2581  buff4[end] = buff4[++start];
2582  buff4[start] = tmp4;
2583  } else {
2584  swab4(&buff4[++start], &buff4[end], chunk);
2585  swab4(&tmp4, &buff4[start], chunk);
2586  }
2587  }
2588  if (count <= chunk / 2) return TRUE;
2589  start = (start + 1) << 2;
2590  start--;
2591  }
2592  }
2593 
2595  if (chunk >= 4) return FALSE;
2596 
2597  if (count > 0) {
2598  uint16_t *buff2 = (uint16_t *)buff;
2599  if ((void *)buff2 == (void *)buff) {
2600  if (start > 0) {
2601  end = (ocount - start) >> 1;
2602  start >>= 1;
2603  } else end = ocount >> 1;
2604  for (; count >= chunk / 2; count -= 2) {
2606  uint16_t tmp2 = buff2[--end];
2607  if (chunk >= 2) {
2608  buff2[end] = buff2[++start];
2609  buff2[start] = tmp2;
2610  }
2612  else {
2613  swab2(&buff2[++start], &buff2[end], 1);
2614  swab2(&tmp2, &buff2[start], 1);
2615  // *INDENT-OFF*
2616  }}}}
2617  // *INDENT-ON*
2618 
2619  if (count == 0) return TRUE;
2620  return FALSE;
2621 }
2622 
2623 
2625 static int16_t theflow[EFFORT_RANGE_MAX];
2626 static int flowlen = 0;
2627 static boolean inited = FALSE;
2628 static int struggling = 0;
2629 static int badthingcount = 0;
2630 static int goodthingcount = 0;
2631 
2632 static int pop_flowstate(void) {
2633  int ret = theflow[0];
2634  flowlen--;
2635  for (int i = 0; i < flowlen; i++) {
2636  theflow[i] = theflow[i + 1];
2637  }
2638  return ret;
2639 }
2640 
2641 
2642 void reset_effort(void) {
2644  mainw->blend_palette = WEED_PALETTE_END;
2645  lives_memset(theflow, 0, sizeof(theflow));
2646  inited = TRUE;
2647  badthingcount = goodthingcount = 0;
2648  struggling = 0;
2649  if ((mainw->is_rendering || (mainw->multitrack
2650  && mainw->multitrack->is_rendering)) && !mainw->preview_rendering)
2652  else mainw->effort = 0;
2653 }
2654 
2655 
2656 void update_effort(int nthings, boolean badthings) {
2657  int spcycles;
2658  short pb_quality = prefs->pb_quality;
2659  if (!inited) reset_effort();
2660  if (!nthings) return;
2661 
2662  if (nthings > EFFORT_RANGE_MAX) nthings = EFFORT_RANGE_MAX;
2663 
2664  //g_print("VALS %d %d %d %d %d\n", nthings, badthings, mainw->effort, badthingcount, goodthingcount);
2665  if (badthings) {
2666  badthingcount += nthings;
2667  goodthingcount = 0;
2668  spcycles = -1;
2669  } else {
2670  spcycles = nthings;
2671  if (spcycles + goodthingcount > EFFORT_RANGE_MAX) spcycles = EFFORT_RANGE_MAX - goodthingcount;
2672  goodthingcount += spcycles;
2673  if (goodthingcount > EFFORT_RANGE_MAX) goodthingcount = EFFORT_RANGE_MAX;
2674  nthings = 1;
2675  }
2676 
2677  while (nthings-- > 0) {
2678  if (flowlen >= EFFORT_RANGE_MAX) {
2680  int res = pop_flowstate();
2681  if (res > 0) badthingcount -= res;
2682  else goodthingcount += res;
2683  //g_print("vals %d %d %d ", res, badthingcount, goodthingcount);
2684  }
2686  theflow[flowlen] = -spcycles;
2687  flowlen++;
2688  }
2689 
2690  //g_print("vals2x %d %d %d %d\n", mainw->effort, badthingcount, goodthingcount, struggling);
2691 
2692  if (!badthingcount) {
2694  if (goodthingcount > EFFORT_RANGE_MAX) goodthingcount = EFFORT_RANGE_MAX;
2696  } else {
2697  if (badthingcount > EFFORT_RANGE_MAX) badthingcount = EFFORT_RANGE_MAX;
2698  mainw->effort = badthingcount;
2699  }
2700  //g_print("vals2 %d %d %d %d\n", mainw->effort, badthingcount, goodthingcount, struggling);
2701 
2702  if (mainw->effort < 0) {
2703  if (struggling > -EFFORT_RANGE_MAX) {
2704  struggling--;
2705  }
2706  if (mainw->effort < -EFFORT_LIMIT_MED) {
2707  if (struggling == -EFFORT_RANGE_MAX && pb_quality < PB_QUALITY_HIGH) {
2708  pb_quality++;
2709  } else if (struggling < -EFFORT_LIMIT_MED && pb_quality < PB_QUALITY_MED) {
2710  pb_quality++;
2711  }
2712  }
2713  }
2714 
2715  if (mainw->effort > 0) {
2716  if (pb_quality > future_prefs->pb_quality) {
2717  pb_quality = future_prefs->pb_quality;
2718  goto tryset;
2719  }
2720  if (!struggling) {
2721  struggling = 1;
2722  return;
2723  }
2724  if (mainw->effort > EFFORT_LIMIT_MED || (struggling > 0 && (mainw->effort > EFFORT_LIMIT_LOW))) {
2725  if (struggling < EFFORT_RANGE_MAX) struggling++;
2726  if (struggling == EFFORT_RANGE_MAX) {
2727  if (pb_quality > PB_QUALITY_LOW) {
2728  pb_quality = PB_QUALITY_LOW;
2729  } else if (mainw->effort > EFFORT_LIMIT_MED) {
2730  if (pb_quality > PB_QUALITY_MED) {
2731  pb_quality--;
2732  }
2733  }
2734  } else {
2735  if (pb_quality > future_prefs->pb_quality) {
2736  pb_quality = future_prefs->pb_quality;
2737  } else if (future_prefs->pb_quality > PB_QUALITY_LOW) {
2738  pb_quality = future_prefs->pb_quality - 1;
2739  }
2740  // *INDENT-OFF*
2741  }}}
2742  // *INDENT-ON
2743  tryset:
2744  if (pb_quality != prefs->pb_quality && (!mainw->frame_layer_preload || mainw->pred_frame == -1
2746  prefs->pb_quality = pb_quality;
2747  mainw->blend_palette = WEED_PALETTE_END;
2748  }
2749 
2750  //g_print("STRG %d and %d %d\n", struggling, mainw->effort, prefs->pb_quality);
2751 }
2752 
2753 
2754 char *grep_in_cmd(const char *cmd, int mstart, int npieces, const char *mphrase, int ridx, int rlen) {
2755  char **lines, **words, **mwords;
2756  char *match = NULL;
2757  char buff[65536];
2758  size_t nlines, mwlen;
2759  int m, minpieces;
2760 
2761  //break_me("GIC");
2762 
2763  if (!mphrase || npieces < -1 || !npieces || rlen < 1 || (ridx <= mstart && ridx + rlen > mstart)
2764  || (npieces > 0 && (ridx + rlen > npieces || mstart >= npieces))) return NULL;
2765 
2766  mwlen = get_token_count(mphrase, ' ');
2767  if (mstart + mwlen > npieces
2768  || (ridx + rlen > mstart && ridx < mstart + mwlen)) return NULL;
2769 
2770  mwords = lives_strsplit(mphrase, " ", mwlen);
2771 
2772  if (!cmd || !mphrase || !*cmd || !*mphrase) goto grpcln;
2773  lives_popen(cmd, FALSE, buff, 65536);
2774  if (THREADVAR(com_failed)
2775  || (!*buff || !(nlines = get_token_count(buff, '\n')))) {
2776  THREADVAR(com_failed) = FALSE;
2777  goto grpcln;
2778  }
2779 
2780  minpieces = MAX(mstart + mwlen, ridx + rlen);
2781 
2782  lines = lives_strsplit(buff, "\n", nlines);
2783  for (int l = 0; l < nlines; l++) {
2784  if (*lines[l] && get_token_count(lines[l], ' ') >= minpieces) {
2785  words = lives_strsplit(lines[l], " ", npieces);
2786  for (m = 0; m < mwlen; m++) {
2787  if (lives_strcmp(words[m + mstart], mwords[m])) break;
2788  }
2789  if (m == mwlen) {
2790  match = lives_strdup(words[ridx]);
2791  for (int w = 1; w < rlen; w++) {
2792  char *tmp = lives_strdup_printf(" %s", words[ridx + w]);
2793  match = lives_concat(match, tmp);
2794  }
2795  }
2796  lives_strfreev(words);
2797  }
2798  if (match) break;
2799  }
2800  lives_strfreev(lines);
2801  grpcln:
2802  lives_strfreev(mwords);
2803  return match;
2804 }
2805 
2806 LIVES_LOCAL_INLINE boolean mini_run(char *cmd) {
2807  if (!cmd) return FALSE;
2808  lives_system(cmd, TRUE);
2809  lives_free(cmd);
2810  if (THREADVAR(com_failed)) return FALSE;
2811  return TRUE;
2812 }
2813 
2814 LIVES_LOCAL_INLINE char *mini_popen(char *cmd) {
2815  if (!cmd) return NULL;
2816  else {
2817  char buff[PATH_MAX];
2818  //char *com = lives_strdup_printf("%s $(%s)", capable->echo_cmd, EXEC_MKTEMP);
2819  lives_popen(cmd, TRUE, buff, PATH_MAX);
2820  lives_free(cmd);
2821  lives_chomp(buff);
2822  return lives_strdup(buff);
2823  }
2824 }
2825 
2826 
2827 LiVESResponseType send_to_trash(const char *item) {
2828  LiVESResponseType resp = LIVES_RESPONSE_NONE;
2829  boolean retval = TRUE;
2830  char *reason = NULL;
2831 #ifndef IMPL_TRASH
2832  do {
2833  resp = LIVES_RESPONSE_NONE;
2835  reason = lives_strdup_printf(_("%s was not found\n"), EXEC_GIO);
2836  retval = FALSE;
2837  }
2838  else {
2839  char *com = lives_strdup_printf("%s trash \"%s\"", EXEC_GIO, item);
2840  retval = mini_run(com);
2841  }
2842 #else
2843 
2851 
2855 
2858  // see: https://specifications.freedesktop.org/trash-spec/trashspec-latest.html
2859  int vnum = 0;
2860  char *trashdir;
2861  char *mp1 = get_mountpount_for(item);
2862  char *mp2 = get_mountpount_for(capable->home_dir);
2863  if (!lives_strcmp(mp1, mp2)) {
2864  char *localshare = lives_strdup(capable->xdg_data_home);
2865  if (!*localshare) {
2866  lives_free(localshare);
2867  localshare = lives_build_path(capable->home_dir, LOCAL_HOME_DIR, "share", NULL);
2868  }
2869  trashdir = lives_build_path(localshare, "Trash", NULL);
2870  trashinfodir = lives_build_path(trashdir, "info", NULL);
2871  trashfilesdir = lives_build_path(trashdir, "files", NULL);
2872  umask = capable->umask;
2873  capable->umask = 0700;
2874  if (!check_dir_access(trashinfodir, TRUE)) {
2875  retval = FALSE;
2876  reason = lives_strdup_printf(_("Could not write to %s\n"), trashinfodir);
2877  }
2878  if (retval) {
2879  if (!check_dir_access(trashfilesdir, TRUE)) {
2880  retval = FALSE;
2881  reason = lives_strdup_printf(_("Could not write to %s\n"), trashfilesdir);
2882  }
2883  }
2884  capable->umask = umask;
2885  if (retval) {
2886  char *trashinfo;
2887  int fd;
2888  while (1) {
2889  if (!vnum) trashinfo = lives_strdup_printf("%s.trashinfo", basenm);
2890  else trashinfo = lives_strdup_printf("%s.%d.trashinfo", basenm, vnum);
2891  fname = lives_build_filename(trashinfodir, trashinfo, NULL);
2892  fd = lives_open2(fname, O_CREAT | O_EXCL);
2893  if (fd) break;
2894  vnum++;
2895  }
2896  // TODO - write stuff, close, move item
2897 
2898 
2899  }
2900  }
2902 #endif
2903  if (!retval) {
2904  char *msg = lives_strdup_printf(_("LiVES was unable to send the item to trash.\n%s"), reason ? reason : "");
2905  lives_freep((void **)&reason);
2906  resp = do_abort_cancel_retry_dialog(msg);
2907  lives_free(msg);
2908  if (resp == LIVES_RESPONSE_CANCEL) return resp;
2909  }
2910  } while (resp == LIVES_RESPONSE_RETRY);
2911  return LIVES_RESPONSE_OK;
2912 }
2913 
2914 
2916 
2917 char *get_wid_for_name(const char *wname) {
2918 #ifndef GDK_WINDOWING_X11
2919  return NULL;
2920 #else
2921  char *wid = NULL, *cmd;
2922  if (!wname || !*wname) return NULL;
2923 
2925  cmd = lives_strdup_printf("%s -l", EXEC_WMCTRL);
2926  wid = grep_in_cmd(cmd, 3, 4, wname, 0, 1);
2927  lives_free(cmd);
2928  if (wid) return wid;
2929  }
2931  cmd = lives_strdup_printf("%s -name \"%s\" 2>/dev/null", EXEC_XWININFO, wname);
2932  wid = grep_in_cmd(cmd, 1, -1, "Window id:", 3, 1);
2933  lives_free(cmd);
2934  if (wid) return wid;
2935  }
2937  char buff[65536];
2938  size_t nlines;
2939  // returns a list, and we need to check each one
2940  cmd = lives_strdup_printf("%s search \"%s\"", EXEC_XDOTOOL, wname);
2941  lives_popen(cmd, FALSE, buff, 65536);
2942  lives_free(cmd);
2943  if (THREADVAR(com_failed)
2944  || (!*buff || !(nlines = get_token_count(buff, '\n')))) {
2945  if (THREADVAR(com_failed)) THREADVAR(com_failed) = FALSE;
2946  }
2947  else {
2948  char buff2[1024];
2949  char **lines = lives_strsplit(buff, "\n", nlines);
2950  for (int l = 0; l < nlines; l++) {
2951  if (!*lines[l]) continue;
2952  cmd = lives_strdup_printf("%s getwindowname %s", EXEC_XDOTOOL, lines[l]);
2953  lives_popen(cmd, FALSE, buff2, 1024);
2954  lives_free(cmd);
2955  if (THREADVAR(com_failed)) {
2956  THREADVAR(com_failed) = FALSE;
2957  break;
2958  }
2959  lives_chomp(buff2);
2960  if (!lives_strcmp(wname, buff2)) {
2961  wid = lives_strdup_printf("0x%lX", atol(lines[l]));
2962  break;
2963  }
2964  }
2965  lives_strfreev(lines);
2966  }
2967  }
2968  return wid;
2969 #endif
2970 }
2971 
2972 
2973 boolean hide_x11_window(const char *wid) {
2974  char *cmd = NULL;
2975 #ifndef GDK_WINDOWING_X11
2976  return NULL;
2977 #endif
2978  if (!wid) return FALSE;
2980  cmd = lives_strdup_printf("%s windowminimize \"%s\"", EXEC_XDOTOOL, wid);
2981  return mini_run(cmd);
2982  }
2983  return FALSE;
2984 }
2985 
2986 
2987 boolean unhide_x11_window(const char *wid) {
2988  char *cmd = NULL;
2989 #ifndef GDK_WINDOWING_X11
2990  return FALSE;
2991 #endif
2992  if (!wid) return FALSE;
2994  cmd = lives_strdup_printf("%s windowmap \"%s\"", EXEC_XDOTOOL, wid);
2995  return mini_run(cmd);
2996 }
2997 
2998 boolean activate_x11_window(const char *wid) {
2999  char *cmd = NULL;
3000 #ifndef GDK_WINDOWING_X11
3001  return FALSE;
3002 #endif
3003  if (!wid) return FALSE;
3004 
3005  if (capable->has_xdotool != MISSING) {
3007  cmd = lives_strdup_printf("%s windowactivate \"%s\"", EXEC_XDOTOOL, wid);
3008  }
3009  else if (capable->has_wmctrl != MISSING) {
3011  cmd = lives_strdup_printf("%s -Fa \"%s\"", EXEC_WMCTRL, wid);
3012  }
3013  else return FALSE;
3014  return mini_run(cmd);
3015 }
3016 
3017 
3018 boolean get_wm_caps(void) {
3019  char *wmname;
3020  if (capable->has_wm_caps) return TRUE;
3022 
3023 #if IS_MINGW
3025  capable->wm_caps.root_window = gdk_screen_get_root_window(mainw->mgeom[widget_opts.monitor].screen);
3026 #else
3027 #ifdef GUI_GTK
3028  capable->wm_caps.is_composited = gdk_screen_is_composited(mainw->mgeom[widget_opts.monitor].screen);
3029  capable->wm_caps.root_window = gdk_screen_get_root_window(mainw->mgeom[widget_opts.monitor].screen);
3030 #else
3032  capable->wm_caps.root_window = NULL;
3033 #endif
3034 #endif
3035 
3036  capable->wm_type = getenv(XDG_SESSION_TYPE);
3037 
3038  wmname = getenv(XDG_CURRENT_DESKTOP);
3039 
3040  if (!wmname) {
3041  if (capable->wm_name) wmname = capable->wm_name;
3042  }
3043  if (!wmname) return FALSE;
3044 
3046  lives_snprintf(capable->wm_caps.wm_name, 64, "%s", wmname);
3047 
3048  if (!strcmp(capable->wm_caps.wm_name, WM_XFWM4) || !strcmp(capable->wm_name, WM_XFWM4)) {
3049  lives_snprintf(capable->wm_caps.panel, 64, "%s", WM_XFCE4_PANEL);
3052  lives_snprintf(capable->wm_caps.ssave, 64, "%s", WM_XFCE4_SSAVE);
3053  lives_snprintf(capable->wm_caps.color_settings, 64, "%s", WM_XFCE4_COLOR);
3054  lives_snprintf(capable->wm_caps.display_settings, 64, "%s", WM_XFCE4_DISP);
3055  lives_snprintf(capable->wm_caps.ssv_settings, 64, "%s", WM_XFCE4_SSAVE);
3056  lives_snprintf(capable->wm_caps.pow_settings, 64, "%s", WM_XFCE4_POW);
3057  lives_snprintf(capable->wm_caps.settings, 64, "%s", WM_XFCE4_SETTINGS);
3058  lives_snprintf(capable->wm_caps.term, 64, "%s", WM_XFCE4_TERMINAL);
3059  lives_snprintf(capable->wm_caps.taskmgr, 64, "%s", WM_XFCE4_TASKMGR);
3060  lives_snprintf(capable->wm_caps.sshot, 64, "%s", WM_XFCE4_SSHOT);
3061  return TRUE;
3062  }
3063  if (!strcmp(capable->wm_caps.wm_name, WM_KWIN) || !strcmp(capable->wm_name, WM_KWIN)) {
3064  lives_snprintf(capable->wm_caps.panel, 64, "%s", WM_KWIN_PANEL);
3065  lives_snprintf(capable->wm_caps.ssave, 64, "%s", WM_KWIN_SSAVE);
3066  lives_snprintf(capable->wm_caps.color_settings, 64, "%s", WM_KWIN_COLOR);
3067  lives_snprintf(capable->wm_caps.display_settings, 64, "%s", WM_KWIN_DISP);
3068  lives_snprintf(capable->wm_caps.ssv_settings, 64, "%s", WM_KWIN_SSAVE);
3069  lives_snprintf(capable->wm_caps.pow_settings, 64, "%s", WM_KWIN_POW);
3070  lives_snprintf(capable->wm_caps.settings, 64, "%s", WM_KWIN_SETTINGS);
3071  lives_snprintf(capable->wm_caps.term, 64, "%s", WM_KWIN_TERMINAL);
3072  lives_snprintf(capable->wm_caps.taskmgr, 64, "%s", WM_KWIN_TASKMGR);
3073  lives_snprintf(capable->wm_caps.sshot, 64, "%s", WM_KWIN_SSHOT);
3074  return TRUE;
3075  }
3076  return FALSE;
3077 }
3078 
3079 
3080 int get_window_stack_level(LiVESXWindow *xwin, int *nwins) {
3081 #ifndef GUI_GTK
3082  if (nwins) *nwins = -1;
3083  return -1;
3084 #else
3085  int mywin = -1, i = 0;
3086  LiVESList *winlist = gdk_screen_get_window_stack(mainw->mgeom[widget_opts.monitor].screen), *list = winlist;
3087  for (; list; list = list->next, i++) {
3088  if ((LiVESXWindow *)list->data == xwin) mywin = i;
3089  lives_widget_object_unref(list->data);
3090  }
3091  lives_list_free(winlist);
3092  if (nwins) *nwins = ++i;
3093  return mywin;
3094 #endif
3095 }
3096 
3097 
3098 boolean show_desktop_panel(void) {
3099  boolean ret = FALSE;
3100 #ifdef GDK_WINDOWING_X11
3101  char *wid = get_wid_for_name(capable->wm_caps.panel);
3102  if (wid) {
3103  ret = unhide_x11_window(wid);
3104  lives_free(wid);
3105  }
3106 #endif
3107  return ret;
3108 }
3109 
3110 boolean hide_desktop_panel(void) {
3111  boolean ret = FALSE;
3112 #ifdef GDK_WINDOWING_X11
3113  char *wid = get_wid_for_name(capable->wm_caps.panel);
3114  if (wid) {
3115  ret = hide_x11_window(wid);
3116  lives_free(wid);
3117  }
3118 #endif
3119  return ret;
3120 }
3121 
3122 
3123 boolean get_x11_visible(const char *wname) {
3124  char *cmd = NULL;
3125 #ifndef GDK_WINDOWING_X11
3126  return FALSE;
3127 #endif
3128  if (!wname || !*wname) return FALSE;
3130  char *state;
3131  cmd = lives_strdup_printf("%s -name \"%s\"", EXEC_XWININFO, wname);
3132  state = grep_in_cmd(cmd, 2, -1, "Map State:", 4, 1);
3133  lives_free(cmd);
3134  if (state && !strcmp(state, "IsViewable")) {
3135  lives_free(state);
3136  return TRUE;
3137  }
3138  }
3140  char buff[65536];
3141  size_t nlines;
3142 
3143  // returns a list, and we need to check each one
3144  cmd = lives_strdup_printf("%s search --all --onlyvisible \"%s\" 2>/dev/null", EXEC_XDOTOOL, wname);
3145  lives_popen(cmd, FALSE, buff, 65536);
3146  lives_free(cmd);
3147  if (THREADVAR(com_failed)
3148  || (!*buff || !(nlines = get_token_count(buff, '\n')))) {
3149  if (THREADVAR(com_failed)) THREADVAR(com_failed) = FALSE;
3150  }
3151  else {
3152  char *wid = get_wid_for_name(wname);
3153  if (wid) {
3154  int l;
3155  char **lines = lives_strsplit(buff, "\n", nlines), *xwid;
3156  for (l = 0; l < nlines; l++) {
3157  if (!*lines[l]) continue;
3158  xwid = lives_strdup_printf("0x%08lX", atol(lines[l]));
3159  if (!strcmp(xwid, wid)) break;
3160  }
3161  lives_strfreev(lines);
3162  lives_free(wid);
3163  if (l < nlines) return TRUE;
3164  }
3165  }
3166  }
3167  return FALSE;
3168 }
3169 
3170 #define XTEMP "XXXXXXXXXX"
3171 
3172 static char *get_systmp_inner(const char *suff, boolean is_dir, const char *prefix) {
3178  char *res = NULL;
3179 
3180  if (!check_for_executable(&capable->has_mktemp, EXEC_MKTEMP)) return NULL;
3181  else {
3182  size_t slen;
3183  char *tmp, *com;
3184  const char *dirflg, *tmpopt;
3185  if (!prefix) {
3186  // no prefix, create in $TMPDIR
3187  if (suff) tmp = lives_strdup_printf("lives-%s-%s", XTEMP, suff);
3188  else tmp = lives_strdup_printf("lives-%s", XTEMP);
3189  tmpopt = "t";
3190  slen = lives_strlen(tmp) + 2;
3191  }
3192  else {
3194  char *tmpfile = lives_strdup_printf("%s%s", prefix, XTEMP);
3195  tmp = lives_build_filename(suff, tmpfile, NULL);
3196  lives_free(tmpfile);
3197  tmpopt = "";
3198  slen = lives_strlen(tmp);
3199  }
3200 
3201  if (is_dir) dirflg = "d";
3202  else dirflg = "";
3203 
3204  com = lives_strdup_printf("%s -n $(%s -q%s%s \"%s\")", capable->echo_cmd, EXEC_MKTEMP, tmpopt,
3205  dirflg, tmp);
3206  lives_free(tmp);
3207  res = mini_popen(com);
3208  if (!res) return NULL;
3209  if (THREADVAR(com_failed)) {
3210  lives_free(res);
3211  return NULL;
3212  }
3213  if (lives_strlen(res) < slen) {
3214  lives_free(res);
3215  return NULL;
3216  }
3217  }
3218  if (!lives_file_test(res, LIVES_FILE_TEST_EXISTS)
3219  || lives_file_test(res, LIVES_FILE_TEST_IS_SYMLINK)) {
3220  lives_free(res);
3221  return NULL;
3222  }
3223  if (is_dir) {
3224  if (!check_dir_access(res, FALSE)) {
3225  lives_free(res);
3226  return NULL;
3227  }
3228  }
3229  return res;
3230 }
3231 
3232 char *get_systmp(const char *suff, boolean is_dir) {
3233  return get_systmp_inner(suff, is_dir, NULL);
3234 }
3235 
3236 static char *_get_worktmp(const char *prefix, boolean is_dir) {
3237  char *dirname = NULL;
3238  char *tmpdir = get_systmp_inner(prefs->workdir, is_dir, prefix);
3239  if (tmpdir) {
3240  dirname = lives_path_get_basename(tmpdir);
3241  lives_free(tmpdir);
3242  }
3243  return dirname;
3244 }
3245 
3246 char *get_worktmp(const char *prefix) {
3247  if (!prefix) return NULL;
3248  return _get_worktmp(prefix, TRUE);
3249 }
3250 
3251 char *get_worktmpfile(const char *prefix) {
3252  if (!prefix) return NULL;
3253  return _get_worktmp(prefix, FALSE);
3254 }
3255 
3256 
3257 boolean check_snap(const char *prog) {
3258  // not working yet...
3260  char *com = lives_strdup_printf("%s find %s", EXEC_SNAP, prog);
3261  char *res = grep_in_cmd(com, 0, 1, prog, 0, 1);
3262  if (!res) return FALSE;
3263  lives_free(res);
3264  return TRUE;
3265 }
3266 
3267 
3268 boolean get_distro_dets(void) {
3269 #ifndef IS_LINUX
3270  capable->distro_name = lives_strdup(capable->os_name);
3271  capable->distro_ver = lives_strdup(capable->os_release);
3272 #else
3273 #define LSB_OS_FILE "/etc/lsb-release"
3274  char *com = lives_strdup_printf("%s %s", capable->cat_cmd, LSB_OS_FILE), *ret;
3275  if ((ret = mini_popen(com))) {
3276  int xlen = get_token_count(ret, '=');
3277  char **array = lives_strsplit(ret, "=", xlen);
3278  lives_free(ret);
3279  if (xlen > 1) {
3280  lives_strstop(array[1], '\n');
3281  capable->distro_name = lives_strdup(array[1]);
3282  if (xlen > 2) {
3283  lives_strstop(array[2], '\n');
3284  capable->distro_ver = lives_strdup(array[2]);
3285  if (xlen > 3) {
3286  lives_strstop(array[3], '\n');
3287  capable->distro_codename = lives_strdup(array[3]);
3288  }}}
3289  lives_strfreev(array);
3290  return TRUE;
3291  }
3292 #endif
3293  return FALSE;
3294 }
3295 
3296 
3297 int get_num_cpus(void) {
3298 #ifdef IS_DARWIN
3299  kerr = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO, &numProcessors, &processorInfo, &numProcessorInfo);
3300  if (kerr == KERN_SUCCESS) {
3301  vm_deallocate(mach_task_self(), (vm_address_t) processorInfo, numProcessorInfo * sizint);
3302  }
3303  return numProcessors;
3304 #else
3305  char buffer[1024];
3306  char command[PATH_MAX];
3307 #ifdef IS_FREEBSD
3308  lives_snprintf(command, PATH_MAX, "sysctl -n kern.smp.cpus");
3309 #else
3310  lives_snprintf(command, PATH_MAX, "%s processor /proc/cpuinfo 2>/dev/null | %s -l 2>/dev/null",
3312 #endif
3313  lives_popen(command, TRUE, buffer, 1024);
3314  return atoi(buffer);
3315 #endif
3316 }
3317 
3318 
3319 boolean get_machine_dets(void) {
3320 #ifdef IS_FREEBSD
3321  char *com = lives_strdup("sysctl -n hw.model");
3322 #else
3323  char *com = lives_strdup_printf("%s -m1 \"^model name\" /proc/cpuinfo | %s -e \"s/.*: //\" -e \"s:\\s\\+:/:g\"",
3325 #endif
3326  capable->cpu_name = mini_popen(com);
3327 
3328  com = lives_strdup("uname -o");
3329  capable->os_name = mini_popen(com);
3330 
3331  com = lives_strdup("uname -r");
3332  capable->os_release = mini_popen(com);
3333 
3334  com = lives_strdup("uname -m");
3335  capable->os_hardware = mini_popen(com);
3336 
3338 
3339 #if IS_X86_64
3340  if (!strcmp(capable->os_hardware, "x86_64")) capable->cacheline_size = get_cacheline_size();
3341 #endif
3342 
3343  com = lives_strdup("uname -n");
3344  capable->mach_name = mini_popen(com);
3345 
3346  com = lives_strdup("whoami");
3347  capable->username = mini_popen(com);
3348 
3349  if (THREADVAR(com_failed)) {
3350  THREADVAR(com_failed) = FALSE;
3351  return FALSE;
3352  }
3353  return TRUE;
3354 }
3355 
3356 
3357 #define DISK_STATS_FILE "/proc/diskstats"
3358 
3359 double get_disk_load(const char *mp) {
3360  if (!mp) return -1;
3361  else {
3362  static ticks_t lticks = 0;
3363  static uint64_t lval = 0;
3364  double ret = -1.;
3365  const char *xmp;
3366  char *com, *res;
3367  if (!lives_strncmp(mp, "/dev/", 5))
3368  xmp = (char *)mp + 5;
3369  else
3370  xmp = mp;
3371  com = lives_strdup_printf("%s -n $(%s %s %s)", capable->echo_cmd, capable->grep_cmd, xmp, DISK_STATS_FILE);
3372  if ((res = mini_popen(com))) {
3373  int xbits = get_token_count(res, ' ');
3374  char **array = lives_strsplit(res, " ", xbits);
3375  lives_free(res);
3376  if (xbits > 13) {
3377  uint64_t val = atoll(array[13]);
3378  ticks_t clock_ticks;
3379  if (LIVES_IS_PLAYING) clock_ticks = mainw->clock_ticks;
3380  else clock_ticks = lives_get_current_ticks();
3381  if (lticks > 0 && clock_ticks > lticks) ret = (double)(val - lval) / ((double)(clock_ticks - lticks)
3383  lticks = clock_ticks;
3384  lval = val;
3385  }
3386  lives_strfreev(array);
3387  }
3388  return ret;
3389  }
3390  return -1.;
3391 }
3392 
3393 
3394 #define CPU_STATS_FILE "/proc/stat"
3395 
3396 int64_t get_cpu_load(int cpun) {
3399  static uint64_t lidle = 0, lsum = 0;
3400  int64_t ret = -1;
3401  char *res, *target, *com;
3402  if (cpun > 0) target = lives_strdup_printf("cpu%d", --cpun);
3403  else if (cpun == 0) target = lives_strdup_printf("cpu");
3404  else target = lives_strdup_printf("btime");
3405  com = lives_strdup_printf("%s -n $(%s %s %s)", capable->echo_cmd, capable->grep_cmd, target, CPU_STATS_FILE);
3406  if ((res = mini_popen(com))) {
3407  int xbits = get_token_count(res, ' ');
3408  char **array = lives_strsplit(res, " ", xbits);
3409  lives_free(res);
3410  if (cpun == -1) {
3411  // get boot time
3412  if (xbits > 1) {
3413  ret = atoll(array[1]);
3414  }
3415  }
3416  else {
3417  if (xbits > 7) {
3418  uint64_t user = atoll(array[1]);
3419  uint64_t nice = atoll(array[2]);
3420  uint64_t sys = atoll(array[3]);
3421  uint64_t idle = atoll(array[4]);
3422  uint64_t iowait = atoll(array[5]);
3423  uint64_t irq = atoll(array[6]);
3424  uint64_t softirq = atoll(array[7]);
3425  uint64_t sum = user + nice + sys + idle + iowait + irq + softirq;
3426  if (lsum) {
3427  double load = 1. - (double)(idle - lidle) / (double)(sum - lsum);
3428  ret = load * (double)MILLIONS(1);
3429  }
3430  lsum = sum;
3431  lidle = idle;
3432  }
3433  lives_strfreev(array);
3434  }
3435  }
3436  return ret;
3437 }
lives_format_storage_space_string
char * lives_format_storage_space_string(uint64_t space)
Definition: machinestate.c:664
lives_freep
boolean lives_freep(void **ptr)
Definition: utils.c:1411
LIVES_GLOBAL_INLINE
#define LIVES_GLOBAL_INLINE
Definition: main.h:239
is_writeable_dir
boolean is_writeable_dir(const char *dir)
Definition: utils.c:5701
WEED_LEAF_DONE
#define WEED_LEAF_DONE
Definition: machinestate.h:412
funcsig_t
uint64_t funcsig_t
Definition: machinestate.h:453
BILLIONS
#define BILLIONS(n)
Definition: mainwindow.h:24
activate_x11_window
boolean activate_x11_window(const char *wid)
Definition: machinestate.c:2998
ANNOY_DISPLAY
#define ANNOY_DISPLAY
Definition: main.h:441
LIVES_IS_PLAYING
#define LIVES_IS_PLAYING
Definition: main.h:840
LIVES_LOCAL_INLINE
#define LIVES_LOCAL_INLINE
Definition: main.h:246
EFFORT_RANGE_MAX
#define EFFORT_RANGE_MAX
if set to TRUE during playback then a new frame (or possibly the current one) will be displayed ASAP
Definition: mainwindow.h:1770
WEED_LEAF_SIGNAL_DATA
#define WEED_LEAF_SIGNAL_DATA
Definition: machinestate.h:422
wm_caps_t::wm_name
char wm_name[64]
Definition: main.h:433
check_dir_access
boolean check_dir_access(const char *dir, boolean leaveit)
Definition: utils.c:4542
update_effort
void update_effort(int nthings, boolean badthings)
Definition: machinestate.c:2656
lives_proc_thread_cancelled
LIVES_GLOBAL_INLINE boolean lives_proc_thread_cancelled(lives_proc_thread_t tinfo)
Definition: machinestate.c:1971
fastrand_int
LIVES_GLOBAL_INLINE uint32_t fastrand_int(uint32_t range)
pick a pseudo random uint between 0 and range (inclusive)
Definition: machinestate.c:54
lives_thread_create
int lives_thread_create(lives_thread_t *thread, lives_thread_attr_t attr, lives_funcptr_t func, void *arg)
Definition: machinestate.c:2318
lives_proc_thread_get_cancellable
LIVES_GLOBAL_INLINE boolean lives_proc_thread_get_cancellable(lives_proc_thread_t tinfo)
Definition: machinestate.c:1942
lives_file_dets_t::md5sum
char * md5sum
Definition: machinestate.h:356
WM_KWIN_COLOR
#define WM_KWIN_COLOR
Definition: machinestate.h:597
lives_free
#define lives_free
Definition: machinestate.h:52
capability::ds_tot
int64_t ds_tot
Definition: main.h:609
WEED_LEAF_RETURN_VALUE
#define WEED_LEAF_RETURN_VALUE
Definition: machinestate.h:417
_item_to_file_details
void * _item_to_file_details(LiVESList **listp, const char *item, const char *orig_loc, uint64_t extra, int type)
create a list from a (sub)directory '.
Definition: machinestate.c:1227
lives_file_dets_t::name
char * name
Definition: machinestate.h:343
rprealloc
RPMALLOC_ALLOCATOR void * rprealloc(void *ptr, size_t size)
Reallocate the given block to at least the given size.
Definition: rpmalloc.c:2644
lives_malloc
#define lives_malloc
Definition: machinestate.h:46
WM_XFCE4_SSAVE
#define WM_XFCE4_SSAVE
Definition: machinestate.h:585
mainwindow::is_ready
boolean is_ready
Definition: mainwindow.h:787
get_worktmp
char * get_worktmp(const char *prefix)
Definition: machinestate.c:3246
lives_proc_thread_dontcare
boolean lives_proc_thread_dontcare(lives_proc_thread_t tinfo)
tell a threead with return value that we no longer need the value so it can free itself
Definition: machinestate.c:1953
capability::cpu_bits
short cpu_bits
Definition: main.h:583
CALL_1
#define CALL_1(ret, t1)
Definition: machinestate.h:502
mainwindow::mgeom
lives_mgeometry_t * mgeom
multi-head support
Definition: mainwindow.h:1576
lives_get_audio_file_name
LIVES_GLOBAL_INLINE char * lives_get_audio_file_name(int fnum)
Definition: audio.c:55
lives_10pow
uint64_t lives_10pow(int pow) GNU_CONST
Definition: utils.c:1438
FUNCSIG_PLANTP_BOOL
#define FUNCSIG_PLANTP_BOOL
get_wm_caps
boolean get_wm_caps(void)
Definition: machinestate.c:3018
lives_file_dets_t::atime_sec
uint64_t atime_sec
Definition: machinestate.h:350
FUNCSIG_STRING_STRING_VOIDP_INT_STRING_VOIDP
#define FUNCSIG_STRING_STRING_VOIDP_INT_STRING_VOIDP
WEED_LEAF_THREAD_CANCELLED
#define WEED_LEAF_THREAD_CANCELLED
Definition: machinestate.h:416
lives_sync
void lives_sync(int times)
Definition: utils.c:115
LIVES_STORAGE_STATUS_OVER_QUOTA
@ LIVES_STORAGE_STATUS_OVER_QUOTA
Definition: machinestate.h:187
USEC_TO_TICKS
#define USEC_TO_TICKS
multiplying factor uSec -> ticks_t (def. 100)
Definition: mainwindow.h:38
LIVES_LONGEST_TIMEOUT
#define LIVES_LONGEST_TIMEOUT
Definition: mainwindow.h:45
lives_proc_thread_signalled
LIVES_GLOBAL_INLINE int lives_proc_thread_signalled(lives_proc_thread_t tinfo)
Definition: machinestate.c:1926
lives_plant_new
LIVES_GLOBAL_INLINE weed_plant_t * lives_plant_new(int subtype)
Definition: machinestate.c:2266
lives_thread_data_create
lives_thread_data_t * lives_thread_data_create(uint64_t idx)
Definition: machinestate.c:2174
lives_proc_thread_signalled_idx
LIVES_GLOBAL_INLINE int64_t lives_proc_thread_signalled_idx(lives_proc_thread_t tinfo)
Definition: machinestate.c:1931
_prefs::workdir
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
fg_run_func
void * fg_run_func(lives_proc_thread_t lpt, void *retval)
Definition: machinestate.c:2045
FUNCSIG_VOIDP_DOUBLE
#define FUNCSIG_VOIDP_DOUBLE
LIVES_THRDATTR_WAIT_SYNC
#define LIVES_THRDATTR_WAIT_SYNC
Definition: machinestate.h:440
EXTRA_DETAILS_MD5SUM
#define EXTRA_DETAILS_MD5SUM
derived values
Definition: machinestate.h:336
EXTRA_DETAILS_EMPTY_DIRS
#define EXTRA_DETAILS_EMPTY_DIRS
Definition: machinestate.h:328
lives_datetime
char * lives_datetime(uint64_t secs, boolean use_local)
Definition: machinestate.c:860
ANNOY_FS
#define ANNOY_FS
Definition: main.h:449
EXTRA_DETAILS_CLIPHDR
#define EXTRA_DETAILS_CLIPHDR
Definition: machinestate.h:333
quick_free
void quick_free(void *p)
Definition: machinestate.c:626
mainwindow::current_file
int current_file
Definition: mainwindow.h:727
IS_VALID_CLIP
#define IS_VALID_CLIP(clip)
Definition: main.h:808
lives_string_hash
LIVES_GLOBAL_INLINE uint32_t lives_string_hash(const char *st)
Definition: machinestate.c:1585
LIVES_FILE_TYPE_FLAG_MISSING
#define LIVES_FILE_TYPE_FLAG_MISSING
Definition: mainwindow.h:459
EXEC_XWININFO
#define EXEC_XWININFO
Definition: mainwindow.h:422
fastrand_add
LIVES_GLOBAL_INLINE void fastrand_add(uint64_t entropy)
Definition: machinestate.c:47
get_storage_status
lives_storage_status_t get_storage_status(const char *dir, uint64_t warn_level, int64_t *dsval, int64_t ds_resvd)
Definition: machinestate.c:693
capability::os_release
char * os_release
Definition: main.h:613
WM_KWIN_TASKMGR
#define WM_KWIN_TASKMGR
Definition: machinestate.h:602
WM_XFCE4_COLOR
#define WM_XFCE4_COLOR
Definition: machinestate.h:586
LIVES_THRDATTR_PRIORITY
#define LIVES_THRDATTR_PRIORITY
Definition: machinestate.h:439
lives_realloc
#define lives_realloc
Definition: machinestate.h:49
cfile
#define cfile
Definition: main.h:1833
CALL_6
#define CALL_6(ret, t1, t2, t3, t4, t5, t6)
Definition: machinestate.h:497
lives_file_dets_t::extra_details
char * extra_details
only filled if EXTRA_DETAILS_MD5 is set, otherwis NULL
Definition: machinestate.h:357
lives_strdup_quick
LIVES_GLOBAL_INLINE char * lives_strdup_quick(const char *s)
Definition: machinestate.c:1484
capability::has_du
lives_checkstatus_t has_du
Definition: main.h:535
wm_caps_t::color_settings
char color_settings[64]
Definition: main.h:480
update_play_times
void update_play_times(void)
like get_play_times, but will force redraw of audio waveforms
Definition: utils.c:3677
EXEC_GZIP
#define EXEC_GZIP
Definition: mainwindow.h:407
CALL_3
#define CALL_3(ret, t1, t2, t3)
Definition: machinestate.h:500
capability::has_wmctrl
lives_checkstatus_t has_wmctrl
Definition: main.h:530
wm_caps_t::ssave
char ssave[64]
Definition: main.h:473
_ext_memcmp
int _ext_memcmp(const void *s1, const void *s2, size_t n)
Definition: machinestate.c:569
capability::cpu_name
char * cpu_name
Definition: main.h:582
lives_clip_t::frames
frames_t frames
number of video frames
Definition: main.h:890
lives_file_dets_t
Definition: machinestate.h:338
_ext_memmove
void * _ext_memmove(void *dest, const void *src, size_t n)
Definition: machinestate.c:573
CLIP_DETAILS_ACHANS
@ CLIP_DETAILS_ACHANS
Definition: main.h:1150
prefs
_prefs * prefs
Definition: preferences.h:847
lives_strcmp
LIVES_GLOBAL_INLINE boolean lives_strcmp(const char *st1, const char *st2)
returns FALSE if strings match
Definition: machinestate.c:1506
WM_XFCE4_SSHOT
#define WM_XFCE4_SSHOT
Definition: machinestate.h:592
wm_caps_t::is_composited
boolean is_composited
Definition: main.h:439
_ext_calloc
void * _ext_calloc(size_t nmemb, size_t msize)
Definition: machinestate.c:584
WM_XFCE4_POW
#define WM_XFCE4_POW
Definition: machinestate.h:588
lives_open2
int lives_open2(const char *pathname, int flags)
Definition: utils.c:99
RES_HIDE
#define RES_HIDE
Definition: main.h:456
capability::cat_cmd
char cat_cmd[PATH_MAX]
Definition: main.h:559
struct_from_template
void * struct_from_template(lives_struct_type st_type)
Definition: lsd-tab.c:76
LIVES_FILE_TYPE_FLAG_EXECUTABLE
#define LIVES_FILE_TYPE_FLAG_EXECUTABLE
Definition: mainwindow.h:454
PB_QUALITY_HIGH
#define PB_QUALITY_HIGH
Definition: preferences.h:34
is_layer_ready
#define is_layer_ready(layer)
Definition: main.h:1485
FUNCSIG_VOIDP_VOIDP_VOIDP
#define FUNCSIG_VOIDP_VOIDP_VOIDP
_prefs::disk_quota
uint64_t disk_quota
Definition: preferences.h:383
capability::has_mktemp
lives_checkstatus_t has_mktemp
Definition: main.h:540
EXTRA_DETAILS_EXECUTABLE
#define EXTRA_DETAILS_EXECUTABLE
Definition: machinestate.h:332
get_x11_visible
boolean get_x11_visible(const char *wname)
Definition: machinestate.c:3123
thrd_work_t
Definition: machinestate.h:401
lives_proc_thread_t
weed_plantptr_t lives_proc_thread_t
lives proc_threads API
Definition: machinestate.c:1670
EFFORT_LIMIT_MED
#define EFFORT_LIMIT_MED
default 32
Definition: mainwindow.h:1772
get_wid_for_name
char * get_wid_for_name(const char *wname)
x11 stuff
Definition: machinestate.c:2917
capability::mach_name
char * mach_name
Definition: main.h:620
FUNCSIG_STRING
#define FUNCSIG_STRING
FUNCSIG_DOUBLE
#define FUNCSIG_DOUBLE
capability::distro_codename
char * distro_codename
Definition: main.h:618
lives_alarm_clear
boolean lives_alarm_clear(lives_alarm_t alarm_handle)
Definition: utils.c:1732
WEED_LEAF_THREADFUNC
#define WEED_LEAF_THREADFUNC
Definition: machinestate.h:413
TICKS_PER_SECOND_DBL
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
Definition: mainwindow.h:37
swab8
LIVES_GLOBAL_INLINE void swab8(const void *from, const void *to, size_t gran)
Definition: machinestate.c:2483
make_nxttab
void make_nxttab(void)
Definition: machinestate.c:120
lives_random
LIVES_GLOBAL_INLINE uint64_t lives_random(void)
Definition: machinestate.c:58
lives_file_dets_t::size
off_t size
e.g. LIVES_FILE_TYPE_FILE
Definition: machinestate.h:345
lives_proc_thread_join_int64
LIVES_GLOBAL_INLINE int64_t lives_proc_thread_join_int64(lives_proc_thread_t tinfo)
Definition: machinestate.c:1990
get_token_count
size_t get_token_count(const char *string, int delim)
Definition: utils.c:5430
rpmalloc
RPMALLOC_ALLOCATOR void * rpmalloc(size_t size)
Allocate a memory block of at least the given size.
Definition: rpmalloc.c:2600
HASHROOT
#define HASHROOT
Definition: machinestate.c:1584
lives_file_buffer_t
Definition: main.h:1604
WM_KWIN_POW
#define WM_KWIN_POW
Definition: machinestate.h:599
CLIP_DETAILS_ASAMPS
@ CLIP_DETAILS_ASAMPS
Definition: main.h:1153
EXTRA_BYTES
#define EXTRA_BYTES
TODO - split into: memory, files, sysops, threads.
Definition: machinestate.h:16
reset_effort
void reset_effort(void)
Definition: machinestate.c:2642
lives_thread_join
uint64_t lives_thread_join(lives_thread_t work, void **retval)
Definition: machinestate.c:2376
fastrand
LIVES_GLOBAL_INLINE uint64_t fastrand(void)
Definition: machinestate.c:40
mini_popen
LIVES_LOCAL_INLINE char * mini_popen(char *cmd)
Definition: machinestate.c:2814
capability::os_name
char * os_name
Definition: main.h:612
CALL_4
#define CALL_4(ret, t1, t2, t3, t4)
Definition: machinestate.h:499
WEED_LEAF_NOTIFY
#define WEED_LEAF_NOTIFY
Definition: machinestate.h:411
lives_proc_thread_set_cancellable
LIVES_GLOBAL_INLINE void lives_proc_thread_set_cancellable(lives_proc_thread_t tinfo)
only threads with no return value can possibly be cancellable. For threads with a value,...
Definition: machinestate.c:1938
lives_alarm_t
int lives_alarm_t
Definition: mainwindow.h:696
lives_nanosleep
#define lives_nanosleep(nanosec)
Definition: machinestate.h:307
lives_file_dets_t::mode
uint64_t mode
Definition: machinestate.h:346
thrd_work_t::ret
void * ret
Definition: machinestate.h:407
thrd_work_t::func
lives_funcptr_t func
Definition: machinestate.h:402
lives_touch
int lives_touch(const char *tfile)
Definition: utils.c:4455
ticks_t
int64_t ticks_t
Definition: main.h:97
EXTRA_DETAILS_CHECK_MISSING
#define EXTRA_DETAILS_CHECK_MISSING
extras we can check for, may consume more time
Definition: machinestate.h:326
WM_XFCE4_PANEL
#define WM_XFCE4_PANEL
Definition: machinestate.h:584
capability::cacheline_size
int cacheline_size
Definition: main.h:584
CALL_2
#define CALL_2(ret, t1, t2)
Definition: machinestate.h:501
do_error_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
do_header_write_error
boolean do_header_write_error(int clip)
Definition: dialogs.c:4169
_ext_realloc
void * _ext_realloc(void *p, size_t n)
Definition: machinestate.c:575
_cpy_if_nonnull
#define _cpy_if_nonnull(d, s, size)
Definition: machinestate.c:527
OIL_MEMCPY_MAX_BYTES
#define OIL_MEMCPY_MAX_BYTES
susbtitute memory functions. These must be real functions and not #defines since we need fn pointers
Definition: machinestate.c:430
WEED_LEAF_DONTCARE_MUTEX
#define WEED_LEAF_DONTCARE_MUTEX
ensures we can set dontcare without it finishing while doing so
Definition: machinestate.h:419
create_nullvideo_clip
int create_nullvideo_clip(const char *handle)
Definition: saveplay.c:3808
WM_KWIN
#define WM_KWIN
Definition: machinestate.h:594
lives_get_randbytes
void lives_get_randbytes(void *ptr, size_t size)
Definition: machinestate.c:60
tv
struct timeval tv
Definition: main.h:1136
TRUE
#define TRUE
Definition: videoplugin.h:59
lives_datetime_rel
char * lives_datetime_rel(const char *datetime)
Definition: machinestate.c:842
get_md5sum
char * get_md5sum(const char *filename)
Definition: machinestate.c:646
sizint
ssize_t sizint
type sizes
Definition: main.c:102
lives_proc_thread_join_funcptr
LIVES_GLOBAL_INLINE weed_funcptr_t lives_proc_thread_join_funcptr(lives_proc_thread_t tinfo)
Definition: machinestate.c:1992
capability::umask
mode_t umask
Definition: main.h:597
capability::has_xdotool
lives_checkstatus_t has_xdotool
Definition: main.h:531
_prefs::nfx_threads
int nfx_threads
Definition: preferences.h:356
WM_KWIN_DISP
#define WM_KWIN_DISP
Definition: machinestate.h:598
lives_threadpool_init
void lives_threadpool_init(void)
Definition: machinestate.c:2280
lives_file_dets_t::type
uint64_t type
Definition: machinestate.h:344
LIVES_NO_ALARM
#define LIVES_NO_ALARM
lives_alarms
Definition: mainwindow.h:1632
get_disk_load
double get_disk_load(const char *mp)
Definition: machinestate.c:3359
lives_memset
#define lives_memset
Definition: machinestate.h:61
_ext_memset
void * _ext_memset(void *p, int i, size_t n)
Definition: machinestate.c:571
EXEC_GIO
#define EXEC_GIO
Definition: mainwindow.h:429
disk_monitor_running
boolean disk_monitor_running(const char *dir)
Definition: machinestate.c:715
DISK_STATS_FILE
#define DISK_STATS_FILE
Definition: machinestate.c:3357
free_fdets_list
void free_fdets_list(LiVESList **listp)
Definition: machinestate.c:1084
WM_XFWM4
#define WM_XFWM4
Definition: machinestate.h:583
hide_desktop_panel
boolean hide_desktop_panel(void)
Definition: machinestate.c:3110
LIVES_STORAGE_STATUS_WARNING
@ LIVES_STORAGE_STATUS_WARNING
Definition: machinestate.h:184
capability::has_gio
lives_checkstatus_t has_gio
Definition: main.h:537
LIVES_WEED_SUBTYPE_PROC_THREAD
#define LIVES_WEED_SUBTYPE_PROC_THREAD
Definition: machinestate.h:204
THREADVAR
#define THREADVAR(var)
Definition: machinestate.h:531
XDG_SESSION_TYPE
#define XDG_SESSION_TYPE
Definition: machinestate.h:606
lives_strcmp_ordered
LIVES_GLOBAL_INLINE int lives_strcmp_ordered(const char *st1, const char *st2)
Definition: machinestate.c:1531
get_dir_size
off_t get_dir_size(const char *dirname)
Definition: machinestate.c:1069
lives_file_dets_t::mtime_nsec
uint64_t mtime_nsec
Definition: machinestate.h:353
MISSING
@ MISSING
not yet implemented (TODO)
Definition: main.h:392
capability::has_wm_caps
boolean has_wm_caps
Definition: main.h:606
lives_mgeometry_t::screen
LiVESXScreen * screen
Definition: mainwindow.h:359
thrd_work_t::done
volatile uint64_t done
Definition: machinestate.h:406
lives_proc_thread_join_plantptr
LIVES_GLOBAL_INLINE weed_plantptr_t lives_proc_thread_join_plantptr(lives_proc_thread_t tinfo)
Definition: machinestate.c:1994
lives_clip_t::fps
double fps
Definition: main.h:893
get_frame_count
int get_frame_count(int idx, int xsize)
sets mainw->files[idx]->frames with current framecount
Definition: utils.c:3109
hasNulByte
#define hasNulByte(x)
each byte B can be thought of as a signed char, subtracting 1 sets bit 7 if B was <= 0,...
Definition: machinestate.c:1459
_prefs::quota_limit
double quota_limit
Definition: preferences.h:486
CANCEL_ERROR
@ CANCEL_ERROR
cancelled because of error
Definition: main.h:740
thrd_work_t::arg
void * arg
Definition: machinestate.h:403
WEED_LEAF_SIGNALLED
#define WEED_LEAF_SIGNALLED
Definition: machinestate.h:421
WEED_LEAF_THREAD_CANCELLABLE
#define WEED_LEAF_THREAD_CANCELLABLE
Definition: machinestate.h:415
RESTYPE_ACTION
#define RESTYPE_ACTION
Definition: main.h:462
dir_to_file_details
lives_proc_thread_t dir_to_file_details(LiVESList **listp, const char *dir, const char *orig_loc, uint64_t extra)
create a list from a (sub)directory '.
Definition: machinestate.c:1353
callbacks.h
disk_monitor_wait_result
LIVES_GLOBAL_INLINE int64_t disk_monitor_wait_result(const char *dir, ticks_t timeout)
Definition: machinestate.c:742
capable
capability * capable
Definition: main.h:627
LIVES_THRDATTR_FG_THREAD
#define LIVES_THRDATTR_FG_THREAD
Definition: machinestate.h:441
lives_proc_thread_create
lives_proc_thread_t lives_proc_thread_create(lives_thread_attr_t attr, lives_funcptr_t func, int return_type, const char *args_fmt,...)
create the specific plant which defines a background task to be run
Definition: machinestate.c:1730
WEED_PLANT_LIVES
#define WEED_PLANT_LIVES
Definition: machinestate.h:196
mainwindow::preview_rendering
boolean preview_rendering
Definition: mainwindow.h:758
lives_clip_t::name
char name[CLIP_NAME_MAXLEN]
the display name
Definition: main.h:922
EXEC_SNAP
#define EXEC_SNAP
Definition: mainwindow.h:431
quick_calloc
void * quick_calloc(size_t n, size_t s)
Definition: machinestate.c:628
getnulpos_be
#define getnulpos_be(nulmask)
Definition: machinestate.c:1464
ALL_USED
#define ALL_USED
Definition: mainwindow.h:192
lives_srandom
LIVES_GLOBAL_INLINE void lives_srandom(unsigned int seed)
Definition: machinestate.c:56
lives_file_dets_t::blk_size
uint64_t blk_size
Definition: machinestate.h:349
reget_afilesize_inner
off_t reget_afilesize_inner(int fileno)
Definition: machinestate.c:1001
wm_caps_t::pan_annoy
uint64_t pan_annoy
Definition: main.h:471
capability::ds_free
int64_t ds_free
Definition: main.h:609
get_num_cpus
int get_num_cpus(void)
Definition: machinestate.c:3297
rpaligned_calloc
RPMALLOC_ALLOCATOR void * rpaligned_calloc(size_t alignment, size_t num, size_t size)
Definition: rpmalloc.c:2675
reverse_buffer
boolean reverse_buffer(uint8_t *buff, size_t count, size_t chunk)
Definition: machinestate.c:2509
mainwindow::clock_ticks
volatile ticks_t clock_ticks
unadjusted system time since pb start, measured concurrently with currticks
Definition: mainwindow.h:1003
MILLIONS
#define MILLIONS(n)
Definition: mainwindow.h:26
lives_memcmp
#define lives_memcmp
Definition: machinestate.h:58
mainwindow::msg
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
lives_fg_run
void * lives_fg_run(lives_proc_thread_t lpt, void *retval)
Definition: widget-helper.c:1790
WM_XFCE4_TERMINAL
#define WM_XFCE4_TERMINAL
Definition: machinestate.h:590
unhide_x11_window
boolean unhide_x11_window(const char *wid)
Definition: machinestate.c:2987
mainwindow::wall_ticks
ticks_t wall_ticks
Definition: mainwindow.h:1004
swab4
LIVES_GLOBAL_INLINE void swab4(const void *from, const void *to, size_t gran)
Definition: machinestate.c:2462
init_thread_memfuncs
boolean init_thread_memfuncs(void)
Definition: machinestate.c:638
mainwindow::blend_palette
volatile int blend_palette
here we can store the details of the blend file at the insertion point, if nothing changes we can tar...
Definition: mainwindow.h:980
capability::sed_cmd
char sed_cmd[PATH_MAX]
Definition: main.h:561
mainwindow::scrap_file
int scrap_file
we throw odd sized frames here when recording in real time; used if a source is a generator or stream
Definition: mainwindow.h:874
get_systmp
char * get_systmp(const char *suff, boolean is_dir)
Definition: machinestate.c:3232
get_file_size
off_t get_file_size(int fd)
Definition: machinestate.c:943
cached_list_free
void cached_list_free(LiVESList **list)
Definition: utils.c:4881
mainwindow::dsu_valid
boolean dsu_valid
Definition: mainwindow.h:1791
rpfree
void rpfree(void *ptr)
Free the given memory block.
Definition: rpmalloc.c:2612
reverse_bytes
LIVES_GLOBAL_INLINE void reverse_bytes(char *buff, size_t count, size_t gran)
Definition: machinestate.c:2502
FUNCSIG_VOIDP
#define FUNCSIG_VOIDP
_future_prefs::pb_quality
short pb_quality
Definition: preferences.h:831
lives_clip_t::afilesize
size_t afilesize
Definition: main.h:912
getnulpos
#define getnulpos(nulmask)
Definition: machinestate.c:1460
wm_caps_t::ssv_settings
char ssv_settings[64]
Definition: main.h:482
capability::wm_caps
wm_caps_t wm_caps
Definition: main.h:607
WM_KWIN_TERMINAL
#define WM_KWIN_TERMINAL
Definition: machinestate.h:601
hide_x11_window
boolean hide_x11_window(const char *wid)
Definition: machinestate.c:2973
lives_fgets
char * lives_fgets(char *s, int size, FILE *stream)
Definition: utils.c:368
LIVES_FILE_TYPE_DIRECTORY
#define LIVES_FILE_TYPE_DIRECTORY
Definition: mainwindow.h:441
_ext_memcpy
void * _ext_memcpy(void *dest, const void *src, size_t n)
Definition: machinestate.c:567
mainwindow::files
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
WM_KWIN_SSHOT
#define WM_KWIN_SSHOT
Definition: machinestate.h:603
LIVES_THRDATTR_AUTODELETE
#define LIVES_THRDATTR_AUTODELETE
Definition: machinestate.h:438
save_clip_value
boolean save_clip_value(int which, lives_clip_details_t, void *val)
Definition: utils.c:5175
WEED_LEAF_DONTCARE
#define WEED_LEAF_DONTCARE
tell proc_thread with return value that we n o longer need return val.
Definition: machinestate.h:418
LIVES_FILE_TYPE_FLAG_EMPTY
#define LIVES_FILE_TYPE_FLAG_EMPTY
Definition: mainwindow.h:458
widget_opts_t::monitor
int monitor
monitor we are displaying on
Definition: widget-helper.h:1437
main_thread_execute
void * main_thread_execute(lives_funcptr_t func, int return_type, void *retval, const char *args_fmt,...)
Definition: machinestate.c:1741
CANCEL_NONE
@ CANCEL_NONE
no cancel
Definition: main.h:701
autotune_u64
void autotune_u64(weed_plant_t *tuner, uint64_t min, uint64_t max, int ntrials, double cost)
Definition: machinestate.c:182
EXTRA_DETAILS_SYMLINK
#define EXTRA_DETAILS_SYMLINK
Definition: machinestate.h:329
mainwindow::first_free_file
int first_free_file
Definition: mainwindow.h:728
WM_XFCE4_TASKMGR
#define WM_XFCE4_TASKMGR
Definition: machinestate.h:591
lives_strstop
LIVES_GLOBAL_INLINE char * lives_strstop(char *st, const char term)
Definition: machinestate.c:1634
wm_caps_t::root_window
LiVESXWindow * root_window
Definition: main.h:438
init_memfuncs
boolean init_memfuncs(void)
Definition: machinestate.c:630
capability::wc_cmd
char wc_cmd[PATH_MAX]
Definition: main.h:562
FUNCSIG_INT_INT_BOOL_VOIDP
#define FUNCSIG_INT_INT_BOOL_VOIDP
FUNCSIG_STRING_STRING_VOIDP_INT
#define FUNCSIG_STRING_STRING_VOIDP_INT
rpmalloc_thread_finalize
void rpmalloc_thread_finalize(void)
Finalize thread, orphan heap.
Definition: rpmalloc.c:2577
sget_file_size
off_t sget_file_size(const char *name)
Definition: machinestate.c:962
check_dev_busy
boolean check_dev_busy(char *devstr)
Definition: machinestate.c:876
widget_opts_t::non_modal
boolean non_modal
non-modal for dialogs
Definition: widget-helper.h:1422
check_for_executable
boolean check_for_executable(lives_checkstatus_t *cap, const char *exec)
Definition: utils.c:3434
FUNCSIG_VOIDP_VOIDP
#define FUNCSIG_VOIDP_VOIDP
show_desktop_panel
boolean show_desktop_panel(void)
Definition: machinestate.c:3098
get_distro_dets
boolean get_distro_dets(void)
Definition: machinestate.c:3268
CLIP_DETAILS_ARATE
@ CLIP_DETAILS_ARATE
Definition: main.h:1148
lives_get_current_ticks
LIVES_GLOBAL_INLINE ticks_t lives_get_current_ticks(void)
Definition: machinestate.c:835
capability::os_hardware
char * os_hardware
Definition: main.h:614
LIVES_FILE_TYPE_UNKNOWN
#define LIVES_FILE_TYPE_UNKNOWN
Definition: mainwindow.h:437
lives_file_dets_t::mtime_sec
uint64_t mtime_sec
Definition: machinestate.h:352
lives_thread_attr_t
uint64_t lives_thread_attr_t
Definition: machinestate.h:435
CALL_VOID_4
#define CALL_VOID_4(t1, t2, t3, t4)
Definition: machinestate.h:483
lives_clip_t::arps
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
Definition: main.h:905
LIVES_THRDFLAG_WAIT_SYNC
#define LIVES_THRDFLAG_WAIT_SYNC
Definition: machinestate.h:432
EFFORT_LIMIT_LOW
#define EFFORT_LIMIT_LOW
default 8
Definition: mainwindow.h:1771
lives_rmdir
int lives_rmdir(const char *dir, boolean force)
Definition: utils.c:4366
lives_strdup_printf
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
WEED_LEAF_INDEX
#define WEED_LEAF_INDEX
Definition: events.h:58
lives_proc_thread_join_voidptr
LIVES_GLOBAL_INLINE void * lives_proc_thread_join_voidptr(lives_proc_thread_t tinfo)
Definition: machinestate.c:1993
CALL_VOID_1
#define CALL_VOID_1(t1)
Definition: machinestate.h:486
lives_calloc
#define lives_calloc
Definition: machinestate.h:67
lives_clip_t::opening
boolean opening
Definition: main.h:946
wm_caps_t::pow_settings
char pow_settings[64]
Definition: main.h:483
DU_BLOCKSIZE
#define DU_BLOCKSIZE
Definition: machinestate.c:1066
WM_XFCE4_SETTINGS
#define WM_XFCE4_SETTINGS
Definition: machinestate.h:589
get_worktmpfile
char * get_worktmpfile(const char *prefix)
Definition: machinestate.c:3251
get16bits
#define get16bits(d)
Definition: machinestate.c:1594
lives_list_free_all
void lives_list_free_all(LiVESList **)
Definition: utils.c:4873
LIVES_FILE_TYPE_FLAG_SYMLINK
#define LIVES_FILE_TYPE_FLAG_SYMLINK
Definition: mainwindow.h:453
capability::distro_ver
char * distro_ver
Definition: main.h:617
get_mountpoint_for
char * get_mountpoint_for(const char *dir)
Definition: machinestate.c:1030
lives_clip_t::hsize
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
Definition: main.h:896
mainwindow::is_rendering
boolean is_rendering
Definition: mainwindow.h:821
read_headers
boolean read_headers(int clipno, const char *dir, const char *file_name)
Definition: saveplay.c:4465
get_ds_free
uint64_t get_ds_free(const char *dir)
Definition: machinestate.c:776
FUNCSIG_STRING_BOOL
#define FUNCSIG_STRING_BOOL
lives_file_dets_t::ctime_nsec
uint64_t ctime_nsec
Definition: machinestate.h:355
LIVES_THRDATTR_NONE
#define LIVES_THRDATTR_NONE
Definition: machinestate.h:437
thrd_work_t::flags
uint64_t flags
Definition: machinestate.h:404
LIVES_STRUCT_FILE_DETS_T
@ LIVES_STRUCT_FILE_DETS_T
Definition: lsd-tab.h:13
mainwindow::ascrap_file
int ascrap_file
scrap file for recording audio scraps
Definition: mainwindow.h:875
PB_QUALITY_MED
#define PB_QUALITY_MED
default
Definition: preferences.h:33
lives_file_dets_t::uid
uint64_t uid
Definition: machinestate.h:347
lives_proc_thread_check
LIVES_GLOBAL_INLINE boolean lives_proc_thread_check(lives_proc_thread_t tinfo)
returns FALSE while the thread is running, TRUE once it has finished
Definition: machinestate.c:1916
nxtval
uint64_t nxtval(uint64_t val, uint64_t lim, boolean less)
Definition: machinestate.c:198
grep_in_cmd
char * grep_in_cmd(const char *cmd, int mstart, int npieces, const char *mphrase, int ridx, int rlen)
Definition: machinestate.c:2754
EXEC_MKTEMP
#define EXEC_MKTEMP
Definition: mainwindow.h:430
WM_XFCE4_DISP
#define WM_XFCE4_DISP
Definition: machinestate.h:587
send_to_trash
LiVESResponseType send_to_trash(const char *item)
Definition: machinestate.c:2827
lives_memmove
#define lives_memmove
Definition: machinestate.h:64
CALL_VOID_0
#define CALL_VOID_0()
Definition: machinestate.h:487
_ext_free_and_return
void * _ext_free_and_return(void *p)
Definition: machinestate.c:565
lives_memcpy
#define lives_memcpy
Definition: machinestate.h:55
wm_caps_t::settings
char settings[64]
Definition: main.h:484
lives_strlen
LIVES_GLOBAL_INLINE size_t lives_strlen(const char *s)
Definition: machinestate.c:1468
future_prefs
_future_prefs * future_prefs
Definition: preferences.h:848
capability::wm_type
char * wm_type
window manager type, e.g. x11
Definition: main.h:604
lives_popen
ssize_t lives_popen(const char *com, boolean allow_error, char *buff, ssize_t buflen)
Definition: utils.c:194
lives_strappend
LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew)
Definition: machinestate.c:1436
LIVES_THRDFLAG_AUTODELETE
#define LIVES_THRDFLAG_AUTODELETE
Definition: machinestate.h:430
LIVES_FILENAME_NOREMOVE
#define LIVES_FILENAME_NOREMOVE
Definition: mainwindow.h:577
capability::home_dir
char home_dir[PATH_MAX]
home directory - default location for config file - locale encoding
Definition: main.h:544
CALL_VOID_6
#define CALL_VOID_6(t1, t2, t3, t4, t5, t6)
Definition: machinestate.h:481
wm_caps_t::pan_res
uint64_t pan_res
Definition: main.h:472
mainwindow::hdrs_cache
LiVESList * hdrs_cache
cache of a file header (e.g. header.lives)
Definition: mainwindow.h:1518
lives_getuid
LIVES_GLOBAL_INLINE int lives_getuid(void)
Definition: machinestate.c:2416
mainwindow::multitrack
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
wm_caps_t::taskmgr
char taskmgr[64]
Definition: main.h:486
lives_alarm_check
ticks_t lives_alarm_check(lives_alarm_t alarm_handle)
Definition: utils.c:1687
lives_threadpool_finish
void lives_threadpool_finish(void)
Definition: machinestate.c:2295
wm_caps_t::term
char term[64]
Definition: main.h:485
_ext_malloc_and_copy
void * _ext_malloc_and_copy(size_t bsize, const void *block)
Definition: machinestate.c:539
disk_monitor_forget
void disk_monitor_forget(void)
Definition: machinestate.c:769
_RV_
#define _RV_
Definition: machinestate.h:451
disk_monitor_start
lives_proc_thread_t disk_monitor_start(const char *dir)
Definition: machinestate.c:717
capability::has_xwininfo
lives_checkstatus_t has_xwininfo
Definition: main.h:524
check_snap
boolean check_snap(const char *prog)
Definition: machinestate.c:3257
DEF_ALIGN
#define DEF_ALIGN
Definition: main.h:629
LOCAL_HOME_DIR
#define LOCAL_HOME_DIR
Definition: mainwindow.h:604
lives_free_and_return
LIVES_GLOBAL_INLINE void * lives_free_and_return(void *p)
TODO: this file should be split into at least: memory functions, thread functions,...
Definition: machinestate.c:593
main.h
make_image_file_name
char * make_image_file_name(lives_clip_t *clip, frames_t frame, const char *img_ext)
lives_image_type can be a string, lives_img_type_t is an enumeration
Definition: utils.c:3053
thrd_work_t::sync_ready
volatile boolean sync_ready
Definition: machinestate.h:408
fast_hash
LIVES_GLOBAL_INLINE uint32_t fast_hash(const char *key)
Definition: machinestate.c:1596
wm_caps_t::panel
char panel[64]
Definition: main.h:470
capability::username
char * username
Definition: main.h:595
LIVES_STORAGE_STATUS_NORMAL
@ LIVES_STORAGE_STATUS_NORMAL
Definition: machinestate.h:183
WM_KWIN_SETTINGS
#define WM_KWIN_SETTINGS
Definition: machinestate.h:600
lives_strtrim
LIVES_GLOBAL_INLINE char * lives_strtrim(const char *buff)
Definition: machinestate.c:1651
capability::wm_name
char * wm_name
window manager name, may be different from wm_caps.wwm_name
Definition: main.h:605
fastrand_dbl
LIVES_GLOBAL_INLINE double fastrand_dbl(double range)
Definition: machinestate.c:49
lives_file_dets_t::ctime_sec
uint64_t ctime_sec
Definition: machinestate.h:354
FUNCSIG_PLANTP_VOIDP_INT64
#define FUNCSIG_PLANTP_VOIDP_INT64
mainwindow::effort
int effort
Definition: mainwindow.h:1773
sig
#define sig(a)
Definition: main.h:268
mainw
mainwindow * mainw
Definition: main.c:103
is_empty_dir
boolean is_empty_dir(const char *dirname)
Definition: machinestate.c:1013
get_image_ext_for_type
const char * get_image_ext_for_type(lives_img_type_t imgtype)
Definition: utils.c:3025
autotune_u64_end
uint64_t autotune_u64_end(weed_plant_t **tuner, uint64_t val)
Definition: machinestate.c:259
capability::echo_cmd
char echo_cmd[PATH_MAX]
Definition: main.h:563
LIVES_FATAL
#define LIVES_FATAL(x)
Definition: main.h:1886
lives_chdir
int lives_chdir(const char *path, boolean no_error_dlg)
Definition: utils.c:1393
lives_file_buffer_t::offset
off_t offset
ptr to data (ptr - buffer + bytes) gives the read size
Definition: main.h:1608
NCYCS
#define NCYCS
Definition: machinestate.c:196
FUNCSIG_INT_INT_INT_BOOL_VOIDP
#define FUNCSIG_INT_INT_INT_BOOL_VOIDP
CPU_STATS_FILE
#define CPU_STATS_FILE
Definition: machinestate.c:3394
check_for_bad_ffmpeg
int check_for_bad_ffmpeg(void)
Definition: machinestate.c:1382
ALIGN_DEF
#define ALIGN_DEF
Definition: colourspace.h:32
mainwindow::frame_layer_preload
weed_plant_t * frame_layer_preload
predictive caching apparatus
Definition: mainwindow.h:954
CLIP_DETAILS_PB_ARATE
@ CLIP_DETAILS_PB_ARATE
Definition: main.h:1149
PB_QUALITY_LOW
#define PB_QUALITY_LOW
Definition: preferences.h:32
lives_system
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
lives_storage_status_t
lives_storage_status_t
disk/storage status values
Definition: machinestate.h:181
rpmalloc_is_thread_initialized
int rpmalloc_is_thread_initialized(void)
Query if allocator is initialized for calling thread.
Definition: rpmalloc.c:2588
lives_proc_thread_join_int
LIVES_GLOBAL_INLINE int lives_proc_thread_join_int(lives_proc_thread_t tinfo)
Definition: machinestate.c:1987
lives_file_buffer_t::read
boolean read
Definition: main.h:1612
reget_afilesize
void reget_afilesize(int fileno)
Definition: machinestate.c:972
_join
#define _join(stype)
Definition: machinestate.c:1976
lives_chomp
LIVES_GLOBAL_INLINE char * lives_chomp(char *buff)
Definition: machinestate.c:1641
lives_proc_thread_join_string
LIVES_GLOBAL_INLINE char * lives_proc_thread_join_string(lives_proc_thread_t tinfo)
Definition: machinestate.c:1991
CALL_VOID_3
#define CALL_VOID_3(t1, t2, t3)
Definition: machinestate.h:484
lives_proc_thread_join_double
LIVES_GLOBAL_INLINE double lives_proc_thread_join_double(lives_proc_thread_t tinfo)
Definition: machinestate.c:1988
rpmalloc_thread_collect
void rpmalloc_thread_collect(void)
Perform deferred deallocations pending for the calling thread heap.
Definition: rpmalloc.c:2720
ONE_BILLION
#define ONE_BILLION
Definition: mainwindow.h:25
gen_unique_id
uint64_t gen_unique_id(void)
Definition: machinestate.c:68
CALL_VOID_5
#define CALL_VOID_5(t1, t2, t3, t4, t5)
Definition: machinestate.h:482
TICKS_TO_NANOSEC
#define TICKS_TO_NANOSEC
Definition: mainwindow.h:39
lives_funcptr_t
void *(* lives_funcptr_t)(void *)
Definition: machinestate.h:378
mainwindow::log_fd
int log_fd
Definition: mainwindow.h:1629
EXEC_DU
#define EXEC_DU
Definition: mainwindow.h:408
_prefs::pb_quality
short pb_quality
Definition: preferences.h:31
stat_to_file_dets
int stat_to_file_dets(const char *fname, lives_file_dets_t *fdets)
Definition: machinestate.c:1099
init_random
void init_random()
Definition: machinestate.c:92
get_window_stack_level
int get_window_stack_level(LiVESXWindow *xwin, int *nwins)
Definition: machinestate.c:3080
widget_opts
widget_opts_t widget_opts
Definition: widget-helper.h:1442
WEED_LEAF_THREAD_PARAM
#define WEED_LEAF_THREAD_PARAM
Definition: machinestate.h:424
XTEMP
#define XTEMP
Definition: machinestate.c:3170
lives_clip_t::vsize
int vsize
frame height (vertical) in pixels
Definition: main.h:897
PATH_MAX
#define PATH_MAX
Definition: main.h:255
get_threadvars
LIVES_GLOBAL_INLINE lives_threadvars_t * get_threadvars(void)
Definition: machinestate.c:2156
do_something_useful
boolean do_something_useful(lives_thread_data_t *tdata)
Definition: machinestate.c:2194
wm_caps_t::display_settings
char display_settings[64]
Definition: main.h:481
LIVES_WEED_SUBTYPE_TUNABLE
#define LIVES_WEED_SUBTYPE_TUNABLE
Definition: machinestate.h:203
lives_clip_t
corresponds to one clip in the GUI
Definition: main.h:877
lives_concat_sep
LIVES_GLOBAL_INLINE char * lives_concat_sep(char *st, const char *sep, char *x)
Definition: machinestate.c:1412
CALL_0
#define CALL_0(ret)
Definition: machinestate.h:503
lives_proc_thread_join_boolean
LIVES_GLOBAL_INLINE int lives_proc_thread_join_boolean(lives_proc_thread_t tinfo)
Definition: machinestate.c:1989
disk_monitor_check_result
int64_t disk_monitor_check_result(const char *dir)
Definition: machinestate.c:726
CALL_VOID_2
#define CALL_VOID_2(t1, t2)
Definition: machinestate.h:485
FUNCSIG_INT_INT64
#define FUNCSIG_INT_INT64
lives_calloc_safety
LIVES_GLOBAL_INLINE void * lives_calloc_safety(size_t nmemb, size_t xsize)
Definition: machinestate.c:603
FUNCSIG_INT
#define FUNCSIG_INT
lives_file_dets_t::lsd
lives_struct_def_t * lsd
Definition: machinestate.h:342
mainwindow::pred_frame
frames64_t pred_frame
Definition: mainwindow.h:955
FUNCSIG_STRING_INT
#define FUNCSIG_STRING_INT
lives_file_dets_t::atime_nsec
uint64_t atime_nsec
Definition: machinestate.h:351
lives_proc_thread_free
LIVES_GLOBAL_INLINE void lives_proc_thread_free(lives_proc_thread_t lpt)
Definition: machinestate.c:1672
LIVES_FILE_IS_DIRECTORY
#define LIVES_FILE_IS_DIRECTORY(ftype)
Definition: mainwindow.h:465
FUNCSIG_VOIDP_STRING_STRING_INT64_INT
#define FUNCSIG_VOIDP_STRING_STRING_INT64_INT
do_abort_cancel_retry_dialog
LIVES_GLOBAL_INLINE LiVESResponseType do_abort_cancel_retry_dialog(const char *text)
Definition: dialogs.c:708
lives_nanosleep_until_nonzero
#define lives_nanosleep_until_nonzero(condition)
Definition: machinestate.h:310
wm_caps_t::sshot
char sshot[64]
Definition: main.h:487
lives_file_buffer_t::bytes
ssize_t bytes
Definition: main.h:1605
ONE_MILLION
#define ONE_MILLION
Definition: mainwindow.h:27
mini_run
LIVES_LOCAL_INLINE boolean mini_run(char *cmd)
Definition: machinestate.c:2806
LIVES_STORAGE_STATUS_OVERFLOW
@ LIVES_STORAGE_STATUS_OVERFLOW
Definition: machinestate.h:186
XDG_CURRENT_DESKTOP
#define XDG_CURRENT_DESKTOP
Definition: machinestate.h:605
capability::has_gzip
lives_checkstatus_t has_gzip
Definition: main.h:526
WM_KWIN_SSAVE
#define WM_KWIN_SSAVE
Definition: machinestate.h:596
thrd_work_t::busy
volatile uint64_t busy
Definition: machinestate.h:405
capability::xdg_data_home
char * xdg_data_home
Definition: main.h:548
find_in_file_buffers
lives_file_buffer_t * find_in_file_buffers(int fd)
Definition: utils.c:401
lives_file_dets_t::gid
uint64_t gid
userid as uint64_t
Definition: machinestate.h:348
FUNCSIG_VOID
#define FUNCSIG_VOID
lives_proc_thread_cancel
LIVES_GLOBAL_INLINE boolean lives_proc_thread_cancel(lives_proc_thread_t tinfo)
Definition: machinestate.c:1946
lives_clip_t::asampsize
int asampsize
audio sample size in bits (8 or 16)
Definition: main.h:908
get_thread_data
lives_thread_data_t * get_thread_data(void)
Definition: machinestate.c:2145
lives_widget_object_unref
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_unref(livespointer object)
decrease refcount by one: if refcount==0, object is destroyed
Definition: widget-helper.c:815
capability::distro_name
char * distro_name
Definition: main.h:616
_ext_free
void _ext_free(void *p)
Definition: machinestate.c:556
lives_plant_new_with_index
LIVES_GLOBAL_INLINE weed_plant_t * lives_plant_new_with_index(int subtype, int64_t index)
Definition: machinestate.c:2273
WEED_LEAF_LIVES_SUBTYPE
#define WEED_LEAF_LIVES_SUBTYPE
Definition: machinestate.h:198
get_max_align
LIVES_GLOBAL_INLINE size_t get_max_align(size_t req_size, size_t align_max)
Definition: machinestate.c:596
lives_getgid
LIVES_GLOBAL_INLINE int lives_getgid(void)
Definition: machinestate.c:2420
lives_proc_thread_join
LIVES_GLOBAL_INLINE void lives_proc_thread_join(lives_proc_thread_t tinfo)
Definition: machinestate.c:1979
allfunc_t
Definition: machinestate.h:505
SECS_IN_DAY
#define SECS_IN_DAY
Definition: machinestate.c:841
lives_getpid
LIVES_GLOBAL_INLINE pid_t lives_getpid(void)
Definition: machinestate.c:2408
rpmalloc_initialize
int rpmalloc_initialize(void)
Initialize the allocator and setup global data.
Definition: rpmalloc.c:2318
LIVES_STORAGE_STATUS_UNKNOWN
@ LIVES_STORAGE_STATUS_UNKNOWN
Definition: machinestate.h:182
DEF_FILE_PERMS
#define DEF_FILE_PERMS
non-executable, is modified by the umask
Definition: main.h:209
lives_clip_t::arate
int arate
current audio playback rate (varies if the clip rate is changed)
Definition: main.h:906
lives_thread_t
LiVESList lives_thread_t
Definition: machinestate.h:434
LIVES_THRDATTR_NO_GUI
#define LIVES_THRDATTR_NO_GUI
Definition: machinestate.h:442
LIVES_STORAGE_STATUS_CRITICAL
@ LIVES_STORAGE_STATUS_CRITICAL
Definition: machinestate.h:185
EXEC_MD5SUM
#define EXEC_MD5SUM
Definition: mainwindow.h:405
lives_threadvars_t
Definition: machinestate.h:382
FALSE
#define FALSE
Definition: videoplugin.h:60
EXTRA_DETAILS_DIRSIZE
#define EXTRA_DETAILS_DIRSIZE
Definition: machinestate.h:327
lives_strappendf
LIVES_GLOBAL_INLINE const char * lives_strappendf(const char *string, int len, const char *fmt,...)
Definition: machinestate.c:1444
get_machine_dets
boolean get_machine_dets(void)
Definition: machinestate.c:3319
capability::grep_cmd
char grep_cmd[PATH_MAX]
Definition: main.h:560
WM_KWIN_PANEL
#define WM_KWIN_PANEL
Definition: machinestate.h:595
lives_alarm_set
lives_alarm_t lives_alarm_set(ticks_t ticks)
set alarm for now + delta ticks (10 nanosec) param ticks (10 nanoseconds) is the offset when we want ...
Definition: utils.c:1643
_
#define _(String)
Definition: support.h:44
MINPOOLTHREADS
#define MINPOOLTHREADS
Definition: machinestate.c:2128
capability::byte_order
int byte_order
Definition: main.h:577
capability::has_snap
lives_checkstatus_t has_snap
Definition: main.h:541
lives_rm
int lives_rm(const char *file)
Definition: utils.c:4395
get_cpu_load
int64_t get_cpu_load(int cpun)
percent * 1 million
Definition: machinestate.c:3396
resubmit_proc_thread
void resubmit_proc_thread(lives_proc_thread_t thread_info, lives_thread_attr_t attr)
(re)submission point, the function call is added to the threadpool tasklist if we have sufficient thr...
Definition: machinestate.c:2106
lives_proc_thread_sync_ready
LIVES_GLOBAL_INLINE void lives_proc_thread_sync_ready(lives_proc_thread_t tinfo)
Definition: machinestate.c:1911
lives_concat
LIVES_GLOBAL_INLINE char * lives_concat(char *st, char *x)
Definition: machinestate.c:1426
lives_clip_t::achans
int achans
number of audio channels (0, 1 or 2)
Definition: main.h:907
swab2
LIVES_GLOBAL_INLINE void swab2(const void *from, const void *to, size_t gran)
Definition: machinestate.c:2448
EXEC_XDOTOOL
#define EXEC_XDOTOOL
Definition: mainwindow.h:427
ordfile_to_file_details
lives_proc_thread_t ordfile_to_file_details(LiVESList **listp, const char *ofname, const char *orig_loc, uint64_t extra)
Definition: machinestate.c:1360
lives_get_relative_ticks
LIVES_GLOBAL_INLINE ticks_t lives_get_relative_ticks(ticks_t origsecs, ticks_t orignsecs)
Definition: machinestate.c:813
lives_strncmp
LIVES_GLOBAL_INLINE boolean lives_strncmp(const char *st1, const char *st2, size_t len)
returns FALSE if strings match
Definition: machinestate.c:1554
_ext_malloc
void * _ext_malloc(size_t n)
Definition: machinestate.c:530
_ext_unmalloc_and_copy
void _ext_unmalloc_and_copy(size_t bsize, void *p)
Definition: machinestate.c:547
MAINW_MSG_SIZE
#define MAINW_MSG_SIZE
mainw->msg bytesize
Definition: mainwindow.h:702
compress_files_in_dir
boolean compress_files_in_dir(const char *dir, int method, void *data)
Definition: machinestate.c:898
lives_recalloc
LIVES_GLOBAL_INLINE void * lives_recalloc(void *p, size_t nmemb, size_t omemb, size_t xsize)
Definition: machinestate.c:615
EXEC_WMCTRL
#define EXEC_WMCTRL
Definition: mainwindow.h:426
allfunc_t::func
weed_funcptr_t func
Definition: machinestate.h:506
rpmalloc_thread_initialize
void rpmalloc_thread_initialize(void)
Initialize thread, assign heap.
Definition: rpmalloc.c:2562
_prefs::show_dev_opts
boolean show_dev_opts
Definition: preferences.h:463