media.c 24.9 KB
Newer Older
1
/*****************************************************************************
2
 * media.c: Libvlc API media descripor management
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2007 VLC authors and VideoLAN
5 6 7 8
 * $Id$
 *
 * Authors: Pierre d'Herbemont <pdherbemont@videolan.org>
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
9 10 11
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
12 13 14 15
 * (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
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
16 17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
18
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
19 20 21
 * You should have received a copy of the GNU Lesser 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.
22 23
 *****************************************************************************/

Geoffroy Couprie's avatar
Geoffroy Couprie committed
24 25 26 27
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

28 29
#include <assert.h>

30
#include <vlc/libvlc.h>
31 32 33 34 35
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_media_list.h> // For the subitems, here for convenience
#include <vlc/libvlc_events.h>

#include <vlc_common.h>
36 37
#include <vlc_input.h>
#include <vlc_meta.h>
38
#include <vlc_playlist.h> /* For the preparser */
39
#include <vlc_url.h>
40

41
#include "../src/libvlc.h"
42 43 44

#include "libvlc_internal.h"
#include "media_internal.h"
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
static const vlc_meta_type_t libvlc_to_vlc_meta[] =
{
    [libvlc_meta_Title]        = vlc_meta_Title,
    [libvlc_meta_Artist]       = vlc_meta_Artist,
    [libvlc_meta_Genre]        = vlc_meta_Genre,
    [libvlc_meta_Copyright]    = vlc_meta_Copyright,
    [libvlc_meta_Album]        = vlc_meta_Album,
    [libvlc_meta_TrackNumber]  = vlc_meta_TrackNumber,
    [libvlc_meta_Description]  = vlc_meta_Description,
    [libvlc_meta_Rating]       = vlc_meta_Rating,
    [libvlc_meta_Date]         = vlc_meta_Date,
    [libvlc_meta_Setting]      = vlc_meta_Setting,
    [libvlc_meta_URL]          = vlc_meta_URL,
    [libvlc_meta_Language]     = vlc_meta_Language,
    [libvlc_meta_NowPlaying]   = vlc_meta_NowPlaying,
    [libvlc_meta_Publisher]    = vlc_meta_Publisher,
    [libvlc_meta_EncodedBy]    = vlc_meta_EncodedBy,
    [libvlc_meta_ArtworkURL]   = vlc_meta_ArtworkURL,
    [libvlc_meta_TrackID]      = vlc_meta_TrackID
};

67
static const libvlc_meta_t vlc_to_libvlc_meta[] =
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
{
    [vlc_meta_Title]        = libvlc_meta_Title,
    [vlc_meta_Artist]       = libvlc_meta_Artist,
    [vlc_meta_Genre]        = libvlc_meta_Genre,
    [vlc_meta_Copyright]    = libvlc_meta_Copyright,
    [vlc_meta_Album]        = libvlc_meta_Album,
    [vlc_meta_TrackNumber]  = libvlc_meta_TrackNumber,
    [vlc_meta_Description]  = libvlc_meta_Description,
    [vlc_meta_Rating]       = libvlc_meta_Rating,
    [vlc_meta_Date]         = libvlc_meta_Date,
    [vlc_meta_Setting]      = libvlc_meta_Setting,
    [vlc_meta_URL]          = libvlc_meta_URL,
    [vlc_meta_Language]     = libvlc_meta_Language,
    [vlc_meta_NowPlaying]   = libvlc_meta_NowPlaying,
    [vlc_meta_Publisher]    = libvlc_meta_Publisher,
    [vlc_meta_EncodedBy]    = libvlc_meta_EncodedBy,
    [vlc_meta_ArtworkURL]   = libvlc_meta_ArtworkURL,
    [vlc_meta_TrackID]      = libvlc_meta_TrackID
};

88 89 90 91
/**************************************************************************
 * input_item_subitem_added (Private) (vlc event Callback)
 **************************************************************************/
static void input_item_subitem_added( const vlc_event_t *p_event,
92
                                       void * user_data )
93
{
94 95
    libvlc_media_t * p_md = user_data;
    libvlc_media_t * p_md_child;
96 97
    libvlc_event_t event;

98
    p_md_child = libvlc_media_new_from_input_item(
99
                p_md->p_libvlc_instance,
100
                p_event->u.input_item_subitem_added.p_new_child );
101

102 103
    /* Add this to our media list */
    if( !p_md->p_subitems )
104
    {
105
        p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance );
106
        libvlc_media_list_set_media( p_md->p_subitems, p_md );
107
    }
108
    if( p_md->p_subitems )
109
    {
110
        libvlc_media_list_add_media( p_md->p_subitems, p_md_child );
111 112
    }

113
    /* Construct the event */
114
    event.type = libvlc_MediaSubItemAdded;
115
    event.u.media_subitem_added.new_child = p_md_child;
116 117 118

    /* Send the event */
    libvlc_event_send( p_md->p_event_manager, &event );
119
    libvlc_media_release( p_md_child );
120 121
}

122 123 124 125 126 127
/**************************************************************************
 * input_item_meta_changed (Private) (vlc event Callback)
 **************************************************************************/
static void input_item_meta_changed( const vlc_event_t *p_event,
                                     void * user_data )
{
128
    libvlc_media_t * p_md = user_data;
129 130 131
    libvlc_event_t event;

    /* Construct the event */
132
    event.type = libvlc_MediaMetaChanged;
133
    event.u.media_meta_changed.meta_type =
134 135 136 137 138 139
        vlc_to_libvlc_meta[p_event->u.input_item_meta_changed.meta_type];

    /* Send the event */
    libvlc_event_send( p_md->p_event_manager, &event );
}

140 141 142 143 144 145
/**************************************************************************
 * input_item_duration_changed (Private) (vlc event Callback)
 **************************************************************************/
static void input_item_duration_changed( const vlc_event_t *p_event,
                                         void * user_data )
{
146
    libvlc_media_t * p_md = user_data;
147 148 149
    libvlc_event_t event;

    /* Construct the event */
150
    event.type = libvlc_MediaDurationChanged;
151 152
    event.u.media_duration_changed.new_duration =
        from_mtime(p_event->u.input_item_duration_changed.new_duration);
153 154 155 156 157 158 159 160

    /* Send the event */
    libvlc_event_send( p_md->p_event_manager, &event );
}

/**************************************************************************
 * input_item_preparsed_changed (Private) (vlc event Callback)
 **************************************************************************/
161 162
static void input_item_preparsed_changed(const vlc_event_t *p_event,
                                         void * user_data)
163
{
164
    libvlc_media_t *media = user_data;
165 166
    libvlc_event_t event;

167 168 169 170 171 172 173
    /* Eventually notify libvlc_media_parse() */
    vlc_mutex_lock(&media->parsed_lock);
    media->is_parsed = true;
    vlc_cond_broadcast(&media->parsed_cond);
    vlc_mutex_unlock(&media->parsed_lock);


174
    /* Construct the event */
175 176
    event.type = libvlc_MediaParsedChanged;
    event.u.media_parsed_changed.new_status =
177 178 179
        p_event->u.input_item_preparsed_changed.new_status;

    /* Send the event */
180
    libvlc_event_send(media->p_event_manager, &event);
181
}
182 183 184 185

/**************************************************************************
 * Install event handler (Private)
 **************************************************************************/
186
static void install_input_item_observer( libvlc_media_t *p_md )
187
{
188 189 190 191
    vlc_event_attach( &p_md->p_input_item->event_manager,
                      vlc_InputItemSubItemAdded,
                      input_item_subitem_added,
                      p_md );
192 193 194 195
    vlc_event_attach( &p_md->p_input_item->event_manager,
                      vlc_InputItemMetaChanged,
                      input_item_meta_changed,
                      p_md );
196 197 198 199 200 201 202 203
    vlc_event_attach( &p_md->p_input_item->event_manager,
                      vlc_InputItemDurationChanged,
                      input_item_duration_changed,
                      p_md );
    vlc_event_attach( &p_md->p_input_item->event_manager,
                      vlc_InputItemPreparsedChanged,
                      input_item_preparsed_changed,
                      p_md );
204 205 206 207 208
}

/**************************************************************************
 * Uninstall event handler (Private)
 **************************************************************************/
209
static void uninstall_input_item_observer( libvlc_media_t *p_md )
210
{
211 212 213 214
    vlc_event_detach( &p_md->p_input_item->event_manager,
                      vlc_InputItemSubItemAdded,
                      input_item_subitem_added,
                      p_md );
215 216 217 218
    vlc_event_detach( &p_md->p_input_item->event_manager,
                      vlc_InputItemMetaChanged,
                      input_item_meta_changed,
                      p_md );
219 220 221 222 223 224 225 226
    vlc_event_detach( &p_md->p_input_item->event_manager,
                      vlc_InputItemDurationChanged,
                      input_item_duration_changed,
                      p_md );
    vlc_event_detach( &p_md->p_input_item->event_manager,
                      vlc_InputItemPreparsedChanged,
                      input_item_preparsed_changed,
                      p_md );
227
}
228 229

/**************************************************************************
230 231 232
 * Create a new media descriptor object from an input_item
 * (libvlc internal)
 * That's the generic constructor
233
 **************************************************************************/
234
libvlc_media_t * libvlc_media_new_from_input_item(
235
                                   libvlc_instance_t *p_instance,
236
                                   input_item_t *p_input_item )
237
{
238
    libvlc_media_t * p_md;
239 240

    if (!p_input_item)
241
    {
242
        libvlc_printerr( "No input item given" );
243 244
        return NULL;
    }
245

Rémi Duraffort's avatar
Rémi Duraffort committed
246
    p_md = calloc( 1, sizeof(libvlc_media_t) );
247 248
    if( !p_md )
    {
249
        libvlc_printerr( "Not enough memory" );
250 251 252
        return NULL;
    }

253 254
    p_md->p_libvlc_instance = p_instance;
    p_md->p_input_item      = p_input_item;
255
    p_md->i_refcount        = 1;
256

257 258 259
    vlc_cond_init(&p_md->parsed_cond);
    vlc_mutex_init(&p_md->parsed_lock);

260
    p_md->state = libvlc_NothingSpecial;
261

262 263 264 265
    /* A media descriptor can be a playlist. When you open a playlist
     * It can give a bunch of item to read. */
    p_md->p_subitems        = NULL;

266 267 268 269 270 271
    p_md->p_event_manager = libvlc_event_manager_new( p_md, p_instance );
    if( unlikely(p_md->p_event_manager == NULL) )
    {
        free(p_md);
        return NULL;
    }
272 273 274 275 276 277 278 279

    libvlc_event_manager_t *em = p_md->p_event_manager;
    libvlc_event_manager_register_event_type(em, libvlc_MediaMetaChanged);
    libvlc_event_manager_register_event_type(em, libvlc_MediaSubItemAdded);
    libvlc_event_manager_register_event_type(em, libvlc_MediaFreed);
    libvlc_event_manager_register_event_type(em, libvlc_MediaDurationChanged);
    libvlc_event_manager_register_event_type(em, libvlc_MediaStateChanged);
    libvlc_event_manager_register_event_type(em, libvlc_MediaParsedChanged);
280

281
    vlc_gc_incref( p_md->p_input_item );
282

283 284
    install_input_item_observer( p_md );

285
    return p_md;
286 287
}

288
/**************************************************************************
289
 * Create a new media descriptor object
290
 **************************************************************************/
291 292
libvlc_media_t *libvlc_media_new_location( libvlc_instance_t *p_instance,
                                           const char * psz_mrl )
293
{
294
    input_item_t * p_input_item;
295
    libvlc_media_t * p_md;
296

297
    p_input_item = input_item_New( psz_mrl, NULL );
298

299
    if (!p_input_item)
300
    {
301
        libvlc_printerr( "Not enough memory" );
302 303
        return NULL;
    }
304

305
    p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
306

307
    /* The p_input_item is retained in libvlc_media_new_from_input_item */
308
    vlc_gc_decref( p_input_item );
309

310
    return p_md;
311 312
}

313 314 315
libvlc_media_t *libvlc_media_new_path( libvlc_instance_t *p_instance,
                                       const char *path )
{
316
    char *mrl = make_URI( path, "file" );
317 318 319 320 321 322 323 324 325 326 327
    if( unlikely(mrl == NULL) )
    {
        libvlc_printerr( "Not enough memory" );
        return NULL;
    }

    libvlc_media_t *m = libvlc_media_new_location( p_instance, mrl );
    free( mrl );
    return m;
}

328 329 330 331 332 333 334 335
libvlc_media_t *libvlc_media_new_fd( libvlc_instance_t *p_instance, int fd )
{
    char mrl[16];
    snprintf( mrl, sizeof(mrl), "fd://%d", fd );

    return libvlc_media_new_location( p_instance, mrl );
}

336 337 338
/**************************************************************************
 * Create a new media descriptor object
 **************************************************************************/
339 340
libvlc_media_t * libvlc_media_new_as_node( libvlc_instance_t *p_instance,
                                           const char * psz_name )
341 342
{
    input_item_t * p_input_item;
343
    libvlc_media_t * p_md;
344

345
    p_input_item = input_item_New( "vlc://nop", psz_name );
346 347 348

    if (!p_input_item)
    {
349
        libvlc_printerr( "Not enough memory" );
350 351 352
        return NULL;
    }

353
    p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
354

355
    p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance );
356 357 358 359

    return p_md;
}

360 361
/**************************************************************************
 * Add an option to the media descriptor,
362 363
 * that will be used to determine how the media_player will read the
 * media. This allow to use VLC advanced reading/streaming
364 365 366 367
 * options in a per-media basis
 *
 * The options are detailled in vlc --long-help, for instance "--sout-all"
 **************************************************************************/
368 369
void libvlc_media_add_option( libvlc_media_t * p_md,
                              const char * psz_option )
370
{
371
    libvlc_media_add_option_flag( p_md, psz_option,
372
                          VLC_INPUT_OPTION_UNIQUE|VLC_INPUT_OPTION_TRUSTED );
373 374
}

375
/**************************************************************************
376
 * Same as libvlc_media_add_option but with configurable flags.
377
 **************************************************************************/
378
void libvlc_media_add_option_flag( libvlc_media_t * p_md,
379
                                   const char * ppsz_option,
380
                                   unsigned i_flags )
381
{
382
    input_item_AddOption( p_md->p_input_item, ppsz_option, i_flags );
383 384
}

385 386 387
/**************************************************************************
 * Delete a media descriptor object
 **************************************************************************/
388
void libvlc_media_release( libvlc_media_t *p_md )
389
{
390
    if (!p_md)
391 392
        return;

393 394 395 396
    p_md->i_refcount--;

    if( p_md->i_refcount > 0 )
        return;
397

398 399
    if( p_md->p_subitems )
        libvlc_media_list_release( p_md->p_subitems );
400

401 402 403
    uninstall_input_item_observer( p_md );
    vlc_gc_decref( p_md->p_input_item );

404 405 406
    vlc_cond_destroy( &p_md->parsed_cond );
    vlc_mutex_destroy( &p_md->parsed_lock );

407 408
    /* Construct the event */
    libvlc_event_t event;
409
    event.type = libvlc_MediaFreed;
410
    event.u.media_freed.md = p_md;
411 412 413 414

    /* Send the event */
    libvlc_event_send( p_md->p_event_manager, &event );

415 416
    libvlc_event_manager_release( p_md->p_event_manager );

417 418 419 420
    free( p_md );
}

/**************************************************************************
421 422
 * Retain a media descriptor object
 **************************************************************************/
423
void libvlc_media_retain( libvlc_media_t *p_md )
424
{
425
    assert (p_md);
426 427 428 429 430
    p_md->i_refcount++;
}

/**************************************************************************
 * Duplicate a media descriptor object
431
 **************************************************************************/
432 433
libvlc_media_t *
libvlc_media_duplicate( libvlc_media_t *p_md_orig )
434
{
435
    return libvlc_media_new_from_input_item(
436
        p_md_orig->p_libvlc_instance, p_md_orig->p_input_item );
437 438
}

439
/**************************************************************************
440
 * Get mrl from a media descriptor object
441 442
 **************************************************************************/
char *
443
libvlc_media_get_mrl( libvlc_media_t * p_md )
444
{
445
    assert( p_md );
446
    return input_item_GetURI( p_md->p_input_item );
447 448
}

449
/**************************************************************************
450
 * Getter for meta information
451 452
 **************************************************************************/

453
char *libvlc_media_get_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta )
454
{
455 456
    char *psz_meta = input_item_GetMeta( p_md->p_input_item,
                                         libvlc_to_vlc_meta[e_meta] );
457
    /* Should be integrated in core */
458 459 460
    if( psz_meta == NULL && e_meta == libvlc_meta_Title
     && p_md->p_input_item->psz_name != NULL )
        psz_meta = strdup( p_md->p_input_item->psz_name );
461

462
    return psz_meta;
463
}
464

Rémi Duraffort's avatar
Rémi Duraffort committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
/**************************************************************************
 * Setter for meta information
 **************************************************************************/

void libvlc_media_set_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta, const char *psz_value )
{
    assert( p_md );
    input_item_SetMeta( p_md->p_input_item, libvlc_to_vlc_meta[e_meta], psz_value );
}

int libvlc_media_save_meta( libvlc_media_t *p_md )
{
    assert( p_md );
    vlc_object_t *p_obj = VLC_OBJECT(libvlc_priv(
                            p_md->p_libvlc_instance->p_libvlc_int)->p_playlist);
    return input_item_WriteMeta( p_obj, p_md->p_input_item ) == VLC_SUCCESS;
}

483 484 485 486 487
/**************************************************************************
 * Getter for state information
 * Can be error, playing, buffering, NothingSpecial.
 **************************************************************************/

488
libvlc_state_t
489
libvlc_media_get_state( libvlc_media_t *p_md )
490
{
491
    assert( p_md );
492 493 494 495 496 497 498 499
    return p_md->state;
}

/**************************************************************************
 * Setter for state information (LibVLC Internal)
 **************************************************************************/

void
500
libvlc_media_set_state( libvlc_media_t *p_md,
501
                                   libvlc_state_t state )
502 503 504 505 506 507
{
    libvlc_event_t event;

    p_md->state = state;

    /* Construct the event */
508
    event.type = libvlc_MediaStateChanged;
509
    event.u.media_state_changed.new_state = state;
510 511 512 513 514

    /* Send the event */
    libvlc_event_send( p_md->p_event_manager, &event );
}

515 516 517 518
/**************************************************************************
 * subitems
 **************************************************************************/
libvlc_media_list_t *
519
libvlc_media_subitems( libvlc_media_t * p_md )
520
{
521 522
    if( p_md->p_subitems )
        libvlc_media_list_retain( p_md->p_subitems );
523 524
    return p_md->p_subitems;
}
525

526
/**************************************************************************
Rémi Duraffort's avatar
Rémi Duraffort committed
527
 * Getter for statistics information
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
 **************************************************************************/
int libvlc_media_get_stats( libvlc_media_t *p_md,
                            libvlc_media_stats_t *p_stats )
{
    if( !p_md->p_input_item )
        return false;

    input_stats_t *p_itm_stats = p_md->p_input_item->p_stats;
    vlc_mutex_lock( &p_itm_stats->lock );
    p_stats->i_read_bytes = p_itm_stats->i_read_bytes;
    p_stats->f_input_bitrate = p_itm_stats->f_input_bitrate;

    p_stats->i_demux_read_bytes = p_itm_stats->i_demux_read_bytes;
    p_stats->f_demux_bitrate = p_itm_stats->f_demux_bitrate;
    p_stats->i_demux_corrupted = p_itm_stats->i_demux_corrupted;
    p_stats->i_demux_discontinuity = p_itm_stats->i_demux_discontinuity;

    p_stats->i_decoded_video = p_itm_stats->i_decoded_video;
    p_stats->i_decoded_audio = p_itm_stats->i_decoded_audio;

    p_stats->i_displayed_pictures = p_itm_stats->i_displayed_pictures;
    p_stats->i_lost_pictures = p_itm_stats->i_lost_pictures;

    p_stats->i_played_abuffers = p_itm_stats->i_played_abuffers;
    p_stats->i_lost_abuffers = p_itm_stats->i_lost_abuffers;

    p_stats->i_sent_packets = p_itm_stats->i_sent_packets;
    p_stats->i_sent_bytes = p_itm_stats->i_sent_bytes;
    p_stats->f_send_bitrate = p_itm_stats->f_send_bitrate;
    vlc_mutex_unlock( &p_itm_stats->lock );
    return true;
}

561 562 563 564
/**************************************************************************
 * event_manager
 **************************************************************************/
libvlc_event_manager_t *
565
libvlc_media_event_manager( libvlc_media_t * p_md )
566
{
567
    assert( p_md );
568

569 570
    return p_md->p_event_manager;
}
571 572

/**************************************************************************
573
 * Get duration of media object (in ms)
574
 **************************************************************************/
575
int64_t
576
libvlc_media_get_duration( libvlc_media_t * p_md )
577
{
578
    assert( p_md );
579

580
    if( !p_md->p_input_item )
581
    {
582
        libvlc_printerr( "No input item" );
583 584
        return -1;
    }
585

586 587 588
    if (!input_item_IsPreparsed( p_md->p_input_item ))
        return -1;

589
    return from_mtime(input_item_GetDuration( p_md->p_input_item ));
590 591
}

592 593 594 595 596 597 598 599 600 601 602
static int media_parse(libvlc_media_t *media)
{
    /* TODO: fetcher and parser independent of playlist */
    playlist_t *playlist =
        libvlc_priv (media->p_libvlc_instance->p_libvlc_int)->p_playlist;

    /* TODO: Fetch art on need basis. But how not to break compatibility? */
    playlist_AskForArtEnqueue(playlist, media->p_input_item );
    return playlist_PreparseEnqueue(playlist, media->p_input_item);
}

603
/**************************************************************************
604
 * Parse the media and wait.
605 606 607 608 609
 **************************************************************************/
void
libvlc_media_parse(libvlc_media_t *media)
{
    vlc_mutex_lock(&media->parsed_lock);
610 611 612 613 614 615 616 617 618 619 620
    if (!media->has_asked_preparse)
    {
        media->has_asked_preparse = true;
        vlc_mutex_unlock(&media->parsed_lock);

        if (media_parse(media))
            /* Parse failed: do not wait! */
            return;
        vlc_mutex_lock(&media->parsed_lock);
    }

621 622 623 624 625 626
    while (!media->is_parsed)
        vlc_cond_wait(&media->parsed_cond, &media->parsed_lock);
    vlc_mutex_unlock(&media->parsed_lock);
}

/**************************************************************************
627
 * Parse the media but do not wait.
628 629 630 631
 **************************************************************************/
void
libvlc_media_parse_async(libvlc_media_t *media)
{
632 633 634
    bool needed;

    vlc_mutex_lock(&media->parsed_lock);
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
635
    needed = !media->has_asked_preparse;
636 637 638 639 640
    media->has_asked_preparse = true;
    vlc_mutex_unlock(&media->parsed_lock);

    if (needed)
        media_parse(media);
641 642
}

643
/**************************************************************************
644
 * Get parsed status for media object.
645
 **************************************************************************/
646
int
647
libvlc_media_is_parsed(libvlc_media_t *media)
648
{
649
    bool parsed;
650

651 652 653 654
    vlc_mutex_lock(&media->parsed_lock);
    parsed = media->is_parsed;
    vlc_mutex_unlock(&media->parsed_lock);
    return parsed;
655 656 657
}

/**************************************************************************
Pierre's avatar
Pierre committed
658 659
 * Sets media descriptor's user_data. user_data is specialized data
 * accessed by the host application, VLC.framework uses it as a pointer to
660
 * an native object that references a libvlc_media_t pointer
661
 **************************************************************************/
Pierre's avatar
Pierre committed
662
void
663
libvlc_media_set_user_data( libvlc_media_t * p_md, void * p_new_user_data )
664
{
665 666
    assert( p_md );
    p_md->p_user_data = p_new_user_data;
667 668 669
}

/**************************************************************************
Pierre's avatar
Pierre committed
670 671
 * Get media descriptor's user_data. user_data is specialized data
 * accessed by the host application, VLC.framework uses it as a pointer to
672
 * an native object that references a libvlc_media_t pointer
673 674
 **************************************************************************/
void *
675
libvlc_media_get_user_data( libvlc_media_t * p_md )
676
{
677 678
    assert( p_md );
    return p_md->p_user_data;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
679
}
680 681 682 683 684

/**************************************************************************
 * Get media descriptor's elementary streams description
 **************************************************************************/
int
685
libvlc_media_get_tracks_info( libvlc_media_t *p_md, libvlc_media_track_info_t ** pp_es )
686 687 688 689 690 691 692
{
    assert( p_md );

    input_item_t *p_input_item = p_md->p_input_item;
    vlc_mutex_lock( &p_input_item->lock );

    const int i_es = p_input_item->i_es;
693
    *pp_es = (i_es > 0) ? malloc( i_es * sizeof(libvlc_media_track_info_t) ) : NULL;
694

695
    if( !*pp_es ) /* no ES, or OOM */
696 697 698 699 700 701 702 703
    {
        vlc_mutex_unlock( &p_input_item->lock );
        return 0;
    }

    /* Fill array */
    for( int i = 0; i < i_es; i++ )
    {
704
        libvlc_media_track_info_t *p_mes = *pp_es+i;
705 706 707
        const es_format_t *p_es = p_input_item->es[i];

        p_mes->i_codec = p_es->i_codec;
708
        p_mes->i_id = p_es->i_id;
709 710 711 712 713 714 715 716

        p_mes->i_profile = p_es->i_profile;
        p_mes->i_level = p_es->i_level;

        switch(p_es->i_cat)
        {
        case UNKNOWN_ES:
        default:
717
            p_mes->i_type = libvlc_track_unknown;
718 719
            break;
        case VIDEO_ES:
720
            p_mes->i_type = libvlc_track_video;
721 722
            p_mes->u.video.i_height = p_es->video.i_height;
            p_mes->u.video.i_width = p_es->video.i_width;
723 724
            break;
        case AUDIO_ES:
725
            p_mes->i_type = libvlc_track_audio;
726 727
            p_mes->u.audio.i_channels = p_es->audio.i_channels;
            p_mes->u.audio.i_rate = p_es->audio.i_rate;
728 729
            break;
        case SPU_ES:
730
            p_mes->i_type = libvlc_track_text;
731 732 733 734 735 736 737
            break;
        }
    }

    vlc_mutex_unlock( &p_input_item->lock );
    return i_es;
}