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