forked from enlightenment/efl
emotion/border: Add border/crop support for emotion objects.
The emotion_object_border_set/get APIs were added, allowing one to specify a positive (border) or negative (crop) value for each of the edjes of the video being played. This allows easier setup on an Emotion object to keep the aspect ratio, either by adding black areas on it, or by cropping the exceding area of the video. NOTE: The specified border/crop is based on the original size of the video. If it is scaled (emotion object size is different from the video size), the borders will be scaled as well. Patch based on an original patch sent by Hugo Camboulive <hugo.camboulive@gmail.com>. SVN revision: 63414
This commit is contained in:
parent
64f3a6da0f
commit
77f43424a6
|
@ -17,6 +17,7 @@ LDADD = \
|
|||
SRCS = \
|
||||
emotion_basic_example.c \
|
||||
emotion_generic_example.c \
|
||||
emotion_border_example.c \
|
||||
emotion_signals_example.c
|
||||
|
||||
EXTRA_DIST = $(SRCS)
|
||||
|
@ -32,6 +33,7 @@ if EFL_BUILD_EXAMPLES
|
|||
pkglib_PROGRAMS += \
|
||||
emotion_basic_example \
|
||||
emotion_generic_example \
|
||||
emotion_border_example \
|
||||
emotion_signals_example
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
#include <Ecore.h>
|
||||
#include <Ecore_Evas.h>
|
||||
#include <Evas.h>
|
||||
#include <Emotion.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define WIDTH (320)
|
||||
#define HEIGHT (240)
|
||||
|
||||
static Eina_List *filenames = NULL;
|
||||
static Eina_List *curfile = NULL;
|
||||
|
||||
static void
|
||||
_playback_started_cb(void *data, Evas_Object *o, void *event_info)
|
||||
{
|
||||
printf("Emotion object started playback.\n");
|
||||
}
|
||||
|
||||
static Evas_Object *
|
||||
_create_emotion_object(Evas *e)
|
||||
{
|
||||
Evas_Object *em = emotion_object_add(e);
|
||||
|
||||
emotion_object_init(em, "gstreamer");
|
||||
|
||||
evas_object_smart_callback_add(
|
||||
em, "playback_started", _playback_started_cb, NULL);
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
static void
|
||||
_on_key_down(void *data, Evas *e, Evas_Object *o, void *event_info)
|
||||
{
|
||||
Evas_Event_Key_Down *ev = event_info;
|
||||
Evas_Object *em = data;
|
||||
|
||||
if (!strcmp(ev->keyname, "Return"))
|
||||
{
|
||||
emotion_object_play_set(em, EINA_TRUE);
|
||||
}
|
||||
else if (!strcmp(ev->keyname, "space"))
|
||||
{
|
||||
emotion_object_play_set(em, EINA_FALSE);
|
||||
}
|
||||
else if (!strcmp(ev->keyname, "Escape"))
|
||||
{
|
||||
ecore_main_loop_quit();
|
||||
}
|
||||
else if (!strcmp(ev->keyname, "n"))
|
||||
{
|
||||
const char *file;
|
||||
if (!curfile)
|
||||
curfile = filenames;
|
||||
else
|
||||
curfile = eina_list_next(curfile);
|
||||
file = eina_list_data_get(curfile);
|
||||
fprintf(stderr, "playing next file: %s\n", file);
|
||||
emotion_object_file_set(em, file);
|
||||
}
|
||||
else if (!strcmp(ev->keyname, "p"))
|
||||
{
|
||||
const char *file;
|
||||
if (!curfile)
|
||||
curfile = eina_list_last(filenames);
|
||||
else
|
||||
curfile = eina_list_prev(curfile);
|
||||
file = eina_list_data_get(curfile);
|
||||
fprintf(stderr, "playing next file: %s\n", file);
|
||||
emotion_object_file_set(em, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "unhandled key: %s\n", ev->keyname);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_frame_decode_cb(void *data, Evas_Object *o, void *event_info)
|
||||
{
|
||||
// fprintf(stderr, "smartcb: frame_decode\n");
|
||||
}
|
||||
|
||||
static void
|
||||
_length_change_cb(void *data, Evas_Object *o, void *event_info)
|
||||
{
|
||||
fprintf(stderr, "smartcb: length_change: %0.3f\n", emotion_object_play_length_get(o));
|
||||
}
|
||||
|
||||
static void
|
||||
_position_update_cb(void *data, Evas_Object *o, void *event_info)
|
||||
{
|
||||
fprintf(stderr, "smartcb: position_update: %0.3f\n", emotion_object_position_get(o));
|
||||
}
|
||||
|
||||
static void
|
||||
_progress_change_cb(void *data, Evas_Object *o, void *event_info)
|
||||
{
|
||||
fprintf(stderr, "smartcb: progress_change: %0.3f, %s\n",
|
||||
emotion_object_progress_status_get(o),
|
||||
emotion_object_progress_info_get(o));
|
||||
}
|
||||
|
||||
static void
|
||||
_frame_resize_cb(void *data, Evas_Object *o, void *event_info)
|
||||
{
|
||||
int w, h;
|
||||
emotion_object_size_get(o, &w, &h);
|
||||
fprintf(stderr, "smartcb: frame_resize: %dx%d\n", w, h);
|
||||
}
|
||||
|
||||
static void /* adjust canvas' contents on resizes */
|
||||
_canvas_resize_cb(Ecore_Evas *ee)
|
||||
{
|
||||
int w, h;
|
||||
Evas_Object *bg, *em;
|
||||
|
||||
ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
|
||||
|
||||
bg = ecore_evas_data_get(ee, "bg");
|
||||
em = ecore_evas_data_get(ee, "emotion");
|
||||
|
||||
evas_object_resize(bg, w, h);
|
||||
evas_object_resize(em, w, h);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
int err;
|
||||
Ecore_Evas *ee;
|
||||
Evas *e;
|
||||
Evas_Object *bg, *em;
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("One argument is necessary. Usage:\n");
|
||||
printf("\t%s <filename>\n", argv[0]);
|
||||
}
|
||||
|
||||
eina_init();
|
||||
for (i = 1; i < argc; i++)
|
||||
filenames = eina_list_append(filenames, eina_stringshare_add(argv[i]));
|
||||
|
||||
curfile = filenames;
|
||||
|
||||
if (!ecore_evas_init())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
/* this will give you a window with an Evas canvas under the first
|
||||
* engine available */
|
||||
ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
|
||||
if (!ee)
|
||||
goto error;
|
||||
|
||||
ecore_evas_callback_resize_set(ee, _canvas_resize_cb);
|
||||
|
||||
ecore_evas_show(ee);
|
||||
|
||||
/* the canvas pointer, de facto */
|
||||
e = ecore_evas_get(ee);
|
||||
|
||||
/* adding a background to this example */
|
||||
bg = evas_object_rectangle_add(e);
|
||||
evas_object_name_set(bg, "our dear rectangle");
|
||||
evas_object_color_set(bg, 255, 0, 0, 255); /* white bg */
|
||||
evas_object_move(bg, 0, 0); /* at canvas' origin */
|
||||
evas_object_resize(bg, WIDTH, HEIGHT); /* covers full canvas */
|
||||
evas_object_show(bg);
|
||||
|
||||
ecore_evas_data_set(ee, "bg", bg);
|
||||
|
||||
/* Creating the emotion object */
|
||||
em = _create_emotion_object(e);
|
||||
emotion_object_file_set(em, eina_list_data_get(curfile));
|
||||
evas_object_move(em, 0, 0);
|
||||
evas_object_resize(em, WIDTH, HEIGHT);
|
||||
emotion_object_border_set(em, -30, -30, -30, -30);
|
||||
evas_object_show(em);
|
||||
|
||||
ecore_evas_data_set(ee, "emotion", em);
|
||||
|
||||
evas_object_smart_callback_add(em, "frame_decode", _frame_decode_cb, NULL);
|
||||
evas_object_smart_callback_add(em, "length_change", _length_change_cb, NULL);
|
||||
evas_object_smart_callback_add(em, "position_update", _position_update_cb, NULL);
|
||||
evas_object_smart_callback_add(em, "progress_change", _progress_change_cb, NULL);
|
||||
evas_object_smart_callback_add(em, "frame_resize", _frame_resize_cb, NULL);
|
||||
|
||||
evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_key_down, em);
|
||||
evas_object_focus_set(bg, EINA_TRUE);
|
||||
|
||||
emotion_object_play_set(em, EINA_TRUE);
|
||||
|
||||
ecore_main_loop_begin();
|
||||
|
||||
ecore_evas_free(ee);
|
||||
ecore_evas_shutdown();
|
||||
return 0;
|
||||
|
||||
error:
|
||||
fprintf(stderr, "you got to have at least one evas engine built and linked"
|
||||
" up to ecore-evas for this example to run properly.\n");
|
||||
|
||||
EINA_LIST_FREE(filenames, curfile)
|
||||
eina_stringshare_del(eina_list_data_get(curfile));
|
||||
|
||||
ecore_evas_shutdown();
|
||||
eina_shutdown();
|
||||
return -1;
|
||||
}
|
|
@ -375,6 +375,47 @@ EAPI void emotion_object_module_option_set (Evas_Object *obj, const
|
|||
*/
|
||||
EAPI Eina_Bool emotion_object_init (Evas_Object *obj, const char *module_filename);
|
||||
|
||||
/**
|
||||
* @brief Set borders for the emotion object.
|
||||
*
|
||||
* @param obj The emotion object where borders are being set.
|
||||
* @param l The left border.
|
||||
* @param r The right border.
|
||||
* @param t The top border.
|
||||
* @param b The bottom border.
|
||||
*
|
||||
* This function sets borders for the emotion video object (just when a video is
|
||||
* present). When positive values are given to one of the parameters, a border
|
||||
* will be added to the respective position of the object, representing that
|
||||
* size on the original video size. However, if the video is scaled up or down
|
||||
* (i.e. the emotion object size is different from the video size), the borders
|
||||
* will be scaled respectively too.
|
||||
*
|
||||
* If a negative value is given to one of the parameters, instead of a border,
|
||||
* that respective side of the video will be cropped.
|
||||
*
|
||||
* It's possible to set a color for the added borders (default is transparent)
|
||||
* with emotion_object_border_color_set(). By default, an Emotion object doesn't
|
||||
* have any border.
|
||||
*
|
||||
* @see emotion_object_border_get()
|
||||
* @see emotion_object_border_color_set()
|
||||
*/
|
||||
EAPI void emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b);
|
||||
|
||||
/**
|
||||
* @brief Get the borders set for the emotion object.
|
||||
*
|
||||
* @param obj The emotion object from which the borders are being retrieved.
|
||||
* @param l The left border.
|
||||
* @param r The right border.
|
||||
* @param t The top border.
|
||||
* @param b The bottom border.
|
||||
*
|
||||
* @see emotion_object_border_set()
|
||||
*/
|
||||
EAPI void emotion_object_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b);
|
||||
|
||||
/**
|
||||
* @brief Set the file to be played in the Emotion object.
|
||||
*
|
||||
|
|
|
@ -76,6 +76,13 @@ struct _Smart_Data
|
|||
int button_num;
|
||||
int button;
|
||||
} spu;
|
||||
struct {
|
||||
int l; /* left */
|
||||
int r; /* right */
|
||||
int t; /* top */
|
||||
int b; /* bottom */
|
||||
Evas_Object *clipper;
|
||||
} crop;
|
||||
|
||||
double ratio;
|
||||
double pos;
|
||||
|
@ -200,6 +207,7 @@ _smart_data_free(Smart_Data *sd)
|
|||
if (sd->video) sd->module->file_close(sd->video);
|
||||
_emotion_module_close(sd->module, sd->video);
|
||||
evas_object_del(sd->obj);
|
||||
evas_object_del(sd->crop.clipper);
|
||||
eina_stringshare_del(sd->file);
|
||||
free(sd->module_name);
|
||||
if (sd->job) ecore_job_del(sd->job);
|
||||
|
@ -279,6 +287,27 @@ _emotion_module_open(const char *name, Evas_Object *obj, Emotion_Video_Module **
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_clipper_position_size_update(Evas_Object *obj, int vid_w, int vid_h)
|
||||
{
|
||||
Smart_Data *sd;
|
||||
double scale_w, scale_h;
|
||||
int x, y;
|
||||
int w, h;
|
||||
|
||||
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
|
||||
|
||||
evas_object_geometry_get(obj, &x, &y, &w, &h);
|
||||
evas_object_move(sd->crop.clipper, x, y);
|
||||
scale_w = (double)w / (double)(vid_w - sd->crop.l - sd->crop.r);
|
||||
scale_h = (double)h / (double)(vid_h - sd->crop.t - sd->crop.b);
|
||||
|
||||
evas_object_image_fill_set(sd->obj, 0, 0, vid_w * scale_w, vid_h * scale_h);
|
||||
evas_object_resize(sd->obj, vid_w * scale_w, vid_h * scale_h);
|
||||
evas_object_move(sd->obj, x - sd->crop.l * scale_w, y - sd->crop.t * scale_h);
|
||||
evas_object_resize(sd->crop.clipper, w, h);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/* Externally accessible calls */
|
||||
/*******************************/
|
||||
|
@ -420,6 +449,60 @@ emotion_object_file_get(const Evas_Object *obj)
|
|||
return sd->file;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b)
|
||||
{
|
||||
Smart_Data *sd;
|
||||
|
||||
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
|
||||
sd->crop.l = -l;
|
||||
sd->crop.r = -r;
|
||||
sd->crop.t = -t;
|
||||
sd->crop.b = -b;
|
||||
if (l == 0 && r == 0 && t == 0 && b == 0)
|
||||
{
|
||||
Evas_Object *old_clipper;
|
||||
if (!sd->crop.clipper)
|
||||
return;
|
||||
old_clipper = evas_object_clip_get(sd->crop.clipper);
|
||||
evas_object_clip_unset(sd->obj);
|
||||
evas_object_clip_set(sd->obj, old_clipper);
|
||||
evas_object_del(sd->crop.clipper);
|
||||
sd->crop.clipper = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int vid_w, vid_h;
|
||||
if (!sd->crop.clipper)
|
||||
{
|
||||
Evas_Object *old_clipper;
|
||||
sd->crop.clipper = evas_object_rectangle_add(
|
||||
evas_object_evas_get(obj));
|
||||
evas_object_color_set(sd->crop.clipper, 255, 255, 255, 255);
|
||||
evas_object_smart_member_add(sd->crop.clipper, obj);
|
||||
old_clipper = evas_object_clip_get(sd->obj);
|
||||
evas_object_clip_set(sd->obj, sd->crop.clipper);
|
||||
evas_object_clip_set(sd->crop.clipper, old_clipper);
|
||||
if (evas_object_visible_get(sd->obj))
|
||||
evas_object_show(sd->crop.clipper);
|
||||
}
|
||||
sd->module->video_data_size_get(sd->video, &vid_w, &vid_h);
|
||||
_clipper_position_size_update(obj, vid_w, vid_h);
|
||||
}
|
||||
}
|
||||
|
||||
EAPI void
|
||||
emotion_object_border_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
|
||||
{
|
||||
Smart_Data *sd;
|
||||
|
||||
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
|
||||
*l = -sd->crop.l;
|
||||
*r = -sd->crop.r;
|
||||
*t = -sd->crop.t;
|
||||
*b = -sd->crop.b;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
emotion_object_play_set(Evas_Object *obj, Eina_Bool play)
|
||||
{
|
||||
|
@ -542,6 +625,8 @@ emotion_object_size_get(const Evas_Object *obj, int *iw, int *ih)
|
|||
if (ih) *ih = 0;
|
||||
E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
|
||||
evas_object_image_size_get(sd->obj, iw, ih);
|
||||
*iw -= (sd->crop.l + sd->crop.r);
|
||||
*ih -= (sd->crop.t + sd->crop.b);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
|
@ -1251,6 +1336,7 @@ _emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio)
|
|||
{
|
||||
evas_object_size_hint_request_set(obj, w, h);
|
||||
evas_object_smart_callback_call(obj, SIG_FRAME_RESIZE, NULL);
|
||||
_clipper_position_size_update(obj, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1629,7 +1715,10 @@ _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y)
|
|||
|
||||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_move(sd->obj, x, y);
|
||||
|
||||
int vid_w, vid_h, w, h;
|
||||
sd->module->video_data_size_get(sd->video, &vid_w, &vid_h);
|
||||
_clipper_position_size_update(obj, vid_w, vid_h);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1639,8 +1728,11 @@ _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h)
|
|||
|
||||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_image_fill_set(sd->obj, 0, 0, w, h);
|
||||
evas_object_resize(sd->obj, w, h);
|
||||
|
||||
int vid_w, vid_h;
|
||||
|
||||
sd->module->video_data_size_get(sd->video, &vid_w, &vid_h);
|
||||
_clipper_position_size_update(obj, vid_w, vid_h);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1651,7 +1743,8 @@ _smart_show(Evas_Object * obj)
|
|||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_show(sd->obj);
|
||||
|
||||
if (sd->crop.clipper)
|
||||
evas_object_show(sd->crop.clipper);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1662,6 +1755,8 @@ _smart_hide(Evas_Object * obj)
|
|||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_hide(sd->obj);
|
||||
if (sd->crop.clipper)
|
||||
evas_object_hide(sd->crop.clipper);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1672,6 +1767,7 @@ _smart_color_set(Evas_Object * obj, int r, int g, int b, int a)
|
|||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_color_set(sd->obj, r, g, b, a);
|
||||
evas_object_color_set(sd->crop.clipper, r, g, b, a);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1681,7 +1777,10 @@ _smart_clip_set(Evas_Object * obj, Evas_Object * clip)
|
|||
|
||||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_clip_set(sd->obj, clip);
|
||||
if (sd->crop.clipper)
|
||||
evas_object_clip_set(sd->crop.clipper, clip);
|
||||
else
|
||||
evas_object_clip_set(sd->obj, clip);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1691,6 +1790,9 @@ _smart_clip_unset(Evas_Object * obj)
|
|||
|
||||
sd = evas_object_smart_data_get(obj);
|
||||
if (!sd) return;
|
||||
evas_object_clip_unset(sd->obj);
|
||||
if (sd->crop.clipper)
|
||||
evas_object_clip_unset(sd->crop.clipper);
|
||||
else
|
||||
evas_object_clip_unset(sd->obj);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue