video_view.c 8.78 KB
Newer Older
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
1 2 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
/*****************************************************************************
 * Copyright © 2015 VideoLAN, VideoLabs SAS
 *****************************************************************************
 *
 * 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"

29
#include "controller/video_controller.h"
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
30
#include "ui/interface.h"
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
31 32 33
#include "video_view.h"
#include "video_player.h"

34 35
#include "ui/utils.h"

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
36
#include "media/media_item.h"
37

38 39
#include <Elementary.h>

40
struct view_sys
41
{
42 43
    interface *p_intf;

44 45
    Evas_Object *p_parent;
    Evas_Object *p_genlist;
46
    video_controller* p_controller;
47 48
    Elm_Genlist_Item_Class* p_default_itc;

49
};
50

51 52
typedef struct video_list_item
{
53
    view_sys *videoview;
54

55 56
    const Elm_Genlist_Item_Class *itc;

57
    media_item *p_media_item;
58

59 60 61
    //For refresh purposes.
    Elm_Object_Item* p_object_item;

62
} video_list_item;
63

Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
64
void
65
genlist_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
66
{
67
    video_list_item *vli = data;
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
68

Thomas Guillem's avatar
Thomas Guillem committed
69
    struct stat sb;
70
    stat(vli->p_media_item->psz_path, &sb);
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
71

72
    //FIXME: This should probably go away since we now have a flattened video list.
73 74
    if (S_ISREG(sb.st_mode))
    {
75
        intf_create_video_player(vli->videoview->p_intf, vli->p_media_item->psz_path);
Thomas Guillem's avatar
Thomas Guillem committed
76
    }
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
77 78 79
}

static void
80
free_list_item(void *data, Evas_Object *obj, void *event_info)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
81
{
82
    video_list_item *vli = data;
83
    media_item_destroy(vli->p_media_item);
84
    free(vli);
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
85 86 87
}

static Evas_Object*
88
create_default_icon(Evas_Object *parent)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
89
{
90
    return create_image(parent, "background_cone.png");
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
91 92
}

93
static char *
94 95 96 97 98 99 100 101 102 103 104 105 106 107
duration_string(int64_t duration)
{
    lldiv_t d;
    long long sec;
    char *str;

    duration /= 1000;
    d = lldiv(duration, 60);
    sec = d.rem;
    d = lldiv(d.quot, 60);
    asprintf(&str, "%02lld:%02lld:%02lld", d.quot, d.rem, sec);
    return str;
}

Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
108
static char *
109
genlist_text_get_cb(void *data, Evas_Object *obj, const char *part)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
110
{
111 112
    video_list_item *vli = data;
    const Elm_Genlist_Item_Class *itc = vli->itc;
Thomas Guillem's avatar
Thomas Guillem committed
113 114 115 116 117

    /* Check the item class style and put the current folder or file name as a string */
    /* Then put this string as the genlist item label */
    if (itc->item_style && !strcmp(itc->item_style, "2line.top.3")) {
        if (part && !strcmp(part, "elm.text.main.left.top")) {
118
            char buf[PATH_MAX];
119
            snprintf(buf, 1023, "<b>%s</b>", media_item_title(vli->p_media_item));
Thomas Guillem's avatar
Thomas Guillem committed
120 121 122
            return strdup(buf);
        }
        else if (!strcmp(part, "elm.text.sub.left.bottom")) {
123
            if(vli->p_media_item->i_duration < 0)
124 125
                return NULL;
            else
126
                return duration_string(vli->p_media_item->i_duration);
Thomas Guillem's avatar
Thomas Guillem committed
127 128
        }
        else if (!strcmp(part, "elm.text.sub.right.bottom")) {
129
            if (vli->p_media_item->i_w <= 0 || vli->p_media_item->i_h <= 0)
130 131
                return NULL;
            char *str_resolution;
132
            asprintf( &str_resolution, "%dx%d", vli->p_media_item->i_w, vli->p_media_item->i_h);
133
            return str_resolution;
Thomas Guillem's avatar
Thomas Guillem committed
134 135 136
        }
    }
    return NULL;
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
137 138
}

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
const media_item*
video_list_item_get_media_item(video_list_item* p_item)
{
    return p_item->p_media_item;
}

void
video_list_item_set_media_item(video_list_item* p_item, const media_item* p_media_item)
{
    LOGI("Received update request for [%s]", p_media_item->psz_path);
    bool b_changed = false;
    if (p_item->p_media_item->i_duration != p_media_item->i_duration)
    {
        LOGI("Updated duration");
        p_item->p_media_item->i_duration = p_media_item->i_duration;
        b_changed = true;
    }
    if (b_changed == true)
    {
        ecore_main_loop_thread_safe_call_async(elm_genlist_item_update, p_item->p_object_item);
    }
}

Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
162
static Evas_Object*
163
genlist_content_get_cb(void *data, Evas_Object *obj, const char *part)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
164
{
165 166 167 168
    video_list_item *vli = data;
    const Elm_Genlist_Item_Class *itc = vli->itc;

    Evas_Object *layout = NULL;
Thomas Guillem's avatar
Thomas Guillem committed
169 170 171 172 173

    /* Check the item class style and add the object needed in the item class*/
    /* Here, puts the icon in the item class to add it to genlist items */
    if (itc->item_style && !strcmp(itc->item_style, "2line.top.3")) {
        if (part && !strcmp(part, "elm.icon.1")) {
174 175 176 177
            layout = elm_layout_add(obj);
            elm_layout_theme_set(layout, "layout", "list/B/type.1", "default");
            Evas_Object *icon = create_default_icon(layout);
            elm_layout_content_set(layout, "elm.swallow.content", icon);
Thomas Guillem's avatar
Thomas Guillem committed
178 179 180
        }
    }

181
    return layout;
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
182 183 184
}

static void
185
genlist_loaded_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
186
{
Thomas Guillem's avatar
Thomas Guillem committed
187
    /* Set the callbacks when one of the genlist item is loaded */
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
188 189 190
}

static void
191
genlist_realized_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
192
{
Thomas Guillem's avatar
Thomas Guillem committed
193
    /* Set the callbacks when one of the genlist item is realized */
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
194 195 196
}

static void
197
genlist_longpressed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
198
{
Thomas Guillem's avatar
Thomas Guillem committed
199
    /* Set the callbacks when one of the genlist item is longpress */
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
200 201 202
}

static void
203
genlist_contracted_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
204
{
Thomas Guillem's avatar
Thomas Guillem committed
205
    Elm_Object_Item *it = event_info;
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
206

Thomas Guillem's avatar
Thomas Guillem committed
207 208
    /* Free the genlist subitems when contracted */
    elm_genlist_item_subitems_clear(it);
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
209 210
}

211
video_list_item *
212
video_view_append_item(view_sys *videoview, media_item* p_item)
213 214 215
{
    /* */
    video_list_item *vli = calloc(1, sizeof(*vli));
216 217
    if (vli == NULL)
        return NULL;
218
    vli->videoview = videoview;
219
    vli->itc = videoview->p_default_itc;
220 221

    /* Item instantiation */
222
    vli->p_media_item = p_item;
223
    /* Set and append new item in the genlist */
224 225
    vli->p_object_item = elm_genlist_item_append(videoview->p_genlist,
            vli->itc,                       /* genlist item class               */
226 227 228 229 230
            vli,                            /* genlist item class user data     */
            NULL,                           /* genlist parent item for trees    */
            ELM_GENLIST_ITEM_NONE,          /* genlist item type                */
            genlist_item_selected_cb,       /* genlist select smart callback    */
            vli);                           /* genlist smart callback user data */
231 232 233 234 235
    if (vli->p_object_item == NULL)
    {
        free(vli);
        return NULL;
    }
236
    /* */
237
    elm_object_item_del_cb_set(vli->p_object_item, free_list_item);
238
    return vli;
239 240 241
}

void
242
video_view_clear(view_sys* videoview)
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
243
{
244
    elm_genlist_clear(videoview->p_genlist);
245 246
}

247
interface_view*
248
create_video_view(interface *intf, Evas_Object *parent)
249
{
250
    interface_view *view = calloc(1, sizeof(*view));
251
    view_sys *vv = malloc(sizeof(*vv));
252 253
    vv->p_intf = intf;
    vv->p_parent = parent;
254
    vv->p_controller = video_controller_create(intf_get_application(intf), vv);
255

256 257 258 259 260 261
    /* Genlist class */
    vv->p_default_itc = elm_genlist_item_class_new();
    //FIXME: this is leaking, please call elm_genlist_item_class_free() from somewhere
    vv->p_default_itc->item_style = "2line.top.3";
    vv->p_default_itc->func.text_get = genlist_text_get_cb;
    vv->p_default_itc->func.content_get = genlist_content_get_cb;
262
    view->p_view_sys = vv;
263

264
    /* Set then create the Genlist object */
265 266 267
    Evas_Object *genlist = vv->p_genlist = elm_genlist_add(parent);

    /* Set the genlist modes */
268 269 270 271 272
    elm_scroller_single_direction_set(genlist, ELM_SCROLLER_SINGLE_DIRECTION_HARD);
    elm_genlist_homogeneous_set(genlist, EINA_TRUE);
    elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);

    /* Set smart Callbacks */
273 274 275 276
    evas_object_smart_callback_add(genlist, "realized", genlist_realized_cb, NULL);
    evas_object_smart_callback_add(genlist, "loaded", genlist_loaded_cb, NULL);
    evas_object_smart_callback_add(genlist, "longpressed", genlist_longpressed_cb, NULL);
    evas_object_smart_callback_add(genlist, "contracted", genlist_contracted_cb, NULL);
277

278 279
    view->view = genlist;

Thomas Guillem's avatar
Thomas Guillem committed
280
    /* */
281
    return view;
Nicolas Pomepuy's avatar
Nicolas Pomepuy committed
282
}