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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * engine.c : Run the playlist and handle its control
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2008 the VideoLAN team
  5.  *
  6.  * Authors: Samuel Hocevar <sam@zoy.org>
  7.  *          Clément Stenac <zorglub@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 <stddef.h>
  27. #include <assert.h>
  28. #include <vlc_common.h>
  29. #include <vlc_sout.h>
  30. #include <vlc_playlist.h>
  31. #include <vlc_interface.h>
  32. #include "playlist_internal.h"
  33. #include "stream_output/stream_output.h" /* sout_DeleteInstance */
  34. /*****************************************************************************
  35.  * Local prototypes
  36.  *****************************************************************************/
  37. static void VariablesInit( playlist_t *p_playlist );
  38. static void playlist_Destructor( vlc_object_t * p_this );
  39. static int RandomCallback( vlc_object_t *p_this, char const *psz_cmd,
  40.                            vlc_value_t oldval, vlc_value_t newval, void *a )
  41. {
  42.     (void)psz_cmd; (void)oldval; (void)newval; (void)a;
  43.     playlist_t *p_playlist = (playlist_t*)p_this;
  44.     PL_LOCK;
  45.     pl_priv(p_playlist)->b_reset_currently_playing = true;
  46.     vlc_cond_signal( &pl_priv(p_playlist)->signal );
  47.     PL_UNLOCK;
  48.     return VLC_SUCCESS;
  49. }
  50. /**
  51.  * Create playlist
  52.  *
  53.  * Create a playlist structure.
  54.  * param p_parent the vlc object that is to be the parent of this playlist
  55.  * return a pointer to the created playlist, or NULL on error
  56.  */
  57. playlist_t * playlist_Create( vlc_object_t *p_parent )
  58. {
  59.     static const char playlist_name[] = "playlist";
  60.     playlist_t *p_playlist;
  61.     playlist_private_t *p;
  62.     /* Allocate structure */
  63.     p = vlc_custom_create( p_parent, sizeof( *p ),
  64.                            VLC_OBJECT_GENERIC, playlist_name );
  65.     if( !p )
  66.         return NULL;
  67.     assert( offsetof( playlist_private_t, public_data ) == 0 );
  68.     p_playlist = &p->public_data;
  69.     TAB_INIT( pl_priv(p_playlist)->i_sds, pl_priv(p_playlist)->pp_sds );
  70.     libvlc_priv(p_parent->p_libvlc)->p_playlist = p_playlist;
  71.     VariablesInit( p_playlist );
  72.     vlc_mutex_init( &p->lock );
  73.     vlc_cond_init( &p->signal );
  74.     /* Initialise data structures */
  75.     pl_priv(p_playlist)->i_last_playlist_id = 0;
  76.     pl_priv(p_playlist)->p_input = NULL;
  77.     ARRAY_INIT( p_playlist->items );
  78.     ARRAY_INIT( p_playlist->all_items );
  79.     ARRAY_INIT( pl_priv(p_playlist)->items_to_delete );
  80.     ARRAY_INIT( p_playlist->current );
  81.     p_playlist->i_current_index = 0;
  82.     pl_priv(p_playlist)->b_reset_currently_playing = true;
  83.     pl_priv(p_playlist)->last_rebuild_date = 0;
  84.     pl_priv(p_playlist)->b_tree = var_CreateGetBool( p_playlist, "playlist-tree" );
  85.     pl_priv(p_playlist)->b_doing_ml = false;
  86.     const bool b_auto_preparse = var_CreateGetBool( p_playlist, "auto-preparse" );
  87.     pl_priv(p_playlist)->b_auto_preparse = b_auto_preparse;
  88.     PL_LOCK; /* playlist_NodeCreate will check for it */
  89.     p_playlist->p_root_category = playlist_NodeCreate( p_playlist, NULL, NULL,
  90.                                     0, NULL );
  91.     p_playlist->p_root_onelevel = playlist_NodeCreate( p_playlist, NULL, NULL,
  92.                                     0, p_playlist->p_root_category->p_input );
  93.     PL_UNLOCK;
  94.     if( !p_playlist->p_root_category || !p_playlist->p_root_onelevel )
  95.         return NULL;
  96.     /* Create playlist and media library */
  97.     PL_LOCK; /* playlist_NodesPairCreate will check for it */
  98.     playlist_NodesPairCreate( p_playlist, _( "Playlist" ),
  99.                             &p_playlist->p_local_category,
  100.                             &p_playlist->p_local_onelevel, false );
  101.     PL_UNLOCK;
  102.     p_playlist->p_local_category->i_flags |= PLAYLIST_RO_FLAG;
  103.     p_playlist->p_local_onelevel->i_flags |= PLAYLIST_RO_FLAG;
  104.     if( !p_playlist->p_local_category || !p_playlist->p_local_onelevel ||
  105.         !p_playlist->p_local_category->p_input ||
  106.         !p_playlist->p_local_onelevel->p_input )
  107.         return NULL;
  108.     if( config_GetInt( p_playlist, "media-library") )
  109.     {
  110.         PL_LOCK; /* playlist_NodesPairCreate will check for it */
  111.         playlist_NodesPairCreate( p_playlist, _( "Media Library" ),
  112.                             &p_playlist->p_ml_category,
  113.                             &p_playlist->p_ml_onelevel, false );
  114.         PL_UNLOCK;
  115.         if(!p_playlist->p_ml_category || !p_playlist->p_ml_onelevel)
  116.             return NULL;
  117.         p_playlist->p_ml_category->i_flags |= PLAYLIST_RO_FLAG;
  118.         p_playlist->p_ml_onelevel->i_flags |= PLAYLIST_RO_FLAG;
  119.     }
  120.     else
  121.     {
  122.         p_playlist->p_ml_category = p_playlist->p_ml_onelevel = NULL;
  123.     }
  124.     /* Initial status */
  125.     pl_priv(p_playlist)->status.p_item = NULL;
  126.     pl_priv(p_playlist)->status.p_node = p_playlist->p_local_onelevel;
  127.     pl_priv(p_playlist)->request.b_request = false;
  128.     pl_priv(p_playlist)->status.i_status = PLAYLIST_STOPPED;
  129.     pl_priv(p_playlist)->b_auto_preparse = false;
  130.     playlist_MLLoad( p_playlist );
  131.     pl_priv(p_playlist)->b_auto_preparse = b_auto_preparse;
  132.     vlc_object_set_destructor( p_playlist, playlist_Destructor );
  133.     return p_playlist;
  134. }
  135. /**
  136.  * Destroy playlist
  137.  *
  138.  * Destroy a playlist structure.
  139.  * param p_playlist the playlist object
  140.  * return nothing
  141.  */
  142. static void playlist_Destructor( vlc_object_t * p_this )
  143. {
  144.     playlist_t *p_playlist = (playlist_t *)p_this;
  145.     playlist_private_t *p_sys = pl_priv(p_playlist);
  146.     assert( !p_sys->p_input );
  147.     assert( !p_sys->p_input_resource );
  148.     assert( !p_sys->p_preparser );
  149.     assert( !p_sys->p_fetcher );
  150.     vlc_cond_destroy( &p_sys->signal );
  151.     vlc_mutex_destroy( &p_sys->lock );
  152.     /* Remove all remaining items */
  153.     FOREACH_ARRAY( playlist_item_t *p_del, p_playlist->all_items )
  154.         free( p_del->pp_children );
  155.         vlc_gc_decref( p_del->p_input );
  156.         free( p_del );
  157.     FOREACH_END();
  158.     ARRAY_RESET( p_playlist->all_items );
  159.     FOREACH_ARRAY( playlist_item_t *p_del, p_sys->items_to_delete )
  160.         free( p_del->pp_children );
  161.         vlc_gc_decref( p_del->p_input );
  162.         free( p_del );
  163.     FOREACH_END();
  164.     ARRAY_RESET( p_sys->items_to_delete );
  165.     ARRAY_RESET( p_playlist->items );
  166.     ARRAY_RESET( p_playlist->current );
  167.     msg_Dbg( p_this, "Destroyed" );
  168. }
  169. /** Get current playing input.
  170.  */
  171. input_thread_t * playlist_CurrentInput( playlist_t * p_playlist )
  172. {
  173.     input_thread_t * p_input;
  174.     PL_LOCK;
  175.     p_input = pl_priv(p_playlist)->p_input;
  176.     if( p_input ) vlc_object_hold( p_input );
  177.     PL_UNLOCK;
  178.     return p_input;
  179. }
  180. /**
  181.  * @}
  182.  */
  183. /** Accessor for status item and status nodes.
  184.  */
  185. playlist_item_t * get_current_status_item( playlist_t * p_playlist )
  186. {
  187.     PL_ASSERT_LOCKED;
  188.     return pl_priv(p_playlist)->status.p_item;
  189. }
  190. playlist_item_t * get_current_status_node( playlist_t * p_playlist )
  191. {
  192.     PL_ASSERT_LOCKED;
  193.     return pl_priv(p_playlist)->status.p_node;
  194. }
  195. void set_current_status_item( playlist_t * p_playlist,
  196.     playlist_item_t * p_item )
  197. {
  198.     PL_ASSERT_LOCKED;
  199.     if( pl_priv(p_playlist)->status.p_item &&
  200.         pl_priv(p_playlist)->status.p_item->i_flags & PLAYLIST_REMOVE_FLAG &&
  201.         pl_priv(p_playlist)->status.p_item != p_item )
  202.     {
  203.         /* It's unsafe given current design to delete a playlist item :(
  204.         playlist_ItemDelete( pl_priv(p_playlist)->status.p_item ); */
  205.     }
  206.     pl_priv(p_playlist)->status.p_item = p_item;
  207. }
  208. void set_current_status_node( playlist_t * p_playlist,
  209.     playlist_item_t * p_node )
  210. {
  211.     PL_ASSERT_LOCKED;
  212.     if( pl_priv(p_playlist)->status.p_node &&
  213.         pl_priv(p_playlist)->status.p_node->i_flags & PLAYLIST_REMOVE_FLAG &&
  214.         pl_priv(p_playlist)->status.p_node != p_node )
  215.     {
  216.         /* It's unsafe given current design to delete a playlist item :(
  217.         playlist_ItemDelete( pl_priv(p_playlist)->status.p_node ); */
  218.     }
  219.     pl_priv(p_playlist)->status.p_node = p_node;
  220. }
  221. static void VariablesInit( playlist_t *p_playlist )
  222. {
  223.     /* These variables control updates */
  224.     var_Create( p_playlist, "intf-change", VLC_VAR_BOOL );
  225.     var_SetBool( p_playlist, "intf-change", true );
  226.     var_Create( p_playlist, "item-change", VLC_VAR_INTEGER );
  227.     var_SetInteger( p_playlist, "item-change", -1 );
  228.     var_Create( p_playlist, "playlist-item-deleted", VLC_VAR_INTEGER );
  229.     var_SetInteger( p_playlist, "playlist-item-deleted", -1 );
  230.     var_Create( p_playlist, "playlist-item-append", VLC_VAR_ADDRESS );
  231.     var_Create( p_playlist, "item-current", VLC_VAR_INTEGER );
  232.     var_SetInteger( p_playlist, "item-current", -1 );
  233.     var_Create( p_playlist, "activity", VLC_VAR_INTEGER );
  234.     var_SetInteger( p_playlist, "activity", 0 );
  235.     /* Variables to control playback */
  236.     var_Create( p_playlist, "play-and-stop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  237.     var_Create( p_playlist, "play-and-exit", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  238.     var_Create( p_playlist, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  239.     var_Create( p_playlist, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  240.     var_Create( p_playlist, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  241.     var_AddCallback( p_playlist, "random", RandomCallback, NULL );
  242.     /* */
  243.     var_Create( p_playlist, "album-art", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  244. }
  245. playlist_item_t * playlist_CurrentPlayingItem( playlist_t * p_playlist )
  246. {
  247.     PL_ASSERT_LOCKED;
  248.     return pl_priv(p_playlist)->status.p_item;
  249. }
  250. int playlist_Status( playlist_t * p_playlist )
  251. {
  252.     PL_ASSERT_LOCKED;
  253.     return pl_priv(p_playlist)->status.i_status;
  254. }