this allows video files to be played for wapapers - they loop and run indefinitely. it is a special video object that shares the same source across all outputs, so if you have the same video set, on 2 screens (or desktops) then it's only decoded once and uses proxies to ducplicate. this works in the pager too (it uses proxies). this is for amusement and fun and ... because we can. :)devs/captainigloo/eglfs_rpi
parent
26a7ba3a58
commit
be1b11ca28
7 changed files with 490 additions and 32 deletions
@ -0,0 +1,353 @@ |
||||
#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; |
||||
} |
@ -0,0 +1,10 @@ |
||||
#ifdef E_TYPEDEFS |
||||
#else |
||||
# ifndef E_VIDEO_H |
||||
# define E_VIDEO_H |
||||
|
||||
E_API Evas_Object *e_video_add(Evas_Object *parent, const char *file, Eina_Bool lowq); |
||||
E_API const char *e_video_file_get(Evas_Object *obj); |
||||
|
||||
# endif |
||||
#endif |
Loading…
Reference in new issue