video_player.c 22.1 KB
Newer Older
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
1
/*****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
2
 * Copyright © 2015-2016 VideoLAN, VideoLabs SAS
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *****************************************************************************
 *
 * Authors: Nicolas Rechatin [nicolas@videolabs.io]
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/
/*
 * By committing to this project, you allow VideoLAN and VideoLabs to relicense
 * the code to a different OSI approved license, in case it is required for
 * compatibility with the Store
 *****************************************************************************/
#include "common.h"

#include <Evas.h>
29
#include <Elementary.h>
30
#include <Emotion.h>
31
#include <efl_extension.h>
32
#include <sound_manager.h>
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
33

34
#include "ui/interface.h"
35
#include "ui/utils.h"
36
#include "ui/menu/popup_menu.h"
37 38
#include "ui/settings/menu_id.h"
#include "preferences/preferences.h"
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
39
#include "video_player.h"
40
#include "playback_service.h"
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
41

42
struct view_sys
43
{
44 45
    interface *intf;

46 47
    bool b_fill;
    bool b_decoded;
48
    playback_service *p_ps;
49
    playback_service_cbs_id *p_ps_cbs_id;
50 51

    /* Widgets */
52
    Evas_Object *win;
53
    Evas_Object *p_evas_video;
54
    Evas_Object *layout;
55
    Evas_Object *play_pause_button, *progress_slider;
56 57
    Evas_Object *backward_button, *forward_button;
    Evas_Object *lock_button, *more_button;
58
    Evas_Object *p_current_popup;
59

60 61 62 63 64
    /* Gestures */
    bool gesture_volume;
    int display_distance;
    int base_volume;

65 66 67
    /* Orientation */
    bool is_locked;

68
};
69

70 71
static void video_player_stop(view_sys *p_sys);

72 73 74
static void
_on_slider_changed_cb(void *data, Evas_Object *obj, void *event_info)
{
75
    view_sys *p_sys = data;
76

77
    playback_service_seek_pos(p_sys->p_ps, elm_slider_value_get(obj));
78 79
}

80 81 82 83 84 85 86 87 88
static void
video_player_update_play_pause_state(view_sys *p_sys)
{
    elm_image_file_set(p_sys->play_pause_button,
            playback_service_is_playing(p_sys->p_ps) ?
                                   ICON_DIR "ic_pause_circle_normal_o.png" :
                                   ICON_DIR "ic_play_circle_normal_o.png", NULL);
}

89
static void
90
clicked_play_pause(void *data, Evas_Object *obj, void *event_info)
91
{
92
    view_sys *p_sys = data;
93

94 95
    playback_service_toggle_play_pause(p_sys->p_ps);
    video_player_update_play_pause_state(p_sys);
96 97
}

98 99 100
static void
clicked_backward(void *data, Evas_Object *obj, void *event_info)
{
101
    view_sys *p_sys = data;
102

103
    playback_service_seek_backward(p_sys->p_ps);
104 105 106 107 108
}

static void
clicked_forward(void *data, Evas_Object *obj, void *event_info)
{
109
    view_sys *p_sys = data;
110

111
    playback_service_seek_forward(p_sys->p_ps);
112 113
}

114 115 116
static void
clicked_lock(void *data, Evas_Object *obj, void *event_info)
{
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    view_sys *p_sys = data;

    if (!p_sys->is_locked)
    {
        int rotation = elm_win_rotation_get(p_sys->win);
        elm_win_wm_rotation_available_rotations_set(p_sys->win, &rotation, 1);
        elm_image_file_set(p_sys->lock_button, ICON_DIR"ic_locked_circle_normal_o.png", NULL);
        p_sys->is_locked = true;
    }
    else
    {
        int rots[4] = { 0, 90, 180, 270 };
        elm_win_wm_rotation_available_rotations_set(p_sys->win, (const int *)(&rots), 4);
        elm_image_file_set(p_sys->lock_button, ICON_DIR"ic_lock_circle_normal_o.png", NULL);
        p_sys->is_locked = false;
    }
133 134
}

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
void clear_popup_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    view_sys *p_sys = data;
    p_sys->p_current_popup = NULL;
}

void channel_menu_free_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
    popup_menu *menu = data;

    for(int i = 0; menu[i].title != NULL ; i++)
        free(menu[i].title);
    free(menu);
}

150
void
151
audio_channel_selected(void *data, Evas_Object *obj, void *event_info)
152 153 154 155 156 157 158
{
    Elm_Object_Item *it_parent = (Elm_Object_Item*) event_info;
    view_sys *p_sys = data;

    // elm_genlist_item_index_get starts counting at 1 (not 0)
    int index = elm_genlist_item_index_get(it_parent);

159
    playback_service_audio_channel_set(p_sys->p_ps, index - 1);
160
    popup_close(obj);
161 162
}

163 164 165 166 167 168
void
clicked_background_playback(void *data, Evas_Object *obj, void *event_info)
{
    view_sys *p_sys = data;

    if (p_sys->p_current_popup)
169
        popup_close(p_sys->p_current_popup);
170 171 172 173

    playback_service_enable_background_playback(p_sys->p_ps);
}

174 175
void
clicked_audio_tracks(void *data, Evas_Object *obj, void *event_info)
176
{
177 178 179 180
    Eina_List *channel_list, *p_it = NULL;
    view_sys *p_sys = data;
    char *channel_title;
    popup_menu *menu;
181

182
    if (p_sys->p_current_popup)
183
        popup_close(p_sys->p_current_popup);
184 185

    // Get the list of channels
186
    channel_list = playback_service_audio_channel_get_list(p_sys->p_ps);
187 188 189 190 191 192 193 194 195 196 197 198 199

    // Allocate the memory for the menu + 1 (menu + NULL terminating item)
    menu = malloc(sizeof(*menu) * (eina_list_count(channel_list) + 1));

    int i = 0;
    EINA_LIST_FOREACH(channel_list, p_it, channel_title)
    {
        if (channel_title)
            menu[i].title = strdup(channel_title);
        else
            asprintf(&menu[i].title, "Audio channel #%d", i);
        menu[i].icon = NULL;
        menu[i].cb = audio_channel_selected;
200
        menu[i].hidden = EINA_FALSE;
201 202 203 204 205 206 207 208 209 210 211 212 213 214
        i++;
    }

    // NULL terminating item
    menu[i].title = NULL;

    Evas_Object *popup = p_sys->p_current_popup = popup_menu_add(menu, p_sys, p_sys->p_evas_video);
    evas_object_show(popup);

    // Register a callback to free the memory allocated for the menu
    evas_object_event_callback_add(popup, EVAS_CALLBACK_FREE, channel_menu_free_cb, menu);
    evas_object_event_callback_add(popup, EVAS_CALLBACK_FREE, clear_popup_cb, p_sys);

    eina_list_free(channel_list);
215 216
}

217 218
void
spu_selected(void *data, Evas_Object *obj, void *event_info)
219
{
220
    Elm_Object_Item *it_parent = (Elm_Object_Item*) event_info;
221
    view_sys *p_sys = data;
222 223 224 225 226 227

    // elm_genlist_item_index_get starts counting at 1 (not 0)
    int index = elm_genlist_item_index_get(it_parent);

    // Disable subtitles is -1, first is 0 so index -2.
    playback_service_spu_channel_set(p_sys->p_ps, index - 2);
228
    popup_close(obj);
229 230
}

231 232 233 234 235 236 237 238 239
void
clicked_spu(void *data, Evas_Object *obj, void *event_info)
{
    Eina_List *spu_list, *p_it = NULL;
    view_sys *p_sys = data;
    char *spu_title;
    popup_menu *menu;

    if (p_sys->p_current_popup)
240
        popup_close(p_sys->p_current_popup);
241 242

    // Get the list of spu
243
    spu_list = playback_service_spu_channel_get_list(p_sys->p_ps);
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259

    // Prepend the "disable subtitles"
    spu_list = eina_list_prepend(spu_list, "Disable subtitles");

    // Allocate the memory for the menu + 1 (menu + NULL terminating item)
    menu = malloc(sizeof(*menu) * (eina_list_count(spu_list) + 1));

    int i = 0;
    EINA_LIST_FOREACH(spu_list, p_it, spu_title)
    {
        if (spu_title)
            menu[i].title = strdup(spu_title);
        else
            asprintf(&menu[i].title, "Subtitle track #%d", i);
        menu[i].icon = NULL;
        menu[i].cb = spu_selected;
260
        menu[i].hidden = EINA_FALSE;
261 262 263 264 265 266 267 268 269 270
        i++;
    }

    // NULL terminating item
    menu[i].title = NULL;

    Evas_Object *popup = p_sys->p_current_popup = popup_menu_add(menu, p_sys, p_sys->p_evas_video);
    evas_object_show(popup);

    // Register a callback to free the memory allocated for the menu
271
    evas_object_event_callback_add(popup, EVAS_CALLBACK_FREE, channel_menu_free_cb, menu);
272 273 274 275 276 277 278
    evas_object_event_callback_add(popup, EVAS_CALLBACK_FREE, clear_popup_cb, p_sys);

    eina_list_free(spu_list);
}

static popup_menu menu_more[] =
{
279 280 281
        {"Subtitles",           NULL, clicked_spu},
        {"Audio Tracks",        NULL, clicked_audio_tracks},
        {"Background playback", NULL, clicked_background_playback},
282 283 284
        {0}
};

285 286 287
static void
clicked_more(void *data, Evas_Object *obj, void *event_info)
{
288 289
    Eina_List *list;
    int spu_count, audio_tracks_count;
290 291
    view_sys *p_sys = data;

292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
    /* SPU */
    list = playback_service_spu_channel_get_list(p_sys->p_ps);
    spu_count = eina_list_count(list);
    eina_list_free(list);

    /* Audio tracks */
    list = playback_service_audio_channel_get_list(p_sys->p_ps);
    audio_tracks_count = eina_list_count(list);
    eina_list_free(list);

    if (spu_count + audio_tracks_count == 0)
        return;

    menu_more[0].hidden = spu_count == 0;
    menu_more[1].hidden = audio_tracks_count == 0;

308 309 310
    Evas_Object *popup = p_sys->p_current_popup = popup_menu_orient_add(menu_more, ELM_POPUP_ORIENT_CENTER, p_sys, p_sys->p_evas_video);
    evas_object_show(popup);
    evas_object_event_callback_add(popup, EVAS_CALLBACK_FREE, clear_popup_cb, p_sys);
311 312
}

313 314 315
static void
ps_on_new_len_cb(playback_service *p_ps, void *p_user_data, double i_len)
{
316
    view_sys *p_sys = p_user_data;
317

318
    char *str = media_timetostr((int64_t)i_len);
319
    elm_object_part_text_set(p_sys->layout, "duration", str);
320
    free(str);
321 322 323 324 325
}

static void
ps_on_new_time_cb(playback_service *p_ps, void *p_user_data, double i_time, double i_pos)
{
326 327
    view_sys *p_sys = p_user_data;
    elm_slider_value_set(p_sys->progress_slider, i_pos);
328

329
    char *str = media_timetostr((int64_t)i_time);
330
    elm_object_part_text_set(p_sys->layout, "time", str);
331
    free(str);
332 333
}

334 335 336
static void
layout_touch_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
{
337
    view_sys *p_sys = data;
338

339
    elm_object_signal_emit(p_sys->layout, "hub_background,show", "");
340

341 342 343
    LOGF("layout_touch_up_cb");
}

344
static void
345
ps_on_stop_cb(playback_service *p_ps, void *p_user_data)
346
{
347
    view_sys *p_sys = p_user_data;
348
    intf_show_previous_view(p_sys->intf);
349 350
}

351 352 353 354
static void
ps_on_playpause_cb(playback_service *p_ps, void *p_user_data, bool b_playing)
{
    view_sys *p_sys = p_user_data;
355 356 357 358
    elm_image_file_set(p_sys->play_pause_button,
            b_playing ?
                    ICON_DIR "ic_pause_circle_normal_o.png" :
                    ICON_DIR "ic_play_circle_normal_o.png", NULL);
359 360
}

361
bool
362
video_player_start(view_sys *p_sys, const char* file_path, double time)
363
{
364
    /* Screen orientation */
365 366 367
    if (elm_win_wm_rotation_supported_get(p_sys->win)) {
        menu_id orientation = preferences_get_enum(PREF_ORIENTATION, ORIENTATION_AUTOMATIC);

368
        int rotation = -1;
369 370 371

        switch (orientation) {
        case ORIENTATION_LANDSCAPE:
372
            rotation = 270;
373 374
            break;
        case ORIENTATION_PORTRAIT:
375
            rotation = 0;
376 377
            break;
        case ORIENTATION_R_LANDSCAPE:
378
            rotation = 90;
379 380
            break;
        case ORIENTATION_R_PORTRAIT:
381
            rotation = 180;
382 383
            break;
        case ORIENTATION_LOCKED:
384
            rotation = elm_win_rotation_get(p_sys->win);
385 386 387 388 389
            break;
        case ORIENTATION_AUTOMATIC:
        default:
            break;
        }
390 391

        if (rotation >= 0)
392
        {
393
            elm_win_wm_rotation_available_rotations_set(p_sys->win, &rotation, 1);
394 395
            p_sys->is_locked = true;
        }
396 397
    }

398 399 400 401 402 403
    /* Lock button */
    if (p_sys->is_locked)
        elm_image_file_set(p_sys->lock_button, ICON_DIR"ic_locked_circle_normal_o.png", NULL);
    else
        elm_image_file_set(p_sys->lock_button, ICON_DIR"ic_lock_circle_normal_o.png", NULL);

404
    /* */
405 406
    elm_object_part_text_set(p_sys->layout, "duration", "--:--:--");
    elm_object_part_text_set(p_sys->layout, "time", "--:--:--");
407

408 409 410 411
    media_item *p_mi = media_item_create(file_path, MEDIA_ITEM_TYPE_VIDEO);
    if (!p_mi)
        return false;

412 413 414 415 416 417 418 419 420 421 422
    /* layout callbacks */
    evas_object_event_callback_add(p_sys->layout, EVAS_CALLBACK_MOUSE_UP, layout_touch_up_cb, p_sys);
    evas_object_event_callback_add(p_sys->layout, EVAS_CALLBACK_MULTI_UP, layout_touch_up_cb, p_sys);

    /* click callbacks */
    evas_object_smart_callback_add(p_sys->play_pause_button, "clicked", clicked_play_pause, p_sys);
    evas_object_smart_callback_add(p_sys->backward_button, "clicked", clicked_backward, p_sys);
    evas_object_smart_callback_add(p_sys->forward_button, "clicked", clicked_forward, p_sys);
    evas_object_smart_callback_add(p_sys->lock_button, "clicked", clicked_lock, p_sys);
    evas_object_smart_callback_add(p_sys->more_button, "clicked", clicked_more, p_sys);

Ludovic Fauvet's avatar
Ludovic Fauvet committed
423
    /* slider callbacks */
424 425 426
    evas_object_smart_callback_add(p_sys->progress_slider, "slider,drag,stop", _on_slider_changed_cb, p_sys);
    evas_object_smart_callback_add(p_sys->progress_slider, "changed", _on_slider_changed_cb, p_sys);

427 428 429 430
    playback_service_callbacks cbs = {
        .pf_on_new_len = ps_on_new_len_cb,
        .pf_on_new_time = ps_on_new_time_cb,
        .pf_on_stopped = ps_on_stop_cb,
431
        .pf_on_playpause = ps_on_playpause_cb,
432
        .p_user_data = p_sys,
433
        .i_ctx = PLAYLIST_CONTEXT_VIDEO,
434 435 436 437 438 439
    };

    p_sys->p_ps_cbs_id = playback_service_register_callbacks(p_sys->p_ps, &cbs);
    if (!p_sys->p_ps_cbs_id)
    {
        free(p_mi);
440
        video_player_stop(p_sys);
441 442 443
        return false;
    }

444
    playback_service_set_context(p_sys->p_ps, PLAYLIST_CONTEXT_VIDEO);
445

446
    playback_service_list_append(p_sys->p_ps, p_mi);
447
    playback_service_start(p_sys->p_ps, time);
448
    elm_object_signal_emit(p_sys->layout, "hub_background,show", "");
449

450 451 452
    return true;
}

453 454 455
static void
video_player_stop(view_sys *p_sys)
{
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
    /* layout callbacks */
    evas_object_event_callback_del(p_sys->layout, EVAS_CALLBACK_MOUSE_UP, layout_touch_up_cb);
    evas_object_event_callback_del(p_sys->layout, EVAS_CALLBACK_MULTI_UP, layout_touch_up_cb);

    /* click callbacks */
    evas_object_smart_callback_del(p_sys->play_pause_button, "clicked", clicked_play_pause);
    evas_object_smart_callback_del(p_sys->backward_button, "clicked", clicked_backward);
    evas_object_smart_callback_del(p_sys->forward_button, "clicked", clicked_forward);
    evas_object_smart_callback_del(p_sys->lock_button, "clicked", clicked_lock);
    evas_object_smart_callback_del(p_sys->more_button, "clicked", clicked_more);

    /*slider callbacks */
    evas_object_smart_callback_del(p_sys->progress_slider, "slider,drag,stop", _on_slider_changed_cb);
    evas_object_smart_callback_del(p_sys->progress_slider, "changed", _on_slider_changed_cb);

    if (p_sys->p_ps_cbs_id)
    {
        playback_service_unregister_callbacks(p_sys->p_ps, p_sys->p_ps_cbs_id);
        playback_service_list_clear(p_sys->p_ps);
        playback_service_stop(p_sys->p_ps);
476
        p_sys->p_ps_cbs_id = NULL;
477
    }
478 479 480 481

    if (elm_win_wm_rotation_supported_get(p_sys->win)) {
        int rots[4] = { 0, 90, 180, 270 };
        elm_win_wm_rotation_available_rotations_set(p_sys->win, (const int *)(&rots), 4);
482
        p_sys->is_locked = false;
483
    }
484 485
}

486 487 488 489 490 491 492 493
static Evas_Event_Flags
line_start(void *data, void *event_info)
{
   Elm_Gesture_Line_Info *p = (Elm_Gesture_Line_Info *) event_info;
   LOGD("line started angle=<%lf> x1,y1=<%d,%d> x2,y2=<%d,%d> tx,ty=<%u,%u> n=<%u>",
          p->angle, p->momentum.x1, p->momentum.y1, p->momentum.x2, p->momentum.y2,
          p->momentum.tx, p->momentum.ty, p->momentum.n);

494 495 496
   if (p->momentum.y1 < 50 || p->momentum.y2 < 50)
       return EVAS_EVENT_FLAG_NONE;

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
   view_sys *p_sys = data;

   if (p->momentum.n == 1 && (p->angle > 315 || p->angle < 45 || (p->angle > 135 && p->angle < 225)))
   {
       if (sound_manager_get_volume(SOUND_TYPE_MEDIA, &p_sys->base_volume) != 0)
       {
           LOGE("Unable to get the volume.");
           return EVAS_EVENT_FLAG_ON_HOLD;
       }

       int w, h;
       evas_object_geometry_get(p_sys->layout, NULL, NULL, &w, &h);

       p_sys->display_distance = MIN(w, h);

       if (p_sys->display_distance == 0)
           return EVAS_EVENT_FLAG_ON_HOLD;

       p_sys->gesture_volume = true;
   }

   return EVAS_EVENT_FLAG_ON_HOLD;
}

static Evas_Event_Flags
line_move(void *data, void *event_info)
{
   Elm_Gesture_Line_Info *p = (Elm_Gesture_Line_Info *) event_info;
   view_sys *p_sys = data;

   if (p_sys->gesture_volume == true)
   {
       int max;
       if (sound_manager_get_max_volume(SOUND_TYPE_MEDIA, &max) != 0)
           return EVAS_EVENT_FLAG_ON_HOLD;

       int step = p_sys->display_distance / max;
       int diff = p->momentum.y1 - p->momentum.y2;
       int volume = MIN(MAX(0, p_sys->base_volume + (diff / step)), max);

       sound_manager_set_volume(SOUND_TYPE_MEDIA, volume);
       LOGD("Volume: %d (max %d)", volume, max);
539 540 541 542 543

       char *tmp;
       asprintf(&tmp, "Volume: %d%%", (volume * 100) / max);
       elm_object_part_text_set(p_sys->layout, "text_overlay", tmp);
       free(tmp);
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
   }

   return EVAS_EVENT_FLAG_ON_HOLD;
}

static Evas_Event_Flags
line_end(void *data, void *event_info)
{
   Elm_Gesture_Line_Info *p = (Elm_Gesture_Line_Info *) event_info;
   LOGD("line end angle=<%lf> x1,y1=<%d,%d> x2,y2=<%d,%d> tx,ty=<%u,%u> n=<%u>",
          p->angle, p->momentum.x1, p->momentum.y1, p->momentum.x2, p->momentum.y2,
          p->momentum.tx, p->momentum.ty, p->momentum.n);

   view_sys *p_sys = data;

   p_sys->gesture_volume = false;
560
   elm_object_part_text_set(p_sys->layout, "text_overlay", "");
561 562 563 564 565 566 567 568 569 570
   return EVAS_EVENT_FLAG_ON_HOLD;
}

static Evas_Event_Flags
line_abort(void *data, void *event_info)
{
   view_sys *p_sys = data;
   LOGD("line abort");

   p_sys->gesture_volume = false;
571
   elm_object_part_text_set(p_sys->layout, "text_overlay", "");
572 573 574
   return EVAS_EVENT_FLAG_ON_HOLD;
}

575 576
Evas_Object*
video_player_create_ui(view_sys *p_sys, Evas_Object *parent)
577 578
{
    /* Create the layout */
579
    Evas_Object *layout = p_sys->layout = elm_layout_add(parent);
580 581 582 583 584 585 586 587 588 589 590 591 592
    elm_layout_file_set(layout, VIDEOPLAYER_EDJ, "media_player_renderer");
    evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
    evas_object_show(layout);

    /* Create the evas */
    Evas *evas = evas_object_evas_get(layout);
    p_sys->p_evas_video = playback_service_set_evas_video(p_sys->p_ps, evas);

    elm_object_part_content_set(layout, "swallow.visualization", p_sys->p_evas_video);
    emotion_object_keep_aspect_set(p_sys->p_evas_video, EMOTION_ASPECT_KEEP_BOTH);
    evas_object_show(p_sys->p_evas_video);

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    /* Create the gesture layer */
    Evas_Object *r = evas_object_rectangle_add(layout);
    evas_object_color_set(r, 0, 0, 0, 0);
    elm_object_part_content_set(layout, "gesturerect", r);

    Evas_Object *g = elm_gesture_layer_add(layout);
    elm_gesture_layer_attach(g, r);
    evas_object_show(r);

    elm_gesture_layer_continues_enable_set(g, EINA_FALSE);

    elm_gesture_layer_cb_set(g, ELM_GESTURE_N_LINES, ELM_GESTURE_STATE_START,
                             line_start, p_sys);
    elm_gesture_layer_cb_set(g, ELM_GESTURE_N_LINES, ELM_GESTURE_STATE_MOVE,
                             line_move, p_sys);
    elm_gesture_layer_cb_set(g, ELM_GESTURE_N_LINES, ELM_GESTURE_STATE_END,
                             line_end, p_sys);
    elm_gesture_layer_cb_set(g, ELM_GESTURE_N_LINES, ELM_GESTURE_STATE_ABORT,
                             line_abort, p_sys);

613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
    /* create play/pause button */
    p_sys->play_pause_button = elm_image_add(layout);
    elm_image_file_set(p_sys->play_pause_button, ICON_DIR"ic_pause_circle_normal_o.png", NULL);
    /* attach to edje layout */
    elm_object_part_content_set(layout, "swallow.play_button", p_sys->play_pause_button);

    /* create backward button */
    p_sys->backward_button = elm_image_add(layout);
    elm_image_file_set(p_sys->backward_button, ICON_DIR"ic_backward_circle_normal_o.png", NULL);
    elm_object_part_content_set(layout, "swallow.backward_button", p_sys->backward_button);

    /* create forward button */
    p_sys->forward_button = elm_image_add(layout);
    elm_image_file_set(p_sys->forward_button, ICON_DIR"ic_forward_circle_normal_o.png", NULL);
    elm_object_part_content_set(layout, "swallow.forward_button", p_sys->forward_button);

    /* create lock button */
    p_sys->lock_button = elm_image_add(layout);
631 632
    if (elm_win_wm_rotation_supported_get(p_sys->win))
        elm_object_part_content_set(layout, "swallow.lock_button", p_sys->lock_button);
633 634 635 636 637 638 639 640 641 642 643

    /* create more button */
    p_sys->more_button = elm_image_add(layout);
    elm_image_file_set(p_sys->more_button, ICON_DIR"ic_more_circle_normal_o.png", NULL);
    elm_object_part_content_set(layout, "swallow.more_button", p_sys->more_button);

    /* progress slider */
    p_sys->progress_slider = elm_slider_add(layout);
    elm_slider_horizontal_set(p_sys->progress_slider, EINA_TRUE);
    elm_object_part_content_set(layout, "swallow.progress", p_sys->progress_slider);

644 645 646 647 648 649 650 651
    return layout;
}

static bool
video_player_callback(view_sys *p_view_sys, interface_view_event event)
{
    switch (event) {
    case INTERFACE_VIEW_EVENT_MENU:
652
    case INTERFACE_VIEW_EVENT_RESUME:
653 654 655 656 657 658
    {
        layout_touch_up_cb(p_view_sys, NULL, NULL, NULL);
        return true;
    }
    case INTERFACE_VIEW_EVENT_BACK:
        if (p_view_sys->p_current_popup) {
659
            popup_close(p_view_sys->p_current_popup);
660
            p_view_sys->p_current_popup = NULL;
661 662 663 664 665 666 667
            return true;
        }
        return false;
    default:
        break;
    }
    return true;
668 669
}

670
interface_view*
671
create_video_player(interface *intf, playback_service *p_ps, Evas_Object *parent)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
672
{
673 674
    interface_view *view = calloc(1, sizeof(*view));

675 676
    view_sys *p_sys = view->p_view_sys = calloc(1, sizeof(*p_sys));
    if (!p_sys)
677 678
        return NULL;

679
    p_sys->intf = intf;
680
    p_sys->p_ps = p_ps;
681 682 683
    p_sys->win = intf_get_window(intf);

    view->view = video_player_create_ui(p_sys, parent);
684
    view->p_view_sys = p_sys;
685
    view->pf_event = video_player_callback;
686
    view->pf_stop = video_player_stop;
687
    view->i_type = VIEW_UNKNOWN;
688

689
    return view;
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
690
}
691 692 693 694

void
destroy_video_player(interface_view *view)
{
695 696
    if (view == NULL)
        return;
697
    video_player_stop(view->p_view_sys);
698
    playback_service_set_evas_video(view->p_view_sys->p_ps, NULL);
699 700
    free(view->p_view_sys);
    free(view);
701
}