Wiki pages multimedia_tutorial created: tuto + 2 images + code c

Signed-off-by: Clément Bénier <clement.benier@openwide.fr>
This commit is contained in:
Clément Bénier 2015-07-21 14:03:18 +02:00 committed by Cedric BAIL
parent 391e5c41dc
commit 5e59030540
5 changed files with 451 additions and 0 deletions

View File

@ -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()

BIN
media/multimedia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
media/multimedia_info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -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]]
----

View File

@ -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}}