1 #include <Elementary.h>
3 #include "elm_widget_video.h"
9 /* TODO: add buffering support to Emotion and display buffering
10 * progress in the theme when needed */
12 EAPI const char ELM_VIDEO_SMART_NAME[] = "elm_video";
14 EVAS_SMART_SUBCLASS_NEW
15 (ELM_VIDEO_SMART_NAME, _elm_video, Elm_Video_Smart_Class,
16 Elm_Layout_Smart_Class, elm_layout_smart_class_get, NULL);
19 _elm_video_smart_event(Evas_Object *obj,
20 Evas_Object *src __UNUSED__,
21 Evas_Callback_Type type,
25 Evas_Event_Key_Down *ev = event_info;
27 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
28 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
29 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
31 if ((!strcmp(ev->keyname, "Left")) ||
32 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
36 current = elm_video_play_position_get(obj);
37 last = elm_video_play_length_get(obj);
41 current += last / 100;
42 elm_video_play_position_set(obj, current);
45 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
50 if ((!strcmp(ev->keyname, "Right")) ||
51 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
55 current = elm_video_play_position_get(obj);
56 last = elm_video_play_length_get(obj);
60 current -= last / 100;
61 if (current < 0) current = 0;
62 elm_video_play_position_set(obj, current);
65 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
70 if (!strcmp(ev->keyname, "space"))
72 if (elm_video_is_playing_get(obj))
76 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
81 INF("keyname: '%s' not handled", ev->keyname);
95 _elm_video_smart_sizing_eval(Evas_Object *obj)
98 ELM_VIDEO_DATA_GET(obj, sd);
100 Evas_Coord minw = -1, minh = -1;
103 evas_object_size_hint_request_get(sd->emotion, &minw, &minh);
104 evas_object_size_hint_aspect_set
105 (sd->emotion, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
106 edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &w, &h);
108 if (w != 0 && h != 0)
114 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
123 _on_size_hints_changed(void *data __UNUSED__,
126 void *event_info __UNUSED__)
128 elm_layout_sizing_eval(obj);
132 _on_open_done(void *data,
133 Evas_Object *obj __UNUSED__,
134 void *event_info __UNUSED__)
136 elm_layout_signal_emit(data, "elm,video,open", "elm");
140 _on_playback_started(void *data,
141 Evas_Object *obj __UNUSED__,
142 void *event_info __UNUSED__)
144 elm_layout_signal_emit(data, "elm,video,play", "elm");
148 _on_playback_finished(void *data,
149 Evas_Object *obj __UNUSED__,
150 void *event_info __UNUSED__)
152 elm_layout_signal_emit(data, "elm,video,end", "elm");
156 _on_aspect_ratio_updated(void *data,
157 Evas_Object *obj __UNUSED__,
158 void *event_info __UNUSED__)
160 elm_layout_sizing_eval(data);
164 _on_title_changed(void *data,
165 Evas_Object *obj __UNUSED__,
166 void *event_info __UNUSED__)
170 ELM_VIDEO_DATA_GET(data, sd);
172 title = emotion_object_title_get(sd->emotion);
173 elm_layout_text_set(data, "elm,title", title);
174 elm_layout_signal_emit(data, "elm,video,title", "elm");
178 _on_audio_level_changed(void *data,
179 Evas_Object *obj __UNUSED__,
180 void *event_info __UNUSED__)
186 _suspend_cb(void *data)
190 ELM_VIDEO_DATA_GET(data, sd);
192 interval = ecore_timer_interval_get(sd->timer);
194 emotion_object_suspend_set(sd->emotion, EMOTION_SLEEP);
195 else if (interval <= 30)
196 emotion_object_suspend_set(sd->emotion, EMOTION_DEEP_SLEEP);
199 emotion_object_suspend_set(sd->emotion, EMOTION_HIBERNATE);
202 return ECORE_CALLBACK_CANCEL;
205 ecore_timer_interval_set(sd->timer, interval + 10);
206 return ECORE_CALLBACK_RENEW;
212 _elm_video_check(Evas_Object *video)
215 ELM_VIDEO_CHECK(video) EINA_FALSE;
226 _elm_video_smart_add(Evas_Object *obj)
228 EVAS_SMART_DATA_ALLOC(obj, Elm_Video_Smart_Data);
232 ELM_WIDGET_CLASS(_elm_video_parent_sc)->base.add(obj);
234 elm_widget_can_focus_set(obj, EINA_TRUE);
237 priv->stop = EINA_FALSE;
238 priv->remember = EINA_FALSE;
240 priv->emotion = emotion_object_add(evas_object_evas_get(obj));
241 emotion_object_init(priv->emotion, NULL);
243 elm_layout_theme_set(obj, "video", "base", elm_widget_style_get(obj));
244 elm_layout_content_set(obj, "elm.swallow.video", priv->emotion);
246 evas_object_smart_callback_add
247 (priv->emotion, "open_done", _on_open_done, obj);
248 evas_object_smart_callback_add
249 (priv->emotion, "playback_started", _on_playback_started, obj);
250 evas_object_smart_callback_add
251 (priv->emotion, "playback_finished", _on_playback_finished, obj);
252 evas_object_smart_callback_add
253 (priv->emotion, "frame_resize", _on_aspect_ratio_updated, obj);
254 evas_object_smart_callback_add
255 (priv->emotion, "title_change", _on_title_changed, obj);
256 evas_object_smart_callback_add
257 (priv->emotion, "audio_level_change", _on_audio_level_changed, obj);
259 evas_object_event_callback_add
260 (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_size_hints_changed, NULL);
262 priv->timer = ecore_timer_add(20.0, _suspend_cb, obj);
267 _elm_video_smart_del(Evas_Object *obj)
269 ELM_VIDEO_DATA_GET(obj, sd);
272 if (sd->timer) ecore_timer_del(sd->timer);
273 if (sd->remember) emotion_object_last_position_save(sd->emotion);
278 ELM_WIDGET_CLASS(_elm_video_parent_sc)->base.del(obj);
282 _elm_video_smart_set_user(Elm_Video_Smart_Class *sc)
284 ELM_WIDGET_CLASS(sc)->base.add = _elm_video_smart_add;
285 ELM_WIDGET_CLASS(sc)->base.del = _elm_video_smart_del;
287 ELM_WIDGET_CLASS(sc)->event = _elm_video_smart_event;
289 /* not a 'focus chain manager' */
290 ELM_WIDGET_CLASS(sc)->focus_next = NULL;
291 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
293 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_video_smart_sizing_eval;
296 EAPI const Elm_Video_Smart_Class *
297 elm_video_smart_class_get(void)
299 static Elm_Video_Smart_Class _sc =
300 ELM_VIDEO_SMART_CLASS_INIT_NAME_VERSION(ELM_VIDEO_SMART_NAME);
301 static const Elm_Video_Smart_Class *class = NULL;
306 _elm_video_smart_set(&_sc);
313 elm_video_add(Evas_Object *parent)
318 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
320 obj = elm_widget_add(_elm_video_smart_class_new(), parent);
321 if (!obj) return NULL;
323 if (!elm_widget_sub_object_add(parent, obj))
324 ERR("could not add %p as sub object of %p", obj, parent);
329 (void) _elm_video_smart_class_new;
336 elm_video_file_set(Evas_Object *obj,
337 const char *filename)
340 ELM_VIDEO_CHECK(obj) EINA_FALSE;
341 ELM_VIDEO_DATA_GET(obj, sd);
343 if (sd->remember) emotion_object_last_position_save(sd->emotion);
344 sd->stop = EINA_FALSE;
345 if (!emotion_object_file_set(sd->emotion, filename)) return EINA_FALSE;
347 if (filename && ((!strncmp(filename, "file://", 7)) || (!strstr(filename, "://"))))
348 emotion_object_last_position_load(sd->emotion);
350 elm_layout_signal_emit(obj, "elm,video,load", "elm");
362 elm_video_emotion_get(const Evas_Object *obj)
365 ELM_VIDEO_CHECK(obj) NULL;
366 ELM_VIDEO_DATA_GET(obj, sd);
376 elm_video_play(Evas_Object *obj)
379 ELM_VIDEO_CHECK(obj);
380 ELM_VIDEO_DATA_GET(obj, sd);
382 if (emotion_object_play_get(sd->emotion)) return;
384 if (sd->timer) ecore_timer_del(sd->timer);
386 sd->stop = EINA_FALSE;
387 emotion_object_play_set(sd->emotion, EINA_TRUE);
393 /* FIXME: pause will setup timer and go into sleep or
394 * hibernate after a while without activity.
397 elm_video_pause(Evas_Object *obj)
400 ELM_VIDEO_CHECK(obj);
401 ELM_VIDEO_DATA_GET(obj, sd);
403 if (!emotion_object_play_get(sd->emotion)) return;
405 if (!sd->timer) sd->timer = ecore_timer_add(20.0, _suspend_cb, obj);
406 emotion_object_play_set(sd->emotion, EINA_FALSE);
407 elm_layout_signal_emit(obj, "elm,video,pause", "elm");
413 /* FIXME: stop should go into hibernate state directly.
416 elm_video_stop(Evas_Object *obj)
419 ELM_VIDEO_CHECK(obj);
420 ELM_VIDEO_DATA_GET(obj, sd);
422 if (!emotion_object_play_get(sd->emotion) && sd->stop) return;
424 if (sd->timer) ecore_timer_del(sd->timer);
427 sd->stop = EINA_TRUE;
428 emotion_object_play_set(sd->emotion, EINA_FALSE);
429 elm_layout_signal_emit(obj, "elm,video,stop", "elm");
430 emotion_object_suspend_set(sd->emotion, EMOTION_HIBERNATE);
437 elm_video_is_playing_get(const Evas_Object *obj)
440 ELM_VIDEO_CHECK(obj) EINA_FALSE;
441 ELM_VIDEO_DATA_GET(obj, sd);
443 return emotion_object_play_get(sd->emotion);
451 elm_video_is_seekable_get(const Evas_Object *obj)
454 ELM_VIDEO_CHECK(obj) EINA_FALSE;
455 ELM_VIDEO_DATA_GET(obj, sd);
457 return emotion_object_seekable_get(sd->emotion);
465 elm_video_audio_mute_get(const Evas_Object *obj)
468 ELM_VIDEO_CHECK(obj) EINA_FALSE;
469 ELM_VIDEO_DATA_GET(obj, sd);
471 return emotion_object_audio_mute_get(sd->emotion);
479 elm_video_audio_mute_set(Evas_Object *obj,
483 ELM_VIDEO_CHECK(obj);
484 ELM_VIDEO_DATA_GET(obj, sd);
486 emotion_object_audio_mute_set(sd->emotion, mute);
494 elm_video_audio_level_get(const Evas_Object *obj)
497 ELM_VIDEO_CHECK(obj) 0.0;
498 ELM_VIDEO_DATA_GET(obj, sd);
500 return emotion_object_audio_volume_get(sd->emotion);
508 elm_video_audio_level_set(Evas_Object *obj,
512 ELM_VIDEO_CHECK(obj);
513 ELM_VIDEO_DATA_GET(obj, sd);
515 emotion_object_audio_volume_set(sd->emotion, volume);
523 elm_video_play_position_get(const Evas_Object *obj)
526 ELM_VIDEO_CHECK(obj) 0.0;
527 ELM_VIDEO_DATA_GET(obj, sd);
529 return emotion_object_position_get(sd->emotion);
537 elm_video_play_position_set(Evas_Object *obj,
541 ELM_VIDEO_CHECK(obj);
542 ELM_VIDEO_DATA_GET(obj, sd);
544 emotion_object_position_set(sd->emotion, position);
552 elm_video_play_length_get(const Evas_Object *obj)
555 ELM_VIDEO_CHECK(obj) 0.0;
556 ELM_VIDEO_DATA_GET(obj, sd);
558 return emotion_object_play_length_get(sd->emotion);
566 elm_video_title_get(const Evas_Object *obj)
569 ELM_VIDEO_CHECK(obj) NULL;
570 ELM_VIDEO_DATA_GET(obj, sd);
572 return emotion_object_title_get(sd->emotion);
580 elm_video_remember_position_set(Evas_Object *obj,
584 ELM_VIDEO_CHECK(obj);
585 ELM_VIDEO_DATA_GET(obj, sd);
587 sd->remember = remember;
595 elm_video_remember_position_get(const Evas_Object *obj)
598 ELM_VIDEO_CHECK(obj) EINA_FALSE;
599 ELM_VIDEO_DATA_GET(obj, sd);