2a2e8860db6527be495dfbd7fda776c344b21f11
[framework/uifw/elementary.git] / src / lib / elc_player.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #ifdef HAVE_EMOTION
5 # include <Emotion.h>
6 #endif
7
8 typedef struct _Widget_Data Widget_Data;
9 struct _Widget_Data
10 {
11    Evas_Object *layout;
12    Evas_Object *video;
13    Evas_Object *emotion;
14
15    Evas_Object *forward;
16    Evas_Object *info;
17    Evas_Object *next;
18    Evas_Object *pause;
19    Evas_Object *play;
20    Evas_Object *prev;
21    Evas_Object *rewind;
22    Evas_Object *stop;
23
24    Evas_Object *slider;
25 };
26
27 #ifdef HAVE_EMOTION
28 static const char *widtype = NULL;
29
30 static const char SIG_FORWARD_CLICKED[] = "forward,clicked";
31 static const char SIG_INFO_CLICKED[] = "info,clicked";
32 static const char SIG_NEXT_CLICKED[] = "next,clicked";
33 static const char SIG_PAUSE_CLICKED[] = "pause,clicked";
34 static const char SIG_PLAY_CLICKED[] = "play,clicked";
35 static const char SIG_PREV_CLICKED[] = "prev,clicked";
36 static const char SIG_REWIND_CLICKED[] = "rewind,clicked";
37 static const char SIG_STOP_CLICKED[] = "stop,clicked";
38
39 static const Evas_Smart_Cb_Description _signals[] = {
40   { SIG_FORWARD_CLICKED, "" },
41   { SIG_INFO_CLICKED, "" },
42   { SIG_NEXT_CLICKED, "" },
43   { SIG_PAUSE_CLICKED, "" },
44   { SIG_PLAY_CLICKED, "" },
45   { SIG_PREV_CLICKED, "" },
46   { SIG_REWIND_CLICKED, "" },
47   { SIG_STOP_CLICKED, "" },
48   { NULL, NULL }
49 };
50
51 static void _del_hook(Evas_Object *obj);
52 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
53 static void _theme_hook(Evas_Object *obj);
54 static void _sizing_eval(Evas_Object *obj);
55 static void _on_focus_hook(void *data, Evas_Object *obj);
56 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
57                              Evas_Callback_Type type, void *event_info);
58
59 static Eina_Bool
60 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
61 {
62    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
63    Evas_Event_Key_Down *ev = event_info;
64    Widget_Data *wd = elm_widget_data_get(obj);
65    if (!wd) return EINA_FALSE;
66    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
67    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
68    if (!wd->video) return EINA_FALSE;
69    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
70      {
71         double current, last;
72
73         current = elm_video_play_position_get(wd->video);
74         last = elm_video_play_length_get(wd->video);
75
76         if (current < last)
77           {
78              current += last / 100;
79              elm_video_play_position_set(wd->video, current);
80           }
81
82         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
83         return EINA_TRUE;
84      }
85    if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
86      {
87         double current, last;
88
89         current = elm_video_play_position_get(wd->video);
90         last = elm_video_play_length_get(wd->video);
91
92         if (current > 0)
93           {
94              current -= last / 100;
95              if (current < 0) current = 0;
96              elm_video_play_position_set(wd->video, current);
97           }
98
99         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
100         return EINA_TRUE;
101      }
102    if (!strcmp(ev->keyname, "space"))
103      {
104 <<<<<<< HEAD
105         if (elm_video_is_playing(wd->video))
106 =======
107         if (elm_video_is_playing_get(wd->video))
108 >>>>>>> remotes/origin/upstream
109           elm_video_pause(wd->video);
110         else
111           elm_video_play(wd->video);
112         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
113         return EINA_TRUE;
114      }
115    fprintf(stderr, "keyname: '%s' not handle\n", ev->keyname);
116    return EINA_FALSE;
117 }
118
119 static void
120 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
121 {
122    Widget_Data *wd = elm_widget_data_get(obj);
123    if (!wd) return;
124    if (elm_widget_focus_get(obj))
125      {
126         edje_object_signal_emit(wd->layout, "elm,action,focus", "elm");
127         evas_object_focus_set(wd->layout, EINA_TRUE);
128      }
129    else
130      {
131         edje_object_signal_emit(wd->layout, "elm,action,unfocus", "elm");
132         evas_object_focus_set(wd->layout, EINA_FALSE);
133      }
134 }
135
136 static void
137 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
138 {
139    Widget_Data *wd = elm_widget_data_get(obj);
140    if (!wd) return;
141    edje_object_mirrored_set(wd->layout, rtl);
142 }
143
144 static void
145 _theme_hook(Evas_Object *obj)
146 {
147    Widget_Data *wd = elm_widget_data_get(obj);
148    if (!wd) return;
149    _elm_widget_mirrored_reload(obj);
150    _mirrored_set(obj, elm_widget_mirrored_get(obj));
151    _elm_theme_object_set(obj, wd->layout, "video", "base", elm_widget_style_get(obj));
152    edje_object_scale_set(wd->layout, elm_widget_scale_get(obj) *
153                          _elm_config->scale);
154
155 #define UPDATE_THEME(Obj, Target, Layout, Name)                         \
156    if (Target)                                                          \
157      {                                                                  \
158         elm_object_style_set(Target, elm_widget_style_get(Obj));        \
159         if (!edje_object_part_swallow(Layout, Name, Target))            \
160           evas_object_hide(Target);                                     \
161         elm_object_disabled_set(Target, elm_widget_disabled_get(Obj));  \
162      }
163
164    UPDATE_THEME(obj, wd->forward, wd->layout, "media_player/forward");
165    UPDATE_THEME(obj, wd->info, wd->layout, "media_player/info");
166    UPDATE_THEME(obj, wd->next, wd->layout, "media_player/next");
167    UPDATE_THEME(obj, wd->pause, wd->layout, "media_player/pause");
168    UPDATE_THEME(obj, wd->play, wd->layout, "media_player/play");
169    UPDATE_THEME(obj, wd->prev, wd->layout, "media_player/prev");
170    UPDATE_THEME(obj, wd->rewind, wd->layout, "media_player/rewind");
171    UPDATE_THEME(obj, wd->next, wd->layout, "media_player/next");
172    UPDATE_THEME(obj, wd->slider, wd->layout, "media_player/slider");
173
174    _sizing_eval(obj);
175 }
176
177 static void
178 _sizing_eval(Evas_Object *obj)
179 {
180    Widget_Data *wd = elm_widget_data_get(obj);
181    Evas_Coord w, h;
182
183    if (!wd) return;
184    edje_object_size_min_get(wd->layout, &w, &h);
185    edje_object_size_min_restricted_calc(wd->layout, &w, &h, w, h);
186    evas_object_size_hint_min_set(obj, w, h);
187 }
188
189 static void
190 _update_slider(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
191 {
192    Evas_Object *player = data;
193    Widget_Data *wd = elm_widget_data_get(player);
194    double pos, length;
195    Eina_Bool seekable;
196
197    if (!wd) return ;
198 <<<<<<< HEAD
199    seekable = elm_video_is_seekable(wd->video);
200 =======
201    seekable = elm_video_is_seekable_get(wd->video);
202 >>>>>>> remotes/origin/upstream
203    length = elm_video_play_length_get(wd->video);
204    pos = elm_video_play_position_get(wd->video);
205
206    elm_object_disabled_set(wd->slider, !seekable);
207    elm_slider_min_max_set(wd->slider, 0, length);
208    elm_slider_value_set(wd->slider, pos);
209 }
210
211 static void
212 _update_position(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
213 {
214    Evas_Object *player = data;
215    Widget_Data *wd = elm_widget_data_get(player);
216
217    if (!wd) return ;
218    elm_video_play_position_set(wd->video, elm_slider_value_get(wd->slider));
219 }
220
221 static void
222 _forward(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
223 {
224    Evas_Object *player = data;
225    Widget_Data *wd = elm_widget_data_get(player);
226    double pos, length;
227
228    if (!wd) return ;
229
230    pos = elm_video_play_position_get(wd->video);
231    length = elm_video_play_length_get(wd->video);
232
233    pos += length * 0.3;
234    elm_video_play_position_set(wd->video, pos);
235
236    edje_object_signal_emit(wd->layout, "elm,button,forward", "elm");
237    evas_object_smart_callback_call(player, SIG_FORWARD_CLICKED, NULL);
238 }
239
240 static void
241 _info(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
242 {
243    Evas_Object *player = data;
244    Widget_Data *wd = elm_widget_data_get(player);
245
246    if (!wd) return ;
247
248    edje_object_signal_emit(wd->layout, "elm,button,info", "elm");
249    evas_object_smart_callback_call(player, SIG_INFO_CLICKED, NULL);
250 }
251
252 static void
253 _next(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
254 {
255    Evas_Object *player = data;
256    Widget_Data *wd = elm_widget_data_get(player);
257    double pos, length;
258
259    if (!wd) return ;
260
261    pos = elm_video_play_position_get(wd->video);
262    length = elm_video_play_length_get(wd->video);
263
264    pos += length * 0.1;
265    elm_video_play_position_set(wd->video, pos);
266
267    edje_object_signal_emit(wd->layout, "elm,button,next", "elm");
268    evas_object_smart_callback_call(player, SIG_NEXT_CLICKED, NULL);
269 }
270
271 static void
272 _pause(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
273 {
274    Evas_Object *player = data;
275    Widget_Data *wd = elm_widget_data_get(player);
276
277    if (!wd) return ;
278
279    edje_object_signal_emit(wd->layout, "elm,player,pause", "elm");
280    elm_video_pause(wd->video);
281
282    edje_object_signal_emit(wd->layout, "elm,button,pause", "elm");
283    evas_object_smart_callback_call(player, SIG_PAUSE_CLICKED, NULL);
284 }
285
286 static void
287 _play(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
288 {
289    Evas_Object *player = data;
290    Widget_Data *wd = elm_widget_data_get(player);
291
292    if (!wd) return ;
293    elm_video_play(wd->video);
294    edje_object_signal_emit(wd->layout, "elm,button,play", "elm");
295    evas_object_smart_callback_call(player, SIG_PLAY_CLICKED, NULL);
296 }
297
298 static void
299 _prev(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
300 {
301    Evas_Object *player = data;
302    Widget_Data *wd = elm_widget_data_get(player);
303    double pos, length;
304
305    if (!wd) return ;
306
307    pos = elm_video_play_position_get(wd->video);
308    length = elm_video_play_length_get(wd->video);
309
310    pos -= length * 0.1;
311    elm_video_play_position_set(wd->video, pos);
312    evas_object_smart_callback_call(player, SIG_PREV_CLICKED, NULL);
313    edje_object_signal_emit(wd->layout, "elm,button,prev", "elm");
314 }
315
316 static void
317 _rewind(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
318 {
319    Evas_Object *player = data;
320    Widget_Data *wd = elm_widget_data_get(player);
321
322    if (!wd) return ;
323    elm_video_play_position_set(wd->video, 0);
324    edje_object_signal_emit(wd->layout, "elm,button,rewind", "elm");
325    evas_object_smart_callback_call(player, SIG_REWIND_CLICKED, NULL);
326 }
327
328 static void
329 _stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
330 {
331    Evas_Object *player = data;
332    Widget_Data *wd = elm_widget_data_get(player);
333
334    if (!wd) return ;
335
336    edje_object_signal_emit(wd->layout, "elm,button,stop", "elm");
337    evas_object_smart_callback_call(player, SIG_STOP_CLICKED, NULL);
338 }
339
340 static void
341 _play_started(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
342 {
343    Evas_Object *player = data;
344    Widget_Data *wd = elm_widget_data_get(player);
345
346    if (!wd) return ;
347
348    edje_object_signal_emit(wd->layout, "elm,player,play", "elm");
349 }
350
351 static void
352 _play_finished(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
353 {
354    Evas_Object *player = data;
355    Widget_Data *wd = elm_widget_data_get(player);
356
357    if (!wd) return ;
358
359    edje_object_signal_emit(wd->layout, "elm,player,pause", "elm");
360 }
361
362 static void
363 _cleanup_callback(Widget_Data *wd)
364 {
365    if (!wd || !wd->emotion) return;
366
367    evas_object_smart_callback_del(wd->emotion, "frame_decode",
368                                   _update_slider);
369    evas_object_smart_callback_del(wd->emotion, "frame_resize",
370                                   _update_slider);
371    evas_object_smart_callback_del(wd->emotion, "length_change",
372                                   _update_slider);
373    evas_object_smart_callback_del(wd->emotion, "position_update",
374                                   _update_slider);
375    evas_object_smart_callback_del(wd->emotion, "playback_started",
376                                   _play_started);
377    evas_object_smart_callback_del(wd->emotion, "playback_finished",
378                                   _play_finished);
379    elm_object_disabled_set(wd->slider, EINA_TRUE);
380    elm_object_disabled_set(wd->forward, EINA_TRUE);
381    elm_object_disabled_set(wd->info, EINA_TRUE);
382    elm_object_disabled_set(wd->next, EINA_TRUE);
383    elm_object_disabled_set(wd->pause, EINA_TRUE);
384    elm_object_disabled_set(wd->play, EINA_TRUE);
385    elm_object_disabled_set(wd->prev, EINA_TRUE);
386    elm_object_disabled_set(wd->rewind, EINA_TRUE);
387    elm_object_disabled_set(wd->next, EINA_TRUE);
388    wd->video = NULL;
389    wd->emotion = NULL;
390 }
391
392 static void
393 _track_video(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
394 {
395    _cleanup_callback(data);
396 }
397
398 static void
399 _del_hook(Evas_Object *obj)
400 {
401    Widget_Data *wd = elm_widget_data_get(obj);
402
403    if (!wd) return;
404    evas_object_smart_callback_del(wd->forward, "clicked", _forward);
405    evas_object_smart_callback_del(wd->info, "clicked", _info);
406    evas_object_smart_callback_del(wd->next, "clicked", _next);
407    evas_object_smart_callback_del(wd->pause, "clicked", _pause);
408    evas_object_smart_callback_del(wd->play, "clicked", _play);
409    evas_object_smart_callback_del(wd->prev,  "clicked", _prev);
410    evas_object_smart_callback_del(wd->rewind, "clicked", _rewind);
411    evas_object_smart_callback_del(wd->next, "clicked", _next);
412    _cleanup_callback(wd);
413    free(wd);
414 }
415
416 static Evas_Object *
417 _player_button_add(Evas_Object *parent, Evas_Object *obj, Evas_Object *layout, const char *name, Evas_Smart_Cb func)
418 {
419    Evas_Object *ic;
420    Evas_Object *bt;
421
422    ic = elm_icon_add(parent);
423    elm_icon_standard_set(ic, name);
424    evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
425    bt = elm_button_add(parent);
426    elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
427    elm_object_part_content_set(bt, "icon", ic);
428    evas_object_size_hint_align_set(bt, 0.0, 0.0);
429    elm_object_style_set(bt, "anchor");
430    evas_object_smart_callback_add(bt, "clicked", func, obj);
431    elm_widget_sub_object_add(obj, bt);
432
433    if (!edje_object_part_swallow(layout, name, bt))
434      evas_object_hide(bt);
435    return bt;
436 }
437
438 static const char *
439 _double_to_time(double value)
440 {
441    char buf[256];
442    int ph, pm, ps, pf;
443
444    ph = value / 3600;
445    pm = value / 60 - (ph * 60);
446    ps = value - (pm * 60);
447    pf = value * 100 - (ps * 100) - (pm * 60 * 100) - (ph * 60 * 60 * 100);
448    if (ph)
449      snprintf(buf, sizeof(buf), "%i:%02i:%02i.%02i",
450               ph, pm, ps, pf);
451    else if (pm)
452      snprintf(buf, sizeof(buf), "%02i:%02i.%02i",
453               pm, ps, pf);
454    else
455      snprintf(buf, sizeof(buf), "%02i.%02i",
456               ps, pf);
457
458    return eina_stringshare_add(buf);
459 }
460 #endif
461
462 static void
463 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
464 {
465    if (part && strcmp(part, "video")) return;
466 #ifdef HAVE_EMOTION
467    ELM_CHECK_WIDTYPE(obj, widtype);
468    Widget_Data *wd = elm_widget_data_get(obj);
469
470    double pos, length;
471    Eina_Bool seekable;
472
473    if (!_elm_video_check(content)) return;
474
475    _cleanup_callback(wd);
476
477    wd->video = content;
478
479    if (!wd->video)
480      {
481         wd->emotion = NULL;
482         return ;
483      }
484
485    elm_object_disabled_set(wd->slider, EINA_FALSE);
486    elm_object_disabled_set(wd->forward, EINA_FALSE);
487    elm_object_disabled_set(wd->info, EINA_FALSE);
488    elm_object_disabled_set(wd->next, EINA_FALSE);
489    elm_object_disabled_set(wd->pause, EINA_FALSE);
490    elm_object_disabled_set(wd->play, EINA_FALSE);
491    elm_object_disabled_set(wd->prev, EINA_FALSE);
492    elm_object_disabled_set(wd->rewind, EINA_FALSE);
493    elm_object_disabled_set(wd->next, EINA_FALSE);
494
495    wd->emotion = elm_video_emotion_get(wd->video);
496    emotion_object_priority_set(wd->emotion, EINA_TRUE);
497    evas_object_event_callback_add(wd->video, EVAS_CALLBACK_DEL,
498                                   _track_video, wd);
499
500 <<<<<<< HEAD
501    seekable = elm_video_is_seekable(wd->video);
502 =======
503    seekable = elm_video_is_seekable_get(wd->video);
504 >>>>>>> remotes/origin/upstream
505    length = elm_video_play_length_get(wd->video);
506    pos = elm_video_play_position_get(wd->video);
507
508    elm_object_disabled_set(wd->slider, !seekable);
509    elm_slider_min_max_set(wd->slider, 0, length);
510    elm_slider_value_set(wd->slider, pos);
511
512 <<<<<<< HEAD
513    if (elm_video_is_playing(wd->video)) edje_object_signal_emit(wd->layout, "elm,player,play", "elm");
514 =======
515    if (elm_video_is_playing_get(wd->video)) edje_object_signal_emit(wd->layout, "elm,player,play", "elm");
516 >>>>>>> remotes/origin/upstream
517    else edje_object_signal_emit(wd->layout, "elm,player,pause", "elm");
518
519    evas_object_smart_callback_add(wd->emotion, "frame_decode",
520                                   _update_slider, obj);
521    evas_object_smart_callback_add(wd->emotion, "frame_resize",
522                                   _update_slider, obj);
523    evas_object_smart_callback_add(wd->emotion, "length_change",
524                                   _update_slider, obj);
525    evas_object_smart_callback_add(wd->emotion, "position_update",
526                                   _update_slider, obj);
527    evas_object_smart_callback_add(wd->emotion, "playback_started",
528                                   _play_started, obj);
529    evas_object_smart_callback_add(wd->emotion, "playback_finished",
530                                   _play_finished, obj);
531
532    /* FIXME: track info from video */
533 #else
534    (void) obj;
535    (void) content;
536 #endif
537
538 }
539
540 EAPI Evas_Object *
541 elm_player_add(Evas_Object *parent)
542 {
543 #ifdef HAVE_EMOTION
544    Evas_Object *obj;
545    Evas *e;
546    Widget_Data *wd;
547
548    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
549    ELM_SET_WIDTYPE(widtype, "player");
550    elm_widget_type_set(obj, "player");
551    elm_widget_sub_object_add(parent, obj);
552    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
553    elm_widget_data_set(obj, wd);
554    elm_widget_del_hook_set(obj, _del_hook);
555    elm_widget_theme_hook_set(obj, _theme_hook);
556    elm_widget_can_focus_set(obj, EINA_TRUE);
557    elm_widget_event_hook_set(obj, _event_hook);
558    elm_widget_content_set_hook_set(obj, _content_set_hook);
559
560    wd->layout = edje_object_add(e);
561    _elm_theme_object_set(obj, wd->layout, "player", "base", "default");
562    elm_widget_resize_object_set(obj, wd->layout);
563    elm_widget_sub_object_add(obj, wd->layout);
564    evas_object_show(wd->layout);
565    evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
566
567    wd->forward = _player_button_add(parent, obj, wd->layout, "media_player/forward", _forward);
568    wd->info = _player_button_add(parent, obj, wd->layout, "media_player/info", _info);
569    wd->next = _player_button_add(parent, obj, wd->layout, "media_player/next", _next);
570    wd->pause = _player_button_add(parent, obj, wd->layout, "media_player/pause", _pause);
571    wd->play = _player_button_add(parent, obj, wd->layout, "media_player/play", _play);
572    wd->prev = _player_button_add(parent, obj, wd->layout, "media_player/prev", _prev);
573    wd->rewind = _player_button_add(parent, obj, wd->layout, "media_player/rewind", _rewind);
574    wd->stop = _player_button_add(parent, obj, wd->layout, "media_player/stop", _stop);
575
576    wd->slider = elm_slider_add(parent);
577    elm_widget_sub_object_add(obj, wd->slider);
578    elm_slider_indicator_format_function_set(wd->slider, _double_to_time, eina_stringshare_del);
579    elm_slider_units_format_function_set(wd->slider, _double_to_time, eina_stringshare_del);
580    elm_slider_min_max_set(wd->slider, 0, 0);
581    elm_slider_value_set(wd->slider, 0);
582    elm_object_disabled_set(wd->slider, EINA_TRUE);
583    evas_object_size_hint_align_set(wd->slider, EVAS_HINT_FILL, 0.5);
584    evas_object_size_hint_weight_set(wd->slider, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
585    edje_object_part_swallow(wd->layout, "media_player/slider", wd->slider);
586    evas_object_smart_callback_add(wd->slider, "changed", _update_position, obj);
587
588    wd->emotion = NULL;
589    wd->video = NULL;
590
591    _mirrored_set(obj, elm_widget_mirrored_get(obj));
592    _sizing_eval(obj);
593
594    return obj;
595 #else
596    (void) parent;
597    return NULL;
598 #endif
599 }
600
601 EAPI void
602 elm_player_video_set(Evas_Object *player, Evas_Object *video)
603 {
604    _content_set_hook(player, "video", video);
605 }