dt_job_t *dt_control_job_create(dt_job_execute_callback execute, const char *msg, ...) { _dt_job_t *job = (_dt_job_t *)calloc(1, sizeof(_dt_job_t)); if(!job) return NULL; va_list ap; va_start(ap, msg); vsnprintf(job->description, DT_CONTROL_DESCRIPTION_LEN, msg, ap); va_end(ap); job->execute = execute; job->state = DT_JOB_STATE_INITIALIZED; dt_pthread_mutex_init(&job->state_mutex, NULL); dt_pthread_mutex_init(&job->wait_mutex, NULL); return job; }
void dt_control_init(dt_control_t *s) { memset(s->vimkey, 0, sizeof(s->vimkey)); s->vimkey_cnt = 0; // same thread as init s->gui_thread = pthread_self(); // s->last_expose_time = dt_get_wtime(); s->key_accelerators_on = 1; s->log_pos = s->log_ack = 0; s->log_busy = 0; s->log_message_timeout_id = 0; dt_pthread_mutex_init(&(s->log_mutex), NULL); pthread_cond_init(&s->cond, NULL); dt_pthread_mutex_init(&s->cond_mutex, NULL); dt_pthread_mutex_init(&s->queue_mutex, NULL); dt_pthread_mutex_init(&s->res_mutex, NULL); dt_pthread_mutex_init(&s->run_mutex, NULL); dt_pthread_mutex_init(&(s->global_mutex), NULL); dt_pthread_mutex_init(&(s->progress_system.mutex), NULL); // start threads dt_control_jobs_init(s); s->button_down = 0; s->button_down_which = 0; s->mouse_over_id = -1; s->dev_closeup = 0; s->dev_zoom_x = 0; s->dev_zoom_y = 0; s->dev_zoom = DT_ZOOM_FIT; }
void dt_film_init(dt_film_t *film) { dt_pthread_mutex_init(&film->images_mutex, NULL); film->last_loaded = film->num_images = 0; film->dirname[0] = '\0'; film->dir = NULL; film->id = -1; film->ref = 0; }
void dt_lua_init_lock() { pthread_mutexattr_t a; pthread_mutexattr_init(&a); pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE); dt_pthread_mutex_init(&darktable.lua_state.mutex, &a); pthread_mutexattr_destroy(&a); // we want our lock initialized locked dt_pthread_mutex_lock(&darktable.lua_state.mutex); }
void gui_init(struct dt_iop_module_t *self) { self->gui_data = malloc(sizeof(dt_iop_zonesystem_gui_data_t)); dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; g->in_preview_buffer = g->out_preview_buffer = NULL; g->is_dragging = FALSE; g->hilite_zone = FALSE; g->preview_width = g->preview_height = 0; g->mouse_over_output_zones = FALSE; dt_pthread_mutex_init(&g->lock, NULL); self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_IOP_MODULE_CONTROL_SPACING); g->preview = dtgtk_drawing_area_new_with_aspect_ratio(1.0); g_signal_connect(G_OBJECT(g->preview), "size-allocate", G_CALLBACK(size_allocate_callback), self); g_signal_connect(G_OBJECT(g->preview), "draw", G_CALLBACK(dt_iop_zonesystem_preview_draw), self); gtk_widget_add_events(GTK_WIDGET(g->preview), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK); /* create the zonesystem bar widget */ g->zones = gtk_drawing_area_new(); gtk_widget_set_tooltip_text(g->zones, _("lightness zones\nuse mouse scrollwheel to change the number of zones\n" "left-click on a border to create a marker\n" "right-click on a marker to delete it")); g_signal_connect(G_OBJECT(g->zones), "draw", G_CALLBACK(dt_iop_zonesystem_bar_draw), self); g_signal_connect(G_OBJECT(g->zones), "motion-notify-event", G_CALLBACK(dt_iop_zonesystem_bar_motion_notify), self); g_signal_connect(G_OBJECT(g->zones), "leave-notify-event", G_CALLBACK(dt_iop_zonesystem_bar_leave_notify), self); g_signal_connect(G_OBJECT(g->zones), "button-press-event", G_CALLBACK(dt_iop_zonesystem_bar_button_press), self); g_signal_connect(G_OBJECT(g->zones), "button-release-event", G_CALLBACK(dt_iop_zonesystem_bar_button_release), self); g_signal_connect(G_OBJECT(g->zones), "scroll-event", G_CALLBACK(dt_iop_zonesystem_bar_scrolled), self); gtk_widget_add_events(GTK_WIDGET(g->zones), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK); gtk_widget_set_size_request(g->zones, -1, DT_PIXEL_APPLY_DPI(40)); gtk_box_pack_start(GTK_BOX(self->widget), g->preview, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(self->widget), g->zones, TRUE, TRUE, 0); /* add signal handler for preview pipe finish to redraw the preview */ dt_control_signal_connect(darktable.signals, DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED, G_CALLBACK(_iop_zonesystem_redraw_preview_callback), self); g->image = NULL; g->image_buffer = NULL; g->image_width = 0; g->image_height = 0; }
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached) { memset(dev,0,sizeof(dt_develop_t)); dev->preview_downsampling = 1.0f; dev->gui_module = NULL; dev->timestamp = 0; dev->average_delay = DT_DEV_AVERAGE_DELAY_START; dev->preview_average_delay = DT_DEV_PREVIEW_AVERAGE_DELAY_START; dev->gui_leaving = 0; dev->gui_synch = 0; dt_pthread_mutex_init(&dev->history_mutex, NULL); dev->history_end = 0; dev->history = NULL; // empty list dev->gui_attached = gui_attached; dev->width = -1; dev->height = -1; dt_image_init(&dev->image_storage); dev->image_dirty = dev->preview_dirty = 1; dev->image_loading = dev->preview_loading = 0; dev->image_force_reload = 0; dev->preview_input_changed = 0; dev->pipe = dev->preview_pipe = NULL; dev->histogram = NULL; dev->histogram_pre_tonecurve = NULL; dev->histogram_pre_levels = NULL; if(g_strcmp0(dt_conf_get_string("plugins/darkroom/histogram/mode"), "linear") == 0) dev->histogram_linear = TRUE; else dev->histogram_linear = FALSE; if(dev->gui_attached) { dev->pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dev->preview_pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dt_dev_pixelpipe_init(dev->pipe); dt_dev_pixelpipe_init_preview(dev->preview_pipe); dev->histogram = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_tonecurve = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_levels = (float*)malloc(sizeof(float) * 4 * 256); memset(dev->histogram, 0, sizeof(float)*256*4); memset(dev->histogram_pre_tonecurve, 0, sizeof(float)*256*4); memset(dev->histogram_pre_levels, 0, sizeof(float)*256*4); dev->histogram_max = -1; dev->histogram_pre_tonecurve_max = -1; dev->histogram_pre_levels_max = -1; } dev->iop_instance = 0; dev->iop = NULL; }
gboolean _camera_initialize(const dt_camctl_t *c, dt_camera_t *cam) { dt_camctl_t *camctl=(dt_camctl_t *)c; CameraAbilities a; GPPortInfo pi; if( cam->gpcam==NULL ) { gp_camera_new(&cam->gpcam); int m = gp_abilities_list_lookup_model( c->gpcams, cam->model ); gp_abilities_list_get_abilities (c->gpcams, m, &a); gp_camera_set_abilities (cam->gpcam, a); int p = gp_port_info_list_lookup_path (c->gpports, cam->port); gp_port_info_list_get_info (c->gpports, p, &pi); gp_camera_set_port_info (cam->gpcam , pi); // Check for abilities if( (a.operations&GP_OPERATION_CAPTURE_IMAGE) ) cam->can_tether=TRUE; if( (a.operations&GP_OPERATION_CAPTURE_PREVIEW) ) cam->can_live_view=TRUE; if( cam->can_tether && (a.operations&GP_OPERATION_CONFIG) ) cam->can_config=TRUE; if( !(a.file_operations&GP_FILE_OPERATION_NONE) ) cam->can_import=TRUE; if( gp_camera_init( cam->gpcam , camctl->gpcontext) != GP_OK ) { dt_print(DT_DEBUG_CAMCTL,"[camera_control] failed to initialize camera %s on port %s\n", cam->model,cam->port); return FALSE; } // read a full copy of config to configuration cache gp_camera_get_config( cam->gpcam, &cam->configuration, c->gpcontext ); // TODO: find a more robust way for this, once we find out how to do it with non-EOS cameras if(cam->can_live_view && dt_camctl_camera_property_exists(camctl, cam, "eoszoomposition")) cam->can_live_view_advanced = TRUE; // initialize timeout callbacks eg. keep alive, some cameras needs it. cam->gpcontext = camctl->gpcontext; gp_camera_set_timeout_funcs(cam->gpcam, (CameraTimeoutStartFunc)_camera_start_timeout_func, (CameraTimeoutStopFunc)_camera_stop_timeout_func, cam); dt_pthread_mutex_init(&cam->jobqueue_lock, NULL); dt_print(DT_DEBUG_CAMCTL,"[camera_control] device %s on port %s initialized\n", cam->model,cam->port); } else dt_print(DT_DEBUG_CAMCTL,"[camera_control] device %s on port %s already initialized\n", cam->model,cam->port); return TRUE; }
void gui_init(struct dt_iop_module_t *self) { self->gui_data = malloc(sizeof(dt_iop_zonesystem_gui_data_t)); dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; g->in_preview_buffer = g->out_preview_buffer = NULL; g->is_dragging = FALSE; g->hilite_zone = FALSE; g->preview_width=g->preview_height = 0; g->mouse_over_output_zones = FALSE; dt_pthread_mutex_init(&g->lock, NULL); self->widget = gtk_vbox_new (FALSE,DT_GUI_IOP_MODULE_CONTROL_SPACING); /* create the zone preview widget */ const int _p_w = dt_conf_get_int("panel_width"); const int panel_width = MAX(-1, MIN(500, _p_w)); g->preview = gtk_drawing_area_new(); g_signal_connect (G_OBJECT (g->preview), "expose-event", G_CALLBACK (dt_iop_zonesystem_preview_expose), self); gtk_widget_add_events (GTK_WIDGET (g->preview), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_size_request(g->preview, panel_width * 0.8, panel_width * 0.8); /* create the zonesystem bar widget */ g->zones = gtk_drawing_area_new(); g_object_set (GTK_OBJECT(g->zones), "tooltip-text", _("lightness zones\nuse mouse scrollwheel to change the number of zones\nleft-click on a border to create a marker\nright-click on a marker to delete it"), (char *)NULL); g_signal_connect (G_OBJECT (g->zones), "expose-event", G_CALLBACK (dt_iop_zonesystem_bar_expose), self); g_signal_connect (G_OBJECT (g->zones), "motion-notify-event", G_CALLBACK (dt_iop_zonesystem_bar_motion_notify), self); g_signal_connect (G_OBJECT (g->zones), "leave-notify-event", G_CALLBACK (dt_iop_zonesystem_bar_leave_notify), self); g_signal_connect (G_OBJECT (g->zones), "button-press-event", G_CALLBACK (dt_iop_zonesystem_bar_button_press), self); g_signal_connect (G_OBJECT (g->zones), "button-release-event", G_CALLBACK (dt_iop_zonesystem_bar_button_release), self); g_signal_connect (G_OBJECT (g->zones), "scroll-event", G_CALLBACK (dt_iop_zonesystem_bar_scrolled), self); gtk_widget_add_events (GTK_WIDGET (g->zones), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_size_request(g->zones, -1, 40); GtkWidget *aspect = gtk_aspect_frame_new(NULL, .5f, .5f, 1.0f, FALSE); gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_NONE); gtk_container_add(GTK_CONTAINER(aspect), g->preview); gtk_box_pack_start (GTK_BOX (self->widget),aspect,TRUE,TRUE,0); gtk_box_pack_start (GTK_BOX (self->widget),g->zones,TRUE,TRUE,0); /* add signal handler for preview pipe finish to redraw the preview */ dt_control_signal_connect(darktable.signals, DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED, G_CALLBACK(_iop_zonesystem_redraw_preview_callback), self); }
const dt_fswatch_t* dt_fswatch_new() { dt_fswatch_t *fswatch = g_malloc0(sizeof(dt_fswatch_t)); if((fswatch->inotify_fd=inotify_init())==-1) { g_free(fswatch); return NULL; } fswatch->items=NULL; dt_pthread_mutex_init(&fswatch->mutex, NULL); pthread_create(&fswatch->thread, NULL, &_fswatch_thread, fswatch); dt_print(DT_DEBUG_FSWATCH,"[fswatch_new] Creating new context %p\n", fswatch); return fswatch; }
void gui_init(struct dt_iop_module_t *self) { self->gui_data = malloc(sizeof(dt_iop_global_tonemap_gui_data_t)); dt_iop_global_tonemap_gui_data_t *g = (dt_iop_global_tonemap_gui_data_t *)self->gui_data; dt_iop_global_tonemap_params_t *p = (dt_iop_global_tonemap_params_t *)self->params; dt_pthread_mutex_init(&g->lock, NULL); g->lwmax = NAN; g->hash = 0; self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE); dt_gui_add_help_link(self->widget, dt_get_help_url(self->op)); /* operator */ g->operator= dt_bauhaus_combobox_new(self); dt_bauhaus_widget_set_label(g->operator, NULL, _("operator")); dt_bauhaus_combobox_add(g->operator, "reinhard"); dt_bauhaus_combobox_add(g->operator, "filmic"); dt_bauhaus_combobox_add(g->operator, "drago"); gtk_widget_set_tooltip_text(g->operator, _("the global tonemap operator")); g_signal_connect(G_OBJECT(g->operator), "value-changed", G_CALLBACK(operator_callback), self); gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->operator), TRUE, TRUE, 0); /* drago bias */ g->drago.bias = dt_bauhaus_slider_new_with_range(self, 0.5, 1.0, 0.05, p->drago.bias, 2); dt_bauhaus_widget_set_label(g->drago.bias, NULL, _("bias")); gtk_widget_set_tooltip_text(g->drago.bias, _("the bias for tonemapper controls the linearity, " "the higher the more details in blacks")); g_signal_connect(G_OBJECT(g->drago.bias), "value-changed", G_CALLBACK(_drago_bias_callback), self); gtk_box_pack_start(GTK_BOX(self->widget), g->drago.bias, TRUE, TRUE, 0); /* drago bias */ g->drago.max_light = dt_bauhaus_slider_new_with_range(self, 1, 500, 10, p->drago.max_light, 2); dt_bauhaus_widget_set_label(g->drago.max_light, NULL, _("target")); gtk_widget_set_tooltip_text(g->drago.max_light, _("the target light for tonemapper specified as cd/m2")); g_signal_connect(G_OBJECT(g->drago.max_light), "value-changed", G_CALLBACK(_drago_max_light_callback), self); gtk_box_pack_start(GTK_BOX(self->widget), g->drago.max_light, TRUE, TRUE, 0); /* detail */ g->detail = dt_bauhaus_slider_new_with_range(self, -1.0, 1.0, 0.01, 0.0, 3); gtk_box_pack_start(GTK_BOX(self->widget), g->detail, TRUE, TRUE, 0); dt_bauhaus_widget_set_label(g->detail, NULL, _("detail")); g_signal_connect(G_OBJECT(g->detail), "value-changed", G_CALLBACK(detail_callback), self); }
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached) { memset(dev,0,sizeof(dt_develop_t)); dev->preview_downsampling = 1.0f; dev->gui_module = NULL; dev->timestamp = 0; dev->gui_leaving = 0; dev->gui_synch = 0; dt_pthread_mutex_init(&dev->history_mutex, NULL); dev->history_end = 0; dev->history = NULL; // empty list dev->gui_attached = gui_attached; dev->width = -1; dev->height = -1; dt_image_init(&dev->image_storage); dev->image_dirty = dev->preview_dirty = 1; dev->image_loading = dev->preview_loading = 0; dev->image_force_reload = 0; dev->preview_input_changed = 0; dev->pipe = dev->preview_pipe = NULL; dev->histogram = NULL; dev->histogram_pre_tonecurve = NULL; dev->histogram_pre_levels = NULL; if(dev->gui_attached) { dev->pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dev->preview_pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dt_dev_pixelpipe_init(dev->pipe); dt_dev_pixelpipe_init(dev->preview_pipe); dev->histogram = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_tonecurve = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_levels = (float*)malloc(sizeof(float) * 4 * 256); memset(dev->histogram, 0, sizeof(float)*256*4); memset(dev->histogram_pre_tonecurve, 0, sizeof(float)*256*4); memset(dev->histogram_pre_levels, 0, sizeof(float)*256*4); dev->histogram_max = -1; dev->histogram_pre_tonecurve_max = -1; dev->histogram_pre_levels_max = -1; } dev->iop_instance = 0; dev->iop = NULL; }
void dt_cache_init( dt_cache_t *cache, size_t entry_size, size_t cost_quota) { cache->cost = 0; cache->lru = 0; cache->entry_size = entry_size; cache->cost_quota = cost_quota; dt_pthread_mutex_init(&cache->lock, 0); cache->allocate = 0; cache->allocate_data = 0; cache->cleanup = 0; cache->cleanup_data = 0; cache->hashtable = g_hash_table_new(0, 0); }
dt_progress_t *dt_control_progress_create(dt_control_t *control, gboolean has_progress_bar, const gchar *message) { // create the object _dt_progress_t *progress = (_dt_progress_t *)calloc(1, sizeof(_dt_progress_t)); dt_pthread_mutex_init(&(progress->mutex), NULL); // fill it with values progress->message = g_strdup(message); progress->has_progress_bar = has_progress_bar; dt_pthread_mutex_lock(&control->progress_system.mutex); // add it to the global list control->progress_system.list = g_list_append(control->progress_system.list, progress); control->progress_system.list_length++; // tell the gui if(control->progress_system.proxy.module != NULL) progress->gui_data = control->progress_system.proxy.added(control->progress_system.proxy.module, has_progress_bar, message); dt_pthread_mutex_unlock(&control->progress_system.mutex); #ifdef HAVE_UNITY if(has_progress_bar) { progress->darktable_launcher = unity_launcher_entry_get_for_desktop_id("darktable.desktop"); unity_launcher_entry_set_progress(progress->darktable_launcher, 0.0); unity_launcher_entry_set_progress_visible(progress->darktable_launcher, TRUE); } #endif // return the object return progress; }
void gui_init(struct dt_iop_module_t *self) { self->gui_data = malloc(sizeof(dt_iop_zonesystem_gui_data_t)); dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; g->in_preview_buffer = g->out_preview_buffer = NULL; g->is_dragging = FALSE; g->hilite_zone = FALSE; g->preview_width=g->preview_height = 0; g->mouse_over_output_zones = FALSE; dt_pthread_mutex_init(&g->lock, NULL); self->widget = gtk_vbox_new (FALSE,DT_GUI_IOP_MODULE_CONTROL_SPACING); /* create the zone preview widget */ const int panel_width = dt_conf_get_int("panel_width") * 0.8; g->preview = gtk_drawing_area_new(); g_signal_connect (G_OBJECT (g->preview), "expose-event", G_CALLBACK (dt_iop_zonesystem_preview_expose), self); gtk_widget_add_events (GTK_WIDGET (g->preview), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_size_request(g->preview, panel_width, panel_width); /* create the zonesystem bar widget */ g->zones = gtk_drawing_area_new(); g_object_set (GTK_OBJECT(g->zones), "tooltip-text", _("lightness zones\nuse mouse scrollwheel to change the number of zones\nleft-click on a border to create a marker\nright-click on a marker to delete it"), (char *)NULL); g_signal_connect (G_OBJECT (g->zones), "expose-event", G_CALLBACK (dt_iop_zonesystem_bar_expose), self); g_signal_connect (G_OBJECT (g->zones), "motion-notify-event", G_CALLBACK (dt_iop_zonesystem_bar_motion_notify), self); g_signal_connect (G_OBJECT (g->zones), "leave-notify-event", G_CALLBACK (dt_iop_zonesystem_bar_leave_notify), self); g_signal_connect (G_OBJECT (g->zones), "button-press-event", G_CALLBACK (dt_iop_zonesystem_bar_button_press), self); g_signal_connect (G_OBJECT (g->zones), "button-release-event", G_CALLBACK (dt_iop_zonesystem_bar_button_release), self); g_signal_connect (G_OBJECT (g->zones), "scroll-event", G_CALLBACK (dt_iop_zonesystem_bar_scrolled), self); gtk_widget_add_events (GTK_WIDGET (g->zones), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_size_request(g->zones, -1, DT_PIXEL_APPLY_DPI(40)); gtk_box_pack_start (GTK_BOX (self->widget),g->preview,TRUE,TRUE,0); gtk_box_pack_start (GTK_BOX (self->widget),g->zones,TRUE,TRUE,0); /* add signal handler for preview pipe finish to redraw the preview */ dt_control_signal_connect(darktable.signals, DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED, G_CALLBACK(_iop_zonesystem_redraw_preview_callback), self); /* load the dt logo as a brackground */ g->image = NULL; g->image_buffer = NULL; g->image_width = 0; g->image_height = 0; char filename[PATH_MAX]; char datadir[PATH_MAX]; const char *logo = is_it_xmas()?"%s/pixmaps/idbutton-2.svg":"%s/pixmaps/idbutton.svg"; dt_loc_get_datadir(datadir, sizeof(datadir)); snprintf(filename, sizeof(filename), logo, datadir); RsvgHandle *svg = rsvg_handle_new_from_file(filename, NULL); if(svg) { cairo_surface_t *surface; cairo_t *cr; RsvgDimensionData dimension; rsvg_handle_get_dimensions(svg, &dimension); float svg_size = MAX(dimension.width, dimension.height); float final_size = panel_width * 0.75; float factor = final_size / svg_size; float final_width = dimension.width * factor, final_height = dimension.height * factor; int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, final_width); g->image_buffer = (guint8 *)calloc(stride * final_height, sizeof(guint8)); surface = cairo_image_surface_create_for_data(g->image_buffer, CAIRO_FORMAT_ARGB32, final_width, final_height, stride); if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { free(g->image_buffer); g->image_buffer = NULL; } else { cr = cairo_create(surface); cairo_scale(cr, factor, factor); rsvg_handle_render_cairo(svg, cr); cairo_surface_flush(surface); g->image = surface; g->image_width = final_width; g->image_height = final_height; } g_object_unref(svg); } }
void gui_init(struct dt_iop_module_t *self) { self->gui_data = malloc(sizeof(dt_iop_exposure_gui_data_t)); dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params; g->modes = NULL; g->deflicker_histogram_sources = NULL; g->deflicker_histogram = NULL; dt_pthread_mutex_init(&g->lock, NULL); /* register hooks with current dev so that histogram can interact with this module. */ darktable.develop->proxy.exposure.module = self; darktable.develop->proxy.exposure.set_white = dt_iop_exposure_set_white; darktable.develop->proxy.exposure.get_white = dt_iop_exposure_get_white; darktable.develop->proxy.exposure.set_black = dt_iop_exposure_set_black; darktable.develop->proxy.exposure.get_black = dt_iop_exposure_get_black; self->request_color_pick = DT_REQUEST_COLORPICK_OFF; self->widget = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE)); g->mode = dt_bauhaus_combobox_new(self); dt_bauhaus_widget_set_label(g->mode, NULL, _("mode")); dt_bauhaus_combobox_add(g->mode, C_("mode", "manual")); g->modes = g_list_append(g->modes, GUINT_TO_POINTER(EXPOSURE_MODE_MANUAL)); dt_bauhaus_combobox_add(g->mode, _("automatic")); g->modes = g_list_append(g->modes, GUINT_TO_POINTER(EXPOSURE_MODE_DEFLICKER)); dt_bauhaus_combobox_set_default(g->mode, 0); dt_bauhaus_combobox_set(g->mode, g_list_index(g->modes, GUINT_TO_POINTER(p->mode))); gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->mode), TRUE, TRUE, 0); g->black = dt_bauhaus_slider_new_with_range(self, -0.1, 0.1, .001, p->black, 4); g_object_set(G_OBJECT(g->black), "tooltip-text", _("adjust the black level"), (char *)NULL); dt_bauhaus_slider_set_format(g->black, "%.4f"); dt_bauhaus_widget_set_label(g->black, NULL, _("black")); dt_bauhaus_slider_enable_soft_boundaries(g->black, -1.0, 1.0); gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->black), TRUE, TRUE, 0); g->mode_stack = gtk_stack_new(); gtk_stack_set_homogeneous(GTK_STACK(g->mode_stack),FALSE); gtk_box_pack_start(GTK_BOX(self->widget), g->mode_stack, TRUE, TRUE, 0); GtkWidget *vbox_manual = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE)); g->exposure = dt_bauhaus_slider_new_with_range(self, -3.0, 3.0, .02, p->exposure, 3); g_object_set(G_OBJECT(g->exposure), "tooltip-text", _("adjust the exposure correction"), (char *)NULL); dt_bauhaus_slider_set_format(g->exposure, "%.2fEV"); dt_bauhaus_widget_set_label(g->exposure, NULL, _("exposure")); dt_bauhaus_slider_enable_soft_boundaries(g->exposure, -18.0, 18.0); gtk_box_pack_start(GTK_BOX(vbox_manual), GTK_WIDGET(g->exposure), TRUE, TRUE, 0); GtkBox *hbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); g->autoexp = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("auto"))); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoexp), FALSE); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(g->autoexp), FALSE, TRUE, 0); g->autoexpp = dt_bauhaus_slider_new_with_range(self, 0.0, 0.2, .001, 0.01, 3); g_object_set(G_OBJECT(g->autoexpp), "tooltip-text", _("percentage of bright values clipped out"), (char *)NULL); gtk_widget_set_sensitive(GTK_WIDGET(g->autoexpp), TRUE); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(g->autoexpp), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox_manual), GTK_WIDGET(hbox), TRUE, TRUE, 0); gtk_widget_show_all(vbox_manual); gtk_stack_add_named(GTK_STACK(g->mode_stack), vbox_manual, "manual"); GtkWidget *vbox_deflicker = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE)); g->deflicker_percentile = dt_bauhaus_slider_new_with_range(self, 0, 100, .01, p->deflicker_percentile, 3); // FIXME: this needs a better tooltip! g_object_set(G_OBJECT(g->deflicker_percentile), "tooltip-text", _("percentile"), (char *)NULL); dt_bauhaus_slider_set_format(g->deflicker_percentile, "%.2f%%"); dt_bauhaus_widget_set_label(g->deflicker_percentile, NULL, _("percentile")); gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(g->deflicker_percentile), TRUE, TRUE, 0); g->deflicker_target_level = dt_bauhaus_slider_new_with_range(self, -18.0, 18.0, .01, p->deflicker_target_level, 3); g_object_set(G_OBJECT(g->deflicker_target_level), "tooltip-text", _("target level"), (char *)NULL); dt_bauhaus_slider_set_format(g->deflicker_target_level, "%.2fEV"); dt_bauhaus_widget_set_label(g->deflicker_target_level, NULL, _("target level")); gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(g->deflicker_target_level), TRUE, TRUE, 0); g->deflicker_histogram_source = dt_bauhaus_combobox_new(self); dt_bauhaus_widget_set_label(g->deflicker_histogram_source, NULL, _("histogram of")); dt_bauhaus_combobox_add(g->deflicker_histogram_source, _("pre-processed image")); g->deflicker_histogram_sources = g_list_append(g->deflicker_histogram_sources, GUINT_TO_POINTER(DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL)); dt_bauhaus_combobox_add(g->deflicker_histogram_source, _("source raw data")); g->deflicker_histogram_sources = g_list_append(g->deflicker_histogram_sources, GUINT_TO_POINTER(DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE)); dt_bauhaus_combobox_set_default(g->deflicker_histogram_source, DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL); dt_bauhaus_combobox_set(g->deflicker_histogram_source, g_list_index(g->modes, GUINT_TO_POINTER(p->deflicker_histogram_source))); gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(g->deflicker_histogram_source), TRUE, TRUE, 0); GtkBox *hbox1 = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); GtkLabel *label = GTK_LABEL(gtk_label_new(_("computed EC: "))); gtk_box_pack_start(GTK_BOX(hbox1), GTK_WIDGET(label), FALSE, FALSE, 0); g->deflicker_used_EC = GTK_LABEL(gtk_label_new("")); // This gets filled in by process g_object_set(G_OBJECT(g->deflicker_used_EC), "tooltip-text", _("what exposure correction have actually been used"), (char *)NULL); gtk_box_pack_start(GTK_BOX(hbox1), GTK_WIDGET(g->deflicker_used_EC), FALSE, FALSE, 0); dt_pthread_mutex_lock(&g->lock); g->deflicker_computed_exposure = NAN; dt_pthread_mutex_unlock(&g->lock); gtk_box_pack_start(GTK_BOX(vbox_deflicker), GTK_WIDGET(hbox1), FALSE, FALSE, 0); gtk_widget_show_all(vbox_deflicker); gtk_stack_add_named(GTK_STACK(g->mode_stack), vbox_deflicker, "deflicker"); g_signal_connect(G_OBJECT(g->mode), "value-changed", G_CALLBACK(mode_callback), self); g_signal_connect(G_OBJECT(g->black), "value-changed", G_CALLBACK(black_callback), self); g_signal_connect(G_OBJECT(g->exposure), "value-changed", G_CALLBACK(exposure_callback), self); g_signal_connect(G_OBJECT(g->autoexpp), "value-changed", G_CALLBACK(autoexpp_callback), self); g_signal_connect(G_OBJECT(g->autoexp), "toggled", G_CALLBACK(autoexp_callback), self); g_signal_connect(G_OBJECT(g->deflicker_percentile), "value-changed", G_CALLBACK(deflicker_params_callback), self); g_signal_connect(G_OBJECT(g->deflicker_target_level), "value-changed", G_CALLBACK(deflicker_params_callback), self); g_signal_connect(G_OBJECT(g->deflicker_histogram_source), "value-changed", G_CALLBACK(deflicker_histogram_source_callback), self); g_signal_connect(G_OBJECT(self->widget), "draw", G_CALLBACK(draw), self); }
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; }
void dt_camctl_detect_cameras(const dt_camctl_t *c) { dt_camctl_t *camctl=(dt_camctl_t *)c; dt_pthread_mutex_lock(&camctl->lock); /* reload portdrivers */ if (camctl->gpports) gp_port_info_list_free (camctl->gpports); gp_port_info_list_new( &camctl->gpports ); gp_port_info_list_load( camctl->gpports ); dt_print(DT_DEBUG_CAMCTL,"[camera_control] loaded %d port drivers.\n", gp_port_info_list_count( camctl->gpports ) ); CameraList *available_cameras=NULL; gp_list_new( &available_cameras ); gp_abilities_list_detect (c->gpcams,c->gpports, available_cameras, c->gpcontext ); dt_print(DT_DEBUG_CAMCTL,"[camera_control] %d cameras connected\n",gp_list_count( available_cameras )>0?gp_list_count( available_cameras ):0); for(int i=0; i<gp_list_count( available_cameras ); i++) { dt_camera_t *camera=g_malloc(sizeof(dt_camera_t)); memset( camera,0,sizeof(dt_camera_t)); gp_list_get_name (available_cameras, i, &camera->model); gp_list_get_value (available_cameras, i, &camera->port); dt_pthread_mutex_init(&camera->config_lock, NULL); dt_pthread_mutex_init(&camera->live_view_pixbuf_mutex, NULL); dt_pthread_mutex_init(&camera->live_view_synch, NULL); // if(strcmp(camera->port,"usb:")==0) { g_free(camera); continue; } GList *citem; if( (citem=g_list_find_custom(c->cameras,camera,_compare_camera_by_port)) == NULL || strcmp(((dt_camera_t *)citem->data)->model,camera->model)!=0 ) { if(citem==NULL) { // Newly connected camera if(_camera_initialize(c,camera)==FALSE) { dt_print(DT_DEBUG_CAMCTL,"[camera_control] failed to initialize device %s on port %s, probably causes are: locked by another application, no access to udev etc.\n", camera->model,camera->port); g_free(camera); continue; } // Check if camera has capabililties for being presented to darktable if( camera->can_import==FALSE && camera->can_tether==FALSE ) { dt_print(DT_DEBUG_CAMCTL,"[camera_control] device %s on port %s doesn't support import or tether, skipping device.\n", camera->model,camera->port); g_free(camera); continue; } // Fetch some summary of camera if( gp_camera_get_summary(camera->gpcam, &camera->summary, c->gpcontext) == GP_OK ) { // Remove device property summary: char *eos=strstr(camera->summary.text,"Device Property Summary:\n"); if (eos) eos[0]='\0'; } // Add to camera list camctl->cameras = g_list_append(camctl->cameras,camera); // Notify listeners of connected camera _dispatch_camera_connected(camctl,camera); } } else g_free(camera); } /* check c->cameras in available_cameras */ if( c->cameras && g_list_length(c->cameras)>0) { GList *citem = c->cameras; do { int index=0; dt_camera_t *cam=(dt_camera_t *)citem->data; if (gp_list_find_by_name(available_cameras,&index,cam->model)!= GP_OK) { /* remove camera from cached list.. */ dt_camctl_t *camctl=(dt_camctl_t *)c; dt_camera_t *oldcam = (dt_camera_t *)citem->data; camctl->cameras=citem= g_list_delete_link (c->cameras,citem); g_free(oldcam); } } while ( citem && (citem=g_list_next(citem))!=NULL); } dt_pthread_mutex_unlock(&camctl->lock); }
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, <); 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; }
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; }
void gui_init(dt_iop_module_t *self) { // init the slider (more sophisticated layouts are possible with gtk tables and boxes): self->gui_data = malloc(sizeof(dt_iop_bilat_gui_data_t)); dt_iop_bilat_gui_data_t *g = (dt_iop_bilat_gui_data_t *)self->gui_data; memset(&g->ll_boundary, 0, sizeof(local_laplacian_boundary_t)); dt_pthread_mutex_init(&g->lock, NULL); g->hash = 0; self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_BAUHAUS_SPACE); g->mode = dt_bauhaus_combobox_new(self); dt_bauhaus_widget_set_label(g->mode, NULL, _("mode")); gtk_box_pack_start(GTK_BOX(self->widget), g->mode, TRUE, TRUE, 0); dt_bauhaus_combobox_add(g->mode, _("bilateral grid")); dt_bauhaus_combobox_add(g->mode, _("local laplacian filter")); dt_bauhaus_combobox_set_default(g->mode, s_mode_local_laplacian); dt_bauhaus_combobox_set(g->mode, s_mode_local_laplacian); gtk_widget_set_tooltip_text(g->mode, _("the filter used for local contrast enhancement. bilateral is faster but can lead to artifacts around edges for extreme settings.")); g->detail = dt_bauhaus_slider_new_with_range(self, 0.0, 500.0, 1.0, 120.0, 0); gtk_box_pack_start(GTK_BOX(self->widget), g->detail, TRUE, TRUE, 0); dt_bauhaus_widget_set_label(g->detail, NULL, _("detail")); dt_bauhaus_slider_set_format(g->detail, "%.0f%%"); gtk_widget_set_tooltip_text(g->detail, _("changes the local contrast")); g->spatial = dt_bauhaus_slider_new_with_range(self, 1, 100, 1, 50, 0); dt_bauhaus_widget_set_label(g->spatial, NULL, _("coarseness")); gtk_box_pack_start(GTK_BOX(self->widget), g->spatial, TRUE, TRUE, 0); gtk_widget_set_tooltip_text(g->spatial, _("feature size of local details (spatial sigma of bilateral filter)")); g->range = dt_bauhaus_slider_new_with_range(self, 1, 100, 1, 20, 0); gtk_box_pack_start(GTK_BOX(self->widget), g->range, TRUE, TRUE, 0); dt_bauhaus_widget_set_label(g->range, NULL, _("contrast")); gtk_widget_set_tooltip_text(g->range, _("L difference to detect edges (range sigma of bilateral filter)")); g->highlights = dt_bauhaus_slider_new_with_range(self, 0.0, 200.0, 1.0, 100.0, 0); gtk_box_pack_start(GTK_BOX(self->widget), g->highlights, TRUE, TRUE, 0); dt_bauhaus_widget_set_label(g->highlights, NULL, _("highlights")); dt_bauhaus_slider_set_format(g->highlights, "%.0f%%"); gtk_widget_set_tooltip_text(g->highlights, _("changes the local contrast of highlights")); g->shadows = dt_bauhaus_slider_new_with_range(self, 0.0, 200.0, 1.0, 100.0, 0); gtk_box_pack_start(GTK_BOX(self->widget), g->shadows, TRUE, TRUE, 0); dt_bauhaus_widget_set_label(g->shadows, NULL, _("shadows")); gtk_widget_set_tooltip_text(g->shadows, _("changes the local contrast of shadows")); dt_bauhaus_slider_set_format(g->shadows, "%.0f%%"); g->midtone = dt_bauhaus_slider_new_with_range(self, 0.001, 1.0, 0.001, 0.2, 3); gtk_box_pack_start(GTK_BOX(self->widget), g->midtone, TRUE, TRUE, 0); dt_bauhaus_widget_set_label(g->midtone, NULL, _("midtone range")); gtk_widget_set_tooltip_text(g->midtone, _("defines what counts as midtones. lower for better dynamic range compression (reduce shadow and highlight contrast), increase for more powerful local contrast")); // work around multi-instance issue which calls show all a fair bit: g_object_set(G_OBJECT(g->highlights), "no-show-all", TRUE, NULL); g_object_set(G_OBJECT(g->shadows), "no-show-all", TRUE, NULL); g_object_set(G_OBJECT(g->midtone), "no-show-all", TRUE, NULL); g_object_set(G_OBJECT(g->range), "no-show-all", TRUE, NULL); g_object_set(G_OBJECT(g->spatial), "no-show-all", TRUE, NULL); g_signal_connect(G_OBJECT(g->spatial), "value-changed", G_CALLBACK(spatial_callback), self); g_signal_connect(G_OBJECT(g->range), "value-changed", G_CALLBACK(range_callback), self); g_signal_connect(G_OBJECT(g->detail), "value-changed", G_CALLBACK(detail_callback), self); g_signal_connect(G_OBJECT(g->highlights), "value-changed", G_CALLBACK(highlights_callback), self); g_signal_connect(G_OBJECT(g->shadows), "value-changed", G_CALLBACK(shadows_callback), self); g_signal_connect(G_OBJECT(g->midtone), "value-changed", G_CALLBACK(midtone_callback), self); g_signal_connect(G_OBJECT(g->mode), "value-changed", G_CALLBACK(mode_callback), self); }
void gui_init(dt_iop_module_t *self) { self->gui_data = malloc(sizeof(dt_iop_levels_gui_data_t)); dt_iop_levels_gui_data_t *c = (dt_iop_levels_gui_data_t *)self->gui_data; dt_iop_levels_params_t *p = (dt_iop_levels_params_t *)self->params; dt_pthread_mutex_init(&c->lock, NULL); dt_pthread_mutex_lock(&c->lock); c->auto_levels[0] = NAN; c->auto_levels[1] = NAN; c->auto_levels[2] = NAN; dt_pthread_mutex_unlock(&c->lock); c->modes = NULL; c->mouse_x = c->mouse_y = -1.0; c->dragging = 0; c->activeToggleButton = NULL; c->current_pick = NONE; c->last_picked_color = -1; for(int i = 0; i < 3; i++) for(int j = 0; j < 2; j++) c->pick_xy_positions[i][j] = -1; self->widget = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5)); c->mode = dt_bauhaus_combobox_new(self); dt_bauhaus_widget_set_label(c->mode, NULL, _("mode")); dt_bauhaus_combobox_add(c->mode, C_("mode", "manual")); c->modes = g_list_append(c->modes, GUINT_TO_POINTER(LEVELS_MODE_MANUAL)); dt_bauhaus_combobox_add(c->mode, _("automatic")); c->modes = g_list_append(c->modes, GUINT_TO_POINTER(LEVELS_MODE_AUTOMATIC)); dt_bauhaus_combobox_set_default(c->mode, LEVELS_MODE_MANUAL); dt_bauhaus_combobox_set(c->mode, g_list_index(c->modes, GUINT_TO_POINTER(p->mode))); gtk_box_pack_start(GTK_BOX(self->widget), c->mode, TRUE, TRUE, 0); c->mode_stack = gtk_stack_new(); gtk_stack_set_homogeneous(GTK_STACK(c->mode_stack),FALSE); gtk_box_pack_start(GTK_BOX(self->widget), c->mode_stack, TRUE, TRUE, 0); c->area = GTK_DRAWING_AREA(dtgtk_drawing_area_new_with_aspect_ratio(9.0 / 16.0)); GtkWidget *vbox_manual = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5)); gtk_box_pack_start(GTK_BOX(vbox_manual), GTK_WIDGET(c->area), TRUE, TRUE, 0); gtk_widget_set_tooltip_text(GTK_WIDGET(c->area),_("drag handles to set black, gray, and white points. " "operates on L channel.")); gtk_widget_add_events(GTK_WIDGET(c->area), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_SCROLL_MASK); g_signal_connect(G_OBJECT(c->area), "draw", G_CALLBACK(dt_iop_levels_area_draw), self); g_signal_connect(G_OBJECT(c->area), "button-press-event", G_CALLBACK(dt_iop_levels_button_press), self); g_signal_connect(G_OBJECT(c->area), "button-release-event", G_CALLBACK(dt_iop_levels_button_release), self); g_signal_connect(G_OBJECT(c->area), "motion-notify-event", G_CALLBACK(dt_iop_levels_motion_notify), self); g_signal_connect(G_OBJECT(c->area), "leave-notify-event", G_CALLBACK(dt_iop_levels_leave_notify), self); g_signal_connect(G_OBJECT(c->area), "scroll-event", G_CALLBACK(dt_iop_levels_scroll), self); GtkWidget *autobutton = gtk_button_new_with_label(_("auto")); gtk_widget_set_tooltip_text(autobutton, _("apply auto levels")); gtk_widget_set_size_request(autobutton, -1, DT_PIXEL_APPLY_DPI(24)); GtkWidget *blackpick = dtgtk_togglebutton_new(dtgtk_cairo_paint_colorpicker, CPF_STYLE_FLAT); gtk_widget_set_tooltip_text(blackpick, _("pick black point from image")); GtkWidget *greypick = dtgtk_togglebutton_new(dtgtk_cairo_paint_colorpicker, CPF_STYLE_FLAT); gtk_widget_set_tooltip_text(greypick, _("pick medium gray point from image")); GtkWidget *whitepick = dtgtk_togglebutton_new(dtgtk_cairo_paint_colorpicker, CPF_STYLE_FLAT); gtk_widget_set_tooltip_text(whitepick, _("pick white point from image")); GdkRGBA color = { 0 }; color.alpha = 1.0; dtgtk_togglebutton_override_color(DTGTK_TOGGLEBUTTON(blackpick), &color); color.red = color.green = color.blue = 0.5; dtgtk_togglebutton_override_color(DTGTK_TOGGLEBUTTON(greypick), &color); color.red = color.green = color.blue = 1.0; dtgtk_togglebutton_override_color(DTGTK_TOGGLEBUTTON(whitepick), &color); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_PIXEL_APPLY_DPI(10)); gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(autobutton), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(blackpick), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(greypick), TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(box), GTK_WIDGET(whitepick), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox_manual), box, TRUE, TRUE, 0); gtk_widget_show_all(vbox_manual); gtk_stack_add_named(GTK_STACK(c->mode_stack), vbox_manual, "manual"); c->percentile_black = dt_bauhaus_slider_new_with_range(self, 0.0f, 100.0f, .1f, p->percentiles[0], 3); gtk_widget_set_tooltip_text(c->percentile_black, _("black percentile")); dt_bauhaus_slider_set_format(c->percentile_black, "%.1f%%"); dt_bauhaus_widget_set_label(c->percentile_black, NULL, _("black")); c->percentile_grey = dt_bauhaus_slider_new_with_range(self, 0.0f, 100.0f, .1f, p->percentiles[1], 3); gtk_widget_set_tooltip_text(c->percentile_grey, _("gray percentile")); dt_bauhaus_slider_set_format(c->percentile_grey, "%.1f%%"); dt_bauhaus_widget_set_label(c->percentile_grey, NULL, _("gray")); c->percentile_white = dt_bauhaus_slider_new_with_range(self, 0.0f, 100.0f, .1f, p->percentiles[2], 3); gtk_widget_set_tooltip_text(c->percentile_white, _("white percentile")); dt_bauhaus_slider_set_format(c->percentile_white, "%.1f%%"); dt_bauhaus_widget_set_label(c->percentile_white, NULL, _("white")); GtkWidget *vbox_automatic = GTK_WIDGET(gtk_box_new(GTK_ORIENTATION_VERTICAL, 5)); gtk_box_pack_start(GTK_BOX(vbox_automatic), GTK_WIDGET(c->percentile_black), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_automatic), GTK_WIDGET(c->percentile_grey), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox_automatic), GTK_WIDGET(c->percentile_white), FALSE, FALSE, 0); gtk_widget_show_all(vbox_automatic); gtk_stack_add_named(GTK_STACK(c->mode_stack), vbox_automatic, "automatic"); switch(p->mode) { case LEVELS_MODE_AUTOMATIC: gtk_stack_set_visible_child_name(GTK_STACK(c->mode_stack), "automatic"); break; case LEVELS_MODE_MANUAL: default: gtk_stack_set_visible_child_name(GTK_STACK(c->mode_stack), "manual"); break; } g_signal_connect(G_OBJECT(c->mode), "value-changed", G_CALLBACK(dt_iop_levels_mode_callback), self); g_signal_connect(G_OBJECT(c->percentile_black), "value-changed", G_CALLBACK(dt_iop_levels_percentiles_callback), self); g_signal_connect(G_OBJECT(c->percentile_grey), "value-changed", G_CALLBACK(dt_iop_levels_percentiles_callback), self); g_signal_connect(G_OBJECT(c->percentile_white), "value-changed", G_CALLBACK(dt_iop_levels_percentiles_callback), self); g_signal_connect(G_OBJECT(autobutton), "clicked", G_CALLBACK(dt_iop_levels_autoadjust_callback), (gpointer)self); g_signal_connect(G_OBJECT(blackpick), "toggled", G_CALLBACK(dt_iop_levels_pick_black_callback), self); g_signal_connect(G_OBJECT(greypick), "toggled", G_CALLBACK(dt_iop_levels_pick_grey_callback), self); g_signal_connect(G_OBJECT(whitepick), "toggled", G_CALLBACK(dt_iop_levels_pick_white_callback), self); }
void dt_opencl_init(dt_opencl_t *cl, const int argc, char *argv[]) { dt_pthread_mutex_init(&cl->lock, NULL); cl->inited = 0; cl->enabled = 0; cl->dlocl = NULL; int exclude_opencl = 0; // user selectable parameter defines minimum requirement on GPU memory // default is 768MB // values below 256 will be (re)set to 256 const int opencl_memory_requirement = max(256, dt_conf_get_int("opencl_memory_requirement")); dt_conf_set_int("opencl_memory_requirement", opencl_memory_requirement); for(int k=0; k<argc; k++) if(!strcmp(argv[k], "--disable-opencl")) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] do not try to find and use an opencl runtime library due to explicit user request\n"); exclude_opencl = 1; } if(exclude_opencl) goto finally; // look for explicit definition of opencl_runtime library in preferences const char *library = dt_conf_get_string("opencl_library"); dt_print(DT_DEBUG_OPENCL, "[opencl_init] trying to load opencl library: '%s'\n", library && strlen(library) != 0 ? library : "<system default>"); // dynamically load opencl runtime if(!dt_dlopencl_init(library, &cl->dlocl)) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] no working opencl library found. Continue with opencl disabled\n"); goto finally; } else { dt_print(DT_DEBUG_OPENCL, "[opencl_init] opencl library '%s' found on your system and loaded\n", cl->dlocl->library); } cl_int err; cl_platform_id all_platforms[DT_OPENCL_MAX_PLATFORMS]; cl_uint all_num_devices[DT_OPENCL_MAX_PLATFORMS]; cl_uint num_platforms = DT_OPENCL_MAX_PLATFORMS; err = (cl->dlocl->symbols->dt_clGetPlatformIDs) (DT_OPENCL_MAX_PLATFORMS, all_platforms, &num_platforms); if(err != CL_SUCCESS) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not get platforms: %d\n", err); goto finally; } if(num_platforms == 0) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] no opencl platform available\n"); goto finally; } for(int n=0; n < num_platforms; n++) { cl_platform_id platform = all_platforms[n]; // get the number of GPU devices available to the platforms // the other common option is CL_DEVICE_TYPE_GPU/CPU (but the latter doesn't work with the nvidia drivers) err = (cl->dlocl->symbols->dt_clGetDeviceIDs)(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &(all_num_devices[n])); if(err != CL_SUCCESS) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not get device id size: %d\n", err); goto finally; } } cl_uint num_devices = 0; for(int n=0; n < num_platforms; n++) num_devices += all_num_devices[n]; // create the device list cl->dev = (dt_opencl_device_t *)malloc(sizeof(dt_opencl_device_t)*num_devices); cl_device_id *devices = (cl_device_id *)malloc(sizeof(cl_device_id)*num_devices); cl_device_id *devs = devices; for(int n=0; n < num_platforms; n++) { cl_platform_id platform = all_platforms[n]; err = (cl->dlocl->symbols->dt_clGetDeviceIDs)(platform, CL_DEVICE_TYPE_ALL, all_num_devices[n], devs, NULL); if(err != CL_SUCCESS) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not get devices list: %d\n", err); goto finally; } devs += all_num_devices[n]; } dt_print(DT_DEBUG_OPENCL, "[opencl_init] found %d device%s\n", num_devices, num_devices > 1 ? "s" : ""); int dev = 0; for(int k=0; k<num_devices; k++) { memset(cl->dev[dev].program_used, 0x0, sizeof(int)*DT_OPENCL_MAX_PROGRAMS); memset(cl->dev[dev].kernel_used, 0x0, sizeof(int)*DT_OPENCL_MAX_KERNELS); cl->dev[dev].eventlist = NULL; cl->dev[dev].eventtags = NULL; cl->dev[dev].numevents = 0; cl->dev[dev].eventsconsolidated = 0; cl->dev[dev].maxevents = 0; cl->dev[dev].lostevents = 0; cl->dev[dev].summary=CL_COMPLETE; cl->dev[dev].used_global_mem = 0; cl_device_id devid = cl->dev[dev].devid = devices[k]; char infostr[1024]; size_t infoint; size_t infointtab[1024]; cl_device_type type; cl_bool image_support = 0; // test GPU memory and image support: (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_NAME, sizeof(infostr), &infostr, NULL); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &image_support, NULL); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &(cl->dev[dev].max_image_height), NULL); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &(cl->dev[dev].max_image_width), NULL); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &(cl->dev[dev].max_mem_alloc), NULL); if(type == CL_DEVICE_TYPE_CPU) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] discarding CPU device %d `%s' as it will not deliver any performance gain.\n", k, infostr); continue; } if(!image_support) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] discarding device %d `%s' due to missing image support.\n", k, infostr); continue; } (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &(cl->dev[dev].max_global_mem), NULL); if(cl->dev[dev].max_global_mem < opencl_memory_requirement*1024*1024) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] discarding device %d `%s' due to insufficient global memory (%luMB).\n", k, infostr, cl->dev[dev].max_global_mem/1024/1024); continue; } dt_print(DT_DEBUG_OPENCL, "[opencl_init] device %d `%s' supports image sizes of %zd x %zd\n", k, infostr, cl->dev[dev].max_image_width, cl->dev[dev].max_image_height); dt_print(DT_DEBUG_OPENCL, "[opencl_init] device %d `%s' allows GPU memory allocations of up to %luMB\n", k, infostr, cl->dev[dev].max_mem_alloc/1024/1024); if(darktable.unmuted & DT_DEBUG_OPENCL) { printf("[opencl_init] device %d: %s \n", k, infostr); printf(" GLOBAL_MEM_SIZE: %.0fMB\n", (double)cl->dev[dev].max_global_mem/1024.0/1024.0); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(infoint), &infoint, NULL); printf(" MAX_WORK_GROUP_SIZE: %zd\n", infoint); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(infoint), &infoint, NULL); printf(" MAX_WORK_ITEM_DIMENSIONS: %zd\n", infoint); printf(" MAX_WORK_ITEM_SIZES: [ "); (cl->dlocl->symbols->dt_clGetDeviceInfo)(devid, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(infointtab), infointtab, NULL); for (int i=0; i<infoint; i++) printf("%zd ", infointtab[i]); printf("]\n"); } dt_pthread_mutex_init(&cl->dev[dev].lock, NULL); cl->dev[dev].context = (cl->dlocl->symbols->dt_clCreateContext)(0, 1, &devid, NULL, NULL, &err); if(err != CL_SUCCESS) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not create context for device %d: %d\n", k, err); goto finally; } // create a command queue for first device the context reported cl->dev[dev].cmd_queue = (cl->dlocl->symbols->dt_clCreateCommandQueue)(cl->dev[dev].context, devid, (darktable.unmuted & DT_DEBUG_PERF) ? CL_QUEUE_PROFILING_ENABLE : 0, &err); if(err != CL_SUCCESS) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not create command queue for device %d: %d\n", k, err); goto finally; } char dtpath[1024], filename[1024], programname[1024]; dt_loc_get_datadir(dtpath, 1024); snprintf(filename, 1024, "%s/kernels/programs.conf", dtpath); // now load all darktable cl kernels. // TODO: compile as a job? FILE *f = fopen(filename, "rb"); if(f) { while(!feof(f)) { int rd = fscanf(f, "%[^\n]\n", programname); if(rd != 1) continue; // remove comments: for(int k=0; k<strlen(programname); k++) if(programname[k] == '#') { programname[k] = '\0'; for(int l=k-1; l>=0; l--) { if (programname[l] == ' ') programname[l] = '\0'; else break; } break; } if(programname[0] == '\0') continue; snprintf(filename, 1024, "%s/kernels/%s", dtpath, programname); dt_print(DT_DEBUG_OPENCL, "[opencl_init] compiling program `%s' ..\n", programname); const int prog = dt_opencl_load_program(dev, filename); if(dt_opencl_build_program(dev, prog)) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] failed to compile program `%s'!\n", programname); goto finally; } } fclose(f); } else { dt_print(DT_DEBUG_OPENCL, "[opencl_init] could not open `%s'!\n", filename); goto finally; } ++dev; } free(devices); if(dev > 0) { dt_print(DT_DEBUG_OPENCL, "[opencl_init] successfully initialized.\n"); cl->num_devs = dev; cl->inited = 1; cl->enabled = dt_conf_get_bool("opencl"); } else { dt_print(DT_DEBUG_OPENCL, "[opencl_init] no suitable devices found.\n"); } finally: dt_print(DT_DEBUG_OPENCL, "[opencl_init] FINALLY: opencl is %sAVAILABLE on this system.\n", cl->inited ? "" : "NOT "); dt_print(DT_DEBUG_OPENCL, "[opencl_init] initial status of opencl enabled flag is %s.\n", cl->enabled ? "ON" : "OFF"); return; }