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};
110
strcat(message,_("SIMD extensions found: "));
111
if((cx & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE3)){
113
strcat(message,"SSE3 ");
115
if( ((dx >> 26) & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE2)) {
117
strcat(message,"SSE2 ");
119
else if (((dx >> 25) & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE)){
121
strcat(message,"SSE ");
124
strcat(message,"none");
127
/* for now, bail out if SSE2 is not availble */
128
if(!(darktable.cpu_flags & DT_CPU_FLAG_SSE2))
130
gtk_init (&argc, &argv);
132
GtkWidget *dlg = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_(
133
"darktable is very cpu intensive and uses SSE2 SIMD instructions \
134
for heavy calculations. This gives a better user experience but also defines a minimum \
135
processor requirement.\n\nThe processor in YOUR system does NOT support SSE2. \
136
darktable will now close down.\n\n%s"),message);
138
gtk_dialog_run(GTK_DIALOG(dlg));
145
int dt_init(int argc, char *argv[])
148
fprintf("[dt_init] unfortunately we depend on SSE2 instructions at this time.\n");
149
fprintf("[dt_init] please contribute a backport patch (or buy a newer processor).\n");
152
bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR);
153
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
154
textdomain (GETTEXT_PACKAGE);
156
darktable.progname = argv[0];
159
gchar *dbfilenameFromCommand = NULL;
162
omp_set_num_threads(omp_get_num_procs());
164
darktable.unmuted = 0;
165
char *image_to_load = NULL;
166
for(int k=1; k<argc; k++)
168
if(argv[k][0] == '-')
170
if(!strcmp(argv[k], "--help"))
172
return usage(argv[0]);
174
else if(!strcmp(argv[k], "--version"))
176
printf("this is "PACKAGE_STRING"\ncopyright (c) 2009-2011 johannes hanika\n"PACKAGE_BUGREPORT"\n");
179
else if(!strcmp(argv[k], "--library"))
181
dbfilenameFromCommand = argv[++k];
183
if(argv[k][1] == 'd' && argc > k+1)
185
if(!strcmp(argv[k+1], "all")) darktable.unmuted = 0xffffffff; // enable all debug information
186
else if(!strcmp(argv[k+1], "cache")) darktable.unmuted |= DT_DEBUG_CACHE; // enable debugging for lib/film/cache module
187
else if(!strcmp(argv[k+1], "control")) darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
188
else if(!strcmp(argv[k+1], "dev")) darktable.unmuted |= DT_DEBUG_DEV; // develop module
189
else if(!strcmp(argv[k+1], "fswatch")) darktable.unmuted |= DT_DEBUG_FSWATCH; // fswatch module
190
else if(!strcmp(argv[k+1], "camctl")) darktable.unmuted |= DT_DEBUG_CAMCTL; // camera control module
191
else if(!strcmp(argv[k+1], "perf")) darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
192
else if(!strcmp(argv[k+1], "pwstorage")) darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
193
else if(!strcmp(argv[k+1], "opencl")) darktable.unmuted |= DT_DEBUG_OPENCL; // gpu accel via opencl
194
else return usage(argv[0]);
200
image_to_load = argv[k];
205
/* check cput caps */
206
dt_check_cpu(argc,argv);
210
(void)setenv("GEGL_PATH", DARKTABLE_DATADIR"/gegl:/usr/lib/gegl-0.0", 1);
211
gegl_init(&argc, &argv);
216
dt_get_user_config_dir (datadir,1024);
218
snprintf(filename, 1024, "%s/darktablerc", datadir);
220
// Initialize the filesystem watcher
221
darktable.fswatch=dt_fswatch_new();
224
// Initialize the camera control
225
darktable.camctl=dt_camctl_new();
227
// has to go first for settings needed by all the others.
228
darktable.conf = (dt_conf_t *)malloc(sizeof(dt_conf_t));
229
dt_conf_init(darktable.conf, filename);
231
// get max lighttable thumbnail size:
232
darktable.thumbnail_size = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_size"), 160, 1300);
233
// and make sure it can be mip-mapped all the way from mip4 to mip0
234
darktable.thumbnail_size /= 16;
235
darktable.thumbnail_size *= 16;
237
// Initialize the password storage engine
238
darktable.pwstorage=dt_pwstorage_new();
240
// check and migrate database into new XDG structure
241
char dbfilename[2048]= {0};
242
gchar *conf_db = dt_conf_get_string("database");
243
if (conf_db && conf_db[0] != '/')
245
char *homedir = getenv ("HOME");
246
snprintf (dbfilename,2048,"%s/%s", homedir, conf_db);
247
if (g_file_test (dbfilename, G_FILE_TEST_EXISTS))
249
fprintf(stderr, "[init] moving database into new XDG directory structure\n");
250
// move database into place
251
char destdbname[2048]= {0};
252
snprintf(destdbname,2048,"%s/%s",datadir,"library.db");
253
if(!g_file_test (destdbname,G_FILE_TEST_EXISTS))
255
rename(dbfilename,destdbname);
256
dt_conf_set_string("database","library.db");
262
// check and migrate the cachedir
263
char cachefilename[2048]= {0};
264
char cachedir[2048]= {0};
265
gchar *conf_cache = dt_conf_get_string("cachefile");
266
if (conf_cache && conf_cache[0] != '/')
268
char *homedir = getenv ("HOME");
269
snprintf (cachefilename,2048,"%s/%s",homedir, conf_cache);
270
if (g_file_test (cachefilename,G_FILE_TEST_EXISTS))
272
fprintf(stderr, "[init] moving cache into new XDG directory structure\n");
273
char destcachename[2048]= {0};
274
snprintf(destcachename,2048,"%s/%s",cachedir,"mipmaps");
275
if(!g_file_test (destcachename,G_FILE_TEST_EXISTS))
277
rename(cachefilename,destcachename);
278
dt_conf_set_string("cachefile","mipmaps");
284
gchar * dbname = NULL;
285
if ( dbfilenameFromCommand == NULL )
287
dbname = dt_conf_get_string ("database");
288
if(!dbname) snprintf(dbfilename, 1024, "%s/library.db", datadir);
289
else if(dbname[0] != '/') snprintf(dbfilename, 1024, "%s/%s", datadir, dbname);
290
else snprintf(dbfilename, 1024, "%s", dbname);
294
snprintf(dbfilename, 1024, "%s", dbfilenameFromCommand);
295
dbname = g_file_get_basename (g_file_new_for_path(dbfilenameFromCommand));
299
// if db file does not exist, also don't load the cache.
300
if(!g_file_test(dbfilename, G_FILE_TEST_IS_REGULAR)) load_cached = 0;
301
if(sqlite3_open(dbfilename, &(darktable.db)))
303
fprintf(stderr, "[init] could not open database ");
304
if(dbname) fprintf(stderr, "`%s'!\n", dbname);
305
else fprintf(stderr, "\n");
307
fprintf(stderr, "[init] maybe your %s/darktablerc is corrupt?\n",datadir);
308
dt_get_datadir(dbfilename, 512);
309
fprintf(stderr, "[init] try `cp %s/darktablerc %s/darktablerc'\n", dbfilename,datadir);
311
fprintf(stderr, "[init] check your /apps/darktable/database gconf entry!\n");
313
sqlite3_close(darktable.db);
314
if (dbname != NULL) g_free(dbname);
317
if (dbname != NULL) g_free(dbname);
319
dt_pthread_mutex_init(&(darktable.db_insert), NULL);
320
dt_pthread_mutex_init(&(darktable.plugin_threadsafe), NULL);
322
// initialize collection query
323
darktable.collection_listeners = NULL;
324
darktable.collection = dt_collection_new(NULL);
326
darktable.opencl = (dt_opencl_t *)malloc(sizeof(dt_opencl_t));
327
dt_opencl_init(darktable.opencl, argc, argv);
329
darktable.points = (dt_points_t *)malloc(sizeof(dt_points_t));
330
dt_points_init(darktable.points, dt_get_num_threads());
332
darktable.control = (dt_control_t *)malloc(sizeof(dt_control_t));
333
dt_control_init(darktable.control);
335
int thumbnails = dt_conf_get_int ("mipmap_cache_thumbnails");
336
thumbnails = MIN(1000, MAX(20, thumbnails));
338
darktable.mipmap_cache = (dt_mipmap_cache_t *)malloc(sizeof(dt_mipmap_cache_t));
339
dt_mipmap_cache_init(darktable.mipmap_cache, thumbnails);
341
darktable.image_cache = (dt_image_cache_t *)malloc(sizeof(dt_image_cache_t));
342
dt_image_cache_init(darktable.image_cache, MIN(10000, MAX(500, thumbnails)), load_cached);
344
darktable.view_manager = (dt_view_manager_t *)malloc(sizeof(dt_view_manager_t));
345
dt_view_manager_init(darktable.view_manager);
347
darktable.gui = (dt_gui_gtk_t *)malloc(sizeof(dt_gui_gtk_t));
348
if(dt_gui_gtk_init(darktable.gui, argc, argv)) return 1;
350
// load the darkroom mode plugins once:
351
dt_iop_load_modules_so();
353
darktable.lib = (dt_lib_t *)malloc(sizeof(dt_lib_t));
354
dt_lib_init(darktable.lib);
356
dt_control_load_config(darktable.control);
357
strncpy(darktable.control->global_settings.dbname, filename, 512); // overwrite if relocated.
359
darktable.imageio = (dt_imageio_t *)malloc(sizeof(dt_imageio_t));
360
dt_imageio_init(darktable.imageio);
366
if(g_str_has_prefix(image_to_load, "file://"))
367
image_to_load += strlen("file://");
368
if(g_path_is_absolute(image_to_load) == FALSE)
370
char* current_dir = g_get_current_dir();
371
char* tmp_filename = g_build_filename(current_dir, image_to_load, NULL);
372
filename = (char*)g_malloc(sizeof(char)*MAXPATHLEN);
373
if(realpath(tmp_filename, filename) == NULL)
375
dt_control_log(_("found strange path `%s'"), tmp_filename);
377
g_free(tmp_filename);
382
g_free(tmp_filename);
386
filename = g_strdup(image_to_load);
389
if(g_file_test(filename, G_FILE_TEST_IS_DIR))
391
// import a directory into a film roll
392
unsigned int last_char = strlen(filename)-1;
393
if(filename[last_char] == '/')
394
filename[last_char] = '\0';
395
id = dt_film_import(filename);
399
dt_ctl_switch_mode_to(DT_LIBRARY);
403
dt_control_log(_("error loading directory `%s'"), filename);
408
// import a single image
409
gchar *directory = g_path_get_dirname((const gchar *)filename);
411
const int filmid = dt_film_new(&film, directory);
412
id = dt_image_import(filmid, filename, TRUE);
416
dt_film_open(filmid);
417
// make sure buffers are loaded (load full for testing)
418
dt_image_t *img = dt_image_cache_get(id, 'r');
419
dt_image_buffer_t buf = dt_image_get_blocking(img, DT_IMAGE_FULL, 'r');
423
dt_image_cache_release(img, 'r');
424
dt_control_log(_("file `%s' has unknown format!"), filename);
428
dt_image_release(img, DT_IMAGE_FULL, 'r');
429
dt_image_cache_release(img, 'r');
430
DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id);
431
dt_ctl_switch_mode_to(DT_DEVELOP);
436
dt_control_log(_("error loading file `%s'"), filename);
443
dt_ctl_switch_mode_to(DT_LIBRARY);
451
dt_ctl_switch_mode_to(DT_MODE_NONE);
453
dt_control_write_config(darktable.control);
454
dt_control_shutdown(darktable.control);
456
dt_lib_cleanup(darktable.lib);
458
dt_view_manager_cleanup(darktable.view_manager);
459
free(darktable.view_manager);
460
dt_imageio_cleanup(darktable.imageio);
461
free(darktable.imageio);
462
dt_gui_gtk_cleanup(darktable.gui);
464
dt_image_cache_cleanup(darktable.image_cache);
465
free(darktable.image_cache);
466
dt_mipmap_cache_cleanup(darktable.mipmap_cache);
467
free(darktable.mipmap_cache);
468
dt_control_cleanup(darktable.control);
469
free(darktable.control);
470
dt_conf_cleanup(darktable.conf);
471
free(darktable.conf);
472
dt_points_cleanup(darktable.points);
473
free(darktable.points);
474
dt_iop_unload_modules_so();
475
dt_opencl_cleanup(darktable.opencl);
476
free(darktable.opencl);
478
dt_camctl_destroy(darktable.camctl);
480
dt_pwstorage_destroy(darktable.pwstorage);
481
dt_fswatch_destroy(darktable.fswatch);
483
sqlite3_close(darktable.db);
484
dt_pthread_mutex_destroy(&(darktable.db_insert));
485
dt_pthread_mutex_destroy(&(darktable.plugin_threadsafe));
493
void dt_print(dt_debug_thread_t thread, const char *msg, ...)
495
if(darktable.unmuted & thread)
504
void dt_gettime_t(char *datetime, time_t t)
507
(void)localtime_r(&t, &tt);
508
strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tt);
511
void dt_gettime(char *datetime)
513
dt_gettime_t(datetime, time(NULL));
516
void *dt_alloc_align(size_t alignment, size_t size)
518
#if defined(__MACH__) || defined(__APPLE__) || (defined(__FreeBSD_version) && __FreeBSD_version < 700013)
522
if(posix_memalign(&ptr, alignment, size)) return NULL;
528
dt_get_user_config_dir (char *data, size_t bufsize)
530
g_snprintf (data,bufsize,"%s/.config/darktable",getenv("HOME"));
531
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
532
g_mkdir_with_parents (data,0700);
536
dt_get_user_cache_dir (char *data, size_t bufsize)
538
g_snprintf (data,bufsize,"%s/.cache/darktable",getenv("HOME"));
539
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
540
g_mkdir_with_parents (data,0700);
545
dt_get_user_local_dir (char *data, size_t bufsize)
547
g_snprintf(data,bufsize,"%s/.local",getenv("HOME"));
548
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
549
g_mkdir_with_parents (data,0700);
553
void dt_get_plugindir(char *datadir, size_t bufsize)
555
#if defined(__MACH__) || defined(__APPLE__)
556
gchar *curr = g_get_current_dir();
558
for(int k=0; darktable.progname[k] != 0; k++) if(darktable.progname[k] == '/')
563
if(darktable.progname[0] == '/') // absolute path
564
snprintf(datadir, bufsize, "%s", darktable.progname);
565
else if(contains) // relative path
566
snprintf(datadir, bufsize, "%s/%s", curr, darktable.progname);
569
// no idea where we have been called. use compiled in path
571
snprintf(datadir, bufsize, "%s/darktable", DARKTABLE_LIBDIR);
574
size_t len = MIN(strlen(datadir), bufsize);
575
char *t = datadir + len; // strip off bin/darktable
576
for(; t>datadir && *t!='/'; t--);
578
if(*t == '.' && *(t-1) != '.')
580
for(; t>datadir && *t!='/'; t--);
583
for(; t>datadir && *t!='/'; t--);
584
strcpy(t, "/lib/darktable");
587
snprintf(datadir, bufsize, "%s/darktable", DARKTABLE_LIBDIR);
591
void dt_get_datadir(char *datadir, size_t bufsize)
593
#if defined(__MACH__) || defined(__APPLE__)
594
gchar *curr = g_get_current_dir();
596
for(int k=0; darktable.progname[k] != 0; k++) if(darktable.progname[k] == '/')
601
if(darktable.progname[0] == '/') // absolute path
602
snprintf(datadir, bufsize, "%s", darktable.progname);
603
else if(contains) // relative path
604
snprintf(datadir, bufsize, "%s/%s", curr, darktable.progname);
607
// no idea where we have been called. use compiled in path
609
snprintf(datadir, bufsize, "%s", DARKTABLE_DATADIR);
612
size_t len = MIN(strlen(datadir), bufsize);
613
char *t = datadir + len; // strip off bin/darktable
614
for(; t>datadir && *t!='/'; t--);
616
if(*t == '.' && *(t-1) != '.')
618
for(; t>datadir && *t!='/'; t--);
621
for(; t>datadir && *t!='/'; t--);
622
strcpy(t, "/share/darktable");
625
snprintf(datadir, bufsize, "%s", DARKTABLE_DATADIR);
629
void dt_show_times(const dt_times_t *start, const char *prefix, const char *suffix, ...)
632
char buf[120]; /* Arbitrary size, should be lots big enough for everything used in DT */
635
/* Skip all the calculations an everything if -d perf isn't on */
636
if (darktable.unmuted & DT_DEBUG_PERF)
639
i = sprintf(buf, "%s took %.3f secs (%.3f CPU)", prefix, end.clock - start->clock, end.user - start->user);
643
va_start(ap, suffix);
645
vsnprintf(buf + i, sizeof buf - i, suffix, ap);
648
dt_print(DT_DEBUG_PERF, "%s\n", buf);