]> git.sesse.net Git - vlc/blobdiff - src/playlist/playlist.c
* src/playlist/item-ext.c: playlist_AddExt() needs to duplicate the input options...
[vlc] / src / playlist / playlist.c
index f17990b7d3f16b32c44a5689e600ed993a027cf6..1e5d2f2c38ee163a8b44f800230591e27368a156 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * playlist.c : Playlist management functions
  *****************************************************************************
- * Copyright (C) 1999-2001 VideoLAN
- * $Id: playlist.c,v 1.66 2003/11/29 11:12:46 fenrir Exp $
+ * Copyright (C) 1999-2004 VideoLAN
+ * $Id: playlist.c,v 1.82 2004/02/23 21:57:56 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -27,6 +27,7 @@
 #include <vlc/vlc.h>
 #include <vlc/vout.h>
 #include <vlc/sout.h>
+#include <vlc/input.h>
 
 #include "stream_control.h"
 #include "input_ext-intf.h"
@@ -34,7 +35,6 @@
 #include "vlc_playlist.h"
 
 #define PLAYLIST_FILE_HEADER_0_5  "# vlc playlist file version 0.5"
-#define PLAYLIST_FILE_HEADER_0_6  "# vlc playlist file version 0.6"
 
 /*****************************************************************************
  * Local prototypes
@@ -43,8 +43,6 @@ static void RunThread ( playlist_t * );
 static void SkipItem  ( playlist_t *, int );
 static void PlayItem  ( playlist_t * );
 
-static void Poubellize ( playlist_t *, input_thread_t * );
-
 /**
  * Create playlist
  *
@@ -69,12 +67,25 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent )
     val.b_bool = VLC_TRUE;
     var_Set( p_playlist, "intf-change", val );
 
+    var_Create( p_playlist, "item-change", VLC_VAR_INTEGER );
+    val.i_int = -1;
+    var_Set( p_playlist, "item-change", val );
+
+    var_Create( p_playlist, "playlist-current", VLC_VAR_INTEGER );
+    val.i_int = -1;
+    var_Set( p_playlist, "playlist-current", val );
+
     var_Create( p_playlist, "intf-popupmenu", VLC_VAR_BOOL );
 
     var_Create( p_playlist, "intf-show", VLC_VAR_BOOL );
     val.b_bool = VLC_TRUE;
     var_Set( p_playlist, "intf-show", val );
 
+
+    var_Create( p_playlist, "prevent-skip", VLC_VAR_BOOL );
+    val.b_bool = VLC_FALSE;
+    var_Set( p_playlist, "prevent-skip", val );
+
     var_Create( p_playlist, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
     var_Create( p_playlist, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
     var_Create( p_playlist, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
@@ -87,9 +98,12 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent )
 
     p_playlist->i_groups = 0;
     p_playlist->pp_groups = NULL;
-    p_playlist->i_max_id = 0;
+    p_playlist->i_last_group = 0;
+    p_playlist->i_last_id = 0;
+    p_playlist->i_sort = SORT_ID;
+    p_playlist->i_order = ORDER_NORMAL;
 
-    playlist_CreateGroup( p_playlist, "Normal" );
+    playlist_CreateGroup( p_playlist, _("Normal") );
 
     if( vlc_thread_create( p_playlist, "playlist", RunThread,
                            VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
@@ -118,6 +132,14 @@ void playlist_Destroy( playlist_t * p_playlist )
     vlc_thread_join( p_playlist );
 
     var_Destroy( p_playlist, "intf-change" );
+    var_Destroy( p_playlist, "item-change" );
+    var_Destroy( p_playlist, "playlist-current" );
+    var_Destroy( p_playlist, "intf-popmenu" );
+    var_Destroy( p_playlist, "intf-show" );
+    var_Destroy( p_playlist, "prevent-skip" );
+    var_Destroy( p_playlist, "random" );
+    var_Destroy( p_playlist, "repeat" );
+    var_Destroy( p_playlist, "loop" );
 
     while( p_playlist->i_groups > 0 )
     {
@@ -140,7 +162,7 @@ void playlist_Destroy( playlist_t * p_playlist )
  * \param i_command the command to do
  * \param i_arg the argument to the command. See playlist_command_t for details
  */
- void playlist_Command( playlist_t * p_playlist, playlist_command_t i_command,
+void playlist_Command( playlist_t * p_playlist, playlist_command_t i_command,
                        int i_arg )
 {
     vlc_value_t val;
@@ -154,6 +176,8 @@ void playlist_Destroy( playlist_t * p_playlist )
         if( p_playlist->p_input )
         {
             input_StopThread( p_playlist->p_input );
+            val.i_int = p_playlist->i_index;
+            var_Set( p_playlist, "item-change",val );
         }
         break;
 
@@ -218,6 +242,8 @@ void playlist_Destroy( playlist_t * p_playlist )
             {
                 input_StopThread( p_playlist->p_input );
             }
+            val.b_bool = VLC_TRUE;
+            var_Set( p_playlist, "prevent-skip", val );
             p_playlist->i_status = PLAYLIST_RUNNING;
         }
         break;
@@ -228,44 +254,39 @@ void playlist_Destroy( playlist_t * p_playlist )
     }
 
     vlc_mutex_unlock( &p_playlist->object_lock );
-
+#if 0
     val.b_bool = VLC_TRUE;
     var_Set( p_playlist, "intf-change", val );
-
+#endif
     return;
 }
-/* Following functions are local */
 
-static void ObjectGarbageCollector( playlist_t *p_playlist,
-                                    int i_type,
-                                    mtime_t *pi_obj_destroyed_date )
+
+static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type,
+                                       mtime_t destroy_date )
 {
     vlc_object_t *p_obj;
-    if( *pi_obj_destroyed_date > mdate() )
-    {
-        return;
-    }
 
-    if( *pi_obj_destroyed_date == 0 )
+    if( destroy_date > mdate() ) return destroy_date;
+
+    if( destroy_date == 0 )
     {
         /* give a little time */
-        *pi_obj_destroyed_date = mdate() + 300000LL;
+        return mdate() + I64C(1000000);
     }
     else
     {
-        while( ( p_obj = vlc_object_find( p_playlist,
-                                           i_type,
-                                           FIND_CHILD ) ) )
+        while( ( p_obj = vlc_object_find( p_playlist, i_type, FIND_CHILD ) ) )
         {
             if( p_obj->p_parent != (vlc_object_t*)p_playlist )
             {
-                /* only first chiled (ie unused) */
+                /* only first child (ie unused) */
                 vlc_object_release( p_obj );
                 break;
             }
             if( i_type == VLC_OBJECT_VOUT )
             {
-                msg_Dbg( p_playlist, "vout garbage collector destroying 1 vout" );
+                msg_Dbg( p_playlist, "garbage collector destroying 1 vout" );
                 vlc_object_detach( p_obj );
                 vlc_object_release( p_obj );
                 vout_Destroy( (vout_thread_t *)p_obj );
@@ -276,7 +297,7 @@ static void ObjectGarbageCollector( playlist_t *p_playlist,
                 sout_DeleteInstance( (sout_instance_t*)p_obj );
             }
         }
-        *pi_obj_destroyed_date = 0;
+        return 0;
     }
 }
 
@@ -341,41 +362,48 @@ static void RunThread ( playlist_t *p_playlist )
                 {
                     vlc_mutex_unlock( &p_playlist->object_lock );
                     playlist_Delete( p_playlist, p_playlist->i_index );
-                    vlc_mutex_lock( &p_playlist->object_lock );
+                    p_playlist->i_index++;
+                    p_playlist->i_status = PLAYLIST_RUNNING;
+                }
+                else
+                {
+                    /* Select the next playlist item */
+                    SkipItem( p_playlist, 1 );
+                    input_StopThread( p_playlist->p_input );
+                    vlc_mutex_unlock( &p_playlist->object_lock );
                 }
-
-                /* Select the next playlist item */
-                SkipItem( p_playlist, 1 );
-
-                input_StopThread( p_playlist->p_input );
-                vlc_mutex_unlock( &p_playlist->object_lock );
-
-                val.b_bool = VLC_TRUE;
-                var_Set( p_playlist, "intf-change", val );
                 continue;
             }
             else if( p_playlist->p_input->stream.control.i_status != INIT_S )
             {
                 vlc_mutex_unlock( &p_playlist->object_lock );
-                ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT,
-                                        &i_vout_destroyed_date );
-                ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT,
-                                        &i_sout_destroyed_date );
+                i_vout_destroyed_date =
+                    ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT,
+                                            i_vout_destroyed_date );
+                i_sout_destroyed_date =
+                    ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT,
+                                            i_sout_destroyed_date );
                 vlc_mutex_lock( &p_playlist->object_lock );
             }
         }
         else if( p_playlist->i_status != PLAYLIST_STOPPED )
         {
-            SkipItem( p_playlist, 0 );
+            var_Get( p_playlist, "prevent-skip", &val);
+            if( val.b_bool == VLC_FALSE)
+            {
+                SkipItem( p_playlist, 0 );
+            }
+            val.b_bool = VLC_TRUE;
+            var_Set( p_playlist, "prevent-skip", val);
             PlayItem( p_playlist );
         }
         else if( p_playlist->i_status == PLAYLIST_STOPPED )
         {
             vlc_mutex_unlock( &p_playlist->object_lock );
-            ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT,
-                                    &i_sout_destroyed_date );
-            ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT,
-                                    &i_vout_destroyed_date );
+            i_sout_destroyed_date =
+                ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, mdate() );
+            i_vout_destroyed_date =
+                ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, mdate() );
             vlc_mutex_lock( &p_playlist->object_lock );
         }
         vlc_mutex_unlock( &p_playlist->object_lock );
@@ -500,9 +528,7 @@ static void SkipItem( playlist_t *p_playlist, int i_arg )
     /* Boundary check */
     if( p_playlist->i_index >= p_playlist->i_size )
     {
-        if( p_playlist->i_status == PLAYLIST_STOPPED
-             || b_random
-             || b_loop )
+        if( p_playlist->i_status == PLAYLIST_STOPPED || b_random || b_loop )
         {
             p_playlist->i_index -= p_playlist->i_size
                          * ( p_playlist->i_index / p_playlist->i_size );
@@ -520,9 +546,9 @@ static void SkipItem( playlist_t *p_playlist, int i_arg )
     }
 
     /* Check that the item is enabled */
-   if( p_playlist->pp_items[p_playlist->i_index]->b_enabled == VLC_FALSE &&
-       p_playlist->i_enabled != 0)
-   {
+    if( p_playlist->pp_items[p_playlist->i_index]->b_enabled == VLC_FALSE &&
+        p_playlist->i_enabled != 0)
+    {
         SkipItem( p_playlist , 1 );
     }
 }
@@ -535,22 +561,31 @@ static void SkipItem( playlist_t *p_playlist, int i_arg )
  *****************************************************************************/
 static void PlayItem( playlist_t *p_playlist )
 {
+    playlist_item_t *p_item;
+    int             i, j;
+    vlc_value_t val;
     if( p_playlist->i_index == -1 )
     {
         if( p_playlist->i_size == 0 || p_playlist->i_enabled == 0)
         {
             return;
         }
-
         SkipItem( p_playlist, 1 );
     }
-
     if( p_playlist->i_enabled == 0)
     {
         return;
     }
 
     msg_Dbg( p_playlist, "creating new input thread" );
-    p_playlist->p_input = input_CreateThread( p_playlist,
-                                  p_playlist->pp_items[p_playlist->i_index] );
+    p_item = p_playlist->pp_items[p_playlist->i_index];
+
+    p_item->i_nb_played++;
+
+    p_playlist->p_input = input_CreateThread( p_playlist, p_item->psz_uri,
+                                              p_item->ppsz_options,
+                                              p_item->i_options );
+
+    val.i_int = p_playlist->i_index;
+    var_Set( p_playlist, "playlist-current", val);
 }