9#include <sys/statvfs.h>
17static void cpuid(
unsigned int ax,
unsigned int *p) {
19 (
"movl %%ebx, %%esi\n\tcpuid\n\txchgl %%ebx, %%esi"
20 :
"=a"(p[0]),
"=S"(p[1]),
"=c"(p[2]),
"=d"(p[3])
24static 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;
38static uint64_t fastrand_val = 0;
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);
50 static const double divd = (double)(0xFFFFFFFFFFFFFFFF);
return (
double)
fastrand() / divd * range;
69 static uint64_t last_rnum = 0;
72 int randres = getentropy(&rnum, 8);
95 if (getentropy(&rseed, 4)) rseed = (
gen_unique_id() & 0xFFFFFFFF);
114 struct _decomp_tab *lower, *higher;
117static struct _decomp_tab nxttbl[64][25];
118static boolean nxttab_inited =
FALSE;
121 LiVESList *preplist = NULL, *dccl, *dccl_last = NULL;
122 uint64_t val6 = 1ul, val;
125 if (nxttab_inited)
return;
126 for (
int j = 0; j < 25; j++) {
128 max2pow = 64 - ((j * 10 + 7) >> 2);
130 for (
int i = 0; i < max2pow; i++) {
131 dcc = (
struct _decomp *)
lives_malloc(
sizeof(
struct _decomp));
135 if (!preplist) dccl = preplist = lives_list_append(preplist, dcc);
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;
144 dccl_last->next = dccl2;
145 dccl2->prev = dccl_last;
150 dccl2->prev = dccl->prev;
151 if (dccl->prev) dccl->prev->next = dccl2;
152 else preplist = dccl2;
160 for (dccl = preplist; dccl; dccl = dccl->next) {
161 dcc = (
struct _decomp *)dccl->data;
164 nxttbl[xi][xj].value = dcc->value;
165 nxttbl[xi][xj].i = xi;
166 nxttbl[xi][xj].j = xj;
168 dcc = (
struct _decomp *)dccl->prev->data;
169 nxttbl[xi][xj].lower = &(nxttbl[dcc->i][dcc->j]);
170 }
else nxttbl[xi][xj].lower = NULL;
172 dcc = (
struct _decomp *)dccl->next->data;
173 nxttbl[xi][xj].higher = &(nxttbl[dcc->i][dcc->j]);
174 }
else nxttbl[xi][xj].higher = NULL;
177 nxttab_inited =
TRUE;
182void autotune_u64(weed_plant_t *tuner, uint64_t min, uint64_t max,
int ntrials,
double cost) {
185 int trials = weed_get_int_value(tuner,
"trials", NULL);
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);
198uint64_t
nxtval(uint64_t val, uint64_t lim,
boolean less) {
210 for (; !(val % 6) && val > 0; j++, val /= 6);
212 for (; val > 1; i++, val /= 2) {
218 val = nxttbl[i][j].value;
221 if (nxttbl[i][j].lower) val = nxttbl[i][j].lower->value;
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;
230 return val > lim ? val : lim;
233 if (nxttbl[i][j].higher) val = nxttbl[i][j].higher->value;
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;
239 val = nxttbl[i][j].value;
242 return val < lim ? val : lim;
246static const char *get_tunert(
int 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)";
255 return "unknown variable";
260 if (!tuner || !*tuner)
return val;
265 int64_t min = weed_get_int64_value(*tuner,
"min", NULL);
269 weed_set_int_value(*tuner,
"trials", 0);
270 weed_set_int64_value(*tuner,
"tottime", 0);
271 weed_set_double_value(*tuner,
"tcost", 0);
274 max = weed_get_int64_value(*tuner,
"max", NULL);
277 weed_set_int_value(*tuner,
"trials", 0);
278 weed_set_int64_value(*tuner,
"tottime", 0);
279 weed_set_double_value(*tuner,
"tcost", 0);
283 ntrials = weed_get_int_value(*tuner,
"ntrials", NULL);
284 trials = weed_get_int_value(*tuner,
"trials", NULL);
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);
290 if (trials >= ntrials) {
291 int cycs = weed_get_int_value(*tuner,
"cycles", NULL) + 1;
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;
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);
307 if (cycs & 1) smfirst =
TRUE;
308 weed_set_int_value(*tuner,
"cycles", cycs);
310 weed_set_int_value(*tuner,
"trials", 0);
311 weed_set_int64_value(*tuner,
"tottime", 0);
312 weed_set_double_value(*tuner,
"tcost", 0);
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;
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;
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;
347 if (!weed_plant_has_leaf(*tuner,
"larger")) {
348 weed_set_double_value(*tuner,
"smaller", avcost);
349 weed_leaf_delete(*tuner,
"larger");
354 if (!weed_plant_has_leaf(*tuner,
"smaller")) {
355 weed_set_double_value(*tuner,
"larger", avcost);
356 weed_leaf_delete(*tuner,
"smaller");
361 if (!weed_plant_has_leaf(*tuner,
"larger")) {
362 weed_set_double_value(*tuner,
"smaller", avcost);
363 weed_leaf_delete(*tuner,
"larger");
368 weed_leaf_delete(*tuner,
"smaller");
369 weed_leaf_delete(*tuner,
"larger");
377 char **res = weed_plant_list_leaves(*tuner, &nleaves);
378 uint64_t bestval = val, xval;
379 const char *key1 =
"totcost_";
381 double avcost, costmin = 0.;
382 boolean gotcost =
FALSE;
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);
389 for (j = i + 1; j < nleaves; j++) {
390 if (!strcmp(res[j], key2))
break;
393 for (j = 0; j < i; j++) {
394 if (!strcmp(res[j], key2))
break;
397 if ((avcost = weed_get_double_value(*tuner, res[i], NULL)
398 / (
double)weed_get_int_value(*tuner, res[j], NULL)) < costmin
409 g_printerr(
"value of %s tuned to %lu\n",
416 weed_plant_free(*tuner);
418 for (j = 0; j < nleaves;
lives_free(res[j++]));
423 weed_set_int64_value(*tuner,
"tottime", tottime);
430#define OIL_MEMCPY_MAX_BYTES 12288
433livespointer lives_orc_memcpy(livespointer dest, livesconstpointer src,
size_t n) {
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);
445 if (!pthread_mutex_trylock(&tuner_mutex)) {
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);
469 if (!tuner) tuned =
TRUE;
470 pthread_mutex_unlock(&tuner_mutex);
474 if (haslock)
autotune_u64(tuner, -1024 * 1024, 1024 * 1024, 128, -1. / (
double)n);
475 memcpy(dest, src, n);
478 if (!tuner) tuned =
TRUE;
479 pthread_mutex_unlock(&tuner_mutex);
487livespointer lives_oil_memcpy(livespointer dest, livesconstpointer src,
size_t n) {
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);
499 if (!pthread_mutex_trylock(&tuner_mutex)) {
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);
511 if (!tuner) tuned =
TRUE;
512 pthread_mutex_unlock(&tuner_mutex);
516 if (haslock)
autotune_u64(tuner, -1024 * 1024, 1024 * 1024, 128, -1. / (
double)n);
517 memcpy(dest, src, n);
520 if (!tuner) tuned =
TRUE;
521 pthread_mutex_unlock(&tuner_mutex);
527#define _cpy_if_nonnull(d, s, size) (d ? lives_memcpy(d, s, size) : d)
540 if (!block || bsize == 0)
return NULL;
541#ifdef lives_malloc_and_copy
542 return lives_malloc_and_copy(bsize, block);
548 if (!p || bsize == 0)
return;
549#ifdef lives_unmalloc_and_copy
550 lives_unmalloc_and_copy(bsize, p);
598 while (align < align_max && !(req_size & align)) align *= 2;
605 size_t totsize = nmemb * xsize;
606 if (!totsize)
return NULL;
609 nmemb = (totsize / xsize) + 1;
619 void *op = __builtin_assume_aligned(p,
DEF_ALIGN);
620 if (omemb > nmemb) omemb = nmemb;
657 array = lives_strsplit(
mainw->
msg,
" ", 2);
658 md5 = lives_strdup(array[0]);
659 lives_strfreev(array);
682 }
else if (space >= 1024) {
704 if (dsval) *dsval = ds;
713static char *running_for = NULL;
722 running_for = lives_strdup(dir);
748 if (timeout)
return -1;
790 boolean must_delete =
FALSE;
792 if (!lives_file_test(dir, LIVES_FILE_TEST_IS_DIR)) must_delete =
TRUE;
796 if (statvfs(dir, &sbuf) == -1)
goto getfserr;
797 if (sbuf.f_flag & ST_RDONLY)
goto getfserr;
800 bytes = sbuf.f_bsize * sbuf.f_bavail;
817 clock_gettime(CLOCK_MONOTONIC, &ts);
820#ifdef USE_MONOTONIC_TIME
821 ret = (lives_get_monotonic_time() - orignsecs) / 10;
824 gettimeofday(&
tv, NULL);
841#define SECS_IN_DAY 86400
845 char *today = NULL, *yesterday = NULL;
847 gettimeofday(&otv, NULL);
853 else dtxt = (
char *)datetime;
862 char *datetime = NULL;
863 struct tm *gm = use_local ? localtime((time_t *)&secs) : gmtime((time_t *)&secs);
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);
881 lock.l_whence = SEEK_SET;
883 lock.l_type = F_WRLCK;
885 int fd = open(devstr, O_RDONLY | O_NONBLOCK);
886 if (fd == -1)
return FALSE;
888 ret = fcntl(fd, F_SETLK, &lock);
890 ret = flock(fd, LOCK_EX | LOCK_NB);
893 if (ret == -1)
return FALSE;
907 boolean retval =
FALSE;
910 if (lives_file_test(dir, LIVES_FILE_TEST_IS_DIR)) {
911 boolean needs_norem =
FALSE;
913 if (lives_file_test(norem, LIVES_FILE_TEST_EXISTS)) {
917 cwd = lives_get_current_dir();
945 struct stat filestat;
948 fstat(fd, &filestat);
949 fsize = filestat.st_size;
955 if ((f2size = (off_t)(fbuff->
offset + fbuff->
bytes)) > fsize)
return f2size;
966 res = stat(name, &xstat);
967 if (res < 0)
return res;
968 return xstat.st_size;
975 boolean bad_header =
FALSE;
1008 if (filesize < 0) filesize = 0;
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;
1031 char *mp = NULL, *tmp, *com, *res;
1032 size_t lmatch = 0, slen;
1035 if (!dir)
return NULL;
1038 com = lives_strdup(
"df -P");
1041 char **array0 = lives_strsplit(res,
"\n", lcount);
1042 for (
int l = 0; l < lcount; l++) {
1044 char **array1 = lives_strsplit(array0[l],
" ", pccount);
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]) {
1050 tmp = lives_strdup(array1[0]);
1051 mp = lives_filename_to_utf8(tmp, -1, NULL, NULL, NULL);
1054 lives_strfreev(array1);
1056 lives_strfreev(array0);
1064#define DU_BLOCKSIZE 1024
1066#define DU_BLOCKSIZE 1
1071 if (!dirname || !*dirname || !lives_file_test(dirname, LIVES_FILE_TEST_IS_DIR))
return -1;
1085 LiVESList *list = *listp;
1087 for (; list && list->data; list = list->next) {
1089 lives_struct_free(filedets->
lsd);
1093 lives_list_free(*listp);
1100 struct stat filestat;
1101 int ret = stat(fname, &filestat);
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;
1130 char *extra_details = lives_strdup(
"");
1140 boolean emptyd =
FALSE;
1145 (tmp =
_(
"(empty)")));
1148 extra_details = tmp2;
1169 char *name = lives_strdup(sfile->
name);
1173 (
_(
"Source: %s, frames: %d, size: %d X %d, fps: %.3f"),
1189 if (lives_file_test(filename, LIVES_FILE_TEST_IS_SYMLINK))
1193 if (lives_file_test(filename, LIVES_FILE_TEST_IS_EXECUTABLE))
1208 if (!lives_file_test(filename, LIVES_FILE_TEST_EXISTS)) {
1211 (tmp =
_(
"(ABSENT)")));
1214 extra_details = tmp2;
1218 return extra_details;
1228 const char *orig_loc, uint64_t extra,
int type) {
1234 char *extra_details;
1235 const char *dir = NULL;
1237 boolean empty =
TRUE;
1245 struct dirent *tdirent;
1248 if (!dir)
return NULL;
1249 tldir = opendir(dir);
1251 *listp = lives_list_append(*listp, NULL);
1256 tdirent = readdir(tldir);
1262 if (tdirent->d_name[0] ==
'.'
1263 && (!tdirent->d_name[1] || tdirent->d_name[1] ==
'.'))
continue;
1265 fdets->
name = lives_strdup(tdirent->d_name);
1268 *listp = lives_list_append(*listp, fdets);
1279 const char *ofname = item;
1281 if (!(orderfile = fopen(ofname,
"r")))
return NULL;
1297 fdets->
name = lives_strdup(buff);
1299 *listp = lives_list_append(*listp, fdets);
1307 default:
return NULL;
1310 if (*listp) empty =
FALSE;
1311 *listp = lives_list_append(*listp, NULL);
1317 while (list && list->data) {
1320 extra_details = lives_strdup(
"");
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);
1327 if (!(extra_details = file_to_file_details(subdirname, fdets, tinfo, extra))) {
1354 const char *orig_loc, uint64_t extra) {
1356 listp, dir, orig_loc, extra, 0);
1361 const char *orig_loc, uint64_t extra) {
1363 listp, ofname, orig_loc, extra, 1);
1369void lives_log(
const char *what) {
1370 char *lives_log_file = lives_build_filename(
prefs->
workdir, LIVES_LOG_FILE, NULL);
1385 boolean maybeok =
FALSE;
1389 for (i = 1; i <= fcount; i++) {
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."));
1421 }
else tmp = lives_strdup(x);
1439 int newln = lives_snprintf((
char *)(
string + sz), len - sz,
"%s", xnew);
1440 if (newln > len) newln = len;
1441 return --newln - sz;
1448 va_start(xargs, fmt);
1449 text = lives_strdup_vprintf(fmt, xargs);
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))
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))
1470#ifndef STD_STRINGFUNCS
1472 uint64_t *pi = (uint64_t *)s, nulmask;
1473 if ((
void *)pi == (
void *)s) {
1485 if (!s)
return NULL;
1486#ifndef STD_STRINGFUNCS
1488 uint64_t *pi = (uint64_t *)s, nulmask, stlen;
1489 if (!s)
return NULL;
1490 if ((
void *)pi == (
void *)s) {
1492 stlen = (
char *)pi - s + 1
1499 return lives_strdup(s);
1507 if (!st1 || !st2)
return (st1 != st2);
1509#ifdef STD_STRINGFUNCS
1510 return strcmp(st1, st2);
1512 uint64_t d1, d2, *ip1 = (uint64_t *)st1, *ip2 = (uint64_t *)st2;
1514 if ((
void *)ip1 == (
void *)st1 && (
void *)ip2 == (
void *)st2) {
1516 if ((d1 = *(ip1++)) == (d2 = *(ip2++))) {
if (
hasNulByte(d1))
return FALSE;}
1522 st1 = (
const char *)(--ip1); st2 = (
const char *)(--ip2);
1524 if (*st1 != *(st2++))
return TRUE;
1525 if (!(*(st1++)))
return FALSE;
1532 if (!st1 || !st2)
return (st1 != st2);
1534#ifdef STD_STRINGFUNCS
1535 return strcmp(st1, st2);
1537 uint64_t d1, d2, *ip1 = (uint64_t *)st1, *ip2 = (uint64_t *)st2;
1539 if ((
void *)ip1 == (
void *)st1 && (
void *)ip2 == (
void *)st2) {
1544 st1 = (
const char *)(--ip1); st2 = (
const char *)(--ip2);
1546 if (*st1 != *st2 || !(*st1))
break;
1550 return (*st1 > *st2) - (*st1 < *st2);
1555 if (!st1 || !st2)
return (st1 != st2);
1557#ifdef STD_STRINGFUNCS
1558 return strncmp(st1, st2, len);
1560 size_t xlen = len >> 3;
1561 uint64_t d1, d2, *ip1 = (uint64_t *)st1, *ip2 = (uint64_t *)st2;
1563 if (xlen && (
void *)ip1 == (
void *)st1 && (
void *)ip2 == (
void *)st2) {
1567 }
while (d1 == d2 && !
hasNulByte(d1) && --xlen);
1573 st1 = (
void *)ip1; st2 = (
void *)ip2;
1574 len -= ((len >> 3) - xlen) << 3;
1576 if (!(len--))
return FALSE;
1577 if (*st1 != *(st2++))
return TRUE;
1578 if (!(*(st1++)))
return FALSE;
1581 return (*st1 != *st2);
1584#define HASHROOT 5381
1586 if (st)
for (uint32_t hash =
HASHROOT;; hash += (hash << 5)
1587 + * (st++))
if (!(*st))
return hash;
1594#define get16bits(d) (*((const uint16_t *) (d)))
1600 uint32_t hash = len +
HASHROOT, tmp;
1602 for (; len > 0; len--) {
1604 tmp = (
get16bits(key + 2) << 11) ^ hash;
1605 hash = (hash << 16) ^ tmp;
1614 hash ^= ((int8_t)key[2]) << 18;
1618 hash ^= hash << 11; hash += hash >> 17;
1620 case 1: hash += (int8_t) * key;
1621 hash ^= hash << 10; hash += hash >> 1;
1627 hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4;
1628 hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6;
1636 if (st && term)
for (
int i = 0; st[i]; i++)
if (st[i] == term) {st[i] = 0;
break;}
1645 if (xs && buff[xs - 1] ==
'\n') buff[--xs] =
'\0';
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);
1675 int return_type,
const char *args_fmt, va_list xargs) {
1679 if (!thread_info)
return NULL;
1682 pthread_mutex_t *dcmutex = (pthread_mutex_t *)
lives_malloc(
sizeof(pthread_mutex_t));
1683 pthread_mutex_init(dcmutex, NULL);
1689 for (c = args_fmt; *c; 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;
1707 if (!return_type)
return NULL;
1731 int return_type,
const char *args_fmt, ...) {
1734 va_start(xargs, args_fmt);
1735 lpt = _lives_proc_thread_create(attr, func, return_type, args_fmt, xargs);
1745 va_start(xargs, args_fmt);
1758 uint32_t ret_type = weed_leaf_seed_type(info,
_RV_);
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
1778#define FUNCSIG_STRING_STRING_VOIDP_INT 0X000044D1
1779#define FUNCSIG_INT_INT_BOOL_VOIDP 0X0000113D
1781#define FUNCSIG_INT_INT_INT_BOOL_VOIDP 0X0001113D
1782#define FUNCSIG_VOIDP_STRING_STRING_INT64_INT 0X000D4451
1784#define FUNCSIG_STRING_STRING_VOIDP_INT_STRING_VOIDP 0X0044D14D
1802 case WEED_SEED_INT64:
CALL_0(int64);
break;
1818 case WEED_SEED_STRING:
CALL_1(
string,
string);
break;
1819 case WEED_SEED_INT64:
CALL_1(int64,
string);
break;
1825 case WEED_SEED_BOOLEAN:
CALL_1(
boolean, voidptr);
break;
1826 case WEED_SEED_INT:
CALL_1(
int, voidptr);
break;
1852 case WEED_SEED_BOOLEAN:
CALL_2(
boolean, voidptr, voidptr);
break;
1863 case WEED_SEED_BOOLEAN:
CALL_3(
boolean, voidptr, voidptr, voidptr);
break;
1864 default:
CALL_VOID_3(voidptr, voidptr, voidptr);
break;
1869 case WEED_SEED_BOOLEAN:
CALL_3(
boolean, plantptr, voidptr, int64);
break;
1870 default:
CALL_VOID_3(plantptr, voidptr, int64);
break;
1875 case WEED_SEED_STRING:
CALL_4(
string,
string,
string, voidptr,
int);
break;
1876 default:
CALL_VOID_4(
string,
string, voidptr,
int);
break;
1881 case WEED_SEED_BOOLEAN:
CALL_4(
boolean,
int,
int,
boolean, voidptr);
break;
1882 default:
CALL_VOID_4(
int,
int,
boolean, voidptr);
break;
1887 default:
CALL_VOID_5(voidptr,
string,
string, int64,
int);
break;
1892 default:
CALL_VOID_5(
int,
int,
int,
boolean, voidptr);
break;
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;
1912 volatile boolean *sync_ready = (
volatile boolean *)weed_get_voidptr_value(tinfo,
"sync_ready", NULL);
1913 if (sync_ready) *sync_ready =
TRUE;
1918 if (!tinfo)
return TRUE;
1922 return (weed_leaf_num_elements(tinfo,
_RV_) > 0
1923 || weed_get_boolean_value(tinfo,
WEED_LEAF_DONE, NULL) == WEED_TRUE);
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;
1959 pthread_mutex_lock(dcmutex);
1962 pthread_mutex_unlock(dcmutex);
1964 pthread_mutex_unlock(dcmutex);
1976#define _join(stype) lives_nanosleep_until_nonzero(weed_leaf_num_elements(tinfo, _RV_)); \
1977 return weed_get_##stype##_value(tinfo, _RV_, NULL);
1985 weed_plant_free(tinfo);
2002 for (
register int nargs = 0; nargs < 16; nargs++) {
2004 int st = weed_leaf_seed_type(func_info, lname);
2008 if (st < 12) funcsig |= 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;
2021static void *_plant_thread_func(
void *args) {
2023 uint32_t ret_type = weed_leaf_seed_type(info,
_RV_);
2026 if (weed_get_boolean_value(info,
"no_gui", NULL) == WEED_TRUE)
THREADVAR(no_gui) =
TRUE;
2027 call_funcsig(
sig, info);
2032 pthread_mutex_lock(dcmutex);
2035 pthread_mutex_unlock(dcmutex);
2036 if (dontcare == WEED_TRUE) {
2038 weed_plant_free(info);
2040 }
else if (!ret_type) weed_plant_free(info);
2046 uint32_t ret_type = weed_leaf_seed_type(lpt,
_RV_);
2049 call_funcsig(
sig, lpt);
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;
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;
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;
2070 case WEED_SEED_STRING: {
2071 char *chval = weed_get_string_value(lpt,
_RV_, NULL);
2072 weed_plant_free(lpt);
2073 return (
void *)chval;
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;
2081 case WEED_SEED_VOIDPTR: {
2083 val = weed_get_voidptr_value(lpt,
_RV_, NULL);
2084 weed_plant_free(lpt);
2087 case WEED_SEED_PLANTPTR: {
2089 pval = weed_get_plantptr_value(lpt,
_RV_, NULL);
2090 weed_plant_free(lpt);
2091 return (
void *)pval;
2095 weed_plant_free(lpt);
2116 weed_set_voidptr_value(thread_info,
"sync_ready", (
void *) & (work->
sync_ready));
2119 weed_set_boolean_value(thread_info,
"no_gui", WEED_TRUE);
2128#define MINPOOLTHREADS 8
2130#define MINPOOLTHREADS 2
2132static int npoolthreads;
2133static pthread_t **poolthrds;
2134static pthread_cond_t tcond = PTHREAD_COND_INITIALIZER;
2135static pthread_mutex_t tcond_mutex = PTHREAD_MUTEX_INITIALIZER;
2136static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
2137static pthread_mutex_t twork_mutex = PTHREAD_MUTEX_INITIALIZER;
2138static pthread_mutex_t twork_count_mutex = PTHREAD_MUTEX_INITIALIZER;
2139static LiVESList *twork_first, *twork_last;
2140static volatile int ntasks;
2141static boolean threads_die;
2143static LiVESList *allctxs = NULL;
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;
2163 return &thrdat->vars;
2166static 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;
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();
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);
2187static boolean gsrc_wrapper(livespointer data) {
2198 uint64_t myflags = 0;
2200 if (!tdata->idx) abort();
2202 pthread_mutex_lock(&twork_mutex);
2204 if (LIVES_UNLIKELY(!list)) {
2205 pthread_mutex_unlock(&twork_mutex);
2209 if (twork_first == list) twork_last = twork_first = NULL;
2211 twork_last = list->prev;
2212 twork_last->next = NULL;
2214 pthread_mutex_unlock(&twork_mutex);
2217 mywork->
busy = tdata->idx;
2218 myflags = mywork->
flags;
2224 lives_widget_context_invoke(tdata->ctx, gsrc_wrapper, mywork);
2229 }
else mywork->
done = tdata->idx;
2231 pthread_mutex_lock(&twork_count_mutex);
2233 pthread_mutex_unlock(&twork_count_mutex);
2238static void *thrdpool(
void *arg) {
2239 boolean skip_wait =
FALSE;
2240 lives_thread_data_t *tdata = (lives_thread_data_t *)arg;
2245 lives_widget_context_push_thread_default(tdata->ctx);
2247 while (!threads_die) {
2249 pthread_mutex_lock(&tcond_mutex);
2250 pthread_cond_wait(&tcond, &tcond_mutex);
2251 pthread_mutex_unlock(&tcond_mutex);
2253 if (LIVES_UNLIKELY(threads_die))
break;
2283 poolthrds = (pthread_t **)
lives_calloc(npoolthreads,
sizeof(pthread_t *));
2284 threads_die =
FALSE;
2285 twork_first = twork_last = NULL;
2287 for (
int i = 0; i < npoolthreads; i++) {
2289 poolthrds[i] = (pthread_t *)
lives_malloc(
sizeof(pthread_t));
2290 pthread_create(poolthrds[i], NULL, thrdpool, tdata);
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);
2313 twork_first = twork_last = NULL;
2319 LiVESList *list = (LiVESList *)thread;
2321 if (!thread) list = (LiVESList *)
lives_calloc(1,
sizeof(LiVESList));
2322 else list->next = list->prev = NULL;
2334 pthread_mutex_lock(&twork_mutex);
2336 twork_first = twork_last = list;
2339 twork_first->prev = list;
2340 list->next = twork_first;
2343 twork_last->next = list;
2344 list->prev = twork_last;
2348 pthread_mutex_unlock(&twork_mutex);
2349 pthread_mutex_lock(&twork_count_mutex);
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);
2361 for (
int i = npoolthreads; i < npoolthreads +
MINPOOLTHREADS; i++) {
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);
2371 pthread_mutex_unlock(&pool_mutex);
2380 LIVES_FATAL(
"lives_thread_join() called on an autodelete thread");
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;
2394 pthread_mutex_lock(&tcond_mutex);
2395 pthread_cond_signal(&tcond);
2396 pthread_mutex_unlock(&tcond_mutex);
2402 if (retval) *retval = task->
ret;
2410 return GetCurrentProcessId(),
2424static uint16_t swabtab[65536];
2425static boolean swabtab_inited =
FALSE;
2427static void init_swabtab(
void) {
2428 for (
int i = 0; i < 256; i++) {
2430 for (
int j = 0; j < 256; j++) {
2431 swabtab[z++] = (j << 8) + i;
2434 swabtab_inited =
TRUE;
2449 uint16_t *s = (uint16_t *)from;
2450 uint16_t *d = (uint16_t *)to;
2457 if (!swabtab_inited) init_swabtab();
2463 union split4 *d = (
union split4 *)to, s;
2470 s.u32 = *(uint32_t *)from;
2473 d->u16[0] = s.u16[1];
2476 swab2(&s.u16[1], &d->u16[0], 1);
2477 swab2(&tmp, &d->u16[1], 1);
2484 union split8 *d = (
union split8 *)to, s;
2490 s.u64 = *(uint64_t *)from;
2493 d->u32[0] = s.u32[1];
2496 swab4(&s.u32[1], &d->u32[0], gran);
2497 swab4(&tmp, &d->u32[1], 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);
2511 ssize_t start = -1, end;
2512 size_t ocount = count;
2515 if ((chunk != 4 && chunk != 2 && chunk != 1) || (count % chunk) != 0)
return FALSE;
2517 if ((chunk & 0x01) || (count % chunk) != 0)
return FALSE;
2525 end = ocount - 1 - chunk;
2526 while (start + chunk < end) {
2545 if (count >= 8 && (ocount & 0x07) == 0) {
2547 uint64_t *buff8 = (uint64_t *)buff;
2548 if ((
void *)buff8 == (
void *)buff) {
2550 for (; count >= 8; count -= 8) {
2552 uint64_t tmp8 = buff8[--end];
2554 buff8[end] = buff8[++start];
2555 buff8[start] = tmp8;
2557 swab8(&buff8[++start], &buff8[end], chunk);
2558 swab8(&tmp8, &buff8[start], chunk);
2561 if (count <= chunk / 2)
return TRUE;
2562 start = (start + 1) << 3;
2568 if (chunk >= 8)
return FALSE;
2570 if (count >= 4 && (ocount & 0x03) == 0) {
2571 uint32_t *buff4 = (uint32_t *)buff;
2572 if ((
void *)buff4 == (
void *)buff) {
2574 end = (ocount - start) >> 2;
2576 }
else end = ocount >> 2;
2577 for (; count >= 4; count -= 4) {
2579 uint32_t tmp4 = buff4[--end];
2581 buff4[end] = buff4[++start];
2582 buff4[start] = tmp4;
2584 swab4(&buff4[++start], &buff4[end], chunk);
2585 swab4(&tmp4, &buff4[start], chunk);
2588 if (count <= chunk / 2)
return TRUE;
2589 start = (start + 1) << 2;
2595 if (chunk >= 4)
return FALSE;
2598 uint16_t *buff2 = (uint16_t *)buff;
2599 if ((
void *)buff2 == (
void *)buff) {
2601 end = (ocount - start) >> 1;
2603 }
else end = ocount >> 1;
2604 for (; count >= chunk / 2; count -= 2) {
2606 uint16_t tmp2 = buff2[--end];
2608 buff2[end] = buff2[++start];
2609 buff2[start] = tmp2;
2613 swab2(&buff2[++start], &buff2[end], 1);
2614 swab2(&tmp2, &buff2[start], 1);
2619 if (count == 0)
return TRUE;
2626static int flowlen = 0;
2627static boolean inited =
FALSE;
2628static int struggling = 0;
2629static int badthingcount = 0;
2630static int goodthingcount = 0;
2632static int pop_flowstate(
void) {
2633 int ret = theflow[0];
2635 for (
int i = 0; i < flowlen; i++) {
2636 theflow[i] = theflow[i + 1];
2647 badthingcount = goodthingcount = 0;
2660 if (!nthings)
return;
2666 badthingcount += nthings;
2672 goodthingcount += spcycles;
2677 while (nthings-- > 0) {
2680 int res = pop_flowstate();
2681 if (res > 0) badthingcount -= res;
2682 else goodthingcount += res;
2686 theflow[flowlen] = -spcycles;
2692 if (!badthingcount) {
2754char *
grep_in_cmd(
const char *cmd,
int mstart,
int npieces,
const char *mphrase,
int ridx,
int rlen) {
2755 char **lines, **words, **mwords;
2758 size_t nlines, mwlen;
2763 if (!mphrase || npieces < -1 || !npieces || rlen < 1 || (ridx <= mstart && ridx + rlen > mstart)
2764 || (npieces > 0 && (ridx + rlen > npieces || mstart >= npieces)))
return NULL;
2767 if (mstart + mwlen > npieces
2768 || (ridx + rlen > mstart && ridx < mstart + mwlen))
return NULL;
2770 mwords = lives_strsplit(mphrase,
" ", mwlen);
2772 if (!cmd || !mphrase || !*cmd || !*mphrase)
goto grpcln;
2780 minpieces = MAX(mstart + mwlen, ridx + rlen);
2782 lines = lives_strsplit(buff,
"\n", nlines);
2783 for (
int l = 0; l < nlines; l++) {
2785 words = lives_strsplit(lines[l],
" ", npieces);
2786 for (m = 0; m < mwlen; m++) {
2790 match = lives_strdup(words[ridx]);
2791 for (
int w = 1; w < rlen; w++) {
2796 lives_strfreev(words);
2800 lives_strfreev(lines);
2802 lives_strfreev(mwords);
2807 if (!cmd)
return FALSE;
2815 if (!cmd)
return NULL;
2822 return lives_strdup(buff);
2828 LiVESResponseType resp = LIVES_RESPONSE_NONE;
2829 boolean retval =
TRUE;
2830 char *reason = NULL;
2833 resp = LIVES_RESPONSE_NONE;
2861 char *mp1 = get_mountpount_for(item);
2869 trashdir = lives_build_path(localshare,
"Trash", NULL);
2870 trashinfodir = lives_build_path(trashdir,
"info", NULL);
2871 trashfilesdir = lives_build_path(trashdir,
"files", NULL);
2891 fname = lives_build_filename(trashinfodir, trashinfo, NULL);
2904 char *msg =
lives_strdup_printf(
_(
"LiVES was unable to send the item to trash.\n%s"), reason ? reason :
"");
2908 if (resp == LIVES_RESPONSE_CANCEL)
return resp;
2910 }
while (resp == LIVES_RESPONSE_RETRY);
2911 return LIVES_RESPONSE_OK;
2918#ifndef GDK_WINDOWING_X11
2921 char *wid = NULL, *cmd;
2922 if (!wname || !*wname)
return NULL;
2928 if (wid)
return wid;
2932 wid =
grep_in_cmd(cmd, 1, -1,
"Window id:", 3, 1);
2934 if (wid)
return wid;
2949 char **lines = lives_strsplit(buff,
"\n", nlines);
2950 for (
int l = 0; l < nlines; l++) {
2951 if (!*lines[l])
continue;
2965 lives_strfreev(lines);
2975#ifndef GDK_WINDOWING_X11
2978 if (!wid)
return FALSE;
2989#ifndef GDK_WINDOWING_X11
2992 if (!wid)
return FALSE;
3000#ifndef GDK_WINDOWING_X11
3003 if (!wid)
return FALSE;
3043 if (!wmname)
return FALSE;
3082 if (nwins) *nwins = -1;
3085 int mywin = -1, i = 0;
3087 for (; list; list = list->next, i++) {
3088 if ((LiVESXWindow *)list->data == xwin) mywin = i;
3091 lives_list_free(winlist);
3092 if (nwins) *nwins = ++i;
3099 boolean ret =
FALSE;
3100#ifdef GDK_WINDOWING_X11
3111 boolean ret =
FALSE;
3112#ifdef GDK_WINDOWING_X11
3125#ifndef GDK_WINDOWING_X11
3128 if (!wname || !*wname)
return FALSE;
3132 state =
grep_in_cmd(cmd, 2, -1,
"Map State:", 4, 1);
3134 if (state && !strcmp(state,
"IsViewable")) {
3155 char **lines = lives_strsplit(buff,
"\n", nlines), *xwid;
3156 for (l = 0; l < nlines; l++) {
3157 if (!*lines[l])
continue;
3159 if (!strcmp(xwid, wid))
break;
3161 lives_strfreev(lines);
3163 if (l < nlines)
return TRUE;
3170#define XTEMP "XXXXXXXXXX"
3172static char *get_systmp_inner(
const char *suff,
boolean is_dir,
const char *prefix) {
3184 const char *dirflg, *tmpopt;
3195 tmp = lives_build_filename(suff, tmpfile, NULL);
3201 if (is_dir) dirflg =
"d";
3208 if (!res)
return NULL;
3218 if (!lives_file_test(res, LIVES_FILE_TEST_EXISTS)
3219 || lives_file_test(res, LIVES_FILE_TEST_IS_SYMLINK)) {
3233 return get_systmp_inner(suff, is_dir, NULL);
3236static char *_get_worktmp(
const char *prefix,
boolean is_dir) {
3237 char *dirname = NULL;
3238 char *tmpdir = get_systmp_inner(
prefs->
workdir, is_dir, prefix);
3240 dirname = lives_path_get_basename(tmpdir);
3247 if (!prefix)
return NULL;
3248 return _get_worktmp(prefix,
TRUE);
3252 if (!prefix)
return NULL;
3253 return _get_worktmp(prefix,
FALSE);
3262 if (!res)
return FALSE;
3273#define LSB_OS_FILE "/etc/lsb-release"
3277 char **array = lives_strsplit(ret,
"=", xlen);
3289 lives_strfreev(array);
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);
3303 return numProcessors;
3308 lives_snprintf(command,
PATH_MAX,
"sysctl -n kern.smp.cpus");
3310 lives_snprintf(command,
PATH_MAX,
"%s processor /proc/cpuinfo 2>/dev/null | %s -l 2>/dev/null",
3314 return atoi(buffer);
3321 char *com = lives_strdup(
"sysctl -n hw.model");
3323 char *com =
lives_strdup_printf(
"%s -m1 \"^model name\" /proc/cpuinfo | %s -e \"s/.*: //\" -e \"s:\\s\\+:/:g\"",
3328 com = lives_strdup(
"uname -o");
3331 com = lives_strdup(
"uname -r");
3334 com = lives_strdup(
"uname -m");
3343 com = lives_strdup(
"uname -n");
3346 com = lives_strdup(
"whoami");
3357#define DISK_STATS_FILE "/proc/diskstats"
3363 static uint64_t lval = 0;
3368 xmp = (
char *)mp + 5;
3374 char **array = lives_strsplit(res,
" ", xbits);
3377 uint64_t val = atoll(array[13]);
3381 if (lticks > 0 && clock_ticks > lticks) ret = (double)(val - lval) / ((double)(clock_ticks - lticks)
3383 lticks = clock_ticks;
3386 lives_strfreev(array);
3394#define CPU_STATS_FILE "/proc/stat"
3399 static uint64_t lidle = 0, lsum = 0;
3401 char *res, *target, *com;
3408 char **array = lives_strsplit(res,
" ", xbits);
3413 ret = atoll(array[1]);
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;
3427 double load = 1. - (double)(idle - lidle) / (double)(sum - lsum);
3433 lives_strfreev(array);
LIVES_GLOBAL_INLINE char * lives_get_audio_file_name(int fnum)
boolean do_header_write_error(int clip)
LIVES_GLOBAL_INLINE LiVESResponseType do_abort_cancel_retry_dialog(const char *text)
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
void * struct_from_template(lives_struct_type st_type)
@ LIVES_STRUCT_FILE_DETS_T
#define FUNCSIG_STRING_BOOL
void * quick_calloc(size_t n, size_t s)
void * _ext_malloc(size_t n)
LIVES_GLOBAL_INLINE const char * lives_strappendf(const char *string, int len, const char *fmt,...)
boolean show_desktop_panel(void)
LIVES_GLOBAL_INLINE int lives_getgid(void)
LIVES_GLOBAL_INLINE weed_plantptr_t lives_proc_thread_join_plantptr(lives_proc_thread_t tinfo)
char * lives_datetime(uint64_t secs, boolean use_local)
LIVES_GLOBAL_INLINE boolean lives_strcmp(const char *st1, const char *st2)
returns FALSE if strings match
boolean hide_desktop_panel(void)
#define FUNCSIG_VOIDP_VOIDP
boolean get_x11_visible(const char *wname)
boolean get_distro_dets(void)
LIVES_GLOBAL_INLINE int64_t lives_proc_thread_signalled_idx(lives_proc_thread_t tinfo)
char * get_md5sum(const char *filename)
LIVES_GLOBAL_INLINE boolean lives_proc_thread_cancel(lives_proc_thread_t tinfo)
off_t get_dir_size(const char *dirname)
weed_plantptr_t lives_proc_thread_t
lives proc_threads API
boolean unhide_x11_window(const char *wid)
char * get_worktmpfile(const char *prefix)
LIVES_GLOBAL_INLINE void * lives_calloc_safety(size_t nmemb, size_t xsize)
char * get_mountpoint_for(const char *dir)
lives_thread_data_t * lives_thread_data_create(uint64_t idx)
uint64_t get_ds_free(const char *dir)
boolean activate_x11_window(const char *wid)
off_t get_file_size(int fd)
LIVES_GLOBAL_INLINE int64_t lives_proc_thread_join_int64(lives_proc_thread_t tinfo)
LIVES_GLOBAL_INLINE int64_t disk_monitor_wait_result(const char *dir, ticks_t timeout)
LIVES_GLOBAL_INLINE uint64_t lives_random(void)
lives_proc_thread_t disk_monitor_start(const char *dir)
#define FUNCSIG_PLANTP_VOIDP_INT64
LIVES_GLOBAL_INLINE void lives_proc_thread_free(lives_proc_thread_t lpt)
boolean init_memfuncs(void)
LIVES_GLOBAL_INLINE weed_funcptr_t lives_proc_thread_join_funcptr(lives_proc_thread_t tinfo)
LIVES_GLOBAL_INLINE char * lives_proc_thread_join_string(lives_proc_thread_t tinfo)
#define FUNCSIG_VOIDP_STRING_STRING_INT64_INT
LIVES_GLOBAL_INLINE boolean lives_proc_thread_get_cancellable(lives_proc_thread_t tinfo)
LIVES_GLOBAL_INLINE size_t lives_strlen(const char *s)
off_t sget_file_size(const char *name)
LIVES_GLOBAL_INLINE int lives_proc_thread_join_int(lives_proc_thread_t tinfo)
void free_fdets_list(LiVESList **listp)
LIVES_GLOBAL_INLINE void * lives_free_and_return(void *p)
TODO: this file should be split into at least: memory functions, thread functions,...
LIVES_GLOBAL_INLINE int lives_proc_thread_join_boolean(lives_proc_thread_t tinfo)
void * _ext_calloc(size_t nmemb, size_t msize)
LIVES_GLOBAL_INLINE char * lives_strstop(char *st, const char term)
LIVES_LOCAL_INLINE char * mini_popen(char *cmd)
LIVES_GLOBAL_INLINE int lives_proc_thread_signalled(lives_proc_thread_t tinfo)
LIVES_LOCAL_INLINE boolean mini_run(char *cmd)
LIVES_GLOBAL_INLINE char * lives_strtrim(const char *buff)
void autotune_u64(weed_plant_t *tuner, uint64_t min, uint64_t max, int ntrials, double cost)
LiVESResponseType send_to_trash(const char *item)
void * fg_run_func(lives_proc_thread_t lpt, void *retval)
void * _ext_malloc_and_copy(size_t bsize, const void *block)
void lives_threadpool_init(void)
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,...
#define hasNulByte(x)
each byte B can be thought of as a signed char, subtracting 1 sets bit 7 if B was <= 0,...
void disk_monitor_forget(void)
lives_thread_data_t * get_thread_data(void)
LIVES_GLOBAL_INLINE char * lives_strdup_quick(const char *s)
LIVES_GLOBAL_INLINE void * lives_proc_thread_join_voidptr(lives_proc_thread_t tinfo)
LIVES_GLOBAL_INLINE char * lives_concat_sep(char *st, const char *sep, char *x)
#define FUNCSIG_STRING_STRING_VOIDP_INT
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
#define FUNCSIG_INT_INT_BOOL_VOIDP
LIVES_GLOBAL_INLINE ticks_t lives_get_current_ticks(void)
void update_effort(int nthings, boolean badthings)
boolean disk_monitor_running(const char *dir)
LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew)
LIVES_GLOBAL_INLINE lives_threadvars_t * get_threadvars(void)
void * _ext_memset(void *p, int i, size_t n)
boolean check_dev_busy(char *devstr)
LIVES_GLOBAL_INLINE int lives_getuid(void)
boolean get_machine_dets(void)
int64_t disk_monitor_check_result(const char *dir)
#define FUNCSIG_STRING_STRING_VOIDP_INT_STRING_VOIDP
boolean hide_x11_window(const char *wid)
boolean compress_files_in_dir(const char *dir, int method, void *data)
double get_disk_load(const char *mp)
LIVES_GLOBAL_INLINE uint32_t fastrand_int(uint32_t range)
pick a pseudo random uint between 0 and range (inclusive)
#define FUNCSIG_INT_INT_INT_BOOL_VOIDP
void _ext_unmalloc_and_copy(size_t bsize, void *p)
LIVES_GLOBAL_INLINE void swab2(const void *from, const void *to, size_t gran)
void * _ext_memcpy(void *dest, const void *src, size_t n)
lives_storage_status_t get_storage_status(const char *dir, uint64_t warn_level, int64_t *dsval, int64_t ds_resvd)
uint64_t nxtval(uint64_t val, uint64_t lim, boolean less)
boolean check_snap(const char *prog)
void * _ext_free_and_return(void *p)
boolean init_thread_memfuncs(void)
void lives_threadpool_finish(void)
LIVES_GLOBAL_INLINE void fastrand_add(uint64_t entropy)
char * get_wid_for_name(const char *wname)
x11 stuff
#define getnulpos_be(nulmask)
char * lives_format_storage_space_string(uint64_t space)
LIVES_GLOBAL_INLINE uint32_t fast_hash(const char *key)
void * _ext_realloc(void *p, size_t n)
LIVES_GLOBAL_INLINE size_t get_max_align(size_t req_size, size_t align_max)
LIVES_GLOBAL_INLINE void swab4(const void *from, const void *to, size_t gran)
LIVES_GLOBAL_INLINE double fastrand_dbl(double range)
int get_window_stack_level(LiVESXWindow *xwin, int *nwins)
uint64_t autotune_u64_end(weed_plant_t **tuner, uint64_t val)
LIVES_GLOBAL_INLINE pid_t lives_getpid(void)
LIVES_GLOBAL_INLINE void lives_proc_thread_join(lives_proc_thread_t tinfo)
uint64_t gen_unique_id(void)
off_t reget_afilesize_inner(int fileno)
LIVES_GLOBAL_INLINE char * lives_chomp(char *buff)
int stat_to_file_dets(const char *fname, lives_file_dets_t *fdets)
LIVES_GLOBAL_INLINE uint32_t lives_string_hash(const char *st)
LIVES_GLOBAL_INLINE boolean lives_strncmp(const char *st1, const char *st2, size_t len)
returns FALSE if strings match
LIVES_GLOBAL_INLINE char * lives_concat(char *st, char *x)
LIVES_GLOBAL_INLINE ticks_t lives_get_relative_ticks(ticks_t origsecs, ticks_t orignsecs)
char * get_worktmp(const char *prefix)
#define FUNCSIG_VOIDP_DOUBLE
LIVES_GLOBAL_INLINE uint64_t fastrand(void)
#define OIL_MEMCPY_MAX_BYTES
susbtitute memory functions. These must be real functions and not #defines since we need fn pointers
int64_t get_cpu_load(int cpun)
percent * 1 million
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...
LIVES_GLOBAL_INLINE int lives_strcmp_ordered(const char *st1, const char *st2)
LIVES_GLOBAL_INLINE void reverse_bytes(char *buff, size_t count, size_t gran)
void * main_thread_execute(lives_funcptr_t func, int return_type, void *retval, const char *args_fmt,...)
uint64_t lives_thread_join(lives_thread_t work, void **retval)
boolean do_something_useful(lives_thread_data_t *tdata)
LIVES_GLOBAL_INLINE weed_plant_t * lives_plant_new_with_index(int subtype, int64_t index)
#define FUNCSIG_STRING_INT
void * _ext_memmove(void *dest, const void *src, size_t n)
boolean get_wm_caps(void)
boolean is_empty_dir(const char *dirname)
#define FUNCSIG_PLANTP_BOOL
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 '.
int check_for_bad_ffmpeg(void)
#define getnulpos(nulmask)
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
LIVES_GLOBAL_INLINE boolean lives_proc_thread_cancelled(lives_proc_thread_t tinfo)
int lives_thread_create(lives_thread_t *thread, lives_thread_attr_t attr, lives_funcptr_t func, void *arg)
#define FUNCSIG_VOIDP_VOIDP_VOIDP
char * get_systmp(const char *suff, boolean is_dir)
void lives_get_randbytes(void *ptr, size_t size)
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
char * lives_datetime_rel(const char *datetime)
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 '.
LIVES_GLOBAL_INLINE double lives_proc_thread_join_double(lives_proc_thread_t tinfo)
LIVES_GLOBAL_INLINE void * lives_recalloc(void *p, size_t nmemb, size_t omemb, size_t xsize)
int _ext_memcmp(const void *s1, const void *s2, size_t n)
#define FUNCSIG_INT_INT64
LIVES_GLOBAL_INLINE weed_plant_t * lives_plant_new(int subtype)
LIVES_GLOBAL_INLINE void lives_proc_thread_sync_ready(lives_proc_thread_t tinfo)
boolean reverse_buffer(uint8_t *buff, size_t count, size_t chunk)
LIVES_GLOBAL_INLINE void swab8(const void *from, const void *to, size_t gran)
void reget_afilesize(int fileno)
#define _cpy_if_nonnull(d, s, size)
lives_proc_thread_t ordfile_to_file_details(LiVESList **listp, const char *ofname, const char *orig_loc, uint64_t extra)
char * grep_in_cmd(const char *cmd, int mstart, int npieces, const char *mphrase, int ridx, int rlen)
LIVES_GLOBAL_INLINE void lives_srandom(unsigned int seed)
#define LIVES_THRDFLAG_WAIT_SYNC
#define XDG_CURRENT_DESKTOP
#define CALL_4(ret, t1, t2, t3, t4)
#define LIVES_THRDATTR_PRIORITY
#define EXTRA_DETAILS_CHECK_MISSING
extras we can check for, may consume more time
#define LIVES_WEED_SUBTYPE_TUNABLE
#define LIVES_THRDATTR_FG_THREAD
#define WEED_LEAF_DONTCARE_MUTEX
ensures we can set dontcare without it finishing while doing so
#define EXTRA_DETAILS_EXECUTABLE
#define WEED_LEAF_SIGNAL_DATA
#define EXTRA_BYTES
TODO - split into: memory, files, sysops, threads.
#define lives_nanosleep(nanosec)
lives_storage_status_t
disk/storage status values
@ LIVES_STORAGE_STATUS_CRITICAL
@ LIVES_STORAGE_STATUS_NORMAL
@ LIVES_STORAGE_STATUS_WARNING
@ LIVES_STORAGE_STATUS_UNKNOWN
@ LIVES_STORAGE_STATUS_OVER_QUOTA
@ LIVES_STORAGE_STATUS_OVERFLOW
#define WM_XFCE4_SETTINGS
#define CALL_VOID_6(t1, t2, t3, t4, t5, t6)
#define EXTRA_DETAILS_SYMLINK
#define CALL_VOID_3(t1, t2, t3)
#define LIVES_THRDATTR_NO_GUI
#define CALL_3(ret, t1, t2, t3)
#define WEED_LEAF_THREAD_CANCELLED
#define CALL_2(ret, t1, t2)
#define LIVES_THRDFLAG_AUTODELETE
#define CALL_VOID_2(t1, t2)
#define WM_XFCE4_TERMINAL
#define EXTRA_DETAILS_MD5SUM
derived values
#define LIVES_THRDATTR_WAIT_SYNC
#define WEED_LEAF_THREADFUNC
#define lives_nanosleep_until_nonzero(condition)
#define WEED_LEAF_LIVES_SUBTYPE
#define LIVES_WEED_SUBTYPE_PROC_THREAD
uint64_t lives_thread_attr_t
#define WEED_LEAF_THREAD_PARAM
#define LIVES_THRDATTR_AUTODELETE
#define WEED_LEAF_DONTCARE
tell proc_thread with return value that we n o longer need return val.
#define CALL_VOID_5(t1, t2, t3, t4, t5)
#define EXTRA_DETAILS_CLIPHDR
#define WEED_LEAF_SIGNALLED
#define WEED_LEAF_THREAD_CANCELLABLE
void *(* lives_funcptr_t)(void *)
#define WEED_LEAF_RETURN_VALUE
#define CALL_6(ret, t1, t2, t3, t4, t5, t6)
#define CALL_VOID_4(t1, t2, t3, t4)
#define EXTRA_DETAILS_DIRSIZE
#define EXTRA_DETAILS_EMPTY_DIRS
#define LIVES_THRDATTR_NONE
int get_frame_count(int idx, int xsize)
sets mainw->files[idx]->frames with current framecount
ssize_t lives_popen(const char *com, boolean allow_error, char *buff, ssize_t buflen)
void lives_list_free_all(LiVESList **)
size_t get_token_count(const char *string, int delim)
#define is_layer_ready(layer)
void lives_sync(int times)
void cached_list_free(LiVESList **list)
int lives_touch(const char *tfile)
#define LIVES_GLOBAL_INLINE
int lives_chdir(const char *path, boolean no_error_dlg)
#define DEF_FILE_PERMS
non-executable, is modified by the umask
uint64_t lives_10pow(int pow) GNU_CONST
boolean lives_alarm_clear(lives_alarm_t alarm_handle)
#define LIVES_LOCAL_INLINE
int lives_system(const char *com, boolean allow_error)
boolean is_writeable_dir(const char *dir)
char * lives_fgets(char *s, int size, FILE *stream)
int create_nullvideo_clip(const char *handle)
const char * get_image_ext_for_type(lives_img_type_t imgtype)
void update_play_times(void)
like get_play_times, but will force redraw of audio waveforms
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 ...
int lives_rmdir(const char *dir, boolean force)
#define IS_VALID_CLIP(clip)
int lives_rm(const char *file)
@ MISSING
not yet implemented (TODO)
int lives_open2(const char *pathname, int flags)
boolean check_dir_access(const char *dir, boolean leaveit)
boolean check_for_executable(lives_checkstatus_t *cap, const char *exec)
lives_file_buffer_t * find_in_file_buffers(int fd)
boolean read_headers(int clipno, const char *dir, const char *file_name)
boolean lives_freep(void **ptr)
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
boolean save_clip_value(int which, lives_clip_details_t, void *val)
ticks_t lives_alarm_check(lives_alarm_t alarm_handle)
@ CANCEL_ERROR
cancelled because of error
#define MAINW_MSG_SIZE
mainw->msg bytesize
#define LIVES_FILE_TYPE_FLAG_MISSING
#define LIVES_LONGEST_TIMEOUT
#define LIVES_FILE_IS_DIRECTORY(ftype)
#define USEC_TO_TICKS
multiplying factor uSec -> ticks_t (def. 100)
#define EFFORT_LIMIT_MED
default 32
#define LIVES_NO_ALARM
lives_alarms
#define LIVES_FILE_TYPE_FLAG_SYMLINK
#define TICKS_PER_SECOND_DBL
actually microseconds / 100.
#define LIVES_FILE_TYPE_FLAG_EXECUTABLE
#define EFFORT_LIMIT_LOW
default 8
#define EFFORT_RANGE_MAX
if set to TRUE during playback then a new frame (or possibly the current one) will be displayed ASAP
#define LIVES_FILE_TYPE_DIRECTORY
#define LIVES_FILE_TYPE_FLAG_EMPTY
#define LIVES_FILE_TYPE_UNKNOWN
#define LIVES_FILENAME_NOREMOVE
#define PB_QUALITY_MED
default
_future_prefs * future_prefs
void rpmalloc_thread_finalize(void)
Finalize thread, orphan heap.
void rpfree(void *ptr)
Free the given memory block.
RPMALLOC_ALLOCATOR void * rpmalloc(size_t size)
Allocate a memory block of at least the given size.
void rpmalloc_thread_collect(void)
Perform deferred deallocations pending for the calling thread heap.
int rpmalloc_is_thread_initialized(void)
Query if allocator is initialized for calling thread.
void rpmalloc_thread_initialize(void)
Initialize thread, assign heap.
RPMALLOC_ALLOCATOR void * rprealloc(void *ptr, size_t size)
Reallocate the given block to at least the given size.
int rpmalloc_initialize(void)
Initialize the allocator and setup global data.
RPMALLOC_ALLOCATOR void * rpaligned_calloc(size_t alignment, size_t num, size_t size)
char workdir[PATH_MAX]
kept in locale encoding
lives_checkstatus_t has_xdotool
char home_dir[PATH_MAX]
home directory - default location for config file - locale encoding
lives_checkstatus_t has_wmctrl
char * wm_type
window manager type, e.g. x11
lives_checkstatus_t has_xwininfo
lives_checkstatus_t has_gio
lives_checkstatus_t has_mktemp
lives_checkstatus_t has_snap
char * wm_name
window manager name, may be different from wm_caps.wwm_name
lives_checkstatus_t has_gzip
lives_checkstatus_t has_du
corresponds to one clip in the GUI
int arps
audio physical sample rate (i.e the "normal" sample rate of the clip when played at 1,...
frames_t frames
number of video frames
int asampsize
audio sample size in bits (8 or 16)
int vsize
frame height (vertical) in pixels
int achans
number of audio channels (0, 1 or 2)
int hsize
frame width (horizontal) in pixels (NOT macropixels !)
char name[CLIP_NAME_MAXLEN]
the display name
int arate
current audio playback rate (varies if the clip rate is changed)
off_t offset
ptr to data (ptr - buffer + bytes) gives the read size
char * extra_details
only filled if EXTRA_DETAILS_MD5 is set, otherwis NULL
uint64_t gid
userid as uint64_t
off_t size
e.g. LIVES_FILE_TYPE_FILE
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
lives_mgeometry_t * mgeom
multi-head support
int scrap_file
we throw odd sized frames here when recording in real time; used if a source is a generator or stream
volatile int blend_palette
here we can store the details of the blend file at the insertion point, if nothing changes we can tar...
volatile ticks_t clock_ticks
unadjusted system time since pb start, measured concurrently with currticks
int ascrap_file
scrap file for recording audio scraps
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
boolean preview_rendering
weed_plant_t * frame_layer_preload
predictive caching apparatus
LiVESList * hdrs_cache
cache of a file header (e.g. header.lives)
volatile boolean sync_ready
char display_settings[64]
LiVESXWindow * root_window
#define lives_strdup_printf(fmt,...)