Preparing stable version
[geeqie.git] / src / lua.c
1 /*
2  * Copyright (C) 2008 - 2016 The Geeqie Team
3  *
4  * Author: Klaus Ethgen
5  *
6  * This program 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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 along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22
23 #ifdef HAVE_LUA
24
25 #define _XOPEN_SOURCE
26
27 #include <lua.h>
28 #include <lauxlib.h>
29 #include <lualib.h>
30
31 #include <stdio.h>
32 #include <glib.h>
33 #include <string.h>
34 #include <time.h>
35
36 #include "main.h"
37 #include "glua.h"
38 #include "ui_fileops.h"
39 #include "exif.h"
40
41 static lua_State *L; /** The LUA object needed for all operations (NOTE: That is
42                        * a upper-case variable to match the documentation!) */
43
44 static FileData *lua_check_image(lua_State *L, int index)
45 {
46         FileData **fd;
47         luaL_checktype(L, index, LUA_TUSERDATA);
48         fd = (FileData **)luaL_checkudata(L, index, "Image");
49         if (fd == NULL) luaL_typerror(L, index, "Image");
50         return *fd;
51 }
52
53 static int lua_image_get_exif(lua_State *L)
54 {
55         FileData *fd;
56         ExifData *exif;
57         ExifData **exif_data;
58
59         fd = lua_check_image(L, 1);
60         exif = exif_read_fd(fd);
61
62         exif_data = (ExifData **)lua_newuserdata(L, sizeof(ExifData *));
63         luaL_getmetatable(L, "Exif");
64         lua_setmetatable(L, -2);
65
66         *exif_data = exif;
67
68         return 1;
69 }
70
71 static int lua_image_get_path(lua_State *L)
72 {
73         FileData *fd;
74
75         fd = lua_check_image(L, 1);
76         lua_pushstring(L, fd->path);
77         return 1;
78 }
79
80 static int lua_image_get_name(lua_State *L)
81 {
82         FileData *fd;
83
84         fd = lua_check_image(L, 1);
85         lua_pushstring(L, fd->name);
86         return 1;
87 }
88
89 static int lua_image_get_extension(lua_State *L)
90 {
91         FileData *fd;
92
93         fd = lua_check_image(L, 1);
94         lua_pushstring(L, fd->extension);
95         return 1;
96 }
97
98 static int lua_image_get_date(lua_State *L)
99 {
100         FileData *fd;
101
102         fd = lua_check_image(L, 1);
103         lua_pushnumber(L, fd->date);
104         return 1;
105 }
106
107 static int lua_image_get_size(lua_State *L)
108 {
109         FileData *fd;
110
111         fd = lua_check_image(L, 1);
112         lua_pushnumber(L, fd->size);
113         return 1;
114 }
115
116 static int lua_image_get_marks(lua_State *L)
117 {
118         FileData *fd;
119
120         fd = lua_check_image(L, 1);
121         lua_pushnumber(L, fd->marks);
122         return 1;
123 }
124
125 static ExifData *lua_check_exif(lua_State *L, int index)
126 {
127         ExifData **exif;
128         luaL_checktype(L, index, LUA_TUSERDATA);
129         exif = (ExifData **)luaL_checkudata(L, index, "Exif");
130         if (exif == NULL) luaL_typerror(L, index, "Exif");
131         return *exif;
132 }
133
134 /* Interface for EXIF data */
135 static int lua_exif_get_datum(lua_State *L)
136 {
137         const gchar *key;
138         gchar *value = NULL;
139         ExifData *exif;
140         struct tm tm;
141         time_t datetime;
142
143         exif = lua_check_exif(L, 1);
144         key = luaL_checkstring(L, 2);
145         if (key == (gchar*)NULL || key[0] == '\0')
146                 {
147                 lua_pushnil(L);
148                 return 1;
149                 }
150         if (!exif)
151                 {
152                 lua_pushnil(L);
153                 return 1;
154                 }
155         value = exif_get_data_as_text(exif, key);
156         if (strcmp(key, "Exif.Photo.DateTimeOriginal") == 0)
157                 {
158                 memset(&tm, 0, sizeof(tm));
159                 if (value && strptime(value, "%Y:%m:%d %H:%M:%S", &tm))
160                         {
161                         datetime = mktime(&tm);
162                         lua_pushnumber(L, datetime);
163                         return 1;
164                         }
165                 else
166                         {
167                         lua_pushnil(L);
168                         return 1;
169                         }
170                 } // if (strcmp(key, "Exif.Photo.Da...
171         lua_pushstring(L, value);
172         return 1;
173 }
174
175 /**
176  * \brief Initialize the lua interpreter.
177  */
178 void lua_init(void)
179 {
180         L = luaL_newstate();
181         luaL_openlibs(L); /* Open all libraries for lua programms */
182
183         /* Now create custom methodes to do something */
184         static const luaL_Reg meta_methods[] = {
185                         {NULL, NULL}
186         };
187
188         /* The Image metatable and methodes */
189         static const luaL_Reg image_methods[] = {
190                         {"get_path", lua_image_get_path},
191                         {"get_name", lua_image_get_name},
192                         {"get_extension", lua_image_get_extension},
193                         {"get_date", lua_image_get_date},
194                         {"get_size", lua_image_get_size},
195                         {"get_exif", lua_image_get_exif},
196                         {"get_marks", lua_image_get_marks},
197                         {NULL, NULL}
198         };
199         luaL_register(L, "Image", image_methods);
200         luaL_newmetatable(L, "Image");
201         luaL_register(L, NULL, meta_methods);
202         lua_pushliteral(L, "__index");
203         lua_pushvalue(L, -3);
204         lua_settable(L, -3);
205         lua_pushliteral(L, "__metatable");
206         lua_pushvalue(L, -3);
207         lua_settable(L, -3);
208         lua_pop(L, 1);
209         lua_pop(L, 1);
210
211         /* The Exif table and methodes */
212         static const luaL_Reg exif_methods[] = {
213                         {"get_datum", lua_exif_get_datum},
214                         {NULL, NULL}
215         };
216         luaL_register(L, "Exif", exif_methods);
217         luaL_newmetatable(L, "Exif");
218         luaL_register(L, NULL, meta_methods);
219         lua_pushliteral(L, "__index");
220         lua_pushvalue(L, -3);
221         lua_settable(L, -3);
222         lua_pushliteral(L, "__metatable");
223         lua_pushvalue(L, -3);
224         lua_settable(L, -3);
225         lua_pop(L, 1);
226         lua_pop(L, 1);
227 }
228
229 /**
230  * \brief Call a lua function to get a single value.
231  */
232 gchar *lua_callvalue(FileData *fd, const gchar *file, const gchar *function)
233 {
234         gint result;
235         gchar *data = NULL;
236         gchar *dir;
237         gchar *path;
238         FileData **image_data;
239         gchar *tmp;
240         GError *error = NULL;
241
242         /* Collection Table (Dummy at the moment) */
243         lua_newtable(L);
244         lua_setglobal(L, "Collection");
245
246         /* Current Image */
247         image_data = (FileData **)lua_newuserdata(L, sizeof(FileData *));
248         luaL_getmetatable(L, "Image");
249         lua_setmetatable(L, -2);
250         lua_setglobal(L, "Image");
251
252         *image_data = fd;
253         if (file[0] == '\0')
254                 {
255                 result = luaL_dostring(L, function);
256                 }
257         else
258                 {
259                 dir = g_build_filename(get_rc_dir(), "lua", NULL);
260                 path = g_build_filename(dir, file, NULL);
261                 result = luaL_dofile(L, path);
262                 g_free(path);
263                 g_free(dir);
264                 }
265
266         if (result)
267                 {
268                 data = g_strdup_printf("Error running lua script: %s", lua_tostring(L, -1));
269                 return data;
270                 }
271         data = g_strdup(lua_tostring(L, -1));
272         tmp = g_locale_to_utf8(data, strlen(data), NULL, NULL, &error);
273         if (error)
274                 {
275                 log_printf("Error converting lua output from locale to UTF-8: %s\n", error->message);
276                 g_error_free(error);
277                 }
278         else
279                 {
280                 g_free(data);
281                 data = g_strdup(tmp);
282                 } // if (error) { ... } else
283         return data;
284 }
285
286 #endif
287 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */