NSIS: fix warnings
[vlc.git] / lib / media.c
blob0b20aaac23408c568676c75d46466085d9547f35
1 /*****************************************************************************
2 * media.c: Libvlc API media descripor management
3 *****************************************************************************
4 * Copyright (C) 2007 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Pierre d'Herbemont <pdherbemont@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <assert.h>
29 #include <errno.h>
31 #include <vlc/libvlc.h>
32 #include <vlc/libvlc_media.h>
33 #include <vlc/libvlc_media_list.h> // For the subitems, here for convenience
34 #include <vlc/libvlc_events.h>
36 #include <vlc_common.h>
37 #include <vlc_input.h>
38 #include <vlc_meta.h>
39 #include <vlc_playlist.h> /* For the preparser */
40 #include <vlc_url.h>
42 #include "../src/libvlc.h"
44 #include "libvlc_internal.h"
45 #include "media_internal.h"
46 #include "media_list_internal.h"
48 static const vlc_meta_type_t libvlc_to_vlc_meta[] =
50 [libvlc_meta_Title] = vlc_meta_Title,
51 [libvlc_meta_Artist] = vlc_meta_Artist,
52 [libvlc_meta_Genre] = vlc_meta_Genre,
53 [libvlc_meta_Copyright] = vlc_meta_Copyright,
54 [libvlc_meta_Album] = vlc_meta_Album,
55 [libvlc_meta_TrackNumber] = vlc_meta_TrackNumber,
56 [libvlc_meta_Description] = vlc_meta_Description,
57 [libvlc_meta_Rating] = vlc_meta_Rating,
58 [libvlc_meta_Date] = vlc_meta_Date,
59 [libvlc_meta_Setting] = vlc_meta_Setting,
60 [libvlc_meta_URL] = vlc_meta_URL,
61 [libvlc_meta_Language] = vlc_meta_Language,
62 [libvlc_meta_NowPlaying] = vlc_meta_NowPlaying,
63 [libvlc_meta_Publisher] = vlc_meta_Publisher,
64 [libvlc_meta_EncodedBy] = vlc_meta_EncodedBy,
65 [libvlc_meta_ArtworkURL] = vlc_meta_ArtworkURL,
66 [libvlc_meta_TrackID] = vlc_meta_TrackID,
67 [libvlc_meta_TrackTotal] = vlc_meta_TrackTotal,
68 [libvlc_meta_Director] = vlc_meta_Director,
69 [libvlc_meta_Season] = vlc_meta_Season,
70 [libvlc_meta_Episode] = vlc_meta_Episode,
71 [libvlc_meta_ShowName] = vlc_meta_ShowName,
72 [libvlc_meta_Actors] = vlc_meta_Actors,
73 [libvlc_meta_AlbumArtist] = vlc_meta_AlbumArtist,
74 [libvlc_meta_DiscNumber] = vlc_meta_DiscNumber,
75 [libvlc_meta_DiscTotal] = vlc_meta_DiscTotal
78 static const libvlc_meta_t vlc_to_libvlc_meta[] =
80 [vlc_meta_Title] = libvlc_meta_Title,
81 [vlc_meta_Artist] = libvlc_meta_Artist,
82 [vlc_meta_Genre] = libvlc_meta_Genre,
83 [vlc_meta_Copyright] = libvlc_meta_Copyright,
84 [vlc_meta_Album] = libvlc_meta_Album,
85 [vlc_meta_TrackNumber] = libvlc_meta_TrackNumber,
86 [vlc_meta_Description] = libvlc_meta_Description,
87 [vlc_meta_Rating] = libvlc_meta_Rating,
88 [vlc_meta_Date] = libvlc_meta_Date,
89 [vlc_meta_Setting] = libvlc_meta_Setting,
90 [vlc_meta_URL] = libvlc_meta_URL,
91 [vlc_meta_Language] = libvlc_meta_Language,
92 [vlc_meta_NowPlaying] = libvlc_meta_NowPlaying,
93 [vlc_meta_ESNowPlaying] = libvlc_meta_NowPlaying,
94 [vlc_meta_Publisher] = libvlc_meta_Publisher,
95 [vlc_meta_EncodedBy] = libvlc_meta_EncodedBy,
96 [vlc_meta_ArtworkURL] = libvlc_meta_ArtworkURL,
97 [vlc_meta_TrackID] = libvlc_meta_TrackID,
98 [vlc_meta_TrackTotal] = libvlc_meta_TrackTotal,
99 [vlc_meta_Director] = libvlc_meta_Director,
100 [vlc_meta_Season] = libvlc_meta_Season,
101 [vlc_meta_Episode] = libvlc_meta_Episode,
102 [vlc_meta_ShowName] = libvlc_meta_ShowName,
103 [vlc_meta_Actors] = libvlc_meta_Actors,
104 [vlc_meta_AlbumArtist] = libvlc_meta_AlbumArtist,
105 [vlc_meta_DiscNumber] = libvlc_meta_DiscNumber,
106 [vlc_meta_DiscTotal] = libvlc_meta_DiscTotal
109 static libvlc_media_list_t *media_get_subitems( libvlc_media_t * p_md,
110 bool b_create )
112 libvlc_media_list_t *p_subitems = NULL;
114 vlc_mutex_lock( &p_md->subitems_lock );
115 if( p_md->p_subitems == NULL && b_create )
117 p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance );
118 if( p_md->p_subitems != NULL )
120 p_md->p_subitems->b_read_only = true;
121 p_md->p_subitems->p_internal_md = p_md;
124 p_subitems = p_md->p_subitems;
125 vlc_mutex_unlock( &p_md->subitems_lock );
126 return p_subitems;
129 /**************************************************************************
130 * input_item_subitem_added (Private) (vlc event Callback)
131 **************************************************************************/
132 static void input_item_subitem_added( const vlc_event_t *p_event,
133 void * user_data )
135 libvlc_media_t * p_md = user_data;
136 libvlc_media_t * p_md_child;
137 libvlc_media_list_t *p_subitems;
138 libvlc_event_t event;
140 p_md_child = libvlc_media_new_from_input_item(
141 p_md->p_libvlc_instance,
142 p_event->u.input_item_subitem_added.p_new_child );
144 /* Add this to our media list */
145 p_subitems = media_get_subitems( p_md, true );
146 if( p_subitems != NULL )
148 libvlc_media_list_lock( p_subitems );
149 libvlc_media_list_internal_add_media( p_subitems, p_md_child );
150 libvlc_media_list_unlock( p_subitems );
153 /* Construct the event */
154 event.type = libvlc_MediaSubItemAdded;
155 event.u.media_subitem_added.new_child = p_md_child;
157 /* Send the event */
158 libvlc_event_send( p_md->p_event_manager, &event );
159 libvlc_media_release( p_md_child );
162 /**************************************************************************
163 * input_item_subitemtree_added (Private) (vlc event Callback)
164 **************************************************************************/
165 static void input_item_subitemtree_added( const vlc_event_t * p_event,
166 void * user_data )
168 VLC_UNUSED( p_event );
169 libvlc_media_t * p_md = user_data;
170 libvlc_event_t event;
172 /* Construct the event */
173 event.type = libvlc_MediaSubItemTreeAdded;
174 event.u.media_subitemtree_added.item = p_md;
176 /* Send the event */
177 libvlc_event_send( p_md->p_event_manager, &event );
180 /**************************************************************************
181 * input_item_meta_changed (Private) (vlc event Callback)
182 **************************************************************************/
183 static void input_item_meta_changed( const vlc_event_t *p_event,
184 void * user_data )
186 libvlc_media_t * p_md = user_data;
187 libvlc_event_t event;
189 /* Construct the event */
190 event.type = libvlc_MediaMetaChanged;
191 event.u.media_meta_changed.meta_type =
192 vlc_to_libvlc_meta[p_event->u.input_item_meta_changed.meta_type];
194 /* Send the event */
195 libvlc_event_send( p_md->p_event_manager, &event );
198 /**************************************************************************
199 * input_item_duration_changed (Private) (vlc event Callback)
200 **************************************************************************/
201 static void input_item_duration_changed( const vlc_event_t *p_event,
202 void * user_data )
204 libvlc_media_t * p_md = user_data;
205 libvlc_event_t event;
207 /* Construct the event */
208 event.type = libvlc_MediaDurationChanged;
209 event.u.media_duration_changed.new_duration =
210 from_mtime(p_event->u.input_item_duration_changed.new_duration);
212 /* Send the event */
213 libvlc_event_send( p_md->p_event_manager, &event );
216 static void send_preparsed_event(libvlc_media_t *media)
218 libvlc_event_t event;
220 /* Eventually notify libvlc_media_parse() */
221 vlc_mutex_lock(&media->parsed_lock);
222 if (media->is_parsed == true)
224 vlc_mutex_unlock(&media->parsed_lock);
225 return;
227 media->is_parsed = true;
228 vlc_cond_broadcast(&media->parsed_cond);
229 vlc_mutex_unlock(&media->parsed_lock);
232 /* Construct the event */
233 event.type = libvlc_MediaParsedChanged;
234 event.u.media_parsed_changed.new_status = true;
236 /* Send the event */
237 libvlc_event_send(media->p_event_manager, &event);
240 /**************************************************************************
241 * input_item_preparsed_changed (Private) (vlc event Callback)
242 **************************************************************************/
243 static void input_item_preparsed_changed(const vlc_event_t *p_event,
244 void * user_data)
246 VLC_UNUSED( p_event );
247 libvlc_media_t *media = user_data;
248 send_preparsed_event(media);
251 /**************************************************************************
252 * input_item_preparse_ended (Private) (vlc event Callback)
253 **************************************************************************/
254 static void input_item_preparse_ended( const vlc_event_t * p_event,
255 void * user_data )
257 VLC_UNUSED( p_event );
258 libvlc_media_t * p_md = user_data;
259 libvlc_media_list_t *p_subitems = media_get_subitems( p_md, false );
260 libvlc_event_t event;
262 event.type = libvlc_MediaParsedStatus;
264 vlc_mutex_lock(&p_md->parsed_lock);
265 switch (p_event->u.input_item_preparse_ended.new_status)
267 case ITEM_PREPARSE_SKIPPED:
268 p_md->parsed_status = libvlc_media_parse_skipped;
269 p_md->has_asked_preparse = false;
270 break;
271 case ITEM_PREPARSE_FAILED:
272 p_md->parsed_status = libvlc_media_parse_failed;
273 break;
274 case ITEM_PREPARSE_DONE:
275 p_md->parsed_status = libvlc_media_parse_done;
276 break;
278 event.u.media_parsed_status.new_status = p_md->parsed_status;
279 vlc_mutex_unlock(&p_md->parsed_lock);
281 if( p_subitems != NULL )
283 /* notify the media list */
284 libvlc_media_list_lock( p_subitems );
285 libvlc_media_list_internal_end_reached( p_subitems );
286 libvlc_media_list_unlock( p_subitems );
289 /* XXX: libVLC 2.2.0 compat: even if case of preparse failure,
290 * libvlc_MediaParsedChanged was sent with a true status. Therefore, send
291 * this event if it was not previously sent */
292 send_preparsed_event(p_md);
294 libvlc_event_send(p_md->p_event_manager, &event);
297 /**************************************************************************
298 * Install event handler (Private)
299 **************************************************************************/
300 static void install_input_item_observer( libvlc_media_t *p_md )
302 vlc_event_attach( &p_md->p_input_item->event_manager,
303 vlc_InputItemSubItemAdded,
304 input_item_subitem_added,
305 p_md );
306 vlc_event_attach( &p_md->p_input_item->event_manager,
307 vlc_InputItemMetaChanged,
308 input_item_meta_changed,
309 p_md );
310 vlc_event_attach( &p_md->p_input_item->event_manager,
311 vlc_InputItemDurationChanged,
312 input_item_duration_changed,
313 p_md );
314 vlc_event_attach( &p_md->p_input_item->event_manager,
315 vlc_InputItemPreparsedChanged,
316 input_item_preparsed_changed,
317 p_md );
318 vlc_event_attach( &p_md->p_input_item->event_manager,
319 vlc_InputItemSubItemTreeAdded,
320 input_item_subitemtree_added,
321 p_md );
322 vlc_event_attach( &p_md->p_input_item->event_manager,
323 vlc_InputItemPreparseEnded,
324 input_item_preparse_ended,
325 p_md );
328 /**************************************************************************
329 * Uninstall event handler (Private)
330 **************************************************************************/
331 static void uninstall_input_item_observer( libvlc_media_t *p_md )
333 vlc_event_detach( &p_md->p_input_item->event_manager,
334 vlc_InputItemSubItemAdded,
335 input_item_subitem_added,
336 p_md );
337 vlc_event_detach( &p_md->p_input_item->event_manager,
338 vlc_InputItemMetaChanged,
339 input_item_meta_changed,
340 p_md );
341 vlc_event_detach( &p_md->p_input_item->event_manager,
342 vlc_InputItemDurationChanged,
343 input_item_duration_changed,
344 p_md );
345 vlc_event_detach( &p_md->p_input_item->event_manager,
346 vlc_InputItemPreparsedChanged,
347 input_item_preparsed_changed,
348 p_md );
349 vlc_event_detach( &p_md->p_input_item->event_manager,
350 vlc_InputItemSubItemTreeAdded,
351 input_item_subitemtree_added,
352 p_md );
353 vlc_event_detach( &p_md->p_input_item->event_manager,
354 vlc_InputItemPreparseEnded,
355 input_item_preparse_ended,
356 p_md );
359 /**************************************************************************
360 * Create a new media descriptor object from an input_item
361 * (libvlc internal)
362 * That's the generic constructor
363 **************************************************************************/
364 libvlc_media_t * libvlc_media_new_from_input_item(
365 libvlc_instance_t *p_instance,
366 input_item_t *p_input_item )
368 libvlc_media_t * p_md;
370 if (!p_input_item)
372 libvlc_printerr( "No input item given" );
373 return NULL;
376 p_md = calloc( 1, sizeof(libvlc_media_t) );
377 if( !p_md )
379 libvlc_printerr( "Not enough memory" );
380 return NULL;
383 p_md->p_libvlc_instance = p_instance;
384 p_md->p_input_item = p_input_item;
385 p_md->i_refcount = 1;
387 vlc_cond_init(&p_md->parsed_cond);
388 vlc_mutex_init(&p_md->parsed_lock);
389 vlc_mutex_init(&p_md->subitems_lock);
391 p_md->state = libvlc_NothingSpecial;
393 /* A media descriptor can be a playlist. When you open a playlist
394 * It can give a bunch of item to read. */
395 p_md->p_subitems = NULL;
397 p_md->p_event_manager = libvlc_event_manager_new( p_md );
398 if( unlikely(p_md->p_event_manager == NULL) )
400 free(p_md);
401 return NULL;
404 vlc_gc_incref( p_md->p_input_item );
406 install_input_item_observer( p_md );
408 libvlc_retain( p_instance );
409 return p_md;
412 /**************************************************************************
413 * Create a new media descriptor object
414 **************************************************************************/
415 libvlc_media_t *libvlc_media_new_location( libvlc_instance_t *p_instance,
416 const char * psz_mrl )
418 input_item_t * p_input_item;
419 libvlc_media_t * p_md;
421 p_input_item = input_item_New( psz_mrl, NULL );
423 if (!p_input_item)
425 libvlc_printerr( "Not enough memory" );
426 return NULL;
429 p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
431 /* The p_input_item is retained in libvlc_media_new_from_input_item */
432 vlc_gc_decref( p_input_item );
434 return p_md;
437 libvlc_media_t *libvlc_media_new_path( libvlc_instance_t *p_instance,
438 const char *path )
440 char *mrl = vlc_path2uri( path, NULL );
441 if( unlikely(mrl == NULL) )
443 libvlc_printerr( "%s", vlc_strerror_c(errno) );
444 return NULL;
447 libvlc_media_t *m = libvlc_media_new_location( p_instance, mrl );
448 free( mrl );
449 return m;
452 libvlc_media_t *libvlc_media_new_fd( libvlc_instance_t *p_instance, int fd )
454 char mrl[16];
455 snprintf( mrl, sizeof(mrl), "fd://%d", fd );
457 return libvlc_media_new_location( p_instance, mrl );
460 libvlc_media_t *libvlc_media_new_callbacks(libvlc_instance_t *p_instance,
461 libvlc_media_open_cb open_cb,
462 libvlc_media_read_cb read_cb,
463 libvlc_media_seek_cb seek_cb,
464 libvlc_media_close_cb close_cb,
465 void *opaque)
467 libvlc_media_t *m = libvlc_media_new_location(p_instance, "imem://");
468 if (unlikely(m == NULL))
469 return NULL;
471 assert(read_cb != NULL);
472 input_item_AddOpaque(m->p_input_item, "imem-data", opaque);
473 input_item_AddOpaque(m->p_input_item, "imem-open", open_cb);
474 input_item_AddOpaque(m->p_input_item, "imem-read", read_cb);
475 input_item_AddOpaque(m->p_input_item, "imem-seek", seek_cb);
476 input_item_AddOpaque(m->p_input_item, "imem-close", close_cb);
477 return m;
480 /**************************************************************************
481 * Create a new media descriptor object
482 **************************************************************************/
483 libvlc_media_t * libvlc_media_new_as_node( libvlc_instance_t *p_instance,
484 const char * psz_name )
486 input_item_t * p_input_item;
487 libvlc_media_t * p_md;
488 libvlc_media_list_t * p_subitems;
490 p_input_item = input_item_New( "vlc://nop", psz_name );
492 if (!p_input_item)
494 libvlc_printerr( "Not enough memory" );
495 return NULL;
498 p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
500 p_subitems = media_get_subitems( p_md, true );
501 if( p_subitems == NULL) {
502 libvlc_media_release( p_md );
503 return NULL;
506 return p_md;
509 /**************************************************************************
510 * Add an option to the media descriptor,
511 * that will be used to determine how the media_player will read the
512 * media. This allow to use VLC advanced reading/streaming
513 * options in a per-media basis
515 * The options are detailled in vlc --long-help, for instance "--sout-all"
516 **************************************************************************/
517 void libvlc_media_add_option( libvlc_media_t * p_md,
518 const char * psz_option )
520 libvlc_media_add_option_flag( p_md, psz_option,
521 VLC_INPUT_OPTION_UNIQUE|VLC_INPUT_OPTION_TRUSTED );
524 /**************************************************************************
525 * Same as libvlc_media_add_option but with configurable flags.
526 **************************************************************************/
527 void libvlc_media_add_option_flag( libvlc_media_t * p_md,
528 const char * ppsz_option,
529 unsigned i_flags )
531 input_item_AddOption( p_md->p_input_item, ppsz_option, i_flags );
534 /**************************************************************************
535 * Delete a media descriptor object
536 **************************************************************************/
537 void libvlc_media_release( libvlc_media_t *p_md )
539 if (!p_md)
540 return;
542 p_md->i_refcount--;
544 if( p_md->i_refcount > 0 )
545 return;
547 uninstall_input_item_observer( p_md );
549 if( p_md->p_subitems )
550 libvlc_media_list_release( p_md->p_subitems );
552 vlc_gc_decref( p_md->p_input_item );
554 vlc_cond_destroy( &p_md->parsed_cond );
555 vlc_mutex_destroy( &p_md->parsed_lock );
556 vlc_mutex_destroy( &p_md->subitems_lock );
558 /* Construct the event */
559 libvlc_event_t event;
560 event.type = libvlc_MediaFreed;
561 event.u.media_freed.md = p_md;
563 /* Send the event */
564 libvlc_event_send( p_md->p_event_manager, &event );
566 libvlc_event_manager_release( p_md->p_event_manager );
567 libvlc_release( p_md->p_libvlc_instance );
568 free( p_md );
571 /**************************************************************************
572 * Retain a media descriptor object
573 **************************************************************************/
574 void libvlc_media_retain( libvlc_media_t *p_md )
576 assert (p_md);
577 p_md->i_refcount++;
580 /**************************************************************************
581 * Duplicate a media descriptor object
582 **************************************************************************/
583 libvlc_media_t *
584 libvlc_media_duplicate( libvlc_media_t *p_md_orig )
586 return libvlc_media_new_from_input_item(
587 p_md_orig->p_libvlc_instance, p_md_orig->p_input_item );
590 /**************************************************************************
591 * Get mrl from a media descriptor object
592 **************************************************************************/
593 char *
594 libvlc_media_get_mrl( libvlc_media_t * p_md )
596 assert( p_md );
597 return input_item_GetURI( p_md->p_input_item );
600 /**************************************************************************
601 * Getter for meta information
602 **************************************************************************/
604 char *libvlc_media_get_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta )
606 char *psz_meta = NULL;
608 if( e_meta == libvlc_meta_NowPlaying )
610 psz_meta = input_item_GetNowPlayingFb( p_md->p_input_item );
612 else
614 psz_meta = input_item_GetMeta( p_md->p_input_item,
615 libvlc_to_vlc_meta[e_meta] );
616 /* Should be integrated in core */
617 if( psz_meta == NULL && e_meta == libvlc_meta_Title
618 && p_md->p_input_item->psz_name != NULL )
619 psz_meta = strdup( p_md->p_input_item->psz_name );
621 return psz_meta;
624 /**************************************************************************
625 * Setter for meta information
626 **************************************************************************/
628 void libvlc_media_set_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta, const char *psz_value )
630 assert( p_md );
631 input_item_SetMeta( p_md->p_input_item, libvlc_to_vlc_meta[e_meta], psz_value );
634 int libvlc_media_save_meta( libvlc_media_t *p_md )
636 assert( p_md );
637 vlc_object_t *p_obj = VLC_OBJECT(p_md->p_libvlc_instance->p_libvlc_int);
638 return input_item_WriteMeta( p_obj, p_md->p_input_item ) == VLC_SUCCESS;
641 /**************************************************************************
642 * Getter for state information
643 * Can be error, playing, buffering, NothingSpecial.
644 **************************************************************************/
646 libvlc_state_t
647 libvlc_media_get_state( libvlc_media_t *p_md )
649 assert( p_md );
650 return p_md->state;
653 /**************************************************************************
654 * Setter for state information (LibVLC Internal)
655 **************************************************************************/
657 void
658 libvlc_media_set_state( libvlc_media_t *p_md,
659 libvlc_state_t state )
661 libvlc_event_t event;
663 p_md->state = state;
665 /* Construct the event */
666 event.type = libvlc_MediaStateChanged;
667 event.u.media_state_changed.new_state = state;
669 /* Send the event */
670 libvlc_event_send( p_md->p_event_manager, &event );
673 /**************************************************************************
674 * subitems
675 **************************************************************************/
676 libvlc_media_list_t *
677 libvlc_media_subitems( libvlc_media_t * p_md )
679 libvlc_media_list_t *p_subitems = media_get_subitems( p_md, true );
680 if( p_subitems )
681 libvlc_media_list_retain( p_subitems );
682 return p_subitems;
685 /**************************************************************************
686 * Getter for statistics information
687 **************************************************************************/
688 int libvlc_media_get_stats( libvlc_media_t *p_md,
689 libvlc_media_stats_t *p_stats )
691 if( !p_md->p_input_item )
692 return false;
694 input_stats_t *p_itm_stats = p_md->p_input_item->p_stats;
695 vlc_mutex_lock( &p_itm_stats->lock );
696 p_stats->i_read_bytes = p_itm_stats->i_read_bytes;
697 p_stats->f_input_bitrate = p_itm_stats->f_input_bitrate;
699 p_stats->i_demux_read_bytes = p_itm_stats->i_demux_read_bytes;
700 p_stats->f_demux_bitrate = p_itm_stats->f_demux_bitrate;
701 p_stats->i_demux_corrupted = p_itm_stats->i_demux_corrupted;
702 p_stats->i_demux_discontinuity = p_itm_stats->i_demux_discontinuity;
704 p_stats->i_decoded_video = p_itm_stats->i_decoded_video;
705 p_stats->i_decoded_audio = p_itm_stats->i_decoded_audio;
707 p_stats->i_displayed_pictures = p_itm_stats->i_displayed_pictures;
708 p_stats->i_lost_pictures = p_itm_stats->i_lost_pictures;
710 p_stats->i_played_abuffers = p_itm_stats->i_played_abuffers;
711 p_stats->i_lost_abuffers = p_itm_stats->i_lost_abuffers;
713 p_stats->i_sent_packets = p_itm_stats->i_sent_packets;
714 p_stats->i_sent_bytes = p_itm_stats->i_sent_bytes;
715 p_stats->f_send_bitrate = p_itm_stats->f_send_bitrate;
716 vlc_mutex_unlock( &p_itm_stats->lock );
717 return true;
720 /**************************************************************************
721 * event_manager
722 **************************************************************************/
723 libvlc_event_manager_t *
724 libvlc_media_event_manager( libvlc_media_t * p_md )
726 assert( p_md );
728 return p_md->p_event_manager;
731 /**************************************************************************
732 * Get duration of media object (in ms)
733 **************************************************************************/
734 int64_t
735 libvlc_media_get_duration( libvlc_media_t * p_md )
737 assert( p_md );
739 if( !p_md->p_input_item )
741 libvlc_printerr( "No input item" );
742 return -1;
745 if (!input_item_IsPreparsed( p_md->p_input_item ))
746 return -1;
748 return from_mtime(input_item_GetDuration( p_md->p_input_item ));
751 static int media_parse(libvlc_media_t *media, bool b_async,
752 libvlc_media_parse_flag_t parse_flag)
754 bool needed;
756 vlc_mutex_lock(&media->parsed_lock);
757 needed = !media->has_asked_preparse;
758 media->has_asked_preparse = true;
759 vlc_mutex_unlock(&media->parsed_lock);
761 if (needed)
763 libvlc_int_t *libvlc = media->p_libvlc_instance->p_libvlc_int;
764 input_item_t *item = media->p_input_item;
765 input_item_meta_request_option_t art_scope = META_REQUEST_OPTION_NONE;
766 input_item_meta_request_option_t parse_scope = META_REQUEST_OPTION_SCOPE_LOCAL;
767 int ret;
769 if (parse_flag & libvlc_media_fetch_local)
770 art_scope |= META_REQUEST_OPTION_SCOPE_LOCAL;
771 if (parse_flag & libvlc_media_fetch_network)
772 art_scope |= META_REQUEST_OPTION_SCOPE_NETWORK;
773 if (art_scope != META_REQUEST_OPTION_NONE) {
774 ret = libvlc_ArtRequest(libvlc, item, art_scope);
775 if (ret != VLC_SUCCESS)
776 return ret;
779 if (parse_flag & libvlc_media_parse_network)
780 parse_scope |= META_REQUEST_OPTION_SCOPE_NETWORK;
781 if (parse_flag & libvlc_media_do_interact)
782 parse_scope |= META_REQUEST_OPTION_DO_INTERACT;
783 ret = libvlc_MetaRequest(libvlc, item, parse_scope);
784 if (ret != VLC_SUCCESS)
785 return ret;
787 else
788 return VLC_EGENERIC;
790 if (!b_async)
792 vlc_mutex_lock(&media->parsed_lock);
793 while (!media->is_parsed)
794 vlc_cond_wait(&media->parsed_cond, &media->parsed_lock);
795 vlc_mutex_unlock(&media->parsed_lock);
797 return VLC_SUCCESS;
800 /**************************************************************************
801 * Parse the media and wait.
802 **************************************************************************/
803 void
804 libvlc_media_parse(libvlc_media_t *media)
806 media_parse( media, false, libvlc_media_fetch_local );
809 /**************************************************************************
810 * Parse the media but do not wait.
811 **************************************************************************/
812 void
813 libvlc_media_parse_async(libvlc_media_t *media)
815 media_parse( media, true, libvlc_media_fetch_local );
818 /**************************************************************************
819 * Parse the media asynchronously with options.
820 **************************************************************************/
822 libvlc_media_parse_with_options( libvlc_media_t *media,
823 libvlc_media_parse_flag_t parse_flag )
825 return media_parse( media, true, parse_flag ) == VLC_SUCCESS ? 0 : -1;
828 /**************************************************************************
829 * Get parsed status for media object.
830 **************************************************************************/
832 libvlc_media_is_parsed(libvlc_media_t *media)
834 bool parsed;
836 vlc_mutex_lock(&media->parsed_lock);
837 parsed = media->is_parsed;
838 vlc_mutex_unlock(&media->parsed_lock);
839 return parsed;
842 libvlc_media_parsed_status_t
843 libvlc_media_get_parsed_status(libvlc_media_t *media)
845 libvlc_media_parsed_status_t status;
847 vlc_mutex_lock(&media->parsed_lock);
848 status = media->parsed_status;
849 vlc_mutex_unlock(&media->parsed_lock);
850 return status;
853 /**************************************************************************
854 * Sets media descriptor's user_data. user_data is specialized data
855 * accessed by the host application, VLC.framework uses it as a pointer to
856 * an native object that references a libvlc_media_t pointer
857 **************************************************************************/
858 void
859 libvlc_media_set_user_data( libvlc_media_t * p_md, void * p_new_user_data )
861 assert( p_md );
862 p_md->p_user_data = p_new_user_data;
865 /**************************************************************************
866 * Get media descriptor's user_data. user_data is specialized data
867 * accessed by the host application, VLC.framework uses it as a pointer to
868 * an native object that references a libvlc_media_t pointer
869 **************************************************************************/
870 void *
871 libvlc_media_get_user_data( libvlc_media_t * p_md )
873 assert( p_md );
874 return p_md->p_user_data;
877 /**************************************************************************
878 * Get media descriptor's elementary streams description
879 **************************************************************************/
881 libvlc_media_get_tracks_info( libvlc_media_t *p_md, libvlc_media_track_info_t ** pp_es )
883 assert( p_md );
885 input_item_t *p_input_item = p_md->p_input_item;
886 vlc_mutex_lock( &p_input_item->lock );
888 const int i_es = p_input_item->i_es;
889 *pp_es = (i_es > 0) ? malloc( i_es * sizeof(libvlc_media_track_info_t) ) : NULL;
891 if( !*pp_es ) /* no ES, or OOM */
893 vlc_mutex_unlock( &p_input_item->lock );
894 return 0;
897 /* Fill array */
898 for( int i = 0; i < i_es; i++ )
900 libvlc_media_track_info_t *p_mes = *pp_es+i;
901 const es_format_t *p_es = p_input_item->es[i];
903 p_mes->i_codec = p_es->i_codec;
904 p_mes->i_id = p_es->i_id;
906 p_mes->i_profile = p_es->i_profile;
907 p_mes->i_level = p_es->i_level;
909 switch(p_es->i_cat)
911 case UNKNOWN_ES:
912 default:
913 p_mes->i_type = libvlc_track_unknown;
914 break;
915 case VIDEO_ES:
916 p_mes->i_type = libvlc_track_video;
917 p_mes->u.video.i_height = p_es->video.i_visible_height;
918 p_mes->u.video.i_width = p_es->video.i_visible_width;
919 break;
920 case AUDIO_ES:
921 p_mes->i_type = libvlc_track_audio;
922 p_mes->u.audio.i_channels = p_es->audio.i_channels;
923 p_mes->u.audio.i_rate = p_es->audio.i_rate;
924 break;
925 case SPU_ES:
926 p_mes->i_type = libvlc_track_text;
927 break;
931 vlc_mutex_unlock( &p_input_item->lock );
932 return i_es;
935 unsigned
936 libvlc_media_tracks_get( libvlc_media_t *p_md, libvlc_media_track_t *** pp_es )
938 assert( p_md );
940 input_item_t *p_input_item = p_md->p_input_item;
941 vlc_mutex_lock( &p_input_item->lock );
943 const int i_es = p_input_item->i_es;
944 *pp_es = (i_es > 0) ? calloc( i_es, sizeof(**pp_es) ) : NULL;
946 if( !*pp_es ) /* no ES, or OOM */
948 vlc_mutex_unlock( &p_input_item->lock );
949 return 0;
952 /* Fill array */
953 for( int i = 0; i < i_es; i++ )
955 libvlc_media_track_t *p_mes = calloc( 1, sizeof(*p_mes) );
956 if ( p_mes )
958 p_mes->audio = malloc( __MAX(__MAX(sizeof(*p_mes->audio),
959 sizeof(*p_mes->video)),
960 sizeof(*p_mes->subtitle)) );
962 if ( !p_mes || !p_mes->audio )
964 libvlc_media_tracks_release( *pp_es, i_es );
965 *pp_es = NULL;
966 free( p_mes );
967 vlc_mutex_unlock( &p_input_item->lock );
968 return 0;
970 (*pp_es)[i] = p_mes;
972 const es_format_t *p_es = p_input_item->es[i];
974 p_mes->i_codec = p_es->i_codec;
975 p_mes->i_original_fourcc = p_es->i_original_fourcc;
976 p_mes->i_id = p_es->i_id;
978 p_mes->i_profile = p_es->i_profile;
979 p_mes->i_level = p_es->i_level;
981 p_mes->i_bitrate = p_es->i_bitrate;
982 p_mes->psz_language = p_es->psz_language != NULL ? strdup(p_es->psz_language) : NULL;
983 p_mes->psz_description = p_es->psz_description != NULL ? strdup(p_es->psz_description) : NULL;
985 switch(p_es->i_cat)
987 case UNKNOWN_ES:
988 default:
989 p_mes->i_type = libvlc_track_unknown;
990 break;
991 case VIDEO_ES:
992 p_mes->i_type = libvlc_track_video;
993 p_mes->video->i_height = p_es->video.i_visible_height;
994 p_mes->video->i_width = p_es->video.i_visible_width;
995 p_mes->video->i_sar_num = p_es->video.i_sar_num;
996 p_mes->video->i_sar_den = p_es->video.i_sar_den;
997 p_mes->video->i_frame_rate_num = p_es->video.i_frame_rate;
998 p_mes->video->i_frame_rate_den = p_es->video.i_frame_rate_base;
999 break;
1000 case AUDIO_ES:
1001 p_mes->i_type = libvlc_track_audio;
1002 p_mes->audio->i_channels = p_es->audio.i_channels;
1003 p_mes->audio->i_rate = p_es->audio.i_rate;
1004 break;
1005 case SPU_ES:
1006 p_mes->i_type = libvlc_track_text;
1007 p_mes->subtitle->psz_encoding = p_es->subs.psz_encoding != NULL ?
1008 strdup(p_es->subs.psz_encoding) : NULL;
1009 break;
1013 vlc_mutex_unlock( &p_input_item->lock );
1014 return i_es;
1017 /**************************************************************************
1018 * Get codec description from media elementary stream
1019 **************************************************************************/
1020 const char *
1021 libvlc_media_get_codec_description( libvlc_track_type_t i_type,
1022 uint32_t i_codec )
1024 switch( i_type )
1026 case libvlc_track_audio:
1027 return vlc_fourcc_GetDescription( AUDIO_ES, i_codec );
1028 case libvlc_track_video:
1029 return vlc_fourcc_GetDescription( VIDEO_ES, i_codec );
1030 case libvlc_track_text:
1031 return vlc_fourcc_GetDescription( SPU_ES, i_codec );
1032 case libvlc_track_unknown:
1033 default:
1034 return vlc_fourcc_GetDescription( UNKNOWN_ES, i_codec );
1038 /**************************************************************************
1039 * Release media descriptor's elementary streams description array
1040 **************************************************************************/
1041 void libvlc_media_tracks_release( libvlc_media_track_t **p_tracks, unsigned i_count )
1043 for( unsigned i = 0; i < i_count; ++i )
1045 if ( !p_tracks[i] )
1046 continue;
1047 free( p_tracks[i]->psz_language );
1048 free( p_tracks[i]->psz_description );
1049 switch( p_tracks[i]->i_type )
1051 case libvlc_track_audio:
1052 break;
1053 case libvlc_track_video:
1054 break;
1055 case libvlc_track_text:
1056 free( p_tracks[i]->subtitle->psz_encoding );
1057 break;
1058 case libvlc_track_unknown:
1059 default:
1060 break;
1062 free( p_tracks[i]->audio );
1063 free( p_tracks[i] );
1065 free( p_tracks );
1068 /**************************************************************************
1069 * Get the media type of the media descriptor object
1070 **************************************************************************/
1071 libvlc_media_type_t libvlc_media_get_type( libvlc_media_t *p_md )
1073 assert( p_md );
1075 int i_type;
1076 input_item_t *p_input_item = p_md->p_input_item;
1078 vlc_mutex_lock( &p_input_item->lock );
1079 i_type = p_md->p_input_item->i_type;
1080 vlc_mutex_unlock( &p_input_item->lock );
1082 switch( i_type )
1084 case ITEM_TYPE_FILE:
1085 return libvlc_media_type_file;
1086 case ITEM_TYPE_NODE:
1087 case ITEM_TYPE_DIRECTORY:
1088 return libvlc_media_type_directory;
1089 case ITEM_TYPE_DISC:
1090 return libvlc_media_type_disc;
1091 case ITEM_TYPE_STREAM:
1092 return libvlc_media_type_stream;
1093 case ITEM_TYPE_PLAYLIST:
1094 return libvlc_media_type_playlist;
1095 default:
1096 return libvlc_media_type_unknown;
1100 int libvlc_media_slaves_add( libvlc_media_t *p_md,
1101 libvlc_media_slave_type_t i_type,
1102 unsigned int i_priority,
1103 const char *psz_uri )
1105 assert( p_md && psz_uri );
1106 input_item_t *p_input_item = p_md->p_input_item;
1108 enum slave_type i_input_slave_type;
1109 switch( i_type )
1111 case libvlc_media_slave_type_subtitle:
1112 i_input_slave_type = SLAVE_TYPE_SPU;
1113 break;
1114 case libvlc_media_slave_type_audio:
1115 i_input_slave_type = SLAVE_TYPE_AUDIO;
1116 default:
1117 vlc_assert_unreachable();
1118 return -1;
1121 enum slave_priority i_input_slave_priority;
1122 switch( i_priority )
1124 case 0:
1125 i_input_slave_priority = SLAVE_PRIORITY_MATCH_NONE;
1126 break;
1127 case 1:
1128 i_input_slave_priority = SLAVE_PRIORITY_MATCH_RIGHT;
1129 break;
1130 case 2:
1131 i_input_slave_priority = SLAVE_PRIORITY_MATCH_LEFT;
1132 break;
1133 case 3:
1134 i_input_slave_priority = SLAVE_PRIORITY_MATCH_ALL;
1135 break;
1136 default:
1137 case 4:
1138 i_input_slave_priority = SLAVE_PRIORITY_USER;
1139 break;
1142 input_item_slave_t *p_slave = input_item_slave_New( psz_uri,
1143 i_input_slave_type,
1144 i_input_slave_priority );
1145 if( p_slave == NULL )
1146 return -1;
1147 return input_item_AddSlave( p_input_item, p_slave ) == VLC_SUCCESS ? 0 : -1;
1150 void libvlc_media_slaves_clear( libvlc_media_t *p_md )
1152 assert( p_md );
1153 input_item_t *p_input_item = p_md->p_input_item;
1155 vlc_mutex_lock( &p_input_item->lock );
1156 for( int i = 0; i < p_input_item->i_slaves; i++ )
1157 input_item_slave_Delete( p_input_item->pp_slaves[i] );
1158 TAB_CLEAN( p_input_item->i_slaves, p_input_item->pp_slaves );
1159 vlc_mutex_unlock( &p_input_item->lock );
1162 unsigned int libvlc_media_slaves_get( libvlc_media_t *p_md,
1163 libvlc_media_slave_t ***ppp_slaves )
1165 assert( p_md && ppp_slaves );
1166 input_item_t *p_input_item = p_md->p_input_item;
1168 vlc_mutex_lock( &p_input_item->lock );
1170 int i_count = p_input_item->i_slaves;
1171 if( i_count <= 0 )
1172 return vlc_mutex_unlock( &p_input_item->lock ), 0;
1174 libvlc_media_slave_t **pp_slaves = calloc( i_count, sizeof(*pp_slaves) );
1175 if( pp_slaves == NULL )
1176 return vlc_mutex_unlock( &p_input_item->lock ), 0;
1178 for( int i = 0; i < i_count; ++i )
1180 input_item_slave_t *p_item_slave = p_input_item->pp_slaves[i];
1181 assert( p_item_slave->i_priority >= SLAVE_PRIORITY_MATCH_NONE );
1183 libvlc_media_slave_t *p_slave = malloc( sizeof(*p_slave) +
1184 strlen( p_item_slave->psz_uri )
1185 + 1 );
1187 if( p_slave == NULL )
1189 libvlc_media_slaves_release(pp_slaves, i);
1190 return vlc_mutex_unlock( &p_input_item->lock ), 0;
1192 strcpy( p_slave->psz_uri, p_item_slave->psz_uri );
1194 switch( p_item_slave->i_type )
1196 case SLAVE_TYPE_SPU:
1197 p_slave->i_type = libvlc_media_slave_type_subtitle;
1198 break;
1199 case SLAVE_TYPE_AUDIO:
1200 p_slave->i_type = libvlc_media_slave_type_audio;
1201 break;
1202 default:
1203 vlc_assert_unreachable();
1206 switch( p_item_slave->i_priority )
1208 case SLAVE_PRIORITY_MATCH_NONE:
1209 p_slave->i_priority = 0;
1210 break;
1211 case SLAVE_PRIORITY_MATCH_RIGHT:
1212 p_slave->i_priority = 1;
1213 break;
1214 case SLAVE_PRIORITY_MATCH_LEFT:
1215 p_slave->i_priority = 2;
1216 break;
1217 case SLAVE_PRIORITY_MATCH_ALL:
1218 p_slave->i_priority = 3;
1219 break;
1220 case SLAVE_PRIORITY_USER:
1221 p_slave->i_priority = 4;
1222 break;
1223 default:
1224 vlc_assert_unreachable();
1226 pp_slaves[i] = p_slave;
1228 vlc_mutex_unlock( &p_input_item->lock );
1230 *ppp_slaves = pp_slaves;
1231 return i_count;
1234 void libvlc_media_slaves_release( libvlc_media_slave_t **pp_slaves,
1235 unsigned int i_count )
1237 assert( pp_slaves );
1238 for( unsigned int i = 0; i < i_count; ++i )
1239 free(pp_slaves[i]);
1240 free(pp_slaves);