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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * media_list_player.c: libvlc new API media_list player functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2007 the VideoLAN team
  5.  * $Id: ee9a8e0a3663d0993f3891607f96252b7d9cd0f7 $
  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 <vlc/libvlc.h>
  24. #include <vlc/libvlc_media.h>
  25. #include <vlc/libvlc_media_list.h>
  26. #include <vlc/libvlc_media_player.h>
  27. #include <vlc/libvlc_media_list_player.h>
  28. #include <vlc/libvlc_events.h>
  29. #include "libvlc_internal.h"
  30. #include "media_internal.h" // Abuse, could and should be removed
  31. #include "media_list_path.h"
  32. struct libvlc_media_list_player_t
  33. {
  34.     libvlc_event_manager_t *    p_event_manager;
  35.     libvlc_instance_t *         p_libvlc_instance;
  36.     int                         i_refcount;
  37.     vlc_mutex_t                 object_lock;
  38.     libvlc_media_list_path_t    current_playing_item_path;
  39.     libvlc_media_t *            p_current_playing_item;
  40.     libvlc_media_list_t *       p_mlist;
  41.     libvlc_media_player_t *     p_mi;
  42. };
  43. /*
  44.  * Private functions
  45.  */
  46. /**************************************************************************
  47.  *       get_next_index (private)
  48.  *
  49.  * Simple next item fetcher.
  50.  **************************************************************************/
  51. static libvlc_media_list_path_t
  52. get_next_path( libvlc_media_list_player_t * p_mlp )
  53. {
  54.     /* We are entered with libvlc_media_list_lock( p_mlp->p_list ) */
  55.     libvlc_media_list_path_t ret;
  56.     libvlc_media_list_t * p_parent_of_playing_item;
  57.     libvlc_media_list_t * p_sublist_of_playing_item;
  58.     if ( !p_mlp->current_playing_item_path )
  59.     {
  60.         if( !libvlc_media_list_count( p_mlp->p_mlist, NULL ) )
  61.             return NULL;
  62.         return libvlc_media_list_path_with_root_index(0);
  63.     }
  64.     
  65.     p_sublist_of_playing_item = libvlc_media_list_sublist_at_path(
  66.                             p_mlp->p_mlist,
  67.                             p_mlp->current_playing_item_path );
  68.  
  69.     /* If item just gained a sublist just play it */
  70.     if( p_sublist_of_playing_item )
  71.     {
  72.         libvlc_media_list_release( p_sublist_of_playing_item );
  73.         return libvlc_media_list_path_copy_by_appending( p_mlp->current_playing_item_path, 0 );
  74.     }
  75.     /* Try to catch next element */
  76.     p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(
  77.                             p_mlp->p_mlist,
  78.                             p_mlp->current_playing_item_path );
  79.     int deepness = libvlc_media_list_path_depth( p_mlp->current_playing_item_path );
  80.     if( deepness < 1 || !p_parent_of_playing_item )
  81.         return NULL;
  82.     ret = libvlc_media_list_path_copy( p_mlp->current_playing_item_path );
  83.     while( ret[deepness-1] >= libvlc_media_list_count( p_parent_of_playing_item, NULL ) )
  84.     {
  85.         deepness--;
  86.         if( deepness <= 0 )
  87.         {
  88.             free( ret );
  89.             libvlc_media_list_release( p_parent_of_playing_item );
  90.             return NULL;
  91.         }
  92.         ret[deepness] = -1;
  93.         ret[deepness-1]++;
  94.         p_parent_of_playing_item  = libvlc_media_list_parentlist_at_path(
  95.                                         p_mlp->p_mlist,
  96.                                         ret );
  97.     }
  98.     libvlc_media_list_release( p_parent_of_playing_item );
  99.     return ret;
  100. }
  101. /**************************************************************************
  102.  *       media_player_reached_end (private) (Event Callback)
  103.  **************************************************************************/
  104. static void
  105. media_player_reached_end( const libvlc_event_t * p_event,
  106.                             void * p_user_data )
  107. {
  108.     libvlc_media_list_player_t * p_mlp = p_user_data;
  109.     libvlc_media_player_t * p_mi = p_event->p_obj;
  110.     libvlc_media_t *p_md, * p_current_md;
  111.     p_md = libvlc_media_player_get_media( p_mi, NULL );
  112.     /* XXX: need if p_mlp->p_current_playing_index is beyond */
  113.     p_current_md = libvlc_media_list_item_at_path(
  114.                         p_mlp->p_mlist,
  115.                         p_mlp->current_playing_item_path );
  116.     if( p_md != p_current_md )
  117.     {
  118.         msg_Warn( p_mlp->p_libvlc_instance->p_libvlc_int,
  119.                   "We are not sync-ed with the media instance" );
  120.         libvlc_media_release( p_md );
  121.         libvlc_media_release( p_current_md );
  122.         return;
  123.     }
  124.     libvlc_media_release( p_md );
  125.     libvlc_media_release( p_current_md );
  126.     libvlc_media_list_player_next( p_mlp, NULL );
  127. }
  128. /**************************************************************************
  129.  *       playlist_item_deleted (private) (Event Callback)
  130.  **************************************************************************/
  131. static void
  132. mlist_item_deleted( const libvlc_event_t * p_event, void * p_user_data )
  133. {
  134.     libvlc_media_t * p_current_md;
  135.     libvlc_media_list_player_t * p_mlp = p_user_data;
  136.     libvlc_media_list_t * p_emitting_mlist = p_event->p_obj;
  137.     /* XXX: need if p_mlp->p_current_playing_index is beyond */
  138.     p_current_md = libvlc_media_list_item_at_path(
  139.                         p_mlp->p_mlist,
  140.                         p_mlp->current_playing_item_path );
  141.     if( p_event->u.media_list_item_deleted.item == p_current_md &&
  142.         p_emitting_mlist == p_mlp->p_mlist )
  143.     {
  144.         /* We are playing this item, we choose to stop */
  145.         libvlc_media_list_player_stop( p_mlp, NULL );
  146.     }
  147. }
  148. /**************************************************************************
  149.  *       install_playlist_observer (private)
  150.  **************************************************************************/
  151. static void
  152. install_playlist_observer( libvlc_media_list_player_t * p_mlp )
  153. {
  154.     libvlc_event_attach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
  155.             libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
  156. }
  157. /**************************************************************************
  158.  *       uninstall_playlist_observer (private)
  159.  **************************************************************************/
  160. static void
  161. uninstall_playlist_observer( libvlc_media_list_player_t * p_mlp )
  162. {
  163.     if ( !p_mlp->p_mlist )
  164.     {
  165.         return;
  166.     }
  167.     libvlc_event_detach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
  168.             libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
  169. }
  170. /**************************************************************************
  171.  *       install_media_player_observer (private)
  172.  **************************************************************************/
  173. static void
  174. install_media_player_observer( libvlc_media_list_player_t * p_mlp )
  175. {
  176.     libvlc_event_attach( libvlc_media_player_event_manager( p_mlp->p_mi, NULL ),
  177.                          libvlc_MediaPlayerEndReached,
  178.                           media_player_reached_end, p_mlp, NULL );
  179. }
  180. /**************************************************************************
  181.  *       uninstall_media_player_observer (private)
  182.  **************************************************************************/
  183. static void
  184. uninstall_media_player_observer( libvlc_media_list_player_t * p_mlp )
  185. {
  186.     if ( !p_mlp->p_mi )
  187.     {
  188.         return;
  189.     }
  190.     libvlc_event_detach( libvlc_media_player_event_manager( p_mlp->p_mi, NULL ),
  191.                          libvlc_MediaPlayerEndReached,
  192.                          media_player_reached_end, p_mlp, NULL );
  193. }
  194. /**************************************************************************
  195.  *       set_current_playing_item (private)
  196.  *
  197.  * Playlist lock should be held
  198.  **************************************************************************/
  199. static void
  200. set_current_playing_item( libvlc_media_list_player_t * p_mlp,
  201.                           libvlc_media_list_path_t path,
  202.                           libvlc_exception_t * p_e )
  203. {
  204.     VLC_UNUSED(p_e);
  205.     libvlc_media_t * p_md;
  206.     p_md = libvlc_media_list_item_at_path( p_mlp->p_mlist, path );
  207.     vlc_mutex_lock( &p_mlp->object_lock );
  208.     if( p_mlp->current_playing_item_path != path )
  209.     {
  210.         free( p_mlp->current_playing_item_path );
  211.         p_mlp->current_playing_item_path = path;
  212.     }
  213.     if( !p_md )
  214.     {
  215.         vlc_mutex_unlock( &p_mlp->object_lock );
  216.         return;
  217.     }
  218.     /* We are not interested in getting media stop event now */
  219.     uninstall_media_player_observer( p_mlp );
  220.     if ( !p_mlp->p_mi )
  221.     {
  222.         p_mlp->p_mi = libvlc_media_player_new_from_media(p_md, p_e);
  223.     }
  224.     
  225.     if( p_md->p_subitems && libvlc_media_list_count( p_md->p_subitems, NULL ) > 0 )
  226.     {
  227.         libvlc_media_t * p_submd;
  228.         p_submd = libvlc_media_list_item_at_index( p_md->p_subitems, 0, NULL );
  229.         libvlc_media_player_set_media( p_mlp->p_mi, p_submd, NULL );
  230.         libvlc_media_release( p_submd );
  231.     }
  232.     else
  233.         libvlc_media_player_set_media( p_mlp->p_mi, p_md, NULL );
  234. //    wait_playing_state(); /* If we want to be synchronous */
  235.     install_media_player_observer( p_mlp );
  236.     vlc_mutex_unlock( &p_mlp->object_lock );
  237.     libvlc_media_release( p_md ); /* for libvlc_media_list_item_at_index */
  238. }
  239. /*
  240.  * Public libvlc functions
  241.  */
  242. /**************************************************************************
  243.  *         new (Public)
  244.  **************************************************************************/
  245. libvlc_media_list_player_t *
  246. libvlc_media_list_player_new( libvlc_instance_t * p_instance,
  247.                               libvlc_exception_t * p_e )
  248. {
  249.     (void)p_e;
  250.     libvlc_media_list_player_t * p_mlp;
  251.     p_mlp = malloc(sizeof(libvlc_media_list_player_t));
  252.     if( !p_mlp )
  253.         return NULL;
  254.     p_mlp->current_playing_item_path = NULL;
  255.     p_mlp->p_mi = NULL;
  256.     p_mlp->p_mlist = NULL;
  257.     vlc_mutex_init( &p_mlp->object_lock );
  258.     p_mlp->p_event_manager = libvlc_event_manager_new( p_mlp,
  259.                                                        p_instance,
  260.                                                        p_e );
  261.     libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
  262.             libvlc_MediaListPlayerNextItemSet, p_e );
  263.     return p_mlp;
  264. }
  265. /**************************************************************************
  266.  *         release (Public)
  267.  **************************************************************************/
  268. void libvlc_media_list_player_release( libvlc_media_list_player_t * p_mlp )
  269. {
  270.     if( !p_mlp )
  271.         return;
  272.     vlc_mutex_lock( &p_mlp->object_lock );
  273.     p_mlp->i_refcount--;
  274.     if( p_mlp->i_refcount > 0 )
  275.     {
  276.         vlc_mutex_unlock( &p_mlp->object_lock );
  277.         return;
  278.     }
  279.     vlc_mutex_unlock( &p_mlp->object_lock );
  280.     vlc_mutex_destroy( &p_mlp->object_lock );
  281.     libvlc_event_manager_release( p_mlp->p_event_manager );
  282.     libvlc_media_player_release( p_mlp->p_mi );
  283.     if( p_mlp->p_mlist )
  284.     {
  285.         uninstall_playlist_observer( p_mlp );
  286.         libvlc_media_list_release( p_mlp->p_mlist );
  287.     }
  288.     free( p_mlp->current_playing_item_path );
  289.     free( p_mlp );
  290. }
  291. /**************************************************************************
  292.  *        set_media_player (Public)
  293.  **************************************************************************/
  294. void libvlc_media_list_player_set_media_player(
  295.                                      libvlc_media_list_player_t * p_mlp,
  296.                                      libvlc_media_player_t * p_mi,
  297.                                      libvlc_exception_t * p_e )
  298. {
  299.     VLC_UNUSED(p_e);
  300.     vlc_mutex_lock( &p_mlp->object_lock );
  301.     if( p_mlp->p_mi )
  302.     {
  303.         uninstall_media_player_observer( p_mlp );
  304.         libvlc_media_player_release( p_mlp->p_mi );
  305.     }
  306.     libvlc_media_player_retain( p_mi );
  307.     p_mlp->p_mi = p_mi;
  308.     install_media_player_observer( p_mlp );
  309.     vlc_mutex_unlock( &p_mlp->object_lock );
  310. }
  311. /**************************************************************************
  312.  *       set_media_list (Public)
  313.  **************************************************************************/
  314. void libvlc_media_list_player_set_media_list(
  315.                                      libvlc_media_list_player_t * p_mlp,
  316.                                      libvlc_media_list_t * p_mlist,
  317.                                      libvlc_exception_t * p_e )
  318. {
  319.     vlc_mutex_lock( &p_mlp->object_lock );
  320.     if(!p_mlist)
  321.     {
  322.         libvlc_exception_raise( p_e, "No media list provided");
  323.         vlc_mutex_unlock( &p_mlp->object_lock );
  324.         return;
  325.     }
  326.     if( libvlc_media_list_player_is_playing( p_mlp, p_e ) )
  327.     {
  328.         libvlc_media_player_stop( p_mlp->p_mi, p_e );
  329.         /* Don't bother if there was an error. */
  330.         libvlc_exception_clear( p_e );
  331.     }
  332.     if( p_mlp->p_mlist )
  333.     {
  334.         uninstall_playlist_observer( p_mlp );
  335.         libvlc_media_list_release( p_mlp->p_mlist );
  336.     }
  337.     libvlc_media_list_retain( p_mlist );
  338.     p_mlp->p_mlist = p_mlist;
  339.  
  340.     install_playlist_observer( p_mlp );
  341.     vlc_mutex_unlock( &p_mlp->object_lock );
  342. }
  343. /**************************************************************************
  344.  *        Play (Public)
  345.  **************************************************************************/
  346. void libvlc_media_list_player_play( libvlc_media_list_player_t * p_mlp,
  347.                                   libvlc_exception_t * p_e )
  348. {
  349.     if( !p_mlp->current_playing_item_path )
  350.     {
  351.         libvlc_media_list_player_next( p_mlp, p_e );
  352.         return; /* Will set to play */
  353.     }
  354.     libvlc_media_player_play( p_mlp->p_mi, p_e );
  355. }
  356. /**************************************************************************
  357.  *        Pause (Public)
  358.  **************************************************************************/
  359. void libvlc_media_list_player_pause( libvlc_media_list_player_t * p_mlp,
  360.                                      libvlc_exception_t * p_e )
  361. {
  362.     if( !p_mlp->p_mi )
  363.         return;
  364.     libvlc_media_player_pause( p_mlp->p_mi, p_e );
  365. }
  366. /**************************************************************************
  367.  *        is_playing (Public)
  368.  **************************************************************************/
  369. int
  370. libvlc_media_list_player_is_playing( libvlc_media_list_player_t * p_mlp,
  371.                                      libvlc_exception_t * p_e )
  372. {
  373.     libvlc_state_t state = libvlc_media_player_get_state( p_mlp->p_mi, p_e );
  374.     return (state == libvlc_Opening) || (state == libvlc_Buffering) ||
  375.            (state == libvlc_Playing);
  376. }
  377. /**************************************************************************
  378.  *        State (Public)
  379.  **************************************************************************/
  380. libvlc_state_t
  381. libvlc_media_list_player_get_state( libvlc_media_list_player_t * p_mlp,
  382.                                     libvlc_exception_t * p_e )
  383. {
  384.     if( !p_mlp->p_mi )
  385.         return libvlc_Ended;
  386.     return libvlc_media_player_get_state( p_mlp->p_mi, p_e );
  387. }
  388. /**************************************************************************
  389.  *        Play item at index (Public)
  390.  **************************************************************************/
  391. void libvlc_media_list_player_play_item_at_index(
  392.                         libvlc_media_list_player_t * p_mlp,
  393.                         int i_index,
  394.                         libvlc_exception_t * p_e )
  395. {
  396.     set_current_playing_item( p_mlp, libvlc_media_list_path_with_root_index(i_index), p_e );
  397.     if( libvlc_exception_raised( p_e ) )
  398.         return;
  399.     /* Send the next item event */
  400.     libvlc_event_t event;
  401.     event.type = libvlc_MediaListPlayerNextItemSet;
  402.     libvlc_event_send( p_mlp->p_event_manager, &event );
  403.     libvlc_media_player_play( p_mlp->p_mi, p_e );
  404. }
  405. /**************************************************************************
  406.  *        Play item (Public)
  407.  **************************************************************************/
  408. void libvlc_media_list_player_play_item(
  409.                         libvlc_media_list_player_t * p_mlp,
  410.                         libvlc_media_t * p_md,
  411.                         libvlc_exception_t * p_e )
  412. {
  413.     libvlc_media_list_path_t path = libvlc_media_list_path_of_item( p_mlp->p_mlist, p_md );
  414.     if( !path )
  415.     {
  416.         libvlc_exception_raise( p_e, "No such item in media list" );
  417.         return;
  418.     }
  419.     set_current_playing_item( p_mlp, path, p_e );
  420.     if( libvlc_exception_raised( p_e ) )
  421.         return;
  422.     libvlc_media_player_play( p_mlp->p_mi, p_e );
  423. }
  424. /**************************************************************************
  425.  *       Stop (Public)
  426.  **************************************************************************/
  427. void libvlc_media_list_player_stop( libvlc_media_list_player_t * p_mlp,
  428.                                     libvlc_exception_t * p_e )
  429. {
  430.     if ( p_mlp->p_mi )
  431.     {
  432.         /* We are not interested in getting media stop event now */
  433.         uninstall_media_player_observer( p_mlp );
  434.         libvlc_media_player_stop( p_mlp->p_mi, p_e );
  435.         install_media_player_observer( p_mlp );
  436.     }
  437.     vlc_mutex_lock( &p_mlp->object_lock );
  438.     free( p_mlp->current_playing_item_path );
  439.     p_mlp->current_playing_item_path = NULL;
  440.     vlc_mutex_unlock( &p_mlp->object_lock );
  441. }
  442. /**************************************************************************
  443.  *       Next (Public)
  444.  **************************************************************************/
  445. void libvlc_media_list_player_next( libvlc_media_list_player_t * p_mlp,
  446.                                     libvlc_exception_t * p_e )
  447. {
  448.     libvlc_media_list_path_t path;
  449.     if (! p_mlp->p_mlist )
  450.     {
  451.         libvlc_exception_raise( p_e, "No more element to play" );
  452.         return;
  453.     }
  454.     libvlc_media_list_lock( p_mlp->p_mlist );
  455.     path = get_next_path( p_mlp );
  456.     if( !path )
  457.     {
  458.         libvlc_media_list_unlock( p_mlp->p_mlist );
  459.         libvlc_exception_raise( p_e, "No more element to play" );
  460.         libvlc_media_list_player_stop( p_mlp, p_e );
  461.         return;
  462.     }
  463.     set_current_playing_item( p_mlp, path, p_e );
  464.     libvlc_media_player_play( p_mlp->p_mi, p_e );
  465.     libvlc_media_list_unlock( p_mlp->p_mlist );
  466.     /* Send the next item event */
  467.     libvlc_event_t event;
  468.     event.type = libvlc_MediaListPlayerNextItemSet;
  469.     libvlc_event_send( p_mlp->p_event_manager, &event);
  470. }