]> git.sesse.net Git - vlc/blob - src/control/media_list_player.c
control/media_list_player.c: Fix a typo in get_next_index.
[vlc] / src / control / media_list_player.c
1 /*****************************************************************************
2  * media_list_player.c: libvlc new API media_list player functions
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id$
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 "libvlc_internal.h"
24 #include <vlc/libvlc.h>
25
26 /*
27  * Private functions
28  */
29
30 /**************************************************************************
31  *       get_next_index (private)
32  *
33  * Simple next item fetcher.
34  **************************************************************************/
35 static int get_next_index( libvlc_media_list_player_t * p_mlp )
36 {
37         /* We are entered with libvlc_media_list_lock( p_mlp->p_list ) */
38         
39         int next = p_mlp->i_current_playing_index + 1;
40
41         if( next >= libvlc_media_list_count( p_mlp->p_mlist, NULL ) )
42                 return -1; /* no more to play */
43
44         return next;
45 }
46
47 /**************************************************************************
48  *       media_instance_reached_end (private) (Event Callback)
49  **************************************************************************/
50 static void 
51 media_instance_reached_end( const libvlc_event_t * p_event,
52                             void * p_user_data )
53 {
54         libvlc_media_list_player_t * p_mlp = p_user_data;
55         libvlc_media_instance_t * p_mi = p_event->p_obj;
56     libvlc_media_descriptor_t *p_md, * p_current_md;
57     p_md = libvlc_media_instance_get_media_descriptor( p_mi, NULL );
58     /* XXX: need if p_mlp->p_current_playing_index is beyond */
59     p_current_md = libvlc_media_list_item_at_index(
60                         p_mlp->p_mlist,
61                         p_mlp->i_current_playing_index,
62                         NULL );
63         if( p_md != p_current_md )
64         {
65                 msg_Warn( p_mlp->p_libvlc_instance->p_libvlc_int,
66                                   "We are not sync-ed with the media instance" );
67         libvlc_media_descriptor_release( p_md );
68         libvlc_media_descriptor_release( p_current_md );
69                 return;
70         }
71     libvlc_media_descriptor_release( p_md );
72     libvlc_media_descriptor_release( p_current_md );
73         libvlc_media_list_player_next( p_mlp, NULL );
74 }
75
76 /**************************************************************************
77  *       playlist_item_deleted (private) (Event Callback)
78  **************************************************************************/
79 static void 
80 mlist_item_deleted( const libvlc_event_t * p_event, void * p_user_data )
81 {
82     libvlc_media_descriptor_t * p_current_md;    
83         libvlc_media_list_player_t * p_mlp = p_user_data;
84         libvlc_media_list_t * p_emitting_mlist = p_event->p_obj;
85     /* XXX: need if p_mlp->p_current_playing_index is beyond */
86     p_current_md = libvlc_media_list_item_at_index(
87                         p_mlp->p_mlist,
88                         p_mlp->i_current_playing_index,
89                         NULL );
90
91         if( p_event->u.media_list_item_deleted.item == p_current_md &&
92             p_emitting_mlist == p_mlp->p_mlist )
93         {
94                 /* We are playing this item, we choose to stop */
95                 libvlc_media_list_player_stop( p_mlp, NULL );
96         }
97 }
98
99 /**************************************************************************
100  *       install_playlist_observer (private)
101  **************************************************************************/
102 static void
103 install_playlist_observer( libvlc_media_list_player_t * p_mlp )
104 {
105         libvlc_event_attach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
106             libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
107 }
108
109 /**************************************************************************
110  *       uninstall_playlist_observer (private)
111  **************************************************************************/
112 static void
113 uninstall_playlist_observer( libvlc_media_list_player_t * p_mlp )
114 {
115     libvlc_event_detach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
116             libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
117 }
118
119 /**************************************************************************
120  *       install_media_instance_observer (private)
121  **************************************************************************/
122 static void
123 install_media_instance_observer( libvlc_media_list_player_t * p_mlp )
124 {
125         libvlc_event_attach( libvlc_media_instance_event_manager( p_mlp->p_mi, NULL ),
126                          libvlc_MediaInstanceReachedEnd,
127                                               media_instance_reached_end, p_mlp, NULL );
128 }
129
130
131 /**************************************************************************
132  *       uninstall_media_instance_observer (private)
133  **************************************************************************/
134 static void
135 uninstall_media_instance_observer( libvlc_media_list_player_t * p_mlp )
136 {
137         libvlc_event_detach( libvlc_media_instance_event_manager( p_mlp->p_mi, NULL ),
138                          libvlc_MediaInstanceReachedEnd,
139                                              media_instance_reached_end, p_mlp, NULL );
140 }
141 /**************************************************************************
142  *       Stop (Public)
143  **************************************************************************/
144 static vlc_bool_t
145 libvlc_media_list_player_is_playing( libvlc_media_list_player_t * p_mlp,
146                                     libvlc_exception_t * p_e )
147 {
148     libvlc_exception_raise( p_e, "Unimplemented" );
149     return 0;
150 }
151
152 /**************************************************************************
153  *       Next (private)
154  *
155  * Playlist lock should be held
156  **************************************************************************/
157 static void
158 media_list_player_set_next( libvlc_media_list_player_t * p_mlp, int index,
159                             libvlc_exception_t * p_e )
160 {
161         libvlc_media_descriptor_t * p_md;
162         
163         p_md = libvlc_media_list_item_at_index( p_mlp->p_mlist, index, p_e );
164         if( !p_md )
165         {
166                 libvlc_media_list_unlock( p_mlp->p_mlist );             
167                 if( !libvlc_exception_raised( p_e ) )
168                         libvlc_exception_raise( p_e, "Can't obtain a media" );
169                 return;
170         }
171
172     vlc_mutex_lock( &p_mlp->object_lock );
173         
174     p_mlp->i_current_playing_index = index;
175
176         /* We are not interested in getting media_descriptor stop event now */
177         uninstall_media_instance_observer( p_mlp );
178     libvlc_media_instance_set_media_descriptor( p_mlp->p_mi, p_md, NULL );
179 //      wait_playing_state(); /* If we want to be synchronous */
180         install_media_instance_observer( p_mlp );
181
182     vlc_mutex_unlock( &p_mlp->object_lock );
183
184         libvlc_media_list_unlock( p_mlp->p_mlist );             
185         
186         libvlc_media_descriptor_release( p_md ); /* for libvlc_media_list_item_at_index */
187 }
188
189 /*
190  * Public libvlc functions
191  */
192
193 /**************************************************************************
194  *         libvlc_media_list_player_new (Public)
195  **************************************************************************/
196 libvlc_media_list_player_t *
197 libvlc_media_list_player_new( libvlc_instance_t * p_instance,
198                               libvlc_exception_t * p_e )
199 {
200     (void)p_e;
201     libvlc_media_list_player_t * p_mlp;
202     p_mlp = malloc(sizeof(libvlc_media_list_player_t));
203         p_mlp->i_current_playing_index = -1;
204     p_mlp->p_mi = NULL;
205     p_mlp->p_mlist = NULL;
206     vlc_mutex_init( p_instance->p_libvlc_int, &p_mlp->object_lock );
207     
208         return p_mlp;
209 }
210
211 /**************************************************************************
212  *         libvlc_media_list_player_release (Public)
213  **************************************************************************/
214 void libvlc_media_list_player_release( libvlc_media_list_player_t * p_mlp )
215 {
216     free(p_mlp);
217 }
218
219 /**************************************************************************
220  *        libvlc_media_list_player_set_media_instance (Public)
221  **************************************************************************/
222 void libvlc_media_list_player_set_media_instance(
223                                      libvlc_media_list_player_t * p_mlp,
224                                      libvlc_media_instance_t * p_mi,
225                                      libvlc_exception_t * p_e )
226 {
227     vlc_mutex_lock( &p_mlp->object_lock );
228
229         if( p_mlp->p_mi )
230         {
231                 uninstall_media_instance_observer( p_mlp );
232                 libvlc_media_instance_release( p_mlp->p_mi );
233         }
234         libvlc_media_instance_retain( p_mi );
235         p_mlp->p_mi = p_mi;
236
237     install_media_instance_observer( p_mlp );
238
239     vlc_mutex_unlock( &p_mlp->object_lock );
240 }
241
242 /**************************************************************************
243  *       Set a playlist (Public)
244  **************************************************************************/
245 void libvlc_media_list_player_set_media_list(
246                                      libvlc_media_list_player_t * p_mlp,
247                                      libvlc_media_list_t * p_mlist,
248                                      libvlc_exception_t * p_e )
249 {
250     vlc_mutex_lock( &p_mlp->object_lock );
251     
252         if( libvlc_media_list_player_is_playing( p_mlp, p_e ) )
253                 libvlc_media_list_player_stop( p_mlp, p_e );
254
255         if( p_mlp->p_mlist )
256         {
257                 uninstall_playlist_observer( p_mlp );
258                 libvlc_media_list_release( p_mlp->p_mlist );
259         }
260         libvlc_media_list_retain( p_mlist );
261         p_mlp->p_mlist = p_mlist;
262     
263         install_playlist_observer( p_mlp );
264
265     vlc_mutex_unlock( &p_mlp->object_lock );
266 }
267
268 /**************************************************************************
269  *        Play (Public)
270  **************************************************************************/
271 void libvlc_media_list_player_play( libvlc_media_list_player_t * p_mlp,
272                                   libvlc_exception_t * p_e )
273 {
274         libvlc_media_list_player_next( p_mlp, p_e );
275
276         if( libvlc_exception_raised( p_e ) )
277                 return;
278
279         libvlc_media_instance_play( p_mlp->p_mi, p_e );
280 }
281
282 /**************************************************************************
283  *        Play item at index (Public)
284  *
285  * Playlist lock should be help
286  **************************************************************************/
287 void libvlc_media_list_player_play_item_at_index(
288                         libvlc_media_list_player_t * p_mlp,
289                         int i_index,
290                         libvlc_exception_t * p_e )
291 {
292         media_list_player_set_next( p_mlp, i_index, p_e );
293
294         if( libvlc_exception_raised( p_e ) )
295                 return;
296
297         libvlc_media_instance_play( p_mlp->p_mi, p_e );
298 }
299
300
301 /**************************************************************************
302  *       Stop (Public)
303  **************************************************************************/
304 void libvlc_media_list_player_stop( libvlc_media_list_player_t * p_mlp,
305                                     libvlc_exception_t * p_e )
306 {
307         libvlc_media_instance_stop( p_mlp->p_mi, p_e );
308
309     vlc_mutex_lock( &p_mlp->object_lock );
310         p_mlp->i_current_playing_index = -1;
311     vlc_mutex_unlock( &p_mlp->object_lock );
312 }
313
314 /**************************************************************************
315  *       Next (Public)
316  **************************************************************************/
317 void libvlc_media_list_player_next( libvlc_media_list_player_t * p_mlp,
318                                     libvlc_exception_t * p_e )
319 {       
320         int index;
321         
322         libvlc_media_list_lock( p_mlp->p_mlist );
323
324         index = get_next_index( p_mlp );
325
326         if( index < 0 )
327         {
328                 libvlc_media_list_unlock( p_mlp->p_mlist );
329                 libvlc_exception_raise( p_e, "No more element to play" );
330                 libvlc_media_list_player_stop( p_mlp, p_e );
331                 return;
332         }
333
334         media_list_player_set_next( p_mlp, index, p_e );
335         
336     libvlc_media_list_unlock( p_mlp->p_mlist );
337 }
338