2
This file is part of darktable,
3
copyright (c) 2009--2010 johannes hanika.
5
darktable is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
10
darktable is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with darktable. If not, see <http://www.gnu.org/licenses/>.
21
#include "common/darktable.h"
22
#include "common/collection.h"
23
#include "common/exif.h"
24
#include "common/fswatch.h"
25
#include "common/pwstorage/pwstorage.h"
27
#include "common/camera_control.h"
29
#include "common/film.h"
30
#include "common/image.h"
31
#include "common/image_cache.h"
32
#include "common/imageio_module.h"
33
#include "common/points.h"
34
#include "common/opencl.h"
35
#include "develop/imageop.h"
37
#include "views/view.h"
38
#include "control/control.h"
39
#include "control/conf.h"
46
#include <sys/param.h>
52
darktable_t darktable;
53
const char dt_supported_extensions[] = "3fr,arw,bay,bmq,cap,cine,cr2,crw,cs1,dc2,dcr,dng,erf,fff,exr,ia,iiq,jpg,jpeg,k25,kc2,kdc,mdc,mef,mos,mrw,nef,nrw,orf,pef,pfm,pxn,qtk,raf,raw,rdc,rw2,rwl,sr2,srf,sti,tif,tiff,x3f";
55
static int usage(const char *argv0)
57
printf("usage: %s [-d {all,cache,control,dev,fswatch,camctl,perf,pwstorage,opencl}] [IMG_1234.{RAW,..}|image_folder/]", argv0);
59
printf(" [--disable-opencl]");
65
typedef void (dt_signal_handler_t)(int) ;
66
static dt_signal_handler_t *_dt_sigill_old_handler = NULL;
69
void _dt_sigill_handler(int param) {
71
GtkWidget *dlg = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_(
72
"darktable has trapped an illegal instruction which probably mean that \
73
an invalid processor optimized codepath is used for your cpu, please try reproduce the crash running 'gdb darktable' from \
74
console and post backtrace log to mailing list with information about your CPU."));
75
gtk_dialog_run(GTK_DIALOG(dlg));
77
/* pass it further the old handler*/
78
_dt_sigill_old_handler(param);
81
#if defined(__i386__) && defined(__PIC__)
82
#define cpuid(level, a, b, c, d) \
83
__asm__ ("xchgl %%ebx, %1\n" \
86
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
90
#define cpuid(level, a, b, c, d) \
92
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
98
void dt_check_cpu(int argc,char **argv)
100
/* hook up SIGILL handler */
101
_dt_sigill_old_handler = signal(SIGILL,&_dt_sigill_handler);
103
/* call cpuid for SSE level */
105
cpuid(0x1,ax,bx,cx,dx);
108
char message[512]={0};
109
strcat(message,_("SIMD extenstions found: "));
110
if((cx & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE3))
111
strcat(message,"SSE3 ");
112
if( ((dx >> 26) & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE2))
113
strcat(message,"SSE2 ");
114
else if (((dx >> 25) & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE))
115
strcat(message,"SSE ");
117
/* for now, bail out if SSE2 is not availble */
118
if(!(darktable.cpu_flags & DT_CPU_FLAG_SSE2))
120
gtk_init (&argc, &argv);
122
GtkWidget *dlg = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_(
123
"darktable is very cpu resource intensive and is using SSE2 SIMD instructions \
124
for heavy calculations, this is for a better user experience but also defines a minimum\
125
requirement of your processor.\n\nThe processor in YOUR system does NOT support this \
126
and darktable will now close down.\n\n%s"),message);
128
gtk_dialog_run(GTK_DIALOG(dlg));
135
int dt_init(int argc, char *argv[])
138
fprintf("[dt_init] unfortunately we depend on SSE2 instructions at this time.\n");
139
fprintf("[dt_init] please contribute a backport patch (or buy a newer processor).\n");
142
bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR);
143
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
144
textdomain (GETTEXT_PACKAGE);
146
darktable.progname = argv[0];
149
gchar *dbfilenameFromCommand = NULL;
152
omp_set_num_threads(omp_get_num_procs());
154
darktable.unmuted = 0;
155
char *image_to_load = NULL;
156
for(int k=1; k<argc; k++)
158
if(argv[k][0] == '-')
160
if(!strcmp(argv[k], "--help"))
162
return usage(argv[0]);
164
else if(!strcmp(argv[k], "--version"))
166
printf("this is "PACKAGE_STRING"\ncopyright (c) 2009-2011 johannes hanika\n"PACKAGE_BUGREPORT"\n");
169
else if(!strcmp(argv[k], "--library"))
171
dbfilenameFromCommand = argv[++k];
173
if(argv[k][1] == 'd' && argc > k+1)
175
if(!strcmp(argv[k+1], "all")) darktable.unmuted = 0xffffffff; // enable all debug information
176
else if(!strcmp(argv[k+1], "cache")) darktable.unmuted |= DT_DEBUG_CACHE; // enable debugging for lib/film/cache module
177
else if(!strcmp(argv[k+1], "control")) darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
178
else if(!strcmp(argv[k+1], "dev")) darktable.unmuted |= DT_DEBUG_DEV; // develop module
179
else if(!strcmp(argv[k+1], "fswatch")) darktable.unmuted |= DT_DEBUG_FSWATCH; // fswatch module
180
else if(!strcmp(argv[k+1], "camctl")) darktable.unmuted |= DT_DEBUG_CAMCTL; // camera control module
181
else if(!strcmp(argv[k+1], "perf")) darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
182
else if(!strcmp(argv[k+1], "pwstorage")) darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
183
else if(!strcmp(argv[k+1], "opencl")) darktable.unmuted |= DT_DEBUG_OPENCL; // gpu accel via opencl
184
else return usage(argv[0]);
190
image_to_load = argv[k];
195
/* check cput caps */
196
dt_check_cpu(argc,argv);
200
(void)setenv("GEGL_PATH", DARKTABLE_DATADIR"/gegl:/usr/lib/gegl-0.0", 1);
201
gegl_init(&argc, &argv);
206
dt_get_user_config_dir (datadir,1024);
208
snprintf(filename, 1024, "%s/darktablerc", datadir);
210
// Initialize the filesystem watcher
211
darktable.fswatch=dt_fswatch_new();
214
// Initialize the camera control
215
darktable.camctl=dt_camctl_new();
217
// has to go first for settings needed by all the others.
218
darktable.conf = (dt_conf_t *)malloc(sizeof(dt_conf_t));
219
dt_conf_init(darktable.conf, filename);
221
// get max lighttable thumbnail size:
222
darktable.thumbnail_size = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_size"), 160, 1300);
223
// and make sure it can be mip-mapped all the way from mip4 to mip0
224
darktable.thumbnail_size /= 16;
225
darktable.thumbnail_size *= 16;
227
// Initialize the password storage engine
228
darktable.pwstorage=dt_pwstorage_new();
230
// check and migrate database into new XDG structure
231
char dbfilename[2048]= {0};
232
gchar *conf_db = dt_conf_get_string("database");
233
if (conf_db && conf_db[0] != '/')
235
char *homedir = getenv ("HOME");
236
snprintf (dbfilename,2048,"%s/%s", homedir, conf_db);
237
if (g_file_test (dbfilename, G_FILE_TEST_EXISTS))
239
fprintf(stderr, "[init] moving database into new XDG directory structure\n");
240
// move database into place
241
char destdbname[2048]= {0};
242
snprintf(destdbname,2048,"%s/%s",datadir,"library.db");
243
if(!g_file_test (destdbname,G_FILE_TEST_EXISTS))
245
rename(dbfilename,destdbname);
246
dt_conf_set_string("database","library.db");
252
// check and migrate the cachedir
253
char cachefilename[2048]= {0};
254
char cachedir[2048]= {0};
255
gchar *conf_cache = dt_conf_get_string("cachefile");
256
if (conf_cache && conf_cache[0] != '/')
258
char *homedir = getenv ("HOME");
259
snprintf (cachefilename,2048,"%s/%s",homedir, conf_cache);
260
if (g_file_test (cachefilename,G_FILE_TEST_EXISTS))
262
fprintf(stderr, "[init] moving cache into new XDG directory structure\n");
263
char destcachename[2048]= {0};
264
snprintf(destcachename,2048,"%s/%s",cachedir,"mipmaps");
265
if(!g_file_test (destcachename,G_FILE_TEST_EXISTS))
267
rename(cachefilename,destcachename);
268
dt_conf_set_string("cachefile","mipmaps");
274
gchar * dbname = NULL;
275
if ( dbfilenameFromCommand == NULL )
277
dbname = dt_conf_get_string ("database");
278
if(!dbname) snprintf(dbfilename, 1024, "%s/library.db", datadir);
279
else if(dbname[0] != '/') snprintf(dbfilename, 1024, "%s/%s", datadir, dbname);
280
else snprintf(dbfilename, 1024, "%s", dbname);
284
snprintf(dbfilename, 1024, "%s", dbfilenameFromCommand);
285
dbname = g_file_get_basename (g_file_new_for_path(dbfilenameFromCommand));
289
// if db file does not exist, also don't load the cache.
290
if(!g_file_test(dbfilename, G_FILE_TEST_IS_REGULAR)) load_cached = 0;
291
if(sqlite3_open(dbfilename, &(darktable.db)))
293
fprintf(stderr, "[init] could not open database ");
294
if(dbname) fprintf(stderr, "`%s'!\n", dbname);
295
else fprintf(stderr, "\n");
297
fprintf(stderr, "[init] maybe your %s/darktablerc is corrupt?\n",datadir);
298
dt_get_datadir(dbfilename, 512);
299
fprintf(stderr, "[init] try `cp %s/darktablerc %s/darktablerc'\n", dbfilename,datadir);
301
fprintf(stderr, "[init] check your /apps/darktable/database gconf entry!\n");
303
sqlite3_close(darktable.db);
304
if (dbname != NULL) g_free(dbname);
307
if (dbname != NULL) g_free(dbname);
309
dt_pthread_mutex_init(&(darktable.db_insert), NULL);
310
dt_pthread_mutex_init(&(darktable.plugin_threadsafe), NULL);
312
// initialize collection query
313
darktable.collection_listeners = NULL;
314
darktable.collection = dt_collection_new(NULL);
316
darktable.opencl = (dt_opencl_t *)malloc(sizeof(dt_opencl_t));
317
dt_opencl_init(darktable.opencl, argc, argv);
319
darktable.points = (dt_points_t *)malloc(sizeof(dt_points_t));
320
dt_points_init(darktable.points, dt_get_num_threads());
322
darktable.control = (dt_control_t *)malloc(sizeof(dt_control_t));
323
dt_control_init(darktable.control);
325
int thumbnails = dt_conf_get_int ("mipmap_cache_thumbnails");
326
thumbnails = MIN(1000, MAX(20, thumbnails));
328
darktable.mipmap_cache = (dt_mipmap_cache_t *)malloc(sizeof(dt_mipmap_cache_t));
329
dt_mipmap_cache_init(darktable.mipmap_cache, thumbnails);
331
darktable.image_cache = (dt_image_cache_t *)malloc(sizeof(dt_image_cache_t));
332
dt_image_cache_init(darktable.image_cache, MIN(10000, MAX(500, thumbnails)), load_cached);
334
darktable.view_manager = (dt_view_manager_t *)malloc(sizeof(dt_view_manager_t));
335
dt_view_manager_init(darktable.view_manager);
337
darktable.gui = (dt_gui_gtk_t *)malloc(sizeof(dt_gui_gtk_t));
338
if(dt_gui_gtk_init(darktable.gui, argc, argv)) return 1;
340
// load the darkroom mode plugins once:
341
dt_iop_load_modules_so();
343
darktable.lib = (dt_lib_t *)malloc(sizeof(dt_lib_t));
344
dt_lib_init(darktable.lib);
346
dt_control_load_config(darktable.control);
347
strncpy(darktable.control->global_settings.dbname, filename, 512); // overwrite if relocated.
349
darktable.imageio = (dt_imageio_t *)malloc(sizeof(dt_imageio_t));
350
dt_imageio_init(darktable.imageio);
356
if(g_str_has_prefix(image_to_load, "file://"))
357
image_to_load += strlen("file://");
358
if(g_path_is_absolute(image_to_load) == FALSE)
360
char* current_dir = g_get_current_dir();
361
char* tmp_filename = g_build_filename(current_dir, image_to_load, NULL);
362
filename = (char*)g_malloc(sizeof(char)*MAXPATHLEN);
363
if(realpath(tmp_filename, filename) == NULL)
365
dt_control_log(_("found strange path `%s'"), tmp_filename);
367
g_free(tmp_filename);
372
g_free(tmp_filename);
376
filename = g_strdup(image_to_load);
379
if(g_file_test(filename, G_FILE_TEST_IS_DIR))
381
// import a directory into a film roll
382
unsigned int last_char = strlen(filename)-1;
383
if(filename[last_char] == '/')
384
filename[last_char] = '\0';
385
id = dt_film_import(filename);
389
dt_ctl_switch_mode_to(DT_LIBRARY);
393
dt_control_log(_("error loading directory `%s'"), filename);
398
// import a single image
399
gchar *directory = g_path_get_dirname((const gchar *)filename);
401
const int filmid = dt_film_new(&film, directory);
402
id = dt_image_import(filmid, filename, TRUE);
406
dt_film_open(filmid);
407
// make sure buffers are loaded (load full for testing)
408
dt_image_t *img = dt_image_cache_get(id, 'r');
409
dt_image_buffer_t buf = dt_image_get_blocking(img, DT_IMAGE_FULL, 'r');
413
dt_image_cache_release(img, 'r');
414
dt_control_log(_("file `%s' has unknown format!"), filename);
418
dt_image_release(img, DT_IMAGE_FULL, 'r');
419
dt_image_cache_release(img, 'r');
420
DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id);
421
dt_ctl_switch_mode_to(DT_DEVELOP);
426
dt_control_log(_("error loading file `%s'"), filename);
433
dt_ctl_switch_mode_to(DT_LIBRARY);
441
dt_ctl_switch_mode_to(DT_MODE_NONE);
443
dt_control_write_config(darktable.control);
444
dt_control_shutdown(darktable.control);
446
dt_lib_cleanup(darktable.lib);
448
dt_view_manager_cleanup(darktable.view_manager);
449
free(darktable.view_manager);
450
dt_imageio_cleanup(darktable.imageio);
451
free(darktable.imageio);
452
dt_gui_gtk_cleanup(darktable.gui);
454
dt_image_cache_cleanup(darktable.image_cache);
455
free(darktable.image_cache);
456
dt_mipmap_cache_cleanup(darktable.mipmap_cache);
457
free(darktable.mipmap_cache);
458
dt_control_cleanup(darktable.control);
459
free(darktable.control);
460
dt_conf_cleanup(darktable.conf);
461
free(darktable.conf);
462
dt_points_cleanup(darktable.points);
463
free(darktable.points);
464
dt_iop_unload_modules_so();
465
dt_opencl_cleanup(darktable.opencl);
466
free(darktable.opencl);
468
dt_camctl_destroy(darktable.camctl);
470
dt_pwstorage_destroy(darktable.pwstorage);
471
dt_fswatch_destroy(darktable.fswatch);
473
sqlite3_close(darktable.db);
474
dt_pthread_mutex_destroy(&(darktable.db_insert));
475
dt_pthread_mutex_destroy(&(darktable.plugin_threadsafe));
483
void dt_print(dt_debug_thread_t thread, const char *msg, ...)
485
if(darktable.unmuted & thread)
494
void dt_gettime_t(char *datetime, time_t t)
497
(void)localtime_r(&t, &tt);
498
strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tt);
501
void dt_gettime(char *datetime)
503
dt_gettime_t(datetime, time(NULL));
506
void *dt_alloc_align(size_t alignment, size_t size)
508
#if defined(__MACH__) || defined(__APPLE__) || (defined(__FreeBSD_version) && __FreeBSD_version < 700013)
512
if(posix_memalign(&ptr, alignment, size)) return NULL;
518
dt_get_user_config_dir (char *data, size_t bufsize)
520
g_snprintf (data,bufsize,"%s/.config/darktable",getenv("HOME"));
521
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
522
g_mkdir_with_parents (data,0700);
526
dt_get_user_cache_dir (char *data, size_t bufsize)
528
g_snprintf (data,bufsize,"%s/.cache/darktable",getenv("HOME"));
529
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
530
g_mkdir_with_parents (data,0700);
535
dt_get_user_local_dir (char *data, size_t bufsize)
537
g_snprintf(data,bufsize,"%s/.local",getenv("HOME"));
538
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
539
g_mkdir_with_parents (data,0700);
543
void dt_get_plugindir(char *datadir, size_t bufsize)
545
#if defined(__MACH__) || defined(__APPLE__)
546
gchar *curr = g_get_current_dir();
548
for(int k=0; darktable.progname[k] != 0; k++) if(darktable.progname[k] == '/')
553
if(darktable.progname[0] == '/') // absolute path
554
snprintf(datadir, bufsize, "%s", darktable.progname);
555
else if(contains) // relative path
556
snprintf(datadir, bufsize, "%s/%s", curr, darktable.progname);
559
// no idea where we have been called. use compiled in path
561
snprintf(datadir, bufsize, "%s/darktable", DARKTABLE_LIBDIR);
564
size_t len = MIN(strlen(datadir), bufsize);
565
char *t = datadir + len; // strip off bin/darktable
566
for(; t>datadir && *t!='/'; t--);
568
if(*t == '.' && *(t-1) != '.')
570
for(; t>datadir && *t!='/'; t--);
573
for(; t>datadir && *t!='/'; t--);
574
strcpy(t, "/lib/darktable");
577
snprintf(datadir, bufsize, "%s/darktable", DARKTABLE_LIBDIR);
581
void dt_get_datadir(char *datadir, size_t bufsize)
583
#if defined(__MACH__) || defined(__APPLE__)
584
gchar *curr = g_get_current_dir();
586
for(int k=0; darktable.progname[k] != 0; k++) if(darktable.progname[k] == '/')
591
if(darktable.progname[0] == '/') // absolute path
592
snprintf(datadir, bufsize, "%s", darktable.progname);
593
else if(contains) // relative path
594
snprintf(datadir, bufsize, "%s/%s", curr, darktable.progname);
597
// no idea where we have been called. use compiled in path
599
snprintf(datadir, bufsize, "%s", DARKTABLE_DATADIR);
602
size_t len = MIN(strlen(datadir), bufsize);
603
char *t = datadir + len; // strip off bin/darktable
604
for(; t>datadir && *t!='/'; t--);
606
if(*t == '.' && *(t-1) != '.')
608
for(; t>datadir && *t!='/'; t--);
611
for(; t>datadir && *t!='/'; t--);
612
strcpy(t, "/share/darktable");
615
snprintf(datadir, bufsize, "%s", DARKTABLE_DATADIR);
619
void dt_show_times(const dt_times_t *start, const char *prefix, const char *suffix, ...)
622
char buf[120]; /* Arbitrary size, should be lots big enough for everything used in DT */
625
/* Skip all the calculations an everything if -d perf isn't on */
626
if (darktable.unmuted & DT_DEBUG_PERF)
629
i = sprintf(buf, "%s took %.3f secs (%.3f CPU)", prefix, end.clock - start->clock, end.user - start->user);
633
va_start(ap, suffix);
635
vsnprintf(buf + i, sizeof buf - i, suffix, ap);
638
dt_print(DT_DEBUG_PERF, "%s\n", buf);