blend: remove unused include
[vlc.git] / lib / media.c
blobf5886ade2f37847b46eae8a5dac518edfaed73fb
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
77 static const libvlc_meta_t vlc_to_libvlc_meta[] =
79 [vlc_meta_Title] = libvlc_meta_Title,
80 [vlc_meta_Artist] = libvlc_meta_Artist,
81 [vlc_meta_Genre] = libvlc_meta_Genre,
82 [vlc_meta_Copyright] = libvlc_meta_Copyright,
83 [vlc_meta_Album] = libvlc_meta_Album,
84 [vlc_meta_TrackNumber] = libvlc_meta_TrackNumber,
85 [vlc_meta_Description] = libvlc_meta_Description,
86 [vlc_meta_Rating] = libvlc_meta_Rating,
87 [vlc_meta_Date] = libvlc_meta_Date,
88 [vlc_meta_Setting] = libvlc_meta_Setting,
89 [vlc_meta_URL] = libvlc_meta_URL,
90 [vlc_meta_Language] = libvlc_meta_Language,
91 [vlc_meta_NowPlaying] = libvlc_meta_NowPlaying,
92 [vlc_meta_ESNowPlaying] = libvlc_meta_NowPlaying,
93 [vlc_meta_Publisher] = libvlc_meta_Publisher,
94 [vlc_meta_EncodedBy] = libvlc_meta_EncodedBy,
95 [vlc_meta_ArtworkURL] = libvlc_meta_ArtworkURL,
96 [vlc_meta_TrackID] = libvlc_meta_TrackID,
97 [vlc_meta_TrackTotal] = libvlc_meta_TrackTotal,
98 [vlc_meta_Director] = libvlc_meta_Director,
99 [vlc_meta_Season] = libvlc_meta_Season,
100 [vlc_meta_Episode] = libvlc_meta_Episode,
101 [vlc_meta_ShowName] = libvlc_meta_ShowName,
102 [vlc_meta_Actors] = libvlc_meta_Actors,
103 [vlc_meta_AlbumArtist] = libvlc_meta_AlbumArtist,
104 [vlc_meta_DiscNumber] = libvlc_meta_DiscNumber
107 static libvlc_media_list_t *media_get_subitems( libvlc_media_t * p_md,
108 bool b_create )
110 libvlc_media_list_t *p_subitems = NULL;
112 vlc_mutex_lock( &p_md->subitems_lock );
113 if( p_md->p_subitems == NULL && b_create )
115 p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance );
116 if( p_md->p_subitems != NULL )
118 p_md->p_subitems->b_read_only = true;
119 p_md->p_subitems->p_internal_md = p_md;
122 p_subitems = p_md->p_subitems;
123 vlc_mutex_unlock( &p_md->subitems_lock );
124 return p_subitems;
127 /**************************************************************************
128 * input_item_subitem_added (Private) (vlc event Callback)
129 **************************************************************************/
130 static void input_item_subitem_added( const vlc_event_t *p_event,
131 void * user_data )
133 libvlc_media_t * p_md = user_data;
134 libvlc_media_t * p_md_child;
135 libvlc_media_list_t *p_subitems;
136 libvlc_event_t event;
138 p_md_child = libvlc_media_new_from_input_item(
139 p_md->p_libvlc_instance,
140 p_event->u.input_item_subitem_added.p_new_child );
142 /* Add this to our media list */
143 p_subitems = media_get_subitems( p_md, true );
144 if( p_subitems != NULL )
146 libvlc_media_list_lock( p_subitems );
147 libvlc_media_list_internal_add_media( p_subitems, p_md_child );
148 libvlc_media_list_unlock( p_subitems );
151 /* Construct the event */
152 event.type = libvlc_MediaSubItemAdded;
153 event.u.media_subitem_added.new_child = p_md_child;
155 /* Send the event */
156 libvlc_event_send( p_md->p_event_manager, &event );
157 libvlc_media_release( p_md_child );
160 /**************************************************************************
161 * input_item_subitemtree_added (Private) (vlc event Callback)
162 **************************************************************************/
163 static void input_item_subitemtree_added( const vlc_event_t * p_event,
164 void * user_data )
166 VLC_UNUSED( p_event );
167 libvlc_media_t * p_md = user_data;
168 libvlc_event_t event;
170 /* Construct the event */
171 event.type = libvlc_MediaSubItemTreeAdded;
172 event.u.media_subitemtree_added.item = p_md;
174 /* Send the event */
175 libvlc_event_send( p_md->p_event_manager, &event );
178 /**************************************************************************
179 * input_item_meta_changed (Private) (vlc event Callback)
180 **************************************************************************/
181 static void input_item_meta_changed( const vlc_event_t *p_event,
182 void * user_data )
184 libvlc_media_t * p_md = user_data;
185 libvlc_event_t event;
187 /* Construct the event */
188 event.type = libvlc_MediaMetaChanged;
189 event.u.media_meta_changed.meta_type =
190 vlc_to_libvlc_meta[p_event->u.input_item_meta_changed.meta_type];
192 /* Send the event */
193 libvlc_event_send( p_md->p_event_manager, &event );
196 /**************************************************************************
197 * input_item_duration_changed (Private) (vlc event Callback)
198 **************************************************************************/
199 static void input_item_duration_changed( const vlc_event_t *p_event,
200 void * user_data )
202 libvlc_media_t * p_md = user_data;
203 libvlc_event_t event;
205 /* Construct the event */
206 event.type = libvlc_MediaDurationChanged;
207 event.u.media_duration_changed.new_duration =
208 from_mtime(p_event->u.input_item_duration_changed.new_duration);
210 /* Send the event */
211 libvlc_event_send( p_md->p_event_manager, &event );
214 /**************************************************************************
215 * input_item_preparsed_changed (Private) (vlc event Callback)
216 **************************************************************************/
217 static void input_item_preparsed_changed(const vlc_event_t *p_event,
218 void * user_data)
220 libvlc_media_t *media = user_data;
221 libvlc_event_t event;
223 /* Eventually notify libvlc_media_parse() */
224 vlc_mutex_lock(&media->parsed_lock);
225 media->is_parsed = true;
226 vlc_cond_broadcast(&media->parsed_cond);
227 vlc_mutex_unlock(&media->parsed_lock);
230 /* Construct the event */
231 event.type = libvlc_MediaParsedChanged;
232 event.u.media_parsed_changed.new_status =
233 p_event->u.input_item_preparsed_changed.new_status;
235 /* Send the event */
236 libvlc_event_send(media->p_event_manager, &event);
239 /**************************************************************************
240 * input_item_preparse_ended (Private) (vlc event Callback)
241 **************************************************************************/
242 static void input_item_preparse_ended( const vlc_event_t * p_event,
243 void * user_data )
245 VLC_UNUSED( p_event );
246 libvlc_media_t * p_md = user_data;
247 libvlc_media_list_t *p_subitems = media_get_subitems( p_md, false );
249 if( p_subitems != NULL )
251 /* notify the media list */
252 libvlc_media_list_lock( p_subitems );
253 libvlc_media_list_internal_end_reached( p_subitems );
254 libvlc_media_list_unlock( p_subitems );
258 /**************************************************************************
259 * Install event handler (Private)
260 **************************************************************************/
261 static void install_input_item_observer( libvlc_media_t *p_md )
263 vlc_event_attach( &p_md->p_input_item->event_manager,
264 vlc_InputItemSubItemAdded,
265 input_item_subitem_added,
266 p_md );
267 vlc_event_attach( &p_md->p_input_item->event_manager,
268 vlc_InputItemMetaChanged,
269 input_item_meta_changed,
270 p_md );
271 vlc_event_attach( &p_md->p_input_item->event_manager,
272 vlc_InputItemDurationChanged,
273 input_item_duration_changed,
274 p_md );
275 vlc_event_attach( &p_md->p_input_item->event_manager,
276 vlc_InputItemPreparsedChanged,
277 input_item_preparsed_changed,
278 p_md );
279 vlc_event_attach( &p_md->p_input_item->event_manager,
280 vlc_InputItemSubItemTreeAdded,
281 input_item_subitemtree_added,
282 p_md );
283 vlc_event_attach( &p_md->p_input_item->event_manager,
284 vlc_InputItemPreparseEnded,
285 input_item_preparse_ended,
286 p_md );
289 /**************************************************************************
290 * Uninstall event handler (Private)
291 **************************************************************************/
292 static void uninstall_input_item_observer( libvlc_media_t *p_md )
294 vlc_event_detach( &p_md->p_input_item->event_manager,
295 vlc_InputItemSubItemAdded,
296 input_item_subitem_added,
297 p_md );
298 vlc_event_detach( &p_md->p_input_item->event_manager,
299 vlc_InputItemMetaChanged,
300 input_item_meta_changed,
301 p_md );
302 vlc_event_detach( &p_md->p_input_item->event_manager,
303 vlc_InputItemDurationChanged,
304 input_item_duration_changed,
305 p_md );
306 vlc_event_detach( &p_md->p_input_item->event_manager,
307 vlc_InputItemPreparsedChanged,
308 input_item_preparsed_changed,
309 p_md );
310 vlc_event_detach( &p_md->p_input_item->event_manager,
311 vlc_InputItemSubItemTreeAdded,
312 input_item_subitemtree_added,
313 p_md );
314 vlc_event_detach( &p_md->p_input_item->event_manager,
315 vlc_InputItemPreparseEnded,
316 input_item_preparse_ended,
317 p_md );
320 /**************************************************************************
321 * Create a new media descriptor object from an input_item
322 * (libvlc internal)
323 * That's the generic constructor
324 **************************************************************************/
325 libvlc_media_t * libvlc_media_new_from_input_item(
326 libvlc_instance_t *p_instance,
327 input_item_t *p_input_item )
329 libvlc_media_t * p_md;
331 if (!p_input_item)
333 libvlc_printerr( "No input item given" );
334 return NULL;
337 p_md = calloc( 1, sizeof(libvlc_media_t) );
338 if( !p_md )
340 libvlc_printerr( "Not enough memory" );
341 return NULL;
344 p_md->p_libvlc_instance = p_instance;
345 p_md->p_input_item = p_input_item;
346 p_md->i_refcount = 1;
348 vlc_cond_init(&p_md->parsed_cond);
349 vlc_mutex_init(&p_md->parsed_lock);
350 vlc_mutex_init(&p_md->subitems_lock);
352 p_md->state = libvlc_NothingSpecial;
354 /* A media descriptor can be a playlist. When you open a playlist
355 * It can give a bunch of item to read. */
356 p_md->p_subitems = NULL;
358 p_md->p_event_manager = libvlc_event_manager_new( p_md, p_instance );
359 if( unlikely(p_md->p_event_manager == NULL) )
361 free(p_md);
362 return NULL;
365 libvlc_event_manager_t *em = p_md->p_event_manager;
366 libvlc_event_manager_register_event_type(em, libvlc_MediaMetaChanged);
367 libvlc_event_manager_register_event_type(em, libvlc_MediaSubItemAdded);
368 libvlc_event_manager_register_event_type(em, libvlc_MediaFreed);
369 libvlc_event_manager_register_event_type(em, libvlc_MediaDurationChanged);
370 libvlc_event_manager_register_event_type(em, libvlc_MediaStateChanged);
371 libvlc_event_manager_register_event_type(em, libvlc_MediaParsedChanged);
372 libvlc_event_manager_register_event_type(em, libvlc_MediaSubItemTreeAdded);
374 vlc_gc_incref( p_md->p_input_item );
376 install_input_item_observer( p_md );
378 return p_md;
381 /**************************************************************************
382 * Create a new media descriptor object
383 **************************************************************************/
384 libvlc_media_t *libvlc_media_new_location( libvlc_instance_t *p_instance,
385 const char * psz_mrl )
387 input_item_t * p_input_item;
388 libvlc_media_t * p_md;
390 p_input_item = input_item_New( psz_mrl, NULL );
392 if (!p_input_item)
394 libvlc_printerr( "Not enough memory" );
395 return NULL;
398 p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
400 /* The p_input_item is retained in libvlc_media_new_from_input_item */
401 vlc_gc_decref( p_input_item );
403 return p_md;
406 libvlc_media_t *libvlc_media_new_path( libvlc_instance_t *p_instance,
407 const char *path )
409 char *mrl = vlc_path2uri( path, NULL );
410 if( unlikely(mrl == NULL) )
412 libvlc_printerr( "%s", vlc_strerror_c(errno) );
413 return NULL;
416 libvlc_media_t *m = libvlc_media_new_location( p_instance, mrl );
417 free( mrl );
418 return m;
421 libvlc_media_t *libvlc_media_new_fd( libvlc_instance_t *p_instance, int fd )
423 char mrl[16];
424 snprintf( mrl, sizeof(mrl), "fd://%d", fd );
426 return libvlc_media_new_location( p_instance, mrl );
429 libvlc_media_t *libvlc_media_new_callbacks(libvlc_instance_t *p_instance,
430 libvlc_media_open_cb open_cb,
431 libvlc_media_read_cb read_cb,
432 libvlc_media_seek_cb seek_cb,
433 libvlc_media_close_cb close_cb,
434 void *opaque)
436 libvlc_media_t *m = libvlc_media_new_location(p_instance, "imem://");
437 if (unlikely(m == NULL))
438 return NULL;
440 assert(read_cb != NULL);
441 input_item_AddOpaque(m->p_input_item, "imem-data", opaque);
442 input_item_AddOpaque(m->p_input_item, "imem-open", open_cb);
443 input_item_AddOpaque(m->p_input_item, "imem-read", read_cb);
444 input_item_AddOpaque(m->p_input_item, "imem-seek", seek_cb);
445 input_item_AddOpaque(m->p_input_item, "imem-close", close_cb);
446 return m;
449 /**************************************************************************
450 * Create a new media descriptor object
451 **************************************************************************/
452 libvlc_media_t * libvlc_media_new_as_node( libvlc_instance_t *p_instance,
453 const char * psz_name )
455 input_item_t * p_input_item;
456 libvlc_media_t * p_md;
457 libvlc_media_list_t * p_subitems;
459 p_input_item = input_item_New( "vlc://nop", psz_name );
461 if (!p_input_item)
463 libvlc_printerr( "Not enough memory" );
464 return NULL;
467 p_md = libvlc_media_new_from_input_item( p_instance, p_input_item );
469 p_subitems = media_get_subitems( p_md, true );
470 if( p_subitems == NULL) {
471 libvlc_media_release( p_md );
472 return NULL;
475 return p_md;
478 /**************************************************************************
479 * Add an option to the media descriptor,
480 * that will be used to determine how the media_player will read the
481 * media. This allow to use VLC advanced reading/streaming
482 * options in a per-media basis
484 * The options are detailled in vlc --long-help, for instance "--sout-all"
485 **************************************************************************/
486 void libvlc_media_add_option( libvlc_media_t * p_md,
487 const char * psz_option )
489 libvlc_media_add_option_flag( p_md, psz_option,
490 VLC_INPUT_OPTION_UNIQUE|VLC_INPUT_OPTION_TRUSTED );
493 /**************************************************************************
494 * Same as libvlc_media_add_option but with configurable flags.
495 **************************************************************************/
496 void libvlc_media_add_option_flag( libvlc_media_t * p_md,
497 const char * ppsz_option,
498 unsigned i_flags )
500 input_item_AddOption( p_md->p_input_item, ppsz_option, i_flags );
503 /**************************************************************************
504 * Delete a media descriptor object
505 **************************************************************************/
506 void libvlc_media_release( libvlc_media_t *p_md )
508 if (!p_md)
509 return;
511 p_md->i_refcount--;
513 if( p_md->i_refcount > 0 )
514 return;
516 if( p_md->p_subitems )
517 libvlc_media_list_release( p_md->p_subitems );
519 uninstall_input_item_observer( p_md );
520 vlc_gc_decref( p_md->p_input_item );
522 vlc_cond_destroy( &p_md->parsed_cond );
523 vlc_mutex_destroy( &p_md->parsed_lock );
524 vlc_mutex_destroy( &p_md->subitems_lock );
526 /* Construct the event */
527 libvlc_event_t event;
528 event.type = libvlc_MediaFreed;
529 event.u.media_freed.md = p_md;
531 /* Send the event */
532 libvlc_event_send( p_md->p_event_manager, &event );
534 libvlc_event_manager_release( p_md->p_event_manager );
536 free( p_md );
539 /**************************************************************************
540 * Retain a media descriptor object
541 **************************************************************************/
542 void libvlc_media_retain( libvlc_media_t *p_md )
544 assert (p_md);
545 p_md->i_refcount++;
548 /**************************************************************************
549 * Duplicate a media descriptor object
550 **************************************************************************/
551 libvlc_media_t *
552 libvlc_media_duplicate( libvlc_media_t *p_md_orig )
554 return libvlc_media_new_from_input_item(
555 p_md_orig->p_libvlc_instance, p_md_orig->p_input_item );
558 /**************************************************************************
559 * Get mrl from a media descriptor object
560 **************************************************************************/
561 char *
562 libvlc_media_get_mrl( libvlc_media_t * p_md )
564 assert( p_md );
565 return input_item_GetURI( p_md->p_input_item );
568 /**************************************************************************
569 * Getter for meta information
570 **************************************************************************/
572 char *libvlc_media_get_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta )
574 char *psz_meta = NULL;
576 if( e_meta == libvlc_meta_NowPlaying )
578 psz_meta = input_item_GetNowPlayingFb( p_md->p_input_item );
580 else
582 psz_meta = input_item_GetMeta( p_md->p_input_item,
583 libvlc_to_vlc_meta[e_meta] );
584 /* Should be integrated in core */
585 if( psz_meta == NULL && e_meta == libvlc_meta_Title
586 && p_md->p_input_item->psz_name != NULL )
587 psz_meta = strdup( p_md->p_input_item->psz_name );
589 return psz_meta;
592 /**************************************************************************
593 * Setter for meta information
594 **************************************************************************/
596 void libvlc_media_set_meta( libvlc_media_t *p_md, libvlc_meta_t e_meta, const char *psz_value )
598 assert( p_md );
599 input_item_SetMeta( p_md->p_input_item, libvlc_to_vlc_meta[e_meta], psz_value );
602 int libvlc_media_save_meta( libvlc_media_t *p_md )
604 assert( p_md );
605 vlc_object_t *p_obj = VLC_OBJECT(p_md->p_libvlc_instance->p_libvlc_int);
606 return input_item_WriteMeta( p_obj, p_md->p_input_item ) == VLC_SUCCESS;
609 /**************************************************************************
610 * Getter for state information
611 * Can be error, playing, buffering, NothingSpecial.
612 **************************************************************************/
614 libvlc_state_t
615 libvlc_media_get_state( libvlc_media_t *p_md )
617 assert( p_md );
618 return p_md->state;
621 /**************************************************************************
622 * Setter for state information (LibVLC Internal)
623 **************************************************************************/
625 void
626 libvlc_media_set_state( libvlc_media_t *p_md,
627 libvlc_state_t state )
629 libvlc_event_t event;
631 p_md->state = state;
633 /* Construct the event */
634 event.type = libvlc_MediaStateChanged;
635 event.u.media_state_changed.new_state = state;
637 /* Send the event */
638 libvlc_event_send( p_md->p_event_manager, &event );
641 /**************************************************************************
642 * subitems
643 **************************************************************************/
644 libvlc_media_list_t *
645 libvlc_media_subitems( libvlc_media_t * p_md )
647 libvlc_media_list_t *p_subitems = media_get_subitems( p_md, true );
648 if( p_subitems )
649 libvlc_media_list_retain( p_subitems );
650 return p_subitems;
653 /**************************************************************************
654 * Getter for statistics information
655 **************************************************************************/
656 int libvlc_media_get_stats( libvlc_media_t *p_md,
657 libvlc_media_stats_t *p_stats )
659 if( !p_md->p_input_item )
660 return false;
662 input_stats_t *p_itm_stats = p_md->p_input_item->p_stats;
663 vlc_mutex_lock( &p_itm_stats->lock );
664 p_stats->i_read_bytes = p_itm_stats->i_read_bytes;
665 p_stats->f_input_bitrate = p_itm_stats->f_input_bitrate;
667 p_stats->i_demux_read_bytes = p_itm_stats->i_demux_read_bytes;
668 p_stats->f_demux_bitrate = p_itm_stats->f_demux_bitrate;
669 p_stats->i_demux_corrupted = p_itm_stats->i_demux_corrupted;
670 p_stats->i_demux_discontinuity = p_itm_stats->i_demux_discontinuity;
672 p_stats->i_decoded_video = p_itm_stats->i_decoded_video;
673 p_stats->i_decoded_audio = p_itm_stats->i_decoded_audio;
675 p_stats->i_displayed_pictures = p_itm_stats->i_displayed_pictures;
676 p_stats->i_lost_pictures = p_itm_stats->i_lost_pictures;
678 p_stats->i_played_abuffers = p_itm_stats->i_played_abuffers;
679 p_stats->i_lost_abuffers = p_itm_stats->i_lost_abuffers;
681 p_stats->i_sent_packets = p_itm_stats->i_sent_packets;
682 p_stats->i_sent_bytes = p_itm_stats->i_sent_bytes;
683 p_stats->f_send_bitrate = p_itm_stats->f_send_bitrate;
684 vlc_mutex_unlock( &p_itm_stats->lock );
685 return true;
688 /**************************************************************************
689 * event_manager
690 **************************************************************************/
691 libvlc_event_manager_t *
692 libvlc_media_event_manager( libvlc_media_t * p_md )
694 assert( p_md );
696 return p_md->p_event_manager;
699 /**************************************************************************
700 * Get duration of media object (in ms)
701 **************************************************************************/
702 int64_t
703 libvlc_media_get_duration( libvlc_media_t * p_md )
705 assert( p_md );
707 if( !p_md->p_input_item )
709 libvlc_printerr( "No input item" );
710 return -1;
713 if (!input_item_IsPreparsed( p_md->p_input_item ))
714 return -1;
716 return from_mtime(input_item_GetDuration( p_md->p_input_item ));
719 static int media_parse(libvlc_media_t *media, bool b_async,
720 libvlc_media_parse_flag_t parse_flag)
722 bool needed;
724 vlc_mutex_lock(&media->parsed_lock);
725 needed = !media->has_asked_preparse;
726 media->has_asked_preparse = true;
727 vlc_mutex_unlock(&media->parsed_lock);
729 if (needed)
731 libvlc_int_t *libvlc = media->p_libvlc_instance->p_libvlc_int;
732 input_item_t *item = media->p_input_item;
733 input_item_meta_request_option_t art_scope = META_REQUEST_OPTION_NONE;
734 input_item_meta_request_option_t parse_scope = META_REQUEST_OPTION_SCOPE_LOCAL;
735 int ret;
737 if (parse_flag & libvlc_media_fetch_local)
738 art_scope |= META_REQUEST_OPTION_SCOPE_LOCAL;
739 if (parse_flag & libvlc_media_fetch_network)
740 art_scope |= META_REQUEST_OPTION_SCOPE_NETWORK;
741 if (art_scope != META_REQUEST_OPTION_NONE) {
742 ret = libvlc_ArtRequest(libvlc, item, art_scope);
743 if (ret != VLC_SUCCESS)
744 return ret;
747 if (parse_flag & libvlc_media_parse_network)
748 parse_scope |= META_REQUEST_OPTION_SCOPE_NETWORK;
749 ret = libvlc_MetaRequest(libvlc, item, parse_scope);
750 if (ret != VLC_SUCCESS)
751 return ret;
753 else
754 return VLC_EGENERIC;
756 if (!b_async)
758 vlc_mutex_lock(&media->parsed_lock);
759 while (!media->is_parsed)
760 vlc_cond_wait(&media->parsed_cond, &media->parsed_lock);
761 vlc_mutex_unlock(&media->parsed_lock);
763 return VLC_SUCCESS;
766 /**************************************************************************
767 * Parse the media and wait.
768 **************************************************************************/
769 void
770 libvlc_media_parse(libvlc_media_t *media)
772 media_parse( media, false, libvlc_media_fetch_local );
775 /**************************************************************************
776 * Parse the media but do not wait.
777 **************************************************************************/
778 void
779 libvlc_media_parse_async(libvlc_media_t *media)
781 media_parse( media, true, libvlc_media_fetch_local );
784 /**************************************************************************
785 * Parse the media asynchronously with options.
786 **************************************************************************/
788 libvlc_media_parse_with_options( libvlc_media_t *media,
789 libvlc_media_parse_flag_t parse_flag )
791 return media_parse( media, true, parse_flag ) == VLC_SUCCESS ? 0 : -1;
794 /**************************************************************************
795 * Get parsed status for media object.
796 **************************************************************************/
798 libvlc_media_is_parsed(libvlc_media_t *media)
800 bool parsed;
802 vlc_mutex_lock(&media->parsed_lock);
803 parsed = media->is_parsed;
804 vlc_mutex_unlock(&media->parsed_lock);
805 return parsed;
808 /**************************************************************************
809 * Sets media descriptor's user_data. user_data is specialized data
810 * accessed by the host application, VLC.framework uses it as a pointer to
811 * an native object that references a libvlc_media_t pointer
812 **************************************************************************/
813 void
814 libvlc_media_set_user_data( libvlc_media_t * p_md, void * p_new_user_data )
816 assert( p_md );
817 p_md->p_user_data = p_new_user_data;
820 /**************************************************************************
821 * Get media descriptor's user_data. user_data is specialized data
822 * accessed by the host application, VLC.framework uses it as a pointer to
823 * an native object that references a libvlc_media_t pointer
824 **************************************************************************/
825 void *
826 libvlc_media_get_user_data( libvlc_media_t * p_md )
828 assert( p_md );
829 return p_md->p_user_data;
832 /**************************************************************************
833 * Get media descriptor's elementary streams description
834 **************************************************************************/
836 libvlc_media_get_tracks_info( libvlc_media_t *p_md, libvlc_media_track_info_t ** pp_es )
838 assert( p_md );
840 input_item_t *p_input_item = p_md->p_input_item;
841 vlc_mutex_lock( &p_input_item->lock );
843 const int i_es = p_input_item->i_es;
844 *pp_es = (i_es > 0) ? malloc( i_es * sizeof(libvlc_media_track_info_t) ) : NULL;
846 if( !*pp_es ) /* no ES, or OOM */
848 vlc_mutex_unlock( &p_input_item->lock );
849 return 0;
852 /* Fill array */
853 for( int i = 0; i < i_es; i++ )
855 libvlc_media_track_info_t *p_mes = *pp_es+i;
856 const es_format_t *p_es = p_input_item->es[i];
858 p_mes->i_codec = p_es->i_codec;
859 p_mes->i_id = p_es->i_id;
861 p_mes->i_profile = p_es->i_profile;
862 p_mes->i_level = p_es->i_level;
864 switch(p_es->i_cat)
866 case UNKNOWN_ES:
867 default:
868 p_mes->i_type = libvlc_track_unknown;
869 break;
870 case VIDEO_ES:
871 p_mes->i_type = libvlc_track_video;
872 p_mes->u.video.i_height = p_es->video.i_height;
873 p_mes->u.video.i_width = p_es->video.i_width;
874 break;
875 case AUDIO_ES:
876 p_mes->i_type = libvlc_track_audio;
877 p_mes->u.audio.i_channels = p_es->audio.i_channels;
878 p_mes->u.audio.i_rate = p_es->audio.i_rate;
879 break;
880 case SPU_ES:
881 p_mes->i_type = libvlc_track_text;
882 break;
886 vlc_mutex_unlock( &p_input_item->lock );
887 return i_es;
890 unsigned
891 libvlc_media_tracks_get( libvlc_media_t *p_md, libvlc_media_track_t *** pp_es )
893 assert( p_md );
895 input_item_t *p_input_item = p_md->p_input_item;
896 vlc_mutex_lock( &p_input_item->lock );
898 const int i_es = p_input_item->i_es;
899 *pp_es = (i_es > 0) ? calloc( i_es, sizeof(**pp_es) ) : NULL;
901 if( !*pp_es ) /* no ES, or OOM */
903 vlc_mutex_unlock( &p_input_item->lock );
904 return 0;
907 /* Fill array */
908 for( int i = 0; i < i_es; i++ )
910 libvlc_media_track_t *p_mes = calloc( 1, sizeof(*p_mes) );
911 if ( p_mes )
913 p_mes->audio = malloc( __MAX(__MAX(sizeof(*p_mes->audio),
914 sizeof(*p_mes->video)),
915 sizeof(*p_mes->subtitle)) );
917 if ( !p_mes || !p_mes->audio )
919 libvlc_media_tracks_release( *pp_es, i_es );
920 *pp_es = NULL;
921 free( p_mes );
922 vlc_mutex_unlock( &p_input_item->lock );
923 return 0;
925 (*pp_es)[i] = p_mes;
927 const es_format_t *p_es = p_input_item->es[i];
929 p_mes->i_codec = p_es->i_codec;
930 p_mes->i_original_fourcc = p_es->i_original_fourcc;
931 p_mes->i_id = p_es->i_id;
933 p_mes->i_profile = p_es->i_profile;
934 p_mes->i_level = p_es->i_level;
936 p_mes->i_bitrate = p_es->i_bitrate;
937 p_mes->psz_language = p_es->psz_language != NULL ? strdup(p_es->psz_language) : NULL;
938 p_mes->psz_description = p_es->psz_description != NULL ? strdup(p_es->psz_description) : NULL;
940 switch(p_es->i_cat)
942 case UNKNOWN_ES:
943 default:
944 p_mes->i_type = libvlc_track_unknown;
945 break;
946 case VIDEO_ES:
947 p_mes->i_type = libvlc_track_video;
948 p_mes->video->i_height = p_es->video.i_height;
949 p_mes->video->i_width = p_es->video.i_width;
950 p_mes->video->i_sar_num = p_es->video.i_sar_num;
951 p_mes->video->i_sar_den = p_es->video.i_sar_den;
952 p_mes->video->i_frame_rate_num = p_es->video.i_frame_rate;
953 p_mes->video->i_frame_rate_den = p_es->video.i_frame_rate_base;
954 break;
955 case AUDIO_ES:
956 p_mes->i_type = libvlc_track_audio;
957 p_mes->audio->i_channels = p_es->audio.i_channels;
958 p_mes->audio->i_rate = p_es->audio.i_rate;
959 break;
960 case SPU_ES:
961 p_mes->i_type = libvlc_track_text;
962 p_mes->subtitle->psz_encoding = p_es->subs.psz_encoding != NULL ?
963 strdup(p_es->subs.psz_encoding) : NULL;
964 break;
968 vlc_mutex_unlock( &p_input_item->lock );
969 return i_es;
972 /**************************************************************************
973 * Get codec description from media elementary stream
974 **************************************************************************/
975 const char *
976 libvlc_media_get_codec_description( libvlc_track_type_t i_type,
977 uint32_t i_codec )
979 switch( i_type )
981 case libvlc_track_audio:
982 return vlc_fourcc_GetDescription( AUDIO_ES, i_codec );
983 case libvlc_track_video:
984 return vlc_fourcc_GetDescription( VIDEO_ES, i_codec );
985 case libvlc_track_text:
986 return vlc_fourcc_GetDescription( SPU_ES, i_codec );
987 case libvlc_track_unknown:
988 default:
989 return vlc_fourcc_GetDescription( UNKNOWN_ES, i_codec );
993 /**************************************************************************
994 * Release media descriptor's elementary streams description array
995 **************************************************************************/
996 void libvlc_media_tracks_release( libvlc_media_track_t **p_tracks, unsigned i_count )
998 for( unsigned i = 0; i < i_count; ++i )
1000 if ( !p_tracks[i] )
1001 continue;
1002 free( p_tracks[i]->psz_language );
1003 free( p_tracks[i]->psz_description );
1004 switch( p_tracks[i]->i_type )
1006 case libvlc_track_audio:
1007 break;
1008 case libvlc_track_video:
1009 break;
1010 case libvlc_track_text:
1011 free( p_tracks[i]->subtitle->psz_encoding );
1012 break;
1013 case libvlc_track_unknown:
1014 default:
1015 break;
1017 free( p_tracks[i]->audio );
1018 free( p_tracks[i] );
1020 free( p_tracks );
1023 /**************************************************************************
1024 * Get the media type of the media descriptor object
1025 **************************************************************************/
1026 libvlc_media_type_t libvlc_media_get_type( libvlc_media_t *p_md )
1028 assert( p_md );
1030 int i_type;
1031 input_item_t *p_input_item = p_md->p_input_item;
1033 vlc_mutex_lock( &p_input_item->lock );
1034 i_type = p_md->p_input_item->i_type;
1035 vlc_mutex_unlock( &p_input_item->lock );
1037 switch( i_type )
1039 case ITEM_TYPE_FILE:
1040 return libvlc_media_type_file;
1041 case ITEM_TYPE_NODE:
1042 case ITEM_TYPE_DIRECTORY:
1043 return libvlc_media_type_directory;
1044 case ITEM_TYPE_DISC:
1045 return libvlc_media_type_disc;
1046 case ITEM_TYPE_STREAM:
1047 return libvlc_media_type_stream;
1048 case ITEM_TYPE_PLAYLIST:
1049 return libvlc_media_type_playlist;
1050 default:
1051 return libvlc_media_type_unknown;