static gboolean alien_job_dispatch (GSource* source, GSourceFunc callback, gpointer user_data) { gpointer message; message = g_async_queue_try_pop (darktable.lua_state.alien_job_queue); if (message == NULL) { return TRUE; } async_call_data* data = (async_call_data*)message; dt_lua_lock(); lua_State* L= darktable.lua_state.state; lua_State *new_thread = lua_newthread(L); int reference = save_thread(L); lua_pushlightuserdata(new_thread,data->cb); lua_pushlightuserdata(new_thread,data->cb_data); lua_pushinteger(new_thread,data->nresults); lua_pushcfunction(new_thread,data->pusher); GList* cur_elt = data->extra; while(cur_elt) { GList * type_type_elt = cur_elt; cur_elt = g_list_next(cur_elt); GList * type_elt = cur_elt; cur_elt = g_list_next(cur_elt); GList * data_elt = cur_elt; cur_elt = g_list_next(cur_elt); switch(GPOINTER_TO_INT(type_type_elt->data)) { case LUA_ASYNC_TYPEID_WITH_FREE: // skip the destructor cur_elt = g_list_next(cur_elt); // do not break case LUA_ASYNC_TYPEID: luaA_push_type(new_thread,GPOINTER_TO_INT(type_elt->data),data_elt->data); break; case LUA_ASYNC_TYPENAME_WITH_FREE: // skip the destructor cur_elt = g_list_next(cur_elt); // do not break case LUA_ASYNC_TYPENAME: luaA_push_type(new_thread,luaA_type_find(L,type_elt->data),&data_elt->data); break; case LUA_ASYNC_DONE: default: // should never happen g_assert(false); break; } } run_async_thread(L,reference); dt_lua_unlock(); alien_job_destroy(data); return G_SOURCE_CONTINUE; }
static int get_widget_params(lua_State *L) { struct dt_lua_widget_type_t *widget_type = lua_touserdata(L, lua_upvalueindex(1)); if(G_TYPE_IS_ABSTRACT(widget_type->gtk_type)){ luaL_error(L,"Trying to create a widget of an abstract type : %s\n",widget_type->name); } lua_widget widget= malloc(widget_type->alloc_size); widget->widget = gtk_widget_new(widget_type->gtk_type,NULL); gtk_widget_show(widget->widget);// widgets are invisible by default g_object_ref_sink(widget->widget); widget->type = widget_type; luaA_push_type(L,widget_type->associated_type,&widget); dt_lua_type_gpointer_alias_type(L,widget_type->associated_type,widget,widget->widget); init_widget_sub(L,widget_type); luaL_getmetafield(L,-1,"__gtk_signals"); lua_pushnil(L); /* first key */ while(lua_next(L, -2) != 0) { g_signal_connect(widget->widget, lua_tostring(L,-2), G_CALLBACK(lua_touserdata(L,-1)), widget); lua_pop(L,1); } lua_pop(L,1); return 1; }
static void finalize_store_wrapper(struct dt_imageio_module_storage_t *self, dt_imageio_module_data_t *data) { dt_lua_lock(); lua_State *L = darktable.lua_state.state; lua_getfield(L, LUA_REGISTRYINDEX, "dt_lua_storages"); lua_getfield(L, -1, self->plugin_name); lua_getfield(L, -1, "finalize_store"); if(lua_isnil(L, -1)) { lua_pop(L, 3); dt_lua_unlock(); return; } luaA_push_type(L, self->parameter_lua_type, data); lua_storage_t *d = (lua_storage_t *)data; push_lua_data(L,d); dt_lua_goto_subtable(L,"files"); push_lua_data(L,d); dt_lua_goto_subtable(L,"extra"); dt_lua_treated_pcall(L,3,0); lua_pop(L, 2); dt_lua_unlock(); }
static int get_format_params(lua_State *L) { dt_imageio_module_format_t *format_module = lua_touserdata(L,lua_upvalueindex(1)); dt_imageio_module_data_t *fdata = format_module->get_params(format_module); luaA_push_type(L,format_module->parameter_lua_type,fdata); format_module->free_params(format_module,fdata); return 1; }
static int32_t async_callback_job(dt_job_t *job) { dt_lua_lock(); lua_State* L= darktable.lua_state.state; async_call_data* data = (async_call_data*)dt_control_job_get_params(job); lua_pushcfunction(L,data->pusher); int nargs =0; GList* cur_elt = data->extra; while(cur_elt) { GList * type_type_elt = cur_elt; cur_elt = g_list_next(cur_elt); GList * type_elt = cur_elt; cur_elt = g_list_next(cur_elt); GList * data_elt = cur_elt; cur_elt = g_list_next(cur_elt); switch(GPOINTER_TO_INT(type_type_elt->data)) { case LUA_ASYNC_TYPEID_WITH_FREE: // skip the destructor cur_elt = g_list_next(cur_elt); // do not break case LUA_ASYNC_TYPEID: luaA_push_type(L,GPOINTER_TO_INT(type_elt->data),data_elt->data); break; case LUA_ASYNC_TYPENAME_WITH_FREE: // skip the destructor cur_elt = g_list_next(cur_elt); // do not break case LUA_ASYNC_TYPENAME: luaA_push_type(L,luaA_type_find(L,type_elt->data),&data_elt->data); break; case LUA_ASYNC_DONE: default: // should never happen g_assert(false); break; } nargs++; } dt_lua_do_chunk_silent(L,nargs,0); dt_lua_redraw_screen(); dt_lua_unlock(); return 0; }
void file_chooser_button_init(lua_State* L) { lua_file_chooser_button file_chooser_button = malloc(sizeof(dt_lua_file_chooser_button_t)); file_chooser_button->parent.widget = gtk_file_chooser_button_new(lua_tostring(L,2),lua_toboolean(L,1)?GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:GTK_FILE_CHOOSER_ACTION_OPEN ); file_chooser_button->parent.type = &file_chooser_button_type; luaA_push_type(L, file_chooser_button_type.associated_type, &file_chooser_button); g_object_ref_sink(file_chooser_button->parent.widget); }
static void combobox_init(lua_State* L) { lua_combobox combobox = malloc(sizeof(dt_lua_combobox_t)); combobox->parent.widget = dt_bauhaus_combobox_new(NULL); if(lua_toboolean(L,1)) { dt_bauhaus_combobox_set_editable(combobox->parent.widget,1); } combobox->parent.type = &combobox_type; luaA_push_type(L, combobox_type.associated_type, &combobox); g_object_ref_sink(combobox->parent.widget); }
void dt_lua_push_glist_type(lua_State *L, GList *list, luaA_Type elt_type) { GList *elt = list; lua_newtable(L); while(elt) { luaA_push_type(L, elt_type, elt->data); luaL_ref(L, -2); elt = g_list_next(elt); } }
void dt_lua_widget_trigger_callback_glist(lua_State*L,lua_widget object,const char* name,GList*extra) { luaA_push_type(L,object->type->associated_type,&object); lua_getuservalue(L,-1); lua_getfield(L,-1,name); if(! lua_isnil(L,-1)) { lua_pushvalue(L,-3); GList* cur_elt = extra; int nargs = 1; while(cur_elt) { const char* next_type = cur_elt->data; cur_elt = g_list_next(cur_elt); luaA_push_type(L,luaA_type_find(L,next_type),&cur_elt->data); nargs++; cur_elt = g_list_next(cur_elt); } dt_lua_do_chunk(L,nargs,0); } dt_lua_redraw_screen(); g_list_free(extra); lua_pop(L,2); }
// internal function: to avoid exif blob reading + 8-bit byteorder flag + high-quality override int dt_imageio_export_with_flags(const uint32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const int32_t ignore_exif, const int32_t display_byteorder, const gboolean high_quality, const gboolean upscale, const int32_t thumbnail_export, const char *filter, const gboolean copy_metadata, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total) { dt_develop_t dev; dt_dev_init(&dev, 0); dt_dev_load_image(&dev, imgid); const int buf_is_downscaled = (thumbnail_export && dt_conf_get_bool("plugins/lighttable/low_quality_thumbnails")); dt_mipmap_buffer_t buf; if(buf_is_downscaled) dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_F, DT_MIPMAP_BLOCKING, 'r'); else dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING, 'r'); const dt_image_t *img = &dev.image_storage; if(!buf.buf || !buf.width || !buf.height) { fprintf(stderr, "allocation failed???\n"); dt_control_log(_("image `%s' is not available!"), img->filename); goto error_early; } const int wd = img->width; const int ht = img->height; const float max_scale = upscale ? 100.0 : 1.0; int res = 0; dt_times_t start; dt_get_times(&start); dt_dev_pixelpipe_t pipe; res = thumbnail_export ? dt_dev_pixelpipe_init_thumbnail(&pipe, wd, ht) : dt_dev_pixelpipe_init_export(&pipe, wd, ht, format->levels(format_params)); if(!res) { dt_control_log( _("failed to allocate memory for %s, please lower the threads used for export or buy more memory."), thumbnail_export ? C_("noun", "thumbnail export") : C_("noun", "export")); goto error; } // If a style is to be applied during export, add the iop params into the history if(!thumbnail_export && format_params->style[0] != '\0') { GList *style_items = dt_styles_get_item_list(format_params->style, TRUE, -1); if(!style_items) { dt_control_log(_("cannot find the style '%s' to apply during export."), format_params->style); goto error; } // remove everything above history_end GList *history = g_list_nth(dev.history, dev.history_end); while(history) { GList *next = g_list_next(history); dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); free(hist->params); free(hist->blend_params); free(history->data); dev.history = g_list_delete_link(dev.history, history); history = next; } // Add each params for(GList *iter = style_items; iter; iter = g_list_next(iter)) { dt_style_item_t *s = (dt_style_item_t *)iter->data; for(GList *module = dev.iop; module; module = g_list_next(module)) { dt_iop_module_t *m = (dt_iop_module_t *)module->data; if(!strcmp(m->op, s->operation)) { dt_dev_history_item_t *h = malloc(sizeof(dt_dev_history_item_t)); dt_iop_module_t *style_module = m; if((format_params->style_append && !(m->flags() & IOP_FLAGS_ONE_INSTANCE)) || m->multi_priority != s->multi_priority) { // dt_dev_module_duplicate() doesn't work here, it's trying too hard to be clever style_module = (dt_iop_module_t *)calloc(1, sizeof(dt_iop_module_t)); if(style_module && !dt_iop_load_module(style_module, m->so, m->dev)) { style_module->instance = m->instance; style_module->multi_priority = s->multi_priority; snprintf(style_module->multi_name, sizeof(style_module->multi_name), "%s", s->name); dev.iop = g_list_insert_sorted(dev.iop, style_module, sort_plugins); } else { free(h); goto error; } } h->params = s->params; h->blend_params = s->blendop_params; h->enabled = s->enabled; h->module = style_module; h->multi_priority = s->multi_priority; g_strlcpy(h->multi_name, s->name, sizeof(h->multi_name)); if(m->legacy_params && (s->module_version != m->version())) { void *new_params = malloc(m->params_size); m->legacy_params(m, h->params, s->module_version, new_params, labs(m->version())); free(h->params); h->params = new_params; } dev.history_end++; dev.history = g_list_append(dev.history, h); // make sure that dt_style_item_free doesn't free data we still use s->params = NULL; s->blendop_params = NULL; break; } } } g_list_free_full(style_items, dt_style_item_free); } dt_dev_pixelpipe_set_icc(&pipe, icc_type, icc_filename, icc_intent); dt_dev_pixelpipe_set_input(&pipe, &dev, (float *)buf.buf, buf.width, buf.height, buf.iscale); dt_dev_pixelpipe_create_nodes(&pipe, &dev); dt_dev_pixelpipe_synch_all(&pipe, &dev); if(filter) { if(!strncmp(filter, "pre:", 4)) dt_dev_pixelpipe_disable_after(&pipe, filter + 4); if(!strncmp(filter, "post:", 5)) dt_dev_pixelpipe_disable_before(&pipe, filter + 5); } dt_dev_pixelpipe_get_dimensions(&pipe, &dev, pipe.iwidth, pipe.iheight, &pipe.processed_width, &pipe.processed_height); dt_show_times(&start, "[export] creating pixelpipe", NULL); // find output color profile for this image: int sRGB = 1; if(icc_type == DT_COLORSPACE_SRGB) { sRGB = 1; } else if(icc_type == DT_COLORSPACE_NONE) { GList *modules = dev.iop; dt_iop_module_t *colorout = NULL; while(modules) { colorout = (dt_iop_module_t *)modules->data; if(colorout->get_p && strcmp(colorout->op, "colorout") == 0) { const dt_colorspaces_color_profile_type_t *type = colorout->get_p(colorout->params, "type"); sRGB = (!type || *type == DT_COLORSPACE_SRGB); break; // colorout can't have > 1 instance } modules = g_list_next(modules); } } else { sRGB = 0; } // get only once at the beginning, in case the user changes it on the way: const gboolean high_quality_processing = ((format_params->max_width == 0 || format_params->max_width >= pipe.processed_width) && (format_params->max_height == 0 || format_params->max_height >= pipe.processed_height)) ? FALSE : high_quality; const int width = format_params->max_width; const int height = format_params->max_height; const double scalex = width > 0 ? fminf(width / (double)pipe.processed_width, max_scale) : 1.0; const double scaley = height > 0 ? fminf(height / (double)pipe.processed_height, max_scale) : 1.0; const double scale = fminf(scalex, scaley); const int processed_width = scale * pipe.processed_width + .5f; const int processed_height = scale * pipe.processed_height + .5f; const int bpp = format->bpp(format_params); dt_get_times(&start); if(high_quality_processing) { /* * if high quality processing was requested, downsampling will be done * at the very end of the pipe (just before border and watermark) */ dt_dev_pixelpipe_process_no_gamma(&pipe, &dev, 0, 0, processed_width, processed_height, scale); } else { // else, downsampling will be right after demosaic // so we need to turn temporarily disable in-pipe late downsampling iop. // find the finalscale module dt_dev_pixelpipe_iop_t *finalscale = NULL; { GList *nodes = g_list_last(pipe.nodes); while(nodes) { dt_dev_pixelpipe_iop_t *node = (dt_dev_pixelpipe_iop_t *)(nodes->data); if(!strcmp(node->module->op, "finalscale")) { finalscale = node; break; } nodes = g_list_previous(nodes); } } if(finalscale) finalscale->enabled = 0; // do the processing (8-bit with special treatment, to make sure we can use openmp further down): if(bpp == 8) dt_dev_pixelpipe_process(&pipe, &dev, 0, 0, processed_width, processed_height, scale); else dt_dev_pixelpipe_process_no_gamma(&pipe, &dev, 0, 0, processed_width, processed_height, scale); if(finalscale) finalscale->enabled = 1; } dt_show_times(&start, thumbnail_export ? "[dev_process_thumbnail] pixel pipeline processing" : "[dev_process_export] pixel pipeline processing", NULL); uint8_t *outbuf = pipe.backbuf; // downconversion to low-precision formats: if(bpp == 8) { if(display_byteorder) { if(high_quality_processing) { const float *const inbuf = (float *)outbuf; for(size_t k = 0; k < (size_t)processed_width * processed_height; k++) { // convert in place, this is unfortunately very serial.. const uint8_t r = CLAMP(inbuf[4 * k + 2] * 0xff, 0, 0xff); const uint8_t g = CLAMP(inbuf[4 * k + 1] * 0xff, 0, 0xff); const uint8_t b = CLAMP(inbuf[4 * k + 0] * 0xff, 0, 0xff); outbuf[4 * k + 0] = r; outbuf[4 * k + 1] = g; outbuf[4 * k + 2] = b; } } // else processing output was 8-bit already, and no need to swap order } else // need to flip { // ldr output: char if(high_quality_processing) { const float *const inbuf = (float *)outbuf; for(size_t k = 0; k < (size_t)processed_width * processed_height; k++) { // convert in place, this is unfortunately very serial.. const uint8_t r = CLAMP(inbuf[4 * k + 0] * 0xff, 0, 0xff); const uint8_t g = CLAMP(inbuf[4 * k + 1] * 0xff, 0, 0xff); const uint8_t b = CLAMP(inbuf[4 * k + 2] * 0xff, 0, 0xff); outbuf[4 * k + 0] = r; outbuf[4 * k + 1] = g; outbuf[4 * k + 2] = b; } } else { // !display_byteorder, need to swap: uint8_t *const buf8 = pipe.backbuf; #ifdef _OPENMP #pragma omp parallel for default(none) schedule(static) #endif // just flip byte order for(size_t k = 0; k < (size_t)processed_width * processed_height; k++) { uint8_t tmp = buf8[4 * k + 0]; buf8[4 * k + 0] = buf8[4 * k + 2]; buf8[4 * k + 2] = tmp; } } } } else if(bpp == 16) { // uint16_t per color channel float *buff = (float *)outbuf; uint16_t *buf16 = (uint16_t *)outbuf; for(int y = 0; y < processed_height; y++) for(int x = 0; x < processed_width; x++) { // convert in place const size_t k = (size_t)processed_width * y + x; for(int i = 0; i < 3; i++) buf16[4 * k + i] = CLAMP(buff[4 * k + i] * 0x10000, 0, 0xffff); } } // else output float, no further harm done to the pixels :) format_params->width = processed_width; format_params->height = processed_height; if(!ignore_exif) { int length; uint8_t *exif_profile = NULL; // Exif data should be 65536 bytes max, but if original size is close to that, // adding new tags could make it go over that... so let it be and see what // happens when we write the image char pathname[PATH_MAX] = { 0 }; gboolean from_cache = TRUE; dt_image_full_path(imgid, pathname, sizeof(pathname), &from_cache); // last param is dng mode, it's false here length = dt_exif_read_blob(&exif_profile, pathname, imgid, sRGB, processed_width, processed_height, 0); res = format->write_image(format_params, filename, outbuf, icc_type, icc_filename, exif_profile, length, imgid, num, total); free(exif_profile); } else { res = format->write_image(format_params, filename, outbuf, icc_type, icc_filename, NULL, 0, imgid, num, total); } dt_dev_pixelpipe_cleanup(&pipe); dt_dev_cleanup(&dev); dt_mipmap_cache_release(darktable.mipmap_cache, &buf); /* now write xmp into that container, if possible */ if(copy_metadata && (format->flags(format_params) & FORMAT_FLAGS_SUPPORT_XMP)) { dt_exif_xmp_attach(imgid, filename); // no need to cancel the export if this fail } if(!thumbnail_export && strcmp(format->mime(format_params), "memory") && !(format->flags(format_params) & FORMAT_FLAGS_NO_TMPFILE)) { #ifdef USE_LUA //Synchronous calling of lua intermediate-export-image events dt_lua_lock(); lua_State *L = darktable.lua_state.state; luaA_push(L, dt_lua_image_t, &imgid); lua_pushstring(L, filename); luaA_push_type(L, format->parameter_lua_type, format_params); if (storage) luaA_push_type(L, storage->parameter_lua_type, storage_params); else lua_pushnil(L); dt_lua_event_trigger(L, "intermediate-export-image", 4); dt_lua_unlock(); #endif dt_control_signal_raise(darktable.signals, DT_SIGNAL_IMAGE_EXPORT_TMPFILE, imgid, filename, format, format_params, storage, storage_params); } return res; error: dt_dev_pixelpipe_cleanup(&pipe); error_early: dt_dev_cleanup(&dev); dt_mipmap_cache_release(darktable.mipmap_cache, &buf); return 1; }
static int store_wrapper(struct dt_imageio_module_storage_t *self, struct dt_imageio_module_data_t *self_data, const int imgid, dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total, const gboolean high_quality, const gboolean upscale) { /* construct a temporary file name */ char tmpdir[PATH_MAX] = { 0 }; gboolean from_cache = FALSE; dt_loc_get_tmp_dir(tmpdir, sizeof(tmpdir)); char dirname[PATH_MAX] = { 0 }; dt_image_full_path(imgid, dirname, sizeof(dirname), &from_cache); dt_image_path_append_version(imgid, dirname, sizeof(dirname)); gchar *filename = g_path_get_basename(dirname); gchar *end = g_strrstr(filename, ".") + 1; g_strlcpy(end, format->extension(fdata), sizeof(dirname) - (end - dirname)); gchar *complete_name = g_build_filename(tmpdir, filename, (char *)NULL); if(dt_imageio_export(imgid, complete_name, format, fdata, high_quality, upscale, FALSE, self, self_data, num, total) != 0) { fprintf(stderr, "[%s] could not export to file: `%s'!\n", self->name(self), complete_name); g_free(complete_name); g_free(filename); return 1; } lua_storage_t *d = (lua_storage_t *)self_data; dt_lua_lock(); lua_State *L = darktable.lua_state.state; push_lua_data(L,d); dt_lua_goto_subtable(L,"files"); luaA_push(L, dt_lua_image_t, &(imgid)); lua_pushstring(L, complete_name); lua_settable(L, -3); lua_pop(L,1); lua_getfield(L, LUA_REGISTRYINDEX, "dt_lua_storages"); lua_getfield(L, -1, self->plugin_name); lua_getfield(L, -1, "store"); if(lua_isnil(L, -1)) { lua_pop(L, 3); dt_lua_unlock(); g_free(filename); return 0; } luaA_push_type(L, self->parameter_lua_type, self_data); luaA_push(L, dt_lua_image_t, &imgid); luaA_push_type(L, format->parameter_lua_type, fdata); lua_pushstring(L, complete_name); lua_pushnumber(L, num); lua_pushnumber(L, total); lua_pushboolean(L, high_quality); push_lua_data(L,d); dt_lua_goto_subtable(L,"extra"); dt_lua_treated_pcall(L,8,0); lua_pop(L, 2); dt_lua_unlock(); g_free(filename); return false; }
static int register_storage(lua_State *L) { lua_settop(L, 7); lua_getfield(L, LUA_REGISTRYINDEX, "dt_lua_storages"); lua_newtable(L); dt_imageio_module_storage_t *storage = malloc(sizeof(dt_imageio_module_storage_t)); memcpy(storage, &ref_storage, sizeof(dt_imageio_module_storage_t)); storage->gui_data = malloc(sizeof(lua_storage_gui_t)); lua_storage_gui_t *data = storage->gui_data; const char *plugin_name = luaL_checkstring(L, 1); lua_pushvalue(L, 1); lua_setfield(L, -2, "plugin_name"); g_strlcpy(storage->plugin_name, plugin_name, sizeof(storage->plugin_name)); const char *name = luaL_checkstring(L, 2); lua_pushvalue(L, 2); lua_setfield(L, -2, "name"); data->name = strdup(name); data->supported_formats = NULL; data->widget = NULL; if(!lua_isnoneornil(L, 3)) { luaL_checktype(L, 3, LUA_TFUNCTION); lua_pushvalue(L, 3); lua_setfield(L, -2, "store"); } if(lua_isnil(L, 4)) { storage->finalize_store = NULL; } else { luaL_checktype(L, 4, LUA_TFUNCTION); lua_pushvalue(L, 4); lua_setfield(L, -2, "finalize_store"); } if(!lua_isnoneornil(L, 5)) { luaL_checktype(L, 5, LUA_TFUNCTION); lua_pushvalue(L, 5); lua_setfield(L, -2, "supported"); } if(lua_isnil(L, 6)) { storage->initialize_store = NULL; } else { luaL_checktype(L, 6, LUA_TFUNCTION); lua_pushvalue(L, 6); lua_setfield(L, -2, "initialize_store"); } if(lua_isnil(L, 7)) { storage->gui_init = empty_wrapper; storage->gui_reset = empty_wrapper; storage->gui_cleanup = empty_wrapper; } else { lua_widget widget; luaA_to(L,lua_widget,&widget,7); dt_lua_widget_bind(L,widget); data->widget = widget; } lua_setfield(L, -2, plugin_name); char tmp[1024]; snprintf(tmp, sizeof(tmp), "dt_imageio_module_data_pseudo_%s", storage->plugin_name); luaA_Type type_id = luaA_type_add(L, tmp, storage->params_size(storage)); storage->parameter_lua_type = dt_lua_init_type_type(darktable.lua_state.state, type_id); luaA_struct_type(darktable.lua_state.state, type_id); dt_lua_register_storage_type(darktable.lua_state.state, storage, type_id); GList *it = darktable.imageio->plugins_format; if(!lua_isnoneornil(L, 5)) { while(it) { lua_pushvalue(L, 5); dt_imageio_module_format_t *format = (dt_imageio_module_format_t *)it->data; dt_imageio_module_data_t *sdata = storage->get_params(storage); dt_imageio_module_data_t *fdata = format->get_params(format); luaA_push_type(L, storage->parameter_lua_type, sdata); luaA_push_type(L, format->parameter_lua_type, fdata); format->free_params(format, fdata); storage->free_params(storage, sdata); dt_lua_treated_pcall(L,2,1); int result = lua_toboolean(L, -1); lua_pop(L, 1); if(result) { data->supported_formats = g_list_prepend(data->supported_formats, format); } it = g_list_next(it); } } else { // all formats are supported while(it) { dt_imageio_module_format_t *format = (dt_imageio_module_format_t *)it->data; data->supported_formats = g_list_prepend(data->supported_formats, format); it = g_list_next(it); } } storage->gui_init(storage); if(storage->widget) g_object_ref(storage->widget); dt_imageio_insert_storage(storage); return 0; }
// FIXME: return 0 on success and 1 on error! static int initialize_store_wrapper(struct dt_imageio_module_storage_t *self, dt_imageio_module_data_t *data, dt_imageio_module_format_t **format, dt_imageio_module_data_t **fdata, GList **images, const gboolean high_quality, const gboolean upscale) { dt_lua_lock(); lua_State *L = darktable.lua_state.state; lua_getfield(L, LUA_REGISTRYINDEX, "dt_lua_storages"); lua_getfield(L, -1, self->plugin_name); lua_getfield(L, -1, "initialize_store"); if(lua_isnil(L, -1)) { lua_pop(L, 3); dt_lua_unlock(); return 1; } luaA_push_type(L, self->parameter_lua_type, data); luaA_push_type(L, (*format)->parameter_lua_type, *fdata); GList *imgids = *images; lua_newtable(L); while(imgids) { luaA_push(L, dt_lua_image_t, &(imgids->data)); luaL_ref(L, -2); imgids = g_list_next(imgids); } lua_pushboolean(L, high_quality); lua_storage_t *d = (lua_storage_t *)data; push_lua_data(L,d); dt_lua_goto_subtable(L,"extra"); dt_lua_treated_pcall(L,5,1); if(!lua_isnoneornil(L, -1)) { g_list_free(*images); if(lua_type(L,-1) != LUA_TTABLE) { dt_print(DT_DEBUG_LUA, "LUA ERROR initialization function of storage did not return nil or table\n"); dt_lua_unlock(); return 1; } GList *new_images = NULL; lua_pushnil(L); while(lua_next(L, -2)) { dt_lua_image_t imgid; luaA_to(L, dt_lua_image_t, &imgid, -1); new_images = g_list_prepend(new_images, GINT_TO_POINTER(imgid)); lua_pop(L, 1); } new_images = g_list_reverse(new_images); *images = new_images; } lua_pop(L, 3); dt_lua_unlock(); return 0; }