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")) ||
48 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
52 current = elm_video_play_position_get(obj);
53 last = elm_video_play_length_get(obj);
57 current += last / 100;
58 elm_video_play_position_set(obj, current);
61 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
64 if ((!strcmp(ev->keyname, "Right")) ||
65 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
69 current = elm_video_play_position_get(obj);
70 last = elm_video_play_length_get(obj);
74 current -= last / 100;
75 if (current < 0) current = 0;
76 elm_video_play_position_set(obj, current);
79 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
82 if (!strcmp(ev->keyname, "space"))
84 if (elm_video_is_playing_get(obj))
88 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
91 fprintf(stderr, "keyname: '%s' not handle\n", ev->keyname);
96 _del_hook(Evas_Object *obj)
98 Widget_Data *wd = elm_widget_data_get(obj);
101 if (wd->timer) ecore_timer_del(wd->timer);
106 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
108 Widget_Data *wd = elm_widget_data_get(obj);
110 if (elm_widget_focus_get(obj))
112 edje_object_signal_emit(wd->layout, "elm,action,focus", "elm");
113 evas_object_focus_set(wd->layout, EINA_TRUE);
117 edje_object_signal_emit(wd->layout, "elm,action,unfocus", "elm");
118 evas_object_focus_set(wd->layout, EINA_FALSE);
123 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
125 Widget_Data *wd = elm_widget_data_get(obj);
127 edje_object_mirrored_set(wd->layout, rtl);
131 _theme_hook(Evas_Object *obj)
133 Widget_Data *wd = elm_widget_data_get(obj);
135 _elm_widget_mirrored_reload(obj);
136 _mirrored_set(obj, elm_widget_mirrored_get(obj));
137 _elm_theme_object_set(obj, wd->layout, "video", "base", elm_widget_style_get(obj));
138 edje_object_scale_set(wd->layout, elm_widget_scale_get(obj) *
144 _sizing_eval(Evas_Object *obj)
146 Widget_Data *wd = elm_widget_data_get(obj);
147 Evas_Coord minw = -1, minh = -1;
151 evas_object_size_hint_request_get(wd->emotion, &minw, &minh);
152 evas_object_size_hint_aspect_set(wd->emotion, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
153 edje_object_size_min_calc(wd->layout, &w, &h);
155 if (w != 0 && h != 0)
160 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
164 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
170 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
172 Widget_Data *wd = elm_widget_data_get(obj);
174 if (wd->remember) emotion_object_last_position_save(wd->emotion);
178 _open_done(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
180 Widget_Data *wd = elm_widget_data_get(data);
182 edje_object_signal_emit(wd->layout, "elm,video,open", "elm");
186 _playback_started(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
188 Widget_Data *wd = elm_widget_data_get(data);
190 edje_object_signal_emit(wd->layout, "elm,video,play", "elm");
194 _playback_finished(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
196 Widget_Data *wd = elm_widget_data_get(data);
198 edje_object_signal_emit(wd->layout, "elm,video,end", "elm");
202 _update_aspect_ratio(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
208 _title_change(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
210 Widget_Data *wd = elm_widget_data_get(data);
213 title = emotion_object_title_get(wd->emotion);
214 edje_object_part_text_set(wd->layout, "elm,title", title);
215 edje_object_signal_emit(wd->layout, "elm,video,title", "elm");
219 _audio_level_change(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
225 _suspend_cb(void *data)
227 Widget_Data *wd = elm_widget_data_get(data);
230 interval = ecore_timer_interval_get(wd->timer);
232 emotion_object_suspend_set(wd->emotion, EMOTION_SLEEP);
233 else if (interval <= 30)
234 emotion_object_suspend_set(wd->emotion, EMOTION_DEEP_SLEEP);
237 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
239 return ECORE_CALLBACK_CANCEL;
242 ecore_timer_interval_set(wd->timer, interval + 10);
243 return ECORE_CALLBACK_RENEW;
248 _elm_video_check(Evas_Object *video)
251 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
260 elm_video_add(Evas_Object *parent)
267 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
268 ELM_SET_WIDTYPE(widtype, "video");
269 elm_widget_type_set(obj, "video");
270 elm_widget_sub_object_add(parent, obj);
271 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
272 elm_widget_data_set(obj, wd);
273 elm_widget_del_hook_set(obj, _del_hook);
274 elm_widget_theme_hook_set(obj, _theme_hook);
275 elm_widget_can_focus_set(obj, EINA_TRUE);
276 elm_widget_event_hook_set(obj, _event_hook);
278 wd->stop = EINA_FALSE;
279 wd->remember = EINA_FALSE;
281 wd->layout = edje_object_add(e);
282 _elm_theme_object_set(obj, wd->layout, "video", "base", "default");
283 elm_widget_resize_object_set(obj, wd->layout);
284 evas_object_show(wd->layout);
285 evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
287 wd->emotion = emotion_object_add(e);
288 emotion_object_init(wd->emotion, NULL);
289 elm_widget_sub_object_add(obj, wd->emotion);
290 edje_object_part_swallow(wd->layout, "elm.swallow.video", wd->emotion);
292 evas_object_smart_callback_add(wd->emotion, "open_done", _open_done, obj);
293 evas_object_smart_callback_add(wd->emotion, "playback_started", _playback_started, obj);
294 evas_object_smart_callback_add(wd->emotion, "playback_finished", _playback_finished, obj);
295 evas_object_smart_callback_add(wd->emotion, "frame_resize", _update_aspect_ratio, obj);
296 evas_object_smart_callback_add(wd->emotion, "title_change", _title_change, obj);
297 evas_object_smart_callback_add(wd->emotion, "audio_level_change", _audio_level_change, obj);
299 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
300 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, NULL);
301 evas_object_smart_callbacks_descriptions_set(obj, _signals);
303 _mirrored_set(obj, elm_widget_mirrored_get(obj));
306 wd->timer = ecore_timer_add(20.0, _suspend_cb, obj);
316 elm_video_file_set(Evas_Object *video, const char *filename)
319 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
320 Widget_Data *wd = elm_widget_data_get(video);
322 if (wd->remember) emotion_object_last_position_save(wd->emotion);
323 wd->stop = EINA_FALSE;
324 if (!emotion_object_file_set(wd->emotion, filename)) return EINA_FALSE;
326 if ((!strncmp(filename, "file://", 7)) || (!strstr(filename, "://")))
327 emotion_object_last_position_load(wd->emotion);
329 edje_object_signal_emit(wd->layout, "elm,video,load", "elm");
341 elm_video_emotion_get(const Evas_Object *video)
344 ELM_CHECK_WIDTYPE(video, widtype) NULL;
345 Widget_Data *wd = elm_widget_data_get(video);
355 elm_video_play(Evas_Object *video)
358 ELM_CHECK_WIDTYPE(video, widtype);
359 Widget_Data *wd = elm_widget_data_get(video);
361 if (emotion_object_play_get(wd->emotion)) return ;
363 if (wd->timer) ecore_timer_del(wd->timer);
365 wd->stop = EINA_FALSE;
366 emotion_object_play_set(wd->emotion, EINA_TRUE);
372 /* FIXME: pause will setup timer and go into sleep or
373 * hibernate after a while without activity.
377 elm_video_pause(Evas_Object *video)
380 ELM_CHECK_WIDTYPE(video, widtype);
381 Widget_Data *wd = elm_widget_data_get(video);
383 if (!emotion_object_play_get(wd->emotion)) return ;
385 if (!wd->timer) wd->timer = ecore_timer_add(20.0, _suspend_cb, video);
386 emotion_object_play_set(wd->emotion, EINA_FALSE);
387 edje_object_signal_emit(wd->layout, "elm,video,pause", "elm");
393 /* FIXME: stop should go into hibernate state directly.
396 elm_video_stop(Evas_Object *video)
399 ELM_CHECK_WIDTYPE(video, widtype);
400 Widget_Data *wd = elm_widget_data_get(video);
402 if (!emotion_object_play_get(wd->emotion) && wd->stop) return ;
404 if (wd->timer) ecore_timer_del(wd->timer);
406 wd->stop = EINA_TRUE;
407 emotion_object_play_set(wd->emotion, EINA_FALSE);
408 edje_object_signal_emit(wd->layout, "elm,video,stop", "elm");
409 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
416 elm_video_is_playing_get(const Evas_Object *video)
419 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
420 Widget_Data *wd = elm_widget_data_get(video);
422 return emotion_object_play_get(wd->emotion);
430 elm_video_is_seekable_get(const Evas_Object *video)
433 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
434 Widget_Data *wd = elm_widget_data_get(video);
436 return emotion_object_seekable_get(wd->emotion);
444 elm_video_audio_mute_get(const Evas_Object *video)
447 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
448 Widget_Data *wd = elm_widget_data_get(video);
450 return emotion_object_audio_mute_get(wd->emotion);
458 elm_video_audio_mute_set(Evas_Object *video, Eina_Bool mute)
461 ELM_CHECK_WIDTYPE(video, widtype);
462 Widget_Data *wd = elm_widget_data_get(video);
464 emotion_object_audio_mute_set(wd->emotion, mute);
472 elm_video_audio_level_get(const Evas_Object *video)
475 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
476 Widget_Data *wd = elm_widget_data_get(video);
478 return emotion_object_audio_volume_get(wd->emotion);
486 elm_video_audio_level_set(Evas_Object *video, double volume)
489 ELM_CHECK_WIDTYPE(video, widtype);
490 Widget_Data *wd = elm_widget_data_get(video);
492 emotion_object_audio_volume_set(wd->emotion, volume);
500 elm_video_play_position_get(const Evas_Object *video)
503 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
504 Widget_Data *wd = elm_widget_data_get(video);
506 return emotion_object_position_get(wd->emotion);
514 elm_video_play_position_set(Evas_Object *video, double position)
517 ELM_CHECK_WIDTYPE(video, widtype);
518 Widget_Data *wd = elm_widget_data_get(video);
520 emotion_object_position_set(wd->emotion, position);
528 elm_video_play_length_get(const Evas_Object *video)
531 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
532 Widget_Data *wd = elm_widget_data_get(video);
534 return emotion_object_play_length_get(wd->emotion);
542 elm_video_title_get(const Evas_Object *video)
545 ELM_CHECK_WIDTYPE(video, widtype) NULL;
546 Widget_Data *wd = elm_widget_data_get(video);
548 return emotion_object_title_get(wd->emotion);
556 elm_video_remember_position_set(Evas_Object *video, Eina_Bool remember)
559 ELM_CHECK_WIDTYPE(video, widtype);
560 Widget_Data *wd = elm_widget_data_get(video);
562 wd->remember = remember;
570 elm_video_remember_position_get(const Evas_Object *video)
573 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
574 Widget_Data *wd = elm_widget_data_get(video);