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 *****************************************************************************/
30 #include <vlc_input.h>
31 #include <vlc_interface.h>
32 #include <vlc_playlist.h>
33 #include "playlist_internal.h"
34 #include "interface/interface.h"
36 /*****************************************************************************
38 *****************************************************************************/
39 static void RunControlThread ( playlist_t
* );
40 static void RunPreparse( playlist_preparse_t
* );
41 static void RunFetcher( playlist_fetcher_t
* );
43 static void DestroyInteraction( playlist_t
* );
45 /*****************************************************************************
46 * Main functions for the global thread
47 *****************************************************************************/
50 * Create the main playlist thread
51 * Additionally to the playlist, this thread controls :
56 * \return an object with a started thread
58 void __playlist_ThreadCreate( vlc_object_t
*p_parent
)
60 playlist_t
*p_playlist
= playlist_Create( p_parent
);
61 if( !p_playlist
) return;
64 p_playlist
->p_stats
= (global_stats_t
*)malloc( sizeof( global_stats_t
) );
65 vlc_mutex_init( p_playlist
, &p_playlist
->p_stats
->lock
);
66 p_playlist
->p_stats_computer
= NULL
;
69 p_playlist
->p_interaction
= NULL
;
72 p_playlist
->p_preparse
= vlc_object_create( p_playlist
,
73 sizeof( playlist_preparse_t
) );
74 if( !p_playlist
->p_preparse
)
76 msg_Err( p_playlist
, "unable to create preparser" );
77 vlc_object_destroy( p_playlist
);
80 p_playlist
->p_preparse
->i_waiting
= 0;
81 p_playlist
->p_preparse
->pp_waiting
= NULL
;
83 vlc_object_attach( p_playlist
->p_preparse
, p_playlist
);
84 if( vlc_thread_create( p_playlist
->p_preparse
, "preparser",
85 RunPreparse
, VLC_THREAD_PRIORITY_LOW
, VLC_TRUE
) )
87 msg_Err( p_playlist
, "cannot spawn preparse thread" );
88 vlc_object_detach( p_playlist
->p_preparse
);
89 vlc_object_destroy( p_playlist
->p_preparse
);
94 p_playlist
->p_fetcher
= vlc_object_create( p_playlist
,
95 sizeof( playlist_fetcher_t
) );
96 if( !p_playlist
->p_fetcher
)
98 msg_Err( p_playlist
, "unable to create secondary preparser" );
99 vlc_object_destroy( p_playlist
);
102 p_playlist
->p_fetcher
->i_waiting
= 0;
103 p_playlist
->p_fetcher
->p_waiting
= NULL
;
104 p_playlist
->p_fetcher
->b_fetch_meta
= var_CreateGetInteger( p_playlist
,
106 p_playlist
->p_fetcher
->i_art_policy
= var_CreateGetInteger( p_playlist
,
109 vlc_object_attach( p_playlist
->p_fetcher
, p_playlist
);
110 if( vlc_thread_create( p_playlist
->p_fetcher
,
113 VLC_THREAD_PRIORITY_LOW
, VLC_TRUE
) )
115 msg_Err( p_playlist
, "cannot spawn secondary preparse thread" );
116 vlc_object_detach( p_playlist
->p_fetcher
);
117 vlc_object_destroy( p_playlist
->p_fetcher
);
122 if( vlc_thread_create( p_playlist
, "playlist", RunControlThread
,
123 VLC_THREAD_PRIORITY_LOW
, VLC_TRUE
) )
125 msg_Err( p_playlist
, "cannot spawn playlist thread" );
126 vlc_object_destroy( p_playlist
);
130 /* The object has been initialized, now attach it */
131 vlc_object_attach( p_playlist
, p_parent
);
137 * Destroy the playlist global thread.
139 * Deinits all things controlled by the playlist global thread
140 * \param p_playlist the playlist thread to destroy
141 * \return VLC_SUCCESS or an error
143 int playlist_ThreadDestroy( playlist_t
* p_playlist
)
145 // Tell playlist to go to last loop
146 vlc_object_kill( p_playlist
);
149 if( p_playlist
->p_preparse
)
151 vlc_object_kill( p_playlist
->p_preparse
);
152 vlc_thread_join( p_playlist
->p_preparse
);
153 free( p_playlist
->p_preparse
->pp_waiting
);
154 vlc_object_detach( p_playlist
->p_preparse
);
155 vlc_object_destroy( p_playlist
->p_preparse
);
159 if( p_playlist
->p_fetcher
)
161 vlc_object_kill( p_playlist
->p_fetcher
);
162 vlc_thread_join( p_playlist
->p_fetcher
);
163 free( p_playlist
->p_fetcher
->p_waiting
);
164 vlc_object_detach( p_playlist
->p_fetcher
);
165 vlc_object_destroy( p_playlist
->p_fetcher
);
168 // Wait for thread to complete
169 vlc_thread_join( p_playlist
);
172 vlc_mutex_destroy( &p_playlist
->p_stats
->lock
);
173 if( p_playlist
->p_stats
)
174 free( p_playlist
->p_stats
);
176 DestroyInteraction( p_playlist
);
178 playlist_Destroy( p_playlist
);
184 * Run the main control thread itself
186 static void RunControlThread ( playlist_t
*p_playlist
)
190 /* Tell above that we're ready */
191 vlc_thread_ready( p_playlist
);
192 while( !p_playlist
->b_die
)
196 if( p_playlist
->p_interaction
)
197 intf_InteractionManage( p_playlist
);
199 playlist_MainLoop( p_playlist
);
200 if( p_playlist
->b_cant_sleep
)
202 /* 100 ms is an acceptable delay for playlist operations */
203 msleep( INTF_IDLE_SLEEP
*2 );
208 vlc_cond_wait( &p_playlist
->object_wait
, &p_playlist
->object_lock
);
212 playlist_LastLoop( p_playlist
);
215 /*****************************************************************************
216 * Preparse-specific functions
217 *****************************************************************************/
218 static void RunPreparse ( playlist_preparse_t
*p_obj
)
220 /* Tell above that we're ready */
221 vlc_thread_ready( p_obj
);
222 playlist_PreparseLoop( p_obj
);
225 static void RunFetcher( playlist_fetcher_t
*p_obj
)
227 /* Tell above that we're ready */
228 vlc_thread_ready( p_obj
);
229 playlist_FetcherLoop( p_obj
);
232 /*****************************************************************************
233 * Interaction functions
234 *****************************************************************************/
235 static void DestroyInteraction( playlist_t
*p_playlist
)
237 if( p_playlist
->p_interaction
)
239 intf_InteractionDestroy( p_playlist
->p_interaction
);
240 p_playlist
->p_interaction
= NULL
;