486 lines
12 KiB
C
486 lines
12 KiB
C
/*
|
|
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <Ecore.h>
|
|
#include <Ecore_Evas.h>
|
|
#include <Ecore_Ipc.h>
|
|
#include <Ecore_File.h>
|
|
#include <Ecore_Desktop.h>
|
|
#include <Evas.h>
|
|
#include <Eet.h>
|
|
#include <Edje.h>
|
|
#include "e_sha1.h"
|
|
|
|
typedef struct _E_Thumb E_Thumb;
|
|
|
|
struct _E_Thumb
|
|
{
|
|
int objid;
|
|
int w, h;
|
|
char *file;
|
|
char *key;
|
|
};
|
|
|
|
/* local subsystem functions */
|
|
static int _e_ipc_init(void);
|
|
static int _e_ipc_cb_server_add(void *data, int type, void *event);
|
|
static int _e_ipc_cb_server_del(void *data, int type, void *event);
|
|
static int _e_ipc_cb_server_data(void *data, int type, void *event);
|
|
static int _e_cb_timer(void *data);
|
|
static int _e_thumb_valid(E_Thumb *eth);
|
|
static void _e_thumb_generate(E_Thumb *eth);
|
|
static char *_e_thumb_file_id(char *file, char *key);
|
|
|
|
/* local subsystem globals */
|
|
static Ecore_Ipc_Server *_e_ipc_server = NULL;
|
|
static Evas_List *_thumblist = NULL;
|
|
static Ecore_Timer *_timer = NULL;
|
|
static char _thumbdir[4096] = "";
|
|
|
|
/* externally accessible functions */
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
char buf[4096];
|
|
int i;
|
|
|
|
/* FIXME: make this configurable */
|
|
// nice(20);
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if ((!strcmp(argv[i], "-h")) ||
|
|
(!strcmp(argv[i], "-help")) ||
|
|
(!strcmp(argv[i], "--help")))
|
|
{
|
|
printf(
|
|
"This is an internal tool for Enlightenment.\n"
|
|
"do not use it.\n"
|
|
);
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
ecore_init();
|
|
ecore_app_args_set(argc, (const char **)argv);
|
|
eet_init();
|
|
evas_init();
|
|
ecore_evas_init();
|
|
edje_init();
|
|
ecore_file_init();
|
|
ecore_ipc_init();
|
|
|
|
ecore_desktop_init();
|
|
ecore_desktop_paths_extras_clear();
|
|
ecore_desktop_paths_prepend_user(ECORE_DESKTOP_PATHS_ICONS, "~/.e/e/icons");
|
|
// snprintf(buf, sizeof(buf), "%s/data/icons", e_prefix_data_get());
|
|
ecore_desktop_paths_append_system(ECORE_DESKTOP_PATHS_ICONS, buf);
|
|
ecore_desktop_paths_regen();
|
|
|
|
snprintf(_thumbdir, sizeof(_thumbdir), "%s/.e/e/fileman/thumbnails",
|
|
getenv("HOME"));
|
|
ecore_file_mkpath(_thumbdir);
|
|
|
|
if (_e_ipc_init()) ecore_main_loop_begin();
|
|
|
|
if (_e_ipc_server)
|
|
{
|
|
ecore_ipc_server_del(_e_ipc_server);
|
|
_e_ipc_server = NULL;
|
|
}
|
|
|
|
ecore_desktop_shutdown();
|
|
ecore_ipc_shutdown();
|
|
ecore_file_shutdown();
|
|
ecore_evas_shutdown();
|
|
edje_shutdown();
|
|
evas_shutdown();
|
|
eet_shutdown();
|
|
ecore_shutdown();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* local subsystem functions */
|
|
static int
|
|
_e_ipc_init(void)
|
|
{
|
|
char *sdir;
|
|
|
|
sdir = getenv("E_IPC_SOCKET");
|
|
if (!sdir)
|
|
{
|
|
printf("The E_IPC_SOCKET environment variable is not set. This is\n"
|
|
"exported by Enlightenment to all processes it launches.\n"
|
|
"This environment variable must be set and must point to\n"
|
|
"Enlightenment's IPC socket file (minus port number).\n");
|
|
return 0;
|
|
}
|
|
_e_ipc_server = ecore_ipc_server_connect(ECORE_IPC_LOCAL_SYSTEM, sdir, 0, NULL);
|
|
if (!_e_ipc_server) return 0;
|
|
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _e_ipc_cb_server_add, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _e_ipc_cb_server_del, NULL);
|
|
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _e_ipc_cb_server_data, NULL);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_ipc_cb_server_add(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Add *e;
|
|
|
|
e = event;
|
|
ecore_ipc_server_send(e->server, 5, 1, 0, 0, 0, NULL, 0); /* send hello */
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_ipc_cb_server_del(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Del *e;
|
|
|
|
e = event;
|
|
/* quit now */
|
|
ecore_main_loop_quit();
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_ipc_cb_server_data(void *data, int type, void *event)
|
|
{
|
|
Ecore_Ipc_Event_Server_Data *e;
|
|
E_Thumb *eth;
|
|
Evas_List *l;
|
|
char *file = NULL;
|
|
char *key = NULL;
|
|
|
|
e = event;
|
|
if (e->major != 5) return 1;
|
|
switch (e->minor)
|
|
{
|
|
case 1:
|
|
if (e->data)
|
|
{
|
|
/* begin thumb */
|
|
/* don't check stuff. since this connects TO e17 it is connecting */
|
|
/* TO a trusted process that WILL send this message properly */
|
|
/* formatted. if the thumbnailer dies anyway - it's not a big loss */
|
|
/* but it is a sign of a bug in e formattign messages maybe */
|
|
file = e->data;
|
|
key = file + strlen(file) + 1;
|
|
if (!key[0]) key = NULL;
|
|
eth = calloc(1, sizeof(E_Thumb));
|
|
if (eth)
|
|
{
|
|
eth->objid = e->ref;
|
|
eth->w = e->ref_to;
|
|
eth->h = e->response;
|
|
eth->file = strdup(file);
|
|
if (key) eth->key = strdup(key);
|
|
_thumblist = evas_list_append(_thumblist, eth);
|
|
if (!_timer) _timer = ecore_timer_add(0.000001, _e_cb_timer, NULL);
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
/* end thumb */
|
|
for (l = _thumblist; l; l = l->next)
|
|
{
|
|
eth = l->data;
|
|
if (eth->objid == e->ref)
|
|
{
|
|
_thumblist = evas_list_remove_list(_thumblist, l);
|
|
if (eth->file) free(eth->file);
|
|
if (eth->key) free(eth->key);
|
|
free(eth);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
/* quit now */
|
|
ecore_main_loop_quit();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_cb_timer(void *data)
|
|
{
|
|
E_Thumb *eth;
|
|
/*
|
|
Evas_List *del_list = NULL, *l;
|
|
*/
|
|
|
|
/* take thumb at head of list */
|
|
if (_thumblist)
|
|
{
|
|
/*
|
|
for (l = _thumblist; l; l = l->next)
|
|
{
|
|
eth = l->data;
|
|
if (_e_thumb_valid(eth))
|
|
del_list = evas_list_append(del_list, eth);
|
|
}
|
|
while (del_list)
|
|
{
|
|
eth = del_list->data;
|
|
del_list = evas_list_remove_list(del_list, del_list);
|
|
_thumblist = evas_list_remove(_thumblist, eth);
|
|
if (eth->file) free(eth->file);
|
|
if (eth->key) free(eth->key);
|
|
free(eth);
|
|
}
|
|
*/
|
|
if (_thumblist)
|
|
{
|
|
eth = _thumblist->data;
|
|
_thumblist = evas_list_remove_list(_thumblist, _thumblist);
|
|
_e_thumb_generate(eth);
|
|
if (eth->file) free(eth->file);
|
|
if (eth->key) free(eth->key);
|
|
free(eth);
|
|
}
|
|
if (_thumblist) _timer = ecore_timer_add(0.000001, _e_cb_timer, NULL);
|
|
else _timer = NULL;
|
|
}
|
|
else
|
|
_timer = NULL;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_e_thumb_valid(E_Thumb *eth)
|
|
{
|
|
char buf[4096], dbuf[4096], *id, *td;
|
|
time_t mtime_orig, mtime_thumb;
|
|
|
|
id = _e_thumb_file_id(eth->file, eth->key);
|
|
if (!id) return 0;
|
|
|
|
td = strdup(id);
|
|
if (!td)
|
|
{
|
|
free(id);
|
|
return 0;
|
|
}
|
|
td[2] = 0;
|
|
|
|
snprintf(dbuf, sizeof(dbuf), "%s/%s", _thumbdir, td);
|
|
snprintf(buf, sizeof(buf), "%s/%s/%s-%ix%i.thm",
|
|
_thumbdir, td, id + 2, eth->w, eth->h);
|
|
free(id);
|
|
free(td);
|
|
|
|
mtime_orig = ecore_file_mod_time(eth->file);
|
|
mtime_thumb = ecore_file_mod_time(buf);
|
|
if (mtime_thumb > mtime_orig)
|
|
{
|
|
ecore_ipc_server_send(_e_ipc_server, 5, 2, eth->objid, 0, 0, buf, strlen(buf) + 1);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
_e_thumb_generate(E_Thumb *eth)
|
|
{
|
|
char buf[4096], dbuf[4096], *id, *td, *ext = NULL;
|
|
Evas *evas = NULL, *evas_im = NULL;
|
|
Ecore_Evas *ee = NULL, *ee_im = NULL;
|
|
Evas_Object *im = NULL, *edje = NULL;
|
|
Eet_File *ef;
|
|
int iw, ih, alpha, ww, hh;
|
|
int *data = NULL;
|
|
time_t mtime_orig, mtime_thumb;
|
|
|
|
id = _e_thumb_file_id(eth->file, eth->key);
|
|
if (!id) return;
|
|
|
|
td = strdup(id);
|
|
if (!td)
|
|
{
|
|
free(id);
|
|
return;
|
|
}
|
|
td[2] = 0;
|
|
|
|
snprintf(dbuf, sizeof(dbuf), "%s/%s", _thumbdir, td);
|
|
snprintf(buf, sizeof(buf), "%s/%s/%s-%ix%i.thm",
|
|
_thumbdir, td, id + 2, eth->w, eth->h);
|
|
free(id);
|
|
free(td);
|
|
|
|
mtime_orig = ecore_file_mod_time(eth->file);
|
|
mtime_thumb = ecore_file_mod_time(buf);
|
|
if (mtime_thumb <= mtime_orig)
|
|
{
|
|
ecore_file_mkdir(dbuf);
|
|
|
|
edje_file_cache_set(0);
|
|
edje_collection_cache_set(0);
|
|
ee = ecore_evas_buffer_new(1, 1);
|
|
evas = ecore_evas_get(ee);
|
|
evas_image_cache_set(evas, 0);
|
|
evas_font_cache_set(evas, 0);
|
|
ww = 0;
|
|
hh = 0;
|
|
alpha = 1;
|
|
ext = strrchr(eth->file, '.');
|
|
|
|
if ((ext) && (!strcasecmp(ext, ".desktop")))
|
|
{
|
|
Ecore_Desktop *desktop;
|
|
|
|
desktop = ecore_desktop_get(eth->file, NULL);
|
|
free(eth->file);
|
|
eth->file = NULL;
|
|
if (desktop)
|
|
{
|
|
if (desktop->icon_path)
|
|
eth->file = strdup(desktop->icon_path);
|
|
else
|
|
eth->file = (char *)ecore_desktop_icon_find(desktop->icon_class, NULL, eth->key);
|
|
free(eth->key);
|
|
eth->key = NULL;
|
|
if (eth->file)
|
|
{
|
|
ext = strrchr(eth->file, '.');
|
|
if ((ext) &&
|
|
((!strcasecmp(ext, ".edj")) ||
|
|
(!strcasecmp(ext, ".eap")))
|
|
)
|
|
{
|
|
eth->key = strdup("icon");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((ext) && (eth->key) &&
|
|
((!strcasecmp(ext, ".edj")) ||
|
|
(!strcasecmp(ext, ".eap")))
|
|
)
|
|
{
|
|
ww = eth->w;
|
|
hh = eth->h;
|
|
im = ecore_evas_object_image_new(ee);
|
|
ee_im = evas_object_data_get(im, "Ecore_Evas");
|
|
evas_im = ecore_evas_get(ee_im);
|
|
evas_image_cache_set(evas_im, 0);
|
|
evas_font_cache_set(evas_im, 0);
|
|
evas_object_image_size_set(im, ww * 8, hh * 8);
|
|
evas_object_image_fill_set(im, 0, 0, ww, hh);
|
|
edje = edje_object_add(evas_im);
|
|
if ((eth->key) &&
|
|
( (!strcmp(eth->key, "e/desktop/background")) ||
|
|
(!strcmp(eth->key, "e/init/splash")) ))
|
|
alpha = 0;
|
|
if (edje_object_file_set(edje, eth->file, eth->key))
|
|
{
|
|
evas_object_move(edje, 0, 0);
|
|
evas_object_resize(edje, ww * 8, hh * 8);
|
|
evas_object_show(edje);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
im = evas_object_image_add(evas);
|
|
evas_object_image_load_size_set(im, eth->w, eth->h);
|
|
evas_object_image_file_set(im, eth->file, NULL);
|
|
iw = 0; ih = 0;
|
|
evas_object_image_size_get(im, &iw, &ih);
|
|
alpha = evas_object_image_alpha_get(im);
|
|
if ((iw > 0) && (ih > 0))
|
|
{
|
|
ww = eth->w;
|
|
hh = (eth->w * ih) / iw;
|
|
if (hh > eth->h)
|
|
{
|
|
hh = eth->h;
|
|
ww = (eth->h * iw) / ih;
|
|
}
|
|
evas_object_image_fill_set(im, 0, 0, ww, hh);
|
|
}
|
|
}
|
|
evas_object_move(im, 0, 0);
|
|
evas_object_resize(im, ww, hh);
|
|
ecore_evas_resize(ee, ww, hh);
|
|
evas_object_show(im);
|
|
if (ww > 0)
|
|
{
|
|
data = (int *)ecore_evas_buffer_pixels_get(ee);
|
|
if (data)
|
|
{
|
|
ef = eet_open(buf, EET_FILE_MODE_WRITE);
|
|
if (ef)
|
|
{
|
|
eet_write(ef, "/thumbnail/orig_file",
|
|
eth->file, strlen(eth->file), 1);
|
|
if (eth->key)
|
|
eet_write(ef, "/thumbnail/orig_key",
|
|
eth->key, strlen(eth->key), 1);
|
|
eet_data_image_write(ef, "/thumbnail/data",
|
|
(void *)data, ww, hh, alpha,
|
|
0, 91, 1);
|
|
eet_close(ef);
|
|
}
|
|
}
|
|
}
|
|
/* will free all */
|
|
if (edje) evas_object_del(edje);
|
|
if (ee_im) ecore_evas_free(ee_im);
|
|
else if (im) evas_object_del(im);
|
|
ecore_evas_free(ee);
|
|
eet_clearcache();
|
|
}
|
|
/* send back path to thumb */
|
|
ecore_ipc_server_send(_e_ipc_server, 5, 2, eth->objid, 0, 0, buf, strlen(buf) + 1);
|
|
}
|
|
|
|
/* FIXME: should use md5 or sha1 sum of the path */
|
|
static char *
|
|
_e_thumb_file_id(char *file, char *key)
|
|
{
|
|
char s[64];
|
|
const char *chmap = "0123456789abcdef";
|
|
unsigned char *buf, id[20];
|
|
int i, len, lenf;
|
|
|
|
len = 0;
|
|
lenf = strlen(file);
|
|
len += lenf;
|
|
len++;
|
|
if (key)
|
|
{
|
|
key += strlen(key);
|
|
len++;
|
|
}
|
|
buf = alloca(len);
|
|
|
|
strcpy((char *)buf, file);
|
|
if (key) strcpy((char *)(buf + lenf + 1), key);
|
|
|
|
e_sha1_sum(buf, len, id);
|
|
|
|
for (i = 0; i < 20; i++)
|
|
{
|
|
s[(i * 2) + 0] = chmap[(id[i] >> 4) & 0xf];
|
|
s[(i * 2) + 1] = chmap[(id[i] ) & 0xf];
|
|
}
|
|
s[(i * 2)] = 0;
|
|
return strdup(s);
|
|
}
|