media.c 25 KB
Newer Older
1
/*****************************************************************************
2
 * media.c: Libvlc API media descripor management
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *****************************************************************************
 * Copyright (C) 2007 the VideoLAN team
 * $Id$
 *
 * Authors: Pierre d'Herbemont <pdherbemont@videolan.org>
 *
 * 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.
 *****************************************************************************/

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
42
43
44
#include "libvlc.h"

#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
 * Preparse if not already done (Private)
231
 **************************************************************************/
232
static void preparse_if_needed( libvlc_media_t *p_md )
233
234
{
    /* XXX: need some locking here */
235
    if (!p_md->has_asked_preparse)
236
    {
237
        playlist_PreparseEnqueue(
238
                libvlc_priv (p_md->p_libvlc_instance->p_libvlc_int)->p_playlist,
239
                p_md->p_input_item );
240
        p_md->has_asked_preparse = true;
241
242
243
244
    }
}

/**************************************************************************
245
246
247
 * Create a new media descriptor object from an input_item
 * (libvlc internal)
 * That's the generic constructor
248
 **************************************************************************/
249
libvlc_media_t * libvlc_media_new_from_input_item(
250
                                   libvlc_instance_t *p_instance,
251
                                   input_item_t *p_input_item )
252
{
253
    libvlc_media_t * p_md;
254
255

    if (!p_input_item)
256
    {
257
        libvlc_printerr( "No input item given" );
258
259
        return NULL;
    }
260

ivoire's avatar
ivoire committed
261
    p_md = calloc( 1, sizeof(libvlc_media_t) );
262
263
    if( !p_md )
    {
264
        libvlc_printerr( "Not enough memory" );
265
266
267
        return NULL;
    }

268
269
    p_md->p_libvlc_instance = p_instance;
    p_md->p_input_item      = p_input_item;
270
    p_md->i_refcount        = 1;
271

272
273
274
    vlc_cond_init(&p_md->parsed_cond);
    vlc_mutex_init(&p_md->parsed_lock);

275
    p_md->state = libvlc_NothingSpecial;
276

277
278
279
280
    /* 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;

281
282
283
284
285
286
    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;
    }
287
288
289
290
291
292
293
294

    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);
295

296
    vlc_gc_incref( p_md->p_input_item );
297

298
299
    install_input_item_observer( p_md );

300
    return p_md;
301
302
}

303
/**************************************************************************
304
 * Create a new media descriptor object
305
 **************************************************************************/
306
307
libvlc_media_t *libvlc_media_new_location( libvlc_instance_t *p_instance,
                                           const char * psz_mrl )
308
{
309
    input_item_t * p_input_item;
310
    libvlc_media_t * p_md;
311

312
    p_input_item = input_item_New( p_instance->p_libvlc_int, psz_mrl, NULL );
313

314
    if (!p_input_item)
315
    {
316
        libvlc_printerr( "Not enough memory" );
317
318
        return NULL;
    }
319

320
    p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
321

322
    /* The p_input_item is retained in libvlc_media_new_from_input_item */
323
    vlc_gc_decref( p_input_item );
324

325
    return p_md;
326
327
}

328
329
330
libvlc_media_t *libvlc_media_new_path( libvlc_instance_t *p_instance,
                                       const char *path )
{
331
    char *mrl = make_URI( path, "file" );
332
333
334
335
336
337
338
339
340
341
342
    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;
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
343
344
345
346
347
348
349
350
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 );
}

351
352
353
/**************************************************************************
 * Create a new media descriptor object
 **************************************************************************/
354
355
libvlc_media_t * libvlc_media_new_as_node( libvlc_instance_t *p_instance,
                                           const char * psz_name )
356
357
{
    input_item_t * p_input_item;
358
    libvlc_media_t * p_md;
359

360
    p_input_item = input_item_New( p_instance->p_libvlc_int, "vlc://nop", psz_name );
361
362
363

    if (!p_input_item)
    {
364
        libvlc_printerr( "Not enough memory" );
365
366
367
        return NULL;
    }

368
    p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
369

370
    p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance );
371
372
373
374

    return p_md;
}

375
376
/**************************************************************************
 * Add an option to the media descriptor,
377
378
 * that will be used to determine how the media_player will read the
 * media. This allow to use VLC advanced reading/streaming
379
380
381
382
 * options in a per-media basis
 *
 * The options are detailled in vlc --long-help, for instance "--sout-all"
 **************************************************************************/
383
384
void libvlc_media_add_option( libvlc_media_t * p_md,
                              const char * psz_option )
385
{
386
    libvlc_media_add_option_flag( p_md, psz_option,
387
                          VLC_INPUT_OPTION_UNIQUE|VLC_INPUT_OPTION_TRUSTED );
388
389
}

390
/**************************************************************************
391
 * Same as libvlc_media_add_option but with configurable flags.
392
 **************************************************************************/
393
void libvlc_media_add_option_flag( libvlc_media_t * p_md,
394
                                   const char * ppsz_option,
395
                                   unsigned i_flags )
396
{
397
    input_item_AddOption( p_md->p_input_item, ppsz_option, i_flags );
398
399
}

400
401
402
/**************************************************************************
 * Delete a media descriptor object
 **************************************************************************/
403
void libvlc_media_release( libvlc_media_t *p_md )
404
{
405
    if (!p_md)
406
407
        return;

408
409
410
411
    p_md->i_refcount--;

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

413
414
    if( p_md->p_subitems )
        libvlc_media_list_release( p_md->p_subitems );
415

416
417
418
    uninstall_input_item_observer( p_md );
    vlc_gc_decref( p_md->p_input_item );

419
420
421
    vlc_cond_destroy( &p_md->parsed_cond );
    vlc_mutex_destroy( &p_md->parsed_lock );

422
423
    /* Construct the event */
    libvlc_event_t event;
424
    event.type = libvlc_MediaFreed;
425
    event.u.media_freed.md = p_md;
426
427
428
429

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

430
431
    libvlc_event_manager_release( p_md->p_event_manager );

432
433
434
435
    free( p_md );
}

/**************************************************************************
436
437
 * Retain a media descriptor object
 **************************************************************************/
438
void libvlc_media_retain( libvlc_media_t *p_md )
439
{
440
    assert (p_md);
441
442
443
444
445
    p_md->i_refcount++;
}

/**************************************************************************
 * Duplicate a media descriptor object
446
 **************************************************************************/
447
448
libvlc_media_t *
libvlc_media_duplicate( libvlc_media_t *p_md_orig )
449
{
450
    return libvlc_media_new_from_input_item(
451
        p_md_orig->p_libvlc_instance, p_md_orig->p_input_item );
452
453
}

454
/**************************************************************************
455
 * Get mrl from a media descriptor object
456
457
 **************************************************************************/
char *
458
libvlc_media_get_mrl( libvlc_media_t * p_md )
459
{
460
    assert( p_md );
461
    return input_item_GetURI( p_md->p_input_item );
462
463
}

464
/**************************************************************************
465
 * Getter for meta information
466
467
 **************************************************************************/

468
char *libvlc_media_get_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta )
469
{
470
    char * psz_meta;
471

472
    assert( p_md );
473
474
    /* XXX: locking */

475
    preparse_if_needed( p_md );
476

477
478
    psz_meta = input_item_GetMeta( p_md->p_input_item,
                                   libvlc_to_vlc_meta[e_meta] );
479

480
    if( e_meta == libvlc_meta_ArtworkURL && !psz_meta && !p_md->has_asked_art )
481
    {
482
        p_md->has_asked_art = true;
483
        playlist_AskForArtEnqueue(
484
                libvlc_priv(p_md->p_libvlc_instance->p_libvlc_int)->p_playlist,
485
                p_md->p_input_item );
486
    }
487

488
    /* Should be integrated in core */
489
490
491
    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 );
492

493
    return psz_meta;
494
}
495

ivoire's avatar
ivoire committed
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
/**************************************************************************
 * 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;
}

514
515
516
517
518
/**************************************************************************
 * Getter for state information
 * Can be error, playing, buffering, NothingSpecial.
 **************************************************************************/

519
libvlc_state_t
520
libvlc_media_get_state( libvlc_media_t *p_md )
521
{
522
    assert( p_md );
523
524
525
526
527
528
529
530
    return p_md->state;
}

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

void
531
libvlc_media_set_state( libvlc_media_t *p_md,
532
                                   libvlc_state_t state )
533
534
535
536
537
538
{
    libvlc_event_t event;

    p_md->state = state;

    /* Construct the event */
539
    event.type = libvlc_MediaStateChanged;
540
    event.u.media_state_changed.new_state = state;
541
542
543
544
545

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

546
547
548
549
/**************************************************************************
 * subitems
 **************************************************************************/
libvlc_media_list_t *
550
libvlc_media_subitems( libvlc_media_t * p_md )
551
{
552
553
    if( p_md->p_subitems )
        libvlc_media_list_retain( p_md->p_subitems );
554
555
    return p_md->p_subitems;
}
556

557
/**************************************************************************
ivoire's avatar
ivoire committed
558
 * Getter for statistics information
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
 **************************************************************************/
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;
}

592
593
594
595
/**************************************************************************
 * event_manager
 **************************************************************************/
libvlc_event_manager_t *
596
libvlc_media_event_manager( libvlc_media_t * p_md )
597
{
598
    assert( p_md );
599

600
601
    return p_md->p_event_manager;
}
602
603

/**************************************************************************
604
 * Get duration of media object (in ms)
605
 **************************************************************************/
606
int64_t
607
libvlc_media_get_duration( libvlc_media_t * p_md )
608
{
609
    assert( p_md );
610

611
    if( !p_md->p_input_item )
612
    {
613
        libvlc_printerr( "No input item" );
614
615
        return -1;
    }
616

617
618
619
620
621
    preparse_if_needed( p_md );

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

622
    return from_mtime(input_item_GetDuration( p_md->p_input_item ));
623
624
}

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
/**************************************************************************
 * Parse the media.
 **************************************************************************/
void
libvlc_media_parse(libvlc_media_t *media)
{
    preparse_if_needed(media);

    vlc_mutex_lock(&media->parsed_lock);
    while (!media->is_parsed)
        vlc_cond_wait(&media->parsed_cond, &media->parsed_lock);
    vlc_mutex_unlock(&media->parsed_lock);
}

/**************************************************************************
 * Parse the media.
 **************************************************************************/
void
libvlc_media_parse_async(libvlc_media_t *media)
{
    preparse_if_needed(media);
}

648
/**************************************************************************
649
 * Get parsed status for media object.
650
 **************************************************************************/
651
int
652
libvlc_media_is_parsed( libvlc_media_t * p_md )
653
{
654
    assert( p_md );
655

656
    if( !p_md->p_input_item )
657
        return false;
658
659

    return input_item_IsPreparsed( p_md->p_input_item );
660
661
662
}

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

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

/**************************************************************************
 * Get media descriptor's elementary streams description
 **************************************************************************/
int
690
libvlc_media_get_tracks_info( libvlc_media_t *p_md, libvlc_media_track_info_t ** pp_es )
691
692
693
694
695
696
697
{
    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;
698
    *pp_es = (i_es > 0) ? malloc( i_es * sizeof(libvlc_media_track_info_t) ) : NULL;
699

700
    if( !*pp_es ) /* no ES, or OOM */
701
702
703
704
705
706
707
708
    {
        vlc_mutex_unlock( &p_input_item->lock );
        return 0;
    }

    /* Fill array */
    for( int i = 0; i < i_es; i++ )
    {
709
        libvlc_media_track_info_t *p_mes = *pp_es+i;
710
711
712
        const es_format_t *p_es = p_input_item->es[i];

        p_mes->i_codec = p_es->i_codec;
713
        p_mes->i_id = p_es->i_id;
714
715
716
717
718
719
720
721

        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:
722
            p_mes->i_type = libvlc_track_unknown;
723
724
            break;
        case VIDEO_ES:
725
            p_mes->i_type = libvlc_track_video;
726
727
            p_mes->u.video.i_height = p_es->video.i_height;
            p_mes->u.video.i_width = p_es->video.i_width;
728
729
            break;
        case AUDIO_ES:
730
            p_mes->i_type = libvlc_track_audio;
731
732
            p_mes->u.audio.i_channels = p_es->audio.i_channels;
            p_mes->u.audio.i_rate = p_es->audio.i_rate;
733
734
            break;
        case SPU_ES:
735
            p_mes->i_type = libvlc_track_text;
736
737
738
739
740
741
742
            break;
        }
    }

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