1 /*****************************************************************************
2 * media_list_player.c: libvlc new API media_list player functions
3 *****************************************************************************
4 * Copyright (C) 2007 the VideoLAN team
7 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
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.
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.
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 #include "media_list_path.h"
28 struct libvlc_media_list_player_t
30 libvlc_event_manager_t * p_event_manager;
31 libvlc_instance_t * p_libvlc_instance;
33 vlc_mutex_t object_lock;
34 libvlc_media_list_path_t current_playing_item_path;
35 libvlc_media_t * p_current_playing_item;
36 libvlc_media_list_t * p_mlist;
37 libvlc_media_player_t * p_mi;
44 /**************************************************************************
45 * get_next_index (private)
47 * Simple next item fetcher.
48 **************************************************************************/
49 static libvlc_media_list_path_t
50 get_next_path( libvlc_media_list_player_t * p_mlp )
52 /* We are entered with libvlc_media_list_lock( p_mlp->p_list ) */
53 libvlc_media_list_path_t ret;
54 libvlc_media_list_t * p_parent_of_playing_item;
55 libvlc_media_list_t * p_sublist_of_playing_item;
57 if ( !p_mlp->current_playing_item_path )
59 if( !libvlc_media_list_count( p_mlp->p_mlist, NULL ) )
61 return libvlc_media_list_path_with_root_index(0);
64 p_sublist_of_playing_item = libvlc_media_list_sublist_at_path(
66 p_mlp->current_playing_item_path );
68 /* If item just gained a sublist just play it */
69 if( p_sublist_of_playing_item )
71 libvlc_media_list_release( p_sublist_of_playing_item );
72 return libvlc_media_list_path_copy_by_appending( p_mlp->current_playing_item_path, 0 );
75 /* Try to catch next element */
76 p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(
78 p_mlp->current_playing_item_path );
80 int deepness = libvlc_media_list_path_deepness( p_mlp->current_playing_item_path );
81 if( deepness < 1 || !p_parent_of_playing_item )
84 ret = libvlc_media_list_path_copy( p_mlp->current_playing_item_path );
86 while( ret[deepness-1] >= libvlc_media_list_count( p_parent_of_playing_item, NULL ) )
92 libvlc_media_list_release( p_parent_of_playing_item );
97 p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(
101 libvlc_media_list_release( p_parent_of_playing_item );
105 /**************************************************************************
106 * media_player_reached_end (private) (Event Callback)
107 **************************************************************************/
109 media_player_reached_end( const libvlc_event_t * p_event,
112 libvlc_media_list_player_t * p_mlp = p_user_data;
113 libvlc_media_player_t * p_mi = p_event->p_obj;
114 libvlc_media_t *p_md, * p_current_md;
116 p_md = libvlc_media_player_get_media( p_mi, NULL );
117 /* XXX: need if p_mlp->p_current_playing_index is beyond */
118 p_current_md = libvlc_media_list_item_at_path(
120 p_mlp->current_playing_item_path );
121 if( p_md != p_current_md )
123 msg_Warn( p_mlp->p_libvlc_instance->p_libvlc_int,
124 "We are not sync-ed with the media instance" );
125 libvlc_media_release( p_md );
126 libvlc_media_release( p_current_md );
129 libvlc_media_release( p_md );
130 libvlc_media_release( p_current_md );
131 libvlc_media_list_player_next( p_mlp, NULL );
134 /**************************************************************************
135 * playlist_item_deleted (private) (Event Callback)
136 **************************************************************************/
138 mlist_item_deleted( const libvlc_event_t * p_event, void * p_user_data )
140 libvlc_media_t * p_current_md;
141 libvlc_media_list_player_t * p_mlp = p_user_data;
142 libvlc_media_list_t * p_emitting_mlist = p_event->p_obj;
143 /* XXX: need if p_mlp->p_current_playing_index is beyond */
144 p_current_md = libvlc_media_list_item_at_path(
146 p_mlp->current_playing_item_path );
148 if( p_event->u.media_list_item_deleted.item == p_current_md &&
149 p_emitting_mlist == p_mlp->p_mlist )
151 /* We are playing this item, we choose to stop */
152 libvlc_media_list_player_stop( p_mlp, NULL );
156 /**************************************************************************
157 * install_playlist_observer (private)
158 **************************************************************************/
160 install_playlist_observer( libvlc_media_list_player_t * p_mlp )
162 libvlc_event_attach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
163 libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
166 /**************************************************************************
167 * uninstall_playlist_observer (private)
168 **************************************************************************/
170 uninstall_playlist_observer( libvlc_media_list_player_t * p_mlp )
172 if ( !p_mlp->p_mlist )
177 libvlc_event_detach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
178 libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
181 /**************************************************************************
182 * install_media_player_observer (private)
183 **************************************************************************/
185 install_media_player_observer( libvlc_media_list_player_t * p_mlp )
187 libvlc_event_attach( libvlc_media_player_event_manager( p_mlp->p_mi, NULL ),
188 libvlc_MediaPlayerEndReached,
189 media_player_reached_end, p_mlp, NULL );
193 /**************************************************************************
194 * uninstall_media_player_observer (private)
195 **************************************************************************/
197 uninstall_media_player_observer( libvlc_media_list_player_t * p_mlp )
204 libvlc_event_detach( libvlc_media_player_event_manager( p_mlp->p_mi, NULL ),
205 libvlc_MediaPlayerEndReached,
206 media_player_reached_end, p_mlp, NULL );
209 /**************************************************************************
210 * set_current_playing_item (private)
212 * Playlist lock should be held
213 **************************************************************************/
215 set_current_playing_item( libvlc_media_list_player_t * p_mlp,
216 libvlc_media_list_path_t path,
217 libvlc_exception_t * p_e )
221 libvlc_media_t * p_md;
223 p_md = libvlc_media_list_item_at_path( p_mlp->p_mlist, path );
224 vlc_mutex_lock( &p_mlp->object_lock );
226 if( p_mlp->current_playing_item_path != path )
228 free( p_mlp->current_playing_item_path );
229 p_mlp->current_playing_item_path = path;
234 vlc_mutex_unlock( &p_mlp->object_lock );
238 /* We are not interested in getting media stop event now */
239 uninstall_media_player_observer( p_mlp );
243 p_mlp->p_mi = libvlc_media_player_new_from_media(p_md, p_e);
246 if( p_md->p_subitems && libvlc_media_list_count( p_md->p_subitems, NULL ) > 0 )
248 libvlc_media_t * p_submd;
249 p_submd = libvlc_media_list_item_at_index( p_md->p_subitems, 0, NULL );
250 libvlc_media_player_set_media( p_mlp->p_mi, p_submd, NULL );
251 libvlc_media_release( p_submd );
254 libvlc_media_player_set_media( p_mlp->p_mi, p_md, NULL );
255 // wait_playing_state(); /* If we want to be synchronous */
256 install_media_player_observer( p_mlp );
258 vlc_mutex_unlock( &p_mlp->object_lock );
260 libvlc_media_release( p_md ); /* for libvlc_media_list_item_at_index */
264 * Public libvlc functions
267 /**************************************************************************
269 **************************************************************************/
270 libvlc_media_list_player_t *
271 libvlc_media_list_player_new( libvlc_instance_t * p_instance,
272 libvlc_exception_t * p_e )
275 libvlc_media_list_player_t * p_mlp;
276 p_mlp = malloc(sizeof(libvlc_media_list_player_t));
280 p_mlp->current_playing_item_path = NULL;
282 p_mlp->p_mlist = NULL;
283 vlc_mutex_init( &p_mlp->object_lock );
284 p_mlp->p_event_manager = libvlc_event_manager_new( p_mlp,
287 libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
288 libvlc_MediaListPlayerNextItemSet, p_e );
293 /**************************************************************************
295 **************************************************************************/
296 void libvlc_media_list_player_release( libvlc_media_list_player_t * p_mlp )
301 /**************************************************************************
302 * set_media_player (Public)
303 **************************************************************************/
304 void libvlc_media_list_player_set_media_player(
305 libvlc_media_list_player_t * p_mlp,
306 libvlc_media_player_t * p_mi,
307 libvlc_exception_t * p_e )
311 vlc_mutex_lock( &p_mlp->object_lock );
315 uninstall_media_player_observer( p_mlp );
316 libvlc_media_player_release( p_mlp->p_mi );
318 libvlc_media_player_retain( p_mi );
321 install_media_player_observer( p_mlp );
323 vlc_mutex_unlock( &p_mlp->object_lock );
326 /**************************************************************************
327 * set_media_list (Public)
328 **************************************************************************/
329 void libvlc_media_list_player_set_media_list(
330 libvlc_media_list_player_t * p_mlp,
331 libvlc_media_list_t * p_mlist,
332 libvlc_exception_t * p_e )
334 vlc_mutex_lock( &p_mlp->object_lock );
336 if( libvlc_media_list_player_is_playing( p_mlp, p_e ) )
338 libvlc_media_player_stop( p_mlp->p_mi, p_e );
339 /* Don't bother if there was an error. */
340 libvlc_exception_clear( p_e );
345 uninstall_playlist_observer( p_mlp );
346 libvlc_media_list_release( p_mlp->p_mlist );
348 libvlc_media_list_retain( p_mlist );
349 p_mlp->p_mlist = p_mlist;
351 install_playlist_observer( p_mlp );
353 vlc_mutex_unlock( &p_mlp->object_lock );
356 /**************************************************************************
358 **************************************************************************/
359 void libvlc_media_list_player_play( libvlc_media_list_player_t * p_mlp,
360 libvlc_exception_t * p_e )
362 if( !p_mlp->current_playing_item_path )
364 libvlc_media_list_player_next( p_mlp, p_e );
365 return; /* Will set to play */
368 libvlc_media_player_play( p_mlp->p_mi, p_e );
372 /**************************************************************************
374 **************************************************************************/
375 void libvlc_media_list_player_pause( libvlc_media_list_player_t * p_mlp,
376 libvlc_exception_t * p_e )
380 libvlc_media_player_pause( p_mlp->p_mi, p_e );
383 /**************************************************************************
384 * is_playing (Public)
385 **************************************************************************/
387 libvlc_media_list_player_is_playing( libvlc_media_list_player_t * p_mlp,
388 libvlc_exception_t * p_e )
390 libvlc_state_t state = libvlc_media_player_get_state( p_mlp->p_mi, p_e );
391 return (state == libvlc_Opening) || (state == libvlc_Buffering) ||
392 (state == libvlc_Playing);
395 /**************************************************************************
397 **************************************************************************/
399 libvlc_media_list_player_get_state( libvlc_media_list_player_t * p_mlp,
400 libvlc_exception_t * p_e )
404 return libvlc_media_player_get_state( p_mlp->p_mi, p_e );
407 /**************************************************************************
408 * Play item at index (Public)
409 **************************************************************************/
410 void libvlc_media_list_player_play_item_at_index(
411 libvlc_media_list_player_t * p_mlp,
413 libvlc_exception_t * p_e )
415 set_current_playing_item( p_mlp, libvlc_media_list_path_with_root_index(i_index), p_e );
417 if( libvlc_exception_raised( p_e ) )
420 /* Send the next item event */
421 libvlc_event_t event;
422 event.type = libvlc_MediaListPlayerNextItemSet;
423 libvlc_event_send( p_mlp->p_event_manager, &event );
425 libvlc_media_player_play( p_mlp->p_mi, p_e );
428 /**************************************************************************
430 **************************************************************************/
431 void libvlc_media_list_player_play_item(
432 libvlc_media_list_player_t * p_mlp,
433 libvlc_media_t * p_md,
434 libvlc_exception_t * p_e )
436 libvlc_media_list_path_t path = libvlc_media_list_path_of_item( p_mlp->p_mlist, p_md );
439 libvlc_exception_raise( p_e, "No such item in media list" );
442 set_current_playing_item( p_mlp, path, p_e );
444 if( libvlc_exception_raised( p_e ) )
447 libvlc_media_player_play( p_mlp->p_mi, p_e );
450 /**************************************************************************
452 **************************************************************************/
453 void libvlc_media_list_player_stop( libvlc_media_list_player_t * p_mlp,
454 libvlc_exception_t * p_e )
458 /* We are not interested in getting media stop event now */
459 uninstall_media_player_observer( p_mlp );
460 libvlc_media_player_stop( p_mlp->p_mi, p_e );
461 install_media_player_observer( p_mlp );
464 vlc_mutex_lock( &p_mlp->object_lock );
465 free( p_mlp->current_playing_item_path );
466 p_mlp->current_playing_item_path = NULL;
467 vlc_mutex_unlock( &p_mlp->object_lock );
470 /**************************************************************************
472 **************************************************************************/
473 void libvlc_media_list_player_next( libvlc_media_list_player_t * p_mlp,
474 libvlc_exception_t * p_e )
476 libvlc_media_list_path_t path;
478 if (! p_mlp->p_mlist )
480 libvlc_exception_raise( p_e, "No more element to play" );
484 libvlc_media_list_lock( p_mlp->p_mlist );
486 path = get_next_path( p_mlp );
490 libvlc_media_list_unlock( p_mlp->p_mlist );
491 libvlc_exception_raise( p_e, "No more element to play" );
492 libvlc_media_list_player_stop( p_mlp, p_e );
496 set_current_playing_item( p_mlp, path, p_e );
498 libvlc_media_player_play( p_mlp->p_mi, p_e );
500 libvlc_media_list_unlock( p_mlp->p_mlist );
502 /* Send the next item event */
503 libvlc_event_t event;
504 event.type = libvlc_MediaListPlayerNextItemSet;
505 libvlc_event_send( p_mlp->p_event_manager, &event);