Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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();
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
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);

}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
  }
}
Beispiel #9
0
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);
}
Beispiel #10
0
// 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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
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;
}