From a1e392231768436f9d97940655755ec681630100 Mon Sep 17 00:00:00 2001
From: Jakob Leben <jleben@videolan.org>
Date: Mon, 1 Feb 2010 04:35:33 +0100
Subject: [PATCH 1/3] playlist: add new input item events for better playlist items handling

Playlist demuxers must call input_item_BeginAddSubItems and
input_item_EndAddSubItems before/after input_item_AddSubItem.
---
 include/vlc_events.h     |    2 +
 include/vlc_input_item.h |    5 +++
 src/input/item.c         |   16 +++++++++
 src/libvlccore.sym       |    2 +
 src/playlist/item.c      |   78 +++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/include/vlc_events.h b/include/vlc_events.h
index cba7fb9..708597e 100644
--- a/include/vlc_events.h
+++ b/include/vlc_events.h
@@ -119,6 +119,8 @@ typedef enum vlc_event_type_t {
     /* Input item events */
     vlc_InputItemMetaChanged,
     vlc_InputItemSubItemAdded,
+    vlc_InputItemBeginAddSubItems,
+    vlc_InputItemEndAddSubItems,
     vlc_InputItemDurationChanged,
     vlc_InputItemPreparsedChanged,
     vlc_InputItemNameChanged,
diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h
index 6cea7d9..04fcec5 100644
--- a/include/vlc_input_item.h
+++ b/include/vlc_input_item.h
@@ -116,6 +116,11 @@ VLC_EXPORT( void, input_item_SetName, ( input_item_t *p_item, const char *psz_na
  * the input item children. */
 VLC_EXPORT( void, input_item_AddSubItem, ( input_item_t *p_parent, input_item_t *p_child ) );
 
+/* MUST be called BEFORE a series of input_item_AddSubItem!!! */
+VLC_EXPORT( void, input_item_BeginAddSubItems, ( input_item_t *p_parent ) );
+
+/* MUST be called AFTER a series of input_item_AddSubItem!!! */
+VLC_EXPORT( void, input_item_EndAddSubItems, ( input_item_t *p_parent ) );
 
 /**
  * Option flags
diff --git a/src/input/item.c b/src/input/item.c
index 588e36b..77210d2 100644
--- a/src/input/item.c
+++ b/src/input/item.c
@@ -60,6 +60,8 @@ static inline void input_item_Init( vlc_object_t *p_o, input_item_t *p_i )
     vlc_event_manager_init( p_em, p_i, p_o );
     vlc_event_manager_register_event_type( p_em, vlc_InputItemMetaChanged );
     vlc_event_manager_register_event_type( p_em, vlc_InputItemSubItemAdded );
+    vlc_event_manager_register_event_type( p_em, vlc_InputItemBeginAddSubItems );
+    vlc_event_manager_register_event_type( p_em, vlc_InputItemEndAddSubItems );
     vlc_event_manager_register_event_type( p_em, vlc_InputItemDurationChanged );
     vlc_event_manager_register_event_type( p_em, vlc_InputItemPreparsedChanged );
     vlc_event_manager_register_event_type( p_em, vlc_InputItemNameChanged );
@@ -268,6 +270,20 @@ void input_item_AddSubItem( input_item_t *p_parent, input_item_t *p_child )
     vlc_event_send( &p_parent->event_manager, &event );
 }
 
+void input_item_BeginAddSubItems( input_item_t *p_item )
+{
+  vlc_event_t event;
+  event.type = vlc_InputItemBeginAddSubItems;
+  vlc_event_send( &p_item->event_manager, &event );
+}
+
+void input_item_EndAddSubItems( input_item_t *p_item )
+{
+  vlc_event_t event;
+  event.type = vlc_InputItemEndAddSubItems;
+  vlc_event_send( &p_item->event_manager, &event );
+}
+
 bool input_item_HasErrorWhenReading( input_item_t *p_item )
 {
     vlc_mutex_lock( &p_item->lock );
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index b3219c0..6fb01af 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -189,8 +189,10 @@ input_GetItem
 input_item_AddInfo
 input_item_AddOption
 input_item_AddSubItem
+input_item_BeginAddSubItems
 input_item_CopyOptions
 input_item_DelInfo
+input_item_EndAddSubItems
 input_item_GetDuration
 input_item_GetInfo
 input_item_GetMeta
diff --git a/src/playlist/item.c b/src/playlist/item.c
index f6a7528..25ee601 100644
--- a/src/playlist/item.c
+++ b/src/playlist/item.c
@@ -116,6 +116,72 @@ static void input_item_subitem_added( const vlc_event_t * p_event,
     PL_UNLOCK;
 
 }
+static void AddSubItem ( const vlc_event_t * p_event,
+                                      void * user_data )
+{
+    playlist_item_t *p_parent = ( playlist_item_t* ) user_data;
+    input_item_t *p_input = p_event->u.input_item_subitem_added.p_new_child;
+    playlist_BothAddInput( p_parent->p_playlist, p_input, p_parent,
+                           PLAYLIST_APPEND, PLAYLIST_END, NULL, NULL, pl_Unlocked );
+}
+
+static void EndAddSubItems ( const vlc_event_t * p_event,
+                                      void * user_data )
+{
+    input_item_t *p_input = p_event->p_obj;
+    playlist_item_t *p_parent = ( playlist_item_t* ) user_data;
+    playlist_t *p_playlist = p_parent->p_playlist;
+
+    PL_LOCK;
+    playlist_item_t *p_status_item = get_current_status_item( p_playlist );
+    bool b_play = var_CreateGetBool( p_playlist, "playlist-autostart" ) &&
+                  p_status_item &&
+                  p_input == p_status_item->p_input;
+    PL_UNLOCK;
+
+    if( b_play && p_parent->i_flags & PLAYLIST_SUBITEM_STOP_FLAG )
+    {
+        p_parent->i_flags &= ~PLAYLIST_SUBITEM_STOP_FLAG;
+        playlist_Stop( p_playlist );
+    }
+    else if( b_play  )
+    {
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+                          pl_Unlocked, p_parent, NULL );
+    }
+
+    vlc_event_detach( &p_input->event_manager,
+                      vlc_InputItemSubItemAdded, AddSubItem, p_parent );
+    vlc_event_detach( &p_input->event_manager,
+                      vlc_InputItemEndAddSubItems, EndAddSubItems, p_parent );
+}
+
+static void BeginAddSubItems ( const vlc_event_t * p_event,
+                                      void * user_data )
+{
+    input_item_t *p_input = p_event->p_obj;
+    playlist_t *p_playlist = ( playlist_t* ) user_data;
+
+    PL_LOCK;
+
+    playlist_item_t *p_parent =
+        playlist_ItemFindFromInputAndRoot( p_playlist, p_input,
+                                           p_playlist->p_root_category, true );
+    assert( p_parent != NULL );
+
+    if( p_parent->i_children == -1 )
+    {
+        p_parent = ItemToNode( p_playlist, p_parent, pl_Locked );
+        p_parent->p_input->i_type = ITEM_TYPE_PLAYLIST;
+    }
+
+    PL_UNLOCK;
+
+    vlc_event_attach( &p_input->event_manager, vlc_InputItemSubItemAdded,
+                      AddSubItem, p_parent );
+    vlc_event_attach( &p_input->event_manager, vlc_InputItemEndAddSubItems,
+                      EndAddSubItems, p_parent );
+}
 
 /*****************************************************************************
  * An input item's meta or duration has changed (Event Callback)
@@ -134,8 +200,10 @@ static void input_item_changed( const vlc_event_t * p_event,
 static void install_input_item_observer( playlist_item_t * p_item )
 {
     vlc_event_manager_t * p_em = &p_item->p_input->event_manager;
-    vlc_event_attach( p_em, vlc_InputItemSubItemAdded,
-                      input_item_subitem_added, p_item );
+    vlc_event_attach( p_em, vlc_InputItemBeginAddSubItems,
+                      BeginAddSubItems, p_item->p_playlist );
+    //vlc_event_attach( p_em, vlc_InputItemSubItemAdded,
+    //                  input_item_subitem_added, p_item );
     vlc_event_attach( p_em, vlc_InputItemDurationChanged,
                       input_item_changed, p_item );
     vlc_event_attach( p_em, vlc_InputItemMetaChanged,
@@ -151,8 +219,10 @@ static void install_input_item_observer( playlist_item_t * p_item )
 static void uninstall_input_item_observer( playlist_item_t * p_item )
 {
     vlc_event_manager_t * p_em = &p_item->p_input->event_manager;
-    vlc_event_detach( p_em, vlc_InputItemSubItemAdded,
-                      input_item_subitem_added, p_item );
+    vlc_event_detach( p_em, vlc_InputItemBeginAddSubItems,
+                      BeginAddSubItems, p_item->p_playlist );
+    //vlc_event_detach( p_em, vlc_InputItemSubItemAdded,
+    //                  input_item_subitem_added, p_item );
     vlc_event_detach( p_em, vlc_InputItemMetaChanged,
                       input_item_changed, p_item );
     vlc_event_detach( p_em, vlc_InputItemDurationChanged,
-- 
1.6.3.3

