9 #include <sys/statvfs.h>
17 static 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])
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;
38 static 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);
94 #ifdef HAVE_GETENTROPY
95 if (getentropy(&rseed, 4)) rseed = (
gen_unique_id() & 0xFFFFFFFF);
114 struct _decomp_tab *lower, *higher;
117 static struct _decomp_tab nxttbl[64][25];
118 static 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;
182 void 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);
198 uint64_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;
246 static 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 // this can be tuned to provide optimal performance
433 livespointer 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);
487 livespointer 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;
713 static 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);
1369 void 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;
2021 static 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
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;
2143 static 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;
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;
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);
2187 static 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);
2238 static 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(),
2424 static uint16_t swabtab[65536];
2425 static boolean swabtab_inited =
FALSE;
2427 static 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;
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;
2632 static 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) {
2754 char *
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"
3172 static 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);
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);
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);