]> git.sesse.net Git - vlc/blobdiff - src/playlist/playlist.c
* src/playlist/playlist.c: fixed deadlock in playlist.
[vlc] / src / playlist / playlist.c
index a72b9f3e46981713a9b0687450479ea5f7a4eedc..e5c15c1118428607ea97ab4e7a2f7842fe711ede 100644 (file)
@@ -2,7 +2,7 @@
  * playlist.c : Playlist management functions
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: playlist.c,v 1.8 2002/06/07 19:54:37 sam Exp $
+ * $Id: playlist.c,v 1.23 2002/11/21 15:51:57 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
 #include <stdlib.h>                                      /* free(), strtol() */
 #include <stdio.h>                                              /* sprintf() */
 #include <string.h>                                            /* strerror() */
-#include <errno.h>                                                 /* ENOMEM */
 
 #include <vlc/vlc.h>
 
 #include "stream_control.h"
 #include "input_ext-intf.h"
 
-#include "playlist.h"
+#include "vlc_playlist.h"
 
 #define PLAYLIST_STOPPED 0
 #define PLAYLIST_RUNNING 1
@@ -62,12 +61,13 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent )
     }
 
     p_playlist->p_input = NULL;
-    p_playlist->i_status = PLAYLIST_RUNNING;
+    p_playlist->i_status = PLAYLIST_STOPPED;
     p_playlist->i_index = -1;
     p_playlist->i_size = 0;
     p_playlist->pp_items = NULL;
 
-    if( vlc_thread_create( p_playlist, "playlist", RunThread, VLC_TRUE ) )
+    if( vlc_thread_create( p_playlist, "playlist", RunThread,
+                           VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
     {
         msg_Err( p_playlist, "cannot spawn playlist thread" );
         vlc_object_destroy( p_playlist );
@@ -105,7 +105,7 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
 {
     playlist_item_t *p_item;
 
-    msg_Warn( p_playlist, "adding playlist item « %s »", psz_target );
+    msg_Dbg( p_playlist, "adding playlist item « %s »", psz_target );
 
     /* Create the new playlist item */
     p_item = malloc( sizeof( playlist_item_t ) );
@@ -117,6 +117,7 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
     p_item->psz_name = strdup( psz_target );
     p_item->i_type = 0;
     p_item->i_status = 0;
+    p_item->b_autodeletion = VLC_FALSE;
 
     vlc_mutex_lock( &p_playlist->object_lock );
 
@@ -135,20 +136,6 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
     if( !(i_mode & PLAYLIST_REPLACE)
          || i_pos < 0 || i_pos >= p_playlist->i_size )
     {
-        int i_index;
-
-        p_playlist->i_size++;
-        p_playlist->pp_items = realloc( p_playlist->pp_items,
-                                        p_playlist->i_size * sizeof(void*) );
-        if( p_playlist->pp_items == NULL )
-        {
-            msg_Err( p_playlist, "out of memory" );
-            free( p_item->psz_name );
-            free( p_item );
-            vlc_mutex_unlock( &p_playlist->object_lock );
-            return -1;
-        }
-
         /* Additional boundary checks */
         if( i_mode & PLAYLIST_APPEND )
         {
@@ -159,16 +146,15 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
         {
             i_pos = 0;
         }
-        else if( i_pos > p_playlist->i_size - 1 )
+        else if( i_pos > p_playlist->i_size )
         {
-            i_pos = p_playlist->i_size - 1;
+            i_pos = p_playlist->i_size;
         }
 
-        /* Now we know exactly where it goes. Just renumber the playlist */
-        for( i_index = p_playlist->i_size - 1; i_index > i_pos ; i_index-- )
-        {
-            p_playlist->pp_items[i_index] = p_playlist->pp_items[i_index - 1];
-        }
+        INSERT_ELEM( p_playlist->pp_items,
+                     p_playlist->i_size,
+                     i_pos,
+                     p_item );
 
         if( p_playlist->i_index >= i_pos )
         {
@@ -179,12 +165,11 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
     {
         /* i_mode == PLAYLIST_REPLACE and 0 <= i_pos < p_playlist->i_size */
         free( p_playlist->pp_items[i_pos]->psz_name );
-        free( p_playlist->pp_items[i_pos] );
         /* XXX: what if the item is still in use? */
+        free( p_playlist->pp_items[i_pos] );
+        p_playlist->pp_items[i_pos] = p_item;
     }
 
-    p_playlist->pp_items[i_pos] = p_item;
-
     if( i_mode & PLAYLIST_GO )
     {
         p_playlist->i_index = i_pos;
@@ -207,41 +192,26 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
  *****************************************************************************/
 int playlist_Delete( playlist_t * p_playlist, int i_pos )
 {
-    int i_index;
-
     vlc_mutex_lock( &p_playlist->object_lock );
 
     if( i_pos >= 0 && i_pos < p_playlist->i_size )
     {
-        msg_Warn( p_playlist, "deleting playlist item « %s »",
-                              p_playlist->pp_items[i_pos]->psz_name );
+        msg_Dbg( p_playlist, "deleting playlist item « %s »",
+                             p_playlist->pp_items[i_pos]->psz_name );
 
         free( p_playlist->pp_items[i_pos]->psz_name );
-        free( p_playlist->pp_items[i_pos] );
         /* XXX: what if the item is still in use? */
+        free( p_playlist->pp_items[i_pos] );
 
-        if( i_pos < p_playlist->i_index )
+        if( i_pos <= p_playlist->i_index )
         {
             p_playlist->i_index--;
         }
 
         /* Renumber the playlist */
-        for( i_index = i_pos + 1; i_index < p_playlist->i_size; i_index++ )
-        {
-            p_playlist->pp_items[i_index - 1] = p_playlist->pp_items[i_index];
-        }
-
-        p_playlist->i_size--;
-        if( p_playlist->i_size )
-        {
-            p_playlist->pp_items = realloc( p_playlist->pp_items,
-                                        p_playlist->i_size * sizeof(void*) );
-        }
-        else
-        {
-            free( p_playlist->pp_items );
-            p_playlist->pp_items = NULL;
-        }
+        REMOVE_ELEM( p_playlist->pp_items,
+                     p_playlist->i_size,
+                     i_pos );
     }
 
     vlc_mutex_unlock( &p_playlist->object_lock );
@@ -329,7 +299,7 @@ static void RunThread ( playlist_t *p_playlist )
                 /* Unlink current input */
                 p_input = p_playlist->p_input;
                 p_playlist->p_input = NULL;
-                vlc_object_detach_all( p_input );
+                vlc_object_detach( p_input );
 
                 /* Release the playlist lock, because we may get stuck
                  * in input_DestroyThread() for some time. */
@@ -349,6 +319,14 @@ static void RunThread ( playlist_t *p_playlist )
             else if( p_playlist->p_input->b_error
                       || p_playlist->p_input->b_eof )
             {
+                /* Check for autodeletion */
+                if( p_playlist->pp_items[p_playlist->i_index]->b_autodeletion )
+                {
+                    vlc_mutex_unlock( &p_playlist->object_lock );
+                    playlist_Delete( p_playlist, p_playlist->i_index );
+                    vlc_mutex_lock( &p_playlist->object_lock );
+                }
+
                 /* Select the next playlist item */
                 SkipItem( p_playlist, 1 );
 
@@ -387,7 +365,7 @@ static void RunThread ( playlist_t *p_playlist )
             /* Unlink current input */
             p_input = p_playlist->p_input;
             p_playlist->p_input = NULL;
-            vlc_object_detach_all( p_input );
+            vlc_object_detach( p_input );
             vlc_mutex_unlock( &p_playlist->object_lock );
 
             /* Destroy input */
@@ -426,6 +404,7 @@ static void RunThread ( playlist_t *p_playlist )
 static void SkipItem( playlist_t *p_playlist, int i_arg )
 {
     int i_oldindex = p_playlist->i_index;
+    vlc_bool_t b_random;
 
     /* If the playlist is empty, there is no current item */
     if( p_playlist->i_size == 0 )
@@ -434,16 +413,33 @@ static void SkipItem( playlist_t *p_playlist, int i_arg )
         return;
     }
 
+    b_random = config_GetInt( p_playlist, "random" );
+
     /* Increment */
+    if( b_random )
+    {
+        srand( (unsigned int)mdate() );
+
+        /* Simple random stuff - we cheat a bit to minimize the chances to
+         * get the same index again. */
+        i_arg = (int)((float)p_playlist->i_size * rand() / (RAND_MAX+1.0));
+        if( i_arg == 0 )
+        {
+            i_arg = (int)((float)p_playlist->i_size * rand() / (RAND_MAX+1.0));
+        }
+    }
+
     p_playlist->i_index += i_arg;
 
     /* Boundary check */
     if( p_playlist->i_index >= p_playlist->i_size )
     {
         if( p_playlist->i_status == PLAYLIST_STOPPED
+             || b_random
              || config_GetInt( p_playlist, "loop" ) )
         {
-            p_playlist->i_index = 0;
+            p_playlist->i_index -= p_playlist->i_size
+                         * ( p_playlist->i_index / p_playlist->i_size );
         }
         else
         {