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);
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 emotion_object_file_set(wd->emotion, filename);
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");
334 EINA_DEPRECATED EAPI void
335 elm_video_uri_set(Evas_Object *video, const char *uri)
338 ELM_CHECK_WIDTYPE(video, widtype);
339 Widget_Data *wd = elm_widget_data_get(video);
341 if (wd->remember) emotion_object_last_position_save(wd->emotion);
342 wd->stop = EINA_FALSE;
343 emotion_object_file_set(wd->emotion, uri);
344 edje_object_signal_emit(wd->layout, "elm,video,load", "elm");
352 elm_video_emotion_get(const Evas_Object *video)
355 ELM_CHECK_WIDTYPE(video, widtype) NULL;
356 Widget_Data *wd = elm_widget_data_get(video);
366 elm_video_play(Evas_Object *video)
369 ELM_CHECK_WIDTYPE(video, widtype);
370 Widget_Data *wd = elm_widget_data_get(video);
372 if (emotion_object_play_get(wd->emotion)) return ;
374 if (wd->timer) ecore_timer_del(wd->timer);
376 wd->stop = EINA_FALSE;
377 emotion_object_play_set(wd->emotion, EINA_TRUE);
383 /* FIXME: pause will setup timer and go into sleep or
384 * hibernate after a while without activity.
388 elm_video_pause(Evas_Object *video)
391 ELM_CHECK_WIDTYPE(video, widtype);
392 Widget_Data *wd = elm_widget_data_get(video);
394 if (!emotion_object_play_get(wd->emotion)) return ;
396 if (!wd->timer) wd->timer = ecore_timer_add(20.0, _suspend_cb, video);
397 emotion_object_play_set(wd->emotion, EINA_FALSE);
398 edje_object_signal_emit(wd->layout, "elm,video,pause", "elm");
404 /* FIXME: stop should go into hibernate state directly.
407 elm_video_stop(Evas_Object *video)
410 ELM_CHECK_WIDTYPE(video, widtype);
411 Widget_Data *wd = elm_widget_data_get(video);
413 if (!emotion_object_play_get(wd->emotion) && wd->stop) return ;
415 if (wd->timer) ecore_timer_del(wd->timer);
417 wd->stop = EINA_TRUE;
418 emotion_object_play_set(wd->emotion, EINA_FALSE);
419 edje_object_signal_emit(wd->layout, "elm,video,stop", "elm");
420 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
427 elm_video_is_playing_get(const Evas_Object *video)
430 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
431 Widget_Data *wd = elm_widget_data_get(video);
433 return emotion_object_play_get(wd->emotion);
441 elm_video_is_seekable_get(const Evas_Object *video)
444 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
445 Widget_Data *wd = elm_widget_data_get(video);
447 return emotion_object_seekable_get(wd->emotion);
455 elm_video_audio_mute_get(const Evas_Object *video)
458 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
459 Widget_Data *wd = elm_widget_data_get(video);
461 return emotion_object_audio_mute_get(wd->emotion);
469 elm_video_audio_mute_set(Evas_Object *video, Eina_Bool mute)
472 ELM_CHECK_WIDTYPE(video, widtype);
473 Widget_Data *wd = elm_widget_data_get(video);
475 emotion_object_audio_mute_set(wd->emotion, mute);
483 elm_video_audio_level_get(const Evas_Object *video)
486 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
487 Widget_Data *wd = elm_widget_data_get(video);
489 return emotion_object_audio_volume_get(wd->emotion);
497 elm_video_audio_level_set(Evas_Object *video, double volume)
500 ELM_CHECK_WIDTYPE(video, widtype);
501 Widget_Data *wd = elm_widget_data_get(video);
503 emotion_object_audio_volume_set(wd->emotion, volume);
511 elm_video_play_position_get(const Evas_Object *video)
514 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
515 Widget_Data *wd = elm_widget_data_get(video);
517 return emotion_object_position_get(wd->emotion);
525 elm_video_play_position_set(Evas_Object *video, double position)
528 ELM_CHECK_WIDTYPE(video, widtype);
529 Widget_Data *wd = elm_widget_data_get(video);
531 emotion_object_position_set(wd->emotion, position);
539 elm_video_play_length_get(const Evas_Object *video)
542 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
543 Widget_Data *wd = elm_widget_data_get(video);
545 return emotion_object_play_length_get(wd->emotion);
553 elm_video_title_get(const Evas_Object *video)
556 ELM_CHECK_WIDTYPE(video, widtype) NULL;
557 Widget_Data *wd = elm_widget_data_get(video);
559 return emotion_object_title_get(wd->emotion);
567 elm_video_remember_position_set(Evas_Object *video, Eina_Bool remember)
570 ELM_CHECK_WIDTYPE(video, widtype);
571 Widget_Data *wd = elm_widget_data_get(video);
573 wd->remember = remember;
581 elm_video_remember_position_get(const Evas_Object *video)
584 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
585 Widget_Data *wd = elm_widget_data_get(video);