示例#1
0
void dt_lua_init(lua_State*L,const int init_gui)
{
  char tmp_path[PATH_MAX];

  // init the lua environment
  lua_CFunction* cur_type = init_funcs;
  while(*cur_type)
  {
    (*cur_type)(L);
    cur_type++;
  }
  dt_lua_push_darktable_lib(L);
  // build the table containing the configuration info

  lua_getglobal(L,"package");
  dt_lua_goto_subtable(L,"loaded");
  lua_pushstring(L,"darktable");
  dt_lua_push_darktable_lib(L);
  lua_settable(L,-3);
  lua_pop(L,1);

  lua_getglobal(L,"package");
  lua_getfield(L,-1,"path");
  lua_pushstring(L,";");
  dt_loc_get_datadir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_pushstring(L,"/lua/?.lua");
  lua_pushstring(L,";");
  dt_loc_get_user_config_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_pushstring(L,"/lua/?.lua");
  lua_concat(L,7);
  lua_setfield(L,-2,"path");
  lua_pop(L,1);



  if(init_gui)
  {
    // run global init script
    dt_loc_get_datadir(tmp_path, PATH_MAX);
    g_strlcat(tmp_path,"/rc.lua",PATH_MAX);
    dt_lua_dofile(darktable.lua_state,tmp_path);
    // run user init script
    dt_loc_get_user_config_dir(tmp_path, PATH_MAX);
    g_strlcat(tmp_path,"/rc.lua",PATH_MAX);
    dt_lua_dofile(darktable.lua_state,tmp_path);
  }

}
示例#2
0
文件: dbus.c 项目: platoali/darktable
static GVariant *
_handle_get_property(GDBusConnection  *connection,
                     const gchar      *sender,
                     const gchar      *object_path,
                     const gchar      *interface_name,
                     const gchar      *property_name,
                     GError          **error,
                     gpointer          user_data)
{
  GVariant *ret;

  ret = NULL;
  if(!g_strcmp0(property_name, "DataDir"))
  {
    gchar datadir[PATH_MAX];
    dt_loc_get_datadir(datadir, sizeof(datadir));
    ret = g_variant_new_string(datadir);
  }
  else if(!g_strcmp0(property_name, "ConfigDir"))
  {
    gchar configdir[PATH_MAX];
    dt_loc_get_user_config_dir(configdir, sizeof(configdir));
    ret = g_variant_new_string(configdir);
  }
  return ret;
}
示例#3
0
文件: styles.c 项目: gthb/darktable
void
dt_styles_create_from_image (const char *name,const char *description,int32_t imgid,GList *filter)
{
  int id=0;
  sqlite3_stmt *stmt;

  /* first create the style header */
  if (!dt_styles_create_style_header(name,description) ) return;

  if ((id=dt_styles_get_id_by_name(name)) != 0)
  {
    /* create the style_items from source image history stack */
    if (filter)
    {
      GList *list=filter;
      char tmp[64];
      char include[2048]= {0};
      g_strlcat(include,"num in (", 2048);
      do
      {
        if(list!=g_list_first(list))
          g_strlcat(include,",", 2048);
        sprintf(tmp,"%ld",(long int)list->data);
        g_strlcat(include,tmp, 2048);
      }
      while ((list=g_list_next(list)));
      g_strlcat(include,")", 2048);
      char query[4096]= {0};
      sprintf(query,"insert into style_items (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from history where imgid=?2 and %s",include);
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
    }
    else
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into style_items (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name) select ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,multi_priority,multi_name from history where imgid=?2", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
    sqlite3_step (stmt);
    sqlite3_finalize (stmt);

    /* backup style to disk */
    char stylesdir[1024];
    dt_loc_get_user_config_dir(stylesdir, 1024);
    g_strlcat(stylesdir,"/styles",1024);
    g_mkdir_with_parents(stylesdir,00755);

    dt_styles_save_to_file(name,stylesdir,FALSE);

    char tmp_accel[1024];
    gchar* tmp_name = g_strdup(name); // freed by _destro_style_shortcut_callback
    snprintf(tmp_accel,1024,"styles/Apply %s",name);
    dt_accel_register_global( tmp_accel, 0, 0);
    GClosure *closure;
    closure = g_cclosure_new(
                G_CALLBACK(_apply_style_shortcut_callback),
                tmp_name, _destroy_style_shortcut_callback);
    dt_accel_connect_global(tmp_accel, closure);
    dt_control_log(_("style named '%s' successfully created"),name);
  }
}
示例#4
0
void dt_lua_init(lua_State*L,const char *lua_command)
{
  /*
     Note to reviewers
     this is the only place where lua code is run without the lua lock.
     At this point, no user script has been called,
     so we are completely thread-safe. no need to lock

     This is also the only place where lua code is run with the gdk lock
     held, but this is not a problem because it is very brief, user calls
     are delegated to a secondary job
     */
  char tmp_path[PATH_MAX];
  // init the lua environment
  lua_CFunction* cur_type = init_funcs;
  while(*cur_type)
  {
    (*cur_type)(L);
    cur_type++;
  }
  // build the table containing the configuration info

  lua_getglobal(L,"package");
  dt_lua_goto_subtable(L,"loaded");
  lua_pushstring(L,"darktable");
  dt_lua_push_darktable_lib(L);
  lua_settable(L,-3);
  lua_pop(L,1);

  lua_getglobal(L,"package");
  lua_getfield(L,-1,"path");
  lua_pushstring(L,";");
  dt_loc_get_datadir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L,tmp_path);
  lua_pushstring(L,"/lua/?.lua");
  lua_pushstring(L,";");
  dt_loc_get_user_config_dir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L,tmp_path);
  lua_pushstring(L,"/lua/?.lua");
  lua_concat(L,7);
  lua_setfield(L,-2,"path");
  lua_pop(L,1);



  dt_job_t *job = dt_control_job_create(&run_early_script, "lua: run initial script");
  dt_control_job_set_params(job, g_strdup(lua_command));
  if(darktable.gui)
  {
    dt_control_add_job(darktable.control, DT_JOB_QUEUE_USER_BG, job);
  }
  else
  {
    run_early_script(job);
    dt_control_job_dispose(job);
  }

}
示例#5
0
static void refresh_watermarks( dt_iop_module_t *self )
{
  dt_iop_watermark_gui_data_t *g = (dt_iop_watermark_gui_data_t *)self->gui_data;
  dt_iop_watermark_params_t *p = (dt_iop_watermark_params_t *)self->params;

  g_signal_handlers_block_by_func (g->combobox1,watermark_callback,self);

  // Clear combobox...
  GtkTreeModel *model=gtk_combo_box_get_model(g->combobox1);
  gtk_list_store_clear (GTK_LIST_STORE(model));

  // check watermarkdir and update combo with entries...
  int count=0;
  const gchar *d_name = NULL;
  gchar configdir[DT_MAX_PATH_LEN];
  gchar datadir[DT_MAX_PATH_LEN];
  gchar filename[DT_MAX_PATH_LEN];
  dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN);
  dt_loc_get_user_config_dir(configdir, DT_MAX_PATH_LEN);
  g_strlcat(datadir,"/watermarks", DT_MAX_PATH_LEN);
  g_strlcat(configdir,"/watermarks", DT_MAX_PATH_LEN);

  /* read watermarks from datadir */
  GDir *dir = g_dir_open(datadir, 0, NULL);
  if(dir)
  {
    while((d_name = g_dir_read_name(dir)))
    {
      snprintf(filename, DT_MAX_PATH_LEN, "%s/%s", datadir, d_name);
      gtk_combo_box_append_text( g->combobox1, d_name );
      count++;
    }
    g_dir_close(dir) ;
  }

  /* read watermarks from user config dir*/
  dir = g_dir_open(configdir, 0, NULL);
  if(dir)
  {
    while((d_name = g_dir_read_name(dir)))
    {
      snprintf(filename, DT_MAX_PATH_LEN, "%s/%s", configdir, d_name);
      gtk_combo_box_append_text( g->combobox1, d_name );
      count++;
    }
    g_dir_close(dir) ;
  }

  _combo_box_set_active_text( g->combobox1, p->filename );

  g_signal_handlers_unblock_by_func (g->combobox1,watermark_callback,self);

}
示例#6
0
void gui_init(struct dt_iop_module_t *self)
{
  const int force_lcms2 = dt_conf_get_bool("plugins/lighttable/export/force_lcms2");

  self->gui_data = calloc(1, sizeof(dt_iop_colorout_gui_data_t));
  dt_iop_colorout_gui_data_t *g = (dt_iop_colorout_gui_data_t *)self->gui_data;

  char datadir[PATH_MAX] = { 0 };
  char confdir[PATH_MAX] = { 0 };
  dt_loc_get_datadir(datadir, sizeof(datadir));
  dt_loc_get_user_config_dir(confdir, sizeof(confdir));

  self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE);

  // TODO:
  g->output_intent = dt_bauhaus_combobox_new(self);
  gtk_box_pack_start(GTK_BOX(self->widget), g->output_intent, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->output_intent, NULL, _("output intent"));
  dt_bauhaus_combobox_add(g->output_intent, _("perceptual"));
  dt_bauhaus_combobox_add(g->output_intent, _("relative colorimetric"));
  dt_bauhaus_combobox_add(g->output_intent, C_("rendering intent", "saturation"));
  dt_bauhaus_combobox_add(g->output_intent, _("absolute colorimetric"));

  if(!force_lcms2)
  {
    gtk_widget_set_no_show_all(g->output_intent, TRUE);
    gtk_widget_set_visible(g->output_intent, FALSE);
  }

  g->output_profile = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(g->output_profile, NULL, _("output profile"));
  gtk_box_pack_start(GTK_BOX(self->widget), g->output_profile, TRUE, TRUE, 0);
  for(GList *l = darktable.color_profiles->profiles; l; l = g_list_next(l))
  {
    dt_colorspaces_color_profile_t *prof = (dt_colorspaces_color_profile_t *)l->data;
    if(prof->out_pos > -1) dt_bauhaus_combobox_add(g->output_profile, prof->name);
  }

  char tooltip[1024];
  g_object_set(G_OBJECT(g->output_intent), "tooltip-text", _("rendering intent"), (char *)NULL);
  snprintf(tooltip, sizeof(tooltip), _("ICC profiles in %s/color/out or %s/color/out"), confdir, datadir);
  g_object_set(G_OBJECT(g->output_profile), "tooltip-text", tooltip, (char *)NULL);

  g_signal_connect(G_OBJECT(g->output_intent), "value-changed", G_CALLBACK(intent_changed), (gpointer)self);
  g_signal_connect(G_OBJECT(g->output_profile), "value-changed", G_CALLBACK(output_profile_changed), (gpointer)self);

  // reload the profiles when the display or softproof profile changed!
  dt_control_signal_connect(darktable.signals, DT_SIGNAL_CONTROL_PROFILE_CHANGED,
                            G_CALLBACK(_signal_profile_changed), self->dev);
  // update the gui when the preferences changed (i.e. show intent when using lcms2)
  dt_control_signal_connect(darktable.signals, DT_SIGNAL_PREFERENCES_CHANGE,
                            G_CALLBACK(_preference_changed), (gpointer)self);
}
示例#7
0
文件: init.c 项目: BloodyD/darktable
void dt_lua_init(lua_State *L, const char *lua_command)
{
  char tmp_path[PATH_MAX] = { 0 };
  // init the lua environment
  lua_CFunction *cur_type = init_funcs;
  while(*cur_type)
  {
    (*cur_type)(L);
    cur_type++;
  }
  assert(lua_gettop(L)
         == 0); // if you are here, you have probably added an initialisation function that is not stack clean

  // build the table containing the configuration info

  lua_getglobal(L, "package");
  dt_lua_goto_subtable(L, "loaded");
  lua_pushstring(L, "darktable");
  dt_lua_push_darktable_lib(L);
  lua_settable(L, -3);
  lua_pop(L, 1);

  lua_getglobal(L, "package");
  lua_getfield(L, -1, "path");
  lua_pushstring(L, ";");
  dt_loc_get_datadir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L, tmp_path);
  lua_pushstring(L, "/lua/?.lua");
  lua_pushstring(L, ";");
  dt_loc_get_user_config_dir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L, tmp_path);
  lua_pushstring(L, "/lua/?.lua");
  lua_concat(L, 7);
  lua_setfield(L, -2, "path");
  lua_pop(L, 1);



  lua_pushcfunction(L,run_early_script);
  lua_pushstring(L,lua_command);

  if(darktable.gui)
  {
    dt_lua_do_chunk_later(L,1);
  }
  else
  {
    dt_lua_do_chunk_silent(L,1,0);
  }
  // allow other threads to wake up and do their job
  dt_lua_unlock();
}
示例#8
0
static void refresh_watermarks(dt_iop_module_t *self)
{
  dt_iop_watermark_gui_data_t *g = (dt_iop_watermark_gui_data_t *)self->gui_data;
  dt_iop_watermark_params_t *p = (dt_iop_watermark_params_t *)self->params;

  g_signal_handlers_block_by_func(g->watermarks, watermark_callback, self);

  // Clear combobox...
  dt_bauhaus_combobox_clear(g->watermarks);

  // check watermarkdir and update combo with entries...
  int count = 0;
  const gchar *d_name = NULL;
  gchar configdir[PATH_MAX] = { 0 };
  gchar datadir[PATH_MAX] = { 0 };
  gchar filename[PATH_MAX] = { 0 };
  dt_loc_get_datadir(datadir, sizeof(datadir));
  dt_loc_get_user_config_dir(configdir, sizeof(configdir));
  g_strlcat(datadir, "/watermarks", sizeof(datadir));
  g_strlcat(configdir, "/watermarks", sizeof(configdir));

  /* read watermarks from datadir */
  GDir *dir = g_dir_open(datadir, 0, NULL);
  if(dir)
  {
    while((d_name = g_dir_read_name(dir)))
    {
      snprintf(filename, sizeof(filename), "%s/%s", datadir, d_name);
      dt_bauhaus_combobox_add(g->watermarks, d_name);
      count++;
    }
    g_dir_close(dir);
  }

  /* read watermarks from user config dir*/
  dir = g_dir_open(configdir, 0, NULL);
  if(dir)
  {
    while((d_name = g_dir_read_name(dir)))
    {
      snprintf(filename, sizeof(filename), "%s/%s", configdir, d_name);
      dt_bauhaus_combobox_add(g->watermarks, d_name);
      count++;
    }
    g_dir_close(dir);
  }

  _combo_box_set_active_text(g->watermarks, p->filename);

  g_signal_handlers_unblock_by_func(g->watermarks, watermark_callback, self);
}
示例#9
0
int
dt_colorspaces_find_profile(char *filename, const int filename_len, const char *profile, const char *inout)
{
  char datadir[DT_MAX_PATH_LEN];
  dt_loc_get_user_config_dir(datadir, DT_MAX_PATH_LEN);
  snprintf(filename, filename_len, "%s/color/%s/%s", datadir, inout, profile);
  if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
  {
    dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN);
    snprintf(filename, filename_len, "%s/color/%s/%s", datadir, inout, profile);
    if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) return 1;
  }
  return 0;
}
示例#10
0
文件: init.c 项目: BloodyD/darktable
static int run_early_script(lua_State* L)
{
  char tmp_path[PATH_MAX] = { 0 };
  // run global init script
  dt_loc_get_datadir(tmp_path, sizeof(tmp_path));
  g_strlcat(tmp_path, "/luarc", sizeof(tmp_path));
  dt_lua_dofile_silent(L, tmp_path, 0, 0);
  if(darktable.gui != NULL)
  {
    // run user init script
    dt_loc_get_user_config_dir(tmp_path, sizeof(tmp_path));
    g_strlcat(tmp_path, "/luarc", sizeof(tmp_path));
    dt_lua_dofile_silent(L, tmp_path, 0, 0);
  }
  if(!lua_isnil(L,1)){
    const char *lua_command = lua_tostring(L, 1);
    dt_lua_dostring_silent(L, lua_command, 0, 0);
  }
  dt_lua_redraw_screen();
  return 0;
}
示例#11
0
int dt_lua_init_configuration(lua_State*L){
  char tmp_path[PATH_MAX];

  dt_lua_push_darktable_lib(L);

  dt_lua_goto_subtable(L,"configuration");
  // build the table containing the configuration info 

  lua_pushstring(L,"tmp_dir");
  dt_loc_get_tmp_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_settable(L,-3);

  lua_pushstring(L,"config_dir");
  dt_loc_get_user_config_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_settable(L,-3);

  lua_pushstring(L,"cache_dir");
  dt_loc_get_user_cache_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_settable(L,-3);

  lua_pushstring(L,"version");
  lua_pushstring(darktable.lua_state,PACKAGE_VERSION);
  lua_settable(L,-3);

  lua_pushstring(L,"verbose");
  lua_pushboolean(L,darktable.unmuted & DT_DEBUG_LUA);
  lua_settable(L,-3);

  lua_pushstring(L,"has_gui");
  lua_pushboolean(L,darktable.gui != NULL);
  lua_settable(L,-3);

  lua_pop(L,-1); //remove the configuration table from the stack
  return 0;
  
}
示例#12
0
文件: init.c 项目: AlicVB/darktable
static int run_early_script(lua_State* L)
{
  char basedir[PATH_MAX] = { 0 };
  // run global init script
  dt_loc_get_datadir(basedir, sizeof(basedir));
  char *luarc = g_build_filename(basedir, "luarc", NULL);
  dt_lua_check_print_error(L, luaL_dofile(L, luarc));
  g_free(luarc);
  if(darktable.gui != NULL)
  {
    // run user init script
    dt_loc_get_user_config_dir(basedir, sizeof(basedir));
    luarc = g_build_filename(basedir, "luarc", NULL);
    dt_lua_check_print_error(L, luaL_dofile(L, luarc));
    g_free(luarc);
  }
  if(!lua_isnil(L,1)){
    const char *lua_command = lua_tostring(L, 1);
    dt_lua_check_print_error(L,luaL_dostring(L,lua_command));
  }
  dt_lua_redraw_screen();
  return 0;
}
示例#13
0
static int32_t run_early_script(dt_job_t *job)
{
  char tmp_path[PATH_MAX];
  lua_State *L = darktable.lua_state.state;
  gboolean has_lock = dt_lua_lock();
  // run global init script
  dt_loc_get_datadir(tmp_path, sizeof(tmp_path));
  g_strlcat(tmp_path, "/luarc", sizeof(tmp_path));
  dt_lua_dofile_silent(L,tmp_path,0,0);
  if(darktable.gui != NULL)
  {
    // run user init script
    dt_loc_get_user_config_dir(tmp_path, sizeof(tmp_path));
    g_strlcat(tmp_path, "/luarc", sizeof(tmp_path));
    dt_lua_dofile_silent(L,tmp_path,0,0);
  }
  char *lua_command = dt_control_job_get_params(job);
  if(lua_command)
    dt_lua_dostring_silent(L, lua_command, 0, 0);
  free(lua_command);
  dt_lua_redraw_screen();
  dt_lua_unlock(has_lock);
  return 0;
}
示例#14
0
文件: gtk.c 项目: sk1p/darktable
int
dt_gui_gtk_init(dt_gui_gtk_t *gui, int argc, char *argv[])
{
  // unset gtk rc from kde:
  char gtkrc[PATH_MAX], path[PATH_MAX], datadir[PATH_MAX], configdir[PATH_MAX];
  dt_loc_get_datadir(datadir, PATH_MAX);
  dt_loc_get_user_config_dir(configdir, PATH_MAX);

  g_snprintf(gtkrc, PATH_MAX, "%s/darktable.gtkrc", configdir);

  if (!g_file_test(gtkrc, G_FILE_TEST_EXISTS))
    g_snprintf(gtkrc, PATH_MAX, "%s/darktable.gtkrc", datadir);

  if (g_file_test(gtkrc, G_FILE_TEST_EXISTS))
    (void)setenv("GTK2_RC_FILES", gtkrc, 1);
  else
    fprintf(stderr, "[gtk_init] could not found darktable.gtkrc");

  /* lets zero mem */
  memset(gui,0,sizeof(dt_gui_gtk_t));

#if GLIB_MAJOR_VERSION <= 2
#if GLIB_MINOR_VERSION < 31
  if (!g_thread_supported ()) g_thread_init(NULL);
#endif
#endif
  gdk_threads_init();

  gdk_threads_enter();

  gtk_init (&argc, &argv);

  GtkWidget *widget;
  gui->ui = dt_ui_initialize(argc,argv);
  gui->pixmap = NULL;
  gui->center_tooltip = 0;
  gui->presets_popup_menu = NULL;

  if(g_file_test(gtkrc, G_FILE_TEST_EXISTS))
    gtk_rc_parse (gtkrc);

  // Initializing the shortcut groups
  darktable.control->accelerators = gtk_accel_group_new();

  darktable.control->accelerator_list = NULL;

  // Connecting the callback to update keyboard accels for key_pressed
  g_signal_connect(G_OBJECT(gtk_accel_map_get()),
                   "changed",
                   G_CALLBACK(key_accel_changed),
                   NULL);

  // Initializing widgets
  init_widgets();

  // Adding the global shortcut group to the main window
  gtk_window_add_accel_group(GTK_WINDOW(dt_ui_main_window(darktable.gui->ui)),
                             darktable.control->accelerators);

  // get the screen resolution
  gui->dpi = gdk_screen_get_resolution(gtk_widget_get_screen(GTK_WIDGET(dt_ui_main_window(darktable.gui->ui))));

  // set constant width from conf key
  int panel_width = dt_conf_get_int("panel_width");
  if(panel_width < 20 || panel_width > 500)
  {
    // fix for unset/insane values.
    panel_width = 300;
    dt_conf_set_int("panel_width", panel_width);
  }

  //  dt_gui_background_jobs_init();

  /* Have the delete event (window close) end the program */
  dt_loc_get_datadir(datadir, PATH_MAX);
  snprintf(path, PATH_MAX, "%s/icons", datadir);
  gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), path);

  widget = dt_ui_center(darktable.gui->ui);

  g_signal_connect (G_OBJECT (widget), "key-press-event",
                    G_CALLBACK (key_pressed), NULL);
  g_signal_connect (G_OBJECT (widget), "configure-event",
                    G_CALLBACK (configure), NULL);
  g_signal_connect (G_OBJECT (widget), "expose-event",
                    G_CALLBACK (expose), NULL);
  g_signal_connect (G_OBJECT (widget), "motion-notify-event",
                    G_CALLBACK (mouse_moved), NULL);
  g_signal_connect (G_OBJECT (widget), "leave-notify-event",
                    G_CALLBACK (center_leave), NULL);
  g_signal_connect (G_OBJECT (widget), "enter-notify-event",
                    G_CALLBACK (center_enter), NULL);
  g_signal_connect (G_OBJECT (widget), "button-press-event",
                    G_CALLBACK (button_pressed), NULL);
  g_signal_connect (G_OBJECT (widget), "button-release-event",
                    G_CALLBACK (button_released), NULL);
  g_signal_connect (G_OBJECT (widget), "scroll-event",
                    G_CALLBACK (scrolled), NULL);
  // TODO: left, right, top, bottom:
  //leave-notify-event

  widget = darktable.gui->widgets.left_border;
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)0);
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), darktable.gui->ui);
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)0);
  g_object_set_data(G_OBJECT (widget), "border", (gpointer)0);
  widget = darktable.gui->widgets.right_border;
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)1);
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), darktable.gui->ui);
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)1);
  g_object_set_data(G_OBJECT (widget), "border", (gpointer)1);
  widget = darktable.gui->widgets.top_border;
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)2);
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), darktable.gui->ui);
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)2);
  g_object_set_data(G_OBJECT (widget), "border", (gpointer)2);
  widget = darktable.gui->widgets.bottom_border;
  g_signal_connect (G_OBJECT (widget), "expose-event", G_CALLBACK (expose_borders), (gpointer)3);
  g_signal_connect (G_OBJECT (widget), "button-press-event", G_CALLBACK (borders_button_pressed), darktable.gui->ui);
  g_signal_connect (G_OBJECT (widget), "scroll-event", G_CALLBACK (borders_scrolled), (gpointer)3);
  g_object_set_data(G_OBJECT (widget), "border", (gpointer)3);
  dt_gui_presets_init();

  widget = dt_ui_center(darktable.gui->ui);
  GTK_WIDGET_UNSET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
  // GTK_WIDGET_SET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
  GTK_WIDGET_SET_FLAGS   (widget, GTK_APP_PAINTABLE);

  // TODO: make this work as: libgnomeui testgnome.c
  /*  GtkContainer *box = GTK_CONTAINER(darktable.gui->widgets.plugins_vbox);
  GtkScrolledWindow *swin = GTK_SCROLLED_WINDOW(darktable.gui->
                                                widgets.right_scrolled_window);
  gtk_container_set_focus_vadjustment (box, gtk_scrolled_window_get_vadjustment (swin));
  */
  dt_ctl_get_display_profile(widget, &darktable.control->xprofile_data, &darktable.control->xprofile_size);

  // register keys for view switching
  dt_accel_register_global(NC_("accel", "capture view"), GDK_t, 0);
  dt_accel_register_global(NC_("accel", "lighttable view"), GDK_l, 0);
  dt_accel_register_global(NC_("accel", "darkroom view"), GDK_d, 0);

  dt_accel_connect_global(
      "capture view",
      g_cclosure_new(G_CALLBACK(_gui_switch_view_key_accel_callback),
                     (gpointer)DT_GUI_VIEW_SWITCH_TO_TETHERING, NULL));
  dt_accel_connect_global(
      "lighttable view",
      g_cclosure_new(G_CALLBACK(_gui_switch_view_key_accel_callback),
                     (gpointer)DT_GUI_VIEW_SWITCH_TO_LIBRARY, NULL));
  dt_accel_connect_global(
      "darkroom view",
      g_cclosure_new(G_CALLBACK(_gui_switch_view_key_accel_callback),
                     (gpointer)DT_GUI_VIEW_SWITCH_TO_DARKROOM, NULL));

  // register_keys for applying styles
  init_styles_key_accels();
  connect_styles_key_accels();
  // register ctrl-q to quit:
  dt_accel_register_global(NC_("accel", "quit"), GDK_q, GDK_CONTROL_MASK);

  dt_accel_connect_global(
      "quit",
      g_cclosure_new(G_CALLBACK(quit_callback), NULL, NULL));

  // Contrast and brightness accelerators
  dt_accel_register_global(NC_("accel", "increase brightness"),
                           GDK_F10, 0);
  dt_accel_register_global(NC_("accel", "decrease brightness"),
                           GDK_F9, 0);
  dt_accel_register_global(NC_("accel", "increase contrast"),
                           GDK_F8, 0);
  dt_accel_register_global(NC_("accel", "decrease contrast"),
                           GDK_F7, 0);

  dt_accel_connect_global(
      "increase brightness",
      g_cclosure_new(G_CALLBACK(brightness_key_accel_callback),
                     (gpointer)1, NULL));
  dt_accel_connect_global(
      "decrease brightness",
      g_cclosure_new(G_CALLBACK(brightness_key_accel_callback),
                     (gpointer)0, NULL));
  dt_accel_connect_global(
      "increase contrast",
      g_cclosure_new(G_CALLBACK(contrast_key_accel_callback),
                     (gpointer)1, NULL));
  dt_accel_connect_global(
      "decrease contrast",
      g_cclosure_new(G_CALLBACK(contrast_key_accel_callback),
                     (gpointer)0, NULL));

  // Full-screen accelerators
  dt_accel_register_global(NC_("accel", "toggle fullscreen"), GDK_F11, 0);
  dt_accel_register_global(NC_("accel", "leave fullscreen"), GDK_Escape, 0);

  dt_accel_connect_global(
      "toggle fullscreen",
      g_cclosure_new(G_CALLBACK(fullscreen_key_accel_callback),
                     (gpointer)1, NULL));
  dt_accel_connect_global(
      "leave fullscreen",
      g_cclosure_new(G_CALLBACK(fullscreen_key_accel_callback),
                     (gpointer)0, NULL));

  // Side-border hide/show
  dt_accel_register_global(NC_("accel", "toggle side borders"), GDK_Tab, 0);

  // toggle view of header
  dt_accel_register_global(NC_("accel", "toggle header"),
                           GDK_h, GDK_CONTROL_MASK);

  // View-switch
  dt_accel_register_global(NC_("accel", "switch view"), GDK_period, 0);

  dt_accel_connect_global(
      "switch view",
      g_cclosure_new(G_CALLBACK(view_switch_key_accel_callback), NULL, NULL));

  darktable.gui->reset = 0;
  for(int i=0; i<3; i++) darktable.gui->bgcolor[i] = 0.1333;

  /* apply contrast to theme */
  dt_gui_contrast_init ();

  return 0;
}
示例#15
0
static gchar *_watermark_get_svgdoc(dt_iop_module_t *self, dt_iop_watermark_data_t *data,
                                    const dt_image_t *image)
{
  gsize length;

  gchar *svgdoc = NULL;
  gchar configdir[PATH_MAX] = { 0 };
  gchar datadir[PATH_MAX] = { 0 };
  gchar *filename;
  dt_loc_get_datadir(datadir, sizeof(datadir));
  dt_loc_get_user_config_dir(configdir, sizeof(configdir));
  g_strlcat(datadir, "/watermarks/", sizeof(datadir));
  g_strlcat(configdir, "/watermarks/", sizeof(configdir));
  g_strlcat(datadir, data->filename, sizeof(datadir));
  g_strlcat(configdir, data->filename, sizeof(configdir));

  if(g_file_test(configdir, G_FILE_TEST_EXISTS))
    filename = configdir;
  else if(g_file_test(datadir, G_FILE_TEST_EXISTS))
    filename = datadir;
  else
    return NULL;

  gchar *svgdata = NULL;
  char datetime[200];

  // EXIF datetime
  struct tm tt_exif = { 0 };
  if(sscanf(image->exif_datetime_taken, "%d:%d:%d %d:%d:%d", &tt_exif.tm_year, &tt_exif.tm_mon,
            &tt_exif.tm_mday, &tt_exif.tm_hour, &tt_exif.tm_min, &tt_exif.tm_sec) == 6)
  {
    tt_exif.tm_year -= 1900;
    tt_exif.tm_mon--;
  }

  // Current datetime
  struct tm tt_cur = { 0 };
  time_t t = time(NULL);
  (void)localtime_r(&t, &tt_cur);

  if(g_file_get_contents(filename, &svgdata, &length, NULL))
  {
    // File is loaded lets substitute strings if found...

    // Darktable internal
    svgdoc = _string_substitute(svgdata, "$(DARKTABLE.NAME)", PACKAGE_NAME);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    svgdoc = _string_substitute(svgdata, "$(DARKTABLE.VERSION)", PACKAGE_VERSION);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Simple text from watermark module
    gchar buffer[1024];

    if (data->font[0] && data->text[0])
    {
      g_snprintf(buffer, sizeof(buffer), "%s", data->text);
      svgdoc = _string_substitute(svgdata, "$(WATERMARK_TEXT)", buffer);
      if(svgdoc != svgdata)
      {
        g_free(svgdata);
        svgdata = svgdoc;
      }

      PangoFontDescription *font = pango_font_description_from_string(data->font);
      const PangoStyle font_style = pango_font_description_get_style(font);
      const int font_weight = (int)pango_font_description_get_weight(font);

      g_snprintf(buffer, sizeof(buffer), "%s", pango_font_description_get_family(font));
      svgdoc = _string_substitute(svgdata, "$(WATERMARK_FONT_FAMILY)", buffer);
      if(svgdoc != svgdata)
      {
        g_free(svgdata);
        svgdata = svgdoc;
      }

      switch (font_style)
      {
      case PANGO_STYLE_OBLIQUE:
        g_strlcpy(buffer, "oblique", sizeof(buffer));
        break;
      case PANGO_STYLE_ITALIC:
        g_strlcpy(buffer, "italic", sizeof(buffer));
        break;
      default:
        g_strlcpy(buffer, "normal", sizeof(buffer));
        break;
      }
      svgdoc = _string_substitute(svgdata, "$(WATERMARK_FONT_STYLE)", buffer);
      if(svgdoc != svgdata)
      {
        g_free(svgdata);
        svgdata = svgdoc;
      }

      g_snprintf(buffer, sizeof(buffer), "%d", font_weight);
      svgdoc = _string_substitute(svgdata, "$(WATERMARK_FONT_WEIGHT)", buffer);
      if(svgdoc != svgdata)
      {
        g_free(svgdata);
        svgdata = svgdoc;
      }

      pango_font_description_free(font);
    }

    // watermark color
    GdkRGBA c = { data->color[0], data->color[1], data->color[2], 1.0f };
    g_snprintf(buffer, sizeof(buffer), "%s", gdk_rgba_to_string(&c));
    svgdoc = _string_substitute(svgdata, "$(WATERMARK_COLOR)", buffer);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Current image ID
    g_snprintf(buffer, sizeof(buffer), "%d", image->id);
    svgdoc = _string_substitute(svgdata, "$(IMAGE.ID)", buffer);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Current image
    dt_image_print_exif(image, buffer, sizeof(buffer));
    svgdoc = _string_substitute(svgdata, "$(IMAGE.EXIF)", buffer);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Image exif
    // EXIF date
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE)", image->exif_datetime_taken);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.SECOND) -- 00..60
    strftime(datetime, sizeof(datetime), "%S", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.SECOND)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.MINUTE) -- 00..59
    strftime(datetime, sizeof(datetime), "%M", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.MINUTE)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.HOUR) -- 00..23
    strftime(datetime, sizeof(datetime), "%H", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.HOUR)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.HOUR_AMPM) -- 01..12
    strftime(datetime, sizeof(datetime), "%I %p", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.HOUR_AMPM)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.DAY) -- 01..31
    strftime(datetime, sizeof(datetime), "%d", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.DAY)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.MONTH) -- 01..12
    strftime(datetime, sizeof(datetime), "%m", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.MONTH)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized
    strftime(datetime, sizeof(datetime), "%b", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.SHORT_MONTH)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.LONG_MONTH) -- January, February, .., December, localized
    strftime(datetime, sizeof(datetime), "%B", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.LONG_MONTH)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.SHORT_YEAR) -- 12
    strftime(datetime, sizeof(datetime), "%y", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.SHORT_YEAR)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.LONG_YEAR) -- 2012
    strftime(datetime, sizeof(datetime), "%Y", &tt_exif);
    svgdoc = _string_substitute(svgdata, "$(EXIF.DATE.LONG_YEAR)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Current date
    // $(DATE) -- YYYY:
    dt_gettime_t(datetime, sizeof(datetime), t);
    svgdoc = _string_substitute(svgdata, "$(DATE)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.SECOND) -- 00..60
    strftime(datetime, sizeof(datetime), "%S", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.SECOND)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.MINUTE) -- 00..59
    strftime(datetime, sizeof(datetime), "%M", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.MINUTE)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.HOUR) -- 00..23
    strftime(datetime, sizeof(datetime), "%H", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.HOUR)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.HOUR_AMPM) -- 01..12
    strftime(datetime, sizeof(datetime), "%I %p", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.HOUR_AMPM)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.DAY) -- 01..31
    strftime(datetime, sizeof(datetime), "%d", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.DAY)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.MONTH) -- 01..12
    strftime(datetime, sizeof(datetime), "%m", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.MONTH)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized
    strftime(datetime, sizeof(datetime), "%b", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.SHORT_MONTH)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.LONG_MONTH) -- January, February, .., December, localized
    strftime(datetime, sizeof(datetime), "%B", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.LONG_MONTH)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.SHORT_YEAR) -- 12
    strftime(datetime, sizeof(datetime), "%y", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.SHORT_YEAR)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.LONG_YEAR) -- 2012
    strftime(datetime, sizeof(datetime), "%Y", &tt_cur);
    svgdoc = _string_substitute(svgdata, "$(DATE.LONG_YEAR)", datetime);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    svgdoc = _string_substitute(svgdata, "$(EXIF.MAKER)", image->camera_maker);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    svgdoc = _string_substitute(svgdata, "$(EXIF.MODEL)", image->camera_model);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    svgdoc = _string_substitute(svgdata, "$(EXIF.LENS)", image->exif_lens);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    svgdoc = _string_substitute(svgdata, "$(IMAGE.FILENAME)", image->filename);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    gchar *basename = g_path_get_basename(image->filename);
    if(g_strrstr(basename, ".")) *(g_strrstr(basename, ".")) = '\0';
    svgdoc = _string_substitute(svgdata, "$(IMAGE.BASENAME)", basename);
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    g_free(basename);

    // TODO: auto generate that code?
    GList *res;
    res = dt_metadata_get(image->id, "Xmp.dc.creator", NULL);
    svgdoc = _string_substitute(svgdata, "$(Xmp.dc.creator)", (res ? res->data : ""));
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if(res)
    {
      g_list_free_full(res, &g_free);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.publisher", NULL);
    svgdoc = _string_substitute(svgdata, "$(Xmp.dc.publisher)", (res ? res->data : ""));
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if(res)
    {
      g_list_free_full(res, &g_free);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.title", NULL);
    svgdoc = _string_substitute(svgdata, "$(Xmp.dc.title)", (res ? res->data : ""));
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if(res)
    {
      g_list_free_full(res, &g_free);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.description", NULL);
    svgdoc = _string_substitute(svgdata, "$(Xmp.dc.description)", (res ? res->data : ""));
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if(res)
    {
      g_list_free_full(res, &g_free);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.rights", NULL);
    svgdoc = _string_substitute(svgdata, "$(Xmp.dc.rights)", (res ? res->data : ""));
    if(svgdoc != svgdata)
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if(res)
    {
      g_list_free_full(res, &g_free);
    }
  }
  return svgdoc;
}
示例#16
0
void gui_init(struct dt_iop_module_t *self)
{
  self->gui_data = malloc(sizeof(dt_iop_watermark_gui_data_t));
  dt_iop_watermark_gui_data_t *g = (dt_iop_watermark_gui_data_t *)self->gui_data;
  dt_iop_watermark_params_t *p = (dt_iop_watermark_params_t *)self->params;

  int line = 0;
  self->widget = gtk_grid_new();
  gtk_grid_set_row_spacing(GTK_GRID(self->widget), DT_BAUHAUS_SPACE);
  gtk_grid_set_column_spacing(GTK_GRID(self->widget), DT_PIXEL_APPLY_DPI(10));

  gtk_grid_attach(GTK_GRID(self->widget), dt_ui_section_label_new(_("content")), 0, line++, 3, 1);

  // Add the marker combobox
  gchar configdir[PATH_MAX] = { 0 };
  gchar datadir[PATH_MAX] = { 0 };
  dt_loc_get_datadir(datadir, sizeof(datadir));
  dt_loc_get_user_config_dir(configdir, sizeof(configdir));
  GtkWidget *label = dtgtk_reset_label_new(_("marker"), self, &p->filename, sizeof(p->filename));
  g->watermarks = dt_bauhaus_combobox_new(self);
  gtk_widget_set_hexpand(GTK_WIDGET(g->watermarks), TRUE);
  char *tooltip = g_strdup_printf(_("SVG watermarks in %s/watermarks or %s/watermarks"), configdir, datadir);
  gtk_widget_set_tooltip_text(g->watermarks, tooltip);
  g_free(tooltip);
  g->refresh = dtgtk_button_new(dtgtk_cairo_paint_refresh, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
  gtk_grid_attach(GTK_GRID(self->widget), label, 0, line++, 1, 1);
  gtk_grid_attach_next_to(GTK_GRID(self->widget), g->watermarks, label, GTK_POS_RIGHT, 1, 1);
  gtk_grid_attach_next_to(GTK_GRID(self->widget), g->refresh, g->watermarks, GTK_POS_RIGHT, 1, 1);


  // Watermark color
  float red = dt_conf_get_float("plugins/darkroom/watermark/color_red");
  float green = dt_conf_get_float("plugins/darkroom/watermark/color_green");
  float blue = dt_conf_get_float("plugins/darkroom/watermark/color_blue");
  GdkRGBA color = (GdkRGBA){.red = red, .green = green, .blue = blue, .alpha = 1.0 };

  label = dtgtk_reset_label_new(_("color"), self, &p->color, 3 * sizeof(float));
  g->colorpick = gtk_color_button_new_with_rgba(&color);
  gtk_widget_set_tooltip_text(g->colorpick, _("watermark color, tag:\n$(WATERMARK_COLOR)"));
  gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(g->colorpick), FALSE);
  gtk_widget_set_size_request(GTK_WIDGET(g->colorpick), DT_PIXEL_APPLY_DPI(24), DT_PIXEL_APPLY_DPI(24));
  gtk_color_button_set_title(GTK_COLOR_BUTTON(g->colorpick), _("select watermark color"));

  gtk_grid_attach(GTK_GRID(self->widget), label, 0, line++, 1, 1);
  gtk_grid_attach_next_to(GTK_GRID(self->widget), g->colorpick, label, GTK_POS_RIGHT, 2, 1);

  // Simple text
  label = gtk_label_new(_("text"));
  gtk_widget_set_halign(label, GTK_ALIGN_START);
  g->text = gtk_entry_new();
  gtk_entry_set_width_chars(GTK_ENTRY(g->text), 1);
  gtk_widget_set_tooltip_text(g->text, _("text string, tag:\n$(WATERMARK_TEXT)"));
  dt_gui_key_accel_block_on_focus_connect(g->text);
  gtk_grid_attach(GTK_GRID(self->widget), label, 0, line++, 1, 1);
  gtk_grid_attach_next_to(GTK_GRID(self->widget), g->text, label, GTK_POS_RIGHT, 2, 1);

  gchar *str = dt_conf_get_string("plugins/darkroom/watermark/text");
  gtk_entry_set_text(GTK_ENTRY(g->text), str);
  g_free(str);

  // Text font
  label = dtgtk_reset_label_new(_("font"), self, &p->font, sizeof(p->font));
  str = dt_conf_get_string("plugins/darkroom/watermark/font");
  g->fontsel = gtk_font_button_new_with_font(str==NULL?"DejaVu Sans 10":str);
  GList *childs = gtk_container_get_children(GTK_CONTAINER(gtk_bin_get_child(GTK_BIN(g->fontsel))));
  gtk_label_set_ellipsize(GTK_LABEL(childs->data), PANGO_ELLIPSIZE_MIDDLE);
  g_list_free(childs);
  gtk_widget_set_tooltip_text(g->fontsel, _("text font, tags:\n$(WATERMARK_FONT_FAMILY)\n"
                                            "$(WATERMARK_FONT_STYLE)\n$(WATERMARK_FONT_WEIGHT)"));
  gtk_font_button_set_show_size (GTK_FONT_BUTTON(g->fontsel), FALSE);
  g_free(str);
  gtk_grid_attach(GTK_GRID(self->widget), label, 0, line++, 1, 1);
  gtk_grid_attach_next_to(GTK_GRID(self->widget), g->fontsel, label, GTK_POS_RIGHT, 2, 1);

  gtk_grid_attach(GTK_GRID(self->widget), dt_ui_section_label_new(_("properties")), 0, line++, 3, 1);

  // Add opacity/scale sliders to table
  g->opacity = dt_bauhaus_slider_new_with_range(self, 0.0, 100.0, 1.0, p->opacity, 0);
  dt_bauhaus_slider_set_format(g->opacity, "%.f%%");
  dt_bauhaus_widget_set_label(g->opacity, NULL, _("opacity"));
  g->scale = dt_bauhaus_slider_new_with_range(self, 1.0, 100.0, 1.0, p->scale, 0);
  dt_bauhaus_slider_enable_soft_boundaries(g->scale, 1.0, 500.0);
  dt_bauhaus_slider_set_format(g->scale, "%.f%%");
  dt_bauhaus_widget_set_label(g->scale, NULL, _("scale"));
  g->rotate = dt_bauhaus_slider_new_with_range(self, -180.0, 180.0, 1.0, p->rotate, 2);
  dt_bauhaus_slider_set_format(g->rotate, "%.02f°");
  dt_bauhaus_widget_set_label(g->rotate, NULL, _("rotation"));
  gtk_grid_attach(GTK_GRID(self->widget), g->opacity, 0, line++, 3, 1);
  gtk_grid_attach(GTK_GRID(self->widget), g->scale, 0, line++, 3, 1);
  gtk_grid_attach(GTK_GRID(self->widget), g->rotate, 0, line++, 3, 1);

  g->sizeto = dt_bauhaus_combobox_new(self);
  dt_bauhaus_combobox_add(g->sizeto, C_("size", "image"));
  dt_bauhaus_combobox_add(g->sizeto, _("larger border"));
  dt_bauhaus_combobox_add(g->sizeto, _("smaller border"));
  dt_bauhaus_combobox_set(g->sizeto, p->sizeto);
  dt_bauhaus_widget_set_label(g->sizeto, NULL, _("scale on"));
  gtk_widget_set_tooltip_text(g->sizeto, _("size is relative to"));
  gtk_grid_attach(GTK_GRID(self->widget), g->sizeto, 0, line++, 3, 1);

  gtk_grid_attach(GTK_GRID(self->widget), dt_ui_section_label_new(_("position")), 0, line++, 3, 1);

  // Create the 3x3 gtk table toggle button table...
  label = dtgtk_reset_label_new(_("alignment"), self, &p->alignment, sizeof(p->alignment));
  GtkWidget *bat = gtk_grid_new();
  gtk_grid_set_row_spacing(GTK_GRID(bat), DT_PIXEL_APPLY_DPI(3));
  gtk_grid_set_column_spacing(GTK_GRID(bat), DT_PIXEL_APPLY_DPI(3));
  for(int i = 0; i < 9; i++)
  {
    g->align[i] = dtgtk_togglebutton_new(dtgtk_cairo_paint_alignment, CPF_STYLE_FLAT | (CPF_SPECIAL_FLAG << i));
    gtk_widget_set_size_request(GTK_WIDGET(g->align[i]), DT_PIXEL_APPLY_DPI(16), DT_PIXEL_APPLY_DPI(16));
    gtk_grid_attach(GTK_GRID(bat), GTK_WIDGET(g->align[i]), i%3, i/3, 1, 1);
    g_signal_connect(G_OBJECT(g->align[i]), "toggled", G_CALLBACK(alignment_callback), self);
  }
  gtk_grid_attach(GTK_GRID(self->widget), label, 0, line++, 1, 1);
  gtk_grid_attach_next_to(GTK_GRID(self->widget), bat, label, GTK_POS_RIGHT, 2, 1);

  // x/y offset
  g->x_offset = dt_bauhaus_slider_new_with_range(self, -1.0, 1.0, 0.001, p->xoffset, 3);
  dt_bauhaus_slider_set_format(g->x_offset, "%.3f");
  dt_bauhaus_widget_set_label(g->x_offset, NULL, _("x offset"));
  g->y_offset = dt_bauhaus_slider_new_with_range(self, -1.0, 1.0, 0.001, p->yoffset, 3);
  dt_bauhaus_slider_set_format(g->y_offset, "%.3f");
  dt_bauhaus_widget_set_label(g->y_offset, NULL, _("y offset"));
  gtk_grid_attach(GTK_GRID(self->widget), g->x_offset, 0, line++, 3, 1);
  gtk_grid_attach(GTK_GRID(self->widget), g->y_offset, 0, line++, 3, 1);

  // Let's add some tooltips and hook up some signals...
  gtk_widget_set_tooltip_text(g->opacity, _("the opacity of the watermark"));
  gtk_widget_set_tooltip_text(g->scale, _("the scale of the watermark"));
  gtk_widget_set_tooltip_text(g->rotate, _("the rotation of the watermark"));

  g_signal_connect(G_OBJECT(g->opacity), "value-changed", G_CALLBACK(opacity_callback), self);
  g_signal_connect(G_OBJECT(g->scale), "value-changed", G_CALLBACK(scale_callback), self);
  g_signal_connect(G_OBJECT(g->rotate), "value-changed", G_CALLBACK(rotate_callback), self);

  g_signal_connect(G_OBJECT(g->x_offset), "value-changed", G_CALLBACK(xoffset_callback), self);

  g_signal_connect(G_OBJECT(g->y_offset), "value-changed", G_CALLBACK(yoffset_callback), self);


  g_signal_connect(G_OBJECT(g->refresh), "clicked", G_CALLBACK(refresh_callback), self);

  refresh_watermarks(self);


  g_signal_connect(G_OBJECT(g->watermarks), "value-changed", G_CALLBACK(watermark_callback), self);
  g_signal_connect(G_OBJECT(g->sizeto), "value-changed", G_CALLBACK(sizeto_callback), self);

  g_signal_connect(G_OBJECT(g->text), "changed", G_CALLBACK(text_callback), self);
  g_signal_connect(G_OBJECT(g->colorpick), "color-set", G_CALLBACK(colorpick_color_set), self);
  g_signal_connect(G_OBJECT(g->fontsel), "font-set", G_CALLBACK(fontsel_callback), self);
}

void gui_cleanup(struct dt_iop_module_t *self)
{
  free(self->gui_data);
  self->gui_data = NULL;
}
示例#17
0
int dt_lua_init_configuration(lua_State *L)
{
  char tmp_path[PATH_MAX] = { 0 };

  dt_lua_push_darktable_lib(L);

  dt_lua_goto_subtable(L, "configuration");
  // build the table containing the configuration info

  lua_pushstring(L, "tmp_dir");
  dt_loc_get_tmp_dir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L, tmp_path);
  lua_settable(L, -3);

  lua_pushstring(L, "config_dir");
  dt_loc_get_user_config_dir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L, tmp_path);
  lua_settable(L, -3);

  lua_pushstring(L, "cache_dir");
  dt_loc_get_user_cache_dir(tmp_path, sizeof(tmp_path));
  lua_pushstring(L, tmp_path);
  lua_settable(L, -3);

  lua_pushstring(L, "version");
  lua_pushstring(L, darktable_package_version);
  lua_settable(L, -3);

  lua_pushstring(L, "verbose");
  lua_pushboolean(L, darktable.unmuted & DT_DEBUG_LUA);
  lua_settable(L, -3);

  lua_pushstring(L, "has_gui");
  lua_pushboolean(L, darktable.gui != NULL);
  lua_settable(L, -3);

  lua_pushstring(L, "api_version_major");
  lua_pushinteger(L, LUA_API_VERSION_MAJOR);
  lua_settable(L, -3);

  lua_pushstring(L, "api_version_minor");
  lua_pushinteger(L, LUA_API_VERSION_MINOR);
  lua_settable(L, -3);

  lua_pushstring(L, "api_version_patch");
  lua_pushinteger(L, LUA_API_VERSION_PATCH);
  lua_settable(L, -3);

  lua_pushstring(L, "api_version_suffix");
  lua_pushstring(L, LUA_API_VERSION_SUFFIX);
  lua_settable(L, -3);

  lua_pushstring(L, "api_version_string");
  if(LUA_API_VERSION_SUFFIX[0] == '\0')
  {
    lua_pushfstring(L, "%d.%d.%d", LUA_API_VERSION_MAJOR, LUA_API_VERSION_MINOR, LUA_API_VERSION_PATCH);
  }
  else
  {
    lua_pushfstring(L, "%d.%d.%d-%s", LUA_API_VERSION_MAJOR, LUA_API_VERSION_MINOR, LUA_API_VERSION_PATCH,
                    LUA_API_VERSION_SUFFIX);
  }
  lua_settable(L, -3);

  lua_pushstring(L, "check_version");
  lua_pushcfunction(L, check_version);
  lua_settable(L, -3);

  luaA_enum(L, lua_os_type);
  luaA_enum_value_name(L, lua_os_type, os_windows, "windows");
  luaA_enum_value_name(L, lua_os_type, os_macos, "macos");
  luaA_enum_value_name(L, lua_os_type, os_linux, "linux");
  luaA_enum_value_name(L, lua_os_type, os_unix, "unix");
  lua_pushstring(L, "running_os");
  luaA_push(L, lua_os_type, &cur_os);
  lua_settable(L, -3);

  lua_pop(L, 1); // remove the configuration table from the stack
  return 0;
}
示例#18
0
static gchar * _watermark_get_svgdoc( dt_iop_module_t *self, dt_iop_watermark_data_t *data, const dt_image_t *image)
{
  gsize length;

  gchar *svgdoc=NULL;
  gchar configdir[DT_MAX_PATH_LEN];
  gchar datadir[DT_MAX_PATH_LEN];
  gchar *filename;
  dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN);
  dt_loc_get_user_config_dir(configdir, DT_MAX_PATH_LEN);
  g_strlcat(datadir,"/watermarks/", DT_MAX_PATH_LEN);
  g_strlcat(configdir,"/watermarks/", DT_MAX_PATH_LEN);
  g_strlcat(datadir,data->filename, DT_MAX_PATH_LEN);
  g_strlcat(configdir,data->filename, DT_MAX_PATH_LEN);

  if (g_file_test(configdir,G_FILE_TEST_EXISTS))
    filename=configdir;
  else if (g_file_test(datadir,G_FILE_TEST_EXISTS))
    filename=datadir;
  else return NULL;

  gchar *svgdata=NULL;
  char datetime[200];

  // EXIF datetime
  struct tm tt_exif = {0};
  if(sscanf(image->exif_datetime_taken,"%d:%d:%d %d:%d:%d",
            &tt_exif.tm_year,
            &tt_exif.tm_mon,
            &tt_exif.tm_mday,
            &tt_exif.tm_hour,
            &tt_exif.tm_min,
            &tt_exif.tm_sec
           ) == 6
    )
  {
    tt_exif.tm_year-=1900;
    tt_exif.tm_mon--;
  }

  // Current datetime
  struct tm tt_cur = {0};
  time_t t = time(NULL);
  (void)localtime_r(&t, &tt_cur);

  if( g_file_get_contents( filename, &svgdata, &length, NULL) )
  {
    // File is loaded lets substitute strings if found...

    // Darktable internal
    svgdoc = _string_substitute(svgdata,"$(DARKTABLE.NAME)",PACKAGE_NAME);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    svgdoc = _string_substitute(svgdata,"$(DARKTABLE.VERSION)",PACKAGE_VERSION);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Current image ID
    gchar buffer[1024];
    g_snprintf(buffer,1024,"%d",image->id);
    svgdoc = _string_substitute(svgdata,"$(IMAGE.ID)",buffer);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Current image
    dt_image_print_exif(image,buffer,1024);
    svgdoc = _string_substitute(svgdata,"$(IMAGE.EXIF)",buffer);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Image exif
    // EXIF date
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE)",image->exif_datetime_taken);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.SECOND) -- 00..60
    strftime(datetime, sizeof(datetime), "%S", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.SECOND)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.MINUTE) -- 00..59
    strftime(datetime, sizeof(datetime), "%M", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.MINUTE)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.HOUR) -- 00..23
    strftime(datetime, sizeof(datetime), "%H", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.HOUR)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.HOUR_AMPM) -- 01..12
    strftime(datetime, sizeof(datetime), "%I %p", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.HOUR_AMPM)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.DAY) -- 01..31
    strftime(datetime, sizeof(datetime), "%d", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.DAY)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.MONTH) -- 01..12
    strftime(datetime, sizeof(datetime), "%m", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.MONTH)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized
    strftime(datetime, sizeof(datetime), "%b", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.SHORT_MONTH)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.LONG_MONTH) -- January, February, .., December, localized
    strftime(datetime, sizeof(datetime), "%B", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.LONG_MONTH)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.SHORT_YEAR) -- 12
    strftime(datetime, sizeof(datetime), "%y", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.SHORT_YEAR)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(EXIF.DATE.LONG_YEAR) -- 2012
    strftime(datetime, sizeof(datetime), "%Y", &tt_exif);
    svgdoc = _string_substitute(svgdata,"$(EXIF.DATE.LONG_YEAR)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // Current date
    // $(DATE) -- YYYY:
    dt_gettime_t(datetime, t);
    svgdoc = _string_substitute(svgdata,"$(DATE)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.SECOND) -- 00..60
    strftime(datetime, sizeof(datetime), "%S", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.SECOND)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.MINUTE) -- 00..59
    strftime(datetime, sizeof(datetime), "%M", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.MINUTE)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.HOUR) -- 00..23
    strftime(datetime, sizeof(datetime), "%H", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.HOUR)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.HOUR_AMPM) -- 01..12
    strftime(datetime, sizeof(datetime), "%I %p", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.HOUR_AMPM)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.DAY) -- 01..31
    strftime(datetime, sizeof(datetime), "%d", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.DAY)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.MONTH) -- 01..12
    strftime(datetime, sizeof(datetime), "%m", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.MONTH)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.SHORT_MONTH) -- Jan, Feb, .., Dec, localized
    strftime(datetime, sizeof(datetime), "%b", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.SHORT_MONTH)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.LONG_MONTH) -- January, February, .., December, localized
    strftime(datetime, sizeof(datetime), "%B", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.LONG_MONTH)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.SHORT_YEAR) -- 12
    strftime(datetime, sizeof(datetime), "%y", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.SHORT_YEAR)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    // $(DATE.LONG_YEAR) -- 2012
    strftime(datetime, sizeof(datetime), "%Y", &tt_cur);
    svgdoc = _string_substitute(svgdata,"$(DATE.LONG_YEAR)",datetime);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    svgdoc = _string_substitute(svgdata,"$(EXIF.MAKER)",image->exif_maker);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    svgdoc = _string_substitute(svgdata,"$(EXIF.MODEL)",image->exif_model);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    svgdoc = _string_substitute(svgdata,"$(EXIF.LENS)",image->exif_lens);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    svgdoc = _string_substitute(svgdata,"$(IMAGE.FILENAME)",image->filename);
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }

    // TODO: auto generate that code?
    GList * res;
    res = dt_metadata_get(image->id, "Xmp.dc.creator", NULL);
    svgdoc = _string_substitute(svgdata,"$(Xmp.dc.creator)",(res?res->data:""));
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if( res )
    {
      g_free(res->data);
      g_list_free(res);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.publisher", NULL);
    svgdoc = _string_substitute(svgdata,"$(Xmp.dc.publisher)",(res?res->data:""));
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if( res )
    {
      g_free(res->data);
      g_list_free(res);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.title", NULL);
    svgdoc = _string_substitute(svgdata,"$(Xmp.dc.title)",(res?res->data:""));
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if( res )
    {
      g_free(res->data);
      g_list_free(res);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.description", NULL);
    svgdoc = _string_substitute(svgdata,"$(Xmp.dc.description)",(res?res->data:""));
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if( res )
    {
      g_free(res->data);
      g_list_free(res);
    }

    res = dt_metadata_get(image->id, "Xmp.dc.rights", NULL);
    svgdoc = _string_substitute(svgdata,"$(Xmp.dc.rights)",(res?res->data:""));
    if( svgdoc != svgdata )
    {
      g_free(svgdata);
      svgdata = svgdoc;
    }
    if( res )
    {
      g_free(res->data);
      g_list_free(res);
    }

  }
  return svgdoc;
}
示例#19
0
void
dt_styles_update (const char *name, const char *newname, const char *newdescription, GList *filter, int imgid, GList *update)
{
  sqlite3_stmt *stmt;
  int id=0;
  gchar *desc = NULL;

  id = dt_styles_get_id_by_name(name);
  if(id == 0) return;

  desc = dt_styles_get_description (name);

  if ((g_strcmp0(name, newname)) || (g_strcmp0(desc, newdescription)))
  {
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "UPDATE styles SET name=?1, description=?2 WHERE id=?3", -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, newname, strlen (newname), SQLITE_STATIC);
    DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, newdescription, strlen (newdescription), SQLITE_STATIC);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, id);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
  }

  if (filter)
  {
    GList *list=filter;
    char tmp[64];
    char include[2048] = {0};
    g_strlcat(include,"num not in (", 2048);
    do
    {
      if(list!=g_list_first(list))
        g_strlcat(include, ",", 2048);
      sprintf(tmp, "%d", GPOINTER_TO_INT(list->data));
      g_strlcat(include, tmp, 2048);
    }
    while ((list=g_list_next(list)));
    g_strlcat(include,")", 2048);

    char query[4096]= {0};
    sprintf(query,"delete from style_items where styleid=?1 and %s", include);
    DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);
  }

  _dt_style_update_from_image(id,imgid,filter,update);

  _dt_style_cleanup_multi_instance(id);

  /* backup style to disk */
  char stylesdir[1024];
  dt_loc_get_user_config_dir(stylesdir, 1024);
  g_strlcat(stylesdir,"/styles",1024);
  g_mkdir_with_parents(stylesdir,00755);

  dt_styles_save_to_file(newname,stylesdir,TRUE);

  /* delete old accelerator and create a new one */
  //TODO: should better use dt_accel_rename_global() to keep the old accel_key untouched, but it seems to be buggy
  if (g_strcmp0(name, newname))
  {
    char tmp_accel[1024];
    snprintf(tmp_accel, 1024, C_("accel", "styles/apply %s"), name);
    dt_accel_deregister_global(tmp_accel);

    gchar* tmp_name = g_strdup(newname); // freed by _destroy_style_shortcut_callback
    snprintf(tmp_accel, 1024, C_("accel", "styles/apply %s"), newname);
    dt_accel_register_global( tmp_accel, 0, 0);
    GClosure *closure;
    closure = g_cclosure_new(
                G_CALLBACK(_apply_style_shortcut_callback),
                tmp_name, _destroy_style_shortcut_callback);
    dt_accel_connect_global(tmp_accel, closure);
  }

  g_free(desc);
}
示例#20
0
void dt_styles_create_from_style(const char *name, const char *newname, const char *description,
                                 GList *filter, int imgid, GList *update)
{
    sqlite3_stmt *stmt;
    int id = 0;
    int oldid = 0;

    oldid = dt_styles_get_id_by_name(name);
    if(oldid == 0) return;

    /* create the style header */
    if(!dt_styles_create_style_header(newname, description)) return;

    if((id = dt_styles_get_id_by_name(newname)) != 0)
    {
        if(filter)
        {
            GList *list = filter;
            char tmp[64];
            char include[2048] = { 0 };
            g_strlcat(include, "num IN (", sizeof(include));
            do
            {
                if(list != g_list_first(list)) g_strlcat(include, ",", sizeof(include));
                snprintf(tmp, sizeof(tmp), "%d", GPOINTER_TO_INT(list->data));
                g_strlcat(include, tmp, sizeof(include));
            } while((list = g_list_next(list)));
            g_strlcat(include, ")", sizeof(include));
            char query[4096] = { 0 };

            snprintf(query, sizeof(query), "INSERT INTO data.style_items "
                     "(styleid,num,module,operation,op_params,enabled,blendop_params,blendop_"
                     "version,multi_priority,multi_name) SELECT ?1, "
                     "num,module,operation,op_params,enabled,blendop_params,blendop_version,"
                     "multi_priority,multi_name FROM data.style_items WHERE styleid=?2 AND %s",
                     include);
            DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
        }
        else
            DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                        "INSERT INTO data.style_items "
                                        "(styleid,num,module,operation,op_params,enabled,blendop_params,blendop_"
                                        "version,multi_priority,multi_name) SELECT ?1, "
                                        "num,module,operation,op_params,enabled,blendop_params,blendop_version,"
                                        "multi_priority,multi_name FROM data.style_items WHERE styleid=?2",
                                        -1, &stmt, NULL);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
        DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, oldid);
        sqlite3_step(stmt);
        sqlite3_finalize(stmt);

        /* insert items from imgid if defined */

        _dt_style_update_from_image(id, imgid, filter, update);

        _dt_style_cleanup_multi_instance(id);

        /* backup style to disk */
        char stylesdir[PATH_MAX] = { 0 };
        dt_loc_get_user_config_dir(stylesdir, sizeof(stylesdir));
        g_strlcat(stylesdir, "/styles", sizeof(stylesdir));
        g_mkdir_with_parents(stylesdir, 00755);

        dt_styles_save_to_file(newname, stylesdir, FALSE);

        char tmp_accel[1024];
        gchar *tmp_name = g_strdup(newname); // freed by _destroy_style_shortcut_callback
        snprintf(tmp_accel, sizeof(tmp_accel), C_("accel", "styles/apply %s"), newname);
        dt_accel_register_global(tmp_accel, 0, 0);
        GClosure *closure;
        closure = g_cclosure_new(G_CALLBACK(_apply_style_shortcut_callback), tmp_name,
                                 _destroy_style_shortcut_callback);
        dt_accel_connect_global(tmp_accel, closure);
        dt_control_log(_("style named '%s' successfully created"), newname);
        dt_control_signal_raise(darktable.signals, DT_SIGNAL_STYLE_CHANGED);
    }
}
示例#21
0
int dt_init(int argc, char *argv[], const int init_gui,lua_State *L)
{
#ifndef __WIN32__
  if(getuid() == 0 || geteuid() == 0)
    printf("WARNING: either your user id or the effective user id are 0. are you running darktable as root?\n");
#endif

  // make everything go a lot faster.
  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
#if !defined __APPLE__ && !defined __WIN32__
  _dt_sigsegv_old_handler = signal(SIGSEGV,&_dt_sigsegv_handler);
#endif

#ifndef __GNUC_PREREQ
  // on OSX, gcc-4.6 and clang chokes if this is not here.
  #if defined __GNUC__ && defined __GNUC_MINOR__
  # define __GNUC_PREREQ(maj, min) \
  ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
  #else
  # define __GNUC_PREREQ(maj, min) 0
  #endif
#endif
#ifndef __has_builtin
// http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
  #define __has_builtin(x) false
#endif

#ifndef __SSE3__
  #error "Unfortunately we depend on SSE3 instructions at this time."
  #error "Please contribute a backport patch (or buy a newer processor)."
#else
  #if (__GNUC_PREREQ(4,8) || __has_builtin(__builtin_cpu_supports))
  //FIXME: check will work only in GCC 4.8+ !!! implement manual cpuid check !!!
  //NOTE: _may_i_use_cpu_feature() looks better, but only avaliable in ICC
  if (!__builtin_cpu_supports("sse3"))
  {
    fprintf(stderr, "[dt_init] unfortunately we depend on SSE3 instructions at this time.\n");
    fprintf(stderr, "[dt_init] please contribute a backport patch (or buy a newer processor).\n");
    return 1;
  }
  #else
  //FIXME: no way to check for SSE3 in runtime, implement manual cpuid check !!!
  #endif
#endif

#ifdef M_MMAP_THRESHOLD
  mallopt(M_MMAP_THRESHOLD,128*1024) ; /* use mmap() for large allocations */
#endif

  // we have to have our share dir in XDG_DATA_DIRS,
  // otherwise GTK+ won't find our logo for the about screen (and maybe other things)
  {
    const gchar *xdg_data_dirs = g_getenv("XDG_DATA_DIRS");
    gchar *new_xdg_data_dirs = NULL;
    gboolean set_env = TRUE;
    if(xdg_data_dirs != NULL && *xdg_data_dirs != '\0')
    {
      // check if DARKTABLE_SHAREDIR is already in there
      gboolean found = FALSE;
      gchar **tokens = g_strsplit(xdg_data_dirs, ":", 0);
      // xdg_data_dirs is neither NULL nor empty => tokens != NULL
      for(char **iter = tokens; *iter != NULL; iter++)
        if(!strcmp(DARKTABLE_SHAREDIR, *iter))
        {
          found = TRUE;
          break;
        }
      g_strfreev(tokens);
      if(found)
        set_env = FALSE;
      else
        new_xdg_data_dirs = g_strjoin(":", DARKTABLE_SHAREDIR, xdg_data_dirs, NULL);
    }
    else
    {
      // see http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html for a reason to use those as a default
      if(!g_strcmp0(DARKTABLE_SHAREDIR, "/usr/local/share") || !g_strcmp0(DARKTABLE_SHAREDIR, "/usr/local/share/") ||
         !g_strcmp0(DARKTABLE_SHAREDIR, "/usr/share") || !g_strcmp0(DARKTABLE_SHAREDIR, "/usr/share/"))
        new_xdg_data_dirs = g_strdup("/usr/local/share/:/usr/share/");
      else
        new_xdg_data_dirs = g_strdup_printf("%s:/usr/local/share/:/usr/share/", DARKTABLE_SHAREDIR);
    }

    if(set_env)
      g_setenv("XDG_DATA_DIRS", new_xdg_data_dirs, 1);
    g_free(new_xdg_data_dirs);
  }

  setlocale(LC_ALL, "");
  bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);


  // init all pointers to 0:
  memset(&darktable, 0, sizeof(darktable_t));

  darktable.progname = argv[0];

  // database
  gchar *dbfilename_from_command = NULL;
  char *datadir_from_command = NULL;
  char *moduledir_from_command = NULL;
  char *tmpdir_from_command = NULL;
  char *configdir_from_command = NULL;
  char *cachedir_from_command = NULL;

#ifdef USE_LUA
  char *lua_command = NULL;
#endif

  darktable.num_openmp_threads = 1;
#ifdef _OPENMP
  darktable.num_openmp_threads = omp_get_num_procs();
#endif
  darktable.unmuted = 0;
  GSList *images_to_load = NULL, *config_override = NULL;
  for(int k=1; k<argc; k++)
  {
    if(argv[k][0] == '-')
    {
      if(!strcmp(argv[k], "--help"))
      {
        return usage(argv[0]);
      }
      if(!strcmp(argv[k], "-h"))
      {
        return usage(argv[0]);
      }
      else if(!strcmp(argv[k], "--version"))
      {
        printf("this is "PACKAGE_STRING"\ncopyright (c) 2009-2014 johannes hanika\n"PACKAGE_BUGREPORT"\n"
#ifdef _OPENMP
        "OpenMP support enabled\n"
#else
        "OpenMP support disabled\n"
#endif
        );
        return 1;
      }
      else if(!strcmp(argv[k], "--library"))
      {
        dbfilename_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--datadir"))
      {
        datadir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--moduledir"))
      {
        moduledir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--tmpdir"))
      {
        tmpdir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--configdir"))
      {
        configdir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--cachedir"))
      {
        cachedir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--localedir"))
      {
        bindtextdomain (GETTEXT_PACKAGE, argv[++k]);
      }
      else if(argv[k][1] == 'd' && argc > k+1)
      {
        if(!strcmp(argv[k+1], "all"))             darktable.unmuted = 0xffffffff;   // enable all debug information
        else if(!strcmp(argv[k+1], "cache"))      darktable.unmuted |= DT_DEBUG_CACHE;   // enable debugging for lib/film/cache module
        else if(!strcmp(argv[k+1], "control"))    darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
        else if(!strcmp(argv[k+1], "dev"))        darktable.unmuted |= DT_DEBUG_DEV; // develop module
        else if(!strcmp(argv[k+1], "fswatch"))    darktable.unmuted |= DT_DEBUG_FSWATCH; // fswatch module
        else if(!strcmp(argv[k+1], "input"))      darktable.unmuted |= DT_DEBUG_INPUT; // input devices
        else if(!strcmp(argv[k+1], "camctl"))     darktable.unmuted |= DT_DEBUG_CAMCTL; // camera control module
        else if(!strcmp(argv[k+1], "perf"))       darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
        else if(!strcmp(argv[k+1], "pwstorage"))  darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
        else if(!strcmp(argv[k+1], "opencl"))     darktable.unmuted |= DT_DEBUG_OPENCL;    // gpu accel via opencl
        else if(!strcmp(argv[k+1], "sql"))        darktable.unmuted |= DT_DEBUG_SQL; // SQLite3 queries
        else if(!strcmp(argv[k+1], "memory"))     darktable.unmuted |= DT_DEBUG_MEMORY; // some stats on mem usage now and then.
        else if(!strcmp(argv[k+1], "lighttable")) darktable.unmuted |= DT_DEBUG_LIGHTTABLE; // lighttable related stuff.
        else if(!strcmp(argv[k+1], "nan"))        darktable.unmuted |= DT_DEBUG_NAN; // check for NANs when processing the pipe.
        else if(!strcmp(argv[k+1], "masks"))      darktable.unmuted |= DT_DEBUG_MASKS; // masks related stuff.
        else if(!strcmp(argv[k+1], "lua"))        darktable.unmuted |= DT_DEBUG_LUA; // lua errors are reported on console
        else return usage(argv[0]);
        k ++;
      }
      else if(argv[k][1] == 't' && argc > k+1)
      {
        darktable.num_openmp_threads = CLAMP(atol(argv[k+1]), 1, 100);
        printf("[dt_init] using %d threads for openmp parallel sections\n", darktable.num_openmp_threads);
        k ++;
      }
      else if(!strcmp(argv[k], "--conf"))
      {
        gchar *keyval = g_strdup(argv[++k]), *c = keyval;
        gchar *end = keyval + strlen(keyval);
        while(*c != '=' && c < end) c++;
        if(*c == '=' && *(c+1) != '\0')
        {
          *c++ = '\0';
          dt_conf_string_entry_t *entry = (dt_conf_string_entry_t*)g_malloc(sizeof(dt_conf_string_entry_t));
          entry->key = g_strdup(keyval);
          entry->value = g_strdup(c);
          config_override = g_slist_append(config_override, entry);
        }
        g_free(keyval);
      }
      else if(!strcmp(argv[k], "--luacmd"))
      {
#ifdef USE_LUA
        lua_command = argv[++k];
#else
        ++k;
#endif
      }
    }
#ifndef MAC_INTEGRATION
    else
    {
      images_to_load = g_slist_append(images_to_load, argv[k]);
    }
#endif
  }

  if(darktable.unmuted & DT_DEBUG_MEMORY)
  {
    fprintf(stderr, "[memory] at startup\n");
    dt_print_mem_usage();
  }

#ifdef _OPENMP
  omp_set_num_threads(darktable.num_openmp_threads);
#endif
  dt_loc_init_datadir(datadir_from_command);
  dt_loc_init_plugindir(moduledir_from_command);
  if(dt_loc_init_tmp_dir(tmpdir_from_command))
  {
    printf(_("ERROR : invalid temporary directory : %s\n"),darktable.tmpdir);
    return usage(argv[0]);
  }
  dt_loc_init_user_config_dir(configdir_from_command);
  dt_loc_init_user_cache_dir(cachedir_from_command);

#if !GLIB_CHECK_VERSION(2, 35, 0)
  g_type_init();
#endif

  // does not work, as gtk is not inited yet.
  // even if it were, it's a super bad idea to invoke gtk stuff from
  // a signal handler.
  /* check cput caps */
  // dt_check_cpu(argc,argv);

#ifdef HAVE_GEGL
  char geglpath[PATH_MAX];
  char datadir[PATH_MAX];
  dt_loc_get_datadir(datadir, sizeof(datadir));
  snprintf(geglpath, sizeof(geglpath), "%s/gegl:/usr/lib/gegl-0.0", datadir);
  (void)setenv("GEGL_PATH", geglpath, 1);
  gegl_init(&argc, &argv);
#endif
#ifdef USE_LUA
  dt_lua_init_early(L);
#endif

  // thread-safe init:
  dt_exif_init();
  char datadir[PATH_MAX];
  dt_loc_get_user_config_dir (datadir, sizeof(datadir));
  char filename[PATH_MAX];
  snprintf(filename, sizeof(filename), "%s/darktablerc", datadir);

  // initialize the config backend. this needs to be done first...
  darktable.conf = (dt_conf_t *)calloc(1, sizeof(dt_conf_t));
  dt_conf_init(darktable.conf, filename, config_override);
  g_slist_free_full(config_override, g_free);

  // set the interface language
  const gchar* lang = dt_conf_get_string("ui_last/gui_language"); // we may not g_free 'lang' since it is owned by setlocale afterwards
  if(lang != NULL && lang[0] != '\0')
  {
    if(setlocale(LC_ALL, lang) != NULL)
      gtk_disable_setlocale();
  }

  // initialize the database
  darktable.db = dt_database_init(dbfilename_from_command);
  if(darktable.db == NULL)
  {
    printf("ERROR : cannot open database\n");
    return 1;
  }
  else if(!dt_database_get_lock_acquired(darktable.db))
  {
    // send the images to the other instance via dbus
    if(images_to_load)
    {
      GSList *p = images_to_load;

      // get a connection!
      GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SESSION,NULL, NULL);

      while (p != NULL)
      {
        // make the filename absolute ...
        gchar *filename = dt_make_path_absolute((gchar*)p->data);
        if(filename == NULL) continue;
        // ... and send it to the running instance of darktable
        g_dbus_connection_call_sync(connection,
                                    "org.darktable.service",
                                    "/darktable",
                                    "org.darktable.service.Remote",
                                    "Open",
                                    g_variant_new ("(s)", filename),
                                    NULL,
                                    G_DBUS_CALL_FLAGS_NONE,
                                    -1,
                                    NULL,
                                    NULL);
        p = g_slist_next(p);
        g_free(filename);
      }

      g_slist_free(images_to_load);
      g_object_unref(connection);
    }

    return 1;
  }

  // Initialize the signal system
  darktable.signals = dt_control_signal_init();

  // Make sure that the database and xmp files are in sync before starting the fswatch.
  // We need conf and db to be up and running for that which is the case here.
  // FIXME: is this also useful in non-gui mode?
  GList *changed_xmp_files = NULL;
  if(init_gui && dt_conf_get_bool("run_crawler_on_start"))
  {
    changed_xmp_files = dt_control_crawler_run();
  }

  // Initialize the filesystem watcher
  darktable.fswatch=dt_fswatch_new();

#ifdef HAVE_GPHOTO2
  // Initialize the camera control
  darktable.camctl=dt_camctl_new();
#endif

  // get max lighttable thumbnail size:
  darktable.thumbnail_width  = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_width"),  200, 3000);
  darktable.thumbnail_height = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_height"), 200, 3000);
  // and make sure it can be mip-mapped all the way from mip4 to mip0
  darktable.thumbnail_width  /= 16;
  darktable.thumbnail_width  *= 16;
  darktable.thumbnail_height /= 16;
  darktable.thumbnail_height *= 16;

  // Initialize the password storage engine
  darktable.pwstorage=dt_pwstorage_new();

  // FIXME: move there into dt_database_t
  dt_pthread_mutex_init(&(darktable.db_insert), NULL);
  dt_pthread_mutex_init(&(darktable.plugin_threadsafe), NULL);
  dt_pthread_mutex_init(&(darktable.capabilities_threadsafe), NULL);
  darktable.control = (dt_control_t *)calloc(1, sizeof(dt_control_t));
  if(init_gui)
  {
    dt_control_init(darktable.control);
  }
  else
  {
    if(dbfilename_from_command && !strcmp(dbfilename_from_command, ":memory:"))
      dt_gui_presets_init(); // init preset db schema.
    darktable.control->running = 0;
    darktable.control->accelerators = NULL;
    dt_pthread_mutex_init(&darktable.control->run_mutex, NULL);
  }

  // initialize collection query
  darktable.collection_listeners = NULL;
  darktable.collection = dt_collection_new(NULL);

  /* initialize selection */
  darktable.selection = dt_selection_new();

  /* capabilities set to NULL */
  darktable.capabilities = NULL;

#ifdef HAVE_GRAPHICSMAGICK
  /* GraphicsMagick init */
  InitializeMagick(darktable.progname);
#endif

  darktable.opencl = (dt_opencl_t *)calloc(1, sizeof(dt_opencl_t));
#ifdef HAVE_OPENCL
  dt_opencl_init(darktable.opencl, argc, argv);
#endif

  darktable.blendop = (dt_blendop_t *)calloc(1, sizeof(dt_blendop_t));
  dt_develop_blend_init(darktable.blendop);

  darktable.points = (dt_points_t *)calloc(1, sizeof(dt_points_t));
  dt_points_init(darktable.points, dt_get_num_threads());

  // must come before mipmap_cache, because that one will need to access
  // image dimensions stored in here:
  darktable.image_cache = (dt_image_cache_t *)calloc(1, sizeof(dt_image_cache_t));
  dt_image_cache_init(darktable.image_cache);

  darktable.mipmap_cache = (dt_mipmap_cache_t *)calloc(1, sizeof(dt_mipmap_cache_t));
  dt_mipmap_cache_init(darktable.mipmap_cache);

  // The GUI must be initialized before the views, because the init()
  // functions of the views depend on darktable.control->accels_* to register
  // their keyboard accelerators

  if(init_gui)
  {
    darktable.gui = (dt_gui_gtk_t *)calloc(1, sizeof(dt_gui_gtk_t));
    if(dt_gui_gtk_init(darktable.gui, argc, argv)) return 1;
    dt_bauhaus_init();
  }
  else darktable.gui = NULL;

  darktable.view_manager = (dt_view_manager_t *)calloc(1, sizeof(dt_view_manager_t));
  dt_view_manager_init(darktable.view_manager);

  darktable.imageio = (dt_imageio_t *)calloc(1, sizeof(dt_imageio_t));
  dt_imageio_init(darktable.imageio);

  // load the darkroom mode plugins once:
  dt_iop_load_modules_so();

  if(init_gui)
  {
    darktable.lib = (dt_lib_t *)calloc(1, sizeof(dt_lib_t));
    dt_lib_init(darktable.lib);

    dt_control_load_config(darktable.control);
  }

  if(init_gui)
  {
    // Loading the keybindings
    char keyfile[PATH_MAX];

    // First dump the default keymapping
    snprintf(keyfile, sizeof(keyfile), "%s/keyboardrc_default", datadir);
    gtk_accel_map_save(keyfile);

    // Removing extraneous semi-colons from the default keymap
    strip_semicolons_from_keymap(keyfile);

    // Then load any modified keys if available
    snprintf(keyfile, sizeof(keyfile), "%s/keyboardrc", datadir);
    if(g_file_test(keyfile, G_FILE_TEST_EXISTS))
      gtk_accel_map_load(keyfile);
    else
      gtk_accel_map_save(keyfile); // Save the default keymap if none is present

    // I doubt that connecting to dbus for darktable-cli makes sense
    darktable.dbus = dt_dbus_init();

    // initialize undo struct
    darktable.undo = dt_undo_init();

    // load image(s) specified on cmdline
    int id = 0;
    if(images_to_load)
    {
      // If only one image is listed, attempt to load it in darkroom
      gboolean load_in_dr = (g_slist_next(images_to_load) == NULL);
      GSList *p = images_to_load;

      while (p != NULL)
      {
        // don't put these function calls into MAX(), the macro will evaluate
        // it twice (and happily deadlock, in this particular case)
        int newid = dt_load_from_string((gchar*)p->data, load_in_dr);
        id = MAX(id, newid);
        p = g_slist_next(p);
      }

      if (!load_in_dr || id == 0)
        dt_ctl_switch_mode_to(DT_LIBRARY);

      g_slist_free(images_to_load);
    }
    else
      dt_ctl_switch_mode_to(DT_LIBRARY);
  }

  if(darktable.unmuted & DT_DEBUG_MEMORY)
  {
    fprintf(stderr, "[memory] after successful startup\n");
    dt_print_mem_usage();
  }

  dt_image_local_copy_synch();

  /* init lua last, since it's user made stuff it must be in the real environment */
#ifdef USE_LUA
  dt_lua_init(darktable.lua_state.state,lua_command);
#endif

  // last but not least construct the popup that asks the user about images whose xmp files are newer than the db entry
  if(init_gui && changed_xmp_files)
  {
    dt_control_crawler_show_image_list(changed_xmp_files);
  }

  return 0;
}
示例#22
0
dt_database_t *dt_database_init(char *alternative)
{
  /* migrate default database location to new default */
  _database_migrate_to_xdg_structure();

  /* delete old mipmaps files */
  _database_delete_mipmaps_files();

  /* lets construct the db filename  */
  gchar * dbname = NULL;
  gchar dbfilename[DT_MAX_PATH_LEN] = {0};
  gchar datadir[DT_MAX_PATH_LEN] = {0};

  dt_loc_get_user_config_dir(datadir, DT_MAX_PATH_LEN);

  if ( alternative == NULL )
  {
    dbname = dt_conf_get_string ("database");
    if(!dbname)               snprintf(dbfilename, DT_MAX_PATH_LEN, "%s/library.db", datadir);
    else if(dbname[0] != '/') snprintf(dbfilename, DT_MAX_PATH_LEN, "%s/%s", datadir, dbname);
    else                      snprintf(dbfilename, DT_MAX_PATH_LEN, "%s", dbname);
  }
  else
  {
    snprintf(dbfilename, DT_MAX_PATH_LEN, "%s", alternative);

    GFile *galternative = g_file_new_for_path(alternative);
    dbname = g_file_get_basename (galternative);
    g_object_unref(galternative);
  }

  /* create database */
  dt_database_t *db = (dt_database_t *)g_malloc(sizeof(dt_database_t));
  memset(db,0,sizeof(dt_database_t));
  db->dbfilename = g_strdup(dbfilename);
  db->is_new_database = FALSE;
  db->lock_acquired = FALSE;

  /* having more than one instance of darktable using the same database is a bad idea */
  /* try to get a lock for the database */
#ifdef __WIN32__
  db->lock_acquired = TRUE;
#else
  mode_t old_mode;
  int fd, lock_tries = 0;
  if(!strcmp(dbfilename, ":memory:"))
  {
    db->lock_acquired = TRUE;
  }
  else
  {
    db->lockfile = g_strconcat(dbfilename, ".lock", NULL);
lock_again:
    lock_tries++;
    old_mode = umask(0);
    fd = open(db->lockfile, O_RDWR | O_CREAT | O_EXCL, 0666);
    umask(old_mode);

    if(fd >= 0) // the lockfile was successfully created - write our PID into it
    {
      gchar *pid = g_strdup_printf("%d", getpid());
      if(write(fd, pid, strlen(pid)+1) > -1)
        db->lock_acquired = TRUE;
      close(fd);
    }
    else // the lockfile already exists - see if it's a stale one left over from a crashed instance
    {
      char buf[64];
      memset(buf, 0, sizeof(buf));
      fd = open(db->lockfile, O_RDWR | O_CREAT, 0666);
      if(fd >= 0)
      {
        if(read(fd, buf, sizeof(buf) - 1) > -1)
        {
          int other_pid = atoi(buf);
          if((kill(other_pid, 0) == -1) && errno == ESRCH)
          {
            // the other process seems to no longer exist. unlink the .lock file and try again
            unlink(db->lockfile);
            if(lock_tries < 5)
              goto lock_again;
          }
        }
        close(fd);
      }
    }
  }
#endif

  if(!db->lock_acquired)
  {
    fprintf(stderr, "[init] database is locked, probably another process is already using it\n");
    g_free(dbname);
    return db;
  }

  /* test if databasefile is available */
  if(!g_file_test(dbfilename, G_FILE_TEST_IS_REGULAR))
    db->is_new_database = TRUE;

  /* opening / creating database */
  if(sqlite3_open(db->dbfilename, &db->handle))
  {
    fprintf(stderr, "[init] could not find database ");
    if(dbname) fprintf(stderr, "`%s'!\n", dbname);
    else       fprintf(stderr, "\n");
    fprintf(stderr, "[init] maybe your %s/darktablerc is corrupt?\n",datadir);
    dt_loc_get_datadir(dbfilename, 512);
    fprintf(stderr, "[init] try `cp %s/darktablerc %s/darktablerc'\n", dbfilename,datadir);
    sqlite3_close(db->handle);
    g_free(dbname);
    g_free(db->lockfile);
    g_free(db);
    return NULL;
  }

  /* attach a memory database to db connection for use with temporary tables
     used during instance life time, which is discarded on exit.
  */
  sqlite3_exec(db->handle, "attach database ':memory:' as memory",NULL,NULL,NULL);

  sqlite3_exec(db->handle, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
  sqlite3_exec(db->handle, "PRAGMA journal_mode = MEMORY", NULL, NULL, NULL);
  sqlite3_exec(db->handle, "PRAGMA page_size = 32768", NULL, NULL, NULL);

  /* now that we got a functional database that is locked for us we can make sure that the schema is set up */
  // does the db contain the new 'db_info' table?
  sqlite3_stmt *stmt;
  int rc = sqlite3_prepare_v2(db->handle, "select value from db_info where key = 'version'", -1, &stmt, NULL);
  if(rc == SQLITE_OK && sqlite3_step(stmt) == SQLITE_ROW)
  {
    // compare the version of the db with what is current for this executable
    const int db_version = sqlite3_column_int(stmt, 0);
    sqlite3_finalize(stmt);
    if(db_version < CURRENT_DATABASE_VERSION)
    {
      // older: upgrade
      if(!_upgrade_schema(db, db_version))
      {
        // we couldn't upgrade the db for some reason. bail out.
        fprintf(stderr, "[init] database `%s' couldn't be upgraded from version %d to %d. aborting\n", dbname, db_version, CURRENT_DATABASE_VERSION);
        dt_database_destroy(db);
        db = NULL;
        goto error;
      }
    }
    else if(db_version > CURRENT_DATABASE_VERSION)
    {
      // newer: bail out. it's better than what we did before: delete everything
      fprintf(stderr, "[init] database version of `%s' is too new for this build of darktable. aborting\n", dbname);
      dt_database_destroy(db);
      db = NULL;
      goto error;
    }
    // else: the current version, do nothing
  }
  else
  {
    // does it contain the legacy 'settings' table?
    sqlite3_finalize(stmt);
    rc = sqlite3_prepare_v2(db->handle, "select settings from settings", -1, &stmt, NULL);
    if(rc == SQLITE_OK && sqlite3_step(stmt) == SQLITE_ROW)
    {
      // the old blob had the version as an int in the first place
      const void *set = sqlite3_column_blob(stmt, 0);
      const int db_version = *(int*)set;
      sqlite3_finalize(stmt);
      if(!_migrate_schema(db, db_version))    // bring the legacy layout to the first one known to our upgrade path ...
      {
        // we couldn't migrate the db for some reason. bail out.
        fprintf(stderr, "[init] database `%s' couldn't be migrated from the legacy version %d. aborting\n", dbname, db_version);
        dt_database_destroy(db);
        db = NULL;
        goto error;
      }
      if(!_upgrade_schema(db, 1))             // ... and upgrade it
      {
        // we couldn't upgrade the db for some reason. bail out.
        fprintf(stderr, "[init] database `%s' couldn't be upgraded from version 1 to %d. aborting\n", dbname, CURRENT_DATABASE_VERSION);
        dt_database_destroy(db);
        db = NULL;
        goto error;
      }
    }
    else
    {
      sqlite3_finalize(stmt);
      _create_schema(db); // a brand new db it seems
    }
  }

  // create the in-memory tables
  // temporary stuff for some ops, need this for some reason with newer sqlite3:
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE memory.color_labels_temp (imgid INTEGER PRIMARY KEY)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE memory.collected_images (rowid INTEGER PRIMARY KEY AUTOINCREMENT, imgid INTEGER)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE memory.tmp_selection (imgid INTEGER)", NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE memory.tagq (tmpid INTEGER PRIMARY KEY, id INTEGER)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE memory.taglist "
                        "(tmpid INTEGER PRIMARY KEY, id INTEGER UNIQUE ON CONFLICT REPLACE, "
                        "count INTEGER)",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE memory.history (imgid INTEGER, num INTEGER, module INTEGER, "
                        "operation VARCHAR(256) UNIQUE ON CONFLICT REPLACE, op_params BLOB, enabled INTEGER, "
                        "blendop_params BLOB, blendop_version INTEGER, multi_priority INTEGER, multi_name VARCHAR(256))",
                        NULL, NULL, NULL);
  DT_DEBUG_SQLITE3_EXEC(db->handle,
                        "CREATE TABLE MEMORY.style_items (styleid INTEGER, num INTEGER, module INTEGER, "
                        "operation VARCHAR(256), op_params BLOB, enabled INTEGER, "
                        "blendop_params BLOB, blendop_version INTEGER, multi_priority INTEGER, multi_name VARCHAR(256))", NULL, NULL, NULL);

  // create a table legacy_presets with all the presets from pre-auto-apply-cleanup darktable.
  dt_legacy_presets_create(db);

  // drop table settings -- we don't want old versions of dt to drop our tables
  sqlite3_exec(db->handle, "drop table settings", NULL, NULL, NULL);

error:
  g_free(dbname);

  return db;
}
示例#23
0
int dt_init(int argc, char *argv[], const gboolean init_gui, const gboolean load_data, lua_State *L)
{
  double start_wtime = dt_get_wtime();

#ifndef __WIN32__
  if(getuid() == 0 || geteuid() == 0)
    printf(
        "WARNING: either your user id or the effective user id are 0. are you running darktable as root?\n");
#endif

#if defined(__SSE__)
  // make everything go a lot faster.
  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
#endif

  dt_set_signal_handlers();

#include "is_supported_platform.h"

  int sse2_supported = 0;

#ifdef HAVE_BUILTIN_CPU_SUPPORTS
  // NOTE: _may_i_use_cpu_feature() looks better, but only avaliable in ICC
  __builtin_cpu_init();
  sse2_supported = __builtin_cpu_supports("sse2");
#else
  sse2_supported = dt_detect_cpu_features() & CPU_FLAG_SSE2;
#endif
  if(!sse2_supported)
  {
    fprintf(stderr, "[dt_init] SSE2 instruction set is unavailable.\n");
    fprintf(stderr, "[dt_init] expect a LOT of functionality to be broken. you have been warned.\n");
  }

#ifdef M_MMAP_THRESHOLD
  mallopt(M_MMAP_THRESHOLD, 128 * 1024); /* use mmap() for large allocations */
#endif

  // make sure that stack/frame limits are good (musl)
  dt_set_rlimits();

  // we have to have our share dir in XDG_DATA_DIRS,
  // otherwise GTK+ won't find our logo for the about screen (and maybe other things)
  {
    const gchar *xdg_data_dirs = g_getenv("XDG_DATA_DIRS");
    gchar *new_xdg_data_dirs = NULL;
    gboolean set_env = TRUE;
    if(xdg_data_dirs != NULL && *xdg_data_dirs != '\0')
    {
      // check if DARKTABLE_SHAREDIR is already in there
      gboolean found = FALSE;
      gchar **tokens = g_strsplit(xdg_data_dirs, G_SEARCHPATH_SEPARATOR_S, 0);
      // xdg_data_dirs is neither NULL nor empty => tokens != NULL
      for(char **iter = tokens; *iter != NULL; iter++)
        if(!strcmp(DARKTABLE_SHAREDIR, *iter))
        {
          found = TRUE;
          break;
        }
      g_strfreev(tokens);
      if(found)
        set_env = FALSE;
      else
        new_xdg_data_dirs = g_strjoin(G_SEARCHPATH_SEPARATOR_S, DARKTABLE_SHAREDIR, xdg_data_dirs, NULL);
    }
    else
    {
#ifndef _WIN32
      // see http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html for a reason to use those as a
      // default
      if(!g_strcmp0(DARKTABLE_SHAREDIR, "/usr/local/share")
         || !g_strcmp0(DARKTABLE_SHAREDIR, "/usr/local/share/")
         || !g_strcmp0(DARKTABLE_SHAREDIR, "/usr/share") || !g_strcmp0(DARKTABLE_SHAREDIR, "/usr/share/"))
        new_xdg_data_dirs = g_strdup("/usr/local/share/" G_SEARCHPATH_SEPARATOR_S "/usr/share/");
      else
        new_xdg_data_dirs = g_strdup_printf("%s" G_SEARCHPATH_SEPARATOR_S "/usr/local/share/" G_SEARCHPATH_SEPARATOR_S
                                            "/usr/share/", DARKTABLE_SHAREDIR);
#else
      set_env = FALSE;
#endif
    }

    if(set_env) g_setenv("XDG_DATA_DIRS", new_xdg_data_dirs, 1);
    g_free(new_xdg_data_dirs);
  }

  setlocale(LC_ALL, "");
  bindtextdomain(GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR);
  bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
  textdomain(GETTEXT_PACKAGE);

  // init all pointers to 0:
  memset(&darktable, 0, sizeof(darktable_t));

  darktable.start_wtime = start_wtime;

  darktable.progname = argv[0];

  // FIXME: move there into dt_database_t
  dt_pthread_mutex_init(&(darktable.db_insert), NULL);
  dt_pthread_mutex_init(&(darktable.plugin_threadsafe), NULL);
  dt_pthread_mutex_init(&(darktable.capabilities_threadsafe), NULL);
  darktable.control = (dt_control_t *)calloc(1, sizeof(dt_control_t));

  // database
  char *dbfilename_from_command = NULL;
  char *noiseprofiles_from_command = NULL;
  char *datadir_from_command = NULL;
  char *moduledir_from_command = NULL;
  char *tmpdir_from_command = NULL;
  char *configdir_from_command = NULL;
  char *cachedir_from_command = NULL;

#ifdef HAVE_OPENCL
  gboolean exclude_opencl = FALSE;
  gboolean print_statistics = strcmp(argv[0], "darktable-cltest");
#endif

#ifdef USE_LUA
  char *lua_command = NULL;
#endif

  darktable.num_openmp_threads = 1;
#ifdef _OPENMP
  darktable.num_openmp_threads = omp_get_num_procs();
#endif
  darktable.unmuted = 0;
  GSList *config_override = NULL;
  for(int k = 1; k < argc; k++)
  {
    if(argv[k][0] == '-')
    {
      if(!strcmp(argv[k], "--help"))
      {
        return usage(argv[0]);
      }
      if(!strcmp(argv[k], "-h"))
      {
        return usage(argv[0]);
      }
      else if(!strcmp(argv[k], "--version"))
      {
#ifdef USE_LUA
        const char *lua_api_version = strcmp(LUA_API_VERSION_SUFFIX, "") ?
                                      STR(LUA_API_VERSION_MAJOR) "."
                                      STR(LUA_API_VERSION_MINOR) "."
                                      STR(LUA_API_VERSION_PATCH) "-"
                                      LUA_API_VERSION_SUFFIX :
                                      STR(LUA_API_VERSION_MAJOR) "."
                                      STR(LUA_API_VERSION_MINOR) "."
                                      STR(LUA_API_VERSION_PATCH);
#endif
        printf("this is %s\ncopyright (c) 2009-%s johannes hanika\n" PACKAGE_BUGREPORT "\n\ncompile options:\n"
               "  bit depth is %s\n"
#ifdef _DEBUG
               "  debug build\n"
#else
               "  normal build\n"
#endif
#if defined(__SSE2__) && defined(__SSE__)
               "  SSE2 optimized codepath enabled\n"
#else
               "  SSE2 optimized codepath disabled\n"
#endif
#ifdef _OPENMP
               "  OpenMP support enabled\n"
#else
               "  OpenMP support disabled\n"
#endif

#ifdef HAVE_OPENCL
               "  OpenCL support enabled\n"
#else
               "  OpenCL support disabled\n"
#endif

#ifdef USE_LUA
               "  Lua support enabled, API version %s\n"
#else
               "  Lua support disabled\n"
#endif

#ifdef USE_COLORDGTK
               "  Colord support enabled\n"
#else
               "  Colord support disabled\n"
#endif

#ifdef HAVE_GPHOTO2
               "  gPhoto2 support enabled\n"
#else
               "  gPhoto2 support disabled\n"
#endif

#ifdef HAVE_GRAPHICSMAGICK
               "  GraphicsMagick support enabled\n"
#else
               "  GraphicsMagick support disabled\n"
#endif

#ifdef HAVE_OPENEXR
               "  OpenEXR support enabled\n"
#else
               "  OpenEXR support disabled\n"
#endif
               ,
               darktable_package_string,
               darktable_last_commit_year,
               (sizeof(void *) == 8 ? "64 bit" : sizeof(void *) == 4 ? "32 bit" : "unknown")
#if USE_LUA
                   ,
               lua_api_version
#endif
               );
        return 1;
      }
      else if(!strcmp(argv[k], "--library") && argc > k + 1)
      {
        dbfilename_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--datadir") && argc > k + 1)
      {
        datadir_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--moduledir") && argc > k + 1)
      {
        moduledir_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--tmpdir") && argc > k + 1)
      {
        tmpdir_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--configdir") && argc > k + 1)
      {
        configdir_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--cachedir") && argc > k + 1)
      {
        cachedir_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--localedir") && argc > k + 1)
      {
        bindtextdomain(GETTEXT_PACKAGE, argv[++k]);
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(argv[k][1] == 'd' && argc > k + 1)
      {
        if(!strcmp(argv[k + 1], "all"))
          darktable.unmuted = 0xffffffff; // enable all debug information
        else if(!strcmp(argv[k + 1], "cache"))
          darktable.unmuted |= DT_DEBUG_CACHE; // enable debugging for lib/film/cache module
        else if(!strcmp(argv[k + 1], "control"))
          darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
        else if(!strcmp(argv[k + 1], "dev"))
          darktable.unmuted |= DT_DEBUG_DEV; // develop module
        else if(!strcmp(argv[k + 1], "input"))
          darktable.unmuted |= DT_DEBUG_INPUT; // input devices
        else if(!strcmp(argv[k + 1], "camctl"))
          darktable.unmuted |= DT_DEBUG_CAMCTL; // camera control module
        else if(!strcmp(argv[k + 1], "perf"))
          darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
        else if(!strcmp(argv[k + 1], "pwstorage"))
          darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
        else if(!strcmp(argv[k + 1], "opencl"))
          darktable.unmuted |= DT_DEBUG_OPENCL; // gpu accel via opencl
        else if(!strcmp(argv[k + 1], "sql"))
          darktable.unmuted |= DT_DEBUG_SQL; // SQLite3 queries
        else if(!strcmp(argv[k + 1], "memory"))
          darktable.unmuted |= DT_DEBUG_MEMORY; // some stats on mem usage now and then.
        else if(!strcmp(argv[k + 1], "lighttable"))
          darktable.unmuted |= DT_DEBUG_LIGHTTABLE; // lighttable related stuff.
        else if(!strcmp(argv[k + 1], "nan"))
          darktable.unmuted |= DT_DEBUG_NAN; // check for NANs when processing the pipe.
        else if(!strcmp(argv[k + 1], "masks"))
          darktable.unmuted |= DT_DEBUG_MASKS; // masks related stuff.
        else if(!strcmp(argv[k + 1], "lua"))
          darktable.unmuted |= DT_DEBUG_LUA; // lua errors are reported on console
        else if(!strcmp(argv[k + 1], "print"))
          darktable.unmuted |= DT_DEBUG_PRINT; // print errors are reported on console
        else if(!strcmp(argv[k + 1], "camsupport"))
          darktable.unmuted |= DT_DEBUG_CAMERA_SUPPORT; // camera support warnings are reported on console
        else
          return usage(argv[0]);
        k++;
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(argv[k][1] == 't' && argc > k + 1)
      {
        darktable.num_openmp_threads = CLAMP(atol(argv[k + 1]), 1, 100);
        printf("[dt_init] using %d threads for openmp parallel sections\n", darktable.num_openmp_threads);
        k++;
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--conf") && argc > k + 1)
      {
        gchar *keyval = g_strdup(argv[++k]), *c = keyval;
        argv[k-1] = NULL;
        argv[k] = NULL;
        gchar *end = keyval + strlen(keyval);
        while(*c != '=' && c < end) c++;
        if(*c == '=' && *(c + 1) != '\0')
        {
          *c++ = '\0';
          dt_conf_string_entry_t *entry = (dt_conf_string_entry_t *)g_malloc(sizeof(dt_conf_string_entry_t));
          entry->key = g_strdup(keyval);
          entry->value = g_strdup(c);
          config_override = g_slist_append(config_override, entry);
        }
        g_free(keyval);
      }
      else if(!strcmp(argv[k], "--noiseprofiles") && argc > k + 1)
      {
        noiseprofiles_from_command = argv[++k];
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--luacmd") && argc > k + 1)
      {
#ifdef USE_LUA
        lua_command = argv[++k];
#else
        ++k;
#endif
        argv[k-1] = NULL;
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--disable-opencl"))
      {
#ifdef HAVE_OPENCL
        exclude_opencl = TRUE;
#endif
        argv[k] = NULL;
      }
      else if(!strcmp(argv[k], "--"))
      {
        // "--" confuses the argument parser of glib/gtk. remove it.
        argv[k] = NULL;
        break;
      }
      else
        return usage(argv[0]); // fail on unrecognized options
    }
  }

  // remove the NULLs to not confuse gtk_init() later.
  for(int i = 1; i < argc; i++)
  {
    int k;
    for(k = i; k < argc; k++)
      if(argv[k] != NULL) break;

    if(k > i)
    {
      k -= i;
      for(int j = i + k; j < argc; j++)
      {
        argv[j-k] = argv[j];
        argv[j] = NULL;
      }
      argc -= k;
    }
  }

  if(darktable.unmuted & DT_DEBUG_MEMORY)
  {
    fprintf(stderr, "[memory] at startup\n");
    dt_print_mem_usage();
  }

  if(init_gui)
  {
    // I doubt that connecting to dbus for darktable-cli makes sense
    darktable.dbus = dt_dbus_init();

    // make sure that we have no stale global progress bar visible. thus it's run as early is possible
    dt_control_progress_init(darktable.control);
  }

#ifdef _OPENMP
  omp_set_num_threads(darktable.num_openmp_threads);
#endif
  dt_loc_init_datadir(datadir_from_command);
  dt_loc_init_plugindir(moduledir_from_command);
  if(dt_loc_init_tmp_dir(tmpdir_from_command))
  {
    fprintf(stderr, "error: invalid temporary directory: %s\n", darktable.tmpdir);
    return usage(argv[0]);
  }
  dt_loc_init_user_config_dir(configdir_from_command);
  dt_loc_init_user_cache_dir(cachedir_from_command);

#ifdef USE_LUA
  dt_lua_init_early(L);
#endif

  // thread-safe init:
  dt_exif_init();
  char datadir[PATH_MAX] = { 0 };
  dt_loc_get_user_config_dir(datadir, sizeof(datadir));
  char darktablerc[PATH_MAX] = { 0 };
  snprintf(darktablerc, sizeof(darktablerc), "%s/darktablerc", datadir);

  // initialize the config backend. this needs to be done first...
  darktable.conf = (dt_conf_t *)calloc(1, sizeof(dt_conf_t));
  dt_conf_init(darktable.conf, darktablerc, config_override);
  g_slist_free_full(config_override, g_free);

  // set the interface language
  const gchar *lang = dt_conf_get_string("ui_last/gui_language");
#if defined(_WIN32)
  // get the default locale if no language preference was specified in the config file
  if(lang == NULL || lang[0] == '\0')
  {
    const wchar_t *wcLocaleName = NULL;
    wcLocaleName = dtwin_get_locale();
    if(wcLocaleName != NULL)
    {
      gchar *langLocale;
      langLocale = g_utf16_to_utf8(wcLocaleName, -1, NULL, NULL, NULL);
      if(langLocale != NULL)
      {
        g_free((gchar *)lang);
        lang = g_strdup(langLocale);
      }
    }
  }
#endif // defined (_WIN32)

  if(lang != NULL && lang[0] != '\0')
  {
    g_setenv("LANGUAGE", lang, 1);
    if(setlocale(LC_ALL, lang) != NULL) gtk_disable_setlocale();
    setlocale(LC_MESSAGES, lang);
    g_setenv("LANG", lang, 1);
  }
  g_free((gchar *)lang);

  // we need this REALLY early so that error messages can be shown, however after gtk_disable_setlocale
  if(init_gui)
  {
#ifdef GDK_WINDOWING_WAYLAND
    // There are currently bad interactions with Wayland (drop-downs
    // are very narrow, scroll events lost). Until this is fixed, give
    // priority to the XWayland backend for Wayland users.
    gdk_set_allowed_backends("x11,*");
#endif
    gtk_init(&argc, &argv);
  }

  // detect cpu features and decide which codepaths to enable
  dt_codepaths_init();

  // get the list of color profiles
  darktable.color_profiles = dt_colorspaces_init();

  // initialize the database
  darktable.db = dt_database_init(dbfilename_from_command, load_data);
  if(darktable.db == NULL)
  {
    printf("ERROR : cannot open database\n");
    return 1;
  }
  else if(!dt_database_get_lock_acquired(darktable.db))
  {
    gboolean image_loaded_elsewhere = FALSE;
#ifndef MAC_INTEGRATION
    // send the images to the other instance via dbus
    fprintf(stderr, "trying to open the images in the running instance\n");

    GDBusConnection *connection = NULL;
    for(int i = 1; i < argc; i++)
    {
      // make the filename absolute ...
      if(argv[i] == NULL || *argv[i] == '\0') continue;
      gchar *filename = dt_util_normalize_path(argv[i]);
      if(filename == NULL) continue;
      if(!connection) connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
      // ... and send it to the running instance of darktable
      image_loaded_elsewhere = g_dbus_connection_call_sync(connection, "org.darktable.service", "/darktable",
                                                           "org.darktable.service.Remote", "Open",
                                                           g_variant_new("(s)", filename), NULL,
                                                           G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL) != NULL;
      g_free(filename);
    }
    if(connection) g_object_unref(connection);
#endif

    if(!image_loaded_elsewhere) dt_database_show_error(darktable.db);

    return 1;
  }

  // Initialize the signal system
  darktable.signals = dt_control_signal_init();

  // Make sure that the database and xmp files are in sync
  // We need conf and db to be up and running for that which is the case here.
  // FIXME: is this also useful in non-gui mode?
  GList *changed_xmp_files = NULL;
  if(init_gui && dt_conf_get_bool("run_crawler_on_start"))
  {
    changed_xmp_files = dt_control_crawler_run();
  }

  if(init_gui)
  {
    dt_control_init(darktable.control);
  }
  else
  {
    if(dbfilename_from_command && !strcmp(dbfilename_from_command, ":memory:"))
      dt_gui_presets_init(); // init preset db schema.
    darktable.control->running = 0;
    darktable.control->accelerators = NULL;
    dt_pthread_mutex_init(&darktable.control->run_mutex, NULL);
  }

  // initialize collection query
  darktable.collection = dt_collection_new(NULL);

  /* initialize selection */
  darktable.selection = dt_selection_new();

  /* capabilities set to NULL */
  darktable.capabilities = NULL;

  // Initialize the password storage engine
  darktable.pwstorage = dt_pwstorage_new();

  darktable.guides = dt_guides_init();

#ifdef HAVE_GRAPHICSMAGICK
  /* GraphicsMagick init */
  InitializeMagick(darktable.progname);

  // *SIGH*
  dt_set_signal_handlers();
#endif

  darktable.opencl = (dt_opencl_t *)calloc(1, sizeof(dt_opencl_t));
#ifdef HAVE_OPENCL
  dt_opencl_init(darktable.opencl, exclude_opencl, print_statistics);
#endif

  darktable.points = (dt_points_t *)calloc(1, sizeof(dt_points_t));
  dt_points_init(darktable.points, dt_get_num_threads());

  darktable.noiseprofile_parser = dt_noiseprofile_init(noiseprofiles_from_command);

  // must come before mipmap_cache, because that one will need to access
  // image dimensions stored in here:
  darktable.image_cache = (dt_image_cache_t *)calloc(1, sizeof(dt_image_cache_t));
  dt_image_cache_init(darktable.image_cache);

  darktable.mipmap_cache = (dt_mipmap_cache_t *)calloc(1, sizeof(dt_mipmap_cache_t));
  dt_mipmap_cache_init(darktable.mipmap_cache);

  // The GUI must be initialized before the views, because the init()
  // functions of the views depend on darktable.control->accels_* to register
  // their keyboard accelerators

  if(init_gui)
  {
    darktable.gui = (dt_gui_gtk_t *)calloc(1, sizeof(dt_gui_gtk_t));
    if(dt_gui_gtk_init(darktable.gui)) return 1;
    dt_bauhaus_init();
  }
  else
    darktable.gui = NULL;

  darktable.view_manager = (dt_view_manager_t *)calloc(1, sizeof(dt_view_manager_t));
  dt_view_manager_init(darktable.view_manager);

  // check whether we were able to load darkroom view. if we failed, we'll crash everywhere later on.
  if(!darktable.develop) return 1;

  darktable.imageio = (dt_imageio_t *)calloc(1, sizeof(dt_imageio_t));
  dt_imageio_init(darktable.imageio);

  // load the darkroom mode plugins once:
  dt_iop_load_modules_so();

  if(init_gui)
  {
#ifdef HAVE_GPHOTO2
    // Initialize the camera control.
    // this is done late so that the gui can react to the signal sent but before switching to lighttable!
    darktable.camctl = dt_camctl_new();
#endif

    darktable.lib = (dt_lib_t *)calloc(1, sizeof(dt_lib_t));
    dt_lib_init(darktable.lib);

    dt_gui_gtk_load_config();

    // init the gui part of views
    dt_view_manager_gui_init(darktable.view_manager);
    // Loading the keybindings
    char keyfile[PATH_MAX] = { 0 };

    // First dump the default keymapping
    snprintf(keyfile, sizeof(keyfile), "%s/keyboardrc_default", datadir);
    gtk_accel_map_save(keyfile);

    // Removing extraneous semi-colons from the default keymap
    strip_semicolons_from_keymap(keyfile);

    // Then load any modified keys if available
    snprintf(keyfile, sizeof(keyfile), "%s/keyboardrc", datadir);
    if(g_file_test(keyfile, G_FILE_TEST_EXISTS))
      gtk_accel_map_load(keyfile);
    else
      gtk_accel_map_save(keyfile); // Save the default keymap if none is present

    // initialize undo struct
    darktable.undo = dt_undo_init();
  }

  if(darktable.unmuted & DT_DEBUG_MEMORY)
  {
    fprintf(stderr, "[memory] after successful startup\n");
    dt_print_mem_usage();
  }

  dt_image_local_copy_synch();

/* init lua last, since it's user made stuff it must be in the real environment */
#ifdef USE_LUA
  dt_lua_init(darktable.lua_state.state, lua_command);
#endif

  if(init_gui)
  {
    const char *mode = "lighttable";
    // april 1st: you have to earn using dt first! or know that you can switch views with keyboard shortcuts
    time_t now;
    time(&now);
    struct tm lt;
    localtime_r(&now, &lt);
    if(lt.tm_mon == 3 && lt.tm_mday == 1) mode = "knight";
    // we have to call dt_ctl_switch_mode_to() here already to not run into a lua deadlock.
    // having another call later is ok
    dt_ctl_switch_mode_to(mode);

#ifndef MAC_INTEGRATION
    // load image(s) specified on cmdline.
    // this has to happen after lua is initialized as image import can run lua code
    // If only one image is listed, attempt to load it in darkroom
    int last_id = 0;
    gboolean only_single_images = TRUE;
    int loaded_images = 0;

    for(int i = 1; i < argc; i++)
    {
      gboolean single_image = FALSE;
      if(argv[i] == NULL || *argv[i] == '\0') continue;
      int new_id = dt_load_from_string(argv[i], FALSE, &single_image);
      if(new_id > 0)
      {
        last_id = new_id;
        loaded_images++;
        if(!single_image) only_single_images = FALSE;
      }
    }

    if(loaded_images == 1 && only_single_images)
    {
      dt_control_set_mouse_over_id(last_id);
      dt_ctl_switch_mode_to("darkroom");
    }
#endif
  }

  // last but not least construct the popup that asks the user about images whose xmp files are newer than the
  // db entry
  if(init_gui && changed_xmp_files)
  {
    dt_control_crawler_show_image_list(changed_xmp_files);
  }

  dt_print(DT_DEBUG_CONTROL, "[init] startup took %f seconds\n", dt_get_wtime() - start_wtime);

  return 0;
}
示例#24
0
文件: database.c 项目: sk1p/darktable
dt_database_t *dt_database_init(char *alternative)
{
  /* migrate default database location to new default */
  _database_migrate_to_xdg_structure();

  /* delete old mipmaps files */
  _database_delete_mipmaps_files();

  /* lets construct the db filename  */
  gchar * dbname = NULL;
  gchar dbfilename[1024] = {0};
  gchar datadir[1024] = {0};

  dt_loc_get_user_config_dir(datadir, 1024);

  if ( alternative == NULL )
  {
    dbname = dt_conf_get_string ("database");
    if(!dbname)               snprintf(dbfilename, 1024, "%s/library.db", datadir);
    else if(dbname[0] != '/') snprintf(dbfilename, 1024, "%s/%s", datadir, dbname);
    else                      snprintf(dbfilename, 1024, "%s", dbname);
  }
  else
  {
    snprintf(dbfilename, 1024, "%s", alternative);
    dbname = g_file_get_basename (g_file_new_for_path(alternative));
  }

  /* create database */
  dt_database_t *db = (dt_database_t *)g_malloc(sizeof(dt_database_t));
  memset(db,0,sizeof(dt_database_t));
  db->dbfilename = g_strdup(dbfilename);
  db->is_new_database = FALSE;

  /* test if databasefile is available */
  if(!g_file_test(dbfilename, G_FILE_TEST_IS_REGULAR)) 
    db->is_new_database = TRUE;

  /* opening / creating database */
  if(sqlite3_open(db->dbfilename, &db->handle))
  {
    fprintf(stderr, "[init] could not find database ");
    if(dbname) fprintf(stderr, "`%s'!\n", dbname);
    else       fprintf(stderr, "\n");
    fprintf(stderr, "[init] maybe your %s/darktablerc is corrupt?\n",datadir);
    dt_loc_get_datadir(dbfilename, 512);
    fprintf(stderr, "[init] try `cp %s/darktablerc %s/darktablerc'\n", dbfilename,datadir);
    g_free(dbname);
    g_free(db);
    return NULL;
  }

  /* attach a memory database to db connection for use with temporary tables
     used during instance life time, which is discarded on exit.
  */
  sqlite3_exec(db->handle, "attach database ':memory:' as memory",NULL,NULL,NULL);
  
  sqlite3_exec(db->handle, "PRAGMA synchronous = OFF", NULL, NULL, NULL);
  sqlite3_exec(db->handle, "PRAGMA journal_mode = MEMORY", NULL, NULL, NULL);
  sqlite3_exec(db->handle, "PRAGMA page_size = 32768", NULL, NULL, NULL);

  g_free(dbname);
  return db;
}
示例#25
0
void gui_init(struct dt_iop_module_t *self)
{
  self->gui_data = malloc(sizeof(dt_iop_colorout_gui_data_t));
  memset(self->gui_data,0,sizeof(dt_iop_colorout_gui_data_t));
  dt_iop_colorout_gui_data_t *g = (dt_iop_colorout_gui_data_t *)self->gui_data;

  g->profiles = NULL;
  dt_iop_color_profile_t *prof = (dt_iop_color_profile_t *)g_malloc0(sizeof(dt_iop_color_profile_t));
  g_strlcpy(prof->filename, "sRGB", sizeof(prof->filename));
  g_strlcpy(prof->name, "sRGB", sizeof(prof->name));
  int pos;
  int display_pos;
  prof->pos = 0;
  prof->display_pos = 0;
  g->profiles = g_list_append(g->profiles, prof);

  prof = (dt_iop_color_profile_t *)g_malloc0(sizeof(dt_iop_color_profile_t));
  g_strlcpy(prof->filename, "adobergb", sizeof(prof->filename));
  g_strlcpy(prof->name, "adobergb", sizeof(prof->name));
  prof->pos = 1;
  prof->display_pos = 1;
  g->profiles = g_list_append(g->profiles, prof);

  prof = (dt_iop_color_profile_t *)g_malloc0(sizeof(dt_iop_color_profile_t));
  g_strlcpy(prof->filename, "X profile", sizeof(prof->filename));
  g_strlcpy(prof->name, "X profile", sizeof(prof->name));
  prof->pos = -1;
  prof->display_pos = 2;
  g->profiles = g_list_append(g->profiles, prof);

  prof = (dt_iop_color_profile_t *)g_malloc0(sizeof(dt_iop_color_profile_t));
  g_strlcpy(prof->filename, "linear_rgb", sizeof(prof->filename));
  g_strlcpy(prof->name, "linear_rgb", sizeof(prof->name));
  pos = prof->pos = 2;
  display_pos = prof->display_pos = 3;
  g->profiles = g_list_append(g->profiles, prof);

  // read {conf,data}dir/color/out/*.icc
  char datadir[DT_MAX_PATH_LEN];
  char confdir[DT_MAX_PATH_LEN];
  char dirname[DT_MAX_PATH_LEN];
  char filename[DT_MAX_PATH_LEN];
  dt_loc_get_user_config_dir(confdir, DT_MAX_PATH_LEN);
  dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN);
  snprintf(dirname, DT_MAX_PATH_LEN, "%s/color/out", confdir);
  if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
    snprintf(dirname, DT_MAX_PATH_LEN, "%s/color/out", datadir);
  cmsHPROFILE tmpprof;
  const gchar *d_name;
  GDir *dir = g_dir_open(dirname, 0, NULL);
  if(dir)
  {
    while((d_name = g_dir_read_name(dir)))
    {
      snprintf(filename, DT_MAX_PATH_LEN, "%s/%s", dirname, d_name);
      tmpprof = cmsOpenProfileFromFile(filename, "r");
      if(tmpprof)
      {
        char *lang = getenv("LANG");
        if (!lang) lang = "en_US";

        dt_iop_color_profile_t *prof = (dt_iop_color_profile_t *)g_malloc0(sizeof(dt_iop_color_profile_t));
        char name[1024];
        cmsGetProfileInfoASCII(tmpprof, cmsInfoDescription, lang, lang+3, name, 1024);
        g_strlcpy(prof->name, name, sizeof(prof->name));
        g_strlcpy(prof->filename, d_name, sizeof(prof->filename));
        prof->pos = ++pos;
        prof->display_pos = ++display_pos;
        cmsCloseProfile(tmpprof);
        g->profiles = g_list_append(g->profiles, prof);
      }
    }
    g_dir_close(dir);
  }

  self->widget = gtk_vbox_new(TRUE, DT_BAUHAUS_SPACE);

  // TODO:
  g->cbox1 = dt_bauhaus_combobox_new(self);
  gtk_box_pack_start(GTK_BOX(self->widget), g->cbox1, TRUE, TRUE, 0);
  dt_bauhaus_widget_set_label(g->cbox1, _("output intent"));
  dt_bauhaus_combobox_add(g->cbox1, _("perceptual"));
  dt_bauhaus_combobox_add(g->cbox1, _("relative colorimetric"));
  dt_bauhaus_combobox_add(g->cbox1, C_("rendering intent", "saturation"));
  dt_bauhaus_combobox_add(g->cbox1, _("absolute colorimetric"));
  g->cbox4 = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(g->cbox4, _("display intent"));
  gtk_box_pack_start(GTK_BOX(self->widget), g->cbox4, TRUE, TRUE, 0);
  dt_bauhaus_combobox_add(g->cbox4, _("perceptual"));
  dt_bauhaus_combobox_add(g->cbox4, _("relative colorimetric"));
  dt_bauhaus_combobox_add(g->cbox4, C_("rendering intent", "saturation"));
  dt_bauhaus_combobox_add(g->cbox4, _("absolute colorimetric"));
  g->cbox2 = dt_bauhaus_combobox_new(self);
  g->cbox3 = dt_bauhaus_combobox_new(self);
  g->cbox5 = dt_bauhaus_combobox_new(self);
  dt_bauhaus_widget_set_label(g->cbox2, _("output profile"));
  dt_bauhaus_widget_set_label(g->cbox5, _("softproof profile"));
  dt_bauhaus_widget_set_label(g->cbox3, _("display profile"));
  gtk_box_pack_start(GTK_BOX(self->widget), g->cbox2, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), g->cbox5, TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(self->widget), g->cbox3, TRUE, TRUE, 0);
  GList *l = g->profiles;
  while(l)
  {
    dt_iop_color_profile_t *prof = (dt_iop_color_profile_t *)l->data;
    if(!strcmp(prof->name, "X profile"))
    {
      // the system display profile is only suitable for display purposes
      dt_bauhaus_combobox_add(g->cbox3, _("system display profile"));
    }
    else if(!strcmp(prof->name, "linear_rgb"))
    {
      dt_bauhaus_combobox_add(g->cbox2, _("linear RGB"));
      dt_bauhaus_combobox_add(g->cbox3, _("linear RGB"));
      dt_bauhaus_combobox_add(g->cbox5, _("linear RGB"));
    }
    else if(!strcmp(prof->name, "sRGB"))
    {
      dt_bauhaus_combobox_add(g->cbox2, _("sRGB (web-safe)"));
      dt_bauhaus_combobox_add(g->cbox3, _("sRGB (web-safe)"));
      dt_bauhaus_combobox_add(g->cbox5, _("sRGB (web-safe)"));
    }
    else if(!strcmp(prof->name, "adobergb"))
    {
      dt_bauhaus_combobox_add(g->cbox2, _("Adobe RGB"));
      dt_bauhaus_combobox_add(g->cbox3, _("Adobe RGB"));
      dt_bauhaus_combobox_add(g->cbox5, _("Adobe RGB"));
    }
    else
    {
      dt_bauhaus_combobox_add(g->cbox2, prof->name);
      dt_bauhaus_combobox_add(g->cbox3, prof->name);
      dt_bauhaus_combobox_add(g->cbox5, prof->name);
    }
    l = g_list_next(l);
  }

  char tooltip[1024];
  g_object_set(G_OBJECT(g->cbox1), "tooltip-text", _("rendering intent"), (char *)NULL);
  snprintf(tooltip, 1024, _("icc profiles in %s/color/out or %s/color/out"), confdir, datadir);
  g_object_set(G_OBJECT(g->cbox2), "tooltip-text", tooltip, (char *)NULL);
  snprintf(tooltip, 1024, _("display icc profiles in %s/color/out or %s/color/out"), confdir, datadir);
  g_object_set(G_OBJECT(g->cbox3), "tooltip-text", tooltip, (char *)NULL);
  snprintf(tooltip, 1024, _("softproof icc profiles in %s/color/out or %s/color/out"), confdir, datadir);
  g_object_set(G_OBJECT(g->cbox5), "tooltip-text", tooltip, (char *)NULL);

  g_signal_connect (G_OBJECT (g->cbox1), "value-changed",
                    G_CALLBACK (intent_changed),
                    (gpointer)self);
  g_signal_connect (G_OBJECT (g->cbox4), "value-changed",
                    G_CALLBACK (display_intent_changed),
                    (gpointer)self);
  g_signal_connect (G_OBJECT (g->cbox2), "value-changed",
                    G_CALLBACK (output_profile_changed),
                    (gpointer)self);
  g_signal_connect (G_OBJECT (g->cbox3), "value-changed",
                    G_CALLBACK (display_profile_changed),
                    (gpointer)self);
  g_signal_connect (G_OBJECT (g->cbox5), "value-changed",
                    G_CALLBACK (softproof_profile_changed),
                    (gpointer)self);

  // reload the profiles when the display profile changed!
  dt_control_signal_connect(darktable.signals, DT_SIGNAL_CONTROL_PROFILE_CHANGED,
                            G_CALLBACK(_signal_profile_changed), self);
}
示例#26
0
gboolean dt_styles_create_from_image(const char *name, const char *description, int32_t imgid, GList *filter)
{
  int id = 0;
  sqlite3_stmt *stmt;

  /* first create the style header */
  if(!dt_styles_create_style_header(name, description)) return FALSE;

  if((id = dt_styles_get_id_by_name(name)) != 0)
  {
    /* create the style_items from source image history stack */
    if(filter)
    {
      GList *list = filter;
      char tmp[64];
      char include[2048] = { 0 };
      g_strlcat(include, "num in (", sizeof(include));
      do
      {
        if(list != g_list_first(list)) g_strlcat(include, ",", sizeof(include));
        snprintf(tmp, sizeof(tmp), "%d", GPOINTER_TO_INT(list->data));
        g_strlcat(include, tmp, sizeof(include));
      } while((list = g_list_next(list)));
      g_strlcat(include, ")", sizeof(include));
      char query[4096] = { 0 };
      snprintf(query, sizeof(query), "insert into style_items "
                                     "(styleid,num,module,operation,op_params,enabled,blendop_params,blendop_"
                                     "version,multi_priority,multi_name) select ?1, "
                                     "num,module,operation,op_params,enabled,blendop_params,blendop_version,"
                                     "multi_priority,multi_name from history where imgid=?2 and %s",
               include);
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
    }
    else
      DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
                                  "insert into style_items "
                                  "(styleid,num,module,operation,op_params,enabled,blendop_params,blendop_"
                                  "version,multi_priority,multi_name) select ?1, "
                                  "num,module,operation,op_params,enabled,blendop_params,blendop_version,"
                                  "multi_priority,multi_name from history where imgid=?2",
                                  -1, &stmt, NULL);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, id);
    DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid);
    sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    _dt_style_cleanup_multi_instance(id);

    /* backup style to disk */
    char stylesdir[PATH_MAX] = { 0 };
    dt_loc_get_user_config_dir(stylesdir, sizeof(stylesdir));
    g_strlcat(stylesdir, "/styles", sizeof(stylesdir));
    g_mkdir_with_parents(stylesdir, 00755);

    dt_styles_save_to_file(name, stylesdir, FALSE);

    char tmp_accel[1024];
    gchar *tmp_name = g_strdup(name); // freed by _destroy_style_shortcut_callback
    snprintf(tmp_accel, sizeof(tmp_accel), C_("accel", "styles/apply %s"), name);
    dt_accel_register_global(tmp_accel, 0, 0);
    GClosure *closure;
    closure = g_cclosure_new(G_CALLBACK(_apply_style_shortcut_callback), tmp_name,
                             _destroy_style_shortcut_callback);
    dt_accel_connect_global(tmp_accel, closure);
    dt_control_signal_raise(darktable.signals, DT_SIGNAL_STYLE_CHANGED);
    return TRUE;
  }
  return FALSE;
}
示例#27
0
int dt_lua_init_configuration(lua_State*L)
{
  char tmp_path[PATH_MAX];

  dt_lua_push_darktable_lib(L);

  dt_lua_goto_subtable(L,"configuration");
  // build the table containing the configuration info

  lua_pushstring(L,"tmp_dir");
  dt_loc_get_tmp_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_settable(L,-3);

  lua_pushstring(L,"config_dir");
  dt_loc_get_user_config_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_settable(L,-3);

  lua_pushstring(L,"cache_dir");
  dt_loc_get_user_cache_dir(tmp_path, PATH_MAX);
  lua_pushstring(L,tmp_path);
  lua_settable(L,-3);

  lua_pushstring(L,"version");
  lua_pushstring(L,PACKAGE_VERSION);
  lua_settable(L,-3);

  lua_pushstring(L,"verbose");
  lua_pushboolean(L,darktable.unmuted & DT_DEBUG_LUA);
  lua_settable(L,-3);

  lua_pushstring(L,"has_gui");
  lua_pushboolean(L,darktable.gui != NULL);
  lua_settable(L,-3);

  lua_pushstring(L,"api_version_major");
  lua_pushnumber(L,API_VERSION_MAJOR);
  lua_settable(L,-3);

  lua_pushstring(L,"api_version_minor");
  lua_pushnumber(L,API_VERSION_MINOR);
  lua_settable(L,-3);

  lua_pushstring(L,"api_version_patch");
  lua_pushnumber(L,API_VERSION_PATCH);
  lua_settable(L,-3);

  lua_pushstring(L,"api_version_suffix");
  lua_pushstring(L,API_VERSION_SUFFIX);
  lua_settable(L,-3);

  lua_pushstring(L,"api_version_string");
  if (strcmp(API_VERSION_SUFFIX, "") == 0) {
    lua_pushfstring(L,"%d.%d.%d",API_VERSION_MAJOR,API_VERSION_MINOR,API_VERSION_PATCH);
  } else {
    lua_pushfstring(L,"%d.%d.%d-%s",API_VERSION_MAJOR,API_VERSION_MINOR,API_VERSION_PATCH,API_VERSION_SUFFIX);
  }
  lua_settable(L,-3);

  lua_pop(L,1); //remove the configuration table from the stack
  return 0;

}
示例#28
0
void
gui_init (dt_lib_module_t *self)
{
  dt_lib_export_t *d = (dt_lib_export_t *)malloc(sizeof(dt_lib_export_t));
  self->data = (void *)d;
  self->widget = gtk_table_new(8, 2, FALSE);
  gtk_table_set_row_spacings(GTK_TABLE(self->widget), 5);

  GtkWidget *label;

  label = dtgtk_label_new(_("target storage"), DARKTABLE_LABEL_TAB | DARKTABLE_LABEL_ALIGN_RIGHT);
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
  d->storage = GTK_COMBO_BOX(gtk_combo_box_new_text());
  GList *it = darktable.imageio->plugins_storage;
  while(it)
  {
    dt_imageio_module_storage_t *module = (dt_imageio_module_storage_t *)it->data;
    gtk_combo_box_append_text(d->storage, module->name(module));
    it = g_list_next(it);
  }
  dt_control_signal_connect(darktable.signals,DT_SIGNAL_IMAGEIO_STORAGE_CHANGE,G_CALLBACK(on_storage_list_changed),self);
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->storage), 0, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  g_signal_connect (G_OBJECT (d->storage), "changed",
                    G_CALLBACK (storage_changed),
                    (gpointer)d);

  d->storage_box = GTK_CONTAINER(gtk_alignment_new(1.0, 1.0, 1.0, 1.0));
  gtk_alignment_set_padding(GTK_ALIGNMENT(d->storage_box), 0, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->storage_box), 0, 2, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0);

  label = dtgtk_label_new(_("file format"), DARKTABLE_LABEL_TAB | DARKTABLE_LABEL_ALIGN_RIGHT);
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_set_row_spacing(GTK_TABLE(self->widget), 2, 20);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 2, 3, 4, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  d->format = GTK_COMBO_BOX(gtk_combo_box_new_text());

  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->format), 0, 2, 4, 5, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  g_signal_connect (G_OBJECT (d->format), "changed",
                    G_CALLBACK (format_changed),
                    (gpointer)d);

  d->format_box = GTK_CONTAINER(gtk_alignment_new(1.0, 1.0, 1.0, 1.0));
  gtk_alignment_set_padding(GTK_ALIGNMENT(d->format_box), 0, 0, 0, 0);
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->format_box), 0, 2, 5, 6, GTK_EXPAND|GTK_FILL, 0, 0, 0);

  label = dtgtk_label_new(_("global options"), DARKTABLE_LABEL_TAB | DARKTABLE_LABEL_ALIGN_RIGHT);
  gtk_table_set_row_spacing(GTK_TABLE(self->widget), 5, 20);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 2, 6, 7, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  d->width  = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(0, 10000, 1));
  g_object_set(G_OBJECT(d->width), "tooltip-text", _("maximum output width\nset to 0 for no scaling"), (char *)NULL);
  d->height = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(0, 10000, 1));
  g_object_set(G_OBJECT(d->height), "tooltip-text", _("maximum output height\nset to 0 for no scaling"), (char *)NULL);

  dt_gui_key_accel_block_on_focus_connect (GTK_WIDGET (d->width));
  dt_gui_key_accel_block_on_focus_connect (GTK_WIDGET (d->height));
  /*
    gtk_widget_add_events(GTK_WIDGET(d->width), GDK_FOCUS_CHANGE_MASK);
    g_signal_connect (G_OBJECT (d->width), "focus-in-event",  G_CALLBACK(focus_in),  NULL);
    g_signal_connect (G_OBJECT (d->width), "focus-out-event", G_CALLBACK(focus_out), NULL);
    gtk_widget_add_events(GTK_WIDGET(d->height), GDK_FOCUS_CHANGE_MASK);
    g_signal_connect (G_OBJECT (d->height), "focus-in-event",  G_CALLBACK(focus_in),  NULL);
    g_signal_connect (G_OBJECT (d->height), "focus-out-event", G_CALLBACK(focus_out), NULL);
    */
  label = gtk_label_new(_("max size"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 1, 7, 8, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  GtkBox *hbox = GTK_BOX(gtk_hbox_new(FALSE, 5));
  gtk_box_pack_start(hbox, GTK_WIDGET(d->width), TRUE, TRUE, 0);
  gtk_box_pack_start(hbox, gtk_label_new(_("x")), FALSE, FALSE, 0);
  gtk_box_pack_start(hbox, GTK_WIDGET(d->height), TRUE, TRUE, 0);
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(hbox), 1, 2, 7, 8, GTK_EXPAND|GTK_FILL, 0, 0, 0);

  label = gtk_label_new(_("intent"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 1, 8, 9, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  d->intent = GTK_COMBO_BOX(gtk_combo_box_new_text());
  gtk_combo_box_append_text(d->intent, _("image settings"));
  gtk_combo_box_append_text(d->intent, _("perceptual"));
  gtk_combo_box_append_text(d->intent, _("relative colorimetric"));
  gtk_combo_box_append_text(d->intent, C_("rendering intent", "saturation"));
  gtk_combo_box_append_text(d->intent, _("absolute colorimetric"));
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->intent), 1, 2, 8, 9, GTK_EXPAND|GTK_FILL, 0, 0, 0);

  //  Add profile combo

  d->profiles = NULL;

  dt_lib_export_profile_t *prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
  g_strlcpy(prof->filename, "sRGB", sizeof(prof->filename));
  g_strlcpy(prof->name, _("sRGB (web-safe)"), sizeof(prof->name));
  int pos;
  prof->pos = 1;
  d->profiles = g_list_append(d->profiles, prof);

  prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
  g_strlcpy(prof->filename, "adobergb", sizeof(prof->filename));
  g_strlcpy(prof->name, _("Adobe RGB"), sizeof(prof->name));
  prof->pos = 2;
  d->profiles = g_list_append(d->profiles, prof);

  prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
  g_strlcpy(prof->filename, "X profile", sizeof(prof->filename));
  g_strlcpy(prof->name, "X profile", sizeof(prof->name));
  prof->pos = 3;
  d->profiles = g_list_append(d->profiles, prof);

  prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
  g_strlcpy(prof->filename, "linear_rgb", sizeof(prof->filename));
  g_strlcpy(prof->name, _("linear RGB"), sizeof(prof->name));
  pos = prof->pos = 4;
  d->profiles = g_list_append(d->profiles, prof);

  // read datadir/color/out/*.icc
  char datadir[DT_MAX_PATH_LEN];
  char confdir[DT_MAX_PATH_LEN];
  char dirname[DT_MAX_PATH_LEN];
  char filename[DT_MAX_PATH_LEN];
  dt_loc_get_user_config_dir(confdir, DT_MAX_PATH_LEN);
  dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN);
  cmsHPROFILE tmpprof;
  const gchar *d_name;
  snprintf(dirname, DT_MAX_PATH_LEN, "%s/color/out", confdir);
  if(!g_file_test(dirname, G_FILE_TEST_IS_DIR))
    snprintf(dirname, DT_MAX_PATH_LEN, "%s/color/out", datadir);
  GDir *dir = g_dir_open(dirname, 0, NULL);
  if(dir)
  {
    while((d_name = g_dir_read_name(dir)))
    {
      snprintf(filename, DT_MAX_PATH_LEN, "%s/%s", dirname, d_name);
      tmpprof = cmsOpenProfileFromFile(filename, "r");
      if(tmpprof)
      {
        char *lang = getenv("LANG");
        if (!lang) lang = "en_US";

        dt_lib_export_profile_t *prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
        char name[1024];
        cmsGetProfileInfoASCII(tmpprof, cmsInfoDescription, lang, lang+3, name, 1024);
        g_strlcpy(prof->name, name, sizeof(prof->name));
        g_strlcpy(prof->filename, d_name, sizeof(prof->filename));
        prof->pos = ++pos;
        cmsCloseProfile(tmpprof);
        d->profiles = g_list_append(d->profiles, prof);
      }
    }
    g_dir_close(dir);
  }
  GList *l = d->profiles;
  label = gtk_label_new(_("profile"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 1, 9, 10, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  d->profile = GTK_COMBO_BOX(gtk_combo_box_new_text());
  dt_ellipsize_combo(d->profile);
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->profile), 1, 2, 9, 10, GTK_SHRINK|GTK_EXPAND|GTK_FILL, 0, 0, 0);
  // gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->profile), 1, 2, 9, 10, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  gtk_combo_box_append_text(d->profile, _("image settings"));
  while(l)
  {
    dt_lib_export_profile_t *prof = (dt_lib_export_profile_t *)l->data;
    if(!strcmp(prof->name, "X profile"))
      gtk_combo_box_append_text(d->profile, _("system display profile"));
    else
      gtk_combo_box_append_text(d->profile, prof->name);
    l = g_list_next(l);
  }

  gtk_combo_box_set_active(d->profile, 0);
  char tooltip[1024];
  snprintf(tooltip, 1024, _("output icc profiles in %s/color/out or %s/color/out"), confdir, datadir);
  g_object_set(G_OBJECT(d->profile), "tooltip-text", tooltip, (char *)NULL);


  //  Add style combo

  label = gtk_label_new(_("style"));
  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  gtk_table_attach(GTK_TABLE(self->widget), label, 0, 1, 10, 11, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  d->style = GTK_COMBO_BOX(gtk_combo_box_new_text());

  dt_ellipsize_combo(d->style);

  gtk_combo_box_append_text(d->style, _("none"));

  GList *styles = dt_styles_get_list("");
  while (styles)
  {
    dt_style_t *style=(dt_style_t *)styles->data;
    gtk_combo_box_append_text(d->style, style->name);
    styles=g_list_next(styles);
  }
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(d->style), 1, 2, 10, 11, GTK_EXPAND|GTK_FILL, 0, 0, 0);
  g_object_set(G_OBJECT(d->style), "tooltip-text", _("temporary style to append while exporting"), (char *)NULL);

  //  Set callback signals

  g_signal_connect (G_OBJECT (d->intent), "changed",
                    G_CALLBACK (intent_changed),
                    (gpointer)d);
  g_signal_connect (G_OBJECT (d->profile), "changed",
                    G_CALLBACK (profile_changed),
                    (gpointer)d);
  g_signal_connect (G_OBJECT (d->style), "changed",
                    G_CALLBACK (style_changed),
                    (gpointer)d);

  // Export button

  GtkButton *button = GTK_BUTTON(gtk_button_new_with_label(_("export")));
  d->export_button = button;
  g_object_set(G_OBJECT(button), "tooltip-text", _("export with current settings (ctrl-e)"), (char *)NULL);
  gtk_table_attach(GTK_TABLE(self->widget), GTK_WIDGET(button), 1, 2, 11, 12, GTK_EXPAND|GTK_FILL, 0, 0, 0);

  g_signal_connect (G_OBJECT (button), "clicked",
                    G_CALLBACK (export_button_clicked),
                    (gpointer)self);
  g_signal_connect (G_OBJECT (d->width), "value-changed",
                    G_CALLBACK (width_changed),
                    (gpointer)0);
  g_signal_connect (G_OBJECT (d->height), "value-changed",
                    G_CALLBACK (height_changed),
                    (gpointer)0);

  self->gui_reset(self);
}
示例#29
0
int dt_init(int argc, char *argv[], const int init_gui)
{
  // make everything go a lot faster.
  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
#ifndef __APPLE__
  _dt_sigsegv_old_handler = signal(SIGSEGV,&_dt_sigsegv_handler);
#endif

#ifndef __SSE2__
  fprintf(stderr, "[dt_init] unfortunately we depend on SSE2 instructions at this time.\n");
  fprintf(stderr, "[dt_init] please contribute a backport patch (or buy a newer processor).\n");
  return 1;
#endif

#ifdef M_MMAP_THRESHOLD
  mallopt(M_MMAP_THRESHOLD,128*1024) ; /* use mmap() for large allocations */
#endif

  bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);


  // init all pointers to 0:
  memset(&darktable, 0, sizeof(darktable_t));

  darktable.progname = argv[0];

  // database
  gchar *dbfilename_from_command = NULL;
  char *datadir_from_command = NULL;
  char *moduledir_from_command = NULL;
  char *tmpdir_from_command = NULL;
  char *configdir_from_command = NULL;
  char *cachedir_from_command = NULL;

  darktable.num_openmp_threads = 1;
#ifdef _OPENMP
  darktable.num_openmp_threads = omp_get_num_procs();
#endif
  darktable.unmuted = 0;
  GSList *images_to_load = NULL;
  for(int k=1; k<argc; k++)
  {
    if(argv[k][0] == '-')
    {
      if(!strcmp(argv[k], "--help"))
      {
        return usage(argv[0]);
      }
      if(!strcmp(argv[k], "-h"))
      {
        return usage(argv[0]);
      }
      else if(!strcmp(argv[k], "--version"))
      {
        printf("this is "PACKAGE_STRING"\ncopyright (c) 2009-2013 johannes hanika\n"PACKAGE_BUGREPORT"\n");
        return 1;
      }
      else if(!strcmp(argv[k], "--library"))
      {
        dbfilename_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--datadir"))
      {
        datadir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--moduledir"))
      {
        moduledir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--tmpdir"))
      {
        tmpdir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--configdir"))
      {
        configdir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--cachedir"))
      {
        cachedir_from_command = argv[++k];
      }
      else if(!strcmp(argv[k], "--localedir"))
      {
        bindtextdomain (GETTEXT_PACKAGE, argv[++k]);
      }
      else if(argv[k][1] == 'd' && argc > k+1)
      {
        if(!strcmp(argv[k+1], "all"))             darktable.unmuted = 0xffffffff;   // enable all debug information
        else if(!strcmp(argv[k+1], "cache"))      darktable.unmuted |= DT_DEBUG_CACHE;   // enable debugging for lib/film/cache module
        else if(!strcmp(argv[k+1], "control"))    darktable.unmuted |= DT_DEBUG_CONTROL; // enable debugging for scheduler module
        else if(!strcmp(argv[k+1], "dev"))        darktable.unmuted |= DT_DEBUG_DEV; // develop module
        else if(!strcmp(argv[k+1], "fswatch"))    darktable.unmuted |= DT_DEBUG_FSWATCH; // fswatch module
        else if(!strcmp(argv[k+1], "camctl"))     darktable.unmuted |= DT_DEBUG_CAMCTL; // camera control module
        else if(!strcmp(argv[k+1], "perf"))       darktable.unmuted |= DT_DEBUG_PERF; // performance measurements
        else if(!strcmp(argv[k+1], "pwstorage"))  darktable.unmuted |= DT_DEBUG_PWSTORAGE; // pwstorage module
        else if(!strcmp(argv[k+1], "opencl"))     darktable.unmuted |= DT_DEBUG_OPENCL;    // gpu accel via opencl
        else if(!strcmp(argv[k+1], "sql"))        darktable.unmuted |= DT_DEBUG_SQL; // SQLite3 queries
        else if(!strcmp(argv[k+1], "memory"))     darktable.unmuted |= DT_DEBUG_MEMORY; // some stats on mem usage now and then.
        else if(!strcmp(argv[k+1], "lighttable")) darktable.unmuted |= DT_DEBUG_LIGHTTABLE; // lighttable related stuff.
        else if(!strcmp(argv[k+1], "nan"))        darktable.unmuted |= DT_DEBUG_NAN; // check for NANs when processing the pipe.
        else return usage(argv[0]);
        k ++;
      }
      else if(argv[k][1] == 't' && argc > k+1)
      {
        darktable.num_openmp_threads = CLAMP(atol(argv[k+1]), 1, 100);
        printf("[dt_init] using %d threads for openmp parallel sections\n", darktable.num_openmp_threads);
        k ++;
      }
    }
#ifndef MAC_INTEGRATION
    else
    {
      images_to_load = g_slist_append(images_to_load, argv[k]);
    }
#endif
  }

  if(darktable.unmuted & DT_DEBUG_MEMORY)
  {
    fprintf(stderr, "[memory] at startup\n");
    dt_print_mem_usage();
  }

#ifdef _OPENMP
  omp_set_num_threads(darktable.num_openmp_threads);
#endif
  dt_loc_init_datadir(datadir_from_command);
  dt_loc_init_plugindir(moduledir_from_command);
  if(dt_loc_init_tmp_dir(tmpdir_from_command))
  {
    printf(_("ERROR : invalid temporary directory : %s\n"),darktable.tmpdir);
    return usage(argv[0]);
  }
  dt_loc_init_user_config_dir(configdir_from_command);
  dt_loc_init_user_cache_dir(cachedir_from_command);

#if !GLIB_CHECK_VERSION(2, 35, 0)
  g_type_init();
#endif

  // does not work, as gtk is not inited yet.
  // even if it were, it's a super bad idea to invoke gtk stuff from
  // a signal handler.
  /* check cput caps */
  // dt_check_cpu(argc,argv);

#ifdef HAVE_GEGL
  char geglpath[DT_MAX_PATH_LEN];
  char datadir[DT_MAX_PATH_LEN];
  dt_loc_get_datadir(datadir, DT_MAX_PATH_LEN);
  snprintf(geglpath, DT_MAX_PATH_LEN, "%s/gegl:/usr/lib/gegl-0.0", datadir);
  (void)setenv("GEGL_PATH", geglpath, 1);
  gegl_init(&argc, &argv);
#endif

  // thread-safe init:
  dt_exif_init();
  char datadir[DT_MAX_PATH_LEN];
  dt_loc_get_user_config_dir (datadir,DT_MAX_PATH_LEN);
  char filename[DT_MAX_PATH_LEN];
  snprintf(filename, DT_MAX_PATH_LEN, "%s/darktablerc", datadir);

  // intialize the config backend. this needs to be done first...
  darktable.conf = (dt_conf_t *)malloc(sizeof(dt_conf_t));
  memset(darktable.conf, 0, sizeof(dt_conf_t));
  dt_conf_init(darktable.conf, filename);

  // set the interface language
  const gchar* lang = dt_conf_get_string("ui_last/gui_language");
  if(lang != NULL && lang[0] != '\0')
  {
    if(setlocale(LC_ALL, lang) != NULL)
      gtk_disable_setlocale();
  }

  // initialize the database
  darktable.db = dt_database_init(dbfilename_from_command);
  if(darktable.db == NULL)
  {
    printf("ERROR : cannot open database\n");
    return 1;
  }
  else if(dt_database_get_already_locked(darktable.db))
  {
    // send the images to the other instance via dbus
    if(images_to_load)
    {
      GSList *p = images_to_load;

      // get a connection!
      GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SESSION,NULL, NULL);

      while (p != NULL)
      {
        // make the filename absolute ...
        gchar *filename = dt_make_path_absolute((gchar*)p->data);
        if(filename == NULL) continue;
        // ... and send it to the running instance of darktable
        g_dbus_connection_call_sync(connection,
                                    "org.darktable.service",
                                    "/darktable",
                                    "org.darktable.service.Remote",
                                    "Open",
                                    g_variant_new ("(s)", filename),
                                    NULL,
                                    G_DBUS_CALL_FLAGS_NONE,
                                    -1,
                                    NULL,
                                    NULL);
        p = g_slist_next(p);
        g_free(filename);
      }

      g_slist_free(images_to_load);
      g_object_unref(connection);
    }

    return 1;
  }

  // Initialize the signal system
  darktable.signals = dt_control_signal_init();

  // Initialize the filesystem watcher
  darktable.fswatch=dt_fswatch_new();

#ifdef HAVE_GPHOTO2
  // Initialize the camera control
  darktable.camctl=dt_camctl_new();
#endif

  // get max lighttable thumbnail size:
  darktable.thumbnail_width  = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_width"),  200, 3000);
  darktable.thumbnail_height = CLAMPS(dt_conf_get_int("plugins/lighttable/thumbnail_height"), 200, 3000);
  // and make sure it can be mip-mapped all the way from mip4 to mip0
  darktable.thumbnail_width  /= 16;
  darktable.thumbnail_width  *= 16;
  darktable.thumbnail_height /= 16;
  darktable.thumbnail_height *= 16;

  // Initialize the password storage engine
  darktable.pwstorage=dt_pwstorage_new();

  // FIXME: move there into dt_database_t
  dt_pthread_mutex_init(&(darktable.db_insert), NULL);
  dt_pthread_mutex_init(&(darktable.plugin_threadsafe), NULL);
  dt_pthread_mutex_init(&(darktable.capabilities_threadsafe), NULL);
  darktable.control = (dt_control_t *)malloc(sizeof(dt_control_t));
  memset(darktable.control, 0, sizeof(dt_control_t));
  if(init_gui)
  {
    dt_control_init(darktable.control);
  }
  else
  {
    // this is in memory, so schema can't exist yet.
    if(dbfilename_from_command && !strcmp(dbfilename_from_command, ":memory:"))
    {
      dt_control_create_database_schema();
      dt_gui_presets_init(); // also init preset db schema.
    }
    darktable.control->running = 0;
    darktable.control->accelerators = NULL;
    dt_pthread_mutex_init(&darktable.control->run_mutex, NULL);
  }

  // initialize collection query
  darktable.collection_listeners = NULL;
  darktable.collection = dt_collection_new(NULL);

  /* initialize sellection */
  darktable.selection = dt_selection_new();

  /* capabilities set to NULL */
  darktable.capabilities = NULL;

#ifdef HAVE_GRAPHICSMAGICK
  /* GraphicsMagick init */
  InitializeMagick(darktable.progname);
#endif

  darktable.opencl = (dt_opencl_t *)malloc(sizeof(dt_opencl_t));
  memset(darktable.opencl, 0, sizeof(dt_opencl_t));
  dt_opencl_init(darktable.opencl, argc, argv);

  darktable.blendop = (dt_blendop_t *)malloc(sizeof(dt_blendop_t));
  memset(darktable.blendop, 0, sizeof(dt_blendop_t));
  dt_develop_blend_init(darktable.blendop);

  darktable.points = (dt_points_t *)malloc(sizeof(dt_points_t));
  memset(darktable.points, 0, sizeof(dt_points_t));
  dt_points_init(darktable.points, dt_get_num_threads());

  // must come before mipmap_cache, because that one will need to access
  // image dimensions stored in here:
  darktable.image_cache = (dt_image_cache_t *)malloc(sizeof(dt_image_cache_t));
  memset(darktable.image_cache, 0, sizeof(dt_image_cache_t));
  dt_image_cache_init(darktable.image_cache);

  darktable.mipmap_cache = (dt_mipmap_cache_t *)malloc(sizeof(dt_mipmap_cache_t));
  memset(darktable.mipmap_cache, 0, sizeof(dt_mipmap_cache_t));
  dt_mipmap_cache_init(darktable.mipmap_cache);

  // The GUI must be initialized before the views, because the init()
  // functions of the views depend on darktable.control->accels_* to register
  // their keyboard accelerators

  if(init_gui)
  {
    darktable.gui = (dt_gui_gtk_t *)malloc(sizeof(dt_gui_gtk_t));
    memset(darktable.gui,0,sizeof(dt_gui_gtk_t));
    if(dt_gui_gtk_init(darktable.gui, argc, argv)) return 1;
    dt_bauhaus_init();
  }
  else darktable.gui = NULL;

  darktable.view_manager = (dt_view_manager_t *)malloc(sizeof(dt_view_manager_t));
  memset(darktable.view_manager, 0, sizeof(dt_view_manager_t));
  dt_view_manager_init(darktable.view_manager);

  // load the darkroom mode plugins once:
  dt_iop_load_modules_so();

  if(init_gui)
  {
    darktable.lib = (dt_lib_t *)malloc(sizeof(dt_lib_t));
    memset(darktable.lib, 0, sizeof(dt_lib_t));
    dt_lib_init(darktable.lib);

    dt_control_load_config(darktable.control);
    g_strlcpy(darktable.control->global_settings.dbname, filename, 512); // overwrite if relocated.
  }
  darktable.imageio = (dt_imageio_t *)malloc(sizeof(dt_imageio_t));
  memset(darktable.imageio, 0, sizeof(dt_imageio_t));
  dt_imageio_init(darktable.imageio);

  if(init_gui)
  {
    // Loading the keybindings
    char keyfile[DT_MAX_PATH_LEN];

    // First dump the default keymapping
    snprintf(keyfile, DT_MAX_PATH_LEN, "%s/keyboardrc_default", datadir);
    gtk_accel_map_save(keyfile);

    // Removing extraneous semi-colons from the default keymap
    strip_semicolons_from_keymap(keyfile);

    // Then load any modified keys if available
    snprintf(keyfile, DT_MAX_PATH_LEN, "%s/keyboardrc", datadir);
    if(g_file_test(keyfile, G_FILE_TEST_EXISTS))
      gtk_accel_map_load(keyfile);
    else
      gtk_accel_map_save(keyfile); // Save the default keymap if none is present

    // I doubt that connecting to dbus for darktable-cli makes sense
    darktable.dbus = dt_dbus_init();

    // initialize undo struct
    darktable.undo = dt_undo_init();

    // load image(s) specified on cmdline
    int id = 0;
    if(images_to_load)
    {
      // If only one image is listed, attempt to load it in darkroom
      gboolean load_in_dr = (g_slist_next(images_to_load) == NULL);
      GSList *p = images_to_load;

      while (p != NULL)
      {
        // don't put these function calls into MAX(), the macro will evaluate
        // it twice (and happily deadlock, in this particular case)
        int newid = dt_load_from_string((gchar*)p->data, load_in_dr);
        id = MAX(id, newid);
        p = g_slist_next(p);
      }

      if (!load_in_dr || id == 0)
        dt_ctl_switch_mode_to(DT_LIBRARY);

      g_slist_free(images_to_load);
    }
    else
      dt_ctl_switch_mode_to(DT_LIBRARY);
  }

  /* start the indexer background job */
  dt_control_start_indexer();

  if(darktable.unmuted & DT_DEBUG_MEMORY)
  {
    fprintf(stderr, "[memory] after successful startup\n");
    dt_print_mem_usage();
  }

  return 0;
}