Multimedia Tutorial

In this tutorial, we will see how to play a multimedia file (video) in an application.

Table of Contents

Multimedia example: The whole code__: multimedia.c
The EFL have a special library for multimedia file playing purposes: Emotion. That library has some wrappers in Elementary to let you easily write applications: these are Elm_Video and Elm_Player. * Elm_Video provides a simple video object. * Elm_Player provides an interface to show a bar with basic actions (like rewind, fast forward, pause, etc.) to interract with a playing video. ———– === Basic video widgets === <code c> Evas_Object *video; video = elm_video_add(win); evas_object_size_hint_weight_set(video, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_video_file_set(video, FILE); elm_video_play(video); evas_object_show(video); </code> Create a new Elm_Video object. This object is the main widget for a video. The actual video file is then set (which is here the FILE macro). Elm_Video can take either a path to a file or any kind of URL. Finally, the video starts playing <code c> Evas_Object *player; player = elm_player_add(win); evas_object_size_hint_weight_set(player, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_content_set(player, video); evas_object_smart_callback_add(player, “info,clicked”, _player_info_cb, video); evas_object_show(player); </code> Now create an Elm_Player object. This object wraps around an Elm_Video to have it automatically resized, to show a user interface with basic buttons, a progress bar and other stuff. A callback is added for the info,clicked event, which is launched when the user clicks on the information button in the player interface. This callback will be detailed further. The player interface is eventually set as a naviframe item. <code c> Elm_Object_Item *it = elm_naviframe_item_push(nav, “Video”, NULL, NULL, player, NULL); elm_naviframe_item_title_enabled_set(it, EINA_FALSE, EINA_FALSE); </code> === Getting more information === The purpose is to display some information about the video the user wants to. For instance, the video file name, its location, duration, and image size will be displayed. This list is of course not exhaustive and much more information could be added. Some are not directly available in Elm_Video nor in Elm_Player. But the underlaying Emotion object is available with the elm_video_emotion_get(video) function. == Playing Status == Set the label to display the playing status in _player_info_cb. <code c> label = elm_label_add(table); evas_object_show(label); _player_info_status_update(label, emotion, NULL); elm_table_pack(table, label, 0, 0, 2, 1); evas_object_smart_callback_add(emotion, “playback_finished”, _player_info_status_update, label); </code> That function is also registered as a callback upon playback_finished so that the status is updated upon playback completion. Get the playing status with _player_info_status_update callback: The emotion_object_play_get return true if the video is playing, if not the video is in paused or ended. <code c> static void _player_info_status_update(void *data, Evas_Object *obj, void *event_info) { Evas_Object *emotion = obj, *label = data; char buf[256];
switch on main item if (!info) { evas_object_smart_callback_del(obj, “playback_finished”, _player_info_status_update); return; } update double position = emotion_object_position_get(emotion); double duration = emotion_object_play_length_get(emotion); if (emotion_object_play_get(emotion)) elm_object_text_set(label, “<b>Playing</b>”); else if (position < duration) elm_object_text_set(label, “<b>Paused</b>”); else elm_object_text_set(label, “<b>Ended</b>”); } </code> == Get the file name and location == Get the file name and location with emotion_object_file_get and ecore_file_file_get functions. <code c> label = elm_label_add(table); elm_object_text_set(label, “File:”); evas_object_show(label); elm_table_pack(table, label, 0, 1, 1, 1); const char *file = emotion_object_file_get(emotion); label = elm_label_add(table); elm_object_text_set(label, ecore_file_file_get(file)); evas_object_show(label); elm_table_pack(table, label, 1, 1, 1, 1); label = elm_label_add(table); elm_object_text_set(label, “Location:”); evas_object_show(label); elm_table_pack(table, label, 0, 2, 1, 1); label = elm_label_add(table); elm_object_text_set(label, ecore_file_dir_get(file)); evas_object_show(label); elm_table_pack(table, label, 1, 2, 1, 1); </code> == Get time position and duration == Get video time position and duration using elm_video_play_position_get and elm_video_play_length_get functions. These functions returns double time values in seconds. <code c> label = elm_label_add(table); elm_object_text_set(label, “Time:”); evas_object_show(label); elm_table_pack(table, label, 0, 3, 1, 1); label = elm_label_add(table); double position = elm_video_play_position_get(video); double duration = elm_video_play_length_get(video); int p_sec = (int) position % 60; int p_min = position / 60; int p_hour = position / 3600; int d_sec = (int) duration % 60; int d_min = duration / 60; int d_hour = duration / 3600; snprintf(buf, sizeof(buf), “%d:%02d:%02d / %d:%02d:%02d”, p_hour, p_min, p_sec, d_hour, d_min, d_sec); elm_object_text_set(label, buf); evas_object_show(label); elm_table_pack(table, label, 1, 3, 1, 1); evas_object_smart_callback_add(emotion, “position_update”, _player_info_time_update, label); evas_object_smart_callback_add(emotion, “length_change”, _player_info_time_update, label); </code> Here, a callback on both position_update and length_change events are added so that timings are always up-to-date. <code c> static void _player_info_time_update(void *data, Evas_Object *obj, void *event_info) { Evas_Object *emotion = obj, *label = data; char buf[256]; switch on main item if (!info) { evas_object_smart_callback_del(emotion, “position_update”, _player_info_time_update); evas_object_smart_callback_del(emotion, “length_change”, _player_info_time_update); return; } update double position = emotion_object_position_get(emotion); double duration = emotion_object_play_length_get(emotion); int p_sec = (int) position % 60; int p_min = position / 60; int p_hour = position / 3600; int d_sec = (int) duration % 60; int d_min = duration / 60; int d_hour = duration / 3600; snprintf(buf, sizeof(buf), “%d:%02d:%02d / %d:%02d:%02d”, p_hour, p_min, p_sec, d_hour, d_min, d_sec); elm_object_text_set(label, buf); } </code> In this callback, the emotion functions emotion_object_position_get and emotion_object_play_length_get are used instead of elm_video_play_position_get and elm_video_play_length_get. They have the exact same semantics, but are shown here so that you know that some data exposed through Emotion may also be available thanks to Elm_Video: _player_info_status_update could also have been called directly after the widget creation as for _player_info_time_update. == Get the video dimensions == Finally get the video dimensions using emotion_object_size_get by giving width and height pointers as parameters: <code c> label = elm_label_add(table); elm_object_text_set(label, “Size:”); evas_object_show(label); elm_table_pack(table, label, 0, 4, 1, 1); label = elm_label_add(table); int w, h; emotion_object_size_get(emotion, &w, &h); snprintf(buf, sizeof(buf), “%d × %d”, w, h); elm_object_text_set(label, buf); evas_object_show(label); elm_table_pack(table, label, 1, 4, 1, 1); </code> All of this is shown in a separate naviframe item. <code c> Elm_Object_Item *it = elm_naviframe_item_push(nav, “Information”, NULL, NULL, table, NULL); elm_naviframe_item_pop_cb_set(it, _player_info_del_cb, NULL); </code> The _player_info_del_cb function is here registered in order to be called when the naviframe item is popped. This callback sets the global boolean info to EINA_FALSE, and so allows other delete callbacks to be called.
The whole code__:
multimedia.c