Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
iop-autoset.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel
3 Copyright (C) 2026 - Aurélien PIERRE
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "iop-autoset.h"
20#include "develop/develop.h"
21#include "develop/pixelpipe.h"
24#include "develop/imageop.h"
25#include "control/conf.h"
26#include "control/control.h"
27
28#include <glib.h>
29
30static void _dt_iop_autoset_restart_cache_wait(gpointer user_data)
31{
32 dt_autoset_manager_t *manager = (dt_autoset_manager_t *)user_data;
33 if(IS_NULL_PTR(manager) || IS_NULL_PTR(manager->dev)) return;
34
35 dt_iop_autoset_advance(manager->dev, manager);
36}
37
39{
40 if(IS_NULL_PTR(module)) return NULL;
41 gchar *key = g_strdup_printf("plugins/darkroom/autoset/%s/%i", module->op, module->multi_priority);
42 return key;
43}
44
46{
47 gchar *key = dt_iop_autoset_get_conf_key(module);
48 if(IS_NULL_PTR(key)) return FALSE;
49
50 const gboolean enabled = !dt_conf_key_exists(key) || dt_conf_get_int(key) != 0;
51 g_free(key);
52 return enabled;
53}
54
55void dt_iop_autoset_module_set_enabled(const dt_iop_module_t *module, const gboolean enabled)
56{
57 gchar *key = dt_iop_autoset_get_conf_key(module);
58 if(IS_NULL_PTR(key)) return;
59
60 dt_conf_set_int(key, enabled ? 1 : 0);
61 g_free(key);
62}
63
65{
66 if(IS_NULL_PTR(manager->input_wait))
67 manager->input_wait = g_malloc0(sizeof(dt_dev_pixelpipe_cache_wait_t));
69 manager->dev = dev;
70 if(!IS_NULL_PTR(input_wait))
71 dt_dev_pixelpipe_cache_wait_cleanup(input_wait, "autoset-build-list-reset");
72
73 if(manager->progress_cursor_active)
74 {
77 }
78
79 g_list_free(manager->iop_to_set);
80 manager->iop_to_set = NULL;
82 for(GList *mod = g_list_first(dev->iop); mod; mod = g_list_next(mod))
83 {
84 dt_iop_module_t * module = (dt_iop_module_t *)mod->data;
85 if(module->enabled && !IS_NULL_PTR(module->autoset) && dt_iop_autoset_module_is_enabled(module))
86 {
87 manager->iop_to_set = g_list_append(manager->iop_to_set, module);
88 fprintf(stdout, "adding %s\n", module->op);
89 }
90 }
91
92 // Start immediately in case we already have the output in cache
93 dt_iop_autoset_advance(dev, manager);
94 // If the cacheline was not found, request was sent to pipeline so just retry later.
95}
96
98{
99 if(IS_NULL_PTR(manager->input_wait))
100 manager->input_wait = g_malloc0(sizeof(dt_dev_pixelpipe_cache_wait_t));
102
103 GList *mod = g_list_first(manager->iop_to_set);
104 dt_dev_pixelpipe_t *pipe = dev->preview_pipe;
105 if(IS_NULL_PTR(mod))
106 {
107 if(!IS_NULL_PTR(input_wait))
108 dt_dev_pixelpipe_cache_wait_cleanup(input_wait, "autoset-finished");
109 pipe->autoset = FALSE;
110 if(manager->progress_cursor_active)
111 {
113 manager->progress_cursor_active = FALSE;
114 }
115 return 1;
116 }
117
118 // Enter busy cursor exactly when the first autoset operation starts.
119 if(!manager->progress_cursor_active)
120 {
123 manager->progress_cursor_active = TRUE;
124 }
125
126 dt_iop_module_t *module = (dt_iop_module_t *)mod->data;
127 if(IS_NULL_PTR(module))
128 {
129 if(!IS_NULL_PTR(input_wait))
130 dt_dev_pixelpipe_cache_wait_cleanup(input_wait, "autoset-module-missing");
131 pipe->autoset = FALSE;
132 if(manager->progress_cursor_active)
133 {
135 manager->progress_cursor_active = FALSE;
136 }
137 return 1;
138 }
139
140 fprintf(stdout, "trying to fetch cache from %s\n", module->op);
141
142 // Note: module pieces (aka pipeline nodes) are not stable in time:
143 // pipeline can be completely destroyed and reconstructed. So we can't store
144 // direct references, we need to grab the current piece attached to module
145 // in the current pipeline.
146 const dt_dev_pixelpipe_iop_t *const piece = dt_dev_pixelpipe_get_module_piece(pipe, module);
147 if(IS_NULL_PTR(piece)) return 1;
148 const dt_dev_pixelpipe_iop_t *const input_piece = dt_dev_pixelpipe_get_prev_enabled_piece(pipe, piece);
149 if(IS_NULL_PTR(input_piece)) return 1;
150
151 // Get the corresponding pipeline cache entry immediately if possible,
152 // else the following function requests a partial pipe recompute
153 dt_pixel_cache_entry_t *entry = NULL;
154 void *input = NULL;
155 if(IS_NULL_PTR(input_wait))
156 return 1;
157 dt_dev_pixelpipe_cache_wait_set_owner(input_wait, "autoset-input", manager);
158 if(!dt_dev_pixelpipe_cache_peek_gui(pipe, input_piece, &input, &entry,
159 input_wait, _dt_iop_autoset_restart_cache_wait, manager))
160 return 1;
161
162 fprintf(stdout, "processing %s\n", module->op);
163
164 // module->autoset will manipulate the internal parameters of the module
165 // outside of the normal control flow (GUI).
166 // We need to protect any concurrent params writing from the GUI
167 // and write history while we still have the lock.
169
171 module->autoset(module, pipe, piece, input);
173
174 dt_dev_add_history_item(dev, module, FALSE, FALSE);
176
177 // Params have changed, update the module GUI to reflect it.
178 dt_iop_gui_update(module);
179
180 manager->iop_to_set = g_list_delete_link(manager->iop_to_set, mod);
181 if(IS_NULL_PTR(manager->iop_to_set))
182 {
183 if(!IS_NULL_PTR(input_wait))
184 dt_dev_pixelpipe_cache_wait_cleanup(input_wait, "autoset-list-empty");
185 pipe->autoset = FALSE;
186 if(manager->progress_cursor_active)
187 {
189 manager->progress_cursor_active = FALSE;
190 }
191 }
192 return 0;
193}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
char * key
int dt_conf_key_exists(const char *key)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_control_log_busy_leave()
Definition control.c:840
void dt_control_change_cursor_by_name_and_flush(const char *curs_str)
Apply a named cursor immediatelly and flush display updates for immediate feedback.
Definition control.c:326
void dt_control_log_busy_enter()
Definition control.c:824
darktable_t darktable
Definition darktable.c:181
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
#define dt_dev_add_history_item(dev, module, enable, redraw)
const dt_dev_pixelpipe_iop_t * dt_dev_pixelpipe_get_module_piece(const dt_dev_pixelpipe_t *pipe, const dt_iop_module_t *module)
void dt_dev_pixelpipe_cache_wait_cleanup(dt_dev_pixelpipe_cache_wait_t *wait, const char *reason)
Cancel one pending GUI cache wait request and clear its runtime state.
const dt_dev_pixelpipe_iop_t * dt_dev_pixelpipe_get_prev_enabled_piece(const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void dt_dev_pixelpipe_cache_wait_set_owner(dt_dev_pixelpipe_cache_wait_t *wait, const char *owner_tag, gpointer owner_object)
Attach debug ownership metadata to one cache wait request.
gboolean dt_dev_pixelpipe_cache_peek_gui(dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, void **data, dt_pixel_cache_entry_t **cache_entry, dt_dev_pixelpipe_cache_wait_t *wait, dt_dev_pixelpipe_cache_ready_callback_t restart, gpointer restart_data)
void dt_iop_gui_update(dt_iop_module_t *module)
Definition imageop.c:2091
static void dt_iop_gui_enter_critical_section(dt_iop_module_t *const module) ACQUIRE(&module -> gui_lock)
Definition imageop.h:413
static void dt_iop_gui_leave_critical_section(dt_iop_module_t *const module) RELEASE(&module -> gui_lock)
Definition imageop.h:419
int dt_iop_autoset_advance(struct dt_develop_t *dev, dt_autoset_manager_t *manager)
Definition iop-autoset.c:97
gboolean dt_iop_autoset_module_is_enabled(const dt_iop_module_t *module)
Definition iop-autoset.c:45
void dt_iop_autoset_build_list(struct dt_develop_t *dev, dt_autoset_manager_t *manager)
Definition iop-autoset.c:64
static void _dt_iop_autoset_restart_cache_wait(gpointer user_data)
Definition iop-autoset.c:30
void dt_iop_autoset_module_set_enabled(const dt_iop_module_t *module, const gboolean enabled)
Definition iop-autoset.c:55
gchar * dt_iop_autoset_get_conf_key(const dt_iop_module_t *module)
Definition iop-autoset.c:38
void dt_dev_pixelpipe_cache_rdlock_entry(dt_dev_pixelpipe_cache_t *cache, gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the read lock on the entry.
Pixelpipe cache for storing intermediate results in the pixelpipe.
struct dt_dev_pixelpipe_cache_t * pixelpipe_cache
Definition darktable.h:790
struct dt_develop_t * dev
Definition iop-autoset.h:25
gboolean progress_cursor_active
Definition iop-autoset.h:24
GList * iop
Definition develop.h:279
struct dt_dev_pixelpipe_t * preview_pipe
Definition develop.h:247
GModule *dt_dev_operation_t op
Definition imageop.h:256