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
#define cpuid(fnc,ax,bx,cx,dx)\
82
__asm__ __volatile__(\
87
: "=a"(ax), "=r"(bx), "=c"(cx), "=d"(dx) : "a"(fnc) );
90
void dt_check_cpu(int argc,char **argv)
92
/* hook up SIGILL handler */
93
_dt_sigill_old_handler = signal(SIGILL,&_dt_sigill_handler);
95
/* call cpuid for SSE level */
97
cpuid(0x1,ax,bx,cx,dx);
100
char message[512]={0};
101
strcat(message,_("SIMD extenstions found: "));
102
if((cx & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE3))
103
strcat(message,"SSE3 ");
104
if( ((dx >> 26) & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE2))
105
strcat(message,"SSE2 ");
106
else if (((dx >> 25) & 1) && (darktable.cpu_flags |= DT_CPU_FLAG_SSE))
107
strcat(message,"SSE ");
109
/* for now, bail out if SSE2 is not availble */
110
if(!(darktable.cpu_flags & DT_CPU_FLAG_SSE2))
112
gtk_init (&argc, &argv);
114
GtkWidget *dlg = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_(
115
"darktable is very cpu resource intensive and is using SSE2 SIMD instructions \
116
for heavy calculations, this is for a better user experience but also defines a minimum\
117
requirement of your processor.\n\nThe processor in YOUR system does NOT support this \
118
and darktable will now close down.\n\n%s"),message);
120
gtk_dialog_run(GTK_DIALOG(dlg));
127
int dt_init(int argc, char *argv[])
130
fprintf("[dt_init] unfortunately we depend on SSE2 instructions at this time.\n");
131
fprintf("[dt_init] please contribute a backport patch (or buy a newer processor).\n");
134
bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR);
135
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
136
textdomain (GETTEXT_PACKAGE);
138
darktable.progname = argv[0];
141
gchar *dbfilenameFromCommand = NULL;
144
omp_set_num_threads(omp_get_num_procs());
146
darktable.unmuted = 0;
147
char *image_to_load = NULL;
148
for(int k=1; k<argc; k++)
150
if(argv[k][0] == '-')
152
if(!strcmp(argv[k], "--help"))
154
return usage(argv[0]);
156
else if(!strcmp(argv[k], "--version"))
158
printf("this is "PACKAGE_STRING"\ncopyright (c) 2009-2011 johannes hanika\n"PACKAGE_BUGREPORT"\n");
161
else if(!strcmp(argv[k], "--library"))
163
dbfilenameFromCommand = argv[++k];
165
if(argv[k][1] == 'd' && argc > k+1)
167
if(!strcmp(argv[k+1], "all")) darktable.unmuted = 0xffffffff; // enable all debug information
168
else if(!strcmp(argv[k+1], "cache")) darktable.unmuted |= DT_DEBUG_CACHE; // enable debugging for lib/film/cache module
169
else if(!strcmp(argv[k+1], "control")) darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
170
else if(!strcmp(argv[k+1], "dev")) darktable.unmuted |= DT_DEBUG_DEV; // develop module
171
else if(!strcmp(argv[k+1], "fswatch")) darktable.unmuted |= DT_DEBUG_FSWATCH; // fswatch module
172
else if(!strcmp(argv[k+1], "camctl")) darktable.unmuted |= DT_DEBUG_CAMCTL; // camera control module
173
else if(!strcmp(argv[k+1], "perf")) darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
174
else if(!strcmp(argv[k+1], "pwstorage")) darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
175
else if(!strcmp(argv[k+1], "opencl")) darktable.unmuted |= DT_DEBUG_OPENCL; // gpu accel via opencl
176
else return usage(argv[0]);
182
image_to_load = argv[k];
187
/* check cput caps */
188
dt_check_cpu(argc,argv);
192
(void)setenv("GEGL_PATH", DARKTABLE_DATADIR"/gegl:/usr/lib/gegl-0.0", 1);
193
gegl_init(&argc, &argv);
198
dt_get_user_config_dir (datadir,1024);
200
snprintf(filename, 1024, "%s/darktablerc", datadir);
202
// Initialize the filesystem watcher
203
darktable.fswatch=dt_fswatch_new();
206
// Initialize the camera control
207
darktable.camctl=dt_camctl_new();
209
// has to go first for settings needed by all the others.
210
darktable.conf = (dt_conf_t *)malloc(sizeof(dt_conf_t));
211
dt_conf_init(darktable.conf, filename);
213
// get max lighttable thumbnail size:
214
darktable.thumbnail_size = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_size"), 160, 1300);
215
// and make sure it can be mip-mapped all the way from mip4 to mip0
216
darktable.thumbnail_size /= 16;
217
darktable.thumbnail_size *= 16;
219
// Initialize the password storage engine
220
darktable.pwstorage=dt_pwstorage_new();
222
// check and migrate database into new XDG structure
223
char dbfilename[2048]= {0};
224
gchar *conf_db = dt_conf_get_string("database");
225
if (conf_db && conf_db[0] != '/')
227
char *homedir = getenv ("HOME");
228
snprintf (dbfilename,2048,"%s/%s", homedir, conf_db);
229
if (g_file_test (dbfilename, G_FILE_TEST_EXISTS))
231
fprintf(stderr, "[init] moving database into new XDG directory structure\n");
232
// move database into place
233
char destdbname[2048]= {0};
234
snprintf(destdbname,2048,"%s/%s",datadir,"library.db");
235
if(!g_file_test (destdbname,G_FILE_TEST_EXISTS))
237
rename(dbfilename,destdbname);
238
dt_conf_set_string("database","library.db");
244
// check and migrate the cachedir
245
char cachefilename[2048]= {0};
246
char cachedir[2048]= {0};
247
gchar *conf_cache = dt_conf_get_string("cachefile");
248
if (conf_cache && conf_cache[0] != '/')
250
char *homedir = getenv ("HOME");
251
snprintf (cachefilename,2048,"%s/%s",homedir, conf_cache);
252
if (g_file_test (cachefilename,G_FILE_TEST_EXISTS))
254
fprintf(stderr, "[init] moving cache into new XDG directory structure\n");
255
char destcachename[2048]= {0};
256
snprintf(destcachename,2048,"%s/%s",cachedir,"mipmaps");
257
if(!g_file_test (destcachename,G_FILE_TEST_EXISTS))
259
rename(cachefilename,destcachename);
260
dt_conf_set_string("cachefile","mipmaps");
266
gchar * dbname = NULL;
267
if ( dbfilenameFromCommand == NULL )
269
dbname = dt_conf_get_string ("database");
270
if(!dbname) snprintf(dbfilename, 1024, "%s/library.db", datadir);
271
else if(dbname[0] != '/') snprintf(dbfilename, 1024, "%s/%s", datadir, dbname);
272
else snprintf(dbfilename, 1024, "%s", dbname);
276
snprintf(dbfilename, 1024, "%s", dbfilenameFromCommand);
277
dbname = g_file_get_basename (g_file_new_for_path(dbfilenameFromCommand));
281
// if db file does not exist, also don't load the cache.
282
if(!g_file_test(dbfilename, G_FILE_TEST_IS_REGULAR)) load_cached = 0;
283
if(sqlite3_open(dbfilename, &(darktable.db)))
285
fprintf(stderr, "[init] could not open database ");
286
if(dbname) fprintf(stderr, "`%s'!\n", dbname);
287
else fprintf(stderr, "\n");
289
fprintf(stderr, "[init] maybe your %s/darktablerc is corrupt?\n",datadir);
290
dt_get_datadir(dbfilename, 512);
291
fprintf(stderr, "[init] try `cp %s/darktablerc %s/darktablerc'\n", dbfilename,datadir);
293
fprintf(stderr, "[init] check your /apps/darktable/database gconf entry!\n");
295
sqlite3_close(darktable.db);
296
if (dbname != NULL) g_free(dbname);
299
if (dbname != NULL) g_free(dbname);
301
dt_pthread_mutex_init(&(darktable.db_insert), NULL);
302
dt_pthread_mutex_init(&(darktable.plugin_threadsafe), NULL);
304
// initialize collection query
305
darktable.collection_listeners = NULL;
306
darktable.collection = dt_collection_new(NULL);
308
darktable.opencl = (dt_opencl_t *)malloc(sizeof(dt_opencl_t));
309
dt_opencl_init(darktable.opencl, argc, argv);
311
darktable.points = (dt_points_t *)malloc(sizeof(dt_points_t));
312
dt_points_init(darktable.points, dt_get_num_threads());
314
darktable.control = (dt_control_t *)malloc(sizeof(dt_control_t));
315
dt_control_init(darktable.control);
317
int thumbnails = dt_conf_get_int ("mipmap_cache_thumbnails");
318
thumbnails = MIN(1000, MAX(20, thumbnails));
320
darktable.mipmap_cache = (dt_mipmap_cache_t *)malloc(sizeof(dt_mipmap_cache_t));
321
dt_mipmap_cache_init(darktable.mipmap_cache, thumbnails);
323
darktable.image_cache = (dt_image_cache_t *)malloc(sizeof(dt_image_cache_t));
324
dt_image_cache_init(darktable.image_cache, MIN(10000, MAX(500, thumbnails)), load_cached);
326
darktable.view_manager = (dt_view_manager_t *)malloc(sizeof(dt_view_manager_t));
327
dt_view_manager_init(darktable.view_manager);
329
darktable.gui = (dt_gui_gtk_t *)malloc(sizeof(dt_gui_gtk_t));
330
if(dt_gui_gtk_init(darktable.gui, argc, argv)) return 1;
332
// load the darkroom mode plugins once:
333
dt_iop_load_modules_so();
335
darktable.lib = (dt_lib_t *)malloc(sizeof(dt_lib_t));
336
dt_lib_init(darktable.lib);
338
dt_control_load_config(darktable.control);
339
strncpy(darktable.control->global_settings.dbname, filename, 512); // overwrite if relocated.
341
darktable.imageio = (dt_imageio_t *)malloc(sizeof(dt_imageio_t));
342
dt_imageio_init(darktable.imageio);
348
if(g_str_has_prefix(image_to_load, "file://"))
349
image_to_load += strlen("file://");
350
if(g_path_is_absolute(image_to_load) == FALSE)
352
char* current_dir = g_get_current_dir();
353
char* tmp_filename = g_build_filename(current_dir, image_to_load, NULL);
354
filename = (char*)g_malloc(sizeof(char)*MAXPATHLEN);
355
if(realpath(tmp_filename, filename) == NULL)
357
dt_control_log(_("found strange path `%s'"), tmp_filename);
359
g_free(tmp_filename);
364
g_free(tmp_filename);
368
filename = g_strdup(image_to_load);
371
if(g_file_test(filename, G_FILE_TEST_IS_DIR))
373
// import a directory into a film roll
374
unsigned int last_char = strlen(filename)-1;
375
if(filename[last_char] == '/')
376
filename[last_char] = '\0';
377
id = dt_film_import(filename);
381
dt_ctl_switch_mode_to(DT_LIBRARY);
385
dt_control_log(_("error loading directory `%s'"), filename);
390
// import a single image
391
gchar *directory = g_path_get_dirname((const gchar *)filename);
393
const int filmid = dt_film_new(&film, directory);
394
id = dt_image_import(filmid, filename, TRUE);
398
dt_film_open(filmid);
399
// make sure buffers are loaded (load full for testing)
400
dt_image_t *img = dt_image_cache_get(id, 'r');
401
dt_image_buffer_t buf = dt_image_get_blocking(img, DT_IMAGE_FULL, 'r');
405
dt_image_cache_release(img, 'r');
406
dt_control_log(_("file `%s' has unknown format!"), filename);
410
dt_image_release(img, DT_IMAGE_FULL, 'r');
411
dt_image_cache_release(img, 'r');
412
DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id);
413
dt_ctl_switch_mode_to(DT_DEVELOP);
418
dt_control_log(_("error loading file `%s'"), filename);
425
dt_ctl_switch_mode_to(DT_LIBRARY);
433
dt_ctl_switch_mode_to(DT_MODE_NONE);
435
dt_control_write_config(darktable.control);
436
dt_control_shutdown(darktable.control);
438
dt_lib_cleanup(darktable.lib);
440
dt_view_manager_cleanup(darktable.view_manager);
441
free(darktable.view_manager);
442
dt_imageio_cleanup(darktable.imageio);
443
free(darktable.imageio);
444
dt_gui_gtk_cleanup(darktable.gui);
446
dt_image_cache_cleanup(darktable.image_cache);
447
free(darktable.image_cache);
448
dt_mipmap_cache_cleanup(darktable.mipmap_cache);
449
free(darktable.mipmap_cache);
450
dt_control_cleanup(darktable.control);
451
free(darktable.control);
452
dt_conf_cleanup(darktable.conf);
453
free(darktable.conf);
454
dt_points_cleanup(darktable.points);
455
free(darktable.points);
456
dt_iop_unload_modules_so();
457
dt_opencl_cleanup(darktable.opencl);
458
free(darktable.opencl);
460
dt_camctl_destroy(darktable.camctl);
462
dt_pwstorage_destroy(darktable.pwstorage);
463
dt_fswatch_destroy(darktable.fswatch);
465
sqlite3_close(darktable.db);
466
dt_pthread_mutex_destroy(&(darktable.db_insert));
467
dt_pthread_mutex_destroy(&(darktable.plugin_threadsafe));
475
void dt_print(dt_debug_thread_t thread, const char *msg, ...)
477
if(darktable.unmuted & thread)
486
void dt_gettime_t(char *datetime, time_t t)
489
(void)localtime_r(&t, &tt);
490
strftime(datetime, 20, "%Y:%m:%d %H:%M:%S", &tt);
493
void dt_gettime(char *datetime)
495
dt_gettime_t(datetime, time(NULL));
498
void *dt_alloc_align(size_t alignment, size_t size)
500
#if defined(__MACH__) || defined(__APPLE__) || (defined(__FreeBSD_version) && __FreeBSD_version < 700013)
504
if(posix_memalign(&ptr, alignment, size)) return NULL;
510
dt_get_user_config_dir (char *data, size_t bufsize)
512
g_snprintf (data,bufsize,"%s/.config/darktable",getenv("HOME"));
513
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
514
g_mkdir_with_parents (data,0700);
518
dt_get_user_cache_dir (char *data, size_t bufsize)
520
g_snprintf (data,bufsize,"%s/.cache/darktable",getenv("HOME"));
521
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
522
g_mkdir_with_parents (data,0700);
527
dt_get_user_local_dir (char *data, size_t bufsize)
529
g_snprintf(data,bufsize,"%s/.local",getenv("HOME"));
530
if (g_file_test (data,G_FILE_TEST_EXISTS)==FALSE)
531
g_mkdir_with_parents (data,0700);
535
void dt_get_plugindir(char *datadir, size_t bufsize)
537
#if defined(__MACH__) || defined(__APPLE__)
538
gchar *curr = g_get_current_dir();
540
for(int k=0; darktable.progname[k] != 0; k++) if(darktable.progname[k] == '/')
545
if(darktable.progname[0] == '/') // absolute path
546
snprintf(datadir, bufsize, "%s", darktable.progname);
547
else if(contains) // relative path
548
snprintf(datadir, bufsize, "%s/%s", curr, darktable.progname);
551
// no idea where we have been called. use compiled in path
553
snprintf(datadir, bufsize, "%s/darktable", DARKTABLE_LIBDIR);
556
size_t len = MIN(strlen(datadir), bufsize);
557
char *t = datadir + len; // strip off bin/darktable
558
for(; t>datadir && *t!='/'; t--);
560
if(*t == '.' && *(t-1) != '.')
562
for(; t>datadir && *t!='/'; t--);
565
for(; t>datadir && *t!='/'; t--);
566
strcpy(t, "/lib/darktable");
569
snprintf(datadir, bufsize, "%s/darktable", DARKTABLE_LIBDIR);
573
void dt_get_datadir(char *datadir, size_t bufsize)
575
#if defined(__MACH__) || defined(__APPLE__)
576
gchar *curr = g_get_current_dir();
578
for(int k=0; darktable.progname[k] != 0; k++) if(darktable.progname[k] == '/')
583
if(darktable.progname[0] == '/') // absolute path
584
snprintf(datadir, bufsize, "%s", darktable.progname);
585
else if(contains) // relative path
586
snprintf(datadir, bufsize, "%s/%s", curr, darktable.progname);
589
// no idea where we have been called. use compiled in path
591
snprintf(datadir, bufsize, "%s", DARKTABLE_DATADIR);
594
size_t len = MIN(strlen(datadir), bufsize);
595
char *t = datadir + len; // strip off bin/darktable
596
for(; t>datadir && *t!='/'; t--);
598
if(*t == '.' && *(t-1) != '.')
600
for(; t>datadir && *t!='/'; t--);
603
for(; t>datadir && *t!='/'; t--);
604
strcpy(t, "/share/darktable");
607
snprintf(datadir, bufsize, "%s", DARKTABLE_DATADIR);
611
void dt_show_times(const dt_times_t *start, const char *prefix, const char *suffix, ...)
614
char buf[120]; /* Arbitrary size, should be lots big enough for everything used in DT */
617
/* Skip all the calculations an everything if -d perf isn't on */
618
if (darktable.unmuted & DT_DEBUG_PERF)
621
i = sprintf(buf, "%s took %.3f secs (%.3f CPU)", prefix, end.clock - start->clock, end.user - start->user);
625
va_start(ap, suffix);
627
vsnprintf(buf + i, sizeof buf - i, suffix, ap);
630
dt_print(DT_DEBUG_PERF, "%s\n", buf);