fprintf(stderr, "playing next file: %s\n", file);
emotion_object_file_set(em, file);
}
+ else if (!strcmp(ev->keyname, "b"))
+ {
+ emotion_object_border_set(em, 0, 0, 50, 50);
+ }
+ else if (!strcmp(ev->keyname, "0"))
+ {
+ emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_NONE);
+ }
+ else if (!strcmp(ev->keyname, "w"))
+ {
+ emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_WIDTH);
+ }
+ else if (!strcmp(ev->keyname, "h"))
+ {
+ emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_HEIGHT);
+ }
+ else if (!strcmp(ev->keyname, "2"))
+ {
+ emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH);
+ }
+ else if (!strcmp(ev->keyname, "c"))
+ {
+ emotion_object_keep_aspect_set(em, EMOTION_ASPECT_CROP);
+ }
else
{
fprintf(stderr, "unhandled key: %s\n", ev->keyname);
evas_object_move(em, 10, 10);
evas_object_resize(em, WIDTH, HEIGHT);
evas_object_resize(em, WIDTH - 20, HEIGHT - 20);
- emotion_object_border_set(em, 0, 0, 50, 50);
+ emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH);
emotion_object_bg_color_set(em, 0, 128, 0, 255);
evas_object_show(em);
EMOTION_HIBERNATE
} Emotion_Suspend;
+enum _Emotion_Aspect
+{
+ EMOTION_ASPECT_KEEP_NONE, /**< ignore video aspect ratio */
+ EMOTION_ASPECT_KEEP_WIDTH, /**< respect video aspect, fitting its width inside the object width */
+ EMOTION_ASPECT_KEEP_HEIGHT, /**< respect video aspect, fitting its height inside the object height */
+ EMOTION_ASPECT_KEEP_BOTH, /**< respect video aspect, fitting it inside the object area */
+ EMOTION_ASPECT_CROP, /**< respect video aspect, cropping exceding area */
+ EMOTION_ASPECT_CUSTOM, /**< use custom borders/crop for the video */
+};
+
typedef enum _Emotion_Module Emotion_Module;
typedef enum _Emotion_Event Emotion_Event;
typedef enum _Emotion_Meta_Info Emotion_Meta_Info; /**< Meta info type to be retrieved. */
typedef enum _Emotion_Vis Emotion_Vis; /**< Type of visualization. */
+typedef enum _Emotion_Aspect Emotion_Aspect; /**< Aspect ratio option. */
#define EMOTION_CHANNEL_AUTO -1
#define EMOTION_CHANNEL_DEFAULT 0
EAPI void emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a);
/**
+ * @brief Set whether emotion should keep the aspect ratio of the video.
+ *
+ * @param obj The emotion object where to set the aspect.
+ * @param a The aspect ratio policy.
+ *
+ * Instead of manually calculating the required border to set with
+ * emotion_object_border_set(), and using this to fix the aspect ratio of the
+ * video when the emotion object has a different aspect, it's possible to just
+ * set the policy to be used.
+ *
+ * The options are:
+ *
+ * - @b #EMOTION_ASPECT_KEEP_NONE - ignore the video aspect ratio, and reset any
+ * border set to 0, stretching the video inside the emotion object area. This
+ * option is similar to EVAS_ASPECT_CONTROL_NONE size hint.
+ * - @b #EMOTION_ASPECT_KEEP_WIDTH - respect the video aspect ratio, fitting the
+ * video width inside the object width. This option is similar to
+ * EVAS_ASPECT_CONTROL_HORIZONTAL size hint.
+ * - @b #EMOTION_ASPECT_KEEP_HEIGHT - respect the video aspect ratio, fitting
+ * the video height inside the object height. This option is similar to
+ * EVAS_ASPECT_CONTROL_VERTIAL size hint.
+ * - @b #EMOTION_ASPECT_KEEP_BOTH - respect the video aspect ratio, fitting both
+ * its width and height inside the object area. This option is similar to
+ * EVAS_ASPECT_CONTROL_BOTH size hint. It's the effect called letterboxing.
+ * - @b #EMOTION_ASPECT_CROP - respect the video aspect ratio, fitting the width
+ * or height inside the object area, and cropping the exceding areas of the
+ * video in height or width. It's the effect called pan-and-scan.
+ * - @b #EMOTION_ASPECT_CUSTOM - ignore the video aspect ratio, and use the
+ * current set from emotion_object_border_set().
+ *
+ * @note Calling this function with any value except #EMOTION_ASPECT_CUSTOM will
+ * invalidate borders set with emotion_object_border_set().
+ *
+ * @note Calling emotion_object_border_set() will automatically set the aspect
+ * policy to #EMOTION_ASPECT_CUSTOM.
+ *
+ * @see emotion_object_border_set()
+ * @see emotion_object_keep_aspect_get()
+ */
+EAPI void emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a);
+
+/**
+ * @brief Get the current emotion aspect ratio policy.
+ *
+ * @param obj The emotion object from which we are fetching the aspect ratio
+ * policy.
+ * @return The current aspect ratio policy.
+ *
+ * @see emotion_object_keep_aspect_set()
+ */
+EAPI Emotion_Aspect emotion_object_keep_aspect_get(const Evas_Object *obj);
+
+/**
* @brief Set the file to be played in the Emotion object.
*
* @param obj The emotion object where the file is being loaded.
Emotion_Module_Options module_options;
Emotion_Suspend state;
+ Emotion_Aspect aspect;
Eina_Bool open : 1;
Eina_Bool play : 1;
}
static void
-_clipper_position_size_update(Evas_Object *obj, int vid_w, int vid_h)
+_clipper_position_size_update(Evas_Object *obj, int w, int h, 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_geometry_get(obj, &x, &y, NULL, NULL);
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);
return sd->file;
}
-EAPI void
-emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b)
+static void
+_emotion_aspect_borders_apply(Evas_Object *obj, Smart_Data *sd, int w, int h, int iw, int ih)
{
- 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)
+ /* applying calculated borders */
+ if (sd->crop.l == 0 && sd->crop.r == 0 &&
+ sd->crop.t == 0 && sd->crop.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;
+ if (sd->crop.clipper)
+ {
+ 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;
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);
}
+ _clipper_position_size_update(obj, w, h, iw, ih);
+}
+
+static void
+_emotion_object_aspect_border_apply(Evas_Object *obj, Smart_Data *sd, int w, int h)
+{
+ int iw, ih;
+ double ir;
+ double r;
+
+ int aspect_opt;
+ sd->module->video_data_size_get(sd->video, &iw, &ih);
+
+ ir = (double)iw / ih;
+ r = (double)w / h;
+
+ /* First check if we should fit the width or height of the video inside the
+ * width/height of the object. This check takes into account the original
+ * aspect ratio and the object aspect ratio, if we are keeping both sizes or
+ * cropping the exceding area.
+ */
+ if (sd->aspect == EMOTION_ASPECT_KEEP_NONE)
+ {
+ sd->crop.l = 0;
+ sd->crop.r = 0;
+ sd->crop.t = 0;
+ sd->crop.b = 0;
+ aspect_opt = 0; // just ignore keep_aspect
+ }
+ else if (sd->aspect == EMOTION_ASPECT_KEEP_WIDTH)
+ {
+ aspect_opt = 1;
+ }
+ else if (sd->aspect == EMOTION_ASPECT_KEEP_HEIGHT)
+ {
+ aspect_opt = 2;
+ }
+ else if (sd->aspect == EMOTION_ASPECT_KEEP_BOTH)
+ {
+ if (ir > r)
+ aspect_opt = 1;
+ else
+ aspect_opt = 2;
+ }
+ else if (sd->aspect == EMOTION_ASPECT_CROP)
+ {
+ if (ir > r)
+ aspect_opt = 2;
+ else
+ aspect_opt = 1;
+ }
+ else if (sd->aspect == EMOTION_ASPECT_CUSTOM)
+ {
+ // nothing to do, just respect the border settings
+ aspect_opt = 0;
+ }
+
+ /* updating borders based on keep_aspect settings */
+ if (aspect_opt == 1) // keep width
+ {
+ int th, dh;
+ double scale;
+
+ sd->crop.l = 0;
+ sd->crop.r = 0;
+ scale = (double)iw / w;
+ th = h * scale;
+ dh = ih - th;
+ sd->crop.t = sd->crop.b = dh / 2;
+ }
+ else if (aspect_opt == 2) // keep height
+ {
+ int tw, dw;
+ double scale;
+
+ sd->crop.t = 0;
+ sd->crop.b = 0;
+ scale = (double)ih / h;
+ tw = w * scale;
+ dw = iw - tw;
+ sd->crop.l = sd->crop.r = dw / 2;
+ }
+
+ _emotion_aspect_borders_apply(obj, sd, w, h, iw, ih);
+}
+
+EAPI void
+emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b)
+{
+ Smart_Data *sd;
+ int w, h;
+
+ E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+
+ sd->aspect = EMOTION_ASPECT_CUSTOM;
+ sd->crop.l = -l;
+ sd->crop.r = -r;
+ sd->crop.t = -t;
+ sd->crop.b = -b;
+ evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+ _emotion_object_aspect_border_apply(obj, sd, w, h);
}
EAPI void
}
EAPI void
+emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a)
+{
+ Smart_Data *sd;
+ int w, h;
+
+ E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
+
+ if (a == sd->aspect)
+ return;
+
+ sd->aspect = a;
+ evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+ _emotion_object_aspect_border_apply(obj, sd, w, h);
+}
+
+EAPI Emotion_Aspect
+emotion_object_keep_aspect_get(const Evas_Object *obj)
+{
+ Smart_Data *sd;
+
+ E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_ASPECT_KEEP_NONE);
+
+ return sd->aspect;
+}
+
+EAPI void
emotion_object_play_set(Evas_Object *obj, Eina_Bool play)
{
Smart_Data *sd;
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
{
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);
+ evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+ _emotion_object_aspect_border_apply(obj, sd, w, h);
}
}
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);
+ evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+ _clipper_position_size_update(obj, w, h, vid_w, vid_h);
evas_object_move(sd->bg, x, y);
}
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);
+ fprintf(stderr, "smart resize: %dx%d\n", w, h);
+ _emotion_object_aspect_border_apply(obj, sd, w, h);
evas_object_resize(sd->bg, w, h);
}