media.c 8.15 KB
Newer Older
Pierre's avatar
Pierre committed
1 2 3 4 5 6 7
/*
 * media_player.c - libvlc smoke test
 *
 * $Id$
 */

/**********************************************************************
Pierre's avatar
Pierre committed
8
 *  Copyright (C) 2010 Pierre d'Herbemont.                            *
Pierre's avatar
Pierre committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *  This program is free software; you can redistribute and/or modify *
 *  it under the terms of the GNU General Public License as published *
 *  by the Free Software Foundation; 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, you can get it from:             *
 *  http://www.gnu.org/copyleft/gpl.html                              *
 **********************************************************************/

#include "test.h"
25 26 27 28 29
#include "../lib/libvlc_internal.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
Pierre's avatar
Pierre committed
30

31
#include <vlc_threads.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
32
#include <vlc_fs.h>
33

34
static void media_parse_ended(const libvlc_event_t *event, void *user_data)
Pierre's avatar
Pierre committed
35 36
{
    (void)event;
Thomas Guillem's avatar
Thomas Guillem committed
37 38
    vlc_sem_t *sem = user_data;
    vlc_sem_post (sem);
Pierre's avatar
Pierre committed
39 40
}

41 42 43 44
static void test_media_preparsed(int argc, const char** argv,
                                 const char *path,
                                 const char *location,
                                 libvlc_media_parsed_status_t i_expected_status)
Pierre's avatar
Pierre committed
45
{
46 47
    log ("test_media_preparsed: %s, expected: %d\n", path ? path : location,
         i_expected_status);
Pierre's avatar
Pierre committed
48 49 50 51

    libvlc_instance_t *vlc = libvlc_new (argc, argv);
    assert (vlc != NULL);

52 53 54 55 56
    libvlc_media_t *media;
    if (path != NULL)
        media = libvlc_media_new_path (vlc, path);
    else
        media = libvlc_media_new_location (vlc, location);
Pierre's avatar
Pierre committed
57 58
    assert (media != NULL);

Thomas Guillem's avatar
Thomas Guillem committed
59 60
    vlc_sem_t sem;
    vlc_sem_init (&sem, 0);
Pierre's avatar
Pierre committed
61

Pierre's avatar
Pierre committed
62
    // Check to see if we are properly receiving the event.
Pierre's avatar
Pierre committed
63
    libvlc_event_manager_t *em = libvlc_media_event_manager (media);
64
    libvlc_event_attach (em, libvlc_MediaParsedChanged, media_parse_ended, &sem);
Pierre's avatar
Pierre committed
65

Pierre's avatar
Pierre committed
66
    // Parse the media. This is synchronous.
67
    int i_ret = libvlc_media_parse_with_options(media, libvlc_media_parse_local, -1);
68
    assert(i_ret == 0);
Pierre's avatar
Pierre committed
69

70
    // Wait for preparsed event
Thomas Guillem's avatar
Thomas Guillem committed
71 72
    vlc_sem_wait (&sem);
    vlc_sem_destroy (&sem);
Pierre's avatar
Pierre committed
73 74

    // We are good, now check Elementary Stream info.
75
    assert (libvlc_media_get_parsed_status(media) == i_expected_status);
76

Pierre's avatar
Pierre committed
77 78 79 80
    libvlc_media_release (media);
    libvlc_release (vlc);
}

81
#define TEST_SUBITEMS_COUNT 6
82
static struct
83 84 85 86 87 88 89 90 91 92 93 94 95
{
    const char *file;
    libvlc_media_type_t type;
} test_media_subitems_list[TEST_SUBITEMS_COUNT] =
{
    { "directory", libvlc_media_type_directory, },
    { "file.jpg", libvlc_media_type_file },
    { "file.mkv", libvlc_media_type_file },
    { "file.mp3", libvlc_media_type_file },
    { "file.png", libvlc_media_type_file },
    { "file.ts", libvlc_media_type_file },
};

96
static void subitem_parse_ended(const libvlc_event_t *event, void *user_data)
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
{
    (void)event;
    vlc_sem_t *sem = user_data;
    vlc_sem_post (sem);
}

static void subitem_added(const libvlc_event_t *event, void *user_data)
{
#ifdef _WIN32
#define FILE_SEPARATOR   '\\'
#else
#define FILE_SEPARATOR   '/'
#endif
    bool *subitems_found = user_data;
    libvlc_media_t *m = event->u.media_subitem_added.new_child;
    assert (m);

    char *mrl = libvlc_media_get_mrl (m);
    assert (mrl);

    const char *file = strrchr (mrl, FILE_SEPARATOR);
    assert (file);
    file++;
    log ("subitem_added, file: %s\n", file);

    for (unsigned i = 0; i < TEST_SUBITEMS_COUNT; ++i)
    {
        if (strcmp (test_media_subitems_list[i].file, file) == 0)
        {
            assert (!subitems_found[i]);
            assert (libvlc_media_get_type(m) == test_media_subitems_list[i].type);
            subitems_found[i] = true;
        }
    }
    free (mrl);
#undef FILE_SEPARATOR
}

135 136
static void test_media_subitems_media(libvlc_media_t *media, bool play,
                                      bool b_items_expected)
137 138 139 140 141 142 143 144 145 146 147 148
{
    libvlc_media_add_option(media, ":ignore-filetypes= ");

    bool subitems_found[TEST_SUBITEMS_COUNT] = { 0 };
    vlc_sem_t sem;
    vlc_sem_init (&sem, 0);

    libvlc_event_manager_t *em = libvlc_media_event_manager (media);
    libvlc_event_attach (em, libvlc_MediaSubItemAdded, subitem_added, subitems_found);

    if (play)
    {
149 150 151 152 153
        /* XXX: libvlc_media_parse_with_options won't work with fd, since it
         * won't be preparsed because fd:// is an unknown type, so play the
         * file to force parsing. */
        libvlc_event_attach (em, libvlc_MediaSubItemTreeAdded, subitem_parse_ended, &sem);

154 155 156 157 158 159 160 161
        libvlc_media_player_t *mp = libvlc_media_player_new_from_media (media);
        assert (mp);
        assert (libvlc_media_player_play (mp) != -1);
        vlc_sem_wait (&sem);
        libvlc_media_player_release (mp);
    }
    else
    {
162
        libvlc_event_attach (em, libvlc_MediaParsedChanged, subitem_parse_ended, &sem);
163

164
        int i_ret = libvlc_media_parse_with_options(media, libvlc_media_parse_local, -1);
165
        assert(i_ret == 0);
166 167 168 169 170
        vlc_sem_wait (&sem);
    }

    vlc_sem_destroy (&sem);

171 172 173
    if (!b_items_expected)
        return;

174 175 176 177 178 179 180
    for (unsigned i = 0; i < TEST_SUBITEMS_COUNT; ++i)
    {
        log ("test if %s was added\n", test_media_subitems_list[i].file);
        assert (subitems_found[i]);
    }
}

181
static void test_media_subitems(int argc, const char** argv)
182 183 184 185 186 187 188 189 190 191
{
    const char *subitems_path = SRCDIR"/samples/subitems";

    libvlc_instance_t *vlc = libvlc_new (argc, argv);
    assert (vlc != NULL);
    libvlc_media_t *media;

    log ("Testing media_subitems: path: '%s'\n", subitems_path);
    media = libvlc_media_new_path (vlc, subitems_path);
    assert (media != NULL);
192
    test_media_subitems_media (media, false, true);
193 194
    libvlc_media_release (media);

195
    #define NB_LOCATIONS 2
196 197
    char *subitems_realpath = realpath (subitems_path, NULL);
    assert (subitems_realpath != NULL);
198
    const char *schemes[NB_LOCATIONS] = { "file://", "dir://" };
199 200 201 202 203 204 205
    for (unsigned i = 0; i < NB_LOCATIONS; ++i)
    {
        char *location;
        assert (asprintf (&location, "%s%s", schemes[i], subitems_realpath) != -1);
        log ("Testing media_subitems: location: '%s'\n", location);
        media = libvlc_media_new_location (vlc, location);
        assert (media != NULL);
206
        test_media_subitems_media (media, false, true);
207 208 209 210 211
        free (location);
        libvlc_media_release (media);
    }
    free (subitems_realpath);

212 213
#ifdef HAVE_OPENAT
    /* listing directory via a fd works only if HAVE_OPENAT is defined */
214 215 216 217 218
    int fd = open (subitems_path, O_RDONLY);
    log ("Testing media_subitems: fd: '%d'\n", fd);
    assert (fd >= 0);
    media = libvlc_media_new_fd (vlc, fd);
    assert (media != NULL);
219
    test_media_subitems_media (media, true, true);
220
    libvlc_media_release (media);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
221
    vlc_close (fd);
222 223 224
#else
#warning not testing subitems list via a fd location
#endif
225

226 227 228 229 230 231
    log ("Testing media_subitems failure\n");
    media = libvlc_media_new_location (vlc, "wrongfile://test");
    assert (media != NULL);
    test_media_subitems_media (media, false, false);
    libvlc_media_release (media);

232 233 234
    libvlc_release (vlc);
}

Pierre's avatar
Pierre committed
235 236 237 238
int main (void)
{
    test_init();

239 240
    test_media_preparsed (test_defaults_nargs, test_defaults_args,
                          SRCDIR"/samples/image.jpg", NULL,
241
                          libvlc_media_parsed_status_done);
242 243
    test_media_preparsed (test_defaults_nargs, test_defaults_args,
                          NULL, "http://parsing_should_be_skipped.org/video.mp4",
244
                          libvlc_media_parsed_status_skipped);
245 246
    test_media_preparsed (test_defaults_nargs, test_defaults_args,
                          NULL, "unknown://parsing_should_be_skipped.org/video.mp4",
247
                          libvlc_media_parsed_status_skipped);
248
    test_media_subitems (test_defaults_nargs, test_defaults_args);
Pierre's avatar
Pierre committed
249 250 251

    return 0;
}