* Provide playlist_LockFoo functions for some functions
authorClément Stenac <zorglub@videolan.org>
Tue, 14 Dec 2004 11:40:09 +0000 (11:40 +0000)
committerClément Stenac <zorglub@videolan.org>
Tue, 14 Dec 2004 11:40:09 +0000 (11:40 +0000)
* Fix deadlock with preparse

20 files changed:
include/vlc_playlist.h
modules/access/cdda/info.c
modules/access/directory.c
modules/access/vcdx/access.c
modules/control/http.c
modules/demux/m3u.c
modules/demux/mp4/mp4.c
modules/demux/playlist/playlist.c
modules/gui/gtk/playlist.c
modules/gui/macosx/playlist.m
modules/gui/ncurses.c
modules/gui/pda/pda_callbacks.c
modules/gui/skins2/vars/playlist.cpp
modules/gui/wxwindows/dialogs.cpp
modules/gui/wxwindows/playlist.cpp
modules/services_discovery/sap.c
modules/visualization/xosd.c
src/playlist/item-ext.c
src/playlist/playlist.c
src/playlist/view.c

index c1c85d4..4129b16 100644 (file)
@@ -79,10 +79,11 @@ struct playlist_item_t
     /* END LEGACY FIELDS */
 };
 
-#define PLAYLIST_SAVE_FLAG      0x1     /**< Must it be saved */
-#define PLAYLIST_SKIP_FLAG      0x2     /**< Must playlist skip after it ? */
-#define PLAYLIST_ENA_FLAG       0x4     /**< Is it enabled ? */
-#define PLAYLIST_DEL_FLAG       0x8     /**< Autodelete ? */
+#define PLAYLIST_SAVE_FLAG      0x01     /**< Must it be saved */
+#define PLAYLIST_SKIP_FLAG      0x02     /**< Must playlist skip after it ? */
+#define PLAYLIST_ENA_FLAG       0x04     /**< Is it enabled ? */
+#define PLAYLIST_DEL_FLAG       0x08     /**< Autodelete ? */
+#define PLAYLIST_RO_FLAG        0x10    /**< Write-enabled ? */
 
 /**
  * playlist view
@@ -247,6 +248,7 @@ int            playlist_Destroy  ( playlist_t * );
 VLC_EXPORT( int, playlist_Control, ( playlist_t *, int, ...  ) );
 
 VLC_EXPORT( int,  playlist_Clear, ( playlist_t * ) );
+VLC_EXPORT( int,  playlist_LockClear, ( playlist_t * ) );
 
 VLC_EXPORT( int, playlist_PreparseEnqueue, (playlist_t *, input_item_t *) );
 
@@ -311,17 +313,23 @@ VLC_EXPORT(int, playlist_NodeAddItem, ( playlist_t *, playlist_item_t *,int,play
 
 /* Misc item operations (act on item+playlist) */
 VLC_EXPORT( int,  playlist_Delete, ( playlist_t *, int ) );
+VLC_EXPORT( int,  playlist_LockDelete, ( playlist_t *, int ) );
 VLC_EXPORT( int,  playlist_Disable, ( playlist_t *, playlist_item_t * ) );
 VLC_EXPORT( int,  playlist_Enable, ( playlist_t *, playlist_item_t * ) );
 VLC_EXPORT( int, playlist_ItemToNode, (playlist_t *,playlist_item_t *) );
+VLC_EXPORT( int, playlist_LockItemToNode, (playlist_t *,playlist_item_t *) );
 VLC_EXPORT( int, playlist_Replace, (playlist_t *,playlist_item_t *, input_item_t*) );
+VLC_EXPORT( int, playlist_LockReplace, (playlist_t *,playlist_item_t *, input_item_t*) );
 
 
 /* Item search functions */
 VLC_EXPORT( playlist_item_t *, playlist_ItemGetById, (playlist_t *, int) );
+VLC_EXPORT( playlist_item_t *, playlist_LockItemGetById, (playlist_t *, int) );
 VLC_EXPORT( playlist_item_t *, playlist_ItemGetByPos, (playlist_t *, int) );
-VLC_EXPORT( int, playlist_GetPositionById, (playlist_t *,int ) );
+VLC_EXPORT( playlist_item_t *, playlist_LockItemGetByPos, (playlist_t *, int) );
 VLC_EXPORT( playlist_item_t *, playlist_ItemGetByInput, (playlist_t *,input_item_t * ) );
+VLC_EXPORT( playlist_item_t *, playlist_LockItemGetByInput, (playlist_t *,input_item_t * ) );
+VLC_EXPORT( int, playlist_GetPositionById, (playlist_t *,int ) );
 
 /* Info functions */
 VLC_EXPORT( char * , playlist_GetInfo, ( playlist_t * , int, const char *, const char *) );
index 2a396fc..5150429 100644 (file)
@@ -920,7 +920,7 @@ CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
         CDDAMetaInfo( p_access, CDIO_INVALID_TRACK, psz_mrl );
     }
 
-    p_item = playlist_ItemGetByInput( p_playlist,
+    p_item = playlist_LockItemGetByInput( p_playlist,
                         ((input_thread_t *)p_access->p_parent)->input.p_item );
 
     if( p_item == p_playlist->status.p_item && !b_single_track )
index 394b308..bd34e74 100644 (file)
@@ -228,7 +228,7 @@ static int Read( access_t *p_access, uint8_t *p_buffer, int i_len)
     {
         input_item_t *p_current = ( (input_thread_t*)p_access->p_parent)->
                                                         input.p_item;
-        p_item = playlist_ItemGetByInput( p_playlist, p_current );
+        p_item = playlist_LockItemGetByInput( p_playlist, p_current );
         msg_Dbg( p_access, "not starting directory playback");
         if( !p_item )
         {
index bd78c80..0664238 100644 (file)
@@ -1364,13 +1364,13 @@ VCDFixupPlayList( input_thread_t *p_input, thread_vcd_data_t *p_vcd,
                           psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
                           p_playlist->i_index);
 
-    } 
-  else 
+    }
+  else
     {
     vcdinfo_itemid_t list_itemid;
     list_itemid.type=VCDINFO_ITEM_TYPE_ENTRY;
 
-    playlist_Delete( p_playlist, p_playlist->i_index);
+    playlist_LockDelete( p_playlist, p_playlist->i_index);
 
     for( i = 0 ; i < p_vcd->num_entries ; i++ )
       {
index 358a1ea..de1c36c 100644 (file)
@@ -1890,7 +1890,7 @@ static void MacroDo( httpd_file_sys_t *p_args,
                                     i_index = j;
                             }
 
-                            playlist_Delete( p_sys->p_playlist,
+                            playlist_LockDelete( p_sys->p_playlist,
                                              p_items[i_index] );
                             msg_Dbg( p_intf, "requested playlist delete: %d",
                                      p_items[i_index] );
@@ -1930,7 +1930,7 @@ static void MacroDo( httpd_file_sys_t *p_args,
                         }
                         if( j == i_nb_items )
                         {
-                            playlist_Delete( p_sys->p_playlist, i );
+                            playlist_LockDelete( p_sys->p_playlist, i );
                             msg_Dbg( p_intf, "requested playlist delete: %d",
                                      i );
                         }
@@ -1941,10 +1941,7 @@ static void MacroDo( httpd_file_sys_t *p_args,
                 }
                 case MVLC_EMPTY:
                 {
-                    while( p_sys->p_playlist->i_size > 0 )
-                    {
-                        playlist_Delete( p_sys->p_playlist, 0 );
-                    }
+                    playlist_LockClear( p_sys->p_playlist );
                     msg_Dbg( p_intf, "requested playlist empty" );
                     break;
                 }
index 06dee5a..fc32ca8 100644 (file)
@@ -652,7 +652,7 @@ static vlc_bool_t FindItem( demux_t *p_demux, playlist_t *p_playlist,
      {
          input_item_t *p_current =
              ((input_thread_t*)p_demux->p_parent)->input.p_item;
-         *pp_item = playlist_ItemGetByInput( p_playlist, p_current );
+         *pp_item = playlist_LockItemGetByInput( p_playlist, p_current );
 
          if( !*pp_item )
              msg_Dbg( p_playlist, "unable to find item in playlist");
index c988aed..6c7bf87 100644 (file)
@@ -338,7 +338,7 @@ static int Open( vlc_object_t * p_this )
                                            FIND_ANYWHERE );
         if( p_playlist )
         {
-            p_item = playlist_ItemGetByInput( p_playlist,
+            p_item = playlist_LockItemGetByInput( p_playlist,
                       ((input_thread_t *)p_demux->p_parent)->input.p_item );
             playlist_ItemToNode( p_playlist, p_item );
 
index fe0393b..4ce3e18 100644 (file)
@@ -127,7 +127,7 @@ vlc_bool_t FindItem( demux_t *p_demux, playlist_t *p_playlist,
      {
          input_item_t *p_current = ( (input_thread_t*)p_demux->p_parent)->
                                                         input.p_item;
-         *pp_item = playlist_ItemGetByInput( p_playlist, p_current );
+         *pp_item = playlist_LockItemGetByInput( p_playlist, p_current );
          if( !*pp_item )
          {
              msg_Dbg( p_playlist, "unable to find item in playlist");
index 3f8d204..77581ef 100644 (file)
@@ -506,7 +506,7 @@ void GtkDeleteGListItem( gpointer data, gpointer param )
     int i_cur_row = (long)data;
     playlist_t * p_playlist = param;
 
-    playlist_Delete( p_playlist, i_cur_row );
+    playlist_LockDelete( p_playlist, i_cur_row );
 }
 
 
index b825ec3..dc08514 100644 (file)
@@ -314,7 +314,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/
             {
                 playlist_Stop( p_playlist );
             }
-            playlist_Delete( p_playlist, p_item->input.i_id );
+            playlist_LockDelete( p_playlist, p_item->input.i_id );
         }
         [self playlistUpdated];
     }
index e78a7d0..599c0e3 100644 (file)
@@ -419,8 +419,9 @@ static int HandleKey( intf_thread_t *p_intf, int i_key )
             {
                 int i_item = p_sys->p_playlist->i_index;
 
-                playlist_Delete( p_sys->p_playlist, p_sys->i_box_plidx );
-                if( i_item < p_sys->p_playlist->i_size && i_item != p_sys->p_playlist->i_index )
+                playlist_LockDelete( p_sys->p_playlist, p_sys->i_box_plidx );
+                if( i_item < p_sys->p_playlist->i_size &&
+                    i_item != p_sys->p_playlist->i_index )
                 {
                     playlist_Goto( p_sys->p_playlist, i_item );
                 }
index 3b15bd2..26c7c50 100644 (file)
@@ -873,7 +873,7 @@ void onDeletePlaylist(GtkButton *button, gpointer user_data)
                  */
                 p_rows = g_list_reverse( p_rows );
             }
-    
+
             for (p_node=p_rows; p_node!=NULL; p_node = p_node->next)
             {
                 GtkTreeIter iter;
@@ -887,7 +887,7 @@ void onDeletePlaylist(GtkButton *button, gpointer user_data)
                         gint item;
 
                         gtk_tree_model_get(p_model, &iter, 2, &item, -1);
-                        playlist_Delete(p_playlist, item);
+                        playlist_LockDelete(p_playlist, item);
                     }
                 }
             }
@@ -929,7 +929,7 @@ void onClearPlaylist(GtkButton *button, gpointer user_data)
 
     for(item = p_playlist->i_size - 1; item >= 0 ;item-- )
     {
-        playlist_Delete( p_playlist, item);
+        playlist_LockDelete( p_playlist, item);
     }
     vlc_object_release( p_playlist );
 
index 3425e39..f076c57 100644 (file)
@@ -64,9 +64,9 @@ void Playlist::delSelected()
     {
         if( (*it).m_selected )
         {
-            playlist_item_t *p_item = playlist_ItemGetByPos( m_pPlaylist,
-                                                             index );
-            playlist_Delete( m_pPlaylist, p_item->input.i_id );
+            playlist_item_t *p_item = playlist_LockItemGetByPos( m_pPlaylist,
+                                                                 index );
+            playlist_LockDelete( m_pPlaylist, p_item->input.i_id );
         }
         else
         {
index 1dab4ed..9d78cf7 100644 (file)
@@ -390,7 +390,7 @@ void DialogsProvider::OnOpenDirectory( wxCommandEvent& event )
         int i_id = playlist_Add( p_playlist, (const char *)path.mb_str(),
                                              (const char *)path.mb_str(),
                                              PLAYLIST_APPEND, PLAYLIST_END );
-        p_item = playlist_ItemGetById( p_playlist, i_id );
+        p_item = playlist_LockItemGetById( p_playlist, i_id );
         if( p_item )
         {
             input_CreateThread( p_intf, &p_item->input );
index 66ca9ef..87f0232 100644 (file)
@@ -619,7 +619,7 @@ void Playlist::UpdateItem( int i )
         return;
     }
 
-    p_item = playlist_ItemGetById( p_playlist, i );
+    p_item = playlist_LockItemGetById( p_playlist, i );
 
     wxTreeItemId item = FindItem( treectrl->GetRootItem(), p_item);
 
@@ -923,7 +923,7 @@ void Playlist::DeleteItem( int item_id )
         return;
     }
 
-    playlist_Delete( p_playlist, item_id );
+    playlist_LockDelete( p_playlist, item_id );
 
     vlc_object_release( p_playlist );
 }
@@ -1480,7 +1480,9 @@ void Playlist::OnPopupPreparse( wxMenuEvent& event )
     {
         if( p_popup_item->i_children == -1 )
         {
+            wxMutexGuiLeave();
             playlist_PreparseEnqueue( p_playlist, &p_popup_item->input );
+            wxMutexGuiEnter();
         }
         else
         {
index d00e1c1..f6684a6 100644 (file)
@@ -1375,7 +1375,7 @@ static int RemoveAnnounce( services_discovery_t *p_sd,
 
     if( p_announce->p_item )
     {
-        playlist_Delete( p_playlist, p_announce->p_item->input.i_id );
+        playlist_LockDelete( p_playlist, p_announce->p_item->input.i_id );
     }
 
     for( i = 0; i< p_sd->p_sys->i_announces; i++)
index 31c1bea..b72b6e2 100644 (file)
@@ -240,8 +240,7 @@ static void Run( intf_thread_t *p_intf )
             else
             {
     //           vlc_mutex_lock(&p_playlist->object_lock );
-                 p_item = playlist_ItemGetByPos( p_playlist,
-                                 p_playlist->i_index );
+                 p_item = p_playlist->status.p_item;
                 item = p_item->input;
                 if( !p_item )
                 {
index 0a2293c..2a673c8 100644 (file)
@@ -436,6 +436,15 @@ playlist_item_t * playlist_ItemGetByPos( playlist_t * p_playlist , int i_pos )
     }
 }
 
+playlist_item_t *playlist_LockItemGetByPos( playlist_t *p_playlist, int i_pos )
+{
+    playlist_item_t *p_ret;
+    vlc_mutex_lock( &p_playlist->object_lock );
+    p_ret = playlist_ItemGetByPos( p_playlist, i_pos );
+    vlc_mutex_unlock( &p_playlist->object_lock );
+    return p_ret;
+}
+
 /**
  * Search an item by its id
  *
@@ -456,6 +465,15 @@ playlist_item_t * playlist_ItemGetById( playlist_t * p_playlist , int i_id )
     return NULL;
 }
 
+playlist_item_t *playlist_LockItemGetById( playlist_t *p_playlist, int i_id)
+{
+    playlist_item_t *p_ret;
+    vlc_mutex_lock( &p_playlist->object_lock );
+    p_ret = playlist_ItemGetById( p_playlist, i_id );
+    vlc_mutex_unlock( &p_playlist->object_lock );
+    return p_ret;
+}
+
 /**
  * Search an item by its input_item_t
  *
@@ -482,6 +500,15 @@ playlist_item_t * playlist_ItemGetByInput( playlist_t * p_playlist ,
     return NULL;
 }
 
+playlist_item_t *playlist_LockItemGetByInput( playlist_t *p_playlist,
+                                               input_item_t *p_item )
+{
+    playlist_item_t *p_ret;
+    vlc_mutex_lock( &p_playlist->object_lock );
+    p_ret = playlist_ItemGetByInput( p_playlist, p_item );
+    vlc_mutex_unlock( &p_playlist->object_lock );
+    return p_ret;
+}
 
 
 /***********************************************************************
@@ -505,8 +532,6 @@ int playlist_ItemToNode( playlist_t *p_playlist,playlist_item_t *p_item )
         p_item->i_children = 0;
     }
 
-    vlc_mutex_lock( &p_playlist->object_lock );
-
     /* Remove it from the array of available items */
     for( i = 0 ; i < p_playlist->i_size ; i++ )
     {
@@ -515,19 +540,27 @@ int playlist_ItemToNode( playlist_t *p_playlist,playlist_item_t *p_item )
             REMOVE_ELEM( p_playlist->pp_items, p_playlist->i_size, i );
         }
     }
-    vlc_mutex_unlock( &p_playlist->object_lock );
     var_SetInteger( p_playlist, "item-change", p_item->input.i_id );
 
     return VLC_SUCCESS;
 }
 
+int playlist_LockItemToNode( playlist_t *p_playlist, playlist_item_t *p_item )
+{
+    int i_ret;
+    vlc_mutex_lock( &p_playlist->object_lock );
+    i_ret = playlist_ItemToNode( p_playlist, p_item );
+    vlc_mutex_unlock( &p_playlist->object_lock );
+    return i_ret;
+}
+
 /**
  * Replaces an item with another one
  * This function must be entered without the playlist lock
  *
  * \see playlist_Replace
  */
-int playlist_LockAndReplace( playlist_t *p_playlist,
+int playlist_LockReplace( playlist_t *p_playlist,
                              playlist_item_t *p_olditem,
                              input_item_t *p_new )
 {
@@ -604,12 +637,12 @@ int playlist_Delete( playlist_t * p_playlist, int i_id )
     /* Check if it is the current item */
     if( p_playlist->status.p_item == p_item )
     {
-        playlist_Control( p_playlist, PLAYLIST_STOP );
+        /* Hack we don't call playlist_Control for lock reasons */
+        p_playlist->status.i_status = PLAYLIST_STOPPED;
+        p_playlist->request.b_request = VLC_TRUE;
         p_playlist->status.p_item = NULL;
     }
 
-    vlc_mutex_lock( &p_playlist->object_lock );
-
     msg_Dbg( p_playlist, "deleting playlist item `%s'",
                           p_item->input.psz_name );
 
@@ -628,11 +661,18 @@ int playlist_Delete( playlist_t * p_playlist, int i_id )
 
     playlist_ItemDelete( p_item );
 
-    vlc_mutex_unlock( &p_playlist->object_lock );
-
     return VLC_SUCCESS;
 }
 
+int playlist_LockDelete( playlist_t * p_playlist, int i_id )
+{
+    int i_ret;
+    vlc_mutex_lock( &p_playlist->object_lock );
+    i_ret = playlist_Delete( p_playlist, i_id );
+    vlc_mutex_unlock( &p_playlist->object_lock );
+    return i_ret;
+}
+
 /**
  * Clear all playlist items
  *
@@ -654,6 +694,15 @@ int playlist_Clear( playlist_t * p_playlist )
     return VLC_SUCCESS;
 }
 
+int playlist_LockClear( playlist_t *p_playlist )
+{
+    int i_ret;
+    vlc_mutex_lock( &p_playlist->object_lock );
+    playlist_Clear( p_playlist );
+    vlc_mutex_unlock( &p_playlist->object_lock );
+    return i_ret;
+}
+
 
 /**
  * Disables a playlist item
index 5f0074f..6ea9139 100644 (file)
@@ -127,6 +127,7 @@ playlist_t * __playlist_Create ( vlc_object_t *p_parent )
 
     p_playlist->p_general = playlist_NodeCreate( p_playlist, VIEW_CATEGORY,
                                         _( "General" ), p_view->p_root );
+    p_playlist->p_general->i_flags |= PLAYLIST_RO_FLAG;
 
     /* Set startup status
      * We set to simple view on startup for interfaces that don't do
@@ -572,10 +573,8 @@ static void RunThread ( playlist_t *p_playlist )
             {
                 if( p_autodelete_item )
                 {
-                    vlc_mutex_unlock( &p_playlist->object_lock );
                     playlist_Delete( p_playlist,
                                      p_autodelete_item->input.i_id );
-                    vlc_mutex_lock( &p_playlist->object_lock );
                     p_autodelete_item = NULL;
                 }
                 p_playlist->status.i_status = PLAYLIST_STOPPED;
@@ -587,9 +586,7 @@ static void RunThread ( playlist_t *p_playlist )
 
             if( p_autodelete_item )
             {
-                vlc_mutex_unlock( &p_playlist->object_lock );
                 playlist_Delete( p_playlist, p_autodelete_item->input.i_id );
-                vlc_mutex_lock( &p_playlist->object_lock );
                 p_autodelete_item = NULL;
             }
         }
@@ -770,7 +767,7 @@ static playlist_item_t * NextItem( playlist_t *p_playlist )
         return NULL;
     }
 
-    if( !p_playlist->request.b_request && p_playlist->status.p_item && 
+    if( !p_playlist->request.b_request && p_playlist->status.p_item &&
         !(p_playlist->status.p_item->i_flags & PLAYLIST_SKIP_FLAG) )
     {
         msg_Dbg( p_playlist, "no-skip mode, stopping") ;
index 14303f2..c7e4474 100644 (file)
@@ -86,6 +86,8 @@ playlist_view_t * playlist_ViewCreate( playlist_t *p_playlist, int i_id,
 /**
  * Creates a new view and add it to the list
  *
+ * This function must be entered without the playlist lock
+ *
  * \param p_playlist a playlist object
  * \param i_id the view identifier
  * \return VLC_SUCCESS or an error
@@ -113,6 +115,8 @@ int playlist_ViewInsert( playlist_t *p_playlist, int i_id, char *psz_name )
 /**
  * Deletes a view
  *
+ * This function must be entered wit the playlist lock
+ *
  * \param p_view the view to delete
  * \return nothing
  */
@@ -122,7 +126,6 @@ int playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view )
     return VLC_SUCCESS;
 }
 
-
 /**
  * Dumps the content of a view
  *
@@ -366,15 +369,22 @@ int playlist_NodeDelete( playlist_t *p_playlist, playlist_item_t *p_root,
             playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id );
         }
     }
-    var_SetInteger( p_playlist, "item-deleted", p_root->input.i_id );    
     /* Delete the node */
-    for( i = 0 ; i< p_root->i_parents; i++ )
+    if( p_root->i_flags & PLAYLIST_RO_FLAG )
     {
-        playlist_NodeRemoveItem( p_playlist, p_root,
-                                 p_root->pp_parents[i]->p_parent );
+        msg_Dbg( p_playlist, "unable to remove node, write-protected" );
     }
-    playlist_ItemDelete( p_root );
-   return VLC_SUCCESS;
+    else
+    {
+        for( i = 0 ; i< p_root->i_parents; i++ )
+        {
+            playlist_NodeRemoveItem( p_playlist, p_root,
+                                     p_root->pp_parents[i]->p_parent );
+        }
+        var_SetInteger( p_playlist, "item-deleted", p_root->input.i_id );
+        playlist_ItemDelete( p_root );
+    }
+    return VLC_SUCCESS;
 }