1 
2 /*
3    This file is part of darktable,
4    Copyright (C) 2013-2020 darktable developers.
5 
6    darktable is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    darktable is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with darktable.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "lua/film.h"
21 #include "common/debug.h"
22 #include "common/film.h"
23 #include "common/grealpath.h"
24 #include "lua/database.h"
25 #include "lua/image.h"
26 #include "lua/types.h"
27 #include <errno.h>
28 
path_member(lua_State * L)29 static int path_member(lua_State *L)
30 {
31   dt_lua_film_t film_id;
32   luaA_to(L, dt_lua_film_t, &film_id, 1);
33   sqlite3_stmt *stmt;
34   DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT folder FROM main.film_rolls WHERE id = ?1",
35                               -1, &stmt, NULL);
36   DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
37   if(sqlite3_step(stmt) == SQLITE_ROW)
38   {
39     lua_pushstring(L, (char *)sqlite3_column_text(stmt, 0));
40   }
41   else
42   {
43     sqlite3_finalize(stmt);
44     return luaL_error(L, "should never happen");
45   }
46   sqlite3_finalize(stmt);
47   return 1;
48 }
49 
id_member(lua_State * L)50 static int id_member(lua_State *L)
51 {
52   dt_lua_film_t film_id;
53   luaA_to(L, dt_lua_film_t, &film_id, 1);
54   lua_pushinteger(L, film_id);
55   return 1;
56 }
57 
58 
film_delete(lua_State * L)59 static int film_delete(lua_State *L)
60 {
61   dt_lua_film_t film_id;
62   luaA_to(L, dt_lua_film_t, &film_id, 1);
63   gboolean force = lua_toboolean(L, 2);
64   if(force || dt_film_is_empty(film_id))
65   {
66     dt_film_remove(film_id);
67   }
68   else
69   {
70     return luaL_error(L, "Can't delete film, film is not empty");
71   }
72   return 0;
73 }
74 
film_tostring(lua_State * L)75 static int film_tostring(lua_State *L)
76 {
77   dt_lua_film_t film_id;
78   luaA_to(L, dt_lua_film_t, &film_id, -1);
79   sqlite3_stmt *stmt;
80   DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT folder FROM main.film_rolls WHERE id = ?1",
81                               -1, &stmt, NULL);
82   DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
83   if(sqlite3_step(stmt) == SQLITE_ROW)
84   {
85     lua_pushstring(L, (char *)sqlite3_column_text(stmt, 0));
86   }
87   else
88   {
89     sqlite3_finalize(stmt);
90     return luaL_error(L, "should never happen");
91   }
92   sqlite3_finalize(stmt);
93   return 1;
94 }
95 
96 
film_len(lua_State * L)97 static int film_len(lua_State *L)
98 {
99   dt_lua_film_t film_id;
100   luaA_to(L, dt_lua_film_t, &film_id, -1);
101   sqlite3_stmt *stmt = NULL;
102   DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),
103                               "SELECT COUNT(*) FROM main.images WHERE film_id = ?1  ", -1, &stmt, NULL);
104   DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
105   if(sqlite3_step(stmt) == SQLITE_ROW)
106   {
107     lua_pushinteger(L, sqlite3_column_int(stmt, 0));
108   }
109   else
110   {
111     lua_pushinteger(L, 0);
112   }
113   sqlite3_finalize(stmt);
114   return 1;
115 }
116 
film_getnum(lua_State * L)117 static int film_getnum(lua_State *L)
118 {
119   int index = luaL_checkinteger(L, -1);
120   if(index < 1)
121   {
122     return luaL_error(L, "incorrect index in database");
123   }
124   dt_lua_film_t film_id;
125   luaA_to(L, dt_lua_film_t, &film_id, -2);
126   sqlite3_stmt *stmt = NULL;
127   char query[1024];
128   snprintf(query, sizeof(query), "SELECT id FROM main.images WHERE film_id = ?1 ORDER BY id LIMIT 1 OFFSET %d",
129            index - 1);
130   DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
131   DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, film_id);
132   if(sqlite3_step(stmt) == SQLITE_ROW)
133   {
134     dt_lua_image_t imgid = sqlite3_column_int(stmt, 0);
135     luaA_push(L, dt_lua_image_t, &imgid);
136     sqlite3_finalize(stmt);
137   }
138   else
139   {
140     sqlite3_finalize(stmt);
141     return luaL_error(L, "incorrect index in database");
142   }
143   return 1;
144 }
films_len(lua_State * L)145 static int films_len(lua_State *L)
146 {
147   sqlite3_stmt *stmt = NULL;
148   DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT COUNT(*) FROM main.film_rolls ", -1, &stmt,
149                               NULL);
150   if(sqlite3_step(stmt) == SQLITE_ROW)
151   {
152     lua_pushinteger(L, sqlite3_column_int(stmt, 0));
153   }
154   else
155   {
156     lua_pushinteger(L, 0);
157   }
158   sqlite3_finalize(stmt);
159   return 1;
160 }
161 
films_index(lua_State * L)162 static int films_index(lua_State *L)
163 {
164   int index = luaL_checkinteger(L, -1);
165   if(index < 1)
166   {
167     return luaL_error(L, "incorrect index in database");
168   }
169   sqlite3_stmt *stmt = NULL;
170   char query[1024];
171   snprintf(query, sizeof(query), "SELECT id FROM main.film_rolls ORDER BY id LIMIT 1 OFFSET %d", index - 1);
172   DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
173   if(sqlite3_step(stmt) == SQLITE_ROW)
174   {
175     int film_id = sqlite3_column_int(stmt, 0);
176     luaA_push(L, dt_lua_film_t, &film_id);
177   }
178   else
179   {
180     lua_pushnil(L);
181   }
182   sqlite3_finalize(stmt);
183   return 1;
184 }
185 
films_new(lua_State * L)186 static int films_new(lua_State *L)
187 {
188   const char *path = luaL_checkstring(L, -1);
189   char *expanded_path = dt_util_fix_path(path);
190   char *final_path = g_realpath(expanded_path);
191   g_free(expanded_path);
192   if(!final_path)
193   {
194     return luaL_error(L, "Couldn't create film for directory '%s' : %s\n", path, strerror(errno));
195   }
196 
197   dt_film_t my_film;
198   dt_film_init(&my_film);
199   int film_id = dt_film_new(&my_film, final_path);
200   g_free(final_path);
201   if(film_id)
202   {
203     luaA_push(L, dt_lua_film_t, &film_id);
204     return 1;
205   }
206   else
207   {
208     return luaL_error(L, "Couldn't create film for directory %s\n", path);
209   }
210 }
211 ///////////////
212 // toplevel and common
213 ///////////////
214 
dt_lua_init_film(lua_State * L)215 int dt_lua_init_film(lua_State *L)
216 {
217 
218   dt_lua_init_int_type(L, dt_lua_film_t);
219   lua_pushcfunction(L, film_delete);
220   lua_pushcclosure(L, dt_lua_type_member_common, 1);
221   dt_lua_type_register_const(L, dt_lua_film_t, "delete");
222   lua_pushcfunction(L, path_member);
223   dt_lua_type_register(L, dt_lua_film_t, "path");
224   lua_pushcfunction(L, id_member);
225   dt_lua_type_register(L, dt_lua_film_t, "id");
226 
227   lua_pushcfunction(L, film_len);
228   lua_pushcfunction(L, film_getnum);
229   dt_lua_type_register_number_const(L, dt_lua_film_t);
230   lua_pushcfunction(L, dt_lua_move_image);
231   lua_pushcclosure(L, dt_lua_type_member_common, 1);
232   dt_lua_type_register_const(L, dt_lua_film_t, "move_image");
233   lua_pushcfunction(L, dt_lua_copy_image);
234   lua_pushcclosure(L, dt_lua_type_member_common, 1);
235   dt_lua_type_register_const(L, dt_lua_film_t, "copy_image");
236   lua_pushcfunction(L, film_tostring);
237   dt_lua_type_setmetafield(L,dt_lua_film_t,"__tostring");
238 
239   /* film table */
240   dt_lua_push_darktable_lib(L);
241   luaA_Type type_id = dt_lua_init_singleton(L, "film_database", NULL);
242   lua_setfield(L, -2, "films");
243   lua_pop(L, 1);
244 
245   lua_pushcfunction(L, films_len);
246   lua_pushcfunction(L, films_index);
247   dt_lua_type_register_number_const_type(L, type_id);
248   lua_pushcfunction(L, films_new);
249   lua_pushcclosure(L, dt_lua_type_member_common, 1);
250   dt_lua_type_register_const_type(L, type_id, "new");
251   lua_pushcfunction(L, film_delete);
252   lua_pushcclosure(L, dt_lua_type_member_common, 1);
253   dt_lua_type_register_const_type(L, type_id, "delete");
254 
255   return 0;
256 }
257 
258 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
259 // vim: shiftwidth=2 expandtab tabstop=2 cindent
260 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
261