#include "e.h" typedef struct _Video Video; struct _Video { Evas_Object_Smart_Clipped_Data __clipped_data; Evas_Object *clip, *o_vid; Eina_Bool lowqual : 1; }; typedef struct _Vidimg Vidimg; struct _Vidimg { Evas_Object *obj; Eina_List *copies; int iw, ih, piw, pih; Ecore_Job *restart_job; Ecore_Event_Handler *offhandler; Ecore_Event_Handler *onhandler; Ecore_Timer *offtimer; }; static Evas_Smart *_smart = NULL; static Evas_Smart_Class _parent_sc = EVAS_SMART_CLASS_INIT_NULL; static Eina_List *vidimgs = NULL; static void _ob_resize(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h); static void _cb_vid_frame(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Vidimg *vi = data; Eina_List *l; Evas_Object *o, *oimg; EINA_LIST_FOREACH(vi->copies, l, o) { Evas_Coord ox, oy, ow, oh; Video *sd; obj = evas_object_data_get(o, "obj"); oimg = emotion_object_image_get(vi->obj); evas_object_image_source_set(o, oimg); evas_object_image_source_clip_set(o, EINA_FALSE); evas_object_image_source_visible_set(o, EINA_FALSE); sd = evas_object_smart_data_get(obj); evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); evas_object_show(sd->o_vid); evas_object_show(sd->clip); _ob_resize(obj, ox, oy, ow, oh); } } static void _cb_vid_resize(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Vidimg *vi = data; Eina_List *l; Evas_Object *o; EINA_LIST_FOREACH(vi->copies, l, o) { Evas_Coord ox, oy, ow, oh; obj = evas_object_data_get(o, "obj"); evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); _ob_resize(obj, ox, oy, ow, oh); } } static void _cb_restart(void *data) { Vidimg *vi = data; vi->restart_job = NULL; emotion_object_position_set(vi->obj, 0.0); emotion_object_play_set(vi->obj, EINA_TRUE); } static void _cb_vid_stop(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Vidimg *vi = data; if (vi->restart_job) ecore_job_del(vi->restart_job); vi->restart_job = ecore_job_add(_cb_restart, vi); } static Eina_Bool vidimg_cb_suspend(void *data) { Vidimg *vi = data; vi->offtimer = NULL; emotion_object_play_set(vi->obj, EINA_FALSE); return EINA_FALSE; } static Eina_Bool vidimg_cb_screensaver_off(void *data, int type EINA_UNUSED, void *event EINA_UNUSED) { Vidimg *vi = data; if (vi->offtimer) { ecore_timer_del(vi->offtimer); vi->offtimer = NULL; } else { emotion_object_play_set(vi->obj, EINA_TRUE); } return ECORE_CALLBACK_PASS_ON; } static Eina_Bool vidimg_cb_screensaver_on(void *data, int type EINA_UNUSED, void *event EINA_UNUSED) { Vidimg *vi = data; if (vi->offtimer) ecore_timer_del(vi->offtimer); vi->offtimer = ecore_timer_add(10.0, vidimg_cb_suspend, vi); return ECORE_CALLBACK_PASS_ON; } static Evas_Object * vidimg_find(Evas_Object *obj, const char *file) { Eina_List *l; Evas_Object *o, *oimg, *oproxy; EINA_LIST_FOREACH(vidimgs, l, o) { if (evas_object_evas_get(o) == evas_object_evas_get(obj)) { const char *f = emotion_object_file_get(o); if ((f) && (file) && (!strcmp(f, file))) { Vidimg *vi = evas_object_data_get(o, "vidimg"); oproxy = evas_object_image_filled_add(evas_object_evas_get(obj)); evas_object_data_set(oproxy, "source", o); oimg = emotion_object_image_get(o); evas_object_image_source_set(oproxy, oimg); evas_object_image_source_clip_set(oproxy, EINA_FALSE); evas_object_image_source_visible_set(oproxy, EINA_FALSE); vi->copies = eina_list_append(vi->copies, oproxy); evas_object_data_set(oproxy, "obj", obj); return oproxy; } } } return NULL; } static Evas_Object * vidimg_video_add(Evas_Object *obj, const char *file) { Evas_Object *o; Vidimg *vi; emotion_init(); o = emotion_object_add(evas_object_evas_get(obj)); if (!emotion_object_init(o, "gstreamer1")) { evas_object_del(o); return NULL; } vi = calloc(1, sizeof(Vidimg)); vi->obj = o; vi->offhandler = ecore_event_handler_add(E_EVENT_SCREENSAVER_OFF, vidimg_cb_screensaver_off, vi); vi->onhandler = ecore_event_handler_add(E_EVENT_SCREENSAVER_ON, vidimg_cb_screensaver_on, vi); evas_object_data_set(o, "vidimg", vi); evas_object_smart_callback_add(o, "frame_decode", _cb_vid_frame, vi); evas_object_smart_callback_add(o, "frame_resize", _cb_vid_resize, vi); evas_object_smart_callback_add(o, "decode_stop", _cb_vid_stop, vi); emotion_object_file_set(o, file); emotion_object_audio_mute_set(o, EINA_TRUE); emotion_object_keep_aspect_set(o, EMOTION_ASPECT_KEEP_NONE); emotion_object_play_set(o, EINA_TRUE); evas_object_pass_events_set(o, EINA_TRUE); evas_object_move(o, -999, -999); evas_object_resize(o, 9, 0); evas_object_show(o); vidimgs = eina_list_append(vidimgs, o); return o; } static void vidimg_release(Evas_Object *o) { Vidimg *vi; Evas_Object *src = evas_object_data_get(o, "source"); if (!src) return; vi = evas_object_data_get(src, "vidimg"); vi->copies = eina_list_remove(vi->copies, o); if (!vi->copies) { vidimgs = eina_list_remove(vidimgs, src); evas_object_data_del(src, "vidimg"); if (vi->restart_job) ecore_job_del(vi->restart_job); ecore_event_handler_del(vi->offhandler); ecore_event_handler_del(vi->onhandler); if (vi->offtimer) ecore_timer_del(vi->offtimer); free(vi); evas_object_del(src); emotion_shutdown(); } } static void _ob_resize(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) { Video *sd = evas_object_smart_data_get(obj); if (!sd) return; evas_object_move(sd->o_vid, x, y); evas_object_resize(sd->o_vid, w, h); } static void _smart_calculate(Evas_Object *obj); static void _smart_add(Evas_Object *obj) { Video *sd; Evas_Object *o; sd = calloc(1, sizeof(Video)); EINA_SAFETY_ON_NULL_RETURN(sd); evas_object_smart_data_set(obj, sd); _parent_sc.add(obj); o = evas_object_rectangle_add(evas_object_evas_get(obj)); evas_object_smart_member_add(o, obj); sd->clip = o; evas_object_color_set(o, 255, 255, 255, 255); } static void _smart_del(Evas_Object *obj) { Video *sd = evas_object_smart_data_get(obj); if (!sd) return; if (sd->clip) evas_object_del(sd->clip); vidimg_release(sd->o_vid); _parent_sc.del(obj); } static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) { Video *sd = evas_object_smart_data_get(obj); Evas_Coord ox, oy, ow, oh; if (!sd) return; evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); if ((ow == w) && (oh == h)) return; evas_object_smart_changed(obj); evas_object_resize(sd->clip, ow, oh); } static void _smart_calculate(Evas_Object *obj) { Video *sd = evas_object_smart_data_get(obj); Evas_Coord ox, oy, ow, oh; if (!sd) return; evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); _ob_resize(obj, ox, oy, ow, oh); evas_object_move(sd->clip, ox, oy); evas_object_resize(sd->clip, ow, oh); } static void _smart_move(Evas_Object *obj, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED) { Video *sd = evas_object_smart_data_get(obj); if (!sd) return; evas_object_smart_changed(obj); } static void _smart_init(void) { static Evas_Smart_Class sc; evas_object_smart_clipped_smart_set(&_parent_sc); sc = _parent_sc; sc.name = "video"; sc.version = EVAS_SMART_CLASS_VERSION; sc.add = _smart_add; sc.del = _smart_del; sc.resize = _smart_resize; sc.move = _smart_move; sc.calculate = _smart_calculate; _smart = evas_smart_class_new(&sc); } E_API Evas_Object * e_video_add(Evas_Object *parent, const char *file, Eina_Bool lowq) { Evas *e; Evas_Object *obj, *o; Video *sd; EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); e = evas_object_evas_get(parent); if (!e) return NULL; if (!_smart) _smart_init(); obj = evas_object_smart_add(e, _smart); sd = evas_object_smart_data_get(obj); if (!sd) return obj; sd->lowqual = lowq; o = sd->o_vid = vidimg_find(obj, file); if (!o) { o = vidimg_video_add(obj, file); if (!o) return obj; o = sd->o_vid = vidimg_find(obj, file); if (!o) return obj; } evas_object_smart_member_add(o, obj); evas_object_clip_set(o, sd->clip); evas_object_image_smooth_scale_set(o, !sd->lowqual); return obj; } E_API const char * e_video_file_get(Evas_Object *obj) { Video *sd; Evas_Object *src; if (evas_object_smart_smart_get(obj) != _smart) return NULL; if (!(sd = evas_object_smart_data_get(obj))) return NULL; src = evas_object_data_get(sd->o_vid, "source"); if (src) return emotion_object_file_get(src); return NULL; }