/* This file is part of darktable, Copyright (C) 2019-2024 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. darktable is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with darktable. If not, see . */ #include "common/darktable.h" #include "common/debug.h" #include "common/presets.h" #include "control/signal.h" #include "bauhaus/bauhaus.h" #include "gui/gtk.h" #include "libs/lib.h" #include #include #include DT_MODULE(1) typedef struct dt_lib_ioporder_t { int current_mode; } dt_lib_ioporder_t; const char *name(dt_lib_module_t *self) { return _("module order"); } dt_view_type_flags_t views(dt_lib_module_t *self) { return DT_VIEW_DARKROOM; } uint32_t container(dt_lib_module_t *self) { return DT_UI_CONTAINER_PANEL_RIGHT_BOTTOM; } int position(const dt_lib_module_t *self) { return 880; } static void _update(dt_lib_module_t *self) { dt_lib_ioporder_t *d = self->data; if(self->arrow) gtk_widget_destroy(self->arrow); self->arrow = NULL; const dt_iop_order_t kind = dt_ioppr_get_iop_order_list_kind(darktable.develop->iop_order_list); if(kind == DT_IOP_ORDER_CUSTOM) { gchar *iop_order_list = dt_ioppr_serialize_text_iop_order_list(darktable.develop->iop_order_list); gboolean found = FALSE; int index = 0; GList *presets = dt_presets_list_all_params("ioporder", FALSE); for(const GList *l = presets; l; l = g_list_next(l)) { const dt_presets_params_t *preset = l->data; const char *params = preset->op_params; const int32_t params_len = preset->op_params_size; const char *name = preset->name; GList *iop_list = dt_ioppr_deserialize_iop_order_list(params, params_len); gchar *iop_list_text = dt_ioppr_serialize_text_iop_order_list(iop_list); g_list_free(iop_list); index++; if(!strcmp(iop_order_list, iop_list_text)) { dt_lib_gui_set_label(self, name); d->current_mode = index; found = TRUE; g_free(iop_list_text); break; } g_free(iop_list_text); } g_list_free_full(presets, dt_presets_params_free); g_free(iop_order_list); if(!found) { d->current_mode = DT_IOP_ORDER_CUSTOM; dt_lib_gui_set_label(self, _(dt_iop_order_string(d->current_mode))); } } else { d->current_mode = kind; dt_lib_gui_set_label(self, _(dt_iop_order_string(d->current_mode))); } } static void _image_loaded_callback(gpointer instance, dt_lib_module_t *self) { // only in darkroom, so let's avoid any update when in lighttable if(dt_view_get_current() == DT_VIEW_DARKROOM) { _update(self); } } void gui_init(dt_lib_module_t *self) { dt_lib_ioporder_t *d = malloc(sizeof(dt_lib_ioporder_t)); self->data = (void *)d; d->current_mode = -1; DT_CONTROL_SIGNAL_HANDLE(DT_SIGNAL_DEVELOP_IMAGE_CHANGED, _image_loaded_callback); DT_CONTROL_SIGNAL_HANDLE(DT_SIGNAL_DEVELOP_INITIALIZE, _image_loaded_callback); DT_CONTROL_SIGNAL_HANDLE(DT_SIGNAL_DEVELOP_HISTORY_CHANGE, _image_loaded_callback); } void gui_cleanup(dt_lib_module_t *self) { free(self->data); self->data = NULL; } void gui_reset(dt_lib_module_t *self) { dt_lib_ioporder_t *d = self->data; // the module reset is use to select the proper default iop-order const gboolean is_ldr = dt_image_is_ldr(&darktable.develop->image_storage); const dt_iop_order_t iop_order = is_ldr ? DT_DEFAULT_IOP_ORDER_JPG : DT_DEFAULT_IOP_ORDER_RAW; GList *iop_order_list = dt_ioppr_get_iop_order_list_version(iop_order); if(iop_order_list) { const dt_imgid_t imgid = darktable.develop->image_storage.id; dt_ioppr_change_iop_order(darktable.develop, imgid, iop_order_list); dt_dev_pixelpipe_rebuild(darktable.develop); d->current_mode = iop_order; dt_lib_gui_set_label(self, _(dt_iop_order_string(d->current_mode))); g_list_free_full(iop_order_list, free); } } void init_presets(dt_lib_module_t *self) { size_t size = 0; char *params = NULL; GList *list; self->pref_based_presets = TRUE; const gboolean is_display_referred = dt_is_display_referred(); list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_LEGACY); params = dt_ioppr_serialize_iop_order_list(list, &size); dt_lib_presets_add(_("legacy"), self->plugin_name, self->version(), (const char *)params, (int32_t)size, TRUE, is_display_referred ? FOR_RAW | FOR_LDR : 0); free(params); dt_ioppr_iop_order_list_free(list); list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V30); params = dt_ioppr_serialize_iop_order_list(list, &size); dt_lib_presets_add(_("v3.0 for RAW input"), self->plugin_name, self->version(), (const char *)params, (int32_t)size, TRUE, 0); free(params); dt_ioppr_iop_order_list_free(list); list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V30_JPG); params = dt_ioppr_serialize_iop_order_list(list, &size); dt_lib_presets_add(_("v3.0 for JPEG/non-RAW input"), self->plugin_name, self->version(), (const char *)params, (int32_t)size, TRUE, 0); free(params); dt_ioppr_iop_order_list_free(list); // make it the default for new RAW list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V50); params = dt_ioppr_serialize_iop_order_list(list, &size); dt_lib_presets_add(_("v5.0 for RAW input"), self->plugin_name, self->version(), (const char *)params, (int32_t)size, TRUE, is_display_referred ? 0 : FOR_RAW | FOR_MATRIX); free(params); dt_ioppr_iop_order_list_free(list); list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V50_JPG); params = dt_ioppr_serialize_iop_order_list(list, &size); dt_lib_presets_add(_("v5.0 for JPEG/non-RAW input"), self->plugin_name, self->version(), (const char *)params, (int32_t)size, TRUE, is_display_referred ? 0 : FOR_LDR | FOR_NOT_MONO); free(params); dt_ioppr_iop_order_list_free(list); } int set_params(dt_lib_module_t *self, const void *params, int size) { if(!params) return 1; GList *iop_order_list = dt_ioppr_deserialize_iop_order_list(params, (size_t)size); if(iop_order_list) { const dt_imgid_t imgid = darktable.develop->image_storage.id; dt_ioppr_change_iop_order(darktable.develop, imgid, iop_order_list); dt_dev_pixelpipe_rebuild(darktable.develop); _update(self); g_list_free_full(iop_order_list, free); return 0; } else { return 1; } } void *get_params(dt_lib_module_t *self, int *size) { size_t p_size = 0; void *params = dt_ioppr_serialize_iop_order_list(darktable.develop->iop_order_list, &p_size); *size = (int)p_size; return params; } gboolean preset_autoapply(dt_lib_module_t *self) { return TRUE; } // clang-format off // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py // vim: shiftwidth=2 expandtab tabstop=2 cindent // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified; // clang-format on