1 #include <Elementary.h>
8 /* TODO: add buffering support to Emotion and display buffering progression in the theme when needed */
10 typedef struct _Widget_Data Widget_Data;
19 Eina_Bool remember : 1;
23 static const char *widtype = NULL;
25 static const Evas_Smart_Cb_Description _signals[] = {
29 static void _del_hook(Evas_Object *obj);
30 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
31 static void _theme_hook(Evas_Object *obj);
32 static void _sizing_eval(Evas_Object *obj);
33 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
34 static void _on_focus_hook(void *data, Evas_Object *obj);
35 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
36 Evas_Callback_Type type, void *event_info);
39 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
41 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
42 Evas_Event_Key_Down *ev = event_info;
43 Widget_Data *wd = elm_widget_data_get(obj);
44 if (!wd) return EINA_FALSE;
45 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
46 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
47 if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
51 current = elm_video_play_position_get(obj);
52 last = elm_video_play_length_get(obj);
56 current += last / 100;
57 elm_video_play_position_set(obj, current);
60 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
63 if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
67 current = elm_video_play_position_get(obj);
68 last = elm_video_play_length_get(obj);
72 current -= last / 100;
73 if (current < 0) current = 0;
74 elm_video_play_position_set(obj, current);
77 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
80 if (!strcmp(ev->keyname, "space"))
82 if (elm_video_is_playing_get(obj))
86 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
89 fprintf(stderr, "keyname: '%s' not handle\n", ev->keyname);
94 _del_hook(Evas_Object *obj)
96 Widget_Data *wd = elm_widget_data_get(obj);
99 if (wd->timer) ecore_timer_del(wd->timer);
104 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
106 Widget_Data *wd = elm_widget_data_get(obj);
108 if (elm_widget_focus_get(obj))
110 edje_object_signal_emit(wd->layout, "elm,action,focus", "elm");
111 evas_object_focus_set(wd->layout, EINA_TRUE);
115 edje_object_signal_emit(wd->layout, "elm,action,unfocus", "elm");
116 evas_object_focus_set(wd->layout, EINA_FALSE);
121 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
123 Widget_Data *wd = elm_widget_data_get(obj);
125 edje_object_mirrored_set(wd->layout, rtl);
129 _theme_hook(Evas_Object *obj)
131 Widget_Data *wd = elm_widget_data_get(obj);
133 _elm_widget_mirrored_reload(obj);
134 _mirrored_set(obj, elm_widget_mirrored_get(obj));
135 _elm_theme_object_set(obj, wd->layout, "video", "base", elm_widget_style_get(obj));
136 edje_object_scale_set(wd->layout, elm_widget_scale_get(obj) *
142 _sizing_eval(Evas_Object *obj)
144 Widget_Data *wd = elm_widget_data_get(obj);
145 Evas_Coord minw = -1, minh = -1;
149 evas_object_size_hint_request_get(wd->emotion, &minw, &minh);
150 evas_object_size_hint_aspect_set(wd->emotion, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
151 edje_object_size_min_calc(wd->layout, &w, &h);
153 if (w != 0 && h != 0)
158 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
162 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
168 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
170 Widget_Data *wd = elm_widget_data_get(obj);
172 if (wd->remember) emotion_object_last_position_save(wd->emotion);
176 _open_done(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
178 Widget_Data *wd = elm_widget_data_get(data);
180 edje_object_signal_emit(wd->layout, "elm,video,open", "elm");
184 _playback_started(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
186 Widget_Data *wd = elm_widget_data_get(data);
188 edje_object_signal_emit(wd->layout, "elm,video,play", "elm");
192 _playback_finished(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
194 Widget_Data *wd = elm_widget_data_get(data);
196 edje_object_signal_emit(wd->layout, "elm,video,end", "elm");
200 _update_aspect_ratio(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
206 _title_change(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
208 Widget_Data *wd = elm_widget_data_get(data);
211 title = emotion_object_title_get(wd->emotion);
212 edje_object_part_text_set(wd->layout, "elm,title", title);
213 edje_object_signal_emit(wd->layout, "elm,video,title", "elm");
217 _audio_level_change(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
223 _suspend_cb(void *data)
225 Widget_Data *wd = elm_widget_data_get(data);
228 interval = ecore_timer_interval_get(wd->timer);
230 emotion_object_suspend_set(wd->emotion, EMOTION_SLEEP);
231 else if (interval <= 30)
232 emotion_object_suspend_set(wd->emotion, EMOTION_DEEP_SLEEP);
235 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
237 return ECORE_CALLBACK_CANCEL;
240 ecore_timer_interval_set(wd->timer, interval + 10);
241 return ECORE_CALLBACK_RENEW;
246 _elm_video_check(Evas_Object *video)
249 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
258 elm_video_add(Evas_Object *parent)
265 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
266 ELM_SET_WIDTYPE(widtype, "video");
267 elm_widget_type_set(obj, "video");
268 elm_widget_sub_object_add(parent, obj);
269 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
270 elm_widget_data_set(obj, wd);
271 elm_widget_del_hook_set(obj, _del_hook);
272 elm_widget_theme_hook_set(obj, _theme_hook);
273 elm_widget_can_focus_set(obj, EINA_TRUE);
274 elm_widget_event_hook_set(obj, _event_hook);
276 wd->stop = EINA_FALSE;
277 wd->remember = EINA_FALSE;
279 wd->layout = edje_object_add(e);
280 _elm_theme_object_set(obj, wd->layout, "video", "base", "default");
281 elm_widget_resize_object_set(obj, wd->layout);
282 evas_object_show(wd->layout);
283 evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
285 wd->emotion = emotion_object_add(e);
286 emotion_object_init(wd->emotion, NULL);
287 elm_widget_sub_object_add(obj, wd->emotion);
288 edje_object_part_swallow(wd->layout, "elm.swallow.video", wd->emotion);
290 evas_object_smart_callback_add(wd->emotion, "open_done", _open_done, obj);
291 evas_object_smart_callback_add(wd->emotion, "playback_started", _playback_started, obj);
292 evas_object_smart_callback_add(wd->emotion, "playback_finished", _playback_finished, obj);
293 evas_object_smart_callback_add(wd->emotion, "frame_resize", _update_aspect_ratio, obj);
294 evas_object_smart_callback_add(wd->emotion, "title_change", _title_change, obj);
295 evas_object_smart_callback_add(wd->emotion, "audio_level_change", _audio_level_change, obj);
297 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
298 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, NULL);
299 evas_object_smart_callbacks_descriptions_set(obj, _signals);
301 _mirrored_set(obj, elm_widget_mirrored_get(obj));
304 wd->timer = ecore_timer_add(20.0, _suspend_cb, obj);
314 elm_video_file_set(Evas_Object *video, const char *filename)
317 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
318 Widget_Data *wd = elm_widget_data_get(video);
320 if (wd->remember) emotion_object_last_position_save(wd->emotion);
321 wd->stop = EINA_FALSE;
322 if (!emotion_object_file_set(wd->emotion, filename)) return EINA_FALSE;
324 if ((!strncmp(filename, "file://", 7)) || (!strstr(filename, "://")))
325 emotion_object_last_position_load(wd->emotion);
327 edje_object_signal_emit(wd->layout, "elm,video,load", "elm");
339 elm_video_emotion_get(const Evas_Object *video)
342 ELM_CHECK_WIDTYPE(video, widtype) NULL;
343 Widget_Data *wd = elm_widget_data_get(video);
353 elm_video_play(Evas_Object *video)
356 ELM_CHECK_WIDTYPE(video, widtype);
357 Widget_Data *wd = elm_widget_data_get(video);
359 if (emotion_object_play_get(wd->emotion)) return ;
361 if (wd->timer) ecore_timer_del(wd->timer);
363 wd->stop = EINA_FALSE;
364 emotion_object_play_set(wd->emotion, EINA_TRUE);
370 /* FIXME: pause will setup timer and go into sleep or
371 * hibernate after a while without activity.
375 elm_video_pause(Evas_Object *video)
378 ELM_CHECK_WIDTYPE(video, widtype);
379 Widget_Data *wd = elm_widget_data_get(video);
381 if (!emotion_object_play_get(wd->emotion)) return ;
383 if (!wd->timer) wd->timer = ecore_timer_add(20.0, _suspend_cb, video);
384 emotion_object_play_set(wd->emotion, EINA_FALSE);
385 edje_object_signal_emit(wd->layout, "elm,video,pause", "elm");
391 /* FIXME: stop should go into hibernate state directly.
394 elm_video_stop(Evas_Object *video)
397 ELM_CHECK_WIDTYPE(video, widtype);
398 Widget_Data *wd = elm_widget_data_get(video);
400 if (!emotion_object_play_get(wd->emotion) && wd->stop) return ;
402 if (wd->timer) ecore_timer_del(wd->timer);
404 wd->stop = EINA_TRUE;
405 emotion_object_play_set(wd->emotion, EINA_FALSE);
406 edje_object_signal_emit(wd->layout, "elm,video,stop", "elm");
407 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
414 elm_video_is_playing_get(const Evas_Object *video)
417 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
418 Widget_Data *wd = elm_widget_data_get(video);
420 return emotion_object_play_get(wd->emotion);
428 elm_video_is_seekable_get(const Evas_Object *video)
431 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
432 Widget_Data *wd = elm_widget_data_get(video);
434 return emotion_object_seekable_get(wd->emotion);
442 elm_video_audio_mute_get(const Evas_Object *video)
445 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
446 Widget_Data *wd = elm_widget_data_get(video);
448 return emotion_object_audio_mute_get(wd->emotion);
456 elm_video_audio_mute_set(Evas_Object *video, Eina_Bool mute)
459 ELM_CHECK_WIDTYPE(video, widtype);
460 Widget_Data *wd = elm_widget_data_get(video);
462 emotion_object_audio_mute_set(wd->emotion, mute);
470 elm_video_audio_level_get(const Evas_Object *video)
473 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
474 Widget_Data *wd = elm_widget_data_get(video);
476 return emotion_object_audio_volume_get(wd->emotion);
484 elm_video_audio_level_set(Evas_Object *video, double volume)
487 ELM_CHECK_WIDTYPE(video, widtype);
488 Widget_Data *wd = elm_widget_data_get(video);
490 emotion_object_audio_volume_set(wd->emotion, volume);
498 elm_video_play_position_get(const Evas_Object *video)
501 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
502 Widget_Data *wd = elm_widget_data_get(video);
504 return emotion_object_position_get(wd->emotion);
512 elm_video_play_position_set(Evas_Object *video, double position)
515 ELM_CHECK_WIDTYPE(video, widtype);
516 Widget_Data *wd = elm_widget_data_get(video);
518 emotion_object_position_set(wd->emotion, position);
526 elm_video_play_length_get(const Evas_Object *video)
529 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
530 Widget_Data *wd = elm_widget_data_get(video);
532 return emotion_object_play_length_get(wd->emotion);
540 elm_video_title_get(const Evas_Object *video)
543 ELM_CHECK_WIDTYPE(video, widtype) NULL;
544 Widget_Data *wd = elm_widget_data_get(video);
546 return emotion_object_title_get(wd->emotion);
554 elm_video_remember_position_set(Evas_Object *video, Eina_Bool remember)
557 ELM_CHECK_WIDTYPE(video, widtype);
558 Widget_Data *wd = elm_widget_data_get(video);
560 wd->remember = remember;
568 elm_video_remember_position_get(const Evas_Object *video)
571 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
572 Widget_Data *wd = elm_widget_data_get(video);