skins2: use new vout_window_ReportSize
[vlc.git] / lib / media_list_player.c
blob9ac935a716f09b4cb42de1b9ddfb6e41454a93be
1 /*****************************************************************************
2 * media_list_player.c: libvlc new API media_list player functions
3 *****************************************************************************
4 * Copyright (C) 2007 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <vlc/libvlc.h>
29 #include <vlc/libvlc_media.h>
30 #include <vlc/libvlc_media_list.h>
31 #include <vlc/libvlc_media_player.h>
32 #include <vlc/libvlc_media_list_player.h>
33 #include <vlc/libvlc_events.h>
34 #include <assert.h>
36 #include "libvlc_internal.h"
38 #include "media_internal.h" // Abuse, could and should be removed
39 #include "media_list_path.h"
41 //#define DEBUG_MEDIA_LIST_PLAYER
43 /* This is a very dummy implementation of playlist on top of
44 * media_list and media_player.
46 * All this code is doing is simply computing the next item
47 * of a tree of media_list (see get_next_index()), and play
48 * the next item when the current is over. This is happening
49 * via the event callback media_player_reached_end().
51 * This is thread safe, and we use a two keys (locks) scheme
52 * to discriminate between callbacks and regular uses.
55 struct libvlc_media_list_player_t
57 libvlc_event_manager_t * p_event_manager;
58 libvlc_instance_t * p_libvlc_instance;
59 int i_refcount;
60 /* Protect access to this structure. */
61 vlc_mutex_t object_lock;
62 /* Protect access to this structure and from callback execution. */
63 vlc_mutex_t mp_callback_lock;
64 /* Indicate to media player callbacks that they are cancelled. */
65 bool are_mp_callback_cancelled;
66 libvlc_media_list_path_t current_playing_item_path;
67 libvlc_media_t * p_current_playing_item;
68 libvlc_media_list_t * p_mlist;
69 libvlc_media_player_t * p_mi;
70 libvlc_playback_mode_t e_playback_mode;
73 /* This is not yet exported by libvlccore */
74 static inline void vlc_assert_locked(vlc_mutex_t *mutex)
76 VLC_UNUSED(mutex);
80 * Forward declaration
83 static
84 int set_relative_playlist_position_and_play(libvlc_media_list_player_t *p_mlp,
85 int i_relative_position);
86 static void stop(libvlc_media_list_player_t * p_mlp);
89 * Private functions
92 /**************************************************************************
93 * Shortcuts
94 **************************************************************************/
95 static inline void lock(libvlc_media_list_player_t * p_mlp)
97 // Obtain an access to this structure
98 vlc_mutex_lock(&p_mlp->object_lock);
100 // Make sure no callback will occurs at the same time
101 vlc_mutex_lock(&p_mlp->mp_callback_lock);
104 static inline void unlock(libvlc_media_list_player_t * p_mlp)
106 vlc_mutex_unlock(&p_mlp->mp_callback_lock);
107 vlc_mutex_unlock(&p_mlp->object_lock);
110 static inline void assert_locked(libvlc_media_list_player_t * p_mlp)
112 vlc_assert_locked(&p_mlp->mp_callback_lock);
115 static inline libvlc_event_manager_t * mlist_em(libvlc_media_list_player_t * p_mlp)
117 assert_locked(p_mlp);
118 return libvlc_media_list_event_manager(p_mlp->p_mlist);
121 static inline libvlc_event_manager_t * mplayer_em(libvlc_media_list_player_t * p_mlp)
123 assert_locked(p_mlp);
124 return libvlc_media_player_event_manager(p_mlp->p_mi);
127 /**************************************************************************
128 * get_next_path (private)
130 * Returns the path to the next item in the list.
131 * If looping is specified and the current item is the last list item in
132 * the list it will return the first item in the list.
133 **************************************************************************/
134 static libvlc_media_list_path_t
135 get_next_path(libvlc_media_list_player_t * p_mlp, bool b_loop)
137 assert_locked(p_mlp);
139 /* We are entered with libvlc_media_list_lock(p_mlp->p_list) */
140 libvlc_media_list_path_t ret;
141 libvlc_media_list_t * p_parent_of_playing_item;
142 libvlc_media_list_t * p_sublist_of_playing_item;
144 if (!p_mlp->current_playing_item_path)
146 if (!libvlc_media_list_count(p_mlp->p_mlist))
147 return NULL;
148 return libvlc_media_list_path_with_root_index(0);
151 p_sublist_of_playing_item = libvlc_media_list_sublist_at_path(
152 p_mlp->p_mlist,
153 p_mlp->current_playing_item_path);
155 /* If item just gained a sublist just play it */
156 if (p_sublist_of_playing_item)
158 libvlc_media_list_release(p_sublist_of_playing_item);
159 return libvlc_media_list_path_copy_by_appending(p_mlp->current_playing_item_path, 0);
162 /* Try to catch parent element */
163 p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(p_mlp->p_mlist,
164 p_mlp->current_playing_item_path);
166 int depth = libvlc_media_list_path_depth(p_mlp->current_playing_item_path);
167 if (depth < 1 || !p_parent_of_playing_item)
168 return NULL;
170 ret = libvlc_media_list_path_copy(p_mlp->current_playing_item_path);
171 ret[depth - 1]++; /* set to next element */
173 /* If this goes beyond the end of the list */
174 while(ret[depth-1] >= libvlc_media_list_count(p_parent_of_playing_item))
176 depth--;
177 if (depth <= 0)
179 if(b_loop)
181 ret[0] = 0;
182 ret[1] = -1;
183 break;
185 else
187 free(ret);
188 libvlc_media_list_release(p_parent_of_playing_item);
189 return NULL;
192 ret[depth] = -1;
193 ret[depth-1]++;
194 p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(
195 p_mlp->p_mlist,
196 ret);
199 libvlc_media_list_release(p_parent_of_playing_item);
200 return ret;
203 /**************************************************************************
204 * find_last_item (private)
206 * Returns the path of the last descendant of a given item path.
207 * Note: Due to the recursive nature of the function and the need to free
208 * media list paths, paths passed in may be freed if they are replaced.
209 Recommended usage is to set return value to the same path that was
210 passed to the function (i.e. item = find_last_item(list, item); )
211 **************************************************************************/
212 static libvlc_media_list_path_t
213 find_last_item( libvlc_media_list_t * p_mlist, libvlc_media_list_path_t current_item )
215 libvlc_media_list_t * p_sublist = libvlc_media_list_sublist_at_path(p_mlist, current_item);
216 libvlc_media_list_path_t last_item_path = current_item;
218 if(p_sublist)
220 int i_count = libvlc_media_list_count(p_sublist);
221 if(i_count > 0)
223 /* Add the last sublist item to the path. */
224 last_item_path = libvlc_media_list_path_copy_by_appending(current_item, i_count - 1);
225 free(current_item);
226 /* Check that sublist item for more descendants. */
227 last_item_path = find_last_item(p_mlist, last_item_path);
230 libvlc_media_list_release(p_sublist);
233 return last_item_path;
236 /**************************************************************************
237 * get_previous_path (private)
239 * Returns the path to the preceding item in the list.
240 * If looping is specified and the current item is the first list item in
241 * the list it will return the last descendant of the last item in the list.
242 **************************************************************************/
243 static libvlc_media_list_path_t
244 get_previous_path(libvlc_media_list_player_t * p_mlp, bool b_loop)
246 assert_locked(p_mlp);
248 /* We are entered with libvlc_media_list_lock(p_mlp->p_list) */
249 libvlc_media_list_path_t ret;
250 libvlc_media_list_t * p_parent_of_playing_item;
252 if (!p_mlp->current_playing_item_path)
254 if (!libvlc_media_list_count(p_mlp->p_mlist))
255 return NULL;
256 return libvlc_media_list_path_with_root_index(0);
259 /* Try to catch parent element */
260 p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(
261 p_mlp->p_mlist,
262 p_mlp->current_playing_item_path);
264 int depth = libvlc_media_list_path_depth(p_mlp->current_playing_item_path);
265 if (depth < 1 || !p_parent_of_playing_item)
266 return NULL;
268 /* Set the return path to the current path */
269 ret = libvlc_media_list_path_copy(p_mlp->current_playing_item_path);
271 /* Change the return path to the previous list entry */
272 ret[depth - 1]--; /* set to previous element */
273 ret[depth] = -1;
275 /* Is the return path is beyond the start of the current list? */
276 if(ret[depth - 1] < 0)
278 /* Move to parent of current item */
279 depth--;
281 /* Are we at the root level of the tree? */
282 if (depth <= 0)
284 // Is looping enabled?
285 if(b_loop)
287 int i_count = libvlc_media_list_count(p_parent_of_playing_item);
289 /* Set current play item to the last element in the list */
290 ret[0] = i_count - 1;
291 ret[1] = -1;
293 /* Set the return path to the last descendant item of the current item */
294 ret = find_last_item(p_mlp->p_mlist, ret);
296 else
298 /* No looping so return empty path. */
299 free(ret);
300 ret = NULL;
303 else
305 /* This is the case of moving backward from the beginning of the
306 * subitem list to its parent item.
307 * This ensures that current path is properly terminated to
308 * use that parent.
310 ret[depth] = -1;
313 else
315 ret = find_last_item(p_mlp->p_mlist, ret);
318 libvlc_media_list_release(p_parent_of_playing_item);
319 return ret;
322 /**************************************************************************
323 * media_player_reached_end (private) (Event Callback)
324 **************************************************************************/
325 static void
326 media_player_reached_end(const libvlc_event_t * p_event, void * p_user_data)
328 VLC_UNUSED(p_event);
329 libvlc_media_list_player_t * p_mlp = p_user_data;
331 vlc_mutex_lock(&p_mlp->mp_callback_lock);
332 if (!p_mlp->are_mp_callback_cancelled)
333 set_relative_playlist_position_and_play(p_mlp, 1);
334 vlc_mutex_unlock(&p_mlp->mp_callback_lock);
337 /**************************************************************************
338 * playlist_item_deleted (private) (Event Callback)
339 **************************************************************************/
340 static void
341 mlist_item_deleted(const libvlc_event_t * p_event, void * p_user_data)
343 // Nothing to do. For now.
344 (void)p_event; (void)p_user_data;
348 /**************************************************************************
349 * install_playlist_observer (private)
350 **************************************************************************/
351 static void
352 install_playlist_observer(libvlc_media_list_player_t * p_mlp)
354 assert_locked(p_mlp);
355 libvlc_event_attach(mlist_em(p_mlp), libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp);
358 /**************************************************************************
359 * uninstall_playlist_observer (private)
360 **************************************************************************/
361 static void
362 uninstall_playlist_observer(libvlc_media_list_player_t * p_mlp)
364 assert_locked(p_mlp);
365 if (!p_mlp->p_mlist) return;
366 libvlc_event_detach(mlist_em(p_mlp), libvlc_MediaListItemDeleted, mlist_item_deleted, p_mlp);
369 /**************************************************************************
370 * install_media_player_observer (private)
371 **************************************************************************/
372 static void
373 install_media_player_observer(libvlc_media_list_player_t * p_mlp)
375 assert_locked(p_mlp);
376 libvlc_event_attach_async(mplayer_em(p_mlp), libvlc_MediaPlayerEndReached, media_player_reached_end, p_mlp);
380 /**************************************************************************
381 * uninstall_media_player_observer (private)
382 **************************************************************************/
383 static void
384 uninstall_media_player_observer(libvlc_media_list_player_t * p_mlp)
386 assert_locked(p_mlp);
387 if (!p_mlp->p_mi) return;
389 // From now on, media_player callback won't be relevant.
390 p_mlp->are_mp_callback_cancelled = true;
392 // Allow callbacks to run, because detach() will wait until all callbacks are processed.
393 // This is safe because only callbacks are allowed, and there execution will be cancelled.
394 vlc_mutex_unlock(&p_mlp->mp_callback_lock);
395 libvlc_event_detach(mplayer_em(p_mlp), libvlc_MediaPlayerEndReached, media_player_reached_end, p_mlp);
397 // Now, lock back the callback lock. No more callback will be present from this point.
398 vlc_mutex_lock(&p_mlp->mp_callback_lock);
399 p_mlp->are_mp_callback_cancelled = false;
401 // What is here is safe, because we guarantee that we won't be able to anything concurrently,
402 // - except (cancelled) callbacks - thanks to the object_lock.
405 /**************************************************************************
406 * set_current_playing_item (private)
408 * Playlist lock should be held
409 **************************************************************************/
410 static void
411 set_current_playing_item(libvlc_media_list_player_t * p_mlp, libvlc_media_list_path_t path)
413 assert_locked(p_mlp);
415 /* First, save the new path that we are going to play */
416 if (p_mlp->current_playing_item_path != path)
418 free(p_mlp->current_playing_item_path);
419 p_mlp->current_playing_item_path = path;
422 if (!path)
423 return;
425 libvlc_media_t * p_md;
426 p_md = libvlc_media_list_item_at_path(p_mlp->p_mlist, path);
427 if (!p_md)
428 return;
430 /* Make sure media_player_reached_end() won't get called */
431 uninstall_media_player_observer(p_mlp);
433 /* Create a new media_player if there is none */
434 if (!p_mlp->p_mi)
435 p_mlp->p_mi = libvlc_media_player_new_from_media(p_md);
437 libvlc_media_player_set_media(p_mlp->p_mi, p_md);
439 install_media_player_observer(p_mlp);
440 libvlc_media_release(p_md); /* for libvlc_media_list_item_at_index */
444 * Public libvlc functions
447 /**************************************************************************
448 * new (Public)
449 **************************************************************************/
450 libvlc_media_list_player_t *
451 libvlc_media_list_player_new(libvlc_instance_t * p_instance)
453 libvlc_media_list_player_t * p_mlp;
454 p_mlp = calloc( 1, sizeof(libvlc_media_list_player_t) );
455 if (unlikely(p_mlp == NULL))
457 libvlc_printerr("Not enough memory");
458 return NULL;
461 p_mlp->p_event_manager = libvlc_event_manager_new(p_mlp, p_instance);
462 if (unlikely(p_mlp->p_event_manager == NULL))
464 free (p_mlp);
465 return NULL;
468 libvlc_retain(p_instance);
469 p_mlp->p_libvlc_instance = p_instance;
470 p_mlp->i_refcount = 1;
471 vlc_mutex_init(&p_mlp->object_lock);
472 vlc_mutex_init(&p_mlp->mp_callback_lock);
473 libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
474 libvlc_MediaListPlayerNextItemSet );
475 libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
476 libvlc_MediaListPlayerStopped );
477 libvlc_event_manager_register_event_type( p_mlp->p_event_manager,
478 libvlc_MediaListPlayerPlayed );
479 p_mlp->e_playback_mode = libvlc_playback_mode_default;
481 return p_mlp;
484 /**************************************************************************
485 * release (Public)
486 **************************************************************************/
487 void libvlc_media_list_player_release(libvlc_media_list_player_t * p_mlp)
489 if (!p_mlp)
490 return;
492 lock(p_mlp);
493 p_mlp->i_refcount--;
494 if (p_mlp->i_refcount > 0)
496 unlock(p_mlp);
497 return;
500 assert(p_mlp->i_refcount == 0);
502 /* Keep the lock(), because the uninstall functions
503 * check for it. That's convenient. */
505 if (p_mlp->p_mi)
507 uninstall_media_player_observer(p_mlp);
508 libvlc_media_player_release(p_mlp->p_mi);
510 if (p_mlp->p_mlist)
512 uninstall_playlist_observer(p_mlp);
513 libvlc_media_list_release(p_mlp->p_mlist);
516 unlock(p_mlp);
517 vlc_mutex_destroy(&p_mlp->object_lock);
518 vlc_mutex_destroy(&p_mlp->mp_callback_lock);
520 libvlc_event_manager_release(p_mlp->p_event_manager);
522 free(p_mlp->current_playing_item_path);
523 libvlc_release(p_mlp->p_libvlc_instance);
524 free(p_mlp);
527 /**************************************************************************
528 * retain (Public)
529 **************************************************************************/
530 void libvlc_media_list_player_retain(libvlc_media_list_player_t * p_mlp)
532 if (!p_mlp)
533 return;
535 lock(p_mlp);
536 p_mlp->i_refcount++;
537 unlock(p_mlp);
540 /**************************************************************************
541 * event_manager (Public)
542 **************************************************************************/
543 libvlc_event_manager_t *
544 libvlc_media_list_player_event_manager(libvlc_media_list_player_t * p_mlp)
546 return p_mlp->p_event_manager;
549 /**************************************************************************
550 * set_media_player (Public)
551 **************************************************************************/
552 void libvlc_media_list_player_set_media_player(libvlc_media_list_player_t * p_mlp, libvlc_media_player_t * p_mi)
554 lock(p_mlp);
556 if (p_mlp->p_mi)
558 uninstall_media_player_observer(p_mlp);
559 libvlc_media_player_release(p_mlp->p_mi);
561 libvlc_media_player_retain(p_mi);
562 p_mlp->p_mi = p_mi;
564 install_media_player_observer(p_mlp);
566 unlock(p_mlp);
569 /**************************************************************************
570 * set_media_list (Public)
571 **************************************************************************/
572 void libvlc_media_list_player_set_media_list(libvlc_media_list_player_t * p_mlp, libvlc_media_list_t * p_mlist)
574 assert (p_mlist);
576 lock(p_mlp);
577 if (p_mlp->p_mlist)
579 uninstall_playlist_observer(p_mlp);
580 libvlc_media_list_release(p_mlp->p_mlist);
582 libvlc_media_list_retain(p_mlist);
583 p_mlp->p_mlist = p_mlist;
585 install_playlist_observer(p_mlp);
587 unlock(p_mlp);
590 /**************************************************************************
591 * Play (Public)
592 **************************************************************************/
593 void libvlc_media_list_player_play(libvlc_media_list_player_t * p_mlp)
595 lock(p_mlp);
596 if (!p_mlp->current_playing_item_path)
598 set_relative_playlist_position_and_play(p_mlp, 1);
599 unlock(p_mlp);
600 return; /* Will set to play */
602 libvlc_media_player_play(p_mlp->p_mi);
603 unlock(p_mlp);
607 /**************************************************************************
608 * Pause (Public)
609 **************************************************************************/
610 void libvlc_media_list_player_pause(libvlc_media_list_player_t * p_mlp)
612 lock(p_mlp);
613 if (!p_mlp->p_mi)
615 unlock(p_mlp);
616 return;
618 libvlc_media_player_pause(p_mlp->p_mi);
619 unlock(p_mlp);
622 /**************************************************************************
623 * is_playing (Public)
624 **************************************************************************/
626 libvlc_media_list_player_is_playing(libvlc_media_list_player_t * p_mlp)
628 if (!p_mlp->p_mi)
630 return libvlc_NothingSpecial;
632 libvlc_state_t state = libvlc_media_player_get_state(p_mlp->p_mi);
633 return (state == libvlc_Opening) || (state == libvlc_Buffering) ||
634 (state == libvlc_Playing);
637 /**************************************************************************
638 * State (Public)
639 **************************************************************************/
640 libvlc_state_t
641 libvlc_media_list_player_get_state(libvlc_media_list_player_t * p_mlp)
643 if (!p_mlp->p_mi)
644 return libvlc_Ended;
645 return libvlc_media_player_get_state(p_mlp->p_mi);
648 /**************************************************************************
649 * Play item at index (Public)
650 **************************************************************************/
651 int libvlc_media_list_player_play_item_at_index(libvlc_media_list_player_t * p_mlp, int i_index)
653 lock(p_mlp);
654 libvlc_media_list_path_t path = libvlc_media_list_path_with_root_index(i_index);
655 set_current_playing_item(p_mlp, path);
656 libvlc_media_player_play(p_mlp->p_mi);
657 unlock(p_mlp);
659 /* Send the next item event */
660 libvlc_event_t event;
661 event.type = libvlc_MediaListPlayerNextItemSet;
662 libvlc_media_t * p_md = libvlc_media_list_item_at_path(p_mlp->p_mlist, path);
663 event.u.media_list_player_next_item_set.item = p_md;
664 libvlc_event_send(p_mlp->p_event_manager, &event);
665 libvlc_media_release(p_md);
666 return 0;
669 /**************************************************************************
670 * Play item (Public)
671 **************************************************************************/
672 int libvlc_media_list_player_play_item(libvlc_media_list_player_t * p_mlp, libvlc_media_t * p_md)
674 lock(p_mlp);
675 libvlc_media_list_path_t path = libvlc_media_list_path_of_item(p_mlp->p_mlist, p_md);
676 if (!path)
678 libvlc_printerr("Item not found in media list");
679 unlock(p_mlp);
680 return -1;
683 set_current_playing_item(p_mlp, path);
684 libvlc_media_player_play(p_mlp->p_mi);
685 unlock(p_mlp);
686 return 0;
689 /**************************************************************************
690 * Stop (Private)
692 * Lock must be held.
693 **************************************************************************/
694 static void stop(libvlc_media_list_player_t * p_mlp)
696 assert_locked(p_mlp);
698 if (p_mlp->p_mi)
700 /* We are not interested in getting media stop event now */
701 uninstall_media_player_observer(p_mlp);
702 libvlc_media_player_stop(p_mlp->p_mi);
703 install_media_player_observer(p_mlp);
706 free(p_mlp->current_playing_item_path);
707 p_mlp->current_playing_item_path = NULL;
709 /* Send the event */
710 libvlc_event_t event;
711 event.type = libvlc_MediaListPlayerStopped;
712 libvlc_event_send(p_mlp->p_event_manager, &event);
715 /**************************************************************************
716 * Stop (Public)
717 **************************************************************************/
718 void libvlc_media_list_player_stop(libvlc_media_list_player_t * p_mlp)
720 lock(p_mlp);
721 stop(p_mlp);
722 unlock(p_mlp);
725 /**************************************************************************
726 * Set relative playlist position and play (Private)
728 * Sets the currently played item to the given relative play item position
729 * (based on the currently playing item) and then begins the new item playback.
730 * Lock must be held.
731 **************************************************************************/
732 static int set_relative_playlist_position_and_play(
733 libvlc_media_list_player_t * p_mlp,
734 int i_relative_position)
736 assert_locked(p_mlp);
738 if (!p_mlp->p_mlist)
740 libvlc_printerr("No media list");
741 return -1;
744 libvlc_media_list_lock(p_mlp->p_mlist);
746 libvlc_media_list_path_t path = p_mlp->current_playing_item_path;
748 if(p_mlp->e_playback_mode != libvlc_playback_mode_repeat)
750 bool b_loop = (p_mlp->e_playback_mode == libvlc_playback_mode_loop);
752 if(i_relative_position > 0)
756 path = get_next_path(p_mlp, b_loop);
757 set_current_playing_item(p_mlp, path);
758 --i_relative_position;
760 while(i_relative_position > 0);
762 else if(i_relative_position < 0)
766 path = get_previous_path(p_mlp, b_loop);
767 set_current_playing_item(p_mlp, path);
768 ++i_relative_position;
770 while (i_relative_position < 0);
773 else
775 set_current_playing_item(p_mlp, path);
778 #ifdef DEBUG_MEDIA_LIST_PLAYER
779 printf("Playing:");
780 libvlc_media_list_path_dump(path);
781 #endif
783 if (!path)
785 libvlc_media_list_unlock(p_mlp->p_mlist);
786 /* Send list played event */
787 libvlc_event_t event;
788 event.type = libvlc_MediaListPlayerPlayed;
789 libvlc_event_send(p_mlp->p_event_manager, &event);
790 return -1;
793 libvlc_media_player_play(p_mlp->p_mi);
795 libvlc_media_list_unlock(p_mlp->p_mlist);
797 /* Send the next item event */
798 libvlc_event_t event;
799 event.type = libvlc_MediaListPlayerNextItemSet;
800 libvlc_media_t * p_md = libvlc_media_list_item_at_path(p_mlp->p_mlist, path);
801 event.u.media_list_player_next_item_set.item = p_md;
802 libvlc_event_send(p_mlp->p_event_manager, &event);
803 libvlc_media_release(p_md);
804 return 0;
807 /**************************************************************************
808 * Next (Public)
809 **************************************************************************/
810 int libvlc_media_list_player_next(libvlc_media_list_player_t * p_mlp)
812 lock(p_mlp);
813 int failure = set_relative_playlist_position_and_play(p_mlp, 1);
814 unlock(p_mlp);
815 return failure;
818 /**************************************************************************
819 * Previous (Public)
820 **************************************************************************/
821 int libvlc_media_list_player_previous(libvlc_media_list_player_t * p_mlp)
823 lock(p_mlp);
824 int failure = set_relative_playlist_position_and_play(p_mlp, -1);
825 unlock(p_mlp);
826 return failure;
829 /**************************************************************************
830 * Set Playback Mode (Public)
831 **************************************************************************/
832 void libvlc_media_list_player_set_playback_mode(
833 libvlc_media_list_player_t * p_mlp,
834 libvlc_playback_mode_t e_mode )
836 lock(p_mlp);
837 p_mlp->e_playback_mode = e_mode;
838 unlock(p_mlp);