1 /*****************************************************************************
2 * playlist.c : Playlist management functions
3 *****************************************************************************
4 * Copyright (C) 1999-2004 the VideoLAN team
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Clément Stenac <zorglub@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
26 #include <vlc_input.h>
27 #include "vlc_playlist.h"
28 #include "vlc_interaction.h"
30 /*****************************************************************************
32 *****************************************************************************/
33 static void RunControlThread ( playlist_t * );
34 static void RunPreparse( playlist_preparse_t * );
36 static playlist_t * CreatePlaylist( vlc_object_t *p_parent );
37 static void HandlePlaylist( playlist_t * );
38 static void EndPlaylist( playlist_t * );
39 static void DestroyPlaylist( playlist_t * );
41 static void HandleStats( playlist_t *, int );
43 static void HandleInteraction( playlist_t * );
44 static void DestroyInteraction( playlist_t * );
46 /*****************************************************************************
47 * Main functions for the global thread
48 *****************************************************************************/
51 * Create the main playlist thread
52 * Additionally to the playlist, this thread controls :
57 * \return an object with a started thread
59 playlist_t * __playlist_ThreadCreate( vlc_object_t *p_parent )
61 playlist_t *p_playlist;
62 p_playlist = CreatePlaylist( p_parent );
64 if( !p_playlist ) return NULL;
67 p_playlist->p_stats = (global_stats_t *)malloc( sizeof( global_stats_t ) );
68 vlc_mutex_init( p_playlist, &p_playlist->p_stats->lock );
71 p_playlist->p_interaction = NULL;
74 p_playlist->p_preparse = vlc_object_create( p_playlist,
75 sizeof( playlist_preparse_t ) );
76 if( !p_playlist->p_preparse )
78 msg_Err( p_playlist, "unable to create preparser" );
79 vlc_object_destroy( p_playlist );
82 p_playlist->p_preparse->i_waiting = 0;
83 p_playlist->p_preparse->pp_waiting = NULL;
85 vlc_object_attach( p_playlist->p_preparse, p_playlist );
86 if( vlc_thread_create( p_playlist->p_preparse, "preparser",
87 RunPreparse, VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
89 msg_Err( p_playlist, "cannot spawn preparse thread" );
90 vlc_object_detach( p_playlist->p_preparse );
91 vlc_object_destroy( p_playlist->p_preparse );
96 if( vlc_thread_create( p_playlist, "playlist", RunControlThread,
97 VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
99 msg_Err( p_playlist, "cannot spawn playlist thread" );
100 vlc_object_destroy( p_playlist );
104 /* The object has been initialized, now attach it */
105 vlc_object_attach( p_playlist, p_parent );
111 * Destroy the playlist global thread.
113 * Deinits all things controlled by the playlist global thread
114 * \param p_playlist the playlist thread to destroy
115 * \return VLC_SUCCESS or an error
117 int playlist_ThreadDestroy( playlist_t * p_playlist )
119 p_playlist->b_die = 1;
121 DestroyInteraction( p_playlist );
122 DestroyPlaylist( p_playlist );
128 * Run the main control thread itself
130 static void RunControlThread ( playlist_t *p_playlist )
134 /* Tell above that we're ready */
135 vlc_thread_ready( p_playlist );
137 while( !p_playlist->b_die )
141 HandleInteraction( p_playlist );
142 HandleStats( p_playlist, i_loops );
144 HandlePlaylist( p_playlist );
146 msleep( INTF_IDLE_SLEEP / 2 );
148 /* Stop sleeping earlier if we have work */
149 /* TODO : statistics about this */
150 if ( p_playlist->request.b_request &&
151 p_playlist->status.i_status == PLAYLIST_RUNNING )
156 msleep( INTF_IDLE_SLEEP / 2 );
159 EndPlaylist( p_playlist );
163 /*****************************************************************************
164 * Playlist-specific functions
165 *****************************************************************************/
166 static playlist_t * CreatePlaylist( vlc_object_t *p_parent )
168 return playlist_Create( p_parent );
171 static void DestroyPlaylist( playlist_t *p_playlist )
173 playlist_Destroy( p_playlist );
176 static void HandlePlaylist( playlist_t *p_playlist )
178 playlist_MainLoop( p_playlist );
181 static void EndPlaylist( playlist_t *p_playlist )
183 playlist_LastLoop( p_playlist );
186 /*****************************************************************************
187 * Preparse-specific functions
188 *****************************************************************************/
189 static void RunPreparse ( playlist_preparse_t *p_obj )
191 /* Tell above that we're ready */
192 vlc_thread_ready( p_obj );
193 playlist_t *p_playlist = (playlist_t *)p_obj->p_parent;
195 while( !p_playlist->b_die )
197 playlist_PreparseLoop( p_obj );
198 if( p_obj->i_waiting == 0 )
200 msleep( INTF_IDLE_SLEEP );
205 /*****************************************************************************
206 * Interaction functions
207 *****************************************************************************/
208 static void DestroyInteraction( playlist_t *p_playlist )
210 if( p_playlist->p_interaction )
212 intf_InteractionDestroy( p_playlist->p_interaction );
216 static void HandleInteraction( playlist_t *p_playlist )
218 if( p_playlist->p_interaction )
220 stats_TimerStart( p_playlist, "Interaction thread",
221 STATS_TIMER_INTERACTION );
222 intf_InteractionManage( p_playlist );
223 stats_TimerStop( p_playlist, STATS_TIMER_INTERACTION );
228 /*****************************************************************************
230 *****************************************************************************/
231 static void HandleStats( playlist_t *p_playlist, int i_loops )
233 if( i_loops %5 == 0 && p_playlist->p_stats )
235 stats_ComputeGlobalStats( p_playlist, p_playlist->p_stats );
236 if( p_playlist->p_input )
238 stats_ComputeInputStats( p_playlist->p_input,
239 p_playlist->p_input->input.p_item->p_stats );