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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * media_list.c: libvlc new API media list functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2007 the VideoLAN team
  5.  * $Id: 6b9bbb900d765db8a633de1a594940897b4e7da3 $
  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. #include <assert.h>
  24. #include <vlc/libvlc.h>
  25. #include <vlc/libvlc_media.h>
  26. #include <vlc/libvlc_media_list.h>
  27. #include <vlc/libvlc_events.h>
  28. #include <vlc_common.h>
  29. #include <vlc_input.h>
  30. #include "libvlc_internal.h"
  31. #include "media_internal.h" // libvlc_media_new_from_input_item()
  32. #include "media_list_internal.h"
  33. typedef enum EventPlaceInTime {
  34.     EventWillHappen,
  35.     EventDidHappen
  36. } EventPlaceInTime;
  37. //#define DEBUG_MEDIA_LIST
  38. #ifdef DEBUG_MEDIA_LIST
  39. # define trace( fmt, ... ) printf( "%s(): " fmt, __FUNCTION__, ##__VA_ARGS__ )
  40. #else
  41. # define trace( ... )
  42. #endif
  43. /*
  44.  * Private functions
  45.  */
  46. /**************************************************************************
  47.  *       notify_item_addition (private)
  48.  *
  49.  * Do the appropriate action when an item is deleted.
  50.  **************************************************************************/
  51. static void
  52. notify_item_addition( libvlc_media_list_t * p_mlist,
  53.                       libvlc_media_t * p_md,
  54.                       int index,
  55.                       EventPlaceInTime event_status )
  56. {
  57.     libvlc_event_t event;
  58.     /* Construct the event */
  59.     if( event_status == EventDidHappen )
  60.     {
  61.         trace("item was added at index %dn", index);
  62.         event.type = libvlc_MediaListItemAdded;
  63.         event.u.media_list_item_added.item = p_md;
  64.         event.u.media_list_item_added.index = index;
  65.     }
  66.     else /* if( event_status == EventWillHappen ) */
  67.     {
  68.         event.type = libvlc_MediaListWillAddItem;
  69.         event.u.media_list_will_add_item.item = p_md;
  70.         event.u.media_list_will_add_item.index = index;
  71.     }
  72.     /* Send the event */
  73.     libvlc_event_send( p_mlist->p_event_manager, &event );
  74. }
  75. /**************************************************************************
  76.  *       notify_item_deletion (private)
  77.  *
  78.  * Do the appropriate action when an item is added.
  79.  **************************************************************************/
  80. static void
  81. notify_item_deletion( libvlc_media_list_t * p_mlist,
  82.                       libvlc_media_t * p_md,
  83.                       int index,
  84.                       EventPlaceInTime event_status )
  85. {
  86.     libvlc_event_t event;
  87.     /* Construct the event */
  88.     if( event_status == EventDidHappen )
  89.     {
  90.         trace("item at index %d was deletedn", index);
  91.         event.type = libvlc_MediaListItemDeleted;
  92.         event.u.media_list_item_deleted.item = p_md;
  93.         event.u.media_list_item_deleted.index = index;
  94.     }
  95.     else /* if( event_status == EventWillHappen ) */
  96.     {
  97.         event.type = libvlc_MediaListWillDeleteItem;
  98.         event.u.media_list_will_delete_item.item = p_md;
  99.         event.u.media_list_will_delete_item.index = index;
  100.     }
  101.     /* Send the event */
  102.     libvlc_event_send( p_mlist->p_event_manager, &event );
  103. }
  104. /**************************************************************************
  105.  *       static mlist_is_writable (private)
  106.  *
  107.  * Raise exception and return 0 when the media_list instance is read-only,
  108.  * or else return 1.
  109.  **************************************************************************/
  110. static inline
  111. int mlist_is_writable( libvlc_media_list_t *p_mlist, libvlc_exception_t *p_e )
  112. {
  113.     if( !p_mlist||p_mlist->b_read_only )
  114.     {
  115.         /* We are read-only from user side */
  116.         libvlc_exception_raise( p_e, "Cannot write to read-only media list." );
  117.         return 0;
  118.     }
  119.     return 1;
  120. }
  121. /*
  122.  * Public libvlc functions
  123.  */
  124. /**************************************************************************
  125.  *       libvlc_media_list_new (Public)
  126.  *
  127.  * Init an object.
  128.  **************************************************************************/
  129. libvlc_media_list_t *
  130. libvlc_media_list_new( libvlc_instance_t * p_inst,
  131.                        libvlc_exception_t * p_e )
  132. {
  133.     libvlc_media_list_t * p_mlist;
  134.     p_mlist = malloc(sizeof(libvlc_media_list_t));
  135.     if( !p_mlist )
  136.         return NULL;
  137.     p_mlist->p_libvlc_instance = p_inst;
  138.     p_mlist->p_event_manager = libvlc_event_manager_new( p_mlist, p_inst, p_e );
  139.     /* Code for that one should be handled in flat_media_list.c */
  140.     p_mlist->p_flat_mlist = NULL;
  141.     p_mlist->b_read_only = false;
  142.     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
  143.             libvlc_MediaListItemAdded, p_e );
  144.     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
  145.             libvlc_MediaListWillAddItem, p_e );
  146.     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
  147.             libvlc_MediaListItemDeleted, p_e );
  148.     libvlc_event_manager_register_event_type( p_mlist->p_event_manager,
  149.             libvlc_MediaListWillDeleteItem, p_e );
  150.     if( libvlc_exception_raised( p_e ) )
  151.     {
  152.         libvlc_event_manager_release( p_mlist->p_event_manager );
  153.         free( p_mlist );
  154.         return NULL;
  155.     }
  156.     vlc_mutex_init( &p_mlist->object_lock );
  157.     vlc_mutex_init( &p_mlist->refcount_lock ); // FIXME: spinlock?
  158.     vlc_array_init( &p_mlist->items );
  159.     p_mlist->i_refcount = 1;
  160.     p_mlist->p_md = NULL;
  161.     return p_mlist;
  162. }
  163. /**************************************************************************
  164.  *       libvlc_media_list_release (Public)
  165.  *
  166.  * Release an object.
  167.  **************************************************************************/
  168. void libvlc_media_list_release( libvlc_media_list_t * p_mlist )
  169. {
  170.     libvlc_media_t * p_md;
  171.     int i;
  172.     vlc_mutex_lock( &p_mlist->refcount_lock );
  173.     p_mlist->i_refcount--;
  174.     if( p_mlist->i_refcount > 0 )
  175.     {
  176.         vlc_mutex_unlock( &p_mlist->refcount_lock );
  177.         return;
  178.     }
  179.     vlc_mutex_unlock( &p_mlist->refcount_lock );
  180.     /* Refcount null, time to free */
  181.     libvlc_event_manager_release( p_mlist->p_event_manager );
  182.     if( p_mlist->p_md )
  183.         libvlc_media_release( p_mlist->p_md );
  184.     for ( i = 0; i < vlc_array_count( &p_mlist->items ); i++ )
  185.     {
  186.         p_md = vlc_array_item_at_index( &p_mlist->items, i );
  187.         libvlc_media_release( p_md );
  188.     }
  189.     vlc_mutex_destroy( &p_mlist->object_lock );
  190.     vlc_array_clear( &p_mlist->items );
  191.     free( p_mlist );
  192. }
  193. /**************************************************************************
  194.  *       libvlc_media_list_retain (Public)
  195.  *
  196.  * Increase an object refcount.
  197.  **************************************************************************/
  198. void libvlc_media_list_retain( libvlc_media_list_t * p_mlist )
  199. {
  200.     vlc_mutex_lock( &p_mlist->refcount_lock );
  201.     p_mlist->i_refcount++;
  202.     vlc_mutex_unlock( &p_mlist->refcount_lock );
  203. }
  204. /**************************************************************************
  205.  *       add_file_content (Public)
  206.  **************************************************************************/
  207. void
  208. libvlc_media_list_add_file_content( libvlc_media_list_t * p_mlist,
  209.                                     const char * psz_uri,
  210.                                     libvlc_exception_t * p_e )
  211. {
  212.     input_item_t * p_input_item;
  213.     libvlc_media_t * p_md;
  214.     p_input_item = input_item_NewExt(
  215.                            p_mlist->p_libvlc_instance->p_libvlc_int, psz_uri,
  216.                                          _("Media Library"), 0, NULL, 0, -1 );
  217.     if( !p_input_item )
  218.     {
  219.         libvlc_exception_raise( p_e, "Can't create an input item" );
  220.         return;
  221.     }
  222.     p_md = libvlc_media_new_from_input_item(
  223.             p_mlist->p_libvlc_instance,
  224.             p_input_item, p_e );
  225.     if( !p_md )
  226.     {
  227.         vlc_gc_decref( p_input_item );
  228.         return;
  229.     }
  230.     libvlc_media_list_add_media( p_mlist, p_md, p_e );
  231.     if( libvlc_exception_raised( p_e ) )
  232.         return;
  233.     input_Read( p_mlist->p_libvlc_instance->p_libvlc_int, p_input_item, true );
  234.     return;
  235. }
  236. /**************************************************************************
  237.  *       set_media (Public)
  238.  **************************************************************************/
  239. void libvlc_media_list_set_media( libvlc_media_list_t * p_mlist,
  240.                                              libvlc_media_t * p_md,
  241.                                              libvlc_exception_t * p_e)
  242. {
  243.     VLC_UNUSED(p_e);
  244.     vlc_mutex_lock( &p_mlist->object_lock );
  245.     if( p_mlist->p_md )
  246.         libvlc_media_release( p_mlist->p_md );
  247.     libvlc_media_retain( p_md );
  248.     p_mlist->p_md = p_md;
  249.     vlc_mutex_unlock( &p_mlist->object_lock );
  250. }
  251. /**************************************************************************
  252.  *       media (Public)
  253.  *
  254.  * If this media_list comes is a media's subitems,
  255.  * This holds the corresponding media.
  256.  * This md is also seen as the information holder for the media_list.
  257.  * Indeed a media_list can have meta information through this
  258.  * media.
  259.  **************************************************************************/
  260. libvlc_media_t *
  261. libvlc_media_list_media( libvlc_media_list_t * p_mlist,
  262.                                     libvlc_exception_t * p_e)
  263. {
  264.     libvlc_media_t *p_md;
  265.     VLC_UNUSED(p_e);
  266.     vlc_mutex_lock( &p_mlist->object_lock );
  267.     p_md = p_mlist->p_md;
  268.     if( p_md )
  269.         libvlc_media_retain( p_md );
  270.     vlc_mutex_unlock( &p_mlist->object_lock );
  271.     return p_md;
  272. }
  273. /**************************************************************************
  274.  *       libvlc_media_list_count (Public)
  275.  *
  276.  * Lock should be hold when entering.
  277.  **************************************************************************/
  278. int libvlc_media_list_count( libvlc_media_list_t * p_mlist,
  279.                              libvlc_exception_t * p_e )
  280. {
  281.     VLC_UNUSED(p_e);
  282.     return vlc_array_count( &p_mlist->items );
  283. }
  284. /**************************************************************************
  285.  *       libvlc_media_list_add_media (Public)
  286.  *
  287.  * Lock should be held when entering.
  288.  **************************************************************************/
  289. void libvlc_media_list_add_media(
  290.                                    libvlc_media_list_t * p_mlist,
  291.                                    libvlc_media_t * p_md,
  292.                                    libvlc_exception_t * p_e )
  293. {
  294.     if( mlist_is_writable(p_mlist,p_e) )
  295.         _libvlc_media_list_add_media( p_mlist, p_md, p_e );
  296. }
  297. /* LibVLC internal version */
  298. void _libvlc_media_list_add_media(
  299.                                    libvlc_media_list_t * p_mlist,
  300.                                    libvlc_media_t * p_md,
  301.                                    libvlc_exception_t * p_e )
  302. {
  303.     VLC_UNUSED(p_e);
  304.     libvlc_media_retain( p_md );
  305.     notify_item_addition( p_mlist, p_md, vlc_array_count( &p_mlist->items ),
  306.                           EventWillHappen );
  307.     vlc_array_append( &p_mlist->items, p_md );
  308.     notify_item_addition( p_mlist, p_md, vlc_array_count( &p_mlist->items )-1,
  309.                           EventDidHappen );
  310. }
  311. /**************************************************************************
  312.  *       libvlc_media_list_insert_media (Public)
  313.  *
  314.  * Lock should be hold when entering.
  315.  **************************************************************************/
  316. void libvlc_media_list_insert_media(
  317.                                    libvlc_media_list_t * p_mlist,
  318.                                    libvlc_media_t * p_md,
  319.                                    int index,
  320.                                    libvlc_exception_t * p_e )
  321. {
  322.     if( mlist_is_writable(p_mlist,p_e) )
  323.         _libvlc_media_list_insert_media( p_mlist, p_md, index, p_e );
  324. }
  325. /* LibVLC internal version */
  326. void _libvlc_media_list_insert_media(
  327.                                    libvlc_media_list_t * p_mlist,
  328.                                    libvlc_media_t * p_md,
  329.                                    int index,
  330.                                    libvlc_exception_t * p_e )
  331. {
  332.     VLC_UNUSED(p_e);
  333.     libvlc_media_retain( p_md );
  334.     notify_item_addition( p_mlist, p_md, index, EventWillHappen );
  335.     vlc_array_insert( &p_mlist->items, p_md, index );
  336.     notify_item_addition( p_mlist, p_md, index, EventDidHappen );
  337. }
  338. /**************************************************************************
  339.  *       libvlc_media_list_remove_index (Public)
  340.  *
  341.  * Lock should be held when entering.
  342.  **************************************************************************/
  343. void libvlc_media_list_remove_index( libvlc_media_list_t * p_mlist,
  344.                                      int index,
  345.                                      libvlc_exception_t * p_e )
  346. {
  347.     if( mlist_is_writable(p_mlist,p_e) )
  348.         _libvlc_media_list_remove_index( p_mlist, index, p_e );
  349. }
  350. /* LibVLC internal version */
  351. void _libvlc_media_list_remove_index( libvlc_media_list_t * p_mlist,
  352.                                      int index,
  353.                                      libvlc_exception_t * p_e )
  354. {
  355.     libvlc_media_t * p_md;
  356.     if( index < 0 || index >= vlc_array_count( &p_mlist->items ))
  357.     {
  358.         libvlc_exception_raise( p_e, "Index out of bounds");
  359.         return;
  360.     }
  361.     p_md = vlc_array_item_at_index( &p_mlist->items, index );
  362.     notify_item_deletion( p_mlist, p_md, index, EventWillHappen );
  363.     vlc_array_remove( &p_mlist->items, index );
  364.     notify_item_deletion( p_mlist, p_md, index, EventDidHappen );
  365.     libvlc_media_release( p_md );
  366. }
  367. /**************************************************************************
  368.  *       libvlc_media_list_item_at_index (Public)
  369.  *
  370.  * Lock should be held when entering.
  371.  **************************************************************************/
  372. libvlc_media_t *
  373. libvlc_media_list_item_at_index( libvlc_media_list_t * p_mlist,
  374.                                  int index,
  375.                                  libvlc_exception_t * p_e )
  376. {
  377.     libvlc_media_t * p_md;
  378.     if( index < 0 || index >= vlc_array_count( &p_mlist->items ))
  379.     {
  380.         libvlc_exception_raise( p_e, "Index out of bounds");
  381.         return NULL;
  382.     }
  383.     p_md = vlc_array_item_at_index( &p_mlist->items, index );
  384.     libvlc_media_retain( p_md );
  385.     return p_md;
  386. }
  387. /**************************************************************************
  388.  *       libvlc_media_list_index_of_item (Public)
  389.  *
  390.  * Lock should be held when entering.
  391.  * Warning: this function returns the first matching item.
  392.  **************************************************************************/
  393. int libvlc_media_list_index_of_item( libvlc_media_list_t * p_mlist,
  394.                                      libvlc_media_t * p_searched_md,
  395.                                      libvlc_exception_t * p_e )
  396. {
  397.     VLC_UNUSED(p_e);
  398.     libvlc_media_t * p_md;
  399.     int i;
  400.     for ( i = 0; i < vlc_array_count( &p_mlist->items ); i++ )
  401.     {
  402.         p_md = vlc_array_item_at_index( &p_mlist->items, i );
  403.         if( p_searched_md == p_md )
  404.             return i;
  405.     }
  406.     return -1;
  407. }
  408. /**************************************************************************
  409.  *       libvlc_media_list_is_readonly (Public)
  410.  *
  411.  * This indicates if this media list is read-only from a user point of view
  412.  **************************************************************************/
  413. int libvlc_media_list_is_readonly( libvlc_media_list_t * p_mlist )
  414. {
  415.     return p_mlist->b_read_only;
  416. }
  417. /**************************************************************************
  418.  *       libvlc_media_list_lock (Public)
  419.  *
  420.  * The lock must be held in access operations. It is never used in the
  421.  * Public method.
  422.  **************************************************************************/
  423. void libvlc_media_list_lock( libvlc_media_list_t * p_mlist )
  424. {
  425.     vlc_mutex_lock( &p_mlist->object_lock );
  426. }
  427. /**************************************************************************
  428.  *       libvlc_media_list_unlock (Public)
  429.  *
  430.  * The lock must be held in access operations
  431.  **************************************************************************/
  432. void libvlc_media_list_unlock( libvlc_media_list_t * p_mlist )
  433. {
  434.     vlc_mutex_unlock( &p_mlist->object_lock );
  435. }
  436. /**************************************************************************
  437.  *       libvlc_media_list_p_event_manager (Public)
  438.  *
  439.  * The p_event_manager is immutable, so you don't have to hold the lock
  440.  **************************************************************************/
  441. libvlc_event_manager_t *
  442. libvlc_media_list_event_manager( libvlc_media_list_t * p_mlist,
  443.                                     libvlc_exception_t * p_e )
  444. {
  445.     VLC_UNUSED(p_e);
  446.     return p_mlist->p_event_manager;
  447. }