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>
30 /**************************************************************************
31 * get_next_index (private)
33 * Simple next item fetcher.
34 **************************************************************************/
35 static int get_next_index( libvlc_media_list_player_t * p_mlp )
37 /* We are entered with libvlc_media_list_lock( p_mlp->p_list ) */
39 int next = p_mlp->i_current_playing_index + 1;
41 if( next >= libvlc_media_list_count( p_mlp->p_mlist, NULL ) )
42 return -1; /* no more to play */
47 /**************************************************************************
48 * media_instance_reached_end (private) (Event Callback)
49 **************************************************************************/
51 media_instance_reached_end( const libvlc_event_t * p_event,
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(
61 p_mlp->i_current_playing_index,
63 if( p_md != p_current_md )
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 );
71 libvlc_media_descriptor_release( p_md );
72 libvlc_media_descriptor_release( p_current_md );
73 libvlc_media_list_player_next( p_mlp, NULL );
76 /**************************************************************************
77 * playlist_item_deleted (private) (Event Callback)
78 **************************************************************************/
80 mlist_item_deleted( const libvlc_event_t * p_event, void * p_user_data )
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(
88 p_mlp->i_current_playing_index,
91 if( p_event->u.media_list_item_deleted.item == p_current_md &&
92 p_emitting_mlist == p_mlp->p_mlist )
94 /* We are playing this item, we choose to stop */
95 libvlc_media_list_player_stop( p_mlp, NULL );
99 /**************************************************************************
100 * install_playlist_observer (private)
101 **************************************************************************/
103 install_playlist_observer( libvlc_media_list_player_t * p_mlp )
105 libvlc_event_attach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
106 libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
109 /**************************************************************************
110 * uninstall_playlist_observer (private)
111 **************************************************************************/
113 uninstall_playlist_observer( libvlc_media_list_player_t * p_mlp )
115 libvlc_event_detach( libvlc_media_list_event_manager( p_mlp->p_mlist, NULL ),
116 libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp, NULL );
119 /**************************************************************************
120 * install_media_instance_observer (private)
121 **************************************************************************/
123 install_media_instance_observer( libvlc_media_list_player_t * p_mlp )
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 );
131 /**************************************************************************
132 * uninstall_media_instance_observer (private)
133 **************************************************************************/
135 uninstall_media_instance_observer( libvlc_media_list_player_t * p_mlp )
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 );
142 /**************************************************************************
144 **************************************************************************/
146 libvlc_media_list_player_is_playing( libvlc_media_list_player_t * p_mlp,
147 libvlc_exception_t * p_e )
149 libvlc_exception_raise( p_e, "Unimplemented" );
153 /**************************************************************************
156 * Playlist lock should be held
157 **************************************************************************/
159 media_list_player_set_next( libvlc_media_list_player_t * p_mlp, int index,
160 libvlc_exception_t * p_e )
162 libvlc_media_descriptor_t * p_md;
164 p_md = libvlc_media_list_item_at_index( p_mlp->p_mlist, index, p_e );
167 libvlc_media_list_unlock( p_mlp->p_mlist );
168 if( !libvlc_exception_raised( p_e ) )
169 libvlc_exception_raise( p_e, "Can't obtain a media" );
173 vlc_mutex_lock( &p_mlp->object_lock );
175 p_mlp->i_current_playing_index = index;
177 /* We are not interested in getting media_descriptor stop event now */
178 uninstall_media_instance_observer( p_mlp );
179 libvlc_media_instance_set_media_descriptor( p_mlp->p_mi, p_md, NULL );
180 // wait_playing_state(); /* If we want to be synchronous */
181 install_media_instance_observer( p_mlp );
183 vlc_mutex_unlock( &p_mlp->object_lock );
185 libvlc_media_list_unlock( p_mlp->p_mlist );
187 libvlc_media_descriptor_release( p_md ); /* for libvlc_media_list_item_at_index */
191 * Public libvlc functions
194 /**************************************************************************
196 **************************************************************************/
197 libvlc_media_list_player_t *
198 libvlc_media_list_player_new( libvlc_instance_t * p_instance,
199 libvlc_exception_t * p_e )
202 libvlc_media_list_player_t * p_mlp;
203 p_mlp = malloc(sizeof(libvlc_media_list_player_t));
204 p_mlp->i_current_playing_index = -1;
206 p_mlp->p_mlist = NULL;
207 vlc_mutex_init( p_instance->p_libvlc_int, &p_mlp->object_lock );
208 p_mlp->p_event_manager = libvlc_event_manager_new( p_mlp,
211 libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
212 libvlc_MediaListPlayerNextItemSet, p_e );
213 libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
214 libvlc_MediaListPlayerNextItemSet, p_e );
219 /**************************************************************************
221 **************************************************************************/
222 void libvlc_media_list_player_release( libvlc_media_list_player_t * p_mlp )
224 libvlc_event_manager_release( p_mlp->p_event_manager );
228 /**************************************************************************
229 * set_media_instance (Public)
230 **************************************************************************/
231 void libvlc_media_list_player_set_media_instance(
232 libvlc_media_list_player_t * p_mlp,
233 libvlc_media_instance_t * p_mi,
234 libvlc_exception_t * p_e )
236 vlc_mutex_lock( &p_mlp->object_lock );
240 uninstall_media_instance_observer( p_mlp );
241 libvlc_media_instance_release( p_mlp->p_mi );
243 libvlc_media_instance_retain( p_mi );
246 install_media_instance_observer( p_mlp );
248 vlc_mutex_unlock( &p_mlp->object_lock );
251 /**************************************************************************
252 * set_media_list (Public)
253 **************************************************************************/
254 void libvlc_media_list_player_set_media_list(
255 libvlc_media_list_player_t * p_mlp,
256 libvlc_media_list_t * p_mlist,
257 libvlc_exception_t * p_e )
259 vlc_mutex_lock( &p_mlp->object_lock );
261 if( libvlc_media_list_player_is_playing( p_mlp, p_e ) )
262 libvlc_media_list_player_stop( p_mlp, p_e );
266 uninstall_playlist_observer( p_mlp );
267 libvlc_media_list_release( p_mlp->p_mlist );
269 libvlc_media_list_retain( p_mlist );
270 p_mlp->p_mlist = p_mlist;
272 install_playlist_observer( p_mlp );
274 vlc_mutex_unlock( &p_mlp->object_lock );
277 /**************************************************************************
279 **************************************************************************/
280 void libvlc_media_list_player_play( libvlc_media_list_player_t * p_mlp,
281 libvlc_exception_t * p_e )
283 if( p_mlp->i_current_playing_index < 0 )
285 libvlc_media_list_player_next( p_mlp, p_e );
286 return; /* Will set to play */
289 libvlc_media_instance_play( p_mlp->p_mi, p_e );
292 /**************************************************************************
293 * Play item at index (Public)
295 * Playlist lock should be help
296 **************************************************************************/
297 void libvlc_media_list_player_play_item_at_index(
298 libvlc_media_list_player_t * p_mlp,
300 libvlc_exception_t * p_e )
302 media_list_player_set_next( p_mlp, i_index, p_e );
304 if( libvlc_exception_raised( p_e ) )
307 /* Send the next item event */
308 libvlc_event_t event;
309 event.type = libvlc_MediaListPlayerNextItemSet;
310 libvlc_event_send( p_mlp->p_event_manager, &event );
312 libvlc_media_instance_play( p_mlp->p_mi, p_e );
316 /**************************************************************************
318 **************************************************************************/
319 void libvlc_media_list_player_stop( libvlc_media_list_player_t * p_mlp,
320 libvlc_exception_t * p_e )
322 libvlc_media_instance_stop( p_mlp->p_mi, p_e );
324 vlc_mutex_lock( &p_mlp->object_lock );
325 p_mlp->i_current_playing_index = -1;
326 vlc_mutex_unlock( &p_mlp->object_lock );
329 /**************************************************************************
331 **************************************************************************/
332 void libvlc_media_list_player_next( libvlc_media_list_player_t * p_mlp,
333 libvlc_exception_t * p_e )
337 libvlc_media_list_lock( p_mlp->p_mlist );
339 index = get_next_index( p_mlp );
343 libvlc_media_list_unlock( p_mlp->p_mlist );
344 libvlc_exception_raise( p_e, "No more element to play" );
345 libvlc_media_list_player_stop( p_mlp, p_e );
349 media_list_player_set_next( p_mlp, index, p_e );
351 libvlc_media_instance_play( p_mlp->p_mi, p_e );
353 libvlc_media_list_unlock( p_mlp->p_mlist );
355 /* Send the next item event */
356 libvlc_event_t event;
357 event.type = libvlc_MediaListPlayerNextItemSet;
358 libvlc_event_send( p_mlp->p_event_manager, &event);