1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4 
5 #define EFL_CANVAS_OBJECT_PROTECTED
6 #define EFL_CANVAS_GROUP_PROTECTED
7 
8 #include <Evas.h>
9 #include <Ecore.h>
10 
11 #ifdef HAVE_EIO
12 # include <math.h>
13 # include <Eio.h>
14 #endif
15 
16 #define EFL_INTERNAL_UNSTABLE
17 #include <Evas_Internal.h>
18 
19 #include "Emotion.h"
20 #include "emotion_private.h"
21 
22 #include "canvas/evas_canvas_eo.h"
23 
24 #ifdef _WIN32
25 # define FMT_UCHAR "%c"
26 #else
27 # define FMT_UCHAR "%hhu"
28 #endif
29 
30 #define E_SMART_OBJ_GET(smart, o, type) \
31      { \
32         if (!o) return; \
33         if (!efl_isa(o, MY_CLASS)) { \
34              ERR("Tried calling on a non-emotion object."); \
35              return; \
36         } \
37         smart = efl_data_scope_get(o, MY_CLASS); \
38         if (!smart) return; \
39      }
40 
41 #define E_SMART_OBJ_GET_RETURN(smart, o, type, ret) \
42    { \
43       if (!o) return ret; \
44       if (!efl_isa(o, MY_CLASS)) { \
45            ERR("Tried calling on a non-emotion object."); \
46            return ret; \
47       } \
48       smart = efl_data_scope_get(o, MY_CLASS); \
49       if (!smart) return ret; \
50    }
51 
52 #define E_OBJ_NAME "efl_canvas_video"
53 
54 #ifdef MY_CLASS
55 # undef MY_CLASS
56 #endif
57 
58 #define MY_CLASS EFL_CANVAS_VIDEO_CLASS
59 
60 typedef struct _Efl_Canvas_Video_Data Efl_Canvas_Video_Data;
61 typedef struct _Emotion_Xattr_Data Emotion_Xattr_Data;
62 
63 struct _Efl_Canvas_Video_Data
64 {
65    Emotion_Engine_Instance *engine_instance;
66 
67    const char    *engine;
68    const char    *file;
69    Evas_Object   *obj;
70    Evas_Object   *bg;
71 
72    Ecore_Job     *job;
73 
74    Emotion_Xattr_Data *xattr;
75 
76    const char *title;
77 
78    struct {
79       const char *info;
80       double  stat;
81    } progress;
82    struct {
83       const char *file;
84       int   num;
85    } ref;
86    struct {
87       int button_num;
88       int button;
89    } spu;
90    struct {
91       int l; /* left */
92       int r; /* right */
93       int t; /* top */
94       int b; /* bottom */
95       Evas_Object *clipper;
96    } crop;
97 
98    struct {
99       int         w, h;
100    } video;
101    struct {
102       double      w, h;
103    } fill;
104 
105    double         ratio;
106    double         pos;
107    double         remember_jump;
108    double         seek_pos;
109    double         len;
110 
111    Emotion_Module_Options module_options;
112 
113    Emotion_Suspend state;
114    Emotion_Aspect aspect;
115 
116    Ecore_Animator *anim;
117 
118    Eina_Bool open : 1;
119    Eina_Bool play : 1;
120    Eina_Bool pause : 1;
121    Eina_Bool remember_play : 1;
122    Eina_Bool seek : 1;
123    Eina_Bool seeking : 1;
124    Eina_Bool loaded : 1;
125 };
126 
127 struct _Emotion_Xattr_Data
128 {
129    EINA_REFCOUNT;
130    Eo       *obj_wref;
131 #ifdef HAVE_EIO
132    Eio_File *load;
133    Eio_File *save;
134 #endif
135 };
136 
137 static void _mouse_move(void *data, Evas *ev, Evas_Object *obj, void *event_info);
138 static void _mouse_down(void *data, Evas *ev, Evas_Object *obj, void *event_info);
139 static void _pos_set_job(void *data);
140 static void _pixels_get(void *data, Evas_Object *obj);
141 
142 static void
_engine_init(Eo * obj,Efl_Canvas_Video_Data * sd)143 _engine_init(Eo *obj, Efl_Canvas_Video_Data *sd)
144 {
145    if (sd->engine_instance) return;
146    sd->engine_instance = emotion_engine_instance_new(sd->engine, obj,
147                                                      &(sd->module_options));
148 }
149 
150 static void
_emotion_image_data_zero(Evas_Object * img)151 _emotion_image_data_zero(Evas_Object *img)
152 {
153    void *data = NULL;
154 
155    data = evas_object_image_data_get(img, 1);
156    if (data)
157      {
158         int w, h, sz = 0;
159         Evas_Colorspace cs;
160 
161         evas_object_image_size_get(img, &w, &h);
162         cs = evas_object_image_colorspace_get(img);
163         if (cs == EVAS_COLORSPACE_ARGB8888)
164            sz = w * h * 4;
165         if ((cs == EVAS_COLORSPACE_YCBCR422P601_PL) ||
166             (cs == EVAS_COLORSPACE_YCBCR422P709_PL))
167            sz = h * 2 * sizeof(unsigned char *);
168         if (sz != 0) memset(data, 0, sz);
169      }
170    evas_object_image_data_set(img, data);
171 }
172 
173 static void
_xattr_data_cancel(Emotion_Xattr_Data * xattr)174 _xattr_data_cancel(Emotion_Xattr_Data *xattr)
175 {
176    (void) xattr;
177 #ifdef HAVE_EIO
178    /* Only cancel the load_xattr or we will loose ref to time_seek stringshare */
179    if (xattr->load) eio_file_cancel(xattr->load);
180    xattr->load = NULL;
181    if (xattr->save) eio_file_cancel(xattr->save);
182    xattr->save = NULL;
183 #endif
184 }
185 
186 static void
_xattr_data_unref(Emotion_Xattr_Data * xattr)187 _xattr_data_unref(Emotion_Xattr_Data *xattr)
188 {
189    EINA_REFCOUNT_UNREF(xattr) {} else return;
190 
191    _xattr_data_cancel(xattr);
192    efl_wref_del_safe(&xattr->obj_wref);
193    free(xattr);
194 }
195 
196 static void
_clipper_position_size_update(Evas_Object * obj,int x,int y,int w,int h,int vid_w,int vid_h)197 _clipper_position_size_update(Evas_Object *obj, int x, int y, int w, int h, int vid_w, int vid_h)
198 {
199    Efl_Canvas_Video_Data *sd;
200    double scale_w, scale_h;
201 
202    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
203 
204    if (vid_w == 0 || vid_h == 0)
205      {
206        evas_object_image_fill_set(sd->obj, 0, 0, 0, 0);
207        evas_object_move(sd->obj, x, y);
208        evas_object_resize(sd->obj, 0, 0);
209        if (!sd->crop.clipper) return;
210        evas_object_move(sd->crop.clipper, x, y);
211        evas_object_resize(sd->crop.clipper, 0, 0);
212      }
213    else
214      {
215        scale_w = (double)w / (double)(vid_w - sd->crop.l - sd->crop.r);
216        scale_h = (double)h / (double)(vid_h - sd->crop.t - sd->crop.b);
217 
218        if (sd->fill.w < 0 && sd->fill.h < 0)
219          evas_object_image_fill_set(sd->obj, 0, 0, vid_w * scale_w, vid_h * scale_h);
220        else
221          evas_object_image_fill_set(sd->obj, 0, 0, sd->fill.w * w, sd->fill.h * h);
222        evas_object_resize(sd->obj, vid_w * scale_w, vid_h * scale_h);
223        evas_object_move(sd->obj, x - sd->crop.l * scale_w, y - sd->crop.t * scale_h);
224        if (!sd->crop.clipper) return;
225        evas_object_move(sd->crop.clipper, x, y);
226        evas_object_resize(sd->crop.clipper, w, h);
227      }
228 }
229 
230 /*******************************/
231 /* Externally accessible calls */
232 /*******************************/
233 
234 
235 
236 EAPI Evas_Object *
emotion_object_add(Evas * evas)237 emotion_object_add(Evas *evas)
238 {
239    evas = evas_find(evas);
240    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(evas, EVAS_CANVAS_CLASS), NULL);
241    return efl_add(MY_CLASS, evas, efl_canvas_object_legacy_ctor(efl_added));
242 }
243 
244 EOLIAN static Eo *
_efl_canvas_video_efl_object_constructor(Eo * obj,Efl_Canvas_Video_Data * pd EINA_UNUSED)245 _efl_canvas_video_efl_object_constructor(Eo *obj, Efl_Canvas_Video_Data *pd EINA_UNUSED)
246 {
247    efl_canvas_group_clipped_set(obj, EINA_TRUE);
248    obj = efl_constructor(efl_super(obj, MY_CLASS));
249    efl_canvas_object_type_set(obj, E_OBJ_NAME);
250 
251    return obj;
252 }
253 
254 EAPI Evas_Object *
emotion_object_image_get(const Evas_Object * obj)255 emotion_object_image_get(const Evas_Object *obj)
256 {
257    Efl_Canvas_Video_Data *sd = efl_data_scope_safe_get(obj, MY_CLASS);
258    if (!sd) return NULL;
259    return sd->obj;
260 }
261 
262 EOLIAN static void
_efl_canvas_video_option_set(Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * pd,const char * opt,const char * val)263 _efl_canvas_video_option_set(Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *pd, const char *opt, const char *val)
264 {
265    Efl_Canvas_Video_Data *sd = pd;
266 
267    if ((!opt) || (!val)) return;
268 
269    if (strcmp(opt, "video") == 0)
270      {
271         if (strcmp(val, "off") == 0)
272           sd->module_options.no_video = EINA_TRUE;
273         else if (strcmp(val, "on") == 0)
274           sd->module_options.no_video = EINA_FALSE;
275         else
276           sd->module_options.no_video = !!atoi(val);
277 
278         ERR("Deprecated. Use emotion_object_video_mute_set()");
279      }
280    else if (strcmp(opt, "audio") == 0)
281      {
282         if (strcmp(val, "off") == 0)
283           sd->module_options.no_audio = EINA_TRUE;
284         else if (strcmp(val, "on") == 0)
285           sd->module_options.no_audio = EINA_FALSE;
286         else
287           sd->module_options.no_audio = !!atoi(val);
288 
289         ERR("Deprecated. Use emotion_object_audio_mute_set()");
290      }
291    else
292      ERR("Unsupported %s=%s", opt, val);
293 }
294 
295 EOLIAN static Eina_Bool
_efl_canvas_video_engine_set(Eo * obj,Efl_Canvas_Video_Data * pd,const char * engine)296 _efl_canvas_video_engine_set(Eo *obj, Efl_Canvas_Video_Data *pd, const char *engine)
297 {
298    Efl_Canvas_Video_Data *sd = pd;
299    const char *file;
300 
301    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
302 
303    if (!engine) engine = "gstreamer1";
304    if (!strcmp(engine, sd->engine)) return EINA_TRUE;
305 
306    eina_stringshare_replace(&(sd->engine), engine);
307 
308    file = sd->file;
309    sd->file = NULL;
310 
311    eina_stringshare_del(sd->title);
312    sd->title = NULL;
313    eina_stringshare_del(sd->progress.info);
314    sd->progress.info = NULL;
315    sd->progress.stat = 0.0;
316    eina_stringshare_del(sd->ref.file);
317    sd->ref.file = NULL;
318    sd->ref.num = 0;
319    sd->spu.button_num = 0;
320    sd->spu.button = -1;
321    sd->ratio = 1.0;
322    sd->pos = 0;
323    sd->remember_jump = 0;
324    sd->seek_pos = 0;
325    sd->len = 0;
326    sd->remember_play = 0;
327 
328    if (sd->anim) ecore_animator_del(sd->anim);
329    sd->anim = NULL;
330 
331    if (sd->engine_instance) emotion_engine_instance_del(sd->engine_instance);
332    sd->engine_instance = NULL;
333    _engine_init(obj, sd);
334    if (!sd->engine_instance)
335      {
336         sd->file = file;
337         return EINA_FALSE;
338      }
339 
340    if (file)
341      {
342         emotion_object_file_set(obj, file);
343         eina_stringshare_del(file);
344      }
345 
346    return EINA_TRUE;
347 }
348 
349 EAPI Eina_Bool
emotion_object_file_set(Evas_Object * obj,const char * file)350 emotion_object_file_set(Evas_Object *obj, const char *file)
351 {
352    return efl_file_simple_load(obj, file, NULL);
353 }
354 
355 EOLIAN static Eina_Error
_efl_canvas_video_efl_file_file_set(Eo * obj,Efl_Canvas_Video_Data * sd,const char * file)356 _efl_canvas_video_efl_file_file_set(Eo *obj, Efl_Canvas_Video_Data *sd, const char *file)
357 {
358    DBG("file=%s", file);
359 
360    eina_stringshare_replace(&sd->file, file);
361    sd->loaded = 0;
362    return efl_file_set(efl_super(obj, MY_CLASS), file);
363 }
364 
365 EOLIAN static Eina_Bool
_efl_canvas_video_efl_file_loaded_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)366 _efl_canvas_video_efl_file_loaded_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
367 {
368    return sd->open && sd->loaded;
369 }
370 
371 EOLIAN static void
_efl_canvas_video_efl_file_unload(Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)372 _efl_canvas_video_efl_file_unload(Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
373 {
374     if (sd->engine_instance) emotion_engine_instance_file_close(sd->engine_instance);
375     sd->engine_instance = NULL;
376     evas_object_image_data_set(sd->obj, NULL);
377     evas_object_image_size_set(sd->obj, 1, 1);
378     _emotion_image_data_zero(sd->obj);
379 
380    if (sd->anim) ecore_animator_del(sd->anim);
381    sd->anim = NULL;
382 
383    _xattr_data_cancel(sd->xattr);
384    sd->loaded = 0;
385 }
386 
387 EOLIAN static Eina_Error
_efl_canvas_video_efl_file_load(Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)388 _efl_canvas_video_efl_file_load(Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
389 {
390    const char *file = sd->file;
391    if (!sd->engine_instance) _engine_init(obj, sd);
392    if (!sd->engine_instance)
393      {
394         WRN("No engine chosen. Please set an engine.");
395         return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
396      }
397 
398    sd->video.w = 0;
399    sd->video.h = 0;
400    if ((file) && (file[0] != 0))
401      {
402         char *file2 = NULL;
403 
404         emotion_engine_instance_file_close(sd->engine_instance);
405         evas_object_image_data_set(sd->obj, NULL);
406         evas_object_image_size_set(sd->obj, 1, 1);
407         _emotion_image_data_zero(sd->obj);
408         sd->open = 0;
409 
410         if (file)
411           {
412              file2 = eina_vpath_resolve(file);
413           }
414 
415         if (!emotion_engine_instance_file_open(sd->engine_instance, file2))
416           {
417              WRN("Couldn't open file=%s", sd->file);
418              return EFL_GFX_IMAGE_LOAD_ERROR_GENERIC;
419           }
420         free(file2);
421         DBG("successfully opened file=%s", sd->file);
422         sd->pos = 0.0;
423         if (sd->play) emotion_engine_instance_play(sd->engine_instance, 0.0);
424      }
425    else
426      {
427         emotion_engine_instance_file_close(sd->engine_instance);
428         evas_object_image_data_set(sd->obj, NULL);
429         evas_object_image_size_set(sd->obj, 1, 1);
430         _emotion_image_data_zero(sd->obj);
431      }
432 
433    if (sd->anim) ecore_animator_del(sd->anim);
434    sd->anim = NULL;
435 
436    _xattr_data_cancel(sd->xattr);
437    sd->loaded = 1;
438 
439    return 0;
440 }
441 
442 EAPI const char *
emotion_object_file_get(const Evas_Object * obj)443 emotion_object_file_get(const Evas_Object *obj)
444 {
445    return efl_file_get(obj);
446 }
447 
448 static void
_emotion_aspect_borders_apply(Evas_Object * obj,Efl_Canvas_Video_Data * sd,int w,int h,int iw,int ih)449 _emotion_aspect_borders_apply(Evas_Object *obj, Efl_Canvas_Video_Data *sd, int w, int h, int iw, int ih)
450 {
451    int x, y;
452 
453    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
454 
455    /* applying calculated borders */
456    if ((sd->crop.l == 0) && (sd->crop.r == 0) &&
457        (sd->crop.t == 0) && (sd->crop.b == 0))
458      {
459         Evas_Object *old_clipper;
460         if (sd->crop.clipper)
461           {
462              old_clipper = evas_object_clip_get(sd->crop.clipper);
463              evas_object_clip_unset(sd->obj);
464              evas_object_clip_set(sd->obj, old_clipper);
465              evas_object_del(sd->crop.clipper);
466              sd->crop.clipper = NULL;
467           }
468      }
469    else
470      {
471         if (!sd->crop.clipper)
472           {
473              Evas_Object *old_clipper;
474              sd->crop.clipper = evas_object_rectangle_add
475                (evas_object_evas_get(obj));
476              evas_object_smart_member_add(sd->crop.clipper, obj);
477              old_clipper = evas_object_clip_get(sd->obj);
478              evas_object_clip_set(sd->obj, sd->crop.clipper);
479              evas_object_clip_set(sd->crop.clipper, old_clipper);
480              evas_object_show(sd->crop.clipper);
481           }
482      }
483    _clipper_position_size_update(obj, x, y, w, h, iw, ih);
484 }
485 
486 static void
_efl_canvas_video_aspect_border_apply(Evas_Object * obj,Efl_Canvas_Video_Data * sd,int w,int h)487 _efl_canvas_video_aspect_border_apply(Evas_Object *obj, Efl_Canvas_Video_Data *sd, int w, int h)
488 {
489    int iw, ih;
490    double ir;
491    double r;
492 
493    int aspect_opt = 0;
494 
495    /* Prefer (if available) the video aspect ratio to calculate the sizes */
496    if (sd->ratio > 0.0)
497      {
498         ir = sd->ratio;
499         ih = sd->video.h;
500         iw = (double)ih * ir;
501      }
502    else
503      {
504         iw = sd->video.w;
505         ih = sd->video.h;
506         ir = (double)iw / ih;
507      }
508 
509    r = (double)w / h;
510 
511    /* First check if we should fit the width or height of the video inside the
512     * width/height of the object.  This check takes into account the original
513     * aspect ratio and the object aspect ratio, if we are keeping both sizes or
514     * cropping the exceding area.
515     */
516    if (sd->aspect == EMOTION_ASPECT_KEEP_NONE)
517      {
518         sd->crop.l = 0;
519         sd->crop.r = 0;
520         sd->crop.t = 0;
521         sd->crop.b = 0;
522         aspect_opt = 0; // just ignore keep_aspect
523      }
524    else if (sd->aspect == EMOTION_ASPECT_KEEP_WIDTH)
525      {
526         aspect_opt = 1;
527      }
528    else if (sd->aspect == EMOTION_ASPECT_KEEP_HEIGHT)
529      {
530         aspect_opt = 2;
531      }
532    else if (sd->aspect == EMOTION_ASPECT_KEEP_BOTH)
533      {
534         if (ir > r) aspect_opt = 1;
535         else aspect_opt = 2;
536      }
537    else if (sd->aspect == EMOTION_ASPECT_CROP)
538      {
539         if (ir > r) aspect_opt = 2;
540         else aspect_opt = 1;
541      }
542    else if (sd->aspect == EMOTION_ASPECT_CUSTOM)
543      {
544         // nothing to do, just respect the border settings
545         aspect_opt = 0;
546      }
547 
548    /* updating borders based on keep_aspect settings */
549    if (aspect_opt == 1) // keep width
550      {
551         int th, dh;
552         double scale;
553 
554         sd->crop.l = 0;
555         sd->crop.r = 0;
556         scale = (double)iw / w;
557         th = h * scale;
558         dh = ih - th;
559         sd->crop.t = sd->crop.b = dh / 2;
560      }
561    else if (aspect_opt == 2) // keep height
562      {
563         int tw, dw;
564         double scale;
565 
566         sd->crop.t = 0;
567         sd->crop.b = 0;
568         scale = (double)ih / h;
569         tw = w * scale;
570         dw = iw - tw;
571         sd->crop.l = sd->crop.r = dw / 2;
572      }
573 
574    _emotion_aspect_borders_apply(obj, sd, w, h, iw, ih);
575 }
576 
577 EAPI void
emotion_object_border_set(Evas_Object * obj,int l,int r,int t,int b)578 emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b)
579 {
580    Efl_Canvas_Video_Data *sd;
581    int w, h;
582 
583    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
584 
585    sd->aspect = EMOTION_ASPECT_CUSTOM;
586    sd->crop.l = -l;
587    sd->crop.r = -r;
588    sd->crop.t = -t;
589    sd->crop.b = -b;
590    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
591    _efl_canvas_video_aspect_border_apply(obj, sd, w, h);
592 }
593 
594 EAPI void
emotion_object_border_get(const Evas_Object * obj,int * l,int * r,int * t,int * b)595 emotion_object_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
596 {
597    Efl_Canvas_Video_Data *sd;
598 
599    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
600    *l = -sd->crop.l;
601    *r = -sd->crop.r;
602    *t = -sd->crop.t;
603    *b = -sd->crop.b;
604 }
605 
606 EAPI void
emotion_object_bg_color_set(Evas_Object * obj,int r,int g,int b,int a)607 emotion_object_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
608 {
609    Efl_Canvas_Video_Data *sd;
610 
611    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
612    evas_object_color_set(sd->bg, r, g, b, a);
613 }
614 
615 EAPI void
emotion_object_bg_color_get(const Evas_Object * obj,int * r,int * g,int * b,int * a)616 emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
617 {
618    Efl_Canvas_Video_Data *sd;
619 
620    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
621    evas_object_color_get(sd->bg, r, g, b, a);
622 }
623 
624 EAPI void
emotion_object_keep_aspect_set(Evas_Object * obj,Emotion_Aspect a)625 emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a)
626 {
627    Efl_Canvas_Video_Data *sd;
628    int w, h;
629 
630    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
631    if (a == sd->aspect) return;
632 
633    sd->aspect = a;
634    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
635    _efl_canvas_video_aspect_border_apply(obj, sd, w, h);
636 }
637 
638 EAPI Emotion_Aspect
emotion_object_keep_aspect_get(const Evas_Object * obj)639 emotion_object_keep_aspect_get(const Evas_Object *obj)
640 {
641    Efl_Canvas_Video_Data *sd;
642 
643    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_ASPECT_KEEP_NONE);
644    return sd->aspect;
645 }
646 
647 EAPI void
emotion_object_play_set(Evas_Object * obj,Eina_Bool play)648 emotion_object_play_set(Evas_Object *obj, Eina_Bool play)
649 {
650    /* avoid calling playback_position_set(0) for legacy */
651    if (play)
652      efl_player_playing_set(obj, EINA_TRUE);
653    efl_player_paused_set(obj, !play);
654 }
655 
656 EOLIAN static Eina_Bool
_efl_canvas_video_efl_player_playing_set(Eo * obj,Efl_Canvas_Video_Data * sd,Eina_Bool play)657 _efl_canvas_video_efl_player_playing_set(Eo *obj, Efl_Canvas_Video_Data *sd, Eina_Bool play)
658 {
659    play = !!play;
660    DBG("play=" FMT_UCHAR ", was=" FMT_UCHAR, play, sd->play);
661    if (!sd->engine_instance) return EINA_FALSE;
662    /* always unset pause if playing is false */
663    if (!play) sd->pause = EINA_FALSE;
664    if (!sd->open)
665      {
666         sd->remember_play = play;
667         return EINA_TRUE;
668      }
669    if (play == sd->play) return EINA_TRUE;
670    sd->play = play;
671    sd->remember_play = play;
672    if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP);
673    if (sd->play) emotion_engine_instance_play(sd->engine_instance, 0.0);
674    else
675      {
676         emotion_engine_instance_stop(sd->engine_instance);
677         efl_player_playback_position_set(obj, 0.0);
678      }
679    return EINA_TRUE;
680 }
681 
682 EOLIAN static Eina_Bool
_efl_canvas_video_efl_player_paused_set(Eo * obj,Efl_Canvas_Video_Data * sd,Eina_Bool paused)683 _efl_canvas_video_efl_player_paused_set(Eo *obj, Efl_Canvas_Video_Data *sd, Eina_Bool paused)
684 {
685    paused = !!paused;
686    DBG("paused=" FMT_UCHAR ", was=" FMT_UCHAR, paused, sd->pause);
687    if (!sd->engine_instance) return EINA_FALSE;
688    if (!sd->open)
689      {
690         /* queue pause */
691         if (sd->remember_play)
692           sd->pause = paused;
693         return sd->remember_play;
694      }
695    if (!sd->play) return EINA_FALSE;
696    if (paused == sd->pause) return EINA_TRUE;
697    sd->pause = paused;
698    if (sd->pause)
699      emotion_engine_instance_stop(sd->engine_instance);
700    else
701      {
702         if (sd->state != EMOTION_WAKEUP) emotion_object_suspend_set(obj, EMOTION_WAKEUP);
703         emotion_engine_instance_play(sd->engine_instance, sd->pos);
704      }
705    return EINA_TRUE;
706 }
707 
708 EAPI Eina_Bool
emotion_object_play_get(const Evas_Object * obj)709 emotion_object_play_get(const Evas_Object *obj)
710 {
711    return efl_player_playing_get(obj) && !efl_player_paused_get(obj);
712 }
713 
714 EOLIAN static Eina_Bool
_efl_canvas_video_efl_player_playing_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)715 _efl_canvas_video_efl_player_playing_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
716 {
717    if (!sd->engine_instance) return EINA_FALSE;
718    return sd->play;
719 }
720 
721 EOLIAN static Eina_Bool
_efl_canvas_video_efl_player_paused_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)722 _efl_canvas_video_efl_player_paused_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
723 {
724    if (!sd->engine_instance) return EINA_FALSE;
725    if (!sd->play) return EINA_FALSE;
726    return sd->pause;
727 }
728 
729 EAPI void
emotion_object_position_set(Evas_Object * obj,double sec)730 emotion_object_position_set(Evas_Object *obj, double sec)
731 {
732    efl_player_playback_position_set(obj, sec);
733 }
734 
735 EOLIAN static void
_efl_canvas_video_efl_player_playback_position_set(Eo * obj,Efl_Canvas_Video_Data * sd,double sec)736 _efl_canvas_video_efl_player_playback_position_set(Eo *obj, Efl_Canvas_Video_Data *sd, double sec)
737 {
738    DBG("sec=%f", sec);
739    if (!sd->engine_instance) return;
740    if (sec < 0.0) sec = 0.0;
741    if (!sd->open)
742      {
743         sd->remember_jump = sec;
744         return;
745      }
746    sd->remember_jump = 0;
747    sd->seek_pos = sec;
748    sd->seek = 1;
749    sd->pos = sd->seek_pos;
750    if (sd->job) ecore_job_del(sd->job);
751    sd->job = ecore_job_add(_pos_set_job, obj);
752 }
753 
754 EAPI double
emotion_object_position_get(const Evas_Object * obj)755 emotion_object_position_get(const Evas_Object *obj)
756 {
757    return efl_player_playback_position_get(obj);
758 }
759 
760 EOLIAN static double
_efl_canvas_video_efl_player_playback_position_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)761 _efl_canvas_video_efl_player_playback_position_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
762 {
763    if (!sd->engine_instance) return 0.0;
764    sd->pos = emotion_engine_instance_pos_get(sd->engine_instance);
765    return sd->pos;
766 }
767 
768 EAPI double
emotion_object_buffer_size_get(const Evas_Object * obj)769 emotion_object_buffer_size_get(const Evas_Object *obj)
770 {
771    Efl_Canvas_Video_Data *sd;
772 
773    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 1.0);
774    if (!sd->engine_instance) return 0.0;
775    return emotion_engine_instance_buffer_size_get(sd->engine_instance);
776 }
777 
778 EAPI Eina_Bool
emotion_object_seekable_get(const Evas_Object * obj)779 emotion_object_seekable_get(const Evas_Object *obj)
780 {
781    return efl_playable_seekable_get(obj);
782 }
783 
784 EAPI Eina_Bool
emotion_object_video_handled_get(const Evas_Object * obj)785 emotion_object_video_handled_get(const Evas_Object *obj)
786 {
787    Efl_Canvas_Video_Data *sd;
788 
789    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
790    if (!sd->engine_instance) return EINA_FALSE;
791    return emotion_engine_instance_video_handled(sd->engine_instance);
792 }
793 
794 EAPI Eina_Bool
emotion_object_audio_handled_get(const Evas_Object * obj)795 emotion_object_audio_handled_get(const Evas_Object *obj)
796 {
797    Efl_Canvas_Video_Data *sd;
798 
799    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
800    if (!sd->engine_instance) return EINA_FALSE;
801    return emotion_engine_instance_audio_handled(sd->engine_instance);
802 }
803 
804 EAPI double
emotion_object_play_length_get(const Evas_Object * obj)805 emotion_object_play_length_get(const Evas_Object *obj)
806 {
807    return efl_playable_length_get(obj);
808 }
809 
810 EAPI void
emotion_object_size_get(const Evas_Object * obj,int * iw,int * ih)811 emotion_object_size_get(const Evas_Object *obj, int *iw, int *ih)
812 {
813    Eina_Size2D sz;
814 
815    sz = efl_gfx_image_load_controller_load_size_get(obj);
816    if (iw) *iw = sz.w;
817    if (ih) *ih = sz.h;
818 }
819 
820 EOLIAN static Eina_Size2D
_efl_canvas_video_efl_gfx_image_load_controller_load_size_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)821 _efl_canvas_video_efl_gfx_image_load_controller_load_size_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
822 {
823    // FIXME: Shouldn't this be efl_gfx_view_size instead?
824    return EINA_SIZE2D(sd->video.w, sd->video.h);
825 }
826 
827 EAPI void
emotion_object_smooth_scale_set(Evas_Object * obj,Eina_Bool smooth)828 emotion_object_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth)
829 {
830    efl_gfx_image_smooth_scale_set(obj, smooth);
831 }
832 
833 EOLIAN static void
_efl_canvas_video_efl_gfx_image_smooth_scale_set(Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd,Eina_Bool smooth)834 _efl_canvas_video_efl_gfx_image_smooth_scale_set(Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd, Eina_Bool smooth)
835 {
836    evas_object_image_smooth_scale_set(sd->obj, smooth);
837 }
838 
839 EAPI Eina_Bool
emotion_object_smooth_scale_get(const Evas_Object * obj)840 emotion_object_smooth_scale_get(const Evas_Object *obj)
841 {
842    return efl_gfx_image_smooth_scale_get(obj);
843 }
844 
845 EOLIAN static Eina_Bool
_efl_canvas_video_efl_gfx_image_smooth_scale_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)846 _efl_canvas_video_efl_gfx_image_smooth_scale_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
847 {
848    return evas_object_image_smooth_scale_get(sd->obj);
849 }
850 
851 EAPI double
emotion_object_ratio_get(const Evas_Object * obj)852 emotion_object_ratio_get(const Evas_Object *obj)
853 {
854    return efl_gfx_image_ratio_get(obj);
855 }
856 
857 EOLIAN static double
_efl_canvas_video_efl_gfx_image_ratio_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)858 _efl_canvas_video_efl_gfx_image_ratio_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
859 {
860    if (!sd->engine_instance) return 0.0;
861    return sd->ratio;
862 }
863 
864 /*
865  * Send a control event to the DVD.
866  */
867 EAPI void
emotion_object_event_simple_send(Evas_Object * obj,Emotion_Event ev)868 emotion_object_event_simple_send(Evas_Object *obj, Emotion_Event ev)
869 {
870    Efl_Canvas_Video_Data *sd;
871 
872    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
873    if (!sd->engine_instance) return;
874    emotion_engine_instance_event_feed(sd->engine_instance, ev);
875 }
876 
877 EAPI void
emotion_object_audio_volume_set(Evas_Object * obj,double vol)878 emotion_object_audio_volume_set(Evas_Object *obj, double vol)
879 {
880    efl_audio_control_volume_set(obj, vol);
881 }
882 
883 EOLIAN static void
_efl_canvas_video_efl_audio_control_volume_set(Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd,double vol)884 _efl_canvas_video_efl_audio_control_volume_set(Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd, double vol)
885 {
886    DBG("vol=%f", vol);
887    if (!sd->engine_instance) return;
888    emotion_engine_instance_audio_channel_volume_set(sd->engine_instance, vol);
889 }
890 
891 EAPI double
emotion_object_audio_volume_get(const Evas_Object * obj)892 emotion_object_audio_volume_get(const Evas_Object *obj)
893 {
894    return efl_audio_control_volume_get(obj);
895 }
896 
897 EOLIAN static double
_efl_canvas_video_efl_audio_control_volume_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)898 _efl_canvas_video_efl_audio_control_volume_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
899 {
900    if (!sd->engine_instance) return 0.0;
901    return emotion_engine_instance_audio_channel_volume_get(sd->engine_instance);
902 }
903 
904 EAPI void
emotion_object_audio_mute_set(Evas_Object * obj,Eina_Bool mute)905 emotion_object_audio_mute_set(Evas_Object *obj, Eina_Bool mute)
906 {
907    efl_audio_control_mute_set(obj, mute);
908 }
909 
910 EOLIAN static void
_efl_canvas_video_efl_audio_control_mute_set(Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd,Eina_Bool mute)911 _efl_canvas_video_efl_audio_control_mute_set(Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd, Eina_Bool mute)
912 {
913    DBG("mute=" FMT_UCHAR, mute);
914    if (!sd->engine_instance) return;
915    emotion_engine_instance_audio_channel_mute_set(sd->engine_instance, mute);
916 }
917 
918 EAPI Eina_Bool
emotion_object_audio_mute_get(const Evas_Object * obj)919 emotion_object_audio_mute_get(const Evas_Object *obj)
920 {
921    return efl_audio_control_mute_get(obj);
922 }
923 
924 EOLIAN static Eina_Bool
_efl_canvas_video_efl_audio_control_mute_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)925 _efl_canvas_video_efl_audio_control_mute_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
926 {
927    if (!sd->engine_instance) return EINA_FALSE;
928    return emotion_engine_instance_audio_channel_mute_get(sd->engine_instance);
929 }
930 
931 EAPI int
emotion_object_audio_channel_count(const Evas_Object * obj)932 emotion_object_audio_channel_count(const Evas_Object *obj)
933 {
934    Efl_Canvas_Video_Data *sd;
935 
936    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
937    if (!sd->engine_instance) return 0;
938    return emotion_engine_instance_audio_channel_count(sd->engine_instance);
939 }
940 
941 EAPI const char *
emotion_object_audio_channel_name_get(const Evas_Object * obj,int channel)942 emotion_object_audio_channel_name_get(const Evas_Object *obj, int channel)
943 {
944    Efl_Canvas_Video_Data *sd;
945 
946    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
947    if (!sd->engine_instance) return NULL;
948    return emotion_engine_instance_audio_channel_name_get(sd->engine_instance, channel);
949 }
950 
951 EAPI void
emotion_object_audio_channel_set(Evas_Object * obj,int channel)952 emotion_object_audio_channel_set(Evas_Object *obj, int channel)
953 {
954    Efl_Canvas_Video_Data *sd;
955 
956    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
957    DBG("channel=%d", channel);
958    if (!sd->engine_instance) return;
959    emotion_engine_instance_audio_channel_set(sd->engine_instance, channel);
960 }
961 
962 EAPI int
emotion_object_audio_channel_get(const Evas_Object * obj)963 emotion_object_audio_channel_get(const Evas_Object *obj)
964 {
965    Efl_Canvas_Video_Data *sd;
966 
967    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
968    if (!sd->engine_instance) return 0;
969    return emotion_engine_instance_audio_channel_get(sd->engine_instance);
970 }
971 
972 EAPI void
emotion_object_video_mute_set(Evas_Object * obj,Eina_Bool mute)973 emotion_object_video_mute_set(Evas_Object *obj, Eina_Bool mute)
974 {
975    Efl_Canvas_Video_Data *sd;
976 
977    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
978    DBG("mute=" FMT_UCHAR, mute);
979    if (!sd->engine_instance) return;
980    emotion_engine_instance_video_channel_mute_set(sd->engine_instance, mute);
981 }
982 
983 EAPI Eina_Bool
emotion_object_video_mute_get(const Evas_Object * obj)984 emotion_object_video_mute_get(const Evas_Object *obj)
985 {
986    Efl_Canvas_Video_Data *sd;
987 
988    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
989    if (!sd->engine_instance) return EINA_FALSE;
990    return emotion_engine_instance_video_channel_mute_get(sd->engine_instance);
991 }
992 
993 EAPI void
emotion_object_video_subtitle_file_set(Evas_Object * obj,const char * filepath)994 emotion_object_video_subtitle_file_set(Evas_Object *obj, const char *filepath)
995 {
996    Efl_Canvas_Video_Data *sd;
997 
998    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
999    DBG("subtitle=%s", filepath);
1000    if (!sd->engine_instance) _engine_init(obj, sd);
1001    if (!sd->engine_instance) return;
1002    emotion_engine_instance_video_subtitle_file_set(sd->engine_instance, filepath);
1003 }
1004 
1005 EAPI const char *
emotion_object_video_subtitle_file_get(const Evas_Object * obj)1006 emotion_object_video_subtitle_file_get(const Evas_Object *obj)
1007 {
1008    Efl_Canvas_Video_Data *sd;
1009 
1010    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1011    if (!sd->engine_instance) return NULL;
1012    return emotion_engine_instance_video_subtitle_file_get(sd->engine_instance);
1013 }
1014 
1015 EAPI int
emotion_object_video_channel_count(const Evas_Object * obj)1016 emotion_object_video_channel_count(const Evas_Object *obj)
1017 {
1018    Efl_Canvas_Video_Data *sd;
1019 
1020    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1021    if (!sd->engine_instance) return 0;
1022    return emotion_engine_instance_video_channel_count(sd->engine_instance);
1023 }
1024 
1025 EAPI const char *
emotion_object_video_channel_name_get(const Evas_Object * obj,int channel)1026 emotion_object_video_channel_name_get(const Evas_Object *obj, int channel)
1027 {
1028    Efl_Canvas_Video_Data *sd;
1029 
1030    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1031    if (!sd->engine_instance) return NULL;
1032    return emotion_engine_instance_video_channel_name_get(sd->engine_instance, channel);
1033 }
1034 
1035 EAPI void
emotion_object_video_channel_set(Evas_Object * obj,int channel)1036 emotion_object_video_channel_set(Evas_Object *obj, int channel)
1037 {
1038    Efl_Canvas_Video_Data *sd;
1039 
1040    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1041    DBG("channel=%d", channel);
1042    if (!sd->engine_instance) return;
1043    emotion_engine_instance_video_channel_set(sd->engine_instance, channel);
1044 }
1045 
1046 EAPI int
emotion_object_video_channel_get(const Evas_Object * obj)1047 emotion_object_video_channel_get(const Evas_Object *obj)
1048 {
1049    Efl_Canvas_Video_Data *sd;
1050 
1051    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1052    if (!sd->engine_instance) return 0;
1053    return emotion_engine_instance_video_channel_get(sd->engine_instance);
1054 }
1055 
1056 EAPI void
emotion_object_spu_mute_set(Evas_Object * obj,Eina_Bool mute)1057 emotion_object_spu_mute_set(Evas_Object *obj, Eina_Bool mute)
1058 {
1059    Efl_Canvas_Video_Data *sd;
1060 
1061    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1062    DBG("mute=" FMT_UCHAR, mute);
1063    if (!sd->engine_instance) return;
1064    emotion_engine_instance_spu_channel_mute_set(sd->engine_instance, mute);
1065 }
1066 
1067 EAPI Eina_Bool
emotion_object_spu_mute_get(const Evas_Object * obj)1068 emotion_object_spu_mute_get(const Evas_Object *obj)
1069 {
1070    Efl_Canvas_Video_Data *sd;
1071 
1072    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1073    if (!sd->engine_instance) return EINA_FALSE;
1074    return emotion_engine_instance_spu_channel_mute_get(sd->engine_instance);
1075 }
1076 
1077 EAPI int
emotion_object_spu_channel_count(const Evas_Object * obj)1078 emotion_object_spu_channel_count(const Evas_Object *obj)
1079 {
1080    Efl_Canvas_Video_Data *sd;
1081 
1082    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1083    if (!sd->engine_instance) return 0;
1084    return emotion_engine_instance_spu_channel_count(sd->engine_instance);
1085 }
1086 
1087 EAPI const char *
emotion_object_spu_channel_name_get(const Evas_Object * obj,int channel)1088 emotion_object_spu_channel_name_get(const Evas_Object *obj, int channel)
1089 {
1090    Efl_Canvas_Video_Data *sd;
1091 
1092    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1093    if (!sd->engine_instance) return NULL;
1094    return emotion_engine_instance_spu_channel_name_get(sd->engine_instance, channel);
1095 }
1096 
1097 EAPI void
emotion_object_spu_channel_set(Evas_Object * obj,int channel)1098 emotion_object_spu_channel_set(Evas_Object *obj, int channel)
1099 {
1100    Efl_Canvas_Video_Data *sd;
1101 
1102    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1103    DBG("channel=%d", channel);
1104    if (!sd->engine_instance) return;
1105    emotion_engine_instance_spu_channel_set(sd->engine_instance, channel);
1106 }
1107 
1108 EAPI int
emotion_object_spu_channel_get(const Evas_Object * obj)1109 emotion_object_spu_channel_get(const Evas_Object *obj)
1110 {
1111    Efl_Canvas_Video_Data *sd;
1112 
1113    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1114    if (!sd->engine_instance) return 0;
1115    return emotion_engine_instance_spu_channel_get(sd->engine_instance);
1116 }
1117 
1118 EAPI int
emotion_object_chapter_count(const Evas_Object * obj)1119 emotion_object_chapter_count(const Evas_Object *obj)
1120 {
1121    Efl_Canvas_Video_Data *sd;
1122 
1123    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1124    if (!sd->engine_instance) return 0;
1125    return emotion_engine_instance_chapter_count(sd->engine_instance);
1126 }
1127 
1128 EAPI void
emotion_object_chapter_set(Evas_Object * obj,int chapter)1129 emotion_object_chapter_set(Evas_Object *obj, int chapter)
1130 {
1131    Efl_Canvas_Video_Data *sd;
1132 
1133    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1134    DBG("chapter=%d", chapter);
1135    if (!sd->engine_instance) return;
1136    emotion_engine_instance_chapter_set(sd->engine_instance, chapter);
1137 }
1138 
1139 EAPI int
emotion_object_chapter_get(const Evas_Object * obj)1140 emotion_object_chapter_get(const Evas_Object *obj)
1141 {
1142    Efl_Canvas_Video_Data *sd;
1143 
1144    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1145    if (!sd->engine_instance) return 0;
1146    return emotion_engine_instance_chapter_get(sd->engine_instance);
1147 }
1148 
1149 EAPI const char *
emotion_object_chapter_name_get(const Evas_Object * obj,int chapter)1150 emotion_object_chapter_name_get(const Evas_Object *obj, int chapter)
1151 {
1152    Efl_Canvas_Video_Data *sd;
1153 
1154    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1155    if (!sd->engine_instance) return NULL;
1156    return emotion_engine_instance_chapter_name_get(sd->engine_instance, chapter);
1157 }
1158 
1159 EAPI void
emotion_object_play_speed_set(Evas_Object * obj,double speed)1160 emotion_object_play_speed_set(Evas_Object *obj, double speed)
1161 {
1162    Efl_Canvas_Video_Data *sd;
1163 
1164    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1165    DBG("speed=%f", speed);
1166    if (!sd->engine_instance) return;
1167    emotion_engine_instance_speed_set(sd->engine_instance, speed);
1168 }
1169 
1170 EAPI double
emotion_object_play_speed_get(const Evas_Object * obj)1171 emotion_object_play_speed_get(const Evas_Object *obj)
1172 {
1173    Efl_Canvas_Video_Data *sd;
1174 
1175    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0.0);
1176    if (!sd->engine_instance) return 0.0;
1177    return emotion_engine_instance_speed_get(sd->engine_instance);
1178 }
1179 
1180 EAPI void
emotion_object_eject(Evas_Object * obj)1181 emotion_object_eject(Evas_Object *obj)
1182 {
1183    Efl_Canvas_Video_Data *sd;
1184 
1185    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1186    if (!sd->engine_instance) return;
1187    emotion_engine_instance_eject(sd->engine_instance);
1188 }
1189 
1190 EAPI const char *
emotion_object_title_get(const Evas_Object * obj)1191 emotion_object_title_get(const Evas_Object *obj)
1192 {
1193    Efl_Canvas_Video_Data *sd;
1194 
1195    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1196    return sd->title;
1197 }
1198 
1199 EAPI const char *
emotion_object_progress_info_get(const Evas_Object * obj)1200 emotion_object_progress_info_get(const Evas_Object *obj)
1201 {
1202    Efl_Canvas_Video_Data *sd;
1203 
1204    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1205    return sd->progress.info;
1206 }
1207 
1208 EAPI double
emotion_object_progress_status_get(const Evas_Object * obj)1209 emotion_object_progress_status_get(const Evas_Object *obj)
1210 {
1211    return efl_player_playback_progress_get(obj);
1212 }
1213 
1214 EOLIAN static double
_efl_canvas_video_efl_player_playback_progress_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)1215 _efl_canvas_video_efl_player_playback_progress_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
1216 {
1217    return sd->progress.stat;
1218 }
1219 
1220 EOLIAN static void
_efl_canvas_video_efl_player_playback_progress_set(Eo * obj,Efl_Canvas_Video_Data * sd EINA_UNUSED,double progress)1221 _efl_canvas_video_efl_player_playback_progress_set(Eo *obj, Efl_Canvas_Video_Data *sd EINA_UNUSED, double progress)
1222 {
1223    const char *info = emotion_object_progress_info_get((const Evas_Object*)obj);
1224    _emotion_progress_set(obj, (char*)info, progress);
1225 }
1226 
1227 EOLIAN static double
_efl_canvas_video_efl_playable_length_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)1228 _efl_canvas_video_efl_playable_length_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
1229 {
1230    if (!sd->engine_instance) return 0.0;
1231    sd->len = emotion_engine_instance_len_get(sd->engine_instance);
1232    return sd->len;
1233 }
1234 
1235 EOLIAN static Eina_Bool
_efl_canvas_video_efl_playable_seekable_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)1236 _efl_canvas_video_efl_playable_seekable_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
1237 {
1238    if (!sd->engine_instance) return EINA_FALSE;
1239    return emotion_engine_instance_seekable(sd->engine_instance);
1240 }
1241 
1242 EAPI const char *
emotion_object_ref_file_get(const Evas_Object * obj)1243 emotion_object_ref_file_get(const Evas_Object *obj)
1244 {
1245    Efl_Canvas_Video_Data *sd;
1246 
1247    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1248    return sd->ref.file;
1249 }
1250 
1251 EAPI int
emotion_object_ref_num_get(const Evas_Object * obj)1252 emotion_object_ref_num_get(const Evas_Object *obj)
1253 {
1254    Efl_Canvas_Video_Data *sd;
1255 
1256    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1257    return sd->ref.num;
1258 }
1259 
1260 EAPI int
emotion_object_spu_button_count_get(const Evas_Object * obj)1261 emotion_object_spu_button_count_get(const Evas_Object *obj)
1262 {
1263    Efl_Canvas_Video_Data *sd;
1264 
1265    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1266    return sd->spu.button_num;
1267 }
1268 
1269 EAPI int
emotion_object_spu_button_get(const Evas_Object * obj)1270 emotion_object_spu_button_get(const Evas_Object *obj)
1271 {
1272    Efl_Canvas_Video_Data *sd;
1273 
1274    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, 0);
1275    return sd->spu.button;
1276 }
1277 
1278 EAPI const char *
emotion_object_meta_info_get(const Evas_Object * obj,Emotion_Meta_Info meta)1279 emotion_object_meta_info_get(const Evas_Object *obj, Emotion_Meta_Info meta)
1280 {
1281    Efl_Canvas_Video_Data *sd;
1282    int id;
1283 
1284    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1285    if (!sd->engine_instance) return NULL;
1286    switch (meta)
1287      {
1288       case EMOTION_META_INFO_TRACK_TITLE:
1289          id = META_TRACK_TITLE;
1290          break;
1291       case EMOTION_META_INFO_TRACK_ARTIST:
1292          id = META_TRACK_ARTIST;
1293          break;
1294       case EMOTION_META_INFO_TRACK_ALBUM:
1295          id = META_TRACK_ALBUM;
1296          break;
1297       case EMOTION_META_INFO_TRACK_YEAR:
1298          id = META_TRACK_YEAR;
1299          break;
1300       case EMOTION_META_INFO_TRACK_GENRE:
1301          id = META_TRACK_GENRE;
1302          break;
1303       case EMOTION_META_INFO_TRACK_COMMENT:
1304          id = META_TRACK_COMMENT;
1305          break;
1306       case EMOTION_META_INFO_TRACK_DISC_ID:
1307          id = META_TRACK_DISCID;
1308         break;
1309       default:
1310          ERR("Unknown meta info id: %d", meta);
1311          return NULL;
1312      }
1313 
1314    return emotion_engine_instance_meta_get(sd->engine_instance, id);
1315 }
1316 
1317 
1318 EAPI Evas_Object *
emotion_file_meta_artwork_get(const Evas_Object * obj,const char * path,Emotion_Artwork_Info type)1319 emotion_file_meta_artwork_get(const Evas_Object *obj, const char *path, Emotion_Artwork_Info type)
1320 {
1321    Efl_Canvas_Video_Data *sd;
1322    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1323    if (!sd->engine_instance) return NULL;
1324 
1325    Evas *ev = evas_object_evas_get(obj);
1326    Evas_Object *artwork = evas_object_image_add(ev);
1327 
1328    Evas_Object *result = emotion_engine_instance_meta_artwork_get(sd->engine_instance, artwork, path, type);
1329    if (!result) return NULL;
1330 
1331    Evas_Load_Error _error = evas_object_image_load_error_get(result);
1332    if (_error != EVAS_LOAD_ERROR_NONE) return NULL;
1333 
1334    return result;
1335 }
1336 
1337 EAPI void
emotion_object_vis_set(Evas_Object * obj,Emotion_Vis visualization)1338 emotion_object_vis_set(Evas_Object *obj, Emotion_Vis visualization)
1339 {
1340    Efl_Canvas_Video_Data *sd;
1341 
1342    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1343    DBG("visualization=%d", visualization);
1344    if (!sd->engine_instance) return;
1345    emotion_engine_instance_vis_set(sd->engine_instance, visualization);
1346 }
1347 
1348 EAPI Emotion_Vis
emotion_object_vis_get(const Evas_Object * obj)1349 emotion_object_vis_get(const Evas_Object *obj)
1350 {
1351    Efl_Canvas_Video_Data *sd;
1352 
1353    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_VIS_NONE);
1354    if (!sd->engine_instance) return EMOTION_VIS_NONE;
1355    return emotion_engine_instance_vis_get(sd->engine_instance);
1356 }
1357 
1358 EAPI Eina_Bool
emotion_object_vis_supported(const Evas_Object * obj,Emotion_Vis visualization)1359 emotion_object_vis_supported(const Evas_Object *obj, Emotion_Vis visualization)
1360 {
1361    Efl_Canvas_Video_Data *sd;
1362 
1363    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE);
1364    if (!sd->engine_instance) return EINA_FALSE;
1365    return emotion_engine_instance_vis_supported(sd->engine_instance, visualization);
1366 }
1367 
1368 EAPI void
emotion_object_priority_set(Evas_Object * obj,Eina_Bool priority)1369 emotion_object_priority_set(Evas_Object *obj, Eina_Bool priority)
1370 {
1371    Efl_Canvas_Video_Data *sd;
1372 
1373    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1374    if (!sd->engine_instance) return;
1375    emotion_engine_instance_priority_set(sd->engine_instance, priority);
1376 }
1377 
1378 EAPI Eina_Bool
emotion_object_priority_get(const Evas_Object * obj)1379 emotion_object_priority_get(const Evas_Object *obj)
1380 {
1381    Efl_Canvas_Video_Data *sd;
1382 
1383    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE);
1384    if (!sd->engine_instance) return EINA_FALSE;
1385    return emotion_engine_instance_priority_get(sd->engine_instance);
1386 }
1387 
1388 #ifdef HAVE_EIO
1389 static void
_eio_load_xattr_cleanup(Emotion_Xattr_Data * xattr,Eio_File * handler)1390 _eio_load_xattr_cleanup(Emotion_Xattr_Data *xattr, Eio_File *handler)
1391 {
1392    if (handler == xattr->load) xattr->load = NULL;
1393    _xattr_data_unref(xattr);
1394 }
1395 
1396 static void
_eio_load_xattr_done(void * data,Eio_File * handler,double xattr_double)1397 _eio_load_xattr_done(void *data, Eio_File *handler, double xattr_double)
1398 {
1399    Emotion_Xattr_Data *xattr = data;
1400 
1401    emotion_object_position_set(evas_object_smart_parent_get(xattr->obj_wref), xattr_double);
1402    efl_event_callback_call(evas_object_smart_parent_get(xattr->obj_wref), EFL_CANVAS_VIDEO_EVENT_POSITION_LOAD_DONE, NULL);
1403    evas_object_smart_callback_call(evas_object_smart_parent_get(xattr->obj_wref), "position_load,succeed", NULL);
1404    _eio_load_xattr_cleanup(xattr, handler);
1405 }
1406 
1407 static void
_eio_load_xattr_error(void * data,Eio_File * handler,int err EINA_UNUSED)1408 _eio_load_xattr_error(void *data, Eio_File *handler, int err EINA_UNUSED)
1409 {
1410    Emotion_Xattr_Data *xattr = data;
1411 
1412    efl_event_callback_call(evas_object_smart_parent_get(xattr->obj_wref), EFL_CANVAS_VIDEO_EVENT_POSITION_LOAD_FAIL, NULL);
1413    evas_object_smart_callback_call(evas_object_smart_parent_get(xattr->obj_wref), "position_load,failed", NULL);
1414    _eio_load_xattr_cleanup(xattr, handler);
1415 }
1416 #endif
1417 
1418 EAPI void
emotion_object_last_position_load(Evas_Object * obj)1419 emotion_object_last_position_load(Evas_Object *obj)
1420 {
1421    Efl_Canvas_Video_Data *sd;
1422    const char *tmp;
1423 #ifndef HAVE_EIO
1424    double xattr;
1425 #endif
1426 
1427    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1428    if (!sd->file) return;
1429 
1430    if (!strncmp(sd->file, "file://", 7)) tmp = sd->file + 7;
1431    else if (!strstr(sd->file, "://")) tmp = sd->file;
1432    else return;
1433 
1434 #ifdef HAVE_EIO
1435    Emotion_Xattr_Data *xattr = sd->xattr;
1436 
1437    if (xattr->load) return;
1438    EINA_REFCOUNT_REF(xattr);
1439 
1440    xattr->load = eio_file_xattr_double_get(tmp,
1441                                            "user.e.time_seek",
1442                                            _eio_load_xattr_done,
1443                                            _eio_load_xattr_error,
1444                                            xattr);
1445 #else
1446    if (eina_xattr_double_get(tmp, "user.e.time_seek", &xattr))
1447      {
1448         emotion_object_position_set(obj, xattr);
1449         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_POSITION_LOAD_DONE, NULL);
1450         evas_object_smart_callback_call(obj, "position_load,succeed", NULL);
1451      }
1452    else
1453      {
1454         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_POSITION_LOAD_FAIL, NULL);
1455         evas_object_smart_callback_call(obj, "position_load,failed", NULL);
1456      }
1457 #endif
1458 }
1459 
1460 #ifdef HAVE_EIO
1461 static void
_eio_save_xattr_cleanup(Emotion_Xattr_Data * xattr,Eio_File * handler)1462 _eio_save_xattr_cleanup(Emotion_Xattr_Data *xattr, Eio_File *handler)
1463 {
1464    if (handler == xattr->save) xattr->save = NULL;
1465    _xattr_data_unref(xattr);
1466 }
1467 
1468 static void
_eio_save_xattr_done(void * data,Eio_File * handler)1469 _eio_save_xattr_done(void *data, Eio_File *handler)
1470 {
1471    Emotion_Xattr_Data *xattr = data;
1472 
1473    efl_event_callback_call(xattr->obj_wref, EFL_CANVAS_VIDEO_EVENT_POSITION_SAVE_DONE, NULL);
1474    evas_object_smart_callback_call(xattr->obj_wref, "position_save,succeed", NULL);
1475    _eio_save_xattr_cleanup(xattr, handler);
1476 }
1477 
1478 static void
_eio_save_xattr_error(void * data,Eio_File * handler,int err EINA_UNUSED)1479 _eio_save_xattr_error(void *data, Eio_File *handler, int err EINA_UNUSED)
1480 {
1481    Emotion_Xattr_Data *xattr = data;
1482 
1483    efl_event_callback_call(xattr->obj_wref, EFL_CANVAS_VIDEO_EVENT_POSITION_SAVE_FAIL, NULL);
1484    evas_object_smart_callback_call(xattr->obj_wref, "position_save,failed", NULL);
1485    _eio_save_xattr_cleanup(xattr, handler);
1486 }
1487 #endif
1488 
1489 EAPI void
emotion_object_last_position_save(Evas_Object * obj)1490 emotion_object_last_position_save(Evas_Object *obj)
1491 {
1492    Efl_Canvas_Video_Data *sd;
1493    const char *tmp;
1494 
1495    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1496    if (!sd->file) return;
1497 
1498    if (!strncmp(sd->file, "file://", 7)) tmp = sd->file + 7;
1499    else if (!strstr(sd->file, "://")) tmp = sd->file;
1500    else return;
1501 #ifdef HAVE_EIO
1502    Emotion_Xattr_Data *xattr = sd->xattr;
1503 
1504    if (xattr->save) return;
1505    EINA_REFCOUNT_REF(xattr);
1506 
1507    xattr->save = eio_file_xattr_double_set(tmp,
1508                                            "user.e.time_seek",
1509                                            emotion_object_position_get(obj),
1510                                            0,
1511                                            _eio_save_xattr_done,
1512                                            _eio_save_xattr_error,
1513                                            xattr);
1514 #else
1515    if (eina_xattr_double_set(tmp, "user.e.time_seek", emotion_object_position_get(obj), 0))
1516      {
1517         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_POSITION_SAVE_DONE, NULL);
1518         evas_object_smart_callback_call(obj, "position_save,succeed", NULL);
1519      }
1520    else
1521      {
1522         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_POSITION_SAVE_FAIL, NULL);
1523         evas_object_smart_callback_call(obj, "position_save,failed", NULL);
1524      }
1525 #endif
1526 }
1527 
1528 EAPI void
emotion_object_suspend_set(Evas_Object * obj,Emotion_Suspend state)1529 emotion_object_suspend_set(Evas_Object *obj, Emotion_Suspend state)
1530 {
1531    Efl_Canvas_Video_Data *sd;
1532 
1533    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1534    switch (state)
1535      {
1536       case EMOTION_WAKEUP:
1537          /* Restore the rendering pipeline, offset and everything back to play again (this will be called automatically by play_set) */
1538       case EMOTION_SLEEP:
1539          /* This destroy some part of the rendering pipeline */
1540       case EMOTION_DEEP_SLEEP:
1541          /* This destroy all the rendering pipeline and just keep the last rendered image (fullscreen) */
1542       case EMOTION_HIBERNATE:
1543          /* This destroy all the rendering pipeline and keep 1/4 of the last rendered image */
1544       default:
1545          break;
1546      }
1547    sd->state = state;
1548 }
1549 
1550 EAPI Emotion_Suspend
emotion_object_suspend_get(Evas_Object * obj)1551 emotion_object_suspend_get(Evas_Object *obj)
1552 {
1553    Efl_Canvas_Video_Data *sd;
1554 
1555    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_WAKEUP);
1556    return sd->state;
1557 }
1558 
1559 /*****************************/
1560 /* Utility calls for modules */
1561 /*****************************/
1562 
1563 EAPI void *
_emotion_video_get(const Evas_Object * obj)1564 _emotion_video_get(const Evas_Object *obj)
1565 {
1566    Efl_Canvas_Video_Data *sd;
1567 
1568    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, NULL);
1569    return emotion_engine_instance_data_get(sd->engine_instance);
1570 }
1571 
1572 static Eina_Bool
_emotion_frame_anim(void * data)1573 _emotion_frame_anim(void *data)
1574 {
1575    Evas_Object *obj = data;
1576    Efl_Canvas_Video_Data *sd;
1577 
1578    E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EINA_FALSE);
1579 
1580    sd->anim = NULL;
1581    evas_object_image_pixels_dirty_set(sd->obj, 1);
1582    _emotion_video_pos_update(obj,
1583                              emotion_engine_instance_pos_get(sd->engine_instance),
1584                              emotion_engine_instance_len_get(sd->engine_instance));
1585    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_FRAME_DECODE, NULL);
1586    evas_object_smart_callback_call(obj, "frame_decode", NULL);
1587    return EINA_FALSE;
1588 }
1589 
1590 EAPI void
_emotion_frame_new(Evas_Object * obj)1591 _emotion_frame_new(Evas_Object *obj)
1592 {
1593    Efl_Canvas_Video_Data *sd;
1594 
1595    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1596    if (!sd->anim)
1597      sd->anim = ecore_evas_animator_add(obj, _emotion_frame_anim, obj);
1598 }
1599 
1600 EAPI void
_emotion_video_pos_update(Evas_Object * obj,double pos,double len)1601 _emotion_video_pos_update(Evas_Object *obj, double pos, double len)
1602 {
1603    Efl_Canvas_Video_Data *sd;
1604    int npos = 0, nlen = 0;
1605 
1606    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1607    if (!EINA_DBL_EQ(pos, sd->pos)) npos = 1;
1608    if (!EINA_DBL_EQ(len, sd->len)) nlen = 1;
1609    sd->pos = pos;
1610    sd->len = len;
1611    if (npos)
1612      {
1613         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_POSITION_CHANGE, NULL);
1614         evas_object_smart_callback_call(obj, "position_update", NULL);
1615      }
1616    if (nlen)
1617      {
1618         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_LENGTH_CHANGE, NULL);
1619         evas_object_smart_callback_call(obj, "length_change", NULL);
1620      }
1621 }
1622 
1623 EAPI void
_emotion_frame_resize(Evas_Object * obj,int w,int h,double ratio)1624 _emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio)
1625 {
1626    Efl_Canvas_Video_Data *sd;
1627    double tmp;
1628    int changed = 0;
1629 
1630    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1631    if ((w != sd->video.w) || (h != sd->video.h))
1632      {
1633         sd->video.w = w;
1634         sd->video.h = h;
1635         _emotion_image_data_zero(sd->obj);
1636         changed = 1;
1637      }
1638    if (h > 0) tmp  = (double)w / (double)h;
1639    else tmp = 1.0;
1640    if (!EINA_DBL_EQ(ratio, tmp)) tmp = ratio;
1641    if (!EINA_DBL_EQ(tmp, sd->ratio))
1642      {
1643         sd->ratio = tmp;
1644         changed = 1;
1645      }
1646    if (changed)
1647      {
1648         evas_object_size_hint_request_set(obj, w, h);
1649         efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_FRAME_RESIZE, NULL);
1650         evas_object_smart_callback_call(obj, "frame_resize", NULL);
1651         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1652         _efl_canvas_video_aspect_border_apply(obj, sd, w, h);
1653      }
1654 }
1655 
1656 EAPI void
_emotion_image_reset(Evas_Object * obj)1657 _emotion_image_reset(Evas_Object *obj)
1658 {
1659    Efl_Canvas_Video_Data *sd;
1660 
1661    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1662    _emotion_image_data_zero(sd->obj);
1663 }
1664 
1665 EAPI void
_emotion_decode_stop(Evas_Object * obj)1666 _emotion_decode_stop(Evas_Object *obj)
1667 {
1668    Efl_Canvas_Video_Data *sd;
1669 
1670    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1671    if (sd->play)
1672      {
1673         sd->play = 0;
1674         evas_object_smart_callback_call(obj, "decode_stop", NULL);
1675      }
1676 }
1677 
1678 EAPI void
_emotion_open_done(Evas_Object * obj)1679 _emotion_open_done(Evas_Object *obj)
1680 {
1681    Efl_Canvas_Video_Data *sd;
1682 
1683    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1684    sd->open = 1;
1685 
1686    if (!EINA_DBL_EQ(sd->remember_jump, 0.0))
1687      emotion_object_position_set(obj, sd->remember_jump);
1688    if (sd->remember_play != sd->play)
1689      {
1690         if (sd->pause)
1691           sd->play = sd->remember_play;
1692         else
1693           emotion_object_play_set(obj, sd->remember_play);
1694      }
1695    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_OPEN_DONE, NULL);
1696    evas_object_smart_callback_call(obj, "open_done", NULL);
1697 }
1698 
1699 EAPI void
_emotion_playback_started(Evas_Object * obj)1700 _emotion_playback_started(Evas_Object *obj)
1701 {
1702    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_PLAYBACK_START, NULL);
1703    evas_object_smart_callback_call(obj, "playback_started", NULL);
1704 }
1705 
1706 EAPI void
_emotion_playback_finished(Evas_Object * obj)1707 _emotion_playback_finished(Evas_Object *obj)
1708 {
1709    Efl_Canvas_Video_Data *sd;
1710 
1711    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1712    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_PLAYBACK_STOP, NULL);
1713    evas_object_smart_callback_call(obj, "playback_finished", NULL);
1714 }
1715 
1716 EAPI void
_emotion_audio_level_change(Evas_Object * obj)1717 _emotion_audio_level_change(Evas_Object *obj)
1718 {
1719    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_VOLUME_CHANGE, NULL);
1720    evas_object_smart_callback_call(obj, "audio_level_change", NULL);
1721 }
1722 
1723 EAPI void
_emotion_channels_change(Evas_Object * obj)1724 _emotion_channels_change(Evas_Object *obj)
1725 {
1726    Efl_Canvas_Video_Data *sd;
1727 
1728    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1729    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_CHANNELS_CHANGE, NULL);
1730    evas_object_smart_callback_call(obj, "channels_change", NULL);
1731 }
1732 
1733 EAPI void
_emotion_title_set(Evas_Object * obj,char * title)1734 _emotion_title_set(Evas_Object *obj, char *title)
1735 {
1736    Efl_Canvas_Video_Data *sd;
1737 
1738    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1739    eina_stringshare_replace(&sd->title, title);
1740    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_TITLE_CHANGE, NULL);
1741    evas_object_smart_callback_call(obj, "title_change", NULL);
1742 }
1743 
1744 EAPI void
_emotion_progress_set(Evas_Object * obj,char * info,double st)1745 _emotion_progress_set(Evas_Object *obj, char *info, double st)
1746 {
1747    Efl_Canvas_Video_Data *sd;
1748 
1749    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1750    eina_stringshare_replace(&sd->progress.info, info);
1751    sd->progress.stat = st;
1752    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_PROGRESS_CHANGE, NULL);
1753    evas_object_smart_callback_call(obj, "progress_change", NULL);
1754 }
1755 
1756 EAPI void
_emotion_file_ref_set(Evas_Object * obj,const char * file,int num)1757 _emotion_file_ref_set(Evas_Object *obj, const char *file, int num)
1758 {
1759    Efl_Canvas_Video_Data *sd;
1760 
1761    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1762    eina_stringshare_replace(&sd->ref.file, file);
1763    sd->ref.num = num;
1764    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_REF_CHANGE, NULL);
1765    evas_object_smart_callback_call(obj, "ref_change", NULL);
1766 }
1767 
1768 EAPI void
_emotion_spu_button_num_set(Evas_Object * obj,int num)1769 _emotion_spu_button_num_set(Evas_Object *obj, int num)
1770 {
1771    Efl_Canvas_Video_Data *sd;
1772 
1773    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1774    sd->spu.button_num = num;
1775    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_BUTTON_NUM_CHANGE, NULL);
1776    evas_object_smart_callback_call(obj, "button_num_change", NULL);
1777 }
1778 
1779 EAPI void
_emotion_spu_button_set(Evas_Object * obj,int button)1780 _emotion_spu_button_set(Evas_Object *obj, int button)
1781 {
1782    Efl_Canvas_Video_Data *sd;
1783 
1784    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1785    sd->spu.button = button;
1786    efl_event_callback_call(obj, EFL_CANVAS_VIDEO_EVENT_BUTTON_CHANGE, NULL);
1787    evas_object_smart_callback_call(obj, "button_change", NULL);
1788 }
1789 
1790 EAPI void
_emotion_seek_done(Evas_Object * obj)1791 _emotion_seek_done(Evas_Object *obj)
1792 {
1793    Efl_Canvas_Video_Data *sd;
1794 
1795    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1796    if (sd->seeking)
1797      {
1798         sd->seeking = 0;
1799         if (sd->seek) emotion_object_position_set(obj, sd->seek_pos);
1800      }
1801 }
1802 
1803 EAPI void
_emotion_frame_refill(Evas_Object * obj,double w,double h)1804 _emotion_frame_refill(Evas_Object *obj, double w, double h)
1805 {
1806    Efl_Canvas_Video_Data *sd;
1807 
1808    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1809    if ((!EINA_DBL_EQ(sd->fill.w, w)) ||
1810        (!EINA_DBL_EQ(sd->fill.h, h)))
1811      {
1812         Evas_Coord ow, oh;
1813 
1814         evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1815         if ((w <= 0) || (h <= 0))
1816           {
1817              double scale_w, scale_h;
1818 
1819              sd->fill.w = -1;
1820              sd->fill.h = -1;
1821 
1822              scale_w = (double)ow / (double)(sd->video.w - sd->crop.l - sd->crop.r);
1823              scale_h = (double)oh / (double)(sd->video.h - sd->crop.t - sd->crop.b);
1824              evas_object_image_fill_set(sd->obj, 0, 0, scale_w * sd->video.w, scale_h * sd->video.h);
1825           }
1826         else
1827           {
1828              sd->fill.w = w;
1829              sd->fill.h = h;
1830              evas_object_image_fill_set(sd->obj, 0, 0, w * ow, h * oh);
1831           }
1832      }
1833 }
1834 
1835 /****************************/
1836 /* Internal object routines */
1837 /****************************/
1838 
1839 static void
_mouse_move(void * data,Evas * ev EINA_UNUSED,Evas_Object * obj,void * event_info)1840 _mouse_move(void *data, Evas *ev EINA_UNUSED, Evas_Object *obj, void *event_info)
1841 {
1842    Evas_Event_Mouse_Move *e;
1843    Efl_Canvas_Video_Data *sd;
1844    int x, y, iw, ih;
1845    Evas_Coord ox, oy, ow, oh;
1846 
1847    e = event_info;
1848    sd = data;
1849    if (!sd->engine_instance) return;
1850    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1851    evas_object_image_size_get(obj, &iw, &ih);
1852    if ((iw < 1) || (ih < 1)) return;
1853    x = (((int)e->cur.canvas.x - ox) * iw) / ow;
1854    y = (((int)e->cur.canvas.y - oy) * ih) / oh;
1855    emotion_engine_instance_event_mouse_move_feed(sd->engine_instance, x, y);
1856 }
1857 
1858 static void
_mouse_down(void * data,Evas * ev EINA_UNUSED,Evas_Object * obj,void * event_info)1859 _mouse_down(void *data, Evas *ev EINA_UNUSED, Evas_Object *obj, void *event_info)
1860 {
1861    Evas_Event_Mouse_Down *e;
1862    Efl_Canvas_Video_Data *sd;
1863    int x, y, iw, ih;
1864    Evas_Coord ox, oy, ow, oh;
1865 
1866    e = event_info;
1867    sd = data;
1868    if (!sd->engine_instance) return;
1869    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1870    evas_object_image_size_get(obj, &iw, &ih);
1871    if ((iw < 1) || (ih < 1)) return;
1872    x = (((int)e->canvas.x - ox) * iw) / ow;
1873    y = (((int)e->canvas.y - oy) * ih) / oh;
1874    emotion_engine_instance_event_mouse_button_feed(sd->engine_instance, 1, x, y);
1875 }
1876 
1877 static void
_pos_set_job(void * data)1878 _pos_set_job(void *data)
1879 {
1880    Evas_Object *obj;
1881    Efl_Canvas_Video_Data *sd;
1882 
1883    obj = data;
1884    E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME);
1885    sd->job = NULL;
1886    if (!sd->engine_instance) return;
1887    if (sd->seeking) return;
1888    if (sd->seek)
1889      {
1890         sd->seeking = 1;
1891         emotion_engine_instance_pos_set(sd->engine_instance, sd->seek_pos);
1892         sd->seek = 0;
1893      }
1894 }
1895 
1896 /* called by evas when it needs pixels for the image object */
1897 static void
_pixels_get(void * data,Evas_Object * obj)1898 _pixels_get(void *data, Evas_Object *obj)
1899 {
1900    int iw, ih, w, h;
1901    Efl_Canvas_Video_Data *sd;
1902    Emotion_Format format;
1903    unsigned char *bgra_data;
1904 
1905    sd = data;
1906    if (!sd->engine_instance) return;
1907    emotion_engine_instance_video_data_size_get(sd->engine_instance, &w, &h);
1908    w = (w >> 1) << 1;
1909    h = (h >> 1) << 1;
1910 
1911    evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL);
1912    evas_object_image_alpha_set(obj, 0);
1913    evas_object_image_size_set(obj, w, h);
1914    iw = w;
1915    ih = h;
1916 
1917    if ((iw <= 1) || (ih <= 1))
1918      {
1919         _emotion_image_data_zero(sd->obj);
1920         evas_object_image_pixels_dirty_set(obj, 0);
1921      }
1922    else
1923      {
1924         format = emotion_engine_instance_format_get(sd->engine_instance);
1925         if ((format == EMOTION_FORMAT_YV12) || (format == EMOTION_FORMAT_I420))
1926           {
1927              unsigned char **rows;
1928 
1929              evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_YCBCR422P601_PL);
1930              rows = evas_object_image_data_get(obj, 1);
1931              if (rows)
1932                {
1933                   if (emotion_engine_instance_yuv_rows_get(sd->engine_instance, iw, ih,
1934                                                            rows,
1935                                                            &rows[ih],
1936                                                            &rows[ih + (ih / 2)]))
1937                   evas_object_image_data_update_add(obj, 0, 0, iw, ih);
1938                }
1939              evas_object_image_data_set(obj, rows);
1940              evas_object_image_pixels_dirty_set(obj, 0);
1941           }
1942         else if (format == EMOTION_FORMAT_BGRA)
1943           {
1944              evas_object_image_colorspace_set(obj, EVAS_COLORSPACE_ARGB8888);
1945              if (emotion_engine_instance_bgra_data_get(sd->engine_instance, &bgra_data))
1946                {
1947                   evas_object_image_data_set(obj, bgra_data);
1948                   evas_object_image_pixels_dirty_set(obj, 0);
1949                }
1950           }
1951      }
1952 }
1953 
1954 /*******************************************/
1955 /* Internal smart object required routines */
1956 /*******************************************/
1957 
1958 EOLIAN static void
_efl_canvas_video_efl_canvas_group_group_add(Evas_Object * obj,Efl_Canvas_Video_Data * sd)1959 _efl_canvas_video_efl_canvas_group_group_add(Evas_Object *obj, Efl_Canvas_Video_Data *sd)
1960 {
1961    Emotion_Xattr_Data *xattr;
1962    unsigned int *pixel;
1963 
1964    /* TODO: remove legacy: emotion used to have no init, call automatically */
1965    emotion_init();
1966 
1967    efl_canvas_group_add(efl_super(obj, MY_CLASS));
1968 
1969    sd->state = EMOTION_WAKEUP;
1970    sd->obj = evas_object_image_add(evas_object_evas_get(obj));
1971    sd->bg = evas_object_rectangle_add(evas_object_evas_get(obj));
1972    sd->engine = eina_stringshare_add("gstreamer1");
1973    evas_object_color_set(sd->bg, 0, 0, 0, 0);
1974    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, sd);
1975    evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, sd);
1976    evas_object_image_pixels_get_callback_set(sd->obj, _pixels_get, sd);
1977    evas_object_smart_member_add(sd->obj, obj);
1978    evas_object_smart_member_add(sd->bg, obj);
1979    evas_object_lower(sd->bg);
1980    sd->ratio = 1.0;
1981    sd->spu.button = -1;
1982    sd->fill.w = -1;
1983    sd->fill.h = -1;
1984    evas_object_image_alpha_set(sd->obj, 0);
1985    pixel = evas_object_image_data_get(sd->obj, 1);
1986    if (pixel)
1987      {
1988         *pixel = 0xff000000;
1989         evas_object_image_data_set(obj, pixel);
1990      }
1991    evas_object_show(sd->obj);
1992    evas_object_show(sd->bg);
1993 
1994    xattr = calloc(1, sizeof(*xattr));
1995    EINA_REFCOUNT_INIT(xattr);
1996    efl_wref_add(obj, &xattr->obj_wref);
1997    sd->xattr = xattr;
1998 }
1999 
2000 EOLIAN static void
_efl_canvas_video_efl_canvas_group_group_del(Evas_Object * obj EINA_UNUSED,Efl_Canvas_Video_Data * sd)2001 _efl_canvas_video_efl_canvas_group_group_del(Evas_Object *obj EINA_UNUSED, Efl_Canvas_Video_Data *sd)
2002 {
2003    if (sd->engine_instance)
2004      {
2005         emotion_engine_instance_file_close(sd->engine_instance);
2006         emotion_engine_instance_del(sd->engine_instance);
2007      }
2008    sd->engine_instance = NULL;
2009    if (sd->job) ecore_job_del(sd->job);
2010    sd->job = NULL;
2011    if (sd->anim) ecore_animator_del(sd->anim);
2012    sd->anim = NULL;
2013    eina_stringshare_del(sd->file);
2014    eina_stringshare_del(sd->progress.info);
2015    eina_stringshare_del(sd->ref.file);
2016    sd->file = NULL;
2017    sd->progress.info = NULL;
2018    sd->ref.file = NULL;
2019    _xattr_data_unref(sd->xattr);
2020    efl_canvas_group_del(efl_super(obj, MY_CLASS));
2021    emotion_shutdown();
2022 }
2023 
2024 EOLIAN static void
_efl_canvas_video_efl_gfx_entity_position_set(Evas_Object * obj,Efl_Canvas_Video_Data * sd,Eina_Position2D pos)2025 _efl_canvas_video_efl_gfx_entity_position_set(Evas_Object *obj, Efl_Canvas_Video_Data *sd, Eina_Position2D pos)
2026 {
2027    Eina_Size2D sz;
2028 
2029    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
2030      return;
2031 
2032    efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
2033 
2034    sz = efl_gfx_entity_size_get(obj);
2035    _clipper_position_size_update(obj, pos.x, pos.y, sz.w, sz.h, sd->video.w, sd->video.h);
2036 }
2037 
2038 EOLIAN static void
_efl_canvas_video_efl_gfx_entity_size_set(Evas_Object * obj,Efl_Canvas_Video_Data * sd,Eina_Size2D sz)2039 _efl_canvas_video_efl_gfx_entity_size_set(Evas_Object *obj, Efl_Canvas_Video_Data *sd, Eina_Size2D sz)
2040 {
2041    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
2042      return;
2043 
2044    efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
2045 
2046    _efl_canvas_video_aspect_border_apply(obj, sd, sz.w, sz.h);
2047    evas_object_resize(sd->bg, sz.w, sz.h);
2048 }
2049 
2050 /* Internal EO APIs and hidden overrides */
2051 
2052 #define EFL_CANVAS_VIDEO_EXTRA_OPS \
2053    EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_canvas_video)
2054 
2055 
2056 #include "efl_canvas_video.eo.c"
2057 #include "efl_canvas_video_eo.legacy.c"
2058