new thumbnailer system. works a bit more like epsilon - launches a

special-purpose executable and hands off workd to do via ipc (well the exe
connects back to e's ipc port actually but either way - same thing). it can
actually launch any numebr of thumbnailers - the default is 2, but this means
it can make full use of smp systems. i need to make this # of thumbnailers
configurable and add a config dialog for it. this does mean thew bg/theme
etc. dialogs pop up much faster as they dont load all the thumbs to start -
its farmed off and ipc tells us when they are ready (and if already generated
- thats pretty damn fast). :) anyway - now thumbnailing works reliably
(thoguh i think the queue handling isnt quite that good - well when it comes
to interacting with efm... but i'll check into that later. dont worry though
- it does actually generate all the thumbs - it just may be busy generating
ones you don't see while it catches up).


SVN revision: 23750
This commit is contained in:
Carsten Haitzler 2006-07-08 09:18:04 +00:00
parent 7b8c6e8b04
commit 50063cad9c
16 changed files with 782 additions and 743 deletions

View File

@ -14,7 +14,8 @@ enlightenment_remote \
enlightenment_eapp \
enlightenment_eapp_cache_gen \
enlightenment_imc \
enlightenment_start
enlightenment_start \
enlightenment_thumb
ENLIGHTENMENTHEADERS = \
e.h \
@ -335,6 +336,11 @@ e_start_main.c
enlightenment_start_LDFLAGS =
enlightenment_thumb_SOURCES = \
e_thumb_main.c
enlightenment_thumb_LDFLAGS = @e_libs@ @dlopen_libs@
installed_headersdir = $(prefix)/include/enlightenment
installed_headers_DATA = $(ENLIGHTENMENTHEADERS)

View File

@ -12,7 +12,6 @@ struct _E_Smart_Data
Evas *evas;
Evas_Object *obj;
char *thumb_path;
char *saved_title;
Evas_Object *event_object;
@ -137,50 +136,32 @@ e_fm_icon_file_set(Evas_Object *obj, E_Fm_File *file)
sd = evas_object_smart_data_get(obj);
if (!sd) return;
if(!sd->file)
e_object_ref(E_OBJECT(file));
if (!sd->file) e_object_ref(E_OBJECT(file));
sd->file = file;
file->icon_object = obj;
/* FIXME fix this */
if (sd->file->mime->thumbnail)
{
sd->thumb_path = e_thumb_file_get(sd->file->path);
if (e_thumb_exists(sd->file->path))
{
sd->thumb_object = e_thumb_evas_object_get(sd->file->path,
sd->evas,
sd->iw,
sd->ih,
1);
// evas_object_geometry_get(sd->thumb_object, NULL, NULL, &icon_w, &icon_h);
// sd->iw = icon_w;
// sd->ih = icon_h;
sd->image_object = edje_object_add(sd->evas);
e_theme_edje_object_set(sd->image_object, "base/theme/fileman",
"fileman/icon_thumb");
edje_extern_object_min_size_set(sd->thumb_object, sd->iw, sd->ih);
edje_extern_object_max_size_set(sd->thumb_object, sd->iw, sd->ih);
edje_object_part_swallow(sd->image_object, "icon_swallow",
sd->thumb_object);
edje_object_size_min_calc(sd->image_object, &icon_w, &icon_h);
sd->iw = icon_w;
sd->ih = icon_h;
edje_extern_object_min_size_set(sd->image_object, icon_w, icon_h);
edje_extern_object_max_size_set(sd->image_object, icon_w, icon_h);
edje_object_part_swallow(sd->icon_object, "icon_swallow",
sd->image_object);
}
else
{
sd->thumb_object = sd->file->mime->thumbnail(sd->file->path, sd->iw,
sd->ih, sd->evas,
&sd->thumb_object,
_e_fm_icon_thumb_generate_cb,
sd);
_e_fm_icon_icon_mime_get(sd);
}
/* FIXME: should use smart callback to change icon when thumb done */
sd->thumb_object = e_thumb_icon_add(sd->evas);
e_thumb_icon_file_set(sd->thumb_object, sd->file->path, NULL);
e_thumb_icon_size_set(sd->thumb_object, 64, 64);
e_thumb_icon_begin(sd->thumb_object);
evas_object_show(sd->thumb_object);
sd->image_object = edje_object_add(sd->evas);
e_theme_edje_object_set(sd->image_object, "base/theme/fileman",
"fileman/icon_thumb");
edje_extern_object_min_size_set(sd->thumb_object, sd->iw, sd->ih);
edje_extern_object_max_size_set(sd->thumb_object, sd->iw, sd->ih);
edje_object_part_swallow(sd->image_object, "icon_swallow",
sd->thumb_object);
edje_object_size_min_calc(sd->image_object, &icon_w, &icon_h);
sd->iw = icon_w;
sd->ih = icon_h;
edje_extern_object_min_size_set(sd->image_object, icon_w, icon_h);
edje_extern_object_max_size_set(sd->image_object, icon_w, icon_h);
edje_object_part_swallow(sd->icon_object, "icon_swallow",
sd->image_object);
}
else
{
@ -513,49 +494,6 @@ _e_fm_icon_icon_mime_get(E_Smart_Data *sd)
sd->image_object);
}
void
_e_fm_icon_thumb_generate_cb(Evas_Object *obj, void *data)
{
E_Smart_Data *sd;
sd = data;
/* FIXME fix this */
#if 0
if (e_fm_file_has_mime(sd->file,".eap") || (ecore_file_exists(sd->thumb_path)))
{
Evas_Coord icon_w, icon_h;
if (sd->image_object) evas_object_del(sd->image_object);
sd->thumb_object = e_thumb_evas_object_get(sd->file->path,
sd->evas,
sd->iw,
sd->ih,
1);
sd->image_object = edje_object_add(sd->evas);
e_theme_edje_object_set(sd->image_object, "base/theme/fileman",
"fileman/icon_thumb");
evas_object_show(sd->image_object);
evas_object_show(sd->thumb_object);
edje_extern_object_min_size_set(sd->thumb_object, sd->iw, sd->ih);
edje_extern_object_max_size_set(sd->thumb_object, sd->iw, sd->ih);
edje_object_part_swallow(sd->image_object, "icon_swallow",
sd->thumb_object);
edje_object_size_min_calc(sd->image_object, &icon_w, &icon_h);
sd->iw = icon_w;
sd->ih = icon_h;
edje_extern_object_min_size_set(sd->image_object, icon_w, icon_h);
edje_extern_object_max_size_set(sd->image_object, icon_w, icon_h);
edje_object_part_swallow(sd->icon_object, "icon_swallow",
sd->image_object);
}
#endif
}
static void
_e_fm_icon_type_set(E_Smart_Data *sd)
{

View File

@ -610,8 +610,7 @@ _e_fm_mime_action_internal_folder_open(E_Fm_Smart_Data *sd)
E_Fm_File *file;
file = sd->operation.files->data;
e_fm_dir_set(sd->object, file->path);
if (file) e_fm_dir_set(sd->object, file->path);
}
static void
@ -621,8 +620,11 @@ _e_fm_mime_action_internal_folder_open_other(E_Fm_Smart_Data *sd)
E_Fm_File *file;
file = sd->operation.files->data;
fileman = e_fileman_new_to_dir(e_container_current_get(e_manager_current_get()), file->path);
e_fileman_show(fileman);
if (file)
{
fileman = e_fileman_new_to_dir(e_container_current_get(e_manager_current_get()), file->path);
e_fileman_show(fileman);
}
}
static void
_e_fm_mime_action_internal_copy_to(E_Fm_Smart_Data *sd)
@ -637,14 +639,15 @@ _e_fm_mime_action_internal_move_to(E_Fm_Smart_Data *sd)
/* thumbnail functions */
/***********************/
Evas_Object * _e_fm_mime_thumbnail_evas(char *path, Evas_Coord w, Evas_Coord h, Evas *evas, Evas_Object **tmp, void (*cb)(Evas_Object *obj, void *data), void *data)
Evas_Object *
_e_fm_mime_thumbnail_evas(char *path, Evas_Coord w, Evas_Coord h, Evas *evas, Evas_Object **tmp, void (*cb)(Evas_Object *obj, void *data), void *data)
{
Evas_Object *r;
r = e_thumb_generate_begin(path, w,
h, evas, tmp, cb,
data);
r = e_thumb_icon_add(evas);
e_thumb_icon_file_set(r, path, NULL);
e_thumb_icon_size_set(r, w, h);
e_thumb_icon_begin(r);
return r;
}

View File

@ -501,7 +501,6 @@ e_fm_icon_destroy(Evas_Object *obj, void *data)
E_Fm_Icon *icon;
icon = data;
e_thumb_generate_end(icon->file->path);
evas_object_del(icon->icon_obj);
icon->state.visible = 0;
}

View File

@ -10,7 +10,7 @@ EAPI Evas_Object *e_icon_add (Evas *evas);
EAPI void e_icon_file_set (Evas_Object *obj, const char *file);
EAPI void e_icon_file_key_set (Evas_Object *obj, const char *file, const char *key);
EAPI void e_icon_file_edje_set (Evas_Object *obj, const char *file, const char *part);
EAPI void e_icon_object_set(Evas_Object *obj, Evas_Object *o);
EAPI void e_icon_object_set (Evas_Object *obj, Evas_Object *o);
EAPI const char *e_icon_file_get (Evas_Object *obj);
EAPI void e_icon_smooth_scale_set (Evas_Object *obj, int smooth);
EAPI int e_icon_smooth_scale_get (Evas_Object *obj);

View File

@ -304,11 +304,12 @@ _load_bgs(E_Config_Dialog *cfd, Evas_Object *il)
{
Evas_Object *ic = NULL;
if (!e_thumb_exists(c))
ic = e_thumb_generate_begin(c, 48, 48, cfd->dia->win->evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get(c, cfd->dia->win->evas, 48, 48, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, f, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(il, ic, _("Theme Wallpaper"), _ilist_cb_bg_selected, cfd, "");
if (!e_config->desktop_default_background) selnum = i;
i++;
@ -370,11 +371,12 @@ _load_bgs(E_Config_Dialog *cfd, Evas_Object *il)
if (ecore_file_is_dir(full_path)) continue;
if (!e_util_edje_collection_exists(full_path, "desktop/background")) continue;
if (!e_thumb_exists(full_path))
ic = e_thumb_generate_begin(full_path, 48, 48, evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get(full_path, evas, 48, 48, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, full_path, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(il, ic, ecore_file_strip_ext(bg_file), _ilist_cb_bg_selected, cfd, full_path);
if ((e_config->desktop_default_background) &&
(!strcmp(e_config->desktop_default_background, full_path)))
@ -486,10 +488,12 @@ _bg_file_added(void *data, Ecore_File_Monitor *monitor, Ecore_File_Event event,
{
if (e_util_edje_collection_exists((char *)path, "desktop/background"))
{
if (!e_thumb_exists((char *)path))
ic = e_thumb_generate_begin((char *)path, 48, 48, evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get((char *)path, evas, 48, 48, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, path, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(il, ic, noext, _ilist_cb_bg_selected, cfd, (char *)path);
}
}

View File

@ -255,16 +255,18 @@ _bg_edj_gen(Evas *evas, char *filename, int method)
int w, h;
const char *file;
char buff[4096], cmd[4096];
char ipart[512];
char ipart[4096];
char *imgdir = NULL;
static char tmpn[1024];
static char tmpn[4096];
FILE *out = NULL;
Ecore_Exe *x;
if (!filename) return;
file = ecore_file_get_file(filename);
snprintf(buff, sizeof(buff), "%s/.e/e/backgrounds/%s.edj", e_user_homedir_get(), ecore_file_strip_ext(file));
snprintf(buff, sizeof(buff), "%s/.e/e/backgrounds/%s.edj",
e_user_homedir_get(),
ecore_file_strip_ext(file));
strcpy(tmpn, "/tmp/e_bgdlg_new.edc-tmp-XXXXXX");
fd = mkstemp(tmpn);
if (fd < 0)
@ -309,7 +311,10 @@ _bg_edj_gen(Evas *evas, char *filename, int method)
fclose(out);
snprintf(cmd, sizeof(cmd), "edje_cc -v %s %s %s", ipart, tmpn, buff);
snprintf(cmd, sizeof(cmd), "edje_cc -v %s %s %s",
ipart,
tmpn,
e_util_filename_escape(buff));
_edj_exe_exit_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _edj_exe_exit_cb, NULL);
x = ecore_exe_run(cmd, tmpn);

View File

@ -532,13 +532,12 @@ _load_bgs(E_Config_Dialog_Data *cfdata)
e_widget_ilist_header_append(cfdata->gui.bg_list, NULL, _("Theme Backgrounds"));
if (edje_object_file_set(o, f1, "desklock/background"))
{
if (!e_thumb_exists(c))
ic = e_thumb_generate_begin(c, BG_LIST_ICON_SIZE_W, BG_LIST_ICON_SIZE_H,
cfdata->evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get(c, cfdata->evas, BG_LIST_ICON_SIZE_W,
BG_LIST_ICON_SIZE_H, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, (char *)f1, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(cfdata->gui.bg_list, ic, _("Theme Desklock Background"),
_ibg_list_cb_bg_selected, cfdata, DEF_DESKLOCK_BACKGROUND);
}
@ -565,13 +564,12 @@ _load_bgs(E_Config_Dialog_Data *cfdata)
ic = NULL;
if (edje_object_file_set(o, f, "desktop/background"))
{
if (!e_thumb_exists(c))
ic = e_thumb_generate_begin(c, BG_LIST_ICON_SIZE_W, BG_LIST_ICON_SIZE_H,
cfdata->evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get(c, cfdata->evas, BG_LIST_ICON_SIZE_W,
BG_LIST_ICON_SIZE_H, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, (char *)f, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(cfdata->gui.bg_list, ic, _("Theme Background"),
_ibg_list_cb_bg_selected, cfdata, DEF_THEME_BACKGROUND);
}
@ -612,13 +610,12 @@ _load_bgs(E_Config_Dialog_Data *cfdata)
if (ecore_file_is_dir(full_path)) continue;
if (!e_util_edje_collection_exists(full_path, "desktop/background")) continue;
if (!e_thumb_exists(full_path))
ic = e_thumb_generate_begin(full_path, BG_LIST_ICON_SIZE_W, BG_LIST_ICON_SIZE_H,
cfdata->evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get(full_path, cfdata->evas, BG_LIST_ICON_SIZE_W,
BG_LIST_ICON_SIZE_H, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, full_path, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(cfdata->gui.bg_list, ic, ecore_file_strip_ext(bg_file),
_ibg_list_cb_bg_selected, cfdata, full_path);

View File

@ -195,11 +195,12 @@ _load_inits(E_Config_Dialog *cfd, Evas_Object *il)
if (ecore_file_is_dir(full_path)) continue;
if (!e_util_edje_collection_exists(full_path, "init/splash")) continue;
if (!e_thumb_exists(full_path))
ic = e_thumb_generate_begin(full_path, 48, 48, cfd->dia->win->evas, &ic, NULL, NULL);
else
ic = e_thumb_evas_object_get(full_path, cfd->dia->win->evas, 48, 48, 1);
ic = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(ic, full_path, "desktop/background");
e_thumb_icon_size_set(ic, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(ic);
e_widget_ilist_append(il, ic, ecore_file_strip_ext(init_file), _ilist_cb_init_selected, cfd, full_path);
if ((e_config->init_default_theme) &&

View File

@ -104,7 +104,6 @@ _e_config_theme_cb_standard(void *data)
d = data;
e_widget_preview_edje_set(d->cfd->data, d->file, "desktop/background");
// e_widget_image_object_set(d->cfd->data, e_thumb_evas_object_get(d->file, d->cfd->dia->win->evas, 160, 120, 1));
cfdata = d->cfd->cfdata;
if (cfdata->current_theme)
@ -199,10 +198,12 @@ _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cf
char *noext;
E_Cfg_Theme_Data *cb_data;
if (!e_thumb_exists(fulltheme))
o3 = e_thumb_generate_begin(fulltheme, 48, 48, cfd->dia->win->evas, &o3, NULL, NULL);
else
o3 = e_thumb_evas_object_get(fulltheme, cfd->dia->win->evas, 48, 48, 1);
o3 = e_thumb_icon_add(cfd->dia->win->evas);
e_thumb_icon_file_set(o3, fulltheme, "desktop/background");
e_thumb_icon_size_set(o3, 64,
(64 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_thumb_icon_begin(o3);
noext = ecore_file_strip_ext(themefile);
@ -221,8 +222,6 @@ _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cf
(320 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_widget_preview_edje_set(im, fulltheme, "desktop/background");
// im = e_widget_image_add_from_object(evas, theme, 320, 240);
// e_widget_image_object_set(im, e_thumb_evas_object_get(fulltheme, evas, 320, 240, 1));
}
free(noext);
i++;
@ -245,9 +244,6 @@ _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cf
(320 * e_zone_current_get(cfd->dia->win->container)->h) /
e_zone_current_get(cfd->dia->win->container)->w);
e_widget_preview_edje_set(im, fulltheme, "desktop/background");
// theme = e_thumb_generate_begin(fulltheme, 320, 240, evas, &theme, NULL, NULL);
// im = e_widget_image_add_from_object(evas, theme, 320, 240);
// e_widget_image_object_set(im, e_thumb_evas_object_get(fulltheme, evas, 320, 240, 1));
}
cfd->data = im;

View File

@ -116,6 +116,7 @@ _e_ipc_cb_client_del(void *data __UNUSED__, int type __UNUSED__, void *event)
e = event;
if (ecore_ipc_client_server_get(e->client) != _e_ipc_server) return 1;
/* delete client sruct */
e_thumb_client_del(e);
ecore_ipc_client_del(e->client);
return 1;
}
@ -127,11 +128,24 @@ _e_ipc_cb_client_data(void *data __UNUSED__, int type __UNUSED__, void *event)
e = event;
if (ecore_ipc_client_server_get(e->client) != _e_ipc_server) return 1;
switch (e->minor)
switch (e->major)
{
case E_IPC_DOMAIN_SETUP:
case E_IPC_DOMAIN_REQUEST:
case E_IPC_DOMAIN_REPLY:
case E_IPC_DOMAIN_EVENT:
switch (e->minor)
{
#define TYPE E_WM_IN
#include "e_ipc_handlers.h"
#include "e_ipc_handlers.h"
#undef TYPE
default:
break;
}
break;
case E_IPC_DOMAIN_THUMB:
e_thumb_client_data(e);
break;
default:
break;
}

View File

@ -13,6 +13,7 @@ typedef enum _E_Ipc_Domain
E_IPC_DOMAIN_REQUEST,
E_IPC_DOMAIN_REPLY,
E_IPC_DOMAIN_EVENT,
E_IPC_DOMAIN_THUMB,
E_IPC_DOMAIN_LAST
} E_Ipc_Domain;

View File

@ -1788,7 +1788,7 @@ _e_menu_submenu_activate(E_Menu_Item *mi)
static void
_e_menu_submenu_deactivate(E_Menu_Item *mi)
{
if (mi->menu->active) return;
if (!mi->menu->active) return;
if (mi->submenu_post_cb.func)
mi->submenu_post_cb.func(mi->submenu_post_cb.data, mi->menu, mi);
}

View File

@ -1,631 +1,317 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "e.h"
#ifdef EFM_DEBUG
# define D(x) do {printf(__FILE__ ":%d: ", __LINE__); printf x; fflush(stdout);} while (0)
#else
# define D(x) ((void) 0)
#endif
typedef struct _E_Thumb E_Thumb;
typedef struct _E_Thumb_Item E_Thumb_Item;
static char *_e_thumb_file_id(char *file);
static void _e_thumb_generate(void);
static int _e_thumb_cb_exe_exit(void *data, int type, void *event);
static char *thumb_path = NULL;
static Evas_List *thumb_files = NULL;
static Evas_List *event_handlers = NULL;
static pid_t pid = -1;
struct _E_Thumb_Item
struct _E_Thumb
{
char path[PATH_MAX];
Evas_Object *obj;
Evas *evas;
Evas_Coord w, h;
void (*cb)(Evas_Object *obj, void *data);
void *data;
int objid;
int w, h;
char *file;
char *key;
unsigned char queued : 1;
unsigned char busy : 1;
};
/* local subsystem functions */
static void _e_thumb_gen_begin(int objid, char *file, char *key, int w, int h);
static void _e_thumb_gen_end(int objid);
static void _e_thumb_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _e_thumb_hash_add(int objid, Evas_Object *obj);
static void _e_thumb_hash_del(int objid);
static Evas_Object *_e_thumb_hash_find(int objid);
static void _e_thumb_thumbnailers_kill(void);
static int _e_thumb_cb_exe_event_del(void *data, int type, void *event);
/* local subsystem globals */
static Evas_List *_thumbnailers = NULL;
static Evas_List *_thumbnailers_exe = NULL;
static Evas_List *_thumb_queue = NULL;
static int _objid = 0;
static Evas_Hash *_thumbs = NULL;
static int _pending = 0;
static int _num_thumbnailers = 2;
static Ecore_Event_Handler *_exe_del_handler = NULL;
/* externally accessible functions */
EAPI int
e_thumb_init(void)
{
char *homedir;
char path[PATH_MAX];
homedir = e_user_homedir_get();
if (homedir)
{
snprintf(path, sizeof(path), "%s/.e/e/fileman/thumbnails", homedir);
if (!ecore_file_exists(path))
ecore_file_mkpath(path);
thumb_path = strdup(path);
free(homedir);
}
else return 0;
event_handlers =
evas_list_append(event_handlers,
ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_e_thumb_cb_exe_exit,
NULL));
_exe_del_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
_e_thumb_cb_exe_event_del,
NULL);
return 1;
}
EAPI int
e_thumb_shutdown(void)
{
E_FREE(thumb_path);
while (event_handlers)
{
ecore_event_handler_del(event_handlers->data);
event_handlers = evas_list_remove_list(event_handlers, event_handlers);
}
evas_list_free(thumb_files);
if (pid != -1)
kill(pid, SIGTERM);
ecore_event_handler_del(_exe_del_handler);
_exe_del_handler = NULL;
return 1;
}
/* return dir where thumbs are saved */
EAPI const char *
e_thumb_dir_get(void)
{
return thumb_path;
}
/* queue an image for thumbnailing or return the thumb if it exists */
EAPI Evas_Object *
e_thumb_generate_begin(char *path, Evas_Coord w, Evas_Coord h, Evas *evas, Evas_Object **tmp, void (*cb)(Evas_Object *obj, void *data), void *data)
e_thumb_icon_add(Evas *evas)
{
E_Thumb_Item *t;
Evas_Object *obj;
E_Thumb *eth;
char buf[32];
if(!ecore_file_exists(path)) return *tmp;
if (e_thumb_exists(path))
{
evas_object_del(*tmp);
*tmp = e_thumb_evas_object_get(path, evas, w, h, 1);
return *tmp;
}
t = E_NEW(E_Thumb_Item, 1);
t->w = w;
t->h = h;
t->evas = evas;
t->cb = cb;
t->data = data;
*tmp = e_icon_add(evas);
t->obj = *tmp;
snprintf(t->path, sizeof(t->path), "%s", path);
thumb_files = evas_list_append(thumb_files, t);
if (pid == -1) _e_thumb_generate();
return *tmp;
obj = e_icon_add(evas);
_objid++;
eth = E_NEW(E_Thumb, 1);
eth->objid = _objid;
eth->w = 64;
eth->h = 64;
evas_object_data_set(obj, "e_thumbdata", eth);
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE,
_e_thumb_del_hook, NULL);
_e_thumb_hash_add(eth->objid, obj);
return obj;
}
/* delete an image from the thumb queue */
EAPI void
e_thumb_generate_end(char *path)
e_thumb_icon_file_set(Evas_Object *obj, char *file, char *key)
{
E_Thumb *eth;
eth = evas_object_data_get(obj, "e_thumbdata");
if (!eth) return;
E_FREE(eth->file);
E_FREE(eth->key);
if (file) eth->file = strdup(file);
if (key) eth->key = strdup(key);
}
EAPI void
e_thumb_icon_size_set(Evas_Object *obj, int w, int h)
{
E_Thumb *eth;
eth = evas_object_data_get(obj, "e_thumbdata");
if (!eth) return;
if ((w < 1) || (h <1)) return;
eth->w = w;
eth->h = h;
}
EAPI void
e_thumb_icon_begin(Evas_Object *obj)
{
E_Thumb *eth, *eth2;
char buf[4096];
eth = evas_object_data_get(obj, "e_thumbdata");
if (!eth) return;
if (!eth->file) return;
if (!_thumbnailers)
{
while (evas_list_count(_thumbnailers_exe) < _num_thumbnailers)
{
Ecore_Exe *exe;
snprintf(buf, sizeof(buf), "%s/enlightenment_thumb", e_prefix_bin_get());
exe = ecore_exe_run(buf, NULL);
_thumbnailers_exe = evas_list_append(_thumbnailers_exe, exe);
}
_thumb_queue = evas_list_append(_thumb_queue, eth);
eth->queued = 1;
return;
}
while (_thumb_queue)
{
eth2 = _thumb_queue->data;
_thumb_queue = evas_list_remove_list(_thumb_queue, _thumb_queue);
eth2->queued = 0;
eth2->busy = 1;
_pending++;
_e_thumb_gen_begin(eth2->objid, eth2->file, eth2->key, eth2->w, eth2->h);
}
eth->busy = 1;
_pending++;
_e_thumb_gen_begin(eth->objid, eth->file, eth->key, eth->w, eth->h);
}
EAPI void
e_thumb_icon_end(Evas_Object *obj)
{
E_Thumb *eth;
eth = evas_object_data_get(obj, "e_thumbdata");
if (!eth) return;
if (eth->queued) _thumb_queue = evas_list_remove(_thumb_queue, eth);
eth->queued = 0;
if (eth->busy) _e_thumb_gen_end(eth->objid);
eth->busy = 0;
_pending--;
if (_pending == 0) _e_thumb_thumbnailers_kill();
}
EAPI void
e_thumb_client_data(Ecore_Ipc_Event_Client_Data *e)
{
int objid;
char *icon;
E_Thumb *eth;
Evas_Object *obj;
if (!evas_list_find(_thumbnailers, e->client))
_thumbnailers = evas_list_prepend(_thumbnailers, e->client);
if (e->minor == 2)
{
objid = e->ref;
icon = e->data;
if ((icon) && (e->size > 1) && (icon[e->size - 1] == 0))
{
obj = _e_thumb_hash_find(objid);
if (obj)
{
eth = evas_object_data_get(obj, "e_thumbdata");
if (eth)
{
eth->busy = 0;
_pending--;
if (_pending == 0) _e_thumb_thumbnailers_kill();
e_icon_file_key_set(obj, icon, "/thumbnail/data");
evas_object_smart_callback_call(obj, "e_thumb_gen", NULL);
}
}
}
}
if (e->minor == 1)
{
/* hello message */
while (_thumb_queue)
{
eth = _thumb_queue->data;
_thumb_queue = evas_list_remove_list(_thumb_queue, _thumb_queue);
eth->queued = 0;
eth->busy = 1;
_pending++;
_e_thumb_gen_begin(eth->objid, eth->file, eth->key, eth->w, eth->h);
}
}
}
EAPI void
e_thumb_client_del(Ecore_Ipc_Event_Client_Del *e)
{
if (!evas_list_find(_thumbnailers, e->client)) return;
_thumbnailers = evas_list_remove(_thumbnailers, e->client);
}
/* local subsystem functions */
static void
_e_thumb_gen_begin(int objid, char *file, char *key, int w, int h)
{
char *buf;
int l1, l2;
Ecore_Ipc_Client *cli;
/* send thumb req */
l1 = strlen(file);
l2 = 0;
if (key) l2 = strlen(key);
buf = alloca(l1 + 1 + l2 + 1);
strcpy(buf, file);
if (key) strcpy(buf + l1 + 1, key);
else buf[l1 + 1] = 0;
cli = _thumbnailers->data;
if (!cli) return;
_thumbnailers = evas_list_remove_list(_thumbnailers, _thumbnailers);
_thumbnailers = evas_list_append(_thumbnailers, cli);
ecore_ipc_client_send(cli, E_IPC_DOMAIN_THUMB, 1, objid, w, h, buf, l1 + 1 + l2 + 1);
}
static void
_e_thumb_gen_end(int objid)
{
Evas_List *l;
E_Thumb_Item *t;
Ecore_Ipc_Client *cli;
for(l = thumb_files; l; l = l->next)
/* send thumb cancel */
for (l = _thumbnailers; l; l = l->next)
{
t = l->data;
if(!strcmp(path, t->path))
{
thumb_files = evas_list_remove_list(thumb_files, l);
break;
}
cli = l->data;
ecore_ipc_client_send(cli, E_IPC_DOMAIN_THUMB, 2, objid, 0, 0, NULL, 0);
}
}
/* return hashed path of thumb */
EAPI char *
e_thumb_file_get(char *file)
{
char *id;
char thumb[PATH_MAX];
id = _e_thumb_file_id(file);
if (!id) return NULL;
snprintf(thumb, sizeof(thumb), "%s/%s", thumb_path, id);
free(id);
return strdup(thumb);
}
/* return the width and height of a thumb, if from_eet is set, then we
* assume that the file being passed is the thumb's eet
*/
EAPI void
e_thumb_geometry_get(char *file, int *w, int *h, int from_eet)
{
Eet_File *ef;
if(!from_eet)
{
char *eet_file;
eet_file = _e_thumb_file_id(file);
if(!eet_file)
{
if(w) *w = -1;
if(h) *h = -1;
return;
}
ef = eet_open(eet_file, EET_FILE_MODE_READ);
if (!ef)
{
eet_close(ef);
if(w) *w = -1;
if(h) *h = -1;
return;
}
}
else
{
ef = eet_open(file, EET_FILE_MODE_READ);
if (!ef)
{
eet_close(ef);
if(w) *w = -1;
if(h) *h = -1;
return;
}
}
if(!eet_data_image_header_read(ef, "/thumbnail/data", w, h, NULL, NULL,
NULL, NULL))
{
eet_close(ef);
if(w) *w = -1;
if(h) *h = -1;
return;
}
eet_close(ef);
}
/* return true if the saved thumb exists OR if its an eap */
EAPI int
e_thumb_exists(char *file)
{
char *thumb;
char *ext;
ext = strrchr(file, '.');
if ((ext) && (!strcasecmp(ext, ".eap")))
return 1;
thumb = e_thumb_file_get(file);
if ((thumb) && (ecore_file_exists(thumb)))
{
free(thumb);
return 1;
}
return 0;
}
EAPI int *
_e_thumb_image_create(char *file, Evas_Coord w, Evas_Coord h, int *ww, int *hh, int *alpha, Evas_Object **im, Ecore_Evas **buf)
{
Evas *evasbuf;
int iw, ih;
*buf = ecore_evas_buffer_new(1, 1);
evasbuf = ecore_evas_get(*buf);
*im = evas_object_image_add(evasbuf);
evas_object_image_file_set(*im, 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 = w;
*hh = (w * ih) / iw;
if (*hh > h)
{
*hh = h;
*ww = (h * iw) / ih;
}
ecore_evas_resize(*buf, *ww, *hh);
evas_object_image_fill_set(*im, 0, 0, *ww, *hh);
evas_object_resize(*im, *ww, *hh);
evas_object_move(*im, 0, 0);
evas_object_show(*im);
return (int *)ecore_evas_buffer_pixels_get(*buf);
}
return NULL;
}
/* thumbnail an e17 background and return pixel data */
const int *
_e_thumb_ebg_create(char *file, Evas_Coord w, Evas_Coord h, int *ww, int *hh, int *alpha, Evas_Object **im, Ecore_Evas **buf)
{
Evas *evasbuf;
Evas_Object *wallpaper;
const int *pixels;
*ww = 640;
*hh = 480;
*alpha = 0;
w = 640;
h = 480;
*buf = ecore_evas_buffer_new(w, h);
evasbuf = ecore_evas_get(*buf);
wallpaper = edje_object_add(evasbuf);
edje_object_file_set(wallpaper, file, "desktop/background");
/* wallpaper */
evas_object_move(wallpaper, 0, 0);
evas_object_resize(wallpaper, w, h);
evas_object_show(wallpaper);
pixels = ecore_evas_buffer_pixels_get(*buf);
evas_object_del(wallpaper);
return pixels;
}
/* thumbnail an e17 theme and return pixel data */
const int *
_e_thumb_etheme_create(char *file, Evas_Coord w, Evas_Coord h, int *ww, int *hh, int *alpha, Evas_Object **im, Ecore_Evas **buf)
{
Evas *evasbuf;
Evas_Object *wallpaper, *window, *clock, *start, **pager, *init;
const int *pixels;
int is_init;
*ww = 640;
*hh = 480;
*alpha = 0;
w = 640;
h = 480;
*buf = ecore_evas_buffer_new(w, h);
evasbuf = ecore_evas_get(*buf);
is_init = e_util_edje_collection_exists(file, "init/splash");
if (is_init)
{
init = edje_object_add(evasbuf);
edje_object_file_set(init, file, "init/splash");
evas_object_move(init, 0, 0);
evas_object_resize(init, w, h);
evas_object_show(init);
pixels = ecore_evas_buffer_pixels_get(*buf);
evas_object_del(init);
}
else
{
wallpaper = edje_object_add(evasbuf);
window = edje_object_add(evasbuf);
clock = edje_object_add(evasbuf);
start = edje_object_add(evasbuf);
pager = E_NEW(Evas_Object*, 3);
pager[0] = edje_object_add(evasbuf);
pager[1] = edje_object_add(evasbuf);
pager[2] = edje_object_add(evasbuf);
edje_object_file_set(wallpaper, file, "desktop/background");
edje_object_file_set(window, file, "widgets/border/default/border");
edje_object_file_set(clock, file, "modules/clock/main");
edje_object_file_set(clock, file, "modules/clock/main");
edje_object_file_set(start, file, "modules/start/main");
edje_object_file_set(pager[0], file, "modules/pager/main");
edje_object_file_set(pager[1], file, "modules/pager/desk");
edje_object_file_set(pager[2], file, "modules/pager/window");
edje_object_part_text_set(window, "title_text", file);
edje_object_part_swallow(pager[0], "items", pager[1]);
edje_object_part_swallow(pager[1], "items", pager[2]);
/* wallpaper */
evas_object_move(wallpaper, 0, 0);
evas_object_resize(wallpaper, w, h);
/* main window */
evas_object_move(window, (w * 0.1), (h * 0.05));
evas_object_resize(window, w * 0.8, h * 0.75);
/* clock */
evas_object_move(clock, (w * 0.9), (h * 0.9));
evas_object_resize(clock, w * 0.1, h * 0.1);
/* start */
evas_object_move(start, 0.1, (h * 0.9));
evas_object_resize(start, w * 0.1, h * 0.1);
/* pager */
evas_object_move(pager[0], (w * 0.3), (h * 0.9));
evas_object_resize(pager[0], w * 0.1, h * 0.1);
evas_object_show(wallpaper);
evas_object_show(window);
evas_object_show(clock);
evas_object_show(start);
evas_object_show(pager[0]);
evas_object_show(pager[1]);
evas_object_show(pager[2]);
pixels = ecore_evas_buffer_pixels_get(*buf);
evas_object_del(wallpaper);
evas_object_del(window);
evas_object_del(clock);
evas_object_del(start);
evas_object_del(pager[0]);
evas_object_del(pager[1]);
evas_object_del(pager[2]);
free(pager);
}
return pixels;
}
/* create and save a thumb to disk */
EAPI int
e_thumb_create(char *file, Evas_Coord w, Evas_Coord h)
{
Eet_File *ef;
char *thumbpath, *ext;
Evas_Object *im = NULL;
const int *data;
int size, ww, hh;
Ecore_Evas *buf;
int alpha;
ext = strrchr(file, '.');
if ((ext) && (!strcasecmp(ext, ".eap")))
return 1;
thumbpath = e_thumb_file_get(file);
if (!thumbpath)
return -1;
if (ext)
{
if (!strcasecmp(ext, ".edj"))
{
/* for now, this function does both the bg and theme previews */
data = _e_thumb_etheme_create(file, w, h, &ww, &hh, &alpha, &im, &buf);
}
else
data = _e_thumb_image_create(file, w, h, &ww, &hh, &alpha, &im, &buf);
}
else
data = _e_thumb_image_create(file, w, h, &ww, &hh, &alpha, &im, &buf);
if (data)
{
ef = eet_open(thumbpath, EET_FILE_MODE_WRITE);
if (!ef)
{
free(thumbpath);
if (im) evas_object_del(im);
ecore_evas_free(buf);
return -1;
}
free(thumbpath);
eet_write(ef, "/thumbnail/orig_path", file, strlen(file), 1);
if ((size = eet_data_image_write(ef, "/thumbnail/data",
(void *)data, ww, hh, alpha,
0, 91, 1)) <= 0)
{
if (im) evas_object_del(im);
ecore_evas_free(buf);
eet_close(ef);
return -1;
}
eet_close(ef);
}
if (im) evas_object_del(im);
ecore_evas_free(buf);
return 1;
}
/* get evas object containing image of the thumb */
EAPI Evas_Object *
e_thumb_evas_object_get(char *file, Evas *evas, Evas_Coord width, Evas_Coord height, int shrink)
{
Eet_File *ef;
char *thumb, *ext;
Evas_Object *im = NULL;
#define DEF_THUMB_RETURN im = evas_object_rectangle_add(evas); \
evas_object_color_set(im, 255, 255, 255, 255); \
evas_object_resize(im, width, height); \
return im
D(("e_thumb_evas_object_get: (%s)\n", file));
/* eap thumbnailer */
ext = strrchr(file, '.');
if (ext)
{
if (!strcasecmp(ext, ".eap"))
{
E_App *app;
D(("e_thumb_evas_object_get: eap found\n"));
app = e_app_new(file, 0);
D(("e_thumb_evas_object_get: eap loaded\n"));
if (!app)
{
D(("e_thumb_evas_object_get: invalid eap\n"));
DEF_THUMB_RETURN;
}
else
{
D(("e_thumb_evas_object_get: creating eap thumb\n"));
im = e_icon_add(evas);
e_icon_file_edje_set(im, file, "icon");
e_object_unref(E_OBJECT(app));
D(("e_thumb_evas_object_get: returning eap thumb\n"));
return im;
}
}
}
/* saved thumb */
/* TODO: add ability to fetch thumbs from freedesktop dirs */
if (!e_thumb_exists(file))
{
if (!e_thumb_create(file, width, height))
{
DEF_THUMB_RETURN;
}
}
thumb = e_thumb_file_get(file);
if (!thumb)
{
DEF_THUMB_RETURN;
}
ef = eet_open(thumb, EET_FILE_MODE_READ);
if (!ef)
{
eet_close(ef);
free(thumb);
DEF_THUMB_RETURN;
}
im = e_icon_add(evas);
e_icon_file_key_set(im, thumb, "/thumbnail/data");
if (shrink)
{
Evas_Coord sw, sh;
e_icon_size_get(im, &sw, &sh);
evas_object_resize(im, sw, sh);
}
e_icon_fill_inside_set(im, 1);
free(thumb);
eet_close(ef);
return im;
}
/* return hash for a file */
static char *
_e_thumb_file_id(char *file)
{
char s[256], *sp;
const char *chmap =
"0123456789abcdef"
"ghijklmnopqrstuv"
"wxyz`~!@#$%^&*()"
"[];',.{}<>?-=_+|";
unsigned int id[4], i;
struct stat st;
if (stat(file, &st) < 0)
return NULL;
id[0] = st.st_ino;
id[1] = st.st_dev;
id[2] = (st.st_size & 0xffffffff);
id[3] = (st.st_mtime & 0xffffffff);
sp = s;
for (i = 0; i < 4; i++)
{
unsigned int t, tt;
int j;
t = id[i];
j = 32;
while (j > 0)
{
tt = t & ((1 << 6) - 1);
*sp = chmap[tt];
t >>= 6;
j -= 6;
sp++;
}
}
*sp = 0;
return strdup(s);
}
/* generate a thumb from the list of queued thumbs */
static void
_e_thumb_generate(void)
_e_thumb_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
E_Thumb_Item *t;
E_Thumb *eth;
if ((!thumb_files) || (pid != -1)) return;
pid = fork();
if (pid == 0)
eth = evas_object_data_get(obj, "e_thumbdata");
if (!eth) return;
evas_object_data_del(obj, "e_thumbdata");
_e_thumb_hash_del(eth->objid);
if (eth->busy)
{
/* reset signal handlers for the child */
signal(SIGSEGV, SIG_DFL);
signal(SIGILL, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGBUS, SIG_DFL);
t = thumb_files->data;
if (!e_thumb_exists(t->path))
e_thumb_create(t->path, t->w, t->h);
eet_clearcache();
exit(0);
}
_e_thumb_gen_end(eth->objid);
_pending--;
if (_pending == 0) _e_thumb_thumbnailers_kill();
}
if (eth->queued)
_thumb_queue = evas_list_remove(_thumb_queue, eth);
E_FREE(eth->file);
E_FREE(eth->key);
free(eth);
}
static void
_e_thumb_hash_add(int objid, Evas_Object *obj)
{
char buf[32];
snprintf(buf, sizeof(buf), "%i", objid);
_thumbs = evas_hash_add(_thumbs, buf, obj);
}
static void
_e_thumb_hash_del(int objid)
{
char buf[32];
snprintf(buf, sizeof(buf), "%i", objid);
_thumbs = evas_hash_del(_thumbs, buf, NULL);
}
static Evas_Object *
_e_thumb_hash_find(int objid)
{
char buf[32];
snprintf(buf, sizeof(buf), "%i", objid);
return evas_hash_find(_thumbs, buf);
}
static void
_e_thumb_thumbnailers_kill(void)
{
Evas_List *l;
for (l = _thumbnailers_exe; l; l = l->next)
ecore_exe_terminate(l->data);
}
/* called when a thumb is generated */
static int
_e_thumb_cb_exe_exit(void *data, int type, void *event)
_e_thumb_cb_exe_event_del(void *data, int type, void *event)
{
Ecore_Exe_Event_Del *ev;
E_Thumb_Item *t;
char *ext;
Evas_List *l;
ev = event;
if (ev->pid != pid) return 1;
if (!thumb_files)
for (l = _thumbnailers_exe; l; l = l->next)
{
pid = -1;
return 1;
}
t = thumb_files->data;
thumb_files = evas_list_remove_list(thumb_files, thumb_files);
ext = strrchr(t->path, '.');
if ((ext) && (strcasecmp(ext, ".eap")))
ext = NULL;
if ((ext) || (ecore_file_exists(t->path)))
{
Evas_Coord w, h;
Evas_Object *tmp;
void *data;
tmp = e_thumb_evas_object_get(t->path,
t->evas,
t->w,
t->h,
1);
if (tmp && t)
if (l->data == ev->exe)
{
data = e_icon_data_get(tmp, &w, &h);
e_icon_data_set(t->obj, data, w, h);
evas_object_del(tmp);
if(t->cb)
t->cb(t->obj, t->data);
free(t);
_thumbnailers_exe = evas_list_remove_list(_thumbnailers_exe, l);
break;
}
}
pid = -1;
_e_thumb_generate();
return 1;
}

View File

@ -10,14 +10,15 @@
EAPI int e_thumb_init(void);
EAPI int e_thumb_shutdown(void);
EAPI const char *e_thumb_dir_get(void);
EAPI char *e_thumb_file_get(char *file);
EAPI void e_thumb_geometry_get(char *file, int *w, int *h, int from_eet);
EAPI int e_thumb_exists(char *file);
EAPI int e_thumb_create(char *file, Evas_Coord w, Evas_Coord h);
EAPI Evas_Object *e_thumb_evas_object_get(char *file, Evas *evas, Evas_Coord width, Evas_Coord height, int shrink);
EAPI Evas_Object *e_thumb_generate_begin(char *path, Evas_Coord w, Evas_Coord h, Evas *evas, Evas_Object **tmp, void (*cb)(Evas_Object *obj, void *data), void *data);
EAPI void e_thumb_generate_end(char *path);
EAPI Evas_Object *e_thumb_icon_add(Evas *evas);
EAPI void e_thumb_icon_file_set(Evas_Object *obj, char *file, char *key);
EAPI void e_thumb_icon_size_set(Evas_Object *obj, int w, int h);
EAPI void e_thumb_icon_begin(Evas_Object *obj);
EAPI void e_thumb_icon_end(Evas_Object *obj);
EAPI void e_thumb_client_data(Ecore_Ipc_Event_Client_Data *e);
EAPI void e_thumb_client_del(Ecore_Ipc_Event_Client_Del *e);
#endif
#endif

388
src/bin/e_thumb_main.c Normal file
View File

@ -0,0 +1,388 @@
/*
* 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 <Evas.h>
#include <Eet.h>
#include <Edje.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 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)
{
int i;
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();
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_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;
if (!e->data) return 1;
switch (e->minor)
{
case 1:
/* 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.001, _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;
/* take thumb at head of list */
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.001, _e_cb_timer, NULL);
else _timer = NULL;
}
else
_timer = NULL;
return 0;
}
static void
_e_thumb_generate(E_Thumb *eth)
{
char buf[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[3] = 0;
snprintf(buf, sizeof(buf), "%s/%s", _thumbdir, td);
ecore_file_mkdir(buf);
snprintf(buf, sizeof(buf), "%s/%s/%s.thm", _thumbdir, td, id + 3);
free(id);
free(td);
mtime_orig = ecore_file_mod_time(eth->file);
mtime_thumb = ecore_file_mod_time(buf);
if (mtime_thumb <= mtime_orig)
{
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;
ext = strrchr(eth->file, '.');
if ((ext) && (!strcasecmp(ext, ".edj")) && (eth->key))
{
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 (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_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);
}
static char *
_e_thumb_file_id(char *file, char *key)
{
char s[512], *sp;
const char *chmap =
"0123456789abcdef"
"ghijklmnopqrstuv";
unsigned int id[8], i, t, tt;
int j;
for (i = 0; i < 8; i++) id[i] = 0x55555555;
j = 0;
sp = file;
while (*sp)
{
i = ((int)*sp) & 0x7;
id[i] ^= ((int)*sp) << j;
j++;
if (j == 25) j = 0;
sp++;
}
sp = key;
if (sp)
{
while (*sp)
{
i = ((int)*sp) & 0x7;
id[i] ^= ((int)*sp) << j;
j++;
if (j == 25) j = 0;
sp++;
}
}
sp = s;
for (i = 0; i < 8; i++)
{
t = id[i];
j = 32;
while (j > 0)
{
tt = t & ((1 << 5) - 1);
*sp = chmap[tt];
t >>= 5;
j -= 5;
sp++;
}
}
*sp = 0;
return strdup(s);
}