From 31fc2b0dfaaeb3af320b23a78baf5429763bba54 Mon Sep 17 00:00:00 2001 From: Rafael Antognolli Date: Mon, 13 Jul 2009 19:38:17 +0000 Subject: [PATCH] Added support to creating animated thumbnails from videos. These thumbnails are generated using an edje template. Each thumbnail is an edje file, that has a group called "movie/thumb" The thumbnail can be animated by receiving a signal "animate" or "animate_loop" (the last one being a loop animation that calls itself when finished), and the animate_loop program can be stopped by receiving a signal "animate_stop". The transition time is set based on the time of the animation (that is set by the call ethumb_video_time_set()). SVN revision: 41322 --- legacy/ethumb/src/bin/ethumb.c | 4 +- legacy/ethumb/src/bin/ethumbd.c | 109 ++++++ legacy/ethumb/src/bin/ethumbd_child.c | 72 ++++ legacy/ethumb/src/bin/ethumbd_private.h | 4 + legacy/ethumb/src/lib/Ethumb.c | 69 ++++ legacy/ethumb/src/lib/Ethumb.h | 10 + legacy/ethumb/src/lib/client/Ethumb_Client.c | 60 +++- legacy/ethumb/src/lib/client/Ethumb_Client.h | 4 + legacy/ethumb/src/lib/ethumb_private.h | 3 +- legacy/ethumb/src/plugins/emotion/Makefile.am | 20 +- legacy/ethumb/src/plugins/emotion/emotion.c | 315 ++++++++++++++++-- .../ethumb/src/plugins/emotion/template.edc | 40 +++ 12 files changed, 681 insertions(+), 29 deletions(-) create mode 100644 legacy/ethumb/src/plugins/emotion/template.edc diff --git a/legacy/ethumb/src/bin/ethumb.c b/legacy/ethumb/src/bin/ethumb.c index faf6e801f4..72681f3c4b 100644 --- a/legacy/ethumb/src/bin/ethumb.c +++ b/legacy/ethumb/src/bin/ethumb.c @@ -31,7 +31,7 @@ #include const char *aspect_opt[] = { "keep", "ignore", "crop", NULL }; -const char *format_opt[] = { "png", "jpg", NULL }; +const char *format_opt[] = { "png", "jpg", "eet", NULL }; struct frame { const char *file; @@ -182,7 +182,7 @@ main(int argc, char *argv[]) r = 0; } - for (i = 0; i < 2; i++) + for (i = 0; i < 3; i++) if (format_opt[i] == format_str) { format = i; diff --git a/legacy/ethumb/src/bin/ethumbd.c b/legacy/ethumb/src/bin/ethumbd.c index 9ff018c915..c1f97d2d05 100644 --- a/legacy/ethumb/src/bin/ethumbd.c +++ b/legacy/ethumb/src/bin/ethumbd.c @@ -70,6 +70,10 @@ struct _Ethumb_Setup Eina_Bool category : 1; Eina_Bool frame : 1; Eina_Bool video_time : 1; + Eina_Bool video_start : 1; + Eina_Bool video_interval : 1; + Eina_Bool video_ntimes : 1; + Eina_Bool video_fps : 1; Eina_Bool document_page : 1; } flags; int fdo; @@ -85,6 +89,10 @@ struct _Ethumb_Setup const char *group; const char *swallow; float video_time; + float video_start; + float video_interval; + int video_ntimes; + int video_fps; int document_page; }; @@ -477,12 +485,16 @@ _ethumbd_pipe_write_setup(int fd, int type, const void *data) case ETHUMBD_SIZE_W: case ETHUMBD_SIZE_H: case ETHUMBD_DOCUMENT_PAGE: + case ETHUMBD_VIDEO_NTIMES: + case ETHUMBD_VIDEO_FPS: i_value = data; _ethumbd_write_safe(fd, i_value, sizeof(*i_value)); break; case ETHUMBD_CROP_X: case ETHUMBD_CROP_Y: case ETHUMBD_VIDEO_TIME: + case ETHUMBD_VIDEO_START: + case ETHUMBD_VIDEO_INTERVAL: f_value = data; _ethumbd_write_safe(fd, f_value, sizeof(*f_value)); break; @@ -544,6 +556,15 @@ _process_setup(struct _Ethumbd *ed) } if (setup->flags.video_time) _ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_TIME, &setup->video_time); + if (setup->flags.video_start) + _ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_START, &setup->video_start); + if (setup->flags.video_interval) + _ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_INTERVAL, + &setup->video_interval); + if (setup->flags.video_ntimes) + _ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_NTIMES, &setup->video_ntimes); + if (setup->flags.video_fps) + _ethumbd_pipe_write_setup(fd, ETHUMBD_VIDEO_FPS, &setup->video_fps); if (setup->flags.document_page) _ethumbd_pipe_write_setup(fd, ETHUMBD_DOCUMENT_PAGE, &setup->document_page); @@ -1327,6 +1348,90 @@ _ethumb_dbus_video_time_set(struct _Ethumb_Object *eobject, DBusMessageIter *ite return 1; } +static int +_ethumb_dbus_video_start_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request) +{ + int type; + double video_start; + + type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_DOUBLE) + { + ERR("invalid param for video_start_set.\n"); + return 0; + } + + dbus_message_iter_get_basic(iter, &video_start); + DBG("setting video_start to: %3.2f\n", video_start); + request->setup.flags.video_start = 1; + request->setup.video_start = video_start; + + return 1; +} + +static int +_ethumb_dbus_video_interval_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request) +{ + int type; + double video_interval; + + type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_DOUBLE) + { + ERR("invalid param for video_interval_set.\n"); + return 0; + } + + dbus_message_iter_get_basic(iter, &video_interval); + DBG("setting video_interval to: %3.2f\n", video_interval); + request->setup.flags.video_interval = 1; + request->setup.video_interval = video_interval; + + return 1; +} + +static int +_ethumb_dbus_video_ntimes_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request) +{ + int type; + int video_ntimes; + + type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_INT32) + { + ERR("invalid param for video_ntimes_set.\n"); + return 0; + } + + dbus_message_iter_get_basic(iter, &video_ntimes); + DBG("setting video_ntimes to: %3.2d\n", video_ntimes); + request->setup.flags.video_ntimes = 1; + request->setup.video_ntimes = video_ntimes; + + return 1; +} + +static int +_ethumb_dbus_video_fps_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request) +{ + int type; + int video_fps; + + type = dbus_message_iter_get_arg_type(iter); + if (type != DBUS_TYPE_INT32) + { + ERR("invalid param for video_fps_set.\n"); + return 0; + } + + dbus_message_iter_get_basic(iter, &video_fps); + DBG("setting video_fps to: %3.2d\n", video_fps); + request->setup.flags.video_fps = 1; + request->setup.video_fps = video_fps; + + return 1; +} + static int _ethumb_dbus_document_page_set(struct _Ethumb_Object *eobject, DBusMessageIter *iter, struct _Ethumb_Request *request) { @@ -1364,6 +1469,10 @@ static struct { "directory", _ethumb_dbus_directory_set }, { "category", _ethumb_dbus_category_set }, { "video_time", _ethumb_dbus_video_time_set }, + { "video_start", _ethumb_dbus_video_start_set }, + { "video_interval", _ethumb_dbus_video_interval_set }, + { "video_ntimes", _ethumb_dbus_video_ntimes_set }, + { "video_fps", _ethumb_dbus_video_fps_set }, { "document_page", _ethumb_dbus_document_page_set }, { NULL, NULL} }; diff --git a/legacy/ethumb/src/bin/ethumbd_child.c b/legacy/ethumb/src/bin/ethumbd_child.c index 8e953c2aca..5a6ac805a0 100644 --- a/legacy/ethumb/src/bin/ethumbd_child.c +++ b/legacy/ethumb/src/bin/ethumbd_child.c @@ -475,6 +475,66 @@ _ec_video_time_set(struct _Ethumbd_Child *ec, Ethumb *e) return 1; } +static int +_ec_video_start_set(struct _Ethumbd_Child *ec, Ethumb *e) +{ + int r; + float value; + + r = _ec_read_safe(ec->pipein, &value, sizeof(value)); + if (!r) + return 0; + ethumb_video_start_set(e, value); + DBG("video_start = %f\n", value); + + return 1; +} + +static int +_ec_video_interval_set(struct _Ethumbd_Child *ec, Ethumb *e) +{ + int r; + float value; + + r = _ec_read_safe(ec->pipein, &value, sizeof(value)); + if (!r) + return 0; + ethumb_video_interval_set(e, value); + DBG("video_interval = %f\n", value); + + return 1; +} + +static int +_ec_video_ntimes_set(struct _Ethumbd_Child *ec, Ethumb *e) +{ + int r; + int value; + + r = _ec_read_safe(ec->pipein, &value, sizeof(value)); + if (!r) + return 0; + ethumb_video_ntimes_set(e, value); + DBG("video_ntimes = %d\n", value); + + return 1; +} + +static int +_ec_video_fps_set(struct _Ethumbd_Child *ec, Ethumb *e) +{ + int r; + int value; + + r = _ec_read_safe(ec->pipein, &value, sizeof(value)); + if (!r) + return 0; + ethumb_video_fps_set(e, value); + DBG("video_fps = %d\n", value); + + return 1; +} + static int _ec_document_page_set(struct _Ethumbd_Child *ec, Ethumb *e) { @@ -532,6 +592,18 @@ _ec_setup_process(struct _Ethumbd_Child *ec, int index, int type) case ETHUMBD_VIDEO_TIME: _ec_video_time_set(ec, e); break; + case ETHUMBD_VIDEO_START: + _ec_video_start_set(ec, e); + break; + case ETHUMBD_VIDEO_INTERVAL: + _ec_video_interval_set(ec, e); + break; + case ETHUMBD_VIDEO_NTIMES: + _ec_video_ntimes_set(ec, e); + break; + case ETHUMBD_VIDEO_FPS: + _ec_video_fps_set(ec, e); + break; case ETHUMBD_DOCUMENT_PAGE: _ec_document_page_set(ec, e); break; diff --git a/legacy/ethumb/src/bin/ethumbd_private.h b/legacy/ethumb/src/bin/ethumbd_private.h index 666b684244..c8ac4d0f8d 100644 --- a/legacy/ethumb/src/bin/ethumbd_private.h +++ b/legacy/ethumb/src/bin/ethumbd_private.h @@ -27,6 +27,10 @@ enum Ethubmd_Setup_Option ETHUMBD_FRAME_GROUP, ETHUMBD_FRAME_SWALLOW, ETHUMBD_VIDEO_TIME, + ETHUMBD_VIDEO_START, + ETHUMBD_VIDEO_INTERVAL, + ETHUMBD_VIDEO_NTIMES, + ETHUMBD_VIDEO_FPS, ETHUMBD_DOCUMENT_PAGE, ETHUMBD_SETUP_FINISHED }; diff --git a/legacy/ethumb/src/lib/Ethumb.c b/legacy/ethumb/src/lib/Ethumb.c index b3e8d3dc0a..fdcdc00661 100644 --- a/legacy/ethumb/src/lib/Ethumb.c +++ b/legacy/ethumb/src/lib/Ethumb.c @@ -190,6 +190,11 @@ ethumb_new(void) ethumb->crop_y = 0.5; ethumb->quality = 80; ethumb->compress = 9; + ethumb->video.start = 0.1; + ethumb->video.time = 3; + ethumb->video.interval = 0.05; + ethumb->video.ntimes = 3; + ethumb->video.fps = 10; ee = ecore_evas_buffer_new(1, 1); e = ecore_evas_get(ee); @@ -562,6 +567,22 @@ ethumb_thumb_category_get(const Ethumb *e) return e->category; } +EAPI void +ethumb_video_start_set(Ethumb *e, float start) +{ + EINA_SAFETY_ON_NULL_RETURN(e); + + e->video.start = start; +} + +EAPI float +ethumb_video_start_get(const Ethumb *e) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); + + return e->video.start; +} + EAPI void ethumb_video_time_set(Ethumb *e, float time) { @@ -578,6 +599,54 @@ ethumb_video_time_get(const Ethumb *e) return e->video.time; } +EAPI void +ethumb_video_interval_set(Ethumb *e, float interval) +{ + EINA_SAFETY_ON_NULL_RETURN(e); + + e->video.interval = interval; +} + +EAPI float +ethumb_video_interval_get(const Ethumb *e) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); + + return e->video.interval; +} + +EAPI void +ethumb_video_ntimes_set(Ethumb *e, int ntimes) +{ + EINA_SAFETY_ON_NULL_RETURN(e); + + e->video.ntimes = ntimes; +} + +EAPI int +ethumb_video_ntimes_get(const Ethumb *e) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); + + return e->video.ntimes; +} + +EAPI void +ethumb_video_fps_set(Ethumb *e, int fps) +{ + EINA_SAFETY_ON_NULL_RETURN(e); + + e->video.fps = fps; +} + +EAPI int +ethumb_video_fps_get(const Ethumb *e) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); + + return e->video.fps; +} + EAPI void ethumb_document_page_set(Ethumb *e, int page) { diff --git a/legacy/ethumb/src/lib/Ethumb.h b/legacy/ethumb/src/lib/Ethumb.h index eacf7a2085..107128c5ff 100644 --- a/legacy/ethumb/src/lib/Ethumb.h +++ b/legacy/ethumb/src/lib/Ethumb.h @@ -105,8 +105,18 @@ EAPI const char * ethumb_thumb_dir_path_get(const Ethumb *e) EINA_WARN_UNUSED_RE EAPI void ethumb_thumb_category_set(Ethumb *e, const char *category) EINA_ARG_NONNULL(1); EAPI const char * ethumb_thumb_category_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; + +EAPI void ethumb_video_start_set(Ethumb *e, float start) EINA_ARG_NONNULL(1); +EAPI float ethumb_video_start_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; EAPI void ethumb_video_time_set(Ethumb *e, float time) EINA_ARG_NONNULL(1); EAPI float ethumb_video_time_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; +EAPI void ethumb_video_interval_set(Ethumb *e, float interval) EINA_ARG_NONNULL(1); +EAPI float ethumb_video_interval_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; +EAPI void ethumb_video_ntimes_set(Ethumb *e, int ntimes) EINA_ARG_NONNULL(1); +EAPI int ethumb_video_ntimes_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; +EAPI void ethumb_video_fps_set(Ethumb *e, int fps) EINA_ARG_NONNULL(1); +EAPI int ethumb_video_fps_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; + EAPI void ethumb_document_page_set(Ethumb *e, int page) EINA_ARG_NONNULL(1); EAPI int ethumb_document_page_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE; diff --git a/legacy/ethumb/src/lib/client/Ethumb_Client.c b/legacy/ethumb/src/lib/client/Ethumb_Client.c index f6f8f4bec3..4a2d20175f 100644 --- a/legacy/ethumb/src/lib/client/Ethumb_Client.c +++ b/legacy/ethumb/src/lib/client/Ethumb_Client.c @@ -604,8 +604,8 @@ ethumb_client_ethumb_setup(Ethumb_Client *client) double t; const char *theme_file, *group, *swallow; const char *directory, *category; - double video_time; - dbus_int32_t document_page; + double video_time, video_start, video_interval; + dbus_int32_t video_ntimes, video_fps, document_page; EINA_SAFETY_ON_NULL_RETURN(client); client->ethumb_dirty = 0; @@ -692,6 +692,26 @@ ethumb_client_ethumb_setup(Ethumb_Client *client) dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_time); _close_variant_iter(viter); + _open_variant_iter("video_start", "d", viter); + video_start = ethumb_video_start_get(e); + dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_start); + _close_variant_iter(viter); + + _open_variant_iter("video_interval", "d", viter); + video_interval = ethumb_video_interval_get(e); + dbus_message_iter_append_basic(&viter, DBUS_TYPE_DOUBLE, &video_interval); + _close_variant_iter(viter); + + _open_variant_iter("video_ntimes", "i", viter); + video_ntimes = ethumb_video_ntimes_get(e); + dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &video_ntimes); + _close_variant_iter(viter); + + _open_variant_iter("video_fps", "i", viter); + video_fps = ethumb_video_fps_get(e); + dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &video_fps); + _close_variant_iter(viter); + _open_variant_iter("document_page", "i", viter); document_page = ethumb_document_page_get(e); dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &document_page); @@ -1147,6 +1167,42 @@ ethumb_client_video_time_set(Ethumb_Client *client, float time) ethumb_video_time_set(client->ethumb, time); } +EAPI void +ethumb_client_video_start_set(Ethumb_Client *client, float start) +{ + EINA_SAFETY_ON_NULL_RETURN(client); + + client->ethumb_dirty = 1; + ethumb_video_start_set(client->ethumb, start); +} + +EAPI void +ethumb_client_video_interval_set(Ethumb_Client *client, float interval) +{ + EINA_SAFETY_ON_NULL_RETURN(client); + + client->ethumb_dirty = 1; + ethumb_video_interval_set(client->ethumb, interval); +} + +EAPI void +ethumb_client_video_ntimes_set(Ethumb_Client *client, int ntimes) +{ + EINA_SAFETY_ON_NULL_RETURN(client); + + client->ethumb_dirty = 1; + ethumb_video_ntimes_set(client->ethumb, ntimes); +} + +EAPI void +ethumb_client_video_fps_set(Ethumb_Client *client, int fps) +{ + EINA_SAFETY_ON_NULL_RETURN(client); + + client->ethumb_dirty = 1; + ethumb_video_fps_set(client->ethumb, fps); +} + EAPI void ethumb_client_document_page_set(Ethumb_Client *client, int page) { diff --git a/legacy/ethumb/src/lib/client/Ethumb_Client.h b/legacy/ethumb/src/lib/client/Ethumb_Client.h index 622540f4ae..1142c190f5 100644 --- a/legacy/ethumb/src/lib/client/Ethumb_Client.h +++ b/legacy/ethumb/src/lib/client/Ethumb_Client.h @@ -72,6 +72,10 @@ EAPI const char * ethumb_client_dir_path_get(const Ethumb_Client *client); EAPI void ethumb_client_category_set(Ethumb_Client *client, const char *category); EAPI const char * ethumb_client_category_get(const Ethumb_Client *client); EAPI void ethumb_client_video_time_set(Ethumb_Client *client, float time); +EAPI void ethumb_client_video_start_set(Ethumb_Client *client, float start); +EAPI void ethumb_client_video_interval_set(Ethumb_Client *client, float interval); +EAPI void ethumb_client_video_ntimes_set(Ethumb_Client *client, int ntimes); +EAPI void ethumb_client_video_fps_set(Ethumb_Client *client, int fps); EAPI void ethumb_client_document_page_set(Ethumb_Client *client, int page); EAPI void ethumb_client_ethumb_setup(Ethumb_Client *client); diff --git a/legacy/ethumb/src/lib/ethumb_private.h b/legacy/ethumb/src/lib/ethumb_private.h index a0ba51c95f..cce6f0c1c1 100644 --- a/legacy/ethumb/src/lib/ethumb_private.h +++ b/legacy/ethumb/src/lib/ethumb_private.h @@ -28,7 +28,8 @@ struct _Ethumb int rw, rh; struct { - double time; + double start, time, interval; + int ntimes, fps; } video; struct { diff --git a/legacy/ethumb/src/plugins/emotion/Makefile.am b/legacy/ethumb/src/plugins/emotion/Makefile.am index 00fb6d02e4..3b0f5bffd4 100644 --- a/legacy/ethumb/src/plugins/emotion/Makefile.am +++ b/legacy/ethumb/src/plugins/emotion/Makefile.am @@ -1,12 +1,28 @@ MAINTAINERCLEANFILES = Makefile.in +EDJE_CC = edje_cc +EDJE_FLAGS = -v + +filesdir = $(pluginsdir)/data +files_DATA = emotion_template.edj + +EXTRA_DIST= \ + template.edc + AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/emotion \ - @EVAS_CFLAGS@ @EINA_CFLAGS@ @EMOTION_CFLAGS@ @ECORE_CFLAGS@ + @EVAS_CFLAGS@ @EINA_CFLAGS@ @EMOTION_CFLAGS@ @ECORE_CFLAGS@ \ + @EDJE_CFLAGS@ pkgdir = $(pluginsdir) pkg_LTLIBRARIES = emotion.la emotion_la_SOURCES = emotion.c emotion_la_DEPENDENCIES = $(top_builddir)/config.h emotion_la_LIBADD = $(top_builddir)/src/lib/libethumb.la \ - @EVAS_LIBS@ @EINA_LIBS@ @EMOTION_LIBS@ @ECORE_LIBS@ + @EVAS_LIBS@ @EINA_LIBS@ @EMOTION_LIBS@ @ECORE_LIBS@ @EDJE_LIBS@ emotion_la_LDFLAGS = -module -avoid-version + + +emotion_template.edj: Makefile $(EXTRADIST) + $(EDJE_CC) $(EDJE_FLAGS) \ + $(top_srcdir)/src/plugins/emotion/template.edc \ + $(top_builddir)/src/plugins/emotion/emotion_template.edj diff --git a/legacy/ethumb/src/plugins/emotion/emotion.c b/legacy/ethumb/src/plugins/emotion/emotion.c index b82db3319d..0883b79c23 100644 --- a/legacy/ethumb/src/plugins/emotion/emotion.c +++ b/legacy/ethumb/src/plugins/emotion/emotion.c @@ -5,31 +5,280 @@ #include #include #include +#include +#include #include +#include +#include #include -static Evas_Object *_emotion = NULL; +struct _emotion_plugin +{ + int fps; + double ptotal, len, pi; + double total_time, tmp_time; + int pcount; + int frnum; + int first; + Eet_File *ef; + Evas_Object *video; + Ethumb *e; + int w, h; +}; + +static void +_resize_movie(struct _emotion_plugin *_plugin) +{ + Ethumb *e = _plugin->e; + double ratio; + int w, h; + int fx, fy, fw, fh; + + ratio = emotion_object_ratio_get(_plugin->video); + ethumb_calculate_aspect_from_ratio(e, ratio, &w, &h); + ethumb_calculate_fill_from_ratio(e, ratio, &fx, &fy, &fw, &fh); + + _plugin->w = w; + _plugin->h = h; + + ethumb_plugin_image_resize(e, _plugin->w, _plugin->h); + + evas_object_resize(_plugin->video, fw, fh); + evas_object_move(_plugin->video, fx, fy); + emotion_object_audio_mute_set(_plugin->video, 1); +} static void _frame_resized_cb(void *data, Evas_Object *o, void *event_info) { - Ethumb *e = data; - Evas_Coord ww, hh; - Evas_Coord mw, mh; + _resize_movie(data); +} - emotion_object_size_get(o, &mw, &mh); - ethumb_calculate_aspect(e, mw, mh, &ww, &hh); - ethumb_plugin_image_resize(e, ww, hh); +static void +_video_stopped_cb(void *data, Evas_Object *o, void *event_info) +{ + struct _emotion_plugin *_plugin = data; - evas_object_resize(o, ww, hh); - evas_object_move(o, 0, 0); + _plugin->pi = 0; + _plugin->ptotal = 0; + _plugin->first = 0; + _plugin->total_time = _plugin->tmp_time; +} + +static void +_video_pos_set(struct _emotion_plugin *_plugin) +{ + double pos; + double interval; + + pos = ethumb_video_start_get(_plugin->e); + interval = ethumb_video_interval_get(_plugin->e); + _plugin->len = emotion_object_play_length_get(_plugin->video); + + if (_plugin->len > 0) + _plugin->first = 1; + + if (pos <=0 || pos >= 1) + _plugin->pi = 0.2 * _plugin->len + _plugin->pcount * + _plugin->len * interval; + else + _plugin->pi = pos * _plugin->len + _plugin->pcount * + _plugin->len * interval; + + emotion_object_position_set(_plugin->video, _plugin->pi); +} + +static int +_setup_thumbnail(struct _emotion_plugin *_plugin) +{ + char buf[4096]; + Evas *evas; + Evas_Object *edje; + int i; + const char *thumb_path; + + ethumb_thumb_path_get(_plugin->e, &thumb_path, NULL); + evas = ethumb_evas_get(_plugin->e); + + if (!edje_file_group_exists(thumb_path, "movie/thumb")) + { + fprintf(stderr, "ERROR: no group 'movie/thumb' found.\n"); + goto exit_error; + } + + edje = edje_object_add(evas); + edje_object_file_set(edje, thumb_path, "movie/thumb"); + if (!edje_object_part_exists(edje, "image")) + { + fprintf(stderr, "ERROR: no 'image' part found.\n"); + evas_object_del(edje); + goto exit_error; + } + if (!edje_edit_program_exist(edje, "animate")) + { + fprintf(stderr, "ERROR: no 'animate' program found.\n"); + evas_object_del(edje); + goto exit_error; + } + + for (i = 0; i < _plugin->frnum; i++) + { + snprintf(buf, sizeof(buf), "images/%d", i); + edje_edit_image_data_add(edje, buf, i); + if (i == 0) + edje_edit_state_image_set(edje, "image", "default 0.00", buf); + else + edje_edit_state_tween_add(edje, "image", "default 0.00", buf); + } + + edje_edit_program_transition_time_set(edje, "animate", + _plugin->total_time); + edje_edit_program_transition_time_set(edje, "animate_loop", + _plugin->total_time); + edje_edit_group_min_w_set(edje, _plugin->w); + edje_edit_group_max_w_set(edje, _plugin->w); + edje_edit_group_min_h_set(edje, _plugin->h); + edje_edit_group_max_h_set(edje, _plugin->h); + edje_edit_save(edje); + + evas_object_del(edje); + + return 1; + +exit_error: + return 0; +} + +static void +_finish_thumb_generation(struct _emotion_plugin *_plugin, int success) +{ + int r = 0; + evas_object_smart_callback_del(_plugin->video, "frame_resize", + _frame_resized_cb); + emotion_object_play_set(_plugin->video, 0); + evas_object_del(_plugin->video); + if (_plugin->ef) + eet_close(_plugin->ef); + + if (success) + r = _setup_thumbnail(_plugin); + + free(_plugin); + ethumb_finished_callback_call(_plugin->e, r); +} + +static int +_frame_grab_single(void *data) +{ + struct _emotion_plugin *_plugin = data; + Ethumb *e = _plugin->e; + double p; + + if (_plugin->len <= 0) + { + _video_pos_set(_plugin); + return EINA_TRUE; + } + + p = emotion_object_position_get(_plugin->video); + if (p < _plugin->pi) + return EINA_TRUE; ethumb_image_save(e); - evas_object_smart_callback_del(o, "frame_resize", _frame_resized_cb); - emotion_object_play_set(o, 0); - evas_object_del(o); + evas_object_smart_callback_del(_plugin->video, "frame_resize", + _frame_resized_cb); + emotion_object_play_set(_plugin->video, 0); + evas_object_del(_plugin->video); + free(_plugin); ethumb_finished_callback_call(e, 1); + + return EINA_FALSE; +} + +static int +_frame_grab(void *data) +{ + struct _emotion_plugin *_plugin = data; + Ethumb *e = _plugin->e; + char buf[4096]; + const void *pixels; + double p; + + if (_plugin->len <= 0) + { + _video_pos_set(_plugin); + return EINA_TRUE; + } + + p = emotion_object_position_get(_plugin->video); + if (p < _plugin->pi) + return EINA_TRUE; + + if (_plugin->first) + { + _plugin->pi = p; + _plugin->first = 0; + } + + if (p > _plugin->pi + _plugin->ptotal) + { + _plugin->total_time += _plugin->tmp_time; + if (_plugin->pcount >= ethumb_video_ntimes_get(e)) + { + _finish_thumb_generation(_plugin, EINA_TRUE); + return EINA_FALSE; + } + else + { + _plugin->pcount++; + _video_pos_set(_plugin); + return EINA_TRUE; + } + } + + _plugin->tmp_time = p - _plugin->pi; + + if (_plugin->ef) + { + Ecore_Evas *ee = ethumb_ecore_evas_get(e); + int quality, compress; + + quality = ethumb_thumb_quality_get(e); + compress = ethumb_thumb_compress_get(e); + + pixels = ecore_evas_buffer_pixels_get(ee); + snprintf(buf, sizeof(buf), "images/%d", _plugin->frnum); + eet_data_image_write(_plugin->ef, buf, pixels, _plugin->w, _plugin->h, + 0, compress, quality, quality); + _plugin->frnum++; + } + + return EINA_TRUE; +} + +static void +_generate_animated_thumb(struct _emotion_plugin *_plugin) +{ + const char *thumb_path; + char *thumb_dir; + char buf[4096]; + Ethumb *e = _plugin->e; + + snprintf(buf, sizeof(buf), "%s/data/emotion_template.edj", PLUGINSDIR); + ethumb_thumb_path_get(e, &thumb_path, NULL); + thumb_dir = ecore_file_dir_get(thumb_path); + ecore_file_mkpath(thumb_dir); + free(thumb_dir); + ecore_file_cp(buf, thumb_path); + _plugin->ef = eet_open(thumb_path, EET_FILE_MODE_READ_WRITE); + if (!_plugin->ef) + { + fprintf(stderr, "ERROR: could not open '%s'\n", thumb_path); + _finish_thumb_generation(_plugin, 0); + } + + ecore_timer_add(1.0 / ethumb_video_fps_get(e), _frame_grab, _plugin); } static void @@ -38,7 +287,9 @@ _generate_thumb(Ethumb *e) Evas_Object *o; int r; const char *file; - float time; + float start; + Ethumb_Thumb_Format f; + struct _emotion_plugin *_plugin = calloc(sizeof(struct _emotion_plugin), 1); o = emotion_object_add(ethumb_evas_get(e)); r = emotion_object_init(o, "xine"); @@ -48,28 +299,48 @@ _generate_thumb(Ethumb *e) " plugin.\n"); evas_object_del(o); ethumb_finished_callback_call(e, 0); + free(_plugin); return; } + _plugin->video = o; + ethumb_file_get(e, &file, NULL); - time = ethumb_video_time_get(e); + start = ethumb_video_start_get(e); + f = ethumb_thumb_format_get(e); emotion_object_file_set(o, file); - emotion_object_position_set(o, time); + + _plugin->video = o; + _plugin->e = e; + + _plugin->ptotal = ethumb_video_time_get(e) / ethumb_video_ntimes_get(e); + _plugin->pcount = 1; + + _resize_movie(_plugin); + evas_object_smart_callback_add(o, "frame_resize", + _frame_resized_cb, _plugin); + evas_object_smart_callback_add(o, "decode_stop", + _video_stopped_cb, _plugin); + + if (f == ETHUMB_THUMB_EET) + { + _generate_animated_thumb(_plugin); + } + else + { + ecore_timer_add(0.1, _frame_grab_single, _plugin); + } + + _video_pos_set(_plugin); emotion_object_play_set(o, 1); - - evas_object_smart_callback_add(o, "frame_resize", _frame_resized_cb, e); - evas_object_show(o); - - _emotion = o; - } EAPI Ethumb_Plugin * ethumb_plugin_get(void) { - static const char *extensions[] = { "avi", NULL }; + static const char *extensions[] = { "avi", "mp4", "ogv", NULL }; static Ethumb_Plugin plugin = { extensions, diff --git a/legacy/ethumb/src/plugins/emotion/template.edc b/legacy/ethumb/src/plugins/emotion/template.edc new file mode 100644 index 0000000000..2985b29180 --- /dev/null +++ b/legacy/ethumb/src/plugins/emotion/template.edc @@ -0,0 +1,40 @@ +collections { + + group { + name: "movie/thumb"; + + parts { + part { + name: "image"; + type: IMAGE; + description { + state: "default" 0.0; + } + } + } + + programs { + program { + name: "animate"; + signal: "animate"; + action: STATE_SET "default" 0.0; + transition: LINEAR 3.0; + target: "image"; + } + program { + name: "animate_loop"; + signal: "animate_loop"; + action: STATE_SET "default" 0.0; + transition: LINEAR 3.0; + target: "image"; + after: "animate_loop"; + } + program { + name: "animate_stop"; + signal: "animate_stop"; + action: ACTION_STOP; + target: "animate_loop"; + } + } + } +}