Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
darktable.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2014 johannes hanika.
4 Copyright (C) 2010-2011, 2015 Bruce Guenter.
5 Copyright (C) 2010-2012 Henrik Andersson.
6 Copyright (C) 2010 Richard Hughes.
7 Copyright (C) 2010-2020 Tobias Ellinghaus.
8 Copyright (C) 2011 Alexey Dokuchaev.
9 Copyright (C) 2011 Antony Dovgal.
10 Copyright (C) 2011 calca.
11 Copyright (C) 2011-2012 Christian Tellefsen.
12 Copyright (C) 2011 David Bremner.
13 Copyright (C) 2011-2012 Edouard Gomez.
14 Copyright (C) 2011 Kanstantsin Shautsou.
15 Copyright (C) 2011-2015 Pascal de Bruijn.
16 Copyright (C) 2011 Robert Bieber.
17 Copyright (C) 2011-2012, 2016-2018 Ulrich Pegelow.
18 Copyright (C) 2012 James C. McPherson.
19 Copyright (C) 2012 Jeroen Hegeman.
20 Copyright (C) 2012-2015 Jérémy Rosen.
21 Copyright (C) 2012-2013, 2015, 2018-2019 parafin.
22 Copyright (C) 2012 Richard Wonka.
23 Copyright (C) 2013, 2021 Aldric Renaudin.
24 Copyright (C) 2013 Jens Fendler.
25 Copyright (C) 2013, 2015, 2017, 2019-2022 Pascal Obry.
26 Copyright (C) 2013 Simon Spannagel.
27 Copyright (C) 2013 sthen.
28 Copyright (C) 2013 Stuart Henderson.
29 Copyright (C) 2014 Fernando R.
30 Copyright (C) 2014 Moritz Lipp.
31 Copyright (C) 2014-2015 Pedro Côrte-Real.
32 Copyright (C) 2014-2017, 2020 Roman Lebedev.
33 Copyright (C) 2015, 2017, 2019 Dan Torop.
34 Copyright (C) 2015 Jean-Sébastien Pédron.
35 Copyright (C) 2015 K. Adam Christensen.
36 Copyright (C) 2015 Matthias Gehre.
37 Copyright (C) 2016-2018 Peter Budai.
38 Copyright (C) 2017, 2021 luzpaz.
39 Copyright (C) 2018-2019 Edgardo Hoszowski.
40 Copyright (C) 2019 Alexis Mousset.
41 Copyright (C) 2019 Andreas Schneider.
42 Copyright (C) 2019, 2022-2023, 2025-2026 Aurélien PIERRE.
43 Copyright (C) 2019 Felipe Contreras.
44 Copyright (C) 2019-2022 Hanno Schwalm.
45 Copyright (C) 2019 Heiko Bauke.
46 Copyright (C) 2019 jakubfi.
47 Copyright (C) 2020 Chris Elston.
48 Copyright (C) 2020 David-Tillmann Schaefer.
49 Copyright (C) 2020-2022 Diederik Ter Rahe.
50 Copyright (C) 2020-2021 Hubert Kowalski.
51 Copyright (C) 2020 Matthieu Volat.
52 Copyright (C) 2020-2022 Philippe Weyland.
53 Copyright (C) 2020-2021 Ralf Brown.
54 Copyright (C) 2021 Ilya Kurdyukov.
55 Copyright (C) 2021 Paolo DePetrillo.
56 Copyright (C) 2022 Martin Bařinka.
57 Copyright (C) 2022 Victor Forsiuk.
58 Copyright (C) 2023 lologor.
59 Copyright (C) 2023 Luca Zulberti.
60 Copyright (C) 2023 Maurizio Paglia.
61 Copyright (C) 2024 Alynx Zhou.
62 Copyright (C) 2025-2026 Guillaume Stutin.
63 Copyright (C) 2025 Miguel Moquillon.
64
65 darktable is free software: you can redistribute it and/or modify
66 it under the terms of the GNU General Public License as published by
67 the Free Software Foundation, either version 3 of the License, or
68 (at your option) any later version.
69
70 darktable is distributed in the hope that it will be useful,
71 but WITHOUT ANY WARRANTY; without even the implied warranty of
72 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73 GNU General Public License for more details.
74
75 You should have received a copy of the GNU General Public License
76 along with darktable. If not, see <http://www.gnu.org/licenses/>.
77*/
78#ifdef HAVE_CONFIG_H
79#include "config.h"
80#endif
81
83
84#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
85#include <malloc.h>
86#endif
87#ifdef __APPLE__
88#include <sys/malloc.h>
89#endif
90
91#include "common/collection.h"
92#include "common/colorspaces.h"
93#include "common/colorlabels.h"
94#include "common/darktable.h"
95#include "common/datetime.h"
96#include "common/exif.h"
97#include "common/history.h"
99#include "common/selection.h"
101#include "common/sentry.h"
102#include "common/telemetry.h"
104#include "bauhaus/bauhaus.h"
105#include "gui/presets.h"
106#include "gui/splash.h"
107
108#include "common/file_location.h"
109#include "common/film.h"
110#include "common/grealpath.h"
111#include "common/image.h"
112#include "common/image_cache.h"
114#include "common/iop_order.h"
115#include "common/l10n.h"
116#include "common/metadata.h"
117#include "common/mipmap_cache.h"
118#include "common/noiseprofiles.h"
119#include "common/opencl.h"
120#include "common/points.h"
122#include "common/tags.h"
123#include "common/styles.h"
124#include "common/undo.h"
125#include "common/fp_mode.h"
126#include "control/conf.h"
127#include "control/control.h"
128#include "control/crawler.h"
131#include "control/signal.h"
132#include "develop/blend.h"
134#include "develop/imageop.h"
135
136#include "gui/gtk.h"
137#include "gui/gui_throttle.h"
138#include "gui/guides.h"
139#include "gui/presets.h"
140#include "libs/lib.h"
141#include "views/view.h"
142#include "conf_gen.h"
143
144#include <errno.h>
145#if !defined(_WIN32) && !defined(__APPLE__)
146#include <fontconfig/fontconfig.h>
147#endif
148#include <glib.h>
149#include <glib/gstdio.h>
150#include <pango/pangocairo.h>
151#include <stdint.h>
152#include <stdio.h>
153#include <stdlib.h>
154#include <string.h>
155#include <sys/param.h>
156#include <sys/types.h>
157#include <unistd.h>
158#include <locale.h>
159#include <limits.h>
160
161#if defined(__x86_64__) || defined(__i386__)
162#include <xmmintrin.h>
163#endif
164
165#ifdef HAVE_GRAPHICSMAGICK
166#include <magick/api.h>
167#elif defined HAVE_IMAGEMAGICK
168#include <MagickWand/MagickWand.h>
169#endif
170
171#include "dbus.h"
172
173#if defined(__SUNOS__)
174#include <sys/varargs.h>
175#endif
176
177#ifdef _OPENMP
178#include <omp.h>
179#endif
180
182
183#if !defined(_WIN32) && !defined(__APPLE__)
184typedef struct _PangoFcFontMap PangoFcFontMap;
185extern GType pango_fc_font_map_get_type(void);
187#endif
188
195static GLogWriterOutput _gtk_log_writer_filter(GLogLevelFlags log_level, const GLogField *fields,
196 gsize n_fields, gpointer user_data)
197{
198 const gchar *message = NULL;
199
200 for(gsize k = 0; k < n_fields; k++)
201 {
202 if(g_strcmp0(fields[k].key, "MESSAGE")) continue;
203
204 message = fields[k].value;
205 break;
206 }
207
208 // Silence only warnings/errors that come from default Adwaita CSS or desktop theme
209 // because there is nothing we can do about those.
210 // Yes, default Adwaita GTK CSS is still using deprecated GTK stuff in 2026...
211 // Even those morons can't keep up with the pace of their own deprecations.
212 if(message)
213 {
214 if(!g_strcmp0(message, "Unable to load dot from the cursor theme"))
215 return G_LOG_WRITER_HANDLED;
216
217 if(g_str_has_prefix(message, "Theme parsing error:")
218 && g_str_has_suffix(message, "The :insensitive pseudo-class is deprecated. Use :disabled instead."))
219 return G_LOG_WRITER_HANDLED;
220
221 if(g_str_has_prefix(message, "Theme parsing error:")
222 && g_str_has_suffix(message, "The :inconsistent pseudo-class is deprecated. Use :indeterminate instead."))
223 return G_LOG_WRITER_HANDLED;
224 }
225
226 return g_log_writer_default(log_level, fields, n_fields, user_data);
227}
228
229static int usage(const char *argv0)
230{
231#ifdef _WIN32
232 char *logfile = g_build_filename(g_get_user_cache_dir(), "ansel", "ansel-log.txt", NULL);
233#endif
234 // clang-format off
235 printf("usage: %s [options] [IMG_1234.{RAW,..}|image_folder/]\n", argv0);
236 printf("\n");
237 printf("options:\n");
238 printf("\n");
239 printf(" --cachedir <user cache directory>\n");
240 printf(" --conf <key>=<value>\n");
241 printf(" --configdir <user config directory>\n");
242 printf(" -d {all,cache,camctl,camsupport,colorprofile,control,demosaic,dev,gtk,history,imageio,import,\n");
243 printf(" input,ioporder,lighttable,lua,masks,memory,nan,nocache_reuse,opencl,params,\n");
244 printf(" perf,pipe,pipecache,print,pwstorage,signal,sql,shortcuts,tiling,undo,verbose}\n");
245 printf(" --d-signal <signal> \n");
246 printf(" --d-signal-act <all,raise,connect,disconnect");
247 // clang-format on
248#ifdef DT_HAVE_SIGNAL_TRACE
249 printf(",print-trace");
250#endif
251 printf(">\n");
252 printf(" --datadir <data directory>\n");
253#ifdef HAVE_OPENCL
254 printf(" --disable-opencl\n");
255#endif
256 printf(" -h, --help");
257#ifdef _WIN32
258 printf(", /?");
259#endif
260 printf("\n");
261 printf(" --library <library file>\n");
262 printf(" --localedir <locale directory>\n");
263 printf(" --moduledir <module directory>\n");
264 printf(" --noiseprofiles <noiseprofiles json file>\n");
265 printf(" -t <num openmp threads>\n");
266 printf(" --tmpdir <tmp directory>\n");
267 printf(" --version\n");
268#ifdef _WIN32
269 printf("\n");
270 printf(" note: debug log and output will be written to this file:\n");
271 printf(" %s\n", logfile);
272#endif
273
274#ifdef _WIN32
275 dt_free(logfile);
276#endif
277
278 return 1;
279}
280
282{
283 char ver[100] = { 0 };
284 g_strlcpy(ver, darktable_package_string, sizeof(ver));
285 int count = -1;
286 char *start = ver;
287 for(char *p = ver; *p; p++)
288 {
289 // first look for a number
290 if(count == -1)
291 {
292 if(*p >= '0' && *p <= '9')
293 {
294 count++;
295 start = p;
296 }
297 }
298 // then check for <major>.<minor>
299 else
300 {
301 if(*p == '.' || *p == '+') count++;
302 if(count == 2)
303 {
304 *p = '\0';
305 break;
306 }
307 }
308 }
309 return g_strdup(start);
310}
311
312gboolean dt_supported_image(const gchar *filename)
313{
314 gboolean supported = FALSE;
315 char *ext = g_strrstr(filename, ".");
316 if(IS_NULL_PTR(ext))
317 return FALSE;
318 ext++;
319 for(const char **i = dt_supported_extensions; !IS_NULL_PTR(*i); i++)
320 if(!g_ascii_strncasecmp(ext, *i, strlen(*i)))
321 {
322 supported = TRUE;
323 break;
324 }
325 return supported;
326}
327
328int dt_load_from_string(const gchar *input, gboolean open_image_in_dr, gboolean *single_image)
329{
330 int32_t id = 0;
331 if(IS_NULL_PTR(input) || input[0] == '\0') return 0;
332
333 char *filename = dt_util_normalize_path(input);
334
335 if(IS_NULL_PTR(filename))
336 {
337 dt_control_log(_("found strange path `%s'"), input);
338 return 0;
339 }
340
341 if(g_file_test(filename, G_FILE_TEST_IS_DIR))
342 {
343 // import a directory into a film roll
344 id = dt_film_import(filename);
345 if(id)
346 {
347 dt_film_open(id);
348 dt_ctl_switch_mode_to("lighttable");
349 }
350 else
351 {
352 dt_control_log(_("error loading directory `%s'"), filename);
353 }
354 if(single_image) *single_image = FALSE;
355 }
356 else
357 {
358 // import a single image
359 gchar *directory = g_path_get_dirname((const gchar *)filename);
360 dt_film_t film;
361 const int filmid = dt_film_new(&film, directory);
362 id = dt_image_import(filmid, filename, TRUE);
363 dt_free(directory);
364 if(id)
365 {
366 dt_film_open(filmid);
367 // make sure buffers are loaded (load full for testing)
370 gboolean loaded = (!IS_NULL_PTR(buf.buf));
372 if(!loaded)
373 {
374 id = 0;
375 dt_control_log(_("file `%s' has unknown format!"), filename);
376 }
377 else
378 {
379 if(open_image_in_dr)
380 {
382 dt_ctl_switch_mode_to("darkroom");
383 }
384 }
385 }
386 else
387 {
388 dt_control_log(_("error loading file `%s'"), filename);
389 }
390 if(single_image) *single_image = TRUE;
391 }
392 dt_free(filename);
393 return id;
394}
395
396// Returns total system memory in kiloBytes
397static inline size_t _get_total_memory()
398{
399#if defined(__linux__)
400 FILE *f = g_fopen("/proc/meminfo", "rb");
401 if(IS_NULL_PTR(f)) return 0;
402 size_t mem = 0;
403 char *line = NULL;
404 size_t len = 0;
405 int first = 1, found = 0;
406 // return "MemTotal" or the value from the first line
407 while(!found && getline(&line, &len, f) != -1)
408 {
409 char *colon = strchr(line, ':');
410 if(IS_NULL_PTR(colon)) continue;
411 found = !strncmp(line, "MemTotal:", 9);
412 if(found || first) mem = atol(colon + 1);
413 first = 0;
414 }
415 fclose(f);
416 if(len > 0)
417 {
418 dt_free(line);
419 }
420 return mem;
421#elif defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) \
422 || defined(__OpenBSD__)
423#if defined(__APPLE__)
424 int mib[2] = { CTL_HW, HW_MEMSIZE };
425#elif defined(HW_PHYSMEM64)
426 int mib[2] = { CTL_HW, HW_PHYSMEM64 };
427#else
428 int mib[2] = { CTL_HW, HW_PHYSMEM };
429#endif
430 uint64_t physical_memory;
431 size_t length = sizeof(uint64_t);
432 sysctl(mib, 2, (void *)&physical_memory, &length, (void *)NULL, 0);
433 return physical_memory / 1024;
434#elif defined _WIN32
435 MEMORYSTATUSEX memInfo;
436 memInfo.dwLength = sizeof(MEMORYSTATUSEX);
437 GlobalMemoryStatusEx(&memInfo);
438 return memInfo.ullTotalPhys / (uint64_t)1024;
439#else
440 // assume 2GB until we have a better solution.
441 fprintf(stderr, "Unknown memory size. Assuming 2GB\n");
442 return 2097152;
443#endif
444}
445
446void *dt_alloc_align(size_t size)
447{
449}
450
451int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
452{
453 double start_wtime = dt_get_wtime();
454
455#ifndef _WIN32
456 if(getuid() == 0 || geteuid() == 0)
457 printf(
458 "WARNING: either your user id or the effective user id are 0. are you running darktable as root?\n");
459#endif
460
461 dt_fp_init(DT_FP_MODE_FAST);
462
464
465#ifdef M_MMAP_THRESHOLD
466 mallopt(M_MMAP_THRESHOLD, 128 * 1024); /* use mmap() for large allocations */
467#endif
468
469 // make sure that stack/frame limits are good (musl)
471
472 // init all pointers to 0:
473 memset(&darktable, 0, sizeof(darktable_t));
474
475 darktable.start_wtime = start_wtime;
476
477 darktable.progname = argv[0];
478
479 darktable.main_message = NULL;
480
481 // FIXME: move there into dt_database_t
482 pthread_mutexattr_t recursive_locking;
483 pthread_mutexattr_init(&recursive_locking);
484 pthread_mutexattr_settype(&recursive_locking, PTHREAD_MUTEX_RECURSIVE);
491
492 darktable.control = (dt_control_t *)calloc(1, sizeof(dt_control_t));
493
494 // database
495 char *dbfilename_from_command = NULL;
496 char *noiseprofiles_from_command = NULL;
497 char *datadir_from_command = NULL;
498 char *moduledir_from_command = NULL;
499 char *localedir_from_command = NULL;
500 char *tmpdir_from_command = NULL;
501 char *configdir_from_command = NULL;
502 char *cachedir_from_command = NULL;
503 char *kerneldir_from_command = NULL;
504
505#ifdef HAVE_OPENCL
506 gboolean exclude_opencl = FALSE;
507 gboolean print_statistics = (strstr(argv[0], "ansel-cltest") == NULL);
508#endif
509
511#ifdef _OPENMP
513#endif
514
515 darktable.unmuted = 0;
516 gboolean cpu_threads_from_cli = FALSE;
517
518 GSList *config_override = NULL;
519 for(int k = 1; k < argc; k++)
520 {
521#ifdef _WIN32
522 if(!strcmp(argv[k], "/?"))
523 {
524 return usage(argv[0]);
525 }
526#endif
527 if(argv[k][0] == '-')
528 {
529 if(!strcmp(argv[k], "--help") || !strcmp(argv[k], "-h"))
530 {
531 return usage(argv[0]);
532 }
533 else if(!strcmp(argv[k], "--version"))
534 {
535 printf("this is %s\ncopyright (c) 2009-2022 Johannes Hanika, (c) 2022-%s Aurélien Pierre\n" PACKAGE_BUGREPORT "\n\ncompile options:\n"
536 " bit depth is %" G_GSIZE_FORMAT " bit\n"
537#ifdef _DEBUG
538 " debug build\n"
539#else
540 " normal build\n"
541#endif
542#ifdef _OPENMP
543 " OpenMP support enabled\n"
544#else
545 " OpenMP support disabled\n"
546#endif
547
548#ifdef HAVE_OPENCL
549 " OpenCL support enabled\n"
550#else
551 " OpenCL support disabled\n"
552#endif
553
554#ifdef USE_COLORDGTK
555 " Colord support enabled\n"
556#else
557 " Colord support disabled\n"
558#endif
559
560#ifdef HAVE_GRAPHICSMAGICK
561 " GraphicsMagick support enabled\n"
562#else
563 " GraphicsMagick support disabled\n"
564#endif
565
566#ifdef HAVE_IMAGEMAGICK
567 " ImageMagick support enabled\n"
568#else
569 " ImageMagick support disabled\n"
570#endif
571
572#ifdef HAVE_OPENEXR
573 " OpenEXR support enabled\n"
574#else
575 " OpenEXR support disabled\n"
576#endif
577 ,
580 CHAR_BIT * sizeof(void *)
581 );
582 return 1;
583 }
584 else if(!strcmp(argv[k], "--library") && argc > k + 1)
585 {
586 dbfilename_from_command = argv[++k];
587 argv[k-1] = NULL;
588 argv[k] = NULL;
589 }
590 else if(!strcmp(argv[k], "--datadir") && argc > k + 1)
591 {
592 datadir_from_command = argv[++k];
593 argv[k-1] = NULL;
594 argv[k] = NULL;
595 }
596 else if(!strcmp(argv[k], "--moduledir") && argc > k + 1)
597 {
598 moduledir_from_command = argv[++k];
599 argv[k-1] = NULL;
600 argv[k] = NULL;
601 }
602 else if(!strcmp(argv[k], "--tmpdir") && argc > k + 1)
603 {
604 tmpdir_from_command = argv[++k];
605 argv[k-1] = NULL;
606 argv[k] = NULL;
607 }
608 else if(!strcmp(argv[k], "--configdir") && argc > k + 1)
609 {
610 configdir_from_command = argv[++k];
611 argv[k-1] = NULL;
612 argv[k] = NULL;
613 }
614 else if(!strcmp(argv[k], "--cachedir") && argc > k + 1)
615 {
616 cachedir_from_command = argv[++k];
617 argv[k-1] = NULL;
618 argv[k] = NULL;
619 }
620 else if(!strcmp(argv[k], "--localedir") && argc > k + 1)
621 {
622 localedir_from_command = argv[++k];
623 argv[k-1] = NULL;
624 argv[k] = NULL;
625 }
626 else if(!strcmp(argv[k], "--kerneldir") && argc > k + 1)
627 {
628 kerneldir_from_command = argv[++k];
629 argv[k-1] = NULL;
630 argv[k] = NULL;
631 }
632 else if(argv[k][1] == 'd' && argc > k + 1)
633 {
634 if(!strcmp(argv[k + 1], "all"))
635 darktable.unmuted = 0xffffffff & ~DT_DEBUG_VERBOSE; // enable all debug information except verbose
636 else if(!strcmp(argv[k + 1], "cache"))
637 darktable.unmuted |= DT_DEBUG_CACHE; // enable debugging for lib/film/cache module
638 else if(!strcmp(argv[k + 1], "control"))
639 darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
640 else if(!strcmp(argv[k + 1], "dev"))
641 darktable.unmuted |= DT_DEBUG_DEV; // develop module
642 else if(!strcmp(argv[k + 1], "gtk"))
643 darktable.unmuted |= DT_DEBUG_GTK; // GTK widgets and display setup
644 else if(!strcmp(argv[k + 1], "input"))
645 darktable.unmuted |= DT_DEBUG_INPUT; // input devices
646 else if(!strcmp(argv[k + 1], "pipecache"))
647 darktable.unmuted |= DT_DEBUG_PIPECACHE; // pipeline cache
648 else if(!strcmp(argv[k + 1], "perf"))
649 darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
650 else if(!strcmp(argv[k + 1], "pwstorage"))
651 darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
652 else if(!strcmp(argv[k + 1], "opencl"))
653 darktable.unmuted |= DT_DEBUG_OPENCL; // gpu accel via opencl
654 else if(!strcmp(argv[k + 1], "sql"))
655 darktable.unmuted |= DT_DEBUG_SQL; // SQLite3 queries
656 else if(!strcmp(argv[k + 1], "memory"))
657 darktable.unmuted |= DT_DEBUG_MEMORY; // some stats on mem usage now and then.
658 else if(!strcmp(argv[k + 1], "lighttable"))
659 darktable.unmuted |= DT_DEBUG_LIGHTTABLE; // lighttable related stuff.
660 else if(!strcmp(argv[k + 1], "nan"))
661 darktable.unmuted |= DT_DEBUG_NAN; // check for NANs when processing the pipe.
662 else if(!strcmp(argv[k + 1], "masks"))
663 darktable.unmuted |= DT_DEBUG_MASKS; // masks related stuff.
664 else if(!strcmp(argv[k + 1], "lua"))
665 darktable.unmuted |= DT_DEBUG_LUA; // lua errors are reported on console
666 else if(!strcmp(argv[k + 1], "print"))
667 darktable.unmuted |= DT_DEBUG_PRINT; // print errors are reported on console
668 else if(!strcmp(argv[k + 1], "camsupport"))
669 darktable.unmuted |= DT_DEBUG_CAMERA_SUPPORT; // camera support warnings are reported on console
670 else if(!strcmp(argv[k + 1], "colorprofile"))
671 darktable.unmuted |= DT_DEBUG_COLORPROFILE; // color profile handling
672 else if(!strcmp(argv[k + 1], "nocache_reuse"))
673 darktable.unmuted |= DT_DEBUG_NOCACHE_REUSE; // disable reusable pixelpipe cache buffers
674 else if(!strcmp(argv[k + 1], "ioporder"))
675 darktable.unmuted |= DT_DEBUG_IOPORDER; // iop order information are reported on console
676 else if(!strcmp(argv[k + 1], "imageio"))
677 darktable.unmuted |= DT_DEBUG_IMAGEIO; // image importing or exporting messages on console
678 else if(!strcmp(argv[k + 1], "undo"))
679 darktable.unmuted |= DT_DEBUG_UNDO; // undo/redo
680 else if(!strcmp(argv[k + 1], "signal"))
681 darktable.unmuted |= DT_DEBUG_SIGNAL; // signal information on console
682 else if(!strcmp(argv[k + 1], "params"))
683 darktable.unmuted |= DT_DEBUG_PARAMS; // iop module params checks on console
684 else if(!strcmp(argv[k + 1], "demosaic"))
686 else if(!strcmp(argv[k + 1], "shortcuts"))
688 else if(!strcmp(argv[k + 1], "tiling"))
690 else if(!strcmp(argv[k + 1], "verbose"))
692 else if(!strcmp(argv[k + 1], "pipe"))
694 else if(!strcmp(argv[k + 1], "history"))
696 else if(!strcmp(argv[k + 1], "import"))
698 else
699 return usage(argv[0]);
700 k++;
701 argv[k-1] = NULL;
702 argv[k] = NULL;
703 }
704 else if(!strcmp(argv[k], "--d-signal-act") && argc > k + 1)
705 {
706 if(!strcmp(argv[k + 1], "all"))
707 darktable.unmuted_signal_dbg_acts = 0xffffffff; // enable all signal debug information
708 else if(!strcmp(argv[k + 1], "raise"))
709 darktable.unmuted_signal_dbg_acts |= DT_DEBUG_SIGNAL_ACT_RAISE; // enable debugging for signal raising
710 else if(!strcmp(argv[k + 1], "connect"))
711 darktable.unmuted_signal_dbg_acts |= DT_DEBUG_SIGNAL_ACT_CONNECT; // enable debugging for signal connection
712 else if(!strcmp(argv[k + 1], "disconnect"))
713 darktable.unmuted_signal_dbg_acts |= DT_DEBUG_SIGNAL_ACT_DISCONNECT; // enable debugging for signal disconnection
714 else if(!strcmp(argv[k + 1], "print-trace"))
715 {
716#ifdef DT_HAVE_SIGNAL_TRACE
717 darktable.unmuted_signal_dbg_acts |= DT_DEBUG_SIGNAL_ACT_PRINT_TRACE; // enable printing of signal tracing
718#else
719 fprintf(stderr, "[signal] print-trace not available, skipping\n");
720#endif
721 }
722 else
723 return usage(argv[0]);
724 k++;
725 argv[k-1] = NULL;
726 argv[k] = NULL;
727 }
728 else if(!strcmp(argv[k], "--d-signal") && argc > k + 1)
729 {
730 gchar *str = g_ascii_strup(argv[k+1], -1);
731
732 #define CHKSIGDBG(sig) else if(!g_strcmp0(str, #sig)) do {darktable.unmuted_signal_dbg[sig] = TRUE;} while (0)
733 if(!g_strcmp0(str, "ALL"))
734 {
735 for(int sig=0; sig<DT_SIGNAL_COUNT; sig++)
737 }
778
779 else
780 {
781 fprintf(stderr, "unknown signal name: '%s'. use 'ALL' to enable debug for all or use full signal name\n", str);
782 return usage(argv[0]);
783 }
784 dt_free(str);
785 #undef CHKSIGDBG
786 k++;
787 argv[k-1] = NULL;
788 argv[k] = NULL;
789 }
790 else if(argv[k][1] == 't' && argc > k + 1)
791 {
792 darktable.num_openmp_threads = CLAMP(atol(argv[k + 1]), 1, 100);
793 printf("[dt_init] using %d threads for openmp parallel sections\n", darktable.num_openmp_threads);
794 k++;
795 argv[k-1] = NULL;
796 argv[k] = NULL;
797 cpu_threads_from_cli = TRUE;
798 }
799 else if(!strcmp(argv[k], "--conf") && argc > k + 1)
800 {
801 gchar *keyval = g_strdup(argv[++k]), *c = keyval;
802 argv[k-1] = NULL;
803 argv[k] = NULL;
804 gchar *end = keyval + strlen(keyval);
805 while(*c != '=' && c < end) c++;
806 if(*c == '=' && *(c + 1) != '\0')
807 {
808 *c++ = '\0';
810 entry->key = g_strdup(keyval);
811 entry->value = g_strdup(c);
812 config_override = g_slist_append(config_override, entry);
813 }
814 dt_free(keyval);
815 }
816 else if(!strcmp(argv[k], "--noiseprofiles") && argc > k + 1)
817 {
818 noiseprofiles_from_command = argv[++k];
819 argv[k-1] = NULL;
820 argv[k] = NULL;
821 }
822 else if(!strcmp(argv[k], "--disable-opencl"))
823 {
824#ifdef HAVE_OPENCL
825 exclude_opencl = TRUE;
826#endif
827 argv[k] = NULL;
828 }
829 else if(!strcmp(argv[k], "--debug"))
830 {
831 argv[k] = NULL;
832 }
833 else if(!strcmp(argv[k], "--"))
834 {
835 // "--" confuses the argument parser of glib/gtk. remove it.
836 argv[k] = NULL;
837 break;
838 }
839#ifdef __APPLE__
840 else if(!strncmp(argv[k], "-psn_", 5))
841 {
842 // "-psn_*" argument is added automatically by macOS and should be ignored
843 argv[k] = NULL;
844 }
845#endif
846 else
847 return usage(argv[0]); // fail on unrecognized options
848 }
849 }
850
851 // remove the NULLs to not confuse gtk_init() later.
852 for(int i = 1; i < argc; i++)
853 {
854 int k;
855 for(k = i; k < argc; k++)
856 if(!IS_NULL_PTR(argv[k])) break;
857
858 if(k > i)
859 {
860 k -= i;
861 for(int j = i + k; j < argc; j++)
862 {
863 argv[j-k] = argv[j];
864 argv[j] = NULL;
865 }
866 argc -= k;
867 }
868 }
869
870 // get valid directories
871 dt_loc_init(datadir_from_command, moduledir_from_command, localedir_from_command, configdir_from_command, cachedir_from_command, tmpdir_from_command, kerneldir_from_command);
872
873 fprintf(stdout, "[build] version: %s\n", darktable_package_string);
874 fprintf(stdout, "[build] type: %s | cpu mode: %s\n", DT_BUILD_TYPE, DT_BUILD_CPU_MODE);
875 fprintf(stdout, "[build] c compiler: %s\n", DT_BUILD_C_COMPILER);
876 fprintf(stdout, "[build] c flags: %s\n", DT_BUILD_C_FLAGS);
877 fprintf(stdout, "[build] c++ compiler: %s\n", DT_BUILD_CXX_COMPILER);
878 fprintf(stdout, "[build] c++ flags: %s\n", DT_BUILD_CXX_FLAGS);
879
881 {
882 fprintf(stderr, "[memory] at startup\n");
884 }
885
886 char sharedir[PATH_MAX] = { 0 };
887 dt_loc_get_sharedir(sharedir, sizeof(sharedir));
888
889 // we have to have our share dir in XDG_DATA_DIRS,
890 // otherwise GTK+ won't find our logo for the about screen (and maybe other things)
891 {
892 const gchar *xdg_data_dirs = g_getenv("XDG_DATA_DIRS");
893 gchar *new_xdg_data_dirs = NULL;
894 gboolean set_env = TRUE;
895 if(!IS_NULL_PTR(xdg_data_dirs) && *xdg_data_dirs != '\0')
896 {
897 // check if sharedir is already in there
898 gboolean found = FALSE;
899 gchar **tokens = g_strsplit(xdg_data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
900 // xdg_data_dirs is neither NULL nor empty => !IS_NULL_PTR(tokens)
901 for(char **iter = tokens; !IS_NULL_PTR(*iter); iter++)
902 if(!strcmp(sharedir, *iter))
903 {
904 found = TRUE;
905 break;
906 }
907 g_strfreev(tokens);
908 if(found)
909 set_env = FALSE;
910 else
911 new_xdg_data_dirs = g_strjoin(G_SEARCHPATH_SEPARATOR_S, sharedir, xdg_data_dirs, NULL);
912 }
913 else
914 {
915#ifndef _WIN32
916 // see http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html for a reason to use those as a
917 // default
918 if(!g_strcmp0(sharedir, "/usr/local/share")
919 || !g_strcmp0(sharedir, "/usr/local/share/")
920 || !g_strcmp0(sharedir, "/usr/share") || !g_strcmp0(sharedir, "/usr/share/"))
921 new_xdg_data_dirs = g_strdup("/usr/local/share/" G_SEARCHPATH_SEPARATOR_S "/usr/share/");
922 else
923 new_xdg_data_dirs = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "/usr/local/share/" G_SEARCHPATH_SEPARATOR_S
924 "/usr/share/", sharedir);
925#else
926 set_env = FALSE;
927#endif
928 }
929
930 if(set_env) g_setenv("XDG_DATA_DIRS", new_xdg_data_dirs, 1);
931 dt_print(DT_DEBUG_DEV, "new_xdg_data_dirs: %s\n", new_xdg_data_dirs);
932 dt_free(new_xdg_data_dirs);
933 }
934
935 setlocale(LC_ALL, "");
936 char localedir[PATH_MAX] = { 0 };
937 dt_loc_get_localedir(localedir, sizeof(localedir));
938 bindtextdomain(GETTEXT_PACKAGE, localedir);
939 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
940 textdomain(GETTEXT_PACKAGE);
941
942 if(init_gui)
943 {
944 // I doubt that connecting to dbus for ansel-cli makes sense
945 darktable.dbus = NULL; //dt_dbus_init();
946
947 // make sure that we have no stale global progress bar visible. thus it's run as early as possible
949 }
950
951 // thread-safe init:
952 dt_exif_init();
953 char datadir[PATH_MAX] = { 0 };
954 dt_loc_get_user_config_dir(datadir, sizeof(datadir));
955 char anselrc[PATH_MAX] = { 0 };
956 dt_concat_path_file(anselrc, datadir, "anselrc");
957
958 // initialize the config backend. this needs to be done first...
959 darktable.conf = (dt_conf_t *)calloc(1, sizeof(dt_conf_t));
960 dt_conf_init(darktable.conf, anselrc, config_override);
961 g_slist_free_full(config_override, dt_free_gpointer);
962
963 // set the interface language and prepare selection for prefs
964 darktable.l10n = dt_l10n_init(init_gui);
965
966 dt_confgen_init();
968
969 // Needs to run after dt_confgen_init()
970 // Don't override cli argument if any
971 if(!cpu_threads_from_cli)
972 {
973 const int user_threads = dt_conf_get_int("cpu_threads");
974 if(user_threads > 0) darktable.num_openmp_threads = user_threads;
975 }
976
977#ifdef _OPENMP
978 omp_set_num_threads(darktable.num_openmp_threads);
979#endif
980
981 // we need this REALLY early so that error messages can be shown, however after gtk_disable_setlocale
982 if(init_gui)
983 {
984 g_log_set_writer_func(_gtk_log_writer_filter, NULL, NULL);
985 gtk_init(&argc, &argv);
986
987 darktable.themes = NULL;
988 }
989
990 // get the list of color profiles
992
993 // initialize datetime data
995
996 // initialize the database
997 gboolean recheck_needed = TRUE;
998 while (recheck_needed)
999 {
1000 darktable.db = dt_database_init(dbfilename_from_command, load_data, init_gui);
1002 {
1003 printf("ERROR : cannot open database\n");
1005 return 1;
1006 }
1008 {
1009 gboolean error = FALSE;
1010
1011 if (init_gui)
1012 {
1013 gboolean image_loaded_elsewhere = FALSE;
1014#ifndef MAC_INTEGRATION
1015 // send the images to the other instance via dbus
1016 fprintf(stderr, "trying to open the images in the running instance\n");
1017
1019 {
1020 GDBusConnection *connection = NULL;
1021 for(int i = 1; i < argc; i++)
1022 {
1023 // make the filename absolute ...
1024 if(argv[i] == NULL || *argv[i] == '\0') continue;
1025 gchar *filename = dt_util_normalize_path(argv[i]);
1026 if(IS_NULL_PTR(filename)) continue;
1027 if(IS_NULL_PTR(connection)) connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
1028 // ... and send it to the running instance of darktable
1029 image_loaded_elsewhere = g_dbus_connection_call_sync(connection, "org.darktable.service", "/darktable",
1030 "org.darktable.service.Remote", "Open",
1031 g_variant_new("(s)", filename), NULL,
1032 G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL) != NULL;
1033 dt_free(filename);
1034 }
1035 if(connection) g_object_unref(connection);
1036 }
1037#endif
1038 if(!image_loaded_elsewhere) error = dt_database_show_error(darktable.db);
1039 }
1040 if(error)
1041 {
1042 fprintf(stderr, "ERROR: can't acquire database lock, aborting.\n");
1044 return error;
1045 }
1046 else
1047 {
1048 // try again
1049 continue;
1050 }
1051 }
1052 recheck_needed = FALSE;
1053 }
1054
1055 //db maintenance on startup (if configured to do so)
1057 {
1059 }
1060
1061 // init darktable tags table
1063
1064 // Initialize the signal system
1066 // Critical: ensure image cache gets refreshed BEFORE any other IMAGE_INFO_CHANGED handlers.
1067 // This handler reloads dt_image_t from DB so all downstream callbacks see fresh metadata.
1069
1070 // Make sure that the database and xmp files are in sync
1071 // We need conf and db to be up and running for that which is the case here.
1072 // FIXME: is this also useful in non-gui mode?
1073 GList *changed_xmp_files = NULL;
1074 if(init_gui && dt_conf_get_bool("run_crawler_on_start"))
1075 {
1076 changed_xmp_files = dt_control_crawler_run();
1077 }
1078
1079 if(init_gui)
1080 {
1082 }
1083 else
1084 {
1085 if(dbfilename_from_command && !strcmp(dbfilename_from_command, ":memory:"))
1086 dt_gui_presets_init(); // init preset db schema.
1090 }
1091
1092 // we initialize grouping early because it's needed for collection init
1093 // idem for folder reachability
1094 if(init_gui)
1095 {
1096 darktable.gui = (dt_gui_gtk_t *)calloc(1, sizeof(dt_gui_gtk_t));
1097 memset(darktable.gui->scroll_to, 0, sizeof(darktable.gui->scroll_to));
1099 }
1100
1101 // initialize collection query
1103
1104 /* initialize selection */
1106
1107 /* capabilities set to NULL */
1108 darktable.capabilities = NULL;
1109
1110 // Initialize the password storage engine
1112
1114
1115#ifdef HAVE_GRAPHICSMAGICK
1116 /* GraphicsMagick init */
1117 InitializeMagick(darktable.progname);
1118
1119 // *SIGH*
1121
1122#elif defined HAVE_IMAGEMAGICK
1123
1124 /* ImageMagick init */
1125 MagickWandGenesis();
1126
1127#endif
1128
1129 darktable.noiseprofile_parser = dt_noiseprofile_init(noiseprofiles_from_command);
1130
1131 // The GUI must be initialized before the views, because the init()
1132 // functions of the views depend on darktable.control->accels_* to register
1133 // their keyboard accelerators
1134
1135 // TODO : Make a single call to unified GUI API initializing everything graphical at once.
1136 // The current tangled mess is a nightmare to maintain.
1137
1138 if(init_gui)
1139 {
1141 {
1142 fprintf(stderr, "ERROR: can't init gui, aborting.\n");
1144 return 1;
1145 }
1147 }
1148 else
1149 darktable.gui = NULL;
1150
1151 // This needs to run after gui init because we init cache lines size with window size
1152 // but before image cache init and pipeline cache init (aka dev init aka darkroom init aka viewmanager init)
1153 // because we init its size here
1155
1158
1159 // check whether we were able to load darkroom view. if we failed, we'll crash everywhere later on.
1161 {
1162 fprintf(stderr, "ERROR: can't init develop system, aborting.\n");
1164 return 1;
1165 }
1166
1169 {
1170 fprintf(stderr, "ERROR: can't init pixelpipe cache, aborting.\n");
1172 return 1;
1173 }
1174
1175 darktable.points = (dt_points_t *)calloc(1, sizeof(dt_points_t));
1177
1178 // must come before mipmap_cache, because that one will need to access
1179 // image dimensions stored in here:
1182
1185
1186 darktable.opencl = (dt_opencl_t *)calloc(1, sizeof(dt_opencl_t));
1187#ifdef HAVE_OPENCL
1188 dt_opencl_init(darktable.opencl, exclude_opencl, print_statistics);
1189 // Show the splash only while compiling OpenCL kernels (triggered from opencl.c),
1190 // then close it immediately so the rest of the startup stays splash-free.
1192#endif
1193
1194 darktable.imageio = (dt_imageio_t *)calloc(1, sizeof(dt_imageio_t));
1196
1197 // load default iop order
1199 // load iop order rules
1201 // load the darkroom mode plugins once:
1203 // check if all modules have a iop order assigned
1205 {
1206 fprintf(stderr, "ERROR: iop order looks bad, aborting.\n");
1208 return 1;
1209 }
1210
1211 // set up memory.darktable_iop_names table
1213
1214 // set up the list of exiv2 metadata
1216
1217 // init metadata flags
1219
1220 if(init_gui)
1221 {
1222 darktable.lib = (dt_lib_t *)calloc(1, sizeof(dt_lib_t));
1224
1225 // prevent bauhaus widgets from sending value-changed signals
1226 // because some of them expect user interactions.
1227 ++darktable.gui->reset;
1228
1229 // init the gui part of views
1231
1232 --darktable.gui->reset;
1233
1234 // initialize undo struct
1236
1237 // Global menu inherits many parts of the GUI,
1238 // so it should be inited last
1240 }
1241
1243 {
1244 fprintf(stderr, "[memory] after successful startup\n");
1246 }
1247
1248 if(init_gui)
1249 {
1250 // we have to call dt_ctl_switch_mode_to() here already to not run into a lua deadlock.
1251 // having another call later is ok
1252 dt_ctl_switch_mode_to("lighttable");
1253
1254#ifndef MAC_INTEGRATION
1255 // load image(s) specified on cmdline.
1256 // this has to happen after lua is initialized as image import can run lua code
1257 if (argc == 2)
1258 {
1259 // If only one image is listed, attempt to load it in darkroom
1260 (void)dt_load_from_string(argv[1], TRUE, NULL);
1261 }
1262 else if (argc > 2)
1263 {
1264 // when multiple names are given, fire up a background job to import them
1266 }
1267#endif
1268 }
1269
1270 // last but not least construct the popup that asks the user about images whose xmp files are newer than the
1271 // db entry
1272 if(init_gui && changed_xmp_files)
1273 {
1274 dt_control_crawler_show_image_list(changed_xmp_files);
1275 }
1276
1277 if(init_gui)
1278 {
1281 //gtk_window_add_accel_group(GTK_WINDOW(dt_ui_main_window(darktable.gui->ui)), darktable.gui->accels->global_accels);
1282 }
1283
1285
1286 // On first launch, ask once for consent to the opt-in data flows (crash reports
1287 // and usage analytics) in a single dialog, before initializing either module so
1288 // their enabled flags are set when they read them.
1289 dt_privacy_ask_consent(init_gui);
1290
1291 // Initialize crash reporting last, after the final dt_set_signal_handlers() so
1292 // sentry's handler sits on top and chains down into our gdb/drmingw fallback.
1293 dt_sentry_init(init_gui);
1294
1295 // Opt-in usage analytics (PostHog) - separate toggle from crash reporting.
1296 dt_telemetry_init(init_gui);
1297
1298 dt_print(DT_DEBUG_CONTROL, "[init] startup took %f seconds\n", dt_get_wtime() - start_wtime);
1299
1300 return 0;
1301}
1302
1303static void _dt_drain_main_context(const int max_iters)
1304{
1305 if(max_iters <= 0) return;
1306 GMainContext *ctx = g_main_context_default();
1307 for(int i = 0; i < max_iters && g_main_context_pending(ctx); i++)
1308 g_main_context_iteration(ctx, FALSE);
1309}
1310
1312{
1313 const int init_gui = (!IS_NULL_PTR(darktable.gui));
1314
1315 // Flush crash reporting and mark this session as a clean exit. Done early so
1316 // events are sent while the rest of the app is still up; the clean-session
1317 // counter it writes is persisted later by dt_conf_cleanup().
1319
1320 // Flush and stop usage analytics.
1322
1323 // Restore selection if exiting on culling mode to be sure it's saved in DB
1326
1327 // Restore auto-computed zoom level to user-defined
1328 dt_conf_set_int("plugins/lighttable/images_in_row", dt_conf_get_int("plugins/lighttable/images_in_row_backup"));
1329
1330 // last chance to ask user for any input...
1331
1332 const gboolean perform_maintenance = dt_database_maybe_maintenance(darktable.db, init_gui, TRUE);
1333 const gboolean perform_snapshot = dt_database_maybe_snapshot(darktable.db);
1334 gchar **snaps_to_remove = NULL;
1335 if(perform_snapshot)
1336 {
1337 snaps_to_remove = dt_database_snaps_to_remove(darktable.db);
1338 }
1339
1340#ifdef HAVE_PRINT
1342#endif
1343
1344 // anything that asks user for input should be placed before this line
1345
1346 if(init_gui)
1347 {
1350
1351 if(darktable.gui->surface)
1352 {
1353 cairo_surface_destroy(darktable.gui->surface);
1354 darktable.gui->surface = NULL;
1355 }
1356
1357 // hide main window and do rest of the cleanup in the background
1358 gtk_widget_hide(dt_ui_main_window(darktable.gui->ui));
1359
1361 //dt_dbus_destroy(darktable.dbus);
1362
1363 // Stop control workers before unloading views and libs. They can still be
1364 // processing lighttable-side jobs while shutdown is tearing down modules.
1366
1368
1371 }
1372
1373 dt_dev_pixelpipe_cache_wait_dump_pending("app-cleanup-before-view-manager");
1376
1377 if(init_gui)
1378 {
1381
1383
1386
1387 /* Force GTK to teardown the toplevel widget tree now, while the main
1388 * context still exists. This helps release style/cairo resources that
1389 * would otherwise stay alive until process exit. */
1390 GtkWidget *main_window = dt_ui_main_window(darktable.gui->ui);
1391 if(GTK_IS_WIDGET(main_window))
1392 gtk_widget_destroy(main_window);
1393
1394 dt_gui_gtk_t *gui = darktable.gui;
1395 darktable.gui = NULL;
1397 dt_free(gui->ui);
1398 dt_free(gui);
1399 }
1400
1408
1411
1412 // Mipmap cleanup may still consult the image cache for paths.
1417
1425 g_list_free_full(darktable.iop_order_list, dt_free_gpointer);
1427 g_list_free_full(darktable.iop_order_rules, dt_free_gpointer);
1429
1430#ifdef HAVE_OPENCL
1432 {
1433 for(int i = 0; i < darktable.opencl->num_devs; i++)
1435 }
1436#endif
1437
1439
1443
1444#ifdef HAVE_GRAPHICSMAGICK
1445 DestroyMagick();
1446#elif defined HAVE_IMAGEMAGICK
1447 MagickWandTerminus();
1448#endif
1449
1451
1452 if(perform_maintenance)
1453 {
1456 }
1457
1459 if(perform_snapshot)
1460 {
1461 if(dt_database_snapshot(darktable.db) && snaps_to_remove)
1462 {
1463 int i = 0;
1464 while(snaps_to_remove[i])
1465 {
1466 // make file to remove writable, mostly problem on windows.
1467 g_chmod(snaps_to_remove[i], S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1468
1469 dt_print(DT_DEBUG_SQL, "[db backup] removing old snap: %s... ", snaps_to_remove[i]);
1470 const int retunlink = g_remove(snaps_to_remove[i++]);
1471 dt_print(DT_DEBUG_SQL, "%s\n", retunlink == 0 ? "success" : "failed!");
1472 }
1473 }
1474 }
1475 if(snaps_to_remove)
1476 {
1477 g_strfreev(snaps_to_remove);
1478 }
1480
1481 if(init_gui)
1482 {
1484 }
1485
1487 {
1488 g_object_unref(darktable.noiseprofile_parser);
1490 }
1491
1492 if(init_gui)
1493 {
1496 }
1497 else
1498 {
1501 }
1503
1505 darktable.signals = NULL;
1506
1508
1515
1517
1518 /* Stop GLib pooled workers first, then release the current thread default
1519 * PangoCairo font map before finalizing Fontconfig caches. */
1520 if(init_gui)
1521 {
1522 g_thread_pool_stop_unused_threads();
1523#if !defined(_WIN32) && !defined(__APPLE__)
1524 PangoFontMap *fontmap = pango_cairo_font_map_get_default();
1525 gboolean use_fontconfig_backend = FALSE;
1526
1527 if(fontmap && PANGO_IS_CAIRO_FONT_MAP(fontmap))
1528 {
1529 const cairo_font_type_t font_backend
1530 = pango_cairo_font_map_get_font_type(PANGO_CAIRO_FONT_MAP(fontmap));
1531 use_fontconfig_backend = (font_backend == CAIRO_FONT_TYPE_FT);
1532 }
1533
1534 if(use_fontconfig_backend && fontmap && g_type_is_a(G_OBJECT_TYPE(fontmap), pango_fc_font_map_get_type()))
1536 if(use_fontconfig_backend) FcFini();
1537#endif
1538 pango_cairo_font_map_set_default(NULL);
1539 }
1540}
1541
1542void dt_print(dt_debug_thread_t thread, const char *msg, ...)
1543{
1544 if(thread == DT_DEBUG_ALWAYS || (darktable.unmuted & thread))
1545 {
1546 printf("%f ", dt_get_wtime() - darktable.start_wtime);
1547 va_list ap;
1548 va_start(ap, msg);
1549 g_vprintf(msg, ap);
1550 va_end(ap);
1551 fflush(stdout);
1552 }
1553}
1554
1555void dt_print_nts(dt_debug_thread_t thread, const char *msg, ...)
1556{
1557 if(thread == DT_DEBUG_ALWAYS || (darktable.unmuted & thread))
1558 {
1559 va_list ap;
1560 va_start(ap, msg);
1561 g_vprintf(msg, ap);
1562 va_end(ap);
1563 fflush(stdout);
1564 }
1565}
1566
1567void dt_vprint(dt_debug_thread_t thread, const char *msg, ...)
1568{
1569 if(thread == DT_DEBUG_ALWAYS || ((darktable.unmuted & DT_DEBUG_VERBOSE) && (darktable.unmuted & thread)))
1570 {
1571 printf("%f ", dt_get_wtime() - darktable.start_wtime);
1572 va_list ap;
1573 va_start(ap, msg);
1574 g_vprintf(msg, ap);
1575 va_end(ap);
1576 fflush(stdout);
1577 }
1578}
1579
1580void dt_show_times(const dt_times_t *start, const char *prefix)
1581{
1582 /* Skip all the calculations an everything if -d perf isn't on */
1584 {
1585 dt_times_t end;
1586 dt_get_times(&end);
1587 char buf[140]; /* Arbitrary size, should be lots big enough for everything used in DT */
1588 snprintf(buf, sizeof(buf), "%s took %.3f secs (%.3f CPU)", prefix, end.clock - start->clock,
1589 end.user - start->user);
1590 dt_print(DT_DEBUG_PERF, "%s\n", buf);
1591 }
1592}
1593
1594void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix, ...)
1595{
1596 /* Skip all the calculations an everything if -d perf isn't on */
1598 {
1599 dt_times_t end;
1600 dt_get_times(&end);
1601 char buf[160]; /* Arbitrary size, should be lots big enough for everything used in DT */
1602 const int n = snprintf(buf, sizeof(buf), "%s took %.3f secs (%.3f CPU) ", prefix, end.clock - start->clock,
1603 end.user - start->user);
1604 if(n < sizeof(buf) - 1)
1605 {
1606 va_list ap;
1607 va_start(ap, suffix);
1608 vsnprintf(buf + n, sizeof(buf) - n, suffix, ap);
1609 va_end(ap);
1610 }
1611 dt_print(DT_DEBUG_PERF, "%s\n", buf);
1612 }
1613}
1614
1615#if defined(_WIN32)
1616#include <windows.h>
1617
1619{
1620 MEMORYSTATUSEX status;
1621 status.dwLength = sizeof(status);
1622 if(GlobalMemoryStatusEx(&status))
1623 return (size_t)status.ullAvailPhys; // Includes reclaimable
1624 else
1625 return 0;
1626}
1627
1628#elif defined(__APPLE__)
1629#include <mach/mach.h>
1630
1632{
1633 mach_port_t host = mach_host_self();
1634 vm_statistics64_data_t vmstat;
1635 mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
1636 if(host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&vmstat, &count) != KERN_SUCCESS) return 0;
1637
1638 size_t page_size;
1639 host_page_size(host, &page_size);
1640
1641 // Free + inactive (reclaimable)
1642 return (vmstat.free_count + vmstat.inactive_count) * page_size;
1643}
1644
1645#elif defined(__linux__)
1646#include <string.h>
1647
1649{
1650 FILE *f = g_fopen("/proc/meminfo", "r");
1651 if(IS_NULL_PTR(f)) return 0;
1652
1653 char line[256];
1654 size_t available_kb = 0;
1655
1656 while(fgets(line, sizeof(line), f))
1657 {
1658 if(sscanf(line, "MemAvailable: %" G_GSIZE_FORMAT " kB", &available_kb) == 1)
1659 {
1660 fclose(f);
1661 return available_kb * 1024; // kB to bytes
1662 }
1663 }
1664
1665 fclose(f);
1666 return 0;
1667}
1668
1669#else
1671{
1672 return 0; // Unsupported platform
1673}
1674#endif
1675
1676
1678{
1679 return dt_conf_get_int("worker_threads");
1680}
1681
1686
1688{
1690}
1691
1692void dt_configure_runtime_performance(dt_sys_resources_t *resources, gboolean init_gui)
1693{
1694 resources->total_memory = _get_total_memory() * 1000;
1695
1696 const size_t threads = darktable.num_openmp_threads;
1697 const size_t mem = resources->total_memory / (1024 * 1024);
1698 const size_t bits = CHAR_BIT * sizeof(void *);
1699 const gboolean sufficient = (mem >= 4096 && threads >= 2);
1700
1701 dt_print(DT_DEBUG_MEMORY, "[MEMORY CONFIGURATION] found a %s %" G_GSIZE_FORMAT "-bit system with %" G_GSIZE_FORMAT " cores\n",
1702 (sufficient) ? "sufficient" : "low performance", bits, threads);
1703
1704 // Override RAM detection with user config
1705 if(dt_conf_get_int64("host_memory_limit") > 0)
1706 resources->total_memory = dt_conf_get_int64("host_memory_limit") * 1024 * 1024;
1707
1708 // Keep OS headroom between 1 GB and a third of the system RAM
1709 resources->headroom_memory = dt_conf_get_int64("memory_os_headroom") * 1024 * 1024;
1710 resources->headroom_memory
1711 = CLAMP(resources->headroom_memory, 1024 * 1024 * 1024, resources->total_memory / 3);
1712
1713 // Keep mipmap cache between 256 MB and a sixth of the system RAM
1714 resources->mipmap_memory = dt_conf_get_int64("memory_mipmap_cache") * 1024 * 1024;
1715 resources->mipmap_memory
1716 = CLAMP(resources->mipmap_memory, 256 * 1024 * 1024, resources->total_memory / 6);
1717
1718 // 6 temp copies of 24 Mpx RGBA float32 at full res
1719 const size_t min_pipecache_memory = 6 * 6000 * 4000 * 4 * sizeof(float);
1720
1721 // Pipeline cache gets the rest. Need to cast as int otherwise, negative values saturate the uint64 to MAX_UINT or something
1722 resources->pixelpipe_memory = MAX((int64_t)resources->total_memory
1723 - (int64_t)resources->mipmap_memory
1724 - (int64_t)resources->headroom_memory,
1725 (int64_t)min_pipecache_memory);
1726
1727 if(resources->pixelpipe_memory == min_pipecache_memory)
1728 {
1729 fprintf(stderr,
1730 "MEMORY WARNING: your pixelpipe cache allocated RAM is too small for your typical raw size.\n"
1731 "MEMORY WARNING: reduce your OS/apps headroom, or your thumbnail cache size.\n"
1732 "MEMORY WARNING: you may also simply need more RAM or need to reset the config key host_memory.\n"
1733 "MEMORY WARNING: we shrank the thumbnails cache to the bare minimum to leave enough space for pixelpipe cache.\n");
1734 resources->mipmap_memory = MAX((int64_t)resources->total_memory
1735 - (int64_t)resources->headroom_memory
1736 - (int64_t)resources->pixelpipe_memory,
1737 (int64_t)128 * 1024 * 1024);
1738 }
1739
1740 // Print
1741 dt_print(DT_DEBUG_MEMORY | DT_DEBUG_CACHE, _("[MEMORY CONFIGURATION] Total system RAM: %" G_GSIZE_FORMAT " MiB\n"),
1742 resources->total_memory / (1024 * 1024));
1743
1744 dt_print(DT_DEBUG_MEMORY | DT_DEBUG_CACHE, _("[MEMORY CONFIGURATION] OS & Apps RAM headroom: %" G_GSIZE_FORMAT " MiB\n"),
1745 resources->headroom_memory / (1024 * 1024));
1746
1747 dt_print(DT_DEBUG_MEMORY | DT_DEBUG_CACHE, _("[MEMORY CONFIGURATION] Lightable thumbnails cache size: %" G_GSIZE_FORMAT " MiB\n"),
1748 resources->mipmap_memory / (1024 * 1024));
1749
1750 dt_print(DT_DEBUG_MEMORY | DT_DEBUG_CACHE, _("[MEMORY CONFIGURATION] Pixelpipe cache size: %" G_GSIZE_FORMAT " MiB\n"),
1751 resources->pixelpipe_memory / (1024 * 1024));
1752
1753 dt_print(DT_DEBUG_MEMORY | DT_DEBUG_CACHE, _("[MEMORY CONFIGURATION] Worker threads: %i\n"), dt_worker_threads());
1754
1755 if(resources->total_memory < resources->headroom_memory + resources->mipmap_memory + resources->pixelpipe_memory)
1756 dt_control_log(_("CRITICAL WARNING: Ansel will not be able to use the RAM you allocated it.\n"
1757 "Review your memory settings or add more RAM to your system."));
1758}
1759
1760int dt_capabilities_check(char *capability)
1761{
1762 for(GList *capabilities = darktable.capabilities; capabilities; capabilities = g_list_next(capabilities))
1763 {
1764 if(!strcmp(capabilities->data, capability))
1765 {
1766 return TRUE;
1767 }
1768 }
1769 return FALSE;
1770}
1771
1772
1773void dt_capabilities_add(char *capability)
1774{
1776
1777 if(!dt_capabilities_check(capability))
1778 darktable.capabilities = g_list_append(darktable.capabilities, capability);
1779
1781}
1782
1783
1792
1793
1799
1800
1802{
1803 fprintf(stdout, "[memory] Currently-free and reclaimable memory detected: %lu MiB\n", get_usable_memory_bytes() / (1024 * 1024));
1804
1805#if defined(__linux__)
1806 char *line = NULL;
1807 size_t len = 128;
1808 char vmsize[64];
1809 char vmpeak[64];
1810 char vmrss[64];
1811 char vmhwm[64];
1812 FILE *f;
1813
1814 char pidstatus[128];
1815 snprintf(pidstatus, sizeof(pidstatus), "/proc/%u/status", (uint32_t)getpid());
1816
1817 f = g_fopen(pidstatus, "r");
1818 if(IS_NULL_PTR(f)) return;
1819
1820 /* read memory size data from /proc/pid/status */
1821 while(getline(&line, &len, f) != -1)
1822 {
1823 if(!strncmp(line, "VmPeak:", 7))
1824 g_strlcpy(vmpeak, line + 8, sizeof(vmpeak));
1825 else if(!strncmp(line, "VmSize:", 7))
1826 g_strlcpy(vmsize, line + 8, sizeof(vmsize));
1827 else if(!strncmp(line, "VmRSS:", 6))
1828 g_strlcpy(vmrss, line + 8, sizeof(vmrss));
1829 else if(!strncmp(line, "VmHWM:", 6))
1830 g_strlcpy(vmhwm, line + 8, sizeof(vmhwm));
1831 }
1832 dt_free(line);
1833 fclose(f);
1834
1835 fprintf(stderr, "[memory] max address space (vmpeak): %15s"
1836 "[memory] cur address space (vmsize): %15s"
1837 "[memory] max used memory (vmhwm ): %15s"
1838 "[memory] cur used memory (vmrss ): %15s",
1839 vmpeak, vmsize, vmhwm, vmrss);
1840
1841#elif defined(__APPLE__)
1842 struct task_basic_info t_info;
1843 mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
1844
1845 if(KERN_SUCCESS != task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count))
1846 {
1847 fprintf(stderr, "[memory] task memory info unknown.\n");
1848 return;
1849 }
1850
1851 // Report in kB, to match output of /proc on Linux.
1852 fprintf(stderr, "[memory] max address space (vmpeak): %15s\n"
1853 "[memory] cur address space (vmsize): %12llu kB\n"
1854 "[memory] max used memory (vmhwm ): %15s\n"
1855 "[memory] cur used memory (vmrss ): %12llu kB\n",
1856 "unknown", (uint64_t)t_info.virtual_size / 1024, "unknown", (uint64_t)t_info.resident_size / 1024);
1857#elif defined (_WIN32)
1858 //Based on: http://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process
1859 MEMORYSTATUSEX memInfo;
1860 memInfo.dwLength = sizeof(MEMORYSTATUSEX);
1861 GlobalMemoryStatusEx(&memInfo);
1862 // DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
1863
1864 // Virtual Memory currently used by current process:
1865 PROCESS_MEMORY_COUNTERS_EX pmc;
1866 GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc));
1867 size_t virtualMemUsedByMe = pmc.PagefileUsage;
1868 size_t virtualMemUsedByMeMax = pmc.PeakPagefileUsage;
1869
1870 // Max Physical Memory currently used by current process
1871 size_t physMemUsedByMeMax = pmc.PeakWorkingSetSize;
1872
1873 // Physical Memory currently used by current process
1874 size_t physMemUsedByMe = pmc.WorkingSetSize;
1875
1876
1877 fprintf(stderr, "[memory] max address space (vmpeak): %12llu kB\n"
1878 "[memory] cur address space (vmsize): %12llu kB\n"
1879 "[memory] max used memory (vmhwm ): %12llu kB\n"
1880 "[memory] cur used memory (vmrss ): %12llu Kb\n",
1881 virtualMemUsedByMeMax / 1024, virtualMemUsedByMe / 1024, physMemUsedByMeMax / 1024,
1882 physMemUsedByMe / 1024);
1883
1884#else
1885 fprintf(stderr, "dt_print_mem_usage() currently unsupported on this platform\n");
1886#endif
1887}
1888
1889void dt_concat_path_file(char destination[PATH_MAX], const char path[PATH_MAX], const char *const file)
1890{
1891 g_strlcpy(destination, path, sizeof(char) * PATH_MAX);
1892 g_strlcat(destination, G_DIR_SEPARATOR_S, sizeof(char) * PATH_MAX);
1893 g_strlcat(destination, file, sizeof(char) * PATH_MAX);
1894}
1895
1896// clang-format off
1897// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1898// vim: shiftwidth=2 expandtab tabstop=2 cindent
1899// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1900// clang-format on
void dt_accels_connect_accels(dt_accels_t *accels)
Actually enable accelerators after having loaded user config.
void dt_accels_cleanup(dt_accels_t *accels)
void dt_accels_load_user_config(dt_accels_t *accels)
Loads keyboardrc.lang from config dir. This needs to run after we inited the accel map from widgets c...
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_bauhaus_cleanup(dt_bauhaus_t *bauhaus)
Definition bauhaus.c:1500
dt_bauhaus_t * dt_bauhaus_init()
Definition bauhaus.c:1382
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
void dt_culling_mode_to_selection()
dt_collection_t * dt_collection_new()
Definition collection.c:117
void dt_collection_free(const dt_collection_t *collection)
Definition collection.c:124
void dt_colorlabels_cleanup(void)
void dt_colorspaces_cleanup(dt_colorspaces_t *self)
dt_colorspaces_t * dt_colorspaces_init()
const dt_aligned_pixel_t f
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_history_cleanup(void)
int32_t dt_image_import(const int32_t film_id, const char *filename, gboolean raise_signals)
void dt_image_cleanup(void)
char * key
void dt_metadata_cleanup(void)
void dt_metadata_init()
#define PACKAGE_BUGREPORT
#define DT_BUILD_CPU_MODE
#define DT_BUILD_CXX_COMPILER
#define DT_BUILD_C_COMPILER
const char darktable_package_string[]
#define DT_BUILD_CXX_FLAGS
#define GETTEXT_PACKAGE
#define DT_BUILD_TYPE
#define DT_BUILD_C_FLAGS
const char darktable_last_commit_year[]
void dt_conf_cleanup(dt_conf_t *cf)
int dt_conf_get_bool(const char *name)
void dt_conf_init(dt_conf_t *cf, const char *filename, GSList *override_entries)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
int64_t dt_conf_get_int64(const char *name)
void dt_ctl_switch_mode_to(const char *mode)
Definition control.c:657
void dt_control_init(dt_control_t *s)
Definition control.c:95
void dt_control_set_mouse_over_id(int32_t value)
Definition control.c:931
void dt_control_log(const char *msg,...)
Definition control.c:761
void dt_control_shutdown(dt_control_t *s)
Definition control.c:446
void dt_control_cleanup(dt_control_t *s)
Definition control.c:468
void dt_control_crawler_show_image_list(GList *images)
Definition crawler.c:680
GList * dt_control_crawler_run(void)
Definition crawler.c:121
void dt_printers_abort_discovery(void)
Definition cups_print.c:210
void dt_vprint(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1567
void dt_show_times(const dt_times_t *start, const char *prefix)
Definition darktable.c:1580
GType pango_fc_font_map_get_type(void)
int dt_load_from_string(const gchar *input, gboolean open_image_in_dr, gboolean *single_image)
Definition darktable.c:328
static GLogWriterOutput _gtk_log_writer_filter(GLogLevelFlags log_level, const GLogField *fields, gsize n_fields, gpointer user_data)
Definition darktable.c:195
void dt_cleanup()
Definition darktable.c:1311
int dt_worker_threads()
Definition darktable.c:1677
static void _dt_drain_main_context(const int max_iters)
Definition darktable.c:1303
void dt_concat_path_file(char destination[PATH_MAX], const char path[PATH_MAX], const char *const file)
Definition darktable.c:1889
darktable_t darktable
Definition darktable.c:181
void dt_print_mem_usage()
Definition darktable.c:1801
size_t get_usable_memory_bytes()
Definition darktable.c:1670
struct _PangoFcFontMap PangoFcFontMap
Definition darktable.c:184
void pango_fc_font_map_shutdown(PangoFcFontMap *fcfontmap)
void * dt_alloc_align(size_t size)
Definition darktable.c:446
void dt_capabilities_remove(char *capability)
Definition darktable.c:1784
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data)
Definition darktable.c:451
size_t dt_get_mipmap_mem()
Definition darktable.c:1687
static size_t _get_total_memory()
Definition darktable.c:397
char * dt_version_major_minor()
Definition darktable.c:281
void dt_print_nts(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1555
void dt_configure_runtime_performance(dt_sys_resources_t *resources, gboolean init_gui)
Definition darktable.c:1692
void dt_capabilities_add(char *capability)
Definition darktable.c:1773
gboolean dt_supported_image(const gchar *filename)
check if file is a supported image
Definition darktable.c:312
void dt_capabilities_cleanup()
Definition darktable.c:1794
void dt_show_times_f(const dt_times_t *start, const char *prefix, const char *suffix,...)
Definition darktable.c:1594
size_t dt_get_available_mem()
Definition darktable.c:1682
int dt_capabilities_check(char *capability)
Definition darktable.c:1760
static int usage(const char *argv0)
Definition darktable.c:229
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1542
#define CHKSIGDBG(sig)
dt_debug_thread_t
Definition darktable.h:712
@ DT_DEBUG_LIGHTTABLE
Definition darktable.h:725
@ DT_DEBUG_UNDO
Definition darktable.h:734
@ DT_DEBUG_INPUT
Definition darktable.h:729
@ DT_DEBUG_PRINT
Definition darktable.h:730
@ DT_DEBUG_OPENCL
Definition darktable.h:722
@ DT_DEBUG_GTK
Definition darktable.h:718
@ DT_DEBUG_PIPE
Definition darktable.h:741
@ DT_DEBUG_PIPECACHE
Definition darktable.h:720
@ DT_DEBUG_HISTORY
Definition darktable.h:740
@ DT_DEBUG_CAMERA_SUPPORT
Definition darktable.h:731
@ DT_DEBUG_NAN
Definition darktable.h:726
@ DT_DEBUG_DEMOSAIC
Definition darktable.h:737
@ DT_DEBUG_MEMORY
Definition darktable.h:724
@ DT_DEBUG_PERF
Definition darktable.h:719
@ DT_DEBUG_VERBOSE
Definition darktable.h:743
@ DT_DEBUG_PARAMS
Definition darktable.h:736
@ DT_DEBUG_CONTROL
Definition darktable.h:716
@ DT_DEBUG_COLORPROFILE
Definition darktable.h:744
@ DT_DEBUG_CACHE
Definition darktable.h:715
@ DT_DEBUG_ALWAYS
Definition darktable.h:713
@ DT_DEBUG_SIGNAL
Definition darktable.h:735
@ DT_DEBUG_PWSTORAGE
Definition darktable.h:721
@ DT_DEBUG_SHORTCUTS
Definition darktable.h:738
@ DT_DEBUG_IMAGEIO
Definition darktable.h:733
@ DT_DEBUG_DEV
Definition darktable.h:717
@ DT_DEBUG_NOCACHE_REUSE
Definition darktable.h:745
@ DT_DEBUG_IMPORT
Definition darktable.h:742
@ DT_DEBUG_IOPORDER
Definition darktable.h:732
@ DT_DEBUG_MASKS
Definition darktable.h:727
@ DT_DEBUG_TILING
Definition darktable.h:739
@ DT_DEBUG_SQL
Definition darktable.h:723
@ DT_DEBUG_LUA
Definition darktable.h:728
#define omp_get_max_threads()
Definition darktable.h:254
static void * dt_alloc_align_internal(size_t size)
Definition darktable.h:409
static void dt_free_gpointer(gpointer ptr)
Definition darktable.h:463
#define dt_free(ptr)
Definition darktable.h:456
static void dt_get_times(dt_times_t *t)
Definition darktable.h:921
static double dt_get_wtime(void)
Definition darktable.h:914
#define PATH_MAX
Definition darktable.h:1062
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
void dt_database_cleanup_busy_statements(const struct dt_database_t *db)
Definition database.c:3709
void dt_database_optimize(const struct dt_database_t *db)
Definition database.c:3906
gboolean dt_database_snapshot(const struct dt_database_t *db)
Definition database.c:3972
void dt_database_perform_maintenance(const struct dt_database_t *db)
Definition database.c:3728
void dt_database_destroy(const dt_database_t *db)
Definition database.c:3626
gboolean dt_database_show_error(const dt_database_t *db)
Definition database.c:2651
char ** dt_database_snaps_to_remove(const struct dt_database_t *db)
Definition database.c:4230
gboolean dt_database_maybe_maintenance(const struct dt_database_t *db, const gboolean has_gui, const gboolean closing_time)
Definition database.c:3829
gboolean dt_database_get_lock_acquired(const dt_database_t *db)
Definition database.c:3704
dt_database_t * dt_database_init(const char *alternative, const gboolean load_data, const gboolean has_gui)
Definition database.c:3008
gboolean dt_database_maybe_snapshot(const struct dt_database_t *db)
Definition database.c:4022
void dt_datetime_init()
Definition datetime.c:30
void dt_dev_history_cleanup(void)
Cleanup cached statements or state used by history I/O.
void dt_dev_pixelpipe_cache_wait_dump_pending(const char *reason)
Dump pending GUI cache wait requests for lifecycle debugging.
#define dt_pthread_rwlock_destroy
Definition dtpthread.h:391
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:374
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Definition dtpthread.h:359
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
Definition dtpthread.h:379
#define dt_pthread_rwlock_init
Definition dtpthread.h:390
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:364
int supported(struct dt_imageio_module_storage_t *storage, struct dt_imageio_module_format_t *format)
Definition example.c:274
void dt_exif_set_exiv2_taglist()
Definition exif.cc:266
void dt_exif_init()
Definition exif.cc:4665
void dt_exif_cleanup()
Definition exif.cc:4705
void dt_loc_get_sharedir(char *sharedir, size_t bufsize)
void dt_loc_get_localedir(char *localedir, size_t bufsize)
void dt_loc_init(const char *datadir, const char *moduledir, const char *localedir, const char *configdir, const char *cachedir, const char *tmpdir, const char *kerneldir)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
int dt_film_new(dt_film_t *film, const char *directory)
Definition film.c:161
int dt_film_open(const int32_t id)
Definition film.c:128
void dt_film_set_folder_status()
Definition film.c:514
int dt_film_import(const char *dirname)
Definition film.c:236
dt_job_t * dt_pathlist_import_create(int argc, char *argv[])
Definition film_jobs.c:115
@ DT_FP_MODE_FAST
Definition fp_mode.h:39
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
Definition getdelim.c:157
int dt_gui_gtk_init(dt_gui_gtk_t *gui)
Definition gtk.c:1102
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
void dt_gui_presets_init()
void dt_gui_presets_cleanup()
void dt_gui_throttle_init(void)
void dt_gui_throttle_cleanup(void)
GList * dt_guides_init()
Definition guides.c:580
void dt_guides_cleanup(GList *guides)
Definition guides.c:841
void dt_image_cache_cleanup(dt_image_cache_t *cache)
void dt_image_cache_init(dt_image_cache_t *cache)
void dt_image_cache_connect_info_changed_first(const struct dt_control_signal_t *ctlsig)
void dt_imageio_cleanup(dt_imageio_t *iio)
void dt_imageio_init(dt_imageio_t *iio)
void dt_iop_set_darktable_iop_table()
Definition imageop.c:2973
void dt_iop_load_modules_so(void)
Definition imageop.c:1541
void dt_iop_unload_modules_so()
Definition imageop.c:1598
GList * dt_ioppr_get_iop_order_list(int32_t imgid, gboolean sorted)
Load the order list for an image from the DB.
Definition iop_order.c:1096
GList * dt_ioppr_get_iop_order_rules()
Return the list of ordering rules (prev/next constraints).
Definition iop_order.c:793
int dt_ioppr_check_so_iop_order(GList *iop_list, GList *iop_order_list)
Check whether any module .so is missing an iop_order entry.
Definition iop_order.c:1960
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job)
Definition jobs.c:405
@ DT_JOB_QUEUE_USER_BG
Definition jobs.h:55
dt_l10n_t * dt_l10n_init(gboolean init_list)
Definition l10n.c:311
void dt_lib_init(dt_lib_t *lib)
Definition lib.c:1324
void dt_lib_cleanup(dt_lib_t *lib)
Definition lib.c:1332
float *const restrict const size_t k
void dt_mipmap_cache_init(dt_mipmap_cache_t *cache)
void dt_mipmap_cache_cleanup(dt_mipmap_cache_t *cache)
size_t size
Definition mipmap_cache.c:3
#define dt_mipmap_cache_get(A, B, C, D, E, F)
@ DT_MIPMAP_BLOCKING
#define dt_mipmap_cache_release(A, B)
@ DT_MIPMAP_FULL
JsonParser * dt_noiseprofile_init(const char *alternative)
void dt_opencl_init(dt_opencl_t *cl, const gboolean exclude_opencl, const gboolean print_statistics)
Definition opencl.c:995
void dt_opencl_cleanup(dt_opencl_t *cl)
Definition opencl.c:1284
gboolean dt_opencl_finish(const int devid)
Definition opencl.c:1347
void dt_dev_pixelpipe_cache_cleanup(dt_dev_pixelpipe_cache_t *cache)
dt_dev_pixelpipe_cache_t * dt_dev_pixelpipe_cache_init(size_t max_memory)
static void dt_points_cleanup(dt_points_t *p)
Definition points.h:65
static void dt_points_init(dt_points_t *p, const unsigned int num_threads)
Definition points.h:55
void dt_control_progress_init(struct dt_control_t *control)
Definition progress.c:224
const dt_pwstorage_t * dt_pwstorage_new()
Definition pwstorage.c:61
void dt_pwstorage_destroy(const dt_pwstorage_t *pwstorage)
Definition pwstorage.c:182
void dt_set_rlimits()
void dt_selection_free(dt_selection_t *selection)
Definition selection.c:252
dt_selection_t * dt_selection_new()
Definition selection.c:238
void dt_sentry_shutdown(void)
Definition sentry.c:483
void dt_sentry_init(const gboolean have_gui)
Definition sentry.c:479
void dt_control_signal_cleanup(dt_control_signal_t *ctlsig)
Definition signal.c:280
dt_control_signal_t * dt_control_signal_init()
Definition signal.c:247
@ DT_DEBUG_SIGNAL_ACT_DISCONNECT
Definition signal.h:327
@ DT_DEBUG_SIGNAL_ACT_CONNECT
Definition signal.h:326
@ DT_DEBUG_SIGNAL_ACT_RAISE
Definition signal.h:325
@ DT_DEBUG_SIGNAL_ACT_PRINT_TRACE
Definition signal.h:328
@ DT_SIGNAL_DEVELOP_INITIALIZE
This signal is raised when darktable.develop is initialized.
Definition signal.h:169
@ DT_SIGNAL_METADATA_CHANGED
This signal is raised when metadata status (shown/hidden) or value has changed.
Definition signal.h:139
@ DT_SIGNAL_VIEWMANAGER_THUMBTABLE_ACTIVATE
Definition signal.h:95
@ DT_SIGNAL_ACTIVE_IMAGES_CHANGE
This signal is raised when image shown in the main view change no param, no returned value.
Definition signal.h:64
@ DT_SIGNAL_CONTROL_REDRAW_ALL
This signal is raised when dt_control_queue_redraw() is called. no param, no returned value.
Definition signal.h:69
@ DT_SIGNAL_MASK_CHANGED
Definition signal.h:303
@ DT_SIGNAL_DEVELOP_HISTORY_CHANGE
This signal is raised when develop history is changed no param, no returned value.
Definition signal.h:204
@ DT_SIGNAL_DEVELOP_IMAGE_CHANGED
This signal is raised when image is changed in darkroom.
Definition signal.h:221
@ DT_SIGNAL_CONTROL_PROFILE_USER_CHANGED
This signal is raised when a profile is changed by the user 1 uint32_t : the profile type that has ch...
Definition signal.h:242
@ DT_SIGNAL_IMAGE_EXPORT_TMPFILE
This signal is raised after an image has been exported to a file, but before it is sent to facebook/p...
Definition signal.h:261
@ DT_SIGNAL_IMAGES_ORDER_CHANGE
This signal is raised to request image order change.
Definition signal.h:150
@ DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED
This signal is raised when develop preview pipe process is finished no param, no returned value.
Definition signal.h:174
@ DT_SIGNAL_STYLE_CHANGED
This signal is raised when a style is added/deleted/changed
Definition signal.h:147
@ DT_SIGNAL_DARKROOM_UI_CHANGED
Signal that the darkroom GUI color changed.
Definition signal.h:224
@ DT_SIGNAL_DEVELOP_UI_PIPE_FINISHED
This signal is raised when pipe is finished and the gui is attached no param, no returned value.
Definition signal.h:179
@ DT_SIGNAL_FILMROLLS_CHANGED
This signal is raised when a filmroll is deleted/changed but not imported.
Definition signal.h:156
@ DT_SIGNAL_MOUSE_OVER_IMAGE_CHANGE
This signal is raised when mouse hovers over image thumbs both on lighttable and in the filmstrip....
Definition signal.h:59
@ DT_SIGNAL_CONTROL_TOAST_REDRAW
This signal is raised when dt_control_toast_redraw() is called. no param, no returned value.
Definition signal.h:288
@ DT_SIGNAL_DEVELOP_MODULE_MOVED
This signal is raised when order of modules in pipeline is changed.
Definition signal.h:218
@ DT_SIGNAL_IMAGE_INFO_CHANGED
This signal is raised when any of image info has changed
Definition signal.h:144
@ DT_SIGNAL_PREFERENCES_CHANGE
This signal is raised after preferences have been changed no parameters no return.
Definition signal.h:273
@ DT_SIGNAL_CONTROL_REDRAW_CENTER
This signal is raised when dt_control_queue_redraw_center() is called. no param, no returned value.
Definition signal.h:74
@ DT_SIGNAL_DEVELOP_MODULEGROUPS_SET
This signal is raised to request a modulegroups update. 1 : dt_iop_module_t *module,...
Definition signal.h:191
@ DT_SIGNAL_FILMROLLS_REMOVED
This signal is raised only when a filmroll is removed.
Definition signal.h:159
@ DT_SIGNAL_TAG_CHANGED
This signal is raised when a tag is added/deleted/changed
Definition signal.h:130
@ DT_SIGNAL_IMAGEIO_STORAGE_CHANGE
This signal is raised when a new storage module is loaded noparameters no return.
Definition signal.h:267
@ DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE
This signal is raised when a thumb is single-clicked in the filmstrip. Views that want filmstrip clic...
Definition signal.h:103
@ DT_SIGNAL_DEVELOP_MODULE_REMOVE
This signal is raised when a module is removed from the history stack 1 module no returned value.
Definition signal.h:215
@ DT_SIGNAL_IMAGE_LOADED
This signal is raised when an asynchronous darkroom image load finishes. 1 : uint32_t the load reques...
Definition signal.h:231
@ DT_SIGNAL_SELECTION_CHANGED
This signal is raised when the selection is changed no param, no returned value.
Definition signal.h:127
@ DT_SIGNAL_CONTROL_PICKERDATA_READY
This signal is raised when new color picker data are available in darkroom. no param,...
Definition signal.h:293
@ DT_SIGNAL_CONTROL_PROFILE_CHANGED
This signal is raised when the screen profile has changed no param, no returned value.
Definition signal.h:236
@ DT_SIGNAL_COUNT
Definition signal.h:319
@ DT_SIGNAL_VIEWMANAGER_FILMSTRIP_DRAG_BEGIN
This signal is raised when a drag starts from the filmstrip. Views that need filmstrip drags to commi...
Definition signal.h:111
@ DT_SIGNAL_IMAGE_IMPORT
This signal is raised when a new image is imported (not cloned) 1 uint32_t : the new image id no retu...
Definition signal.h:248
@ DT_SIGNAL_COLLECTION_CHANGED
This signal is raised when collection changed. To avoid leaking the list, dt_collection_t is connecte...
Definition signal.h:122
@ DT_SIGNAL_CONTROL_LOG_REDRAW
This signal is raised when dt_control_log_redraw() is called. no param, no returned value.
Definition signal.h:283
@ DT_SIGNAL_CONTROL_NAVIGATION_REDRAW
This signal is raised when dt_control_navigation_redraw() is called. no param, no returned value.
Definition signal.h:278
@ DT_SIGNAL_METADATA_UPDATE
Definition signal.h:296
@ DT_SIGNAL_DEVELOP_HISTORY_WILL_CHANGE
This signal is raised when develop history is about to be changed 1 : GList * the current history 2 :...
Definition signal.h:199
@ DT_SIGNAL_VIEWMANAGER_VIEW_CHANGED
This signal is raised by viewmanager when a view has changed. 1 : dt_view_t * the old view 2 : dt_vie...
Definition signal.h:81
void dt_gui_splash_close(void)
Definition splash.c:695
struct _GtkWidget GtkWidget
Definition splash.h:29
void dt_styles_cleanup(void)
unsigned __int64 uint64_t
Definition strptime.c:75
struct dt_dbus_t * dbus
Definition darktable.h:786
struct dt_undo_t * undo
Definition darktable.h:787
dt_pthread_mutex_t readFile_mutex
Definition darktable.h:803
struct dt_lib_t * lib
Definition darktable.h:771
int32_t unmuted_signal_dbg_acts
Definition darktable.h:830
struct dt_imageio_t * imageio
Definition darktable.h:784
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:790
int32_t num_openmp_threads
Definition darktable.h:758
struct dt_l10n_t * l10n
Definition darktable.h:789
struct dt_gui_gtk_t * gui
Definition darktable.h:775
dt_pthread_rwlock_t database_threadsafe
Definition darktable.h:816
struct dt_colorspaces_t * color_profiles
Definition darktable.h:788
GList * capabilities
Definition darktable.h:767
struct dt_collection_t * collection
Definition darktable.h:781
struct dt_mipmap_cache_t * mipmap_cache
Definition darktable.h:776
struct dt_selection_t * selection
Definition darktable.h:782
GList * iop
Definition darktable.h:761
dt_pthread_mutex_t exiv2_threadsafe
Definition darktable.h:800
struct dt_sys_resources_t dtresources
Definition darktable.h:834
dt_pthread_mutex_t plugin_threadsafe
Definition darktable.h:793
dt_pthread_mutex_t capabilities_threadsafe
Definition darktable.h:796
GList * iop_order_list
Definition darktable.h:762
const struct dt_database_t * db
Definition darktable.h:779
GList * iop_order_rules
Definition darktable.h:763
struct dt_control_signal_t * signals
Definition darktable.h:774
struct dt_bauhaus_t * bauhaus
Definition darktable.h:778
struct dt_opencl_t * opencl
Definition darktable.h:785
GList * themes
Definition darktable.h:829
int32_t unmuted
Definition darktable.h:760
struct dt_image_cache_t * image_cache
Definition darktable.h:777
struct dt_develop_t * develop
Definition darktable.h:770
struct dt_points_t * points
Definition darktable.h:783
dt_pthread_mutex_t pipeline_threadsafe
Definition darktable.h:808
struct dt_view_manager_t * view_manager
Definition darktable.h:772
JsonParser * noiseprofile_parser
Definition darktable.h:768
GList * guides
Definition darktable.h:827
gboolean unmuted_signal_dbg[DT_SIGNAL_COUNT]
Definition darktable.h:831
char * main_message
Definition darktable.h:837
char * progname
Definition darktable.h:818
struct dt_conf_t * conf
Definition darktable.h:769
const struct dt_pwstorage_t * pwstorage
Definition darktable.h:780
double start_wtime
Definition darktable.h:828
struct dt_control_t * control
Definition darktable.h:773
Definition conf.h:89
char * key
Definition conf.h:90
char * value
Definition conf.h:91
dt_pthread_mutex_t run_mutex
Definition control.h:256
int32_t running
Definition control.h:254
dt_pthread_mutex_t log_mutex
Definition control.h:240
GDBusConnection * dbus_connection
Definition dbus.h:38
cairo_surface_t * surface
Definition gtk.h:168
int32_t reset
Definition gtk.h:172
dt_accels_t * accels
Definition gtk.h:194
dt_ui_t * ui
Definition gtk.h:164
GtkWidget * scroll_to[2]
Definition gtk.h:221
gboolean culling_mode
Definition gtk.h:187
Definition lib.h:54
int num_devs
Definition opencl.h:236
int inited
Definition opencl.h:232
size_t pixelpipe_memory
Definition darktable.h:753
double clock
Definition darktable.h:842
double user
Definition darktable.h:843
void dt_set_signal_handlers()
void dt_set_darktable_tags()
Definition tags.c:618
void dt_tags_cleanup(void)
Definition tags.c:1932
void dt_telemetry_shutdown(void)
Definition telemetry.c:413
void dt_telemetry_init(const gboolean have_gui)
Definition telemetry.c:409
#define MAX(a, b)
Definition thinplate.c:29
void dt_undo_cleanup(dt_undo_t *self)
Definition undo.c:76
dt_undo_t * dt_undo_init(void)
Definition undo.c:50
gchar * dt_util_normalize_path(const gchar *_input)
Definition utility.c:680
void dt_view_manager_cleanup(dt_view_manager_t *vm)
Definition view.c:131
void dt_view_manager_init(dt_view_manager_t *vm)
Definition view.c:114
void dt_view_manager_gui_init(dt_view_manager_t *vm)
Definition view.c:122
void dt_ui_cleanup_titlebar(dt_ui_t *ui)
void dt_ui_cleanup_main_table(dt_ui_t *ui)
void dt_ui_init_global_menu(dt_ui_t *ui)