media.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:21k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * media.c: Libvlc API media descripor management
  3.  *****************************************************************************
  4.  * Copyright (C) 2007 the VideoLAN team
  5.  * $Id: d1a45d4d60591f3c108812d9b0ee708604f5f87f $
  6.  *
  7.  * Authors: Pierre d'Herbemont <pdherbemont@videolan.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  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 General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. # include <config.h>
  25. #endif
  26. #include <vlc/libvlc.h>
  27. #include <vlc/libvlc_media.h>
  28. #include <vlc/libvlc_media_list.h> // For the subitems, here for convenience
  29. #include <vlc/libvlc_events.h>
  30. #include <vlc_common.h>
  31. #include <vlc_input.h>
  32. #include <vlc_meta.h>
  33. #include <vlc_playlist.h> /* For the preparser */
  34. #include "libvlc.h"
  35. #include "libvlc_internal.h"
  36. #include "media_internal.h"
  37. static const vlc_meta_type_t libvlc_to_vlc_meta[] =
  38. {
  39.     [libvlc_meta_Title]        = vlc_meta_Title,
  40.     [libvlc_meta_Artist]       = vlc_meta_Artist,
  41.     [libvlc_meta_Genre]        = vlc_meta_Genre,
  42.     [libvlc_meta_Copyright]    = vlc_meta_Copyright,
  43.     [libvlc_meta_Album]        = vlc_meta_Album,
  44.     [libvlc_meta_TrackNumber]  = vlc_meta_TrackNumber,
  45.     [libvlc_meta_Description]  = vlc_meta_Description,
  46.     [libvlc_meta_Rating]       = vlc_meta_Rating,
  47.     [libvlc_meta_Date]         = vlc_meta_Date,
  48.     [libvlc_meta_Setting]      = vlc_meta_Setting,
  49.     [libvlc_meta_URL]          = vlc_meta_URL,
  50.     [libvlc_meta_Language]     = vlc_meta_Language,
  51.     [libvlc_meta_NowPlaying]   = vlc_meta_NowPlaying,
  52.     [libvlc_meta_Publisher]    = vlc_meta_Publisher,
  53.     [libvlc_meta_EncodedBy]    = vlc_meta_EncodedBy,
  54.     [libvlc_meta_ArtworkURL]   = vlc_meta_ArtworkURL,
  55.     [libvlc_meta_TrackID]      = vlc_meta_TrackID
  56. };
  57. static const libvlc_meta_t vlc_to_libvlc_meta[] =
  58. {
  59.     [vlc_meta_Title]        = libvlc_meta_Title,
  60.     [vlc_meta_Artist]       = libvlc_meta_Artist,
  61.     [vlc_meta_Genre]        = libvlc_meta_Genre,
  62.     [vlc_meta_Copyright]    = libvlc_meta_Copyright,
  63.     [vlc_meta_Album]        = libvlc_meta_Album,
  64.     [vlc_meta_TrackNumber]  = libvlc_meta_TrackNumber,
  65.     [vlc_meta_Description]  = libvlc_meta_Description,
  66.     [vlc_meta_Rating]       = libvlc_meta_Rating,
  67.     [vlc_meta_Date]         = libvlc_meta_Date,
  68.     [vlc_meta_Setting]      = libvlc_meta_Setting,
  69.     [vlc_meta_URL]          = libvlc_meta_URL,
  70.     [vlc_meta_Language]     = libvlc_meta_Language,
  71.     [vlc_meta_NowPlaying]   = libvlc_meta_NowPlaying,
  72.     [vlc_meta_Publisher]    = libvlc_meta_Publisher,
  73.     [vlc_meta_EncodedBy]    = libvlc_meta_EncodedBy,
  74.     [vlc_meta_ArtworkURL]   = libvlc_meta_ArtworkURL,
  75.     [vlc_meta_TrackID]      = libvlc_meta_TrackID
  76. };
  77. /**************************************************************************
  78.  * input_item_subitem_added (Private) (vlc event Callback)
  79.  **************************************************************************/
  80. static void input_item_subitem_added( const vlc_event_t *p_event,
  81.                                        void * user_data )
  82. {
  83.     libvlc_media_t * p_md = user_data;
  84.     libvlc_media_t * p_md_child;
  85.     libvlc_event_t event;
  86.     p_md_child = libvlc_media_new_from_input_item(
  87.                 p_md->p_libvlc_instance,
  88.                 p_event->u.input_item_subitem_added.p_new_child, NULL );
  89.     /* Add this to our media list */
  90.     if( !p_md->p_subitems )
  91.     {
  92.         p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance, NULL );
  93.         libvlc_media_list_set_media( p_md->p_subitems, p_md, NULL );
  94.     }
  95.     if( p_md->p_subitems )
  96.     {
  97.         libvlc_media_list_add_media( p_md->p_subitems, p_md_child, NULL );
  98.     }
  99.     /* Construct the event */
  100.     event.type = libvlc_MediaSubItemAdded;
  101.     event.u.media_subitem_added.new_child = p_md_child;
  102.     /* Send the event */
  103.     libvlc_event_send( p_md->p_event_manager, &event );
  104.     libvlc_media_release( p_md_child );
  105. }
  106. /**************************************************************************
  107.  * input_item_meta_changed (Private) (vlc event Callback)
  108.  **************************************************************************/
  109. static void input_item_meta_changed( const vlc_event_t *p_event,
  110.                                      void * user_data )
  111. {
  112.     libvlc_media_t * p_md = user_data;
  113.     libvlc_event_t event;
  114.     /* Construct the event */
  115.     event.type = libvlc_MediaMetaChanged;
  116.     event.u.media_meta_changed.meta_type =
  117.         vlc_to_libvlc_meta[p_event->u.input_item_meta_changed.meta_type];
  118.     /* Send the event */
  119.     libvlc_event_send( p_md->p_event_manager, &event );
  120. }
  121. /**************************************************************************
  122.  * input_item_duration_changed (Private) (vlc event Callback)
  123.  **************************************************************************/
  124. static void input_item_duration_changed( const vlc_event_t *p_event,
  125.                                          void * user_data )
  126. {
  127.     libvlc_media_t * p_md = user_data;
  128.     libvlc_event_t event;
  129.     /* Construct the event */
  130.     event.type = libvlc_MediaDurationChanged;
  131.     event.u.media_duration_changed.new_duration = 
  132.         p_event->u.input_item_duration_changed.new_duration;
  133.     /* Send the event */
  134.     libvlc_event_send( p_md->p_event_manager, &event );
  135. }
  136. /**************************************************************************
  137.  * input_item_preparsed_changed (Private) (vlc event Callback)
  138.  **************************************************************************/
  139. static void input_item_preparsed_changed( const vlc_event_t *p_event,
  140.                                           void * user_data )
  141. {
  142.     libvlc_media_t * p_md = user_data;
  143.     libvlc_event_t event;
  144.     /* Construct the event */
  145.     event.type = libvlc_MediaPreparsedChanged;
  146.     event.u.media_preparsed_changed.new_status = 
  147.         p_event->u.input_item_preparsed_changed.new_status;
  148.     /* Send the event */
  149.     libvlc_event_send( p_md->p_event_manager, &event );
  150. }
  151. /**************************************************************************
  152.  * Install event handler (Private)
  153.  **************************************************************************/
  154. static void install_input_item_observer( libvlc_media_t *p_md )
  155. {
  156.     vlc_event_attach( &p_md->p_input_item->event_manager,
  157.                       vlc_InputItemSubItemAdded,
  158.                       input_item_subitem_added,
  159.                       p_md );
  160.     vlc_event_attach( &p_md->p_input_item->event_manager,
  161.                       vlc_InputItemMetaChanged,
  162.                       input_item_meta_changed,
  163.                       p_md );
  164.     vlc_event_attach( &p_md->p_input_item->event_manager,
  165.                       vlc_InputItemDurationChanged,
  166.                       input_item_duration_changed,
  167.                       p_md );
  168.     vlc_event_attach( &p_md->p_input_item->event_manager,
  169.                       vlc_InputItemPreparsedChanged,
  170.                       input_item_preparsed_changed,
  171.                       p_md );
  172. }
  173. /**************************************************************************
  174.  * Uninstall event handler (Private)
  175.  **************************************************************************/
  176. static void uninstall_input_item_observer( libvlc_media_t *p_md )
  177. {
  178.     vlc_event_detach( &p_md->p_input_item->event_manager,
  179.                       vlc_InputItemSubItemAdded,
  180.                       input_item_subitem_added,
  181.                       p_md );
  182.     vlc_event_detach( &p_md->p_input_item->event_manager,
  183.                       vlc_InputItemMetaChanged,
  184.                       input_item_meta_changed,
  185.                       p_md );
  186.     vlc_event_detach( &p_md->p_input_item->event_manager,
  187.                       vlc_InputItemDurationChanged,
  188.                       input_item_duration_changed,
  189.                       p_md );
  190.     vlc_event_detach( &p_md->p_input_item->event_manager,
  191.                       vlc_InputItemPreparsedChanged,
  192.                       input_item_preparsed_changed,
  193.                       p_md );
  194. }
  195. /**************************************************************************
  196.  * Preparse if not already done (Private)
  197.  **************************************************************************/
  198. static void preparse_if_needed( libvlc_media_t *p_md )
  199. {
  200.     /* XXX: need some locking here */
  201.     if (!p_md->b_preparsed)
  202.     {
  203.         playlist_PreparseEnqueue(
  204.                 libvlc_priv (p_md->p_libvlc_instance->p_libvlc_int)->p_playlist,
  205.                 p_md->p_input_item, pl_Unlocked );
  206.         p_md->b_preparsed = true;
  207.     }
  208. }
  209. /**************************************************************************
  210.  * Create a new media descriptor object from an input_item
  211.  * (libvlc internal)
  212.  * That's the generic constructor
  213.  **************************************************************************/
  214. libvlc_media_t * libvlc_media_new_from_input_item(
  215.                                    libvlc_instance_t *p_instance,
  216.                                    input_item_t *p_input_item,
  217.                                    libvlc_exception_t *p_e )
  218. {
  219.     libvlc_media_t * p_md;
  220.     if (!p_input_item)
  221.     {
  222.         libvlc_exception_raise( p_e, "No input item given" );
  223.         return NULL;
  224.     }
  225.     p_md = malloc( sizeof(libvlc_media_t) );
  226.     if( !p_md )
  227.     {
  228.         libvlc_exception_raise( p_e, "Not enough memory" );
  229.         return NULL;
  230.     }
  231.     p_md->p_libvlc_instance = p_instance;
  232.     p_md->p_input_item      = p_input_item;
  233.     p_md->b_preparsed       = false;
  234.     p_md->i_refcount        = 1;
  235.     p_md->p_user_data       = NULL;
  236.     p_md->state = libvlc_NothingSpecial;
  237.     /* A media descriptor can be a playlist. When you open a playlist
  238.      * It can give a bunch of item to read. */
  239.     p_md->p_subitems        = NULL;
  240.     p_md->p_event_manager = libvlc_event_manager_new( p_md, p_instance, p_e );
  241.     libvlc_event_manager_register_event_type( p_md->p_event_manager,
  242.         libvlc_MediaMetaChanged, p_e );
  243.     libvlc_event_manager_register_event_type( p_md->p_event_manager,
  244.         libvlc_MediaSubItemAdded, p_e );
  245.     libvlc_event_manager_register_event_type( p_md->p_event_manager,
  246.         libvlc_MediaFreed, p_e );
  247.     libvlc_event_manager_register_event_type( p_md->p_event_manager,
  248.         libvlc_MediaDurationChanged, p_e );
  249.     libvlc_event_manager_register_event_type( p_md->p_event_manager,
  250.         libvlc_MediaStateChanged, p_e );
  251.     vlc_gc_incref( p_md->p_input_item );
  252.     install_input_item_observer( p_md );
  253.     return p_md;
  254. }
  255. /**************************************************************************
  256.  * Create a new media descriptor object
  257.  **************************************************************************/
  258. libvlc_media_t * libvlc_media_new(
  259.                                    libvlc_instance_t *p_instance,
  260.                                    const char * psz_mrl,
  261.                                    libvlc_exception_t *p_e )
  262. {
  263.     input_item_t * p_input_item;
  264.     libvlc_media_t * p_md;
  265.     p_input_item = input_item_New( p_instance->p_libvlc_int, psz_mrl, NULL );
  266.     if (!p_input_item)
  267.     {
  268.         libvlc_exception_raise( p_e, "Can't create md's input_item" );
  269.         return NULL;
  270.     }
  271.     p_md = libvlc_media_new_from_input_item( p_instance,
  272.                 p_input_item, p_e );
  273.     /* The p_input_item is retained in libvlc_media_new_from_input_item */
  274.     vlc_gc_decref( p_input_item );
  275.     return p_md;
  276. }
  277. /**************************************************************************
  278.  * Create a new media descriptor object
  279.  **************************************************************************/
  280. libvlc_media_t * libvlc_media_new_as_node(
  281.                                    libvlc_instance_t *p_instance,
  282.                                    const char * psz_name,
  283.                                    libvlc_exception_t *p_e )
  284. {
  285.     input_item_t * p_input_item;
  286.     libvlc_media_t * p_md;
  287.     p_input_item = input_item_New( p_instance->p_libvlc_int, "vlc://nop", psz_name );
  288.     if (!p_input_item)
  289.     {
  290.         libvlc_exception_raise( p_e, "Can't create md's input_item" );
  291.         return NULL;
  292.     }
  293.     p_md = libvlc_media_new_from_input_item( p_instance,
  294.                 p_input_item, p_e );
  295.     p_md->p_subitems = libvlc_media_list_new( p_md->p_libvlc_instance, NULL );
  296.     return p_md;
  297. }
  298. /**************************************************************************
  299.  * Add an option to the media descriptor,
  300.  * that will be used to determine how the media_player will read the
  301.  * media. This allow to use VLC advanced reading/streaming
  302.  * options in a per-media basis
  303.  *
  304.  * The options are detailled in vlc --long-help, for instance "--sout-all"
  305.  **************************************************************************/
  306. void libvlc_media_add_option(
  307.                                    libvlc_media_t * p_md,
  308.                                    const char * ppsz_option,
  309.                                    libvlc_exception_t *p_e )
  310. {
  311.     VLC_UNUSED(p_e);
  312.     input_item_AddOption( p_md->p_input_item, ppsz_option,
  313.                           VLC_INPUT_OPTION_UNIQUE|VLC_INPUT_OPTION_TRUSTED );
  314. }
  315. /**************************************************************************
  316.  * Same as libvlc_media_add_option but with untrusted source.
  317.  **************************************************************************/
  318. void libvlc_media_add_option_untrusted(
  319.                                    libvlc_media_t * p_md,
  320.                                    const char * ppsz_option,
  321.                                    libvlc_exception_t *p_e )
  322. {
  323.     VLC_UNUSED(p_e);
  324.     input_item_AddOption( p_md->p_input_item, ppsz_option,
  325.                           VLC_INPUT_OPTION_UNIQUE );
  326. }
  327. /**************************************************************************
  328.  * Delete a media descriptor object
  329.  **************************************************************************/
  330. void libvlc_media_release( libvlc_media_t *p_md )
  331. {
  332.     if (!p_md)
  333.         return;
  334.     p_md->i_refcount--;
  335.     if( p_md->i_refcount > 0 )
  336.         return;
  337.     if( p_md->p_subitems )
  338.         libvlc_media_list_release( p_md->p_subitems );
  339.     uninstall_input_item_observer( p_md );
  340.     vlc_gc_decref( p_md->p_input_item );
  341.     /* Construct the event */
  342.     libvlc_event_t event;
  343.     event.type = libvlc_MediaFreed;
  344.     event.u.media_freed.md = p_md;
  345.     /* Send the event */
  346.     libvlc_event_send( p_md->p_event_manager, &event );
  347.     libvlc_event_manager_release( p_md->p_event_manager );
  348.     free( p_md );
  349. }
  350. /**************************************************************************
  351.  * Retain a media descriptor object
  352.  **************************************************************************/
  353. void libvlc_media_retain( libvlc_media_t *p_md )
  354. {
  355.     if (!p_md)
  356.         return;
  357.     p_md->i_refcount++;
  358. }
  359. /**************************************************************************
  360.  * Duplicate a media descriptor object
  361.  **************************************************************************/
  362. libvlc_media_t *
  363. libvlc_media_duplicate( libvlc_media_t *p_md_orig )
  364. {
  365.     return libvlc_media_new_from_input_item(
  366.         p_md_orig->p_libvlc_instance, p_md_orig->p_input_item, NULL );
  367. }
  368. /**************************************************************************
  369.  * Get mrl from a media descriptor object
  370.  **************************************************************************/
  371. char *
  372. libvlc_media_get_mrl( libvlc_media_t * p_md,
  373.                                  libvlc_exception_t * p_e )
  374. {
  375.     VLC_UNUSED(p_e);
  376.     return input_item_GetURI( p_md->p_input_item );
  377. }
  378. /**************************************************************************
  379.  * Getter for meta information
  380.  **************************************************************************/
  381. char * libvlc_media_get_meta( libvlc_media_t *p_md,
  382.                                          libvlc_meta_t e_meta,
  383.                                          libvlc_exception_t *p_e )
  384. {
  385.     char * psz_meta;
  386.     VLC_UNUSED(p_e);
  387.     /* XXX: locking */
  388.     preparse_if_needed( p_md );
  389.     psz_meta = input_item_GetMeta( p_md->p_input_item,
  390.                                    libvlc_to_vlc_meta[e_meta] );
  391.     if( e_meta == libvlc_meta_ArtworkURL && !psz_meta )
  392.     {
  393.         playlist_AskForArtEnqueue(
  394.                 libvlc_priv(p_md->p_libvlc_instance->p_libvlc_int)->p_playlist,
  395.                 p_md->p_input_item, pl_Unlocked );
  396.     }
  397.     /* Should be integrated in core */
  398.     if( !psz_meta && e_meta == libvlc_meta_Title && p_md->p_input_item->psz_name )
  399.     {
  400.         free( psz_meta );
  401.         return strdup( p_md->p_input_item->psz_name );
  402.     }
  403.     return psz_meta;
  404. }
  405. /**************************************************************************
  406.  * Getter for state information
  407.  * Can be error, playing, buffering, NothingSpecial.
  408.  **************************************************************************/
  409. libvlc_state_t
  410. libvlc_media_get_state( libvlc_media_t *p_md,
  411.                                    libvlc_exception_t *p_e )
  412. {
  413.     VLC_UNUSED(p_e);
  414.     return p_md->state;
  415. }
  416. /**************************************************************************
  417.  * Setter for state information (LibVLC Internal)
  418.  **************************************************************************/
  419. void
  420. libvlc_media_set_state( libvlc_media_t *p_md,
  421.                                    libvlc_state_t state,
  422.                                    libvlc_exception_t *p_e )
  423. {
  424.     libvlc_event_t event;
  425.     VLC_UNUSED(p_e);
  426.     p_md->state = state;
  427.     /* Construct the event */
  428.     event.type = libvlc_MediaStateChanged;
  429.     event.u.media_state_changed.new_state = state;
  430.     /* Send the event */
  431.     libvlc_event_send( p_md->p_event_manager, &event );
  432. }
  433. /**************************************************************************
  434.  * subitems
  435.  **************************************************************************/
  436. libvlc_media_list_t *
  437. libvlc_media_subitems( libvlc_media_t * p_md,
  438.                                   libvlc_exception_t * p_e )
  439. {
  440.     VLC_UNUSED(p_e);
  441.     if( p_md->p_subitems )
  442.         libvlc_media_list_retain( p_md->p_subitems );
  443.     return p_md->p_subitems;
  444. }
  445. /**************************************************************************
  446.  * event_manager
  447.  **************************************************************************/
  448. libvlc_event_manager_t *
  449. libvlc_media_event_manager( libvlc_media_t * p_md,
  450.                                        libvlc_exception_t * p_e )
  451. {
  452.     VLC_UNUSED(p_e);
  453.     return p_md->p_event_manager;
  454. }
  455. /**************************************************************************
  456.  * Get duration of media object.
  457.  **************************************************************************/
  458. int64_t
  459. libvlc_media_get_duration( libvlc_media_t * p_md,
  460.                                       libvlc_exception_t * p_e )
  461. {
  462.     VLC_UNUSED(p_e);
  463.     if( !p_md || !p_md->p_input_item)
  464.     {
  465.         libvlc_exception_raise( p_e, "No input item" );
  466.         return -1;
  467.     }
  468.     return input_item_GetDuration( p_md->p_input_item );
  469. }
  470. /**************************************************************************
  471.  * Get preparsed status for media object.
  472.  **************************************************************************/
  473. int
  474. libvlc_media_is_preparsed( libvlc_media_t * p_md,
  475.                                        libvlc_exception_t * p_e )
  476. {
  477.     VLC_UNUSED(p_e);
  478.     if( !p_md || !p_md->p_input_item)
  479.     {
  480.         libvlc_exception_raise( p_e, "No input item" );
  481.         return false;
  482.     }
  483.     return input_item_IsPreparsed( p_md->p_input_item );
  484. }
  485. /**************************************************************************
  486.  * Sets media descriptor's user_data. user_data is specialized data 
  487.  * accessed by the host application, VLC.framework uses it as a pointer to 
  488.  * an native object that references a libvlc_media_t pointer
  489.  **************************************************************************/
  490. void 
  491. libvlc_media_set_user_data( libvlc_media_t * p_md,
  492.                                        void * p_new_user_data,
  493.                                        libvlc_exception_t * p_e )
  494. {
  495.     VLC_UNUSED(p_e);
  496.     if( p_md )
  497.     {
  498.         p_md->p_user_data = p_new_user_data;
  499.     }
  500. }
  501. /**************************************************************************
  502.  * Get media descriptor's user_data. user_data is specialized data 
  503.  * accessed by the host application, VLC.framework uses it as a pointer to 
  504.  * an native object that references a libvlc_media_t pointer
  505.  **************************************************************************/
  506. void *
  507. libvlc_media_get_user_data( libvlc_media_t * p_md,
  508.                                        libvlc_exception_t * p_e )
  509. {
  510.     VLC_UNUSED(p_e);
  511.     if( p_md )
  512.     {
  513.         return p_md->p_user_data;
  514.     }
  515.     else
  516.     {
  517.         return NULL;
  518.     }
  519. }