#ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #define EFL_ACCESS_OBJECT_PROTECTED #define EFL_ACCESS_WIDGET_ACTION_PROTECTED #define EFL_PART_PROTECTED #include #include #include "elm_priv.h" #include "elm_widget_layout.h" #include "elm_widget_player.h" #include "elm_player_part.eo.h" #include "elm_part_helper.h" #define MY_CLASS ELM_PLAYER_CLASS #define MY_CLASS_NAME "Elm_Player" #define MY_CLASS_NAME_LEGACY "elm_player" static const char SIG_FORWARD_CLICKED[] = "forward,clicked"; static const char SIG_INFO_CLICKED[] = "info,clicked"; static const char SIG_NEXT_CLICKED[] = "next,clicked"; static const char SIG_PAUSE_CLICKED[] = "pause,clicked"; static const char SIG_PLAY_CLICKED[] = "play,clicked"; static const char SIG_PREV_CLICKED[] = "prev,clicked"; static const char SIG_REWIND_CLICKED[] = "rewind,clicked"; static const char SIG_STOP_CLICKED[] = "stop,clicked"; static const char SIG_EJECT_CLICKED[] = "eject,clicked"; static const char SIG_VOLUME_CLICKED[] = "volume,clicked"; static const char SIG_MUTE_CLICKED[] = "mute,clicked"; /* static const char SIG_STOP_CLICKED[] = "repeat,clicked"; static const char SIG_STOP_CLICKED[] = "shuffle,clicked"; static const char SIG_STOP_CLICKED[] = "record,clicked"; static const char SIG_STOP_CLICKED[] = "replay,clicked"; static const char SIG_STOP_CLICKED[] = "power,clicked"; static const char SIG_STOP_CLICKED[] = "fullscreen,clicked"; static const char SIG_STOP_CLICKED[] = "normal,clicked"; static const char SIG_STOP_CLICKED[] = "quality,clicked"; */ static const Evas_Smart_Cb_Description _smart_callbacks[] = { { SIG_FORWARD_CLICKED, "" }, { SIG_INFO_CLICKED, "" }, { SIG_NEXT_CLICKED, "" }, { SIG_PAUSE_CLICKED, "" }, { SIG_PLAY_CLICKED, "" }, { SIG_PREV_CLICKED, "" }, { SIG_REWIND_CLICKED, "" }, { SIG_STOP_CLICKED, "" }, { SIG_EJECT_CLICKED, "" }, { SIG_VOLUME_CLICKED, "" }, { SIG_MUTE_CLICKED, "" }, { SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */ { SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */ { SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */ { NULL, NULL } }; static void _update_frame(void *data, const Efl_Event *event); static void _update_slider(void *data, const Efl_Event *event); static void _play_started(void *data, const Efl_Event *event); static void _play_finished(void *data, const Efl_Event *event); static void _update_position(void *data, const Efl_Event *event); static void _drag_start(void *data, const Efl_Event *event); static void _drag_stop(void *data, const Efl_Event *event); static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static Eina_Bool _key_action_play(Evas_Object *obj, const char *params); static const Elm_Action key_actions[] = { {"move", _key_action_move}, {"play", _key_action_play}, {NULL, NULL} }; EFL_CALLBACKS_ARRAY_DEFINE(_emotion_cb, { EFL_CANVAS_VIDEO_EVENT_FRAME_DECODE, _update_frame }, { EFL_CANVAS_VIDEO_EVENT_FRAME_RESIZE, _update_slider }, { EFL_CANVAS_VIDEO_EVENT_LENGTH_CHANGE, _update_slider }, { EFL_CANVAS_VIDEO_EVENT_POSITION_CHANGE, _update_frame }, { EFL_CANVAS_VIDEO_EVENT_PLAYBACK_START, _play_started }, { EFL_CANVAS_VIDEO_EVENT_PLAYBACK_STOP, _play_finished } ); EFL_CALLBACKS_ARRAY_DEFINE(_slider_cb, { EFL_UI_RANGE_EVENT_CHANGED, _update_position }, { EFL_UI_SLIDER_EVENT_SLIDER_DRAG_START, _drag_start }, { EFL_UI_SLIDER_EVENT_SLIDER_DRAG_STOP, _drag_stop } ); static Eina_Bool _key_action_move(Evas_Object *obj, const char *params) { ELM_PLAYER_DATA_GET(obj, sd); const char *dir = params; if (!sd->video) return EINA_FALSE; _elm_widget_focus_auto_show(obj); if (!strcmp(dir, "left")) { double current, last; current = elm_video_play_position_get(sd->video); last = elm_video_play_length_get(sd->video); if (current < last) { current -= last / 100; elm_video_play_position_set(sd->video, current); } } else if (!strcmp(dir, "right")) { double current, last; current = elm_video_play_position_get(sd->video); last = elm_video_play_length_get(sd->video); if (current > 0) { current += last / 100; if (current < 0) current = 0; elm_video_play_position_set(sd->video, current); } } else return EINA_FALSE; return EINA_TRUE; } static Eina_Bool _key_action_play(Evas_Object *obj, const char *params EINA_UNUSED) { ELM_PLAYER_DATA_GET(obj, sd); if (!sd->video) return EINA_FALSE; if (elm_video_is_playing_get(sd->video)) elm_video_pause(sd->video); else elm_video_play(sd->video); return EINA_TRUE; } static void _update_theme_button(Evas_Object *obj, Evas_Object *bt, const char *name) { Evas_Object *ic; char buf[256]; if (!bt) return; ic = evas_object_data_get(bt, "icon"); if (ic) { snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_icon_standard_set(ic, buf); } snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_object_style_set(bt, buf); snprintf(buf, sizeof(buf), "elm.swallow.media_player.%s", name); if (!elm_layout_content_set(obj, buf, bt)) evas_object_hide(bt); elm_object_disabled_set(bt, elm_widget_disabled_get(obj)); } static void _update_theme_slider(Evas_Object *obj, Evas_Object *sl, const char *name, const char *name2) { char buf[256]; if (!sl) return; snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_object_style_set(sl, buf); snprintf(buf, sizeof(buf), "elm.swallow.media_player.%s", name2); if (!elm_layout_content_set(obj, buf, sl)) evas_object_hide(sl); elm_object_disabled_set(sl, elm_widget_disabled_get(obj)); } EOLIAN static Eina_Error _elm_player_efl_ui_widget_theme_apply(Eo *obj, Elm_Player_Data *sd) { Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC; int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS)); if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret; _update_theme_button(obj, sd->forward, "forward"); _update_theme_button(obj, sd->info, "info"); _update_theme_button(obj, sd->next, "next"); _update_theme_button(obj, sd->pause, "pause"); _update_theme_button(obj, sd->play, "play"); _update_theme_button(obj, sd->prev, "prev"); _update_theme_button(obj, sd->rewind, "rewind"); _update_theme_button(obj, sd->next, "next"); _update_theme_button(obj, sd->stop, "stop"); _update_theme_button(obj, sd->eject, "eject"); _update_theme_button(obj, sd->volume, "volume"); _update_theme_button(obj, sd->mute, "mute"); _update_theme_slider(obj, sd->slider, "position", "positionslider"); _update_theme_slider(obj, sd->vslider, "volume", "volumeslider"); elm_layout_sizing_eval(obj); return int_ret; } static void _update_slider(void *data, const Efl_Event *event EINA_UNUSED) { double pos, length; Eina_Bool seekable; ELM_PLAYER_DATA_GET(data, sd); if (!sd) return; seekable = elm_video_is_seekable_get(sd->video); length = elm_video_play_length_get(sd->video); pos = elm_video_play_position_get(sd->video); elm_object_disabled_set(sd->slider, (!seekable) | elm_widget_disabled_get(data)); elm_slider_min_max_set(sd->slider, 0, length); if ((!EINA_DBL_EQ(elm_slider_value_get(sd->slider), pos)) && (!sd->dragging)) elm_slider_value_set(sd->slider, pos); } static void _update_frame(void *data, const Efl_Event *event) { ELM_PLAYER_DATA_GET(data, sd); if (!sd) return; _update_slider(data, event); } static void _update_position(void *data, const Efl_Event *event EINA_UNUSED) { double pos; ELM_PLAYER_DATA_GET(data, sd); pos = elm_slider_value_get(sd->slider); if (!EINA_FLT_EQ(pos, elm_video_play_position_get(sd->video))) elm_video_play_position_set(sd->video, pos); } static void _drag_start(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); sd->dragging = EINA_TRUE; } static void _drag_stop(void *data, const Efl_Event *event EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); sd->dragging = EINA_FALSE; } static void _update_volume(void *data, const Efl_Event *event EINA_UNUSED) { double vol; ELM_PLAYER_DATA_GET(data, sd); vol = elm_slider_value_get(sd->vslider) / 100.0; if (!EINA_DBL_EQ(vol, elm_video_audio_level_get(sd->video))) elm_video_audio_level_set(sd->video, vol); } static void _forward(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { double pos, length; ELM_PLAYER_DATA_GET(data, sd); length = elm_video_play_length_get(sd->video); pos = elm_video_play_position_get(sd->video); pos += 30.0; if (pos > length) pos = length; elm_video_play_position_set(sd->video, pos); elm_layout_signal_emit(data, "elm,button,forward", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_FORWARD_CLICKED, NULL); } static void _info(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,info", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_INFO_CLICKED, NULL); } static void _next(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,next", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_NEXT_CLICKED, NULL); } static void _pause(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); elm_layout_signal_emit(data, "elm,player,pause", "elm"); elm_video_pause(sd->video); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_PAUSE_CLICKED, NULL); } static void _play(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); elm_layout_signal_emit(data, "elm,player,play", "elm"); elm_video_play(sd->video); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_PLAY_CLICKED, NULL); } static void _prev(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_PREV_CLICKED, NULL); elm_layout_signal_emit(data, "elm,button,prev", "elm"); } static void _rewind(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { double pos; ELM_PLAYER_DATA_GET(data, sd); pos = elm_video_play_position_get(sd->video); pos -= 30.0; if (pos < 0.0) pos = 0.0; elm_video_play_position_set(sd->video, pos); elm_layout_signal_emit(data, "elm,button,rewind", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_REWIND_CLICKED, NULL); } static void _stop(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,stop", "elm"); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_QUALITY_CLICKED, NULL); } static void _eject(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { ELM_PLAYER_DATA_GET(data, sd); elm_layout_signal_emit(data, "elm,button,eject", "elm"); emotion_object_eject(elm_video_emotion_get(sd->video)); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_EJECT_CLICKED, NULL); } static void _mute_toggle(Evas_Object *obj) { ELM_PLAYER_DATA_GET(obj, sd); if (!elm_video_audio_mute_get(sd->video)) { elm_video_audio_mute_set(sd->video, EINA_TRUE); elm_layout_signal_emit(obj, "elm,player,mute", "elm"); } else { elm_video_audio_mute_set(sd->video, EINA_FALSE); elm_layout_signal_emit(obj, "elm,player,unmute", "elm"); } } static void _volume(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,volume", "elm"); _mute_toggle(data); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_VOLUME_CLICKED, NULL); } static void _mute(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { elm_layout_signal_emit(data, "elm,button,mute", "elm"); _mute_toggle(data); efl_event_callback_legacy_call(data, ELM_PLAYER_EVENT_MUTE_CLICKED, NULL); } static void _play_started(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,player,play", "elm"); } static void _play_finished(void *data, const Efl_Event *event EINA_UNUSED) { elm_layout_signal_emit(data, "elm,player,pause", "elm"); } static void _on_video_del(Elm_Player_Data *sd) { elm_object_disabled_set(sd->forward, EINA_TRUE); elm_object_disabled_set(sd->info, EINA_TRUE); elm_object_disabled_set(sd->next, EINA_TRUE); elm_object_disabled_set(sd->pause, EINA_TRUE); elm_object_disabled_set(sd->play, EINA_TRUE); elm_object_disabled_set(sd->prev, EINA_TRUE); elm_object_disabled_set(sd->rewind, EINA_TRUE); elm_object_disabled_set(sd->next, EINA_TRUE); elm_object_disabled_set(sd->stop, EINA_TRUE); elm_object_disabled_set(sd->volume, EINA_TRUE); elm_object_disabled_set(sd->mute, EINA_TRUE); elm_object_disabled_set(sd->slider, EINA_TRUE); elm_object_disabled_set(sd->vslider, EINA_TRUE); sd->video = NULL; sd->emotion = NULL; } static void _video_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { _on_video_del(data); } static Evas_Object * _player_button_add(Evas_Object *obj, const char *name, Evas_Smart_Cb func) { Evas_Object *ic; Evas_Object *bt; char buf[256]; ic = elm_icon_add(obj); snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_icon_standard_set(ic, buf); bt = elm_button_add(obj); if (ic) evas_object_data_set(bt, "icon", ic); efl_ui_mirrored_automatic_set(bt, EINA_FALSE); elm_object_content_set(bt, ic); evas_object_show(ic); snprintf(buf, sizeof(buf), "media_player/%s/%s", name, elm_widget_style_get(obj)); elm_object_style_set(bt, buf); evas_object_smart_callback_add(bt, "clicked", func, obj); snprintf(buf, sizeof(buf), "elm.swallow.media_player.%s", name); if (!elm_layout_content_set(obj, buf, bt)) { elm_widget_sub_object_add(obj, bt); evas_object_hide(bt); } evas_object_show(bt); return bt; } static char * _double_to_time(double value) { char buf[256]; int ph, pm, ps, pf; ph = value / 3600; pm = value / 60 - (ph * 60); ps = value - (pm * 60) - (ph * 3600); pf = value * 100 - (ps * 100) - (pm * 60 * 100) - (ph * 60 * 60 * 100); if (ph) snprintf(buf, sizeof(buf), "%i:%02i:%02i.%02i", ph, pm, ps, pf); else if (pm) snprintf(buf, sizeof(buf), "%02i:%02i.%02i", pm, ps, pf); else snprintf(buf, sizeof(buf), "%02i.%02i", ps, pf); return (char *)eina_stringshare_add(buf); } static void _str_free(char *data) { eina_stringshare_del(data); } /* a video object is never parented by a player one, just tracked. * treating this special case here and delegating other objects to own * layout */ static Eina_Bool _elm_player_content_set(Eo *obj, Elm_Player_Data *sd, const char *part, Evas_Object *content) { Eina_Bool int_ret = EINA_FALSE; double pos, length; Eina_Bool seekable; if (part && strcmp(part, "video")) { int_ret = efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); return int_ret; } if ((!part) || (!strcmp(part, "video"))) part = "elm.swallow.content"; int_ret = efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); if (!_elm_video_check(content)) return EINA_FALSE; if (sd->video == content) goto end; evas_object_del(sd->video); sd->video = content; if (!content) goto end; elm_object_disabled_set(sd->forward, EINA_FALSE); elm_object_disabled_set(sd->info, EINA_FALSE); elm_object_disabled_set(sd->next, EINA_FALSE); elm_object_disabled_set(sd->pause, EINA_FALSE); elm_object_disabled_set(sd->play, EINA_FALSE); elm_object_disabled_set(sd->prev, EINA_FALSE); elm_object_disabled_set(sd->rewind, EINA_FALSE); elm_object_disabled_set(sd->next, EINA_FALSE); elm_object_disabled_set(sd->stop, EINA_FALSE); elm_object_disabled_set(sd->volume, EINA_FALSE); elm_object_disabled_set(sd->mute, EINA_FALSE); elm_object_disabled_set(sd->slider, EINA_FALSE); elm_object_disabled_set(sd->vslider, EINA_FALSE); sd->emotion = elm_video_emotion_get(sd->video); emotion_object_priority_set(sd->emotion, EINA_TRUE); evas_object_event_callback_add (sd->video, EVAS_CALLBACK_DEL, _video_del, sd); seekable = elm_video_is_seekable_get(sd->video); length = elm_video_play_length_get(sd->video); pos = elm_video_play_position_get(sd->video); elm_object_disabled_set(sd->slider, !seekable); elm_slider_min_max_set(sd->slider, 0, length); elm_slider_value_set(sd->slider, pos); elm_slider_value_set(sd->vslider, elm_video_audio_level_get(sd->video) * 100.0); // XXX: get mute if (elm_video_is_playing_get(sd->video)) elm_layout_signal_emit(obj, "elm,player,play", "elm"); else elm_layout_signal_emit(obj, "elm,player,pause", "elm"); efl_event_callback_array_add(sd->emotion, _emotion_cb(), obj); /* FIXME: track info from video */ end: return EINA_TRUE; } EOLIAN static void _elm_player_efl_canvas_group_group_add(Eo *obj, Elm_Player_Data *priv) { char buf[256]; efl_canvas_group_add(efl_super(obj, MY_CLASS)); if (!elm_layout_theme_set(obj, "player", "base", elm_widget_style_get(obj))) CRI("Failed to set layout!"); efl_ui_layout_finger_size_multiplier_set(obj, 0, 0); priv->forward = _player_button_add(obj, "forward", _forward); priv->info = _player_button_add(obj, "info", _info); priv->next = _player_button_add(obj, "next", _next); priv->pause = _player_button_add(obj, "pause", _pause); priv->play = _player_button_add(obj, "play", _play); priv->prev = _player_button_add(obj, "prev", _prev); priv->rewind = _player_button_add(obj, "rewind", _rewind); priv->stop = _player_button_add(obj, "stop", _stop); priv->eject = _player_button_add(obj, "eject", _eject); priv->volume = _player_button_add(obj, "volume", _volume); priv->mute = _player_button_add(obj, "mute", _mute); priv->slider = elm_slider_add(obj); snprintf(buf, sizeof(buf), "media_player/position/%s", elm_widget_style_get(obj)); elm_object_style_set(priv->slider, buf); elm_slider_indicator_show_set(priv->slider, EINA_TRUE); elm_slider_indicator_format_function_set (priv->slider, _double_to_time, _str_free); elm_slider_units_format_function_set (priv->slider, _double_to_time, _str_free); elm_slider_value_set(priv->slider, 0); elm_object_disabled_set(priv->slider, EINA_TRUE); evas_object_size_hint_align_set(priv->slider, EVAS_HINT_FILL, 0.5); evas_object_size_hint_weight_set (priv->slider, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_content_set(obj, "elm.swallow.media_player.positionslider", priv->slider); efl_event_callback_array_add(priv->slider, _slider_cb(), obj); priv->vslider = elm_slider_add(obj); elm_slider_indicator_show_set(priv->vslider, EINA_FALSE); snprintf(buf, sizeof(buf), "media_player/volume/%s", elm_widget_style_get(obj)); elm_object_style_set(priv->vslider, buf); elm_slider_min_max_set(priv->vslider, 0, 100); elm_slider_value_set(priv->vslider, 100); elm_slider_horizontal_set(priv->vslider, EINA_FALSE); elm_slider_inverted_set(priv->vslider, EINA_TRUE); evas_object_size_hint_align_set(priv->vslider, 0.5, EVAS_HINT_FILL); evas_object_size_hint_weight_set (priv->vslider, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_content_set(obj, "elm.swallow.media_player.volumeslider", priv->vslider); efl_event_callback_add (priv->vslider, EFL_UI_RANGE_EVENT_CHANGED, _update_volume, obj); elm_layout_sizing_eval(obj); elm_widget_can_focus_set(obj, EINA_TRUE); } EOLIAN static void _elm_player_efl_canvas_group_group_del(Eo *obj, Elm_Player_Data *sd EINA_UNUSED) { efl_canvas_group_del(efl_super(obj, MY_CLASS)); } EAPI Evas_Object * elm_player_add(Evas_Object *parent) { EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); return elm_legacy_add(MY_CLASS, parent); } EOLIAN static Eo * _elm_player_efl_object_constructor(Eo *obj, Elm_Player_Data *sd EINA_UNUSED) { obj = efl_constructor(efl_super(obj, MY_CLASS)); efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY); evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks); efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ANIMATION); return obj; } EOLIAN static void _elm_player_class_constructor(Efl_Class *klass) { evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } EOLIAN const Efl_Access_Action_Data * _elm_player_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Player_Data *pd EINA_UNUSED) { static Efl_Access_Action_Data atspi_actions[] = { { "move,left", "move", "left", _key_action_move}, { "move,right", "move", "right", _key_action_move}, { "play", "play", NULL, _key_action_play}, { NULL, NULL, NULL, NULL} }; return &atspi_actions[0]; } /* Standard widget overrides */ ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(elm_player, Elm_Player_Data) /* Efl.Part implementation */ ELM_PART_OVERRIDE(elm_player, ELM_PLAYER, Elm_Player_Data) ELM_PART_OVERRIDE_CONTENT_SET(elm_player, ELM_PLAYER, Elm_Player_Data) ELM_PART_CONTENT_DEFAULT_GET(elm_player, "video") #include "elm_player_part.eo.c" /* End of Efl.Part */ /* Internal EO APIs and hidden overrides */ #define ELM_PLAYER_EXTRA_OPS \ ELM_PART_CONTENT_DEFAULT_OPS(elm_player), \ EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_player) #include "elm_player_eo.c"