+
+ libvlc_media_list_release(p_parent_of_playing_item);
+ return ret;
+}
+
+/**************************************************************************
+ * find_last_item (private)
+ *
+ * Returns the path of the last descendant of a given item path.
+ * Note: Due to the recursive nature of the function and the need to free
+ * media list paths, paths passed in may be freed if they are replaced.
+ Recommended usage is to set return value to the same path that was
+ passed to the function (i.e. item = find_last_item(list, item); )
+ **************************************************************************/
+static libvlc_media_list_path_t
+find_last_item( libvlc_media_list_t * p_mlist, libvlc_media_list_path_t current_item )
+{
+ libvlc_media_list_t * p_sublist = libvlc_media_list_sublist_at_path(p_mlist, current_item);
+ libvlc_media_list_path_t last_item_path = current_item;
+
+ if(p_sublist)
+ {
+ int i_count = libvlc_media_list_count(p_sublist);
+ if(i_count > 0)
+ {
+ /* Add the last sublist item to the path. */
+ last_item_path = libvlc_media_list_path_copy_by_appending(current_item, i_count - 1);
+ free(current_item);
+ /* Check that sublist item for more descendants. */
+ last_item_path = find_last_item(p_mlist, last_item_path);
+ }
+
+ libvlc_media_list_release(p_sublist);
+ }
+
+ return last_item_path;
+}
+
+/**************************************************************************
+ * get_previous_path (private)
+ *
+ * Returns the path to the preceding item in the list.
+ * If looping is specified and the current item is the first list item in
+ * the list it will return the last descendant of the last item in the list.
+ **************************************************************************/
+static libvlc_media_list_path_t
+get_previous_path(libvlc_media_list_player_t * p_mlp, bool b_loop)
+{
+ assert_locked(p_mlp);
+
+ /* We are entered with libvlc_media_list_lock(p_mlp->p_list) */
+ libvlc_media_list_path_t ret;
+ libvlc_media_list_t * p_parent_of_playing_item;
+
+ if (!p_mlp->current_playing_item_path)
+ {
+ if (!libvlc_media_list_count(p_mlp->p_mlist))
+ return NULL;
+ return libvlc_media_list_path_with_root_index(0);
+ }
+
+ /* Try to catch parent element */
+ p_parent_of_playing_item = libvlc_media_list_parentlist_at_path(
+ p_mlp->p_mlist,
+ p_mlp->current_playing_item_path);
+
+ int depth = libvlc_media_list_path_depth(p_mlp->current_playing_item_path);
+ if (depth < 1 || !p_parent_of_playing_item)
+ return NULL;
+
+ /* Set the return path to the current path */
+ ret = libvlc_media_list_path_copy(p_mlp->current_playing_item_path);
+
+ /* Change the return path to the previous list entry */
+ ret[depth - 1]--; /* set to previous element */
+ ret[depth] = -1;
+
+ /* Is the return path is beyond the start of the current list? */
+ if(ret[depth - 1] < 0)
+ {
+ /* Move to parent of current item */
+ depth--;
+
+ /* Are we at the root level of the tree? */
+ if (depth <= 0)
+ {
+ // Is looping enabled?
+ if(b_loop)
+ {
+ int i_count = libvlc_media_list_count(p_parent_of_playing_item);
+
+ /* Set current play item to the last element in the list */
+ ret[0] = i_count - 1;
+ ret[1] = -1;
+
+ /* Set the return path to the last descendant item of the current item */
+ ret = find_last_item(p_mlp->p_mlist, ret);
+ }
+ else
+ {
+ /* No looping so return empty path. */
+ free(ret);
+ ret = NULL;
+ }
+ }
+ else
+ {
+ /* This is the case of moving backward from the beginning of the
+ * subitem list to its parent item.
+ * This ensures that current path is properly terminated to
+ * use that parent.
+ */
+ ret[depth] = -1;
+ }
+ }
+ else
+ {
+ ret = find_last_item(p_mlp->p_mlist, ret);
+ }
+