cedric pushed a commit to branch master. http://git.enlightenment.org/website/www-content.git/commit/?id=5e59030540671b4ebe808ac44df40fb94a251700
commit 5e59030540671b4ebe808ac44df40fb94a251700 Author: Clément Bénier <clement.ben...@openwide.fr> Date: Tue Jul 21 14:03:18 2015 +0200 Wiki pages multimedia_tutorial created: tuto + 2 images + code c Signed-off-by: Clément Bénier <clement.ben...@openwide.fr> --- media/code_c/tutorial/multimedia/multimedia.c | 196 ++++++++++++++++++++ media/multimedia.png | Bin 0 -> 215119 bytes media/multimedia_info.png | Bin 0 -> 22726 bytes pages/docs.txt | 1 + pages/tutorial/multimedia_tutorial.txt | 254 ++++++++++++++++++++++++++ 5 files changed, 451 insertions(+) diff --git a/media/code_c/tutorial/multimedia/multimedia.c b/media/code_c/tutorial/multimedia/multimedia.c new file mode 100644 index 0000000..6b9c9be --- /dev/null +++ b/media/code_c/tutorial/multimedia/multimedia.c @@ -0,0 +1,196 @@ +#include <Elementary.h> +#include <Emotion.h> + +#define FILE "<pathToYourVideo>/big_buck_bunny_1080p_h264.mov" + +static Evas_Object *nav; +static Eina_Bool info; //if displaying info item + +/* Time position and duration update */ +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); +} + +/* get update status */ +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>"); +} + +/* del info item callback */ +static Eina_Bool +_player_info_del_cb(void *data, Elm_Object_Item *it) +{ + info = EINA_FALSE; + return EINA_TRUE; +} + +/* info callback */ +static void +_player_info_cb(void *data, Evas_Object *obj, void *event_info) +{ + Evas_Object *video = data, *emotion; + Evas_Object *table, *label; + char buf[256]; + + emotion = elm_video_emotion_get(video); + info = EINA_TRUE; + table = elm_table_add(obj); + elm_table_padding_set(table, 8, 8); + evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(table); + + /* display the playing status in label */ + 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); + + /* get the file name and location */ + //set file label + label = elm_label_add(table); + elm_object_text_set(label, "File:"); + evas_object_show(label); + elm_table_pack(table, label, 0, 1, 1, 1); + + //set file name label + 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); + + //set location label + label = elm_label_add(table); + elm_object_text_set(label, "Location:"); + evas_object_show(label); + elm_table_pack(table, label, 0, 2, 1, 1); + + //set location path label + label = elm_label_add(table); + elm_object_text_set(label, ecore_file_dir_get(file)); + elm_object_text_set(label,"/home/efl/videos"); + evas_object_show(label); + elm_table_pack(table, label, 1, 2, 1, 1); + + /* get the video position and duration */ + //set time label + label = elm_label_add(table); + elm_object_text_set(label, "Time:"); + evas_object_show(label); + elm_table_pack(table, label, 0, 3, 1, 1); + + //set position-duration label + 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); + elm_table_pack(table, label, 1, 3, 1, 1); + evas_object_show(label); + 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); + + /* get the video dimensions */ + 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); + + /* push info in a separate naviframe item */ + 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); +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Evas_Object *win; + info = EINA_FALSE; + win = elm_win_util_standard_add("main", "Multimedia Tutorial"); + evas_object_show(win); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + elm_win_autodel_set(win, EINA_TRUE); + nav = elm_naviframe_add(win); + evas_object_size_hint_weight_set(nav, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, nav); + evas_object_show(nav); + + 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); + + 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); + + 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); + + elm_run(); + elm_shutdown(); + return EXIT_SUCCESS; +} +ELM_MAIN() diff --git a/media/multimedia.png b/media/multimedia.png new file mode 100644 index 0000000..e03efd9 Binary files /dev/null and b/media/multimedia.png differ diff --git a/media/multimedia_info.png b/media/multimedia_info.png new file mode 100644 index 0000000..1c26283 Binary files /dev/null and b/media/multimedia_info.png differ diff --git a/pages/docs.txt b/pages/docs.txt index 9e89660..1d15295 100644 --- a/pages/docs.txt +++ b/pages/docs.txt @@ -51,6 +51,7 @@ Go check the current available version of EFL on each distro/platform: * [[tutorial/gl_2d_tutorial|GL 2D Tutorial]] * [[tutorial/preference_tutorial|Preference Tutorial]] * [[tutorial/effects_tutorial|Effects Tutorial]] + * [[tutorial/multimedia_tutorial|Effects Tutorial]] ---- diff --git a/pages/tutorial/multimedia_tutorial.txt b/pages/tutorial/multimedia_tutorial.txt new file mode 100644 index 0000000..9be66ce --- /dev/null +++ b/pages/tutorial/multimedia_tutorial.txt @@ -0,0 +1,254 @@ +~~Title: Multimedia Tutorial~~ +==== Multimedia Tutorial ==== + +In this tutorial, we will see how to play a multimedia file (video) in an +application. + +=== Table of Contents === + + * [[#Basic_video_widgets|Basic video widgets]] + * [[#Getting_more_information|Getting more information]] + * [[#Playing_Status|Playing Status]] + * [[#Get_the_file_name_and_location|Get the file name and location]] + * [[#Get_time_position_and_duration|Get time position and duration]] + * [[#Get_the_video_dimensions|Get the video dimensions]] + +Multimedia example: {{ :multimedia.png }} +//**__The whole code__: **//{{:code_c/tutorial/multimedia/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. + +{{ :multimedia_info.png }} +\\ +//**__The whole code__: **//{{:code_c/tutorial/multimedia/multimedia.c}} --