static int lua_job_progress(lua_State *L) { dt_progress_t *progress; luaA_to(L, dt_lua_backgroundjob_t, &progress, 1); dt_lua_unlock(false); gboolean i_own_lock = dt_control_gdk_lock(); dt_pthread_mutex_lock(&darktable.control->progress_system.mutex); GList *iter = g_list_find(darktable.control->progress_system.list, progress); dt_pthread_mutex_unlock(&darktable.control->progress_system.mutex); if(i_own_lock) dt_control_gdk_unlock(); dt_lua_lock(); if(!iter) luaL_error(L,"Accessing an invalid job"); if(lua_isnone(L, 3)) { dt_lua_unlock(false); double result = dt_control_progress_get_progress(progress); dt_lua_lock(); if(!dt_control_progress_has_progress_bar(progress)) lua_pushnil(L); else lua_pushnumber(L, result); return 1; } else { double value; luaA_to(L,progress_double,&value,3); dt_lua_unlock(false); dt_control_progress_set_progress(darktable.control, progress, value); dt_lua_lock(); return 0; } }
void dt_ctl_switch_mode_to(dt_control_gui_mode_t mode) { dt_control_gui_mode_t oldmode = dt_conf_get_int("ui_last/view"); if(oldmode == mode) return; darktable.control->button_down = 0; darktable.control->button_down_which = 0; darktable.gui->center_tooltip = 0; GtkWidget *widget = dt_ui_center(darktable.gui->ui); g_object_set(G_OBJECT(widget), "tooltip-text", "", (char *)NULL); char buf[512]; snprintf(buf, sizeof(buf) - 1, _("switch to %s mode"), dt_view_manager_name(darktable.view_manager)); gboolean i_own_lock = dt_control_gdk_lock(); int error = dt_view_manager_switch(darktable.view_manager, mode); if(i_own_lock) dt_control_gdk_unlock(); if(error) return; dt_conf_set_int ("ui_last/view", mode); }
static int lua_job_valid(lua_State*L) { dt_progress_t *progress; luaA_to(L, dt_lua_backgroundjob_t, &progress, 1); if(lua_isnone(L, 3)) { dt_lua_unlock(false); gboolean i_own_lock = dt_control_gdk_lock(); dt_pthread_mutex_lock(&darktable.control->progress_system.mutex); GList *iter = g_list_find(darktable.control->progress_system.list, progress); dt_pthread_mutex_unlock(&darktable.control->progress_system.mutex); if(i_own_lock) dt_control_gdk_unlock(); dt_lua_lock(); if(iter) lua_pushboolean(L, true); else lua_pushboolean(L, false); return 1; } else { int validity = lua_toboolean(L, 3); if(validity) return luaL_argerror(L, 3, "a job can not be made valid"); dt_lua_unlock(false); dt_control_progress_destroy(darktable.control, progress); dt_lua_lock(); return 0; } }
static void _lib_filmstrip_scroll_to_image(dt_lib_module_t *self, gint imgid, gboolean activate) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; /* if no imgid just bail out */ if(imgid <= 0) return; strip->activated_image = imgid; strip->offset = dt_collection_image_offset(imgid); DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, strip->activated_image); /* activate the image if requested */ if (activate) { strip->activated_image = imgid; dt_control_signal_raise(darktable.signals, DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE); } /* redraw filmstrip */ gboolean owns_lock = dt_control_gdk_lock(); gtk_widget_queue_draw(self->widget); if(owns_lock) dt_control_gdk_unlock(); }
static void _lib_backgroundjobs_destroy(dt_lib_module_t *self, const guint *key) { dt_lib_backgroundjobs_t *d = (dt_lib_backgroundjobs_t*)self->data; gboolean i_own_lock = dt_control_gdk_lock(); dt_bgjob_t *j = (dt_bgjob_t*)g_hash_table_lookup(d->jobs, key); if(j) { g_hash_table_remove(d->jobs, key); /* remove job widget from jobbox */ if(GTK_IS_WIDGET(j->widget)) gtk_container_remove(GTK_CONTAINER(d->jobbox),j->widget); /* if jobbox is empty lets hide */ if(g_list_length(gtk_container_get_children(GTK_CONTAINER(d->jobbox)))==0) gtk_widget_hide(d->jobbox); /* free allocted mem */ g_free(j); g_free((guint*)key); } if(i_own_lock) dt_control_gdk_unlock(); }
void dt_control_queue_redraw_widget(GtkWidget *widget) { if(dt_control_running()) { gboolean i_own_lock = dt_control_gdk_lock(); gtk_widget_queue_draw(widget); if (i_own_lock) dt_control_gdk_unlock(); } }
void dt_control_signal_raise(const dt_control_signal_t *ctlsig, dt_signal_t signal,...) { va_list extra_args; // ignore all signals on shutdown, especially don't lock anything.. if(!dt_control_running()) return; va_start(extra_args,signal); gboolean i_own_lock = dt_control_gdk_lock(); //g_signal_emit_by_name(G_OBJECT(ctlsig->sink), _signal_description[signal].name); g_signal_emit_valist(G_OBJECT(ctlsig->sink),g_signal_lookup(_signal_description[signal].name,_signal_type), 0,extra_args); va_end(extra_args); if (i_own_lock) dt_control_gdk_unlock(); }
static const guint * _lib_backgroundjobs_create(dt_lib_module_t *self,int type,const gchar *message) { dt_lib_backgroundjobs_t *d = (dt_lib_backgroundjobs_t *)self->data; /* lets make this threadsafe */ gboolean i_own_lock = dt_control_gdk_lock(); /* initialize a new job */ dt_bgjob_t *j=(dt_bgjob_t*)g_malloc(sizeof(dt_bgjob_t)); j->type = type; j->widget = gtk_event_box_new(); guint *key = g_malloc(sizeof(guint)); *key = g_direct_hash((gconstpointer)j); /* create in hash out of j pointer*/ g_hash_table_insert(d->jobs, key, j); /* intialize the ui elements for job */ gtk_widget_set_name (GTK_WIDGET (j->widget), "background_job_eventbox"); GtkBox *vbox = GTK_BOX (gtk_vbox_new (FALSE,0)); GtkBox *hbox = GTK_BOX (gtk_hbox_new (FALSE,0)); gtk_container_set_border_width (GTK_CONTAINER(vbox),2); gtk_container_add (GTK_CONTAINER(j->widget), GTK_WIDGET(vbox)); /* add job label */ j->label = gtk_label_new(message); gtk_misc_set_alignment(GTK_MISC(j->label), 0.0, 0.5); gtk_box_pack_start( GTK_BOX( hbox ), GTK_WIDGET(j->label), TRUE, TRUE, 0); gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET(hbox), TRUE, TRUE, 0); /* use progressbar ? */ if (type == 0) { j->progressbar = gtk_progress_bar_new(); gtk_box_pack_start( GTK_BOX( vbox ), j->progressbar, TRUE, FALSE, 2); #ifdef HAVE_UNITY j->darktable_launcher = unity_launcher_entry_get_for_desktop_id("darktable.desktop"); unity_launcher_entry_set_progress( j->darktable_launcher, 0.0 ); unity_launcher_entry_set_progress_visible( j->darktable_launcher, TRUE ); #endif } /* lets show jobbox if its hidden */ gtk_box_pack_start(GTK_BOX(d->jobbox), j->widget, TRUE, FALSE, 1); gtk_box_reorder_child(GTK_BOX(d->jobbox), j->widget, 1); gtk_widget_show_all(j->widget); gtk_widget_show(d->jobbox); if(i_own_lock) dt_control_gdk_unlock(); return key; }
/** camctl camera disconnect callback */ static void _camctl_camera_disconnected_callback (const dt_camera_t *camera,void *data) { dt_lib_module_t *self = (dt_lib_module_t *)data; /* rescan connected cameras */ dt_camctl_detect_cameras(darktable.camctl); /* update gui with detected devices */ gboolean i_own_lock = dt_control_gdk_lock(); _lib_import_ui_devices_update(self); if(i_own_lock) dt_control_gdk_unlock(); }
gboolean dt_lua_lock() { gboolean had_lock = dt_control_gdk_haslock(); if(had_lock){ dt_control_gdk_unlock(); } if(!darktable.lua_state.ending && pthread_equal(darktable.control->gui_thread,pthread_self()) != 0) { dt_print(DT_DEBUG_LUA,"LUA WARNING locking from the gui thread should be avoided\n"); } dt_pthread_mutex_lock(&darktable.lua_state.mutex); return had_lock; }
static gboolean _slider_postponed_value_change(gpointer data) { gboolean i_own_lock = dt_control_gdk_lock(); if (DTGTK_SLIDER(data)->is_changed==TRUE) { g_signal_emit_by_name(G_OBJECT(data),"value-changed"); if(DTGTK_SLIDER(data)->type==DARKTABLE_SLIDER_VALUE) DTGTK_SLIDER(data)->is_changed=FALSE; } if (i_own_lock) dt_control_gdk_unlock(); return DTGTK_SLIDER(data)->is_dragging; // This is called by the gtk mainloop and is threadsafe }
static void _lib_backgroundjobs_progress(dt_lib_module_t *self, const guint *key, double progress) { if(!darktable.control->running) return; dt_lib_backgroundjobs_t *d = (dt_lib_backgroundjobs_t*)self->data; gboolean i_own_lock = dt_control_gdk_lock(); dt_bgjob_t *j = (dt_bgjob_t*)g_hash_table_lookup(d->jobs, key); if(j) { /* check if progress is above 1.0 and destroy bgjob if finished */ /* FIXME: actually we are having some rounding issues, where the */ /* FIXME: last item doesn't bring to total to 1.0 flat */ /* FIXME: so this is why we have the ugly kludge below */ if (progress > 0.999999) { if (GTK_IS_WIDGET(j->widget)) gtk_container_remove( GTK_CONTAINER(d->jobbox), j->widget ); #ifdef HAVE_UNITY unity_launcher_entry_set_progress( j->darktable_launcher, 1.0 ); unity_launcher_entry_set_progress_visible( j->darktable_launcher, FALSE ); #endif #ifdef MAC_INTEGRATION #ifdef GTK_TYPE_OSX_APPLICATION gtk_osxapplication_attention_request(g_object_new(GTK_TYPE_OSX_APPLICATION, NULL), INFO_REQUEST); #else gtkosx_application_attention_request(g_object_new(GTKOSX_TYPE_APPLICATION, NULL), INFO_REQUEST); #endif #endif /* hide jobbox if theres no jobs left */ if (g_list_length(gtk_container_get_children(GTK_CONTAINER(d->jobbox))) == 0 ) gtk_widget_hide(d->jobbox); } else { if( j->type == 0 ) gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(j->progressbar), progress ); #ifdef HAVE_UNITY unity_launcher_entry_set_progress( j->darktable_launcher, progress ); #endif } } if(i_own_lock) dt_control_gdk_unlock(); }
static void _lib_backgroundjobs_progress(dt_lib_module_t *self, const guint *key, double progress) { if(!darktable.control->running) return; gboolean i_own_lock = dt_control_gdk_lock(); dt_lib_backgroundjobs_t *d = (dt_lib_backgroundjobs_t*)self->data; dt_bgjob_t *j = (dt_bgjob_t*)g_hash_table_lookup(d->jobs, key); if(j) { if( j->type == 0 ) gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(j->progressbar), progress ); #ifdef HAVE_UNITY unity_launcher_entry_set_progress( j->darktable_launcher, progress ); #endif } if(i_own_lock) dt_control_gdk_unlock(); }
/** camctl status listener callback */ static void _camctl_camera_control_status_callback(dt_camctl_status_t status,void *data) { dt_lib_module_t *self = (dt_lib_module_t *)data; dt_lib_import_t *d = (dt_lib_import_t*)self->data; /* check if we need gdk locking */ gboolean i_have_lock = dt_control_gdk_lock(); /* handle camctl status */ switch(status) { case CAMERA_CONTROL_BUSY: { /* set all devicese as inaccessible */ GList *child = gtk_container_get_children(GTK_CONTAINER(d->devices)); if(child) do { if( !(GTK_IS_TOGGLE_BUTTON(child->data) && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(child->data))==TRUE) ) gtk_widget_set_sensitive(GTK_WIDGET(child->data),FALSE); } while( (child=g_list_next(child)) ); } break; case CAMERA_CONTROL_AVAILABLE: { /* set all devices as accessible */ GList *child = gtk_container_get_children(GTK_CONTAINER(d->devices)); if(child) do { gtk_widget_set_sensitive(GTK_WIDGET(child->data),TRUE); } while( (child=g_list_next(child)) ); } break; } /* unlock */ if(i_have_lock) dt_control_gdk_unlock(); }
static void _lib_modulegroups_set(dt_lib_module_t *self, uint32_t group) { dt_lib_modulegroups_t *d = (dt_lib_modulegroups_t *)self->data; /* this is a proxy function so it might be called from another thread */ gboolean i_own_lock = dt_control_gdk_lock(); /* if no change just update visibility */ if(d->current == group) { _lib_modulegroups_update_iop_visibility(self); return; } /* set current group */ if(group < DT_MODULEGROUP_SIZE && GTK_IS_TOGGLE_BUTTON(d->buttons[group])) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(d->buttons[group]), TRUE); if(i_own_lock) dt_control_gdk_unlock(); }
static void _lib_backgroundjobs_destroy(dt_lib_module_t *self, const guint *key) { gboolean i_own_lock = dt_control_gdk_lock(); dt_lib_backgroundjobs_t *d = (dt_lib_backgroundjobs_t*)self->data; dt_bgjob_t *j = (dt_bgjob_t*)g_hash_table_lookup(d->jobs, key); if(j) { g_hash_table_remove(d->jobs, key); /* remove job widget from jobbox */ if(j->widget && GTK_IS_WIDGET(j->widget)) gtk_container_remove(GTK_CONTAINER(d->jobbox),j->widget); j->widget = 0; #ifdef HAVE_UNITY if( j->type == 0 ) { unity_launcher_entry_set_progress( j->darktable_launcher, 1.0 ); unity_launcher_entry_set_progress_visible( j->darktable_launcher, FALSE ); } #endif #ifdef MAC_INTEGRATION #ifdef GTK_TYPE_OSX_APPLICATION gtk_osxapplication_attention_request(g_object_new(GTK_TYPE_OSX_APPLICATION, NULL), INFO_REQUEST); #else gtkosx_application_attention_request(g_object_new(GTKOSX_TYPE_APPLICATION, NULL), INFO_REQUEST); #endif #endif /* if jobbox is empty lets hide */ if(g_list_length(gtk_container_get_children(GTK_CONTAINER(d->jobbox)))==0) gtk_widget_hide(d->jobbox); /* free allocted mem */ g_free(j); g_free((guint*)key); } if(i_own_lock) dt_control_gdk_unlock(); }
static void _lib_backgroundjobs_set_cancellable(dt_lib_module_t *self, const guint *key, struct dt_job_t *job) { if(!darktable.control->running) return; gboolean i_own_lock = dt_control_gdk_lock(); dt_lib_backgroundjobs_t *d = (dt_lib_backgroundjobs_t*)self->data; dt_bgjob_t *j = (dt_bgjob_t*)g_hash_table_lookup(d->jobs, key); if (j) { GtkWidget *w=j->widget; GtkBox *hbox = GTK_BOX (g_list_nth_data (gtk_container_get_children (GTK_CONTAINER ( gtk_bin_get_child (GTK_BIN (w) ) ) ), 0)); GtkWidget *button = dtgtk_button_new(dtgtk_cairo_paint_cancel,CPF_STYLE_FLAT); gtk_widget_set_size_request(button,17,17); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (_lib_backgroundjobs_cancel_callback), (gpointer)job); gtk_box_pack_start (hbox, GTK_WIDGET(button), FALSE, FALSE, 0); gtk_widget_show_all(button); } if(i_own_lock) dt_control_gdk_unlock(); }
static void _lib_filmstrip_scroll_to_image(dt_lib_module_t *self, gint imgid, gboolean activate) { dt_lib_filmstrip_t *strip = (dt_lib_filmstrip_t *)self->data; /* if no imgid just bail out */ if(imgid <= 0) return; strip->activated_image = imgid; char query[1024]; const gchar *qin = dt_collection_get_query (darktable.collection); if(qin) { snprintf(query, 1024, "select rowid from (%s) where id=?3", qin); sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, 0); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, -1); DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, imgid); if(sqlite3_step(stmt) == SQLITE_ROW) { strip->offset = sqlite3_column_int(stmt, 0) - 1; } sqlite3_finalize(stmt); } /* activate the image if requested */ if (activate) { strip->activated_image = imgid; dt_control_signal_raise(darktable.signals, DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE); } /* redraw filmstrip */ gboolean owns_lock = dt_control_gdk_lock(); gtk_widget_queue_draw(self->widget); if(owns_lock) dt_control_gdk_unlock(); }
/* Detect hot sensor pixels based on the 4 surrounding sites. Pixels * having 3 or 4 (depending on permissive setting) surrounding pixels that * than value*multiplier are considered "hot", and are replaced by the maximum of * the neighbour pixels. The permissive variant allows for * correcting pairs of hot pixels in adjacent sites. Replacement using * the maximum produces fewer artifacts when inadvertently replacing * non-hot pixels. */ void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *i, void *o, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out) { dt_iop_hotpixels_gui_data_t *g = (dt_iop_hotpixels_gui_data_t *)self->gui_data; const dt_iop_hotpixels_data_t *data = (dt_iop_hotpixels_data_t *)piece->data; const float threshold = data->threshold; const float multiplier = data->multiplier; const int width = roi_out->width; const int widthx2 = width*2; const gboolean markfixed = data->markfixed; const int min_neighbours = data->permissive ? 3 : 4; // The loop should output only a few pixels, so just copy everything first memcpy(o, i, roi_out->width*roi_out->height*sizeof(float)); int fixed = 0; #ifdef _OPENMP #pragma omp parallel for default(none) shared(roi_out, i, o) reduction(+:fixed) schedule(static) #endif for (int row=2; row<roi_out->height-2; row++) { const float *in = (float*)i + width*row+2; float *out = (float*)o + width*row+2; for (int col=2; col<width-1; col++, in++, out++) { float mid= *in * multiplier; if (*in > threshold) { int count=0; float maxin=0.0; float other; #define TESTONE(OFFSET) \ other=in[OFFSET]; \ if (mid > other) \ { \ count++; \ if (other > maxin) maxin = other; \ } TESTONE(-2); TESTONE(-widthx2); TESTONE(+2); TESTONE(+widthx2); #undef TESTONE if (count >= min_neighbours) { *out = maxin; fixed++; if (markfixed) { for (int i=-2; i>=-10 && i>=-col; i-=2) out[i] = *in; for (int i=2; i<=10 && i<width-col; i+=2) out[i] = *in; } } } } } if (g != NULL) { // lock gui thread mutex, if we are not called from gui thread (very likely) gboolean i_have_lock = dt_control_gdk_lock(); char buf[256]; snprintf(buf, sizeof buf, _("fixed %d pixels"), fixed); gtk_label_set_text(g->message, buf); if(i_have_lock) dt_control_gdk_unlock(); } }
int _camera_storage_image_filename(const dt_camera_t *camera,const char *filename,CameraFile *preview,CameraFile *exif,void *user_data) { _camera_import_dialog_t *data=(_camera_import_dialog_t*)user_data; GtkTreeIter iter; const char *img; unsigned long size; GdkPixbuf *pixbuf=NULL; GdkPixbuf *thumb=NULL; /* stop fetching previews if job is cancelled */ if (data->preview_job && dt_control_job_get_state(data->preview_job) == DT_JOB_STATE_CANCELLED ) return 0; gboolean i_own_lock = dt_control_gdk_lock(); char exif_info[1024]= {0}; char file_info[4096]= {0}; if( preview ) { gp_file_get_data_and_size(preview, &img, &size); if( size > 0 ) { // we got preview image data lets create a pixbuf from image blob GError *err=NULL; GInputStream *stream; if( (stream = g_memory_input_stream_new_from_data(img, size,NULL)) !=NULL) pixbuf = gdk_pixbuf_new_from_stream( stream, NULL, &err ); } if(pixbuf) { // Scale pixbuf to a thumbnail double sw=gdk_pixbuf_get_width( pixbuf ); double scale=75.0/gdk_pixbuf_get_height( pixbuf ); thumb = gdk_pixbuf_scale_simple( pixbuf, sw*scale,75 , GDK_INTERP_BILINEAR ); } } #if 0 // libgphoto only supports fetching exif in jpegs, not raw char buffer[1024]= {0}; if ( exif ) { const char *exif_data; char *value=NULL; gp_file_get_data_and_size(exif, &exif_data, &size); if( size > 0 ) { void *exif=dt_exif_data_new((uint8_t *)exif_data,size); if( (value=g_strdup( dt_exif_data_get_value(exif,"Exif.Photo.ExposureTime",buffer,1024) ) ) != NULL); snprintf(exif_info, sizeof(exif_info), "exposure: %s\n", value); } else fprintf(stderr,"No exifdata read\n"); } #endif // filename\n 1/60 f/2.8 24mm iso 160 snprintf(file_info, sizeof(file_info), "%s%c%s",filename,strlen(exif_info)?'\n':'\0',strlen(exif_info)?exif_info:""); gtk_list_store_append(data->store,&iter); gtk_list_store_set(data->store,&iter,0,thumb,1,file_info,-1); if(pixbuf) g_object_unref(pixbuf); if(thumb) g_object_ref(thumb); if (i_own_lock) dt_control_gdk_unlock(); return 1; }