1 /*
2 This file is part of darktable,
3 Copyright (C) 2013-2020 darktable developers.
4
5 darktable 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 darktable 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 "lua/styles.h"
20 #include "common/debug.h"
21 #include "common/styles.h"
22 #include "lua/glist.h"
23 #include "lua/image.h"
24 #include "lua/types.h"
25
26
27 // can't use glist functions we need a list of int and glist can only produce a list of int*
28 static GList *style_item_table_to_id_list(lua_State *L, int index);
29
30 /////////////////////////
31 // dt_style_t
32 /////////////////////////
style_gc(lua_State * L)33 static int style_gc(lua_State *L)
34 {
35 dt_style_t style;
36 luaA_to(L, dt_style_t, &style, -1);
37 g_free(style.name);
38 g_free(style.description);
39 return 0;
40 }
41
style_tostring(lua_State * L)42 static int style_tostring(lua_State *L)
43 {
44 dt_style_t style;
45 luaA_to(L, dt_style_t, &style, 1);
46 lua_pushstring(L, style.name);
47 return 1;
48 }
49
50
style_delete(lua_State * L)51 static int style_delete(lua_State *L)
52 {
53 dt_style_t style;
54 luaA_to(L, dt_style_t, &style, 1);
55 dt_styles_delete_by_name(style.name);
56 return 0;
57 }
58
59
style_duplicate(lua_State * L)60 static int style_duplicate(lua_State *L)
61 {
62 dt_style_t style;
63 luaA_to(L, dt_style_t, &style, 1);
64 const char *newname = luaL_checkstring(L, 2);
65 const char *description = lua_isnoneornil(L, 3) ? style.description : luaL_checkstring(L, 3);
66 GList *filter = style_item_table_to_id_list(L, 4);
67 dt_styles_create_from_style(style.name, newname, description, filter, -1, NULL, TRUE, FALSE);
68 g_list_free(filter);
69 return 0;
70 }
71
style_getnumber(lua_State * L)72 static int style_getnumber(lua_State *L)
73 {
74 int index = luaL_checknumber(L, -1);
75 if(index <= 0)
76 {
77 return luaL_error(L, "incorrect index for style");
78 }
79 dt_style_t style;
80 luaA_to(L, dt_style_t, &style, -2);
81 GList *items = dt_styles_get_item_list(style.name, TRUE, -1);
82 dt_style_item_t *item = g_list_nth_data(items, index - 1);
83 if(!item)
84 {
85 return luaL_error(L, "incorrect index for style");
86 }
87 items = g_list_remove(items, item);
88 g_list_free_full(items, dt_style_item_free);
89 luaA_push(L, dt_style_item_t, item);
90 free(item);
91 return 1;
92 }
93
94
style_length(lua_State * L)95 static int style_length(lua_State *L)
96 {
97
98 dt_style_t style;
99 luaA_to(L, dt_style_t, &style, -1);
100 GList *items = dt_styles_get_item_list(style.name, TRUE, -1);
101 lua_pushinteger(L, g_list_length(items));
102 g_list_free_full(items, dt_style_item_free);
103 return 1;
104 }
105
106
name_member(lua_State * L)107 static int name_member(lua_State *L)
108 {
109 dt_style_t style;
110 luaA_to(L, dt_style_t, &style, 1);
111 if(lua_gettop(L) != 3)
112 {
113 lua_pushstring(L, style.name);
114 return 1;
115 }
116 else
117 {
118 const char *newval;
119 newval = luaL_checkstring(L, 3);
120 dt_styles_update(style.name, newval, style.description, NULL, -1, NULL, FALSE, FALSE);
121 return 0;
122 }
123 }
124
description_member(lua_State * L)125 static int description_member(lua_State *L)
126 {
127 dt_style_t style;
128 luaA_to(L, dt_style_t, &style, 1);
129 if(lua_gettop(L) != 3)
130 {
131 lua_pushstring(L, style.description);
132 return 1;
133 }
134 else
135 {
136 const char *newval;
137 newval = luaL_checkstring(L, -1);
138 dt_styles_update(style.name, style.name, newval, NULL, -1, NULL, FALSE, FALSE);
139 return 0;
140 }
141 }
142
143
144 /////////////////////////
145 // dt_style_item_t
146 /////////////////////////
147
style_item_tostring(lua_State * L)148 static int style_item_tostring(lua_State *L)
149 {
150 dt_style_item_t *item = luaL_checkudata(L, -1, "dt_style_item_t");
151 lua_pushfstring(L, "%d : %s", item->num, item->name);
152 return 1;
153 }
154
style_item_gc(lua_State * L)155 static int style_item_gc(lua_State *L)
156 {
157 // FIXME: Can't we use dt_style_item_free() instead? Or may the pointer itself not be freed?
158 dt_style_item_t *item = luaL_checkudata(L, -1, "dt_style_item_t");
159 g_free(item->name);
160 g_free(item->operation);
161 free(item->params);
162 free(item->blendop_params);
163 return 0;
164 }
165
style_item_table_to_id_list(lua_State * L,int index)166 static GList *style_item_table_to_id_list(lua_State *L, int index)
167 {
168 if(lua_isnoneornil(L, index)) return NULL;
169 luaL_checktype(L, index, LUA_TTABLE);
170 lua_pushnil(L); /* first key */
171 GList *result = NULL;
172 while(lua_next(L, index) != 0)
173 {
174 /* uses 'key' (at index -2) and 'value' (at index -1) */
175 dt_style_item_t *item = luaL_checkudata(L, -1, "dt_style_item_t");
176 result = g_list_prepend(result, GINT_TO_POINTER(item->num));
177 lua_pop(L, 1);
178 }
179 result = g_list_reverse(result);
180 return result;
181 }
182
183 /////////////////////////
184 // toplevel and common
185 /////////////////////////
style_table_index(lua_State * L)186 static int style_table_index(lua_State *L)
187 {
188 int index = luaL_checkinteger(L, -1);
189 if(index < 1)
190 {
191 return luaL_error(L, "incorrect index in database");
192 }
193 sqlite3_stmt *stmt = NULL;
194 char query[1024];
195 snprintf(query, sizeof(query), "SELECT name FROM data.styles ORDER BY name LIMIT 1 OFFSET %d", index - 1);
196 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
197 if(sqlite3_step(stmt) == SQLITE_ROW)
198 {
199 const char *name = (const char *)sqlite3_column_text(stmt, 0);
200 dt_style_t *style = dt_styles_get_by_name(name);
201 luaA_push(L, dt_style_t, style);
202 free(style);
203 }
204 else
205 {
206 lua_pushnil(L);
207 }
208 sqlite3_finalize(stmt);
209 return 1;
210 }
211
style_table_len(lua_State * L)212 static int style_table_len(lua_State *L)
213 {
214 sqlite3_stmt *stmt = NULL;
215 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT COUNT(*) FROM data.styles", -1, &stmt, NULL);
216 if(sqlite3_step(stmt) == SQLITE_ROW)
217 lua_pushinteger(L, sqlite3_column_int(stmt, 0));
218 else
219 {
220 lua_pushinteger(L, 0);
221 }
222 sqlite3_finalize(stmt);
223 return 1;
224 }
225
dt_lua_style_create_from_image(lua_State * L)226 int dt_lua_style_create_from_image(lua_State *L)
227 {
228 dt_lua_image_t imgid;
229 luaA_to(L, dt_lua_image_t, &imgid, -3);
230 const char *newname = luaL_checkstring(L, -2);
231 const char *description = lua_isnoneornil(L, -1) ? "" : luaL_checkstring(L, -1);
232 dt_styles_create_from_image(newname, description, imgid, NULL, TRUE);
233 GList *style_list = dt_styles_get_list(newname);
234 while(style_list)
235 {
236 dt_style_t *data = style_list->data;
237 if(!strcmp(data->name, newname))
238 {
239 luaA_push(L, dt_style_t, data);
240 g_free(data);
241 style_list = g_list_delete_link(style_list, style_list);
242 }
243 }
244 g_list_free_full(style_list, dt_style_free); // deal with what's left
245 return 1;
246 }
247
dt_lua_style_apply(lua_State * L)248 int dt_lua_style_apply(lua_State *L)
249 {
250 dt_lua_image_t imgid = -1;
251 dt_style_t style;
252 if(luaL_testudata(L, 1, "dt_lua_image_t"))
253 {
254 luaA_to(L, dt_lua_image_t, &imgid, 1);
255 luaA_to(L, dt_style_t, &style, 2);
256 }
257 else
258 {
259 luaA_to(L, dt_style_t, &style, 1);
260 luaA_to(L, dt_lua_image_t, &imgid, 2);
261 }
262 dt_styles_apply_to_image(style.name, FALSE, FALSE, imgid);
263 DT_DEBUG_CONTROL_SIGNAL_RAISE(darktable.signals, DT_SIGNAL_TAG_CHANGED);
264 return 1;
265 }
266
dt_lua_style_import(lua_State * L)267 int dt_lua_style_import(lua_State *L)
268 {
269 const char *filename = luaL_checkstring(L, 1);
270 dt_styles_import_from_file(filename);
271 return 0;
272 }
273
dt_lua_style_export(lua_State * L)274 int dt_lua_style_export(lua_State *L)
275 {
276 dt_style_t style;
277 luaA_to(L, dt_style_t, &style, 1);
278 const char *filename = lua_tostring(L, 2);
279 if(!filename) filename = ".";
280 gboolean overwrite = lua_toboolean(L, 3);
281 dt_styles_save_to_file(style.name, filename, overwrite);
282 return 0;
283 }
284
285
286
dt_lua_init_styles(lua_State * L)287 int dt_lua_init_styles(lua_State *L)
288 {
289 // dt_style
290 dt_lua_init_type(L, dt_style_t);
291 lua_pushcfunction(L, name_member);
292 dt_lua_type_register_const(L, dt_style_t, "name");
293 lua_pushcfunction(L, description_member);
294 dt_lua_type_register_const(L, dt_style_t, "description");
295 lua_pushcfunction(L, style_length);
296 lua_pushcfunction(L, style_getnumber);
297 dt_lua_type_register_number_const(L, dt_style_t);
298 lua_pushcfunction(L, style_duplicate);
299 lua_pushcclosure(L, dt_lua_type_member_common, 1);
300 dt_lua_type_register_const(L, dt_style_t, "duplicate");
301 lua_pushcfunction(L, style_delete);
302 lua_pushcclosure(L, dt_lua_type_member_common, 1);
303 dt_lua_type_register_const(L, dt_style_t, "delete");
304 lua_pushcfunction(L, dt_lua_style_apply);
305 lua_pushcclosure(L, dt_lua_type_member_common, 1);
306 dt_lua_type_register_const(L, dt_style_t, "apply");
307 lua_pushcfunction(L, dt_lua_style_export);
308 lua_pushcclosure(L, dt_lua_type_member_common, 1);
309 dt_lua_type_register_const(L, dt_style_t, "export");
310 lua_pushcfunction(L, style_gc);
311 dt_lua_type_setmetafield(L,dt_style_t,"__gc");
312 lua_pushcfunction(L, style_tostring);
313 dt_lua_type_setmetafield(L,dt_style_t,"__tostring");
314
315 // dt_style_item_t
316 dt_lua_init_type(L, dt_style_item_t);
317 luaA_struct(L, dt_style_item_t);
318 luaA_struct_member(L, dt_style_item_t, num, const int);
319 luaA_struct_member(L, dt_style_item_t, name, const_string);
320 lua_pushcfunction(L, dt_lua_type_member_luaautoc);
321 dt_lua_type_register_struct(L, dt_style_item_t);
322 lua_pushcfunction(L, style_item_gc);
323 dt_lua_type_setmetafield(L,dt_style_item_t,"__gc");
324 lua_pushcfunction(L, style_item_tostring);
325 dt_lua_type_setmetafield(L,dt_style_item_t,"__tostring");
326
327
328
329 /* style table type */
330 dt_lua_push_darktable_lib(L);
331 luaA_Type type_id = dt_lua_init_singleton(L, "style_table", NULL);
332 lua_setfield(L, -2, "styles");
333 lua_pop(L, 1);
334
335 lua_pushcfunction(L, style_table_len);
336 lua_pushcfunction(L, style_table_index);
337 dt_lua_type_register_number_const_type(L, type_id);
338 lua_pushcfunction(L, style_duplicate);
339 lua_pushcclosure(L, dt_lua_type_member_common, 1);
340 dt_lua_type_register_const_type(L, type_id, "duplicate");
341 lua_pushcfunction(L, style_delete);
342 lua_pushcclosure(L, dt_lua_type_member_common, 1);
343 dt_lua_type_register_const_type(L, type_id, "delete");
344 lua_pushcfunction(L, dt_lua_style_create_from_image);
345 lua_pushcclosure(L, dt_lua_type_member_common, 1);
346 dt_lua_type_register_const_type(L, type_id, "create");
347 lua_pushcfunction(L, dt_lua_style_apply);
348 lua_pushcclosure(L, dt_lua_type_member_common, 1);
349 dt_lua_type_register_const_type(L, type_id, "apply");
350 lua_pushcfunction(L, dt_lua_style_import);
351 lua_pushcclosure(L, dt_lua_type_member_common, 1);
352 dt_lua_type_register_const_type(L, type_id, "import");
353 lua_pushcfunction(L, dt_lua_style_export);
354 lua_pushcclosure(L, dt_lua_type_member_common, 1);
355 dt_lua_type_register_const_type(L, type_id, "export");
356
357 return 0;
358 }
359
360
361 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
362 // vim: shiftwidth=2 expandtab tabstop=2 cindent
363 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
364