diff --git a/include/vlc_events.h b/include/vlc_events.h
index 50cbc61..5cd21d6 100644
--- a/include/vlc_events.h
+++ b/include/vlc_events.h
@@ -130,7 +130,8 @@ typedef enum vlc_event_type_t {
     vlc_ServicesDiscoveryItemAdded,
     vlc_ServicesDiscoveryItemRemoved,
     vlc_ServicesDiscoveryStarted,
-    vlc_ServicesDiscoveryEnded
+    vlc_ServicesDiscoveryEnded,
+    vlc_ServicesDiscoveryLoadingChanged
 } vlc_event_type_t;
 
 /* Event definition */
@@ -202,6 +203,10 @@ typedef struct vlc_event_t
         {
             void * unused;
         } services_discovery_ended;
+        struct services_discovery_loading_changed
+        {
+            bool new_value;
+        } services_discovery_loading_changed;
 
     } u;
 } vlc_event_t;
diff --git a/include/vlc_services_discovery.h b/include/vlc_services_discovery.h
index 956b77b..2f975b7 100644
--- a/include/vlc_services_discovery.h
+++ b/include/vlc_services_discovery.h
@@ -49,6 +49,7 @@ struct services_discovery_t
     vlc_event_manager_t event_manager;      /* Accessed through Setters for non class function */
 
     char *psz_name;
+    char *psz_longname;
     config_chain_t *p_cfg;
 
     services_discovery_sys_t *p_sys;
@@ -96,6 +97,9 @@ VLC_EXPORT( vlc_event_manager_t *,  services_discovery_EventManager, ( services_
 VLC_EXPORT( void,                   services_discovery_AddItem, ( services_discovery_t * p_this, input_item_t * p_item, const char * psz_category ) );
 VLC_EXPORT( void,                   services_discovery_RemoveItem, ( services_discovery_t * p_this, input_item_t * p_item ) );
 
+/* Used by services_discover module to hint to the client that it is currently loading */
+VLC_EXPORT( void,                   services_discovery_SetLoading, ( services_discovery_t * p_this, bool loading ) );
+
 
 /* SD probing */
 
diff --git a/modules/gui/qt4/components/playlist/selector.cpp b/modules/gui/qt4/components/playlist/selector.cpp
index 2b42401..9e0589d 100644
--- a/modules/gui/qt4/components/playlist/selector.cpp
+++ b/modules/gui/qt4/components/playlist/selector.cpp
@@ -134,6 +134,8 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf )
              this, plItemRemoved( int ) );
     CONNECT( THEMIM->getIM(), metaChanged( input_item_t *),
             this, inputItemUpdate( input_item_t * ) );
+    CONNECT( THEMIM, sdLoading( void * ),
+             this, sdLoadingChange( void * ) );
 
     createItems();
     CONNECT( this, itemActivated( QTreeWidgetItem *, int ),
@@ -499,3 +501,12 @@ void PLSelector::drawBranches ( QPainter * painter, const QRect & rect, const QM
                             QStyle::PE_IndicatorArrowDown :
                             QStyle::PE_IndicatorArrowRight, &option, painter );
 }
+
+void PLSelector::sdLoadingChange( void *data )
+{
+    services_discovery_t *p_sd = (services_discovery_t *) data;
+    if( var_GetBool( p_sd, "sd-loading-status" ) )
+        msg_Info( p_sd, "%s started loading", p_sd->psz_longname );
+    else
+        msg_Info( p_sd, "%s finished loading", p_sd->psz_longname );
+}
diff --git a/modules/gui/qt4/components/playlist/selector.hpp b/modules/gui/qt4/components/playlist/selector.hpp
index e9ea017..6954fc5 100644
--- a/modules/gui/qt4/components/playlist/selector.hpp
+++ b/modules/gui/qt4/components/playlist/selector.hpp
@@ -136,6 +136,7 @@ private slots:
     void inputItemUpdate( input_item_t * );
     void podcastAdd( PLSelItem* );
     void podcastRemove( PLSelItem* );
+    void sdLoadingChange( void * );
 
 signals:
     void activated( playlist_item_t * );
diff --git a/modules/gui/qt4/input_manager.cpp b/modules/gui/qt4/input_manager.cpp
index 4edfc82..d942b98 100644
--- a/modules/gui/qt4/input_manager.cpp
+++ b/modules/gui/qt4/input_manager.cpp
@@ -56,6 +56,8 @@ static int LoopChanged( vlc_object_t *, const char *,
                         vlc_value_t, vlc_value_t, void * );
 static int RepeatChanged( vlc_object_t *, const char *,
                         vlc_value_t, vlc_value_t, void * );
+static int SDLoading( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
 
 
 static int InputEvent( vlc_object_t *, const char *,
@@ -913,6 +915,7 @@ MainInputManager::MainInputManager( intf_thread_t *_p_intf )
     var_AddCallback( THEPL, "random", RandomChanged, this );
     var_AddCallback( THEPL, "repeat", RepeatChanged, this );
     var_AddCallback( THEPL, "loop", LoopChanged, this );
+    var_AddCallback( THEPL, "sd-loading", SDLoading, this );
 
     var_AddCallback( THEPL, "volume-change", VolumeChanged, this );
     var_AddCallback( THEPL, "volume-muted", SoundMuteChanged, this );
@@ -958,6 +961,7 @@ MainInputManager::~MainInputManager()
     var_DelCallback( THEPL, "random", RandomChanged, this );
     var_DelCallback( THEPL, "repeat", RepeatChanged, this );
     var_DelCallback( THEPL, "loop", LoopChanged, this );
+    var_DelCallback( THEPL, "sd-loading", SDLoading, this );
 
 }
 
@@ -1002,6 +1006,9 @@ void MainInputManager::customEvent( QEvent *event )
     case RepeatChanged_Type:
         notifyRepeatLoop();
         return;
+    case SDLoading_Type:
+        emit sdLoading( var_GetAddress( THEPL, "sd-loading" ) );
+        return;
     case LeafToParent_Type:
         imEv = static_cast<IMEvent*>( event );
         emit leafBecameParent( imEv->p_item );
@@ -1222,3 +1229,13 @@ static int RepeatChanged
     QApplication::postEvent( mim, event );
     return VLC_SUCCESS;
 }
+
+static int SDLoading
+( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data )
+{
+    MainInputManager *mim = static_cast<MainInputManager*>(data);
+
+    IMEvent *event = new IMEvent( SDLoading_Type );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}
diff --git a/modules/gui/qt4/input_manager.hpp b/modules/gui/qt4/input_manager.hpp
index 6a856f1..888c8c9 100644
--- a/modules/gui/qt4/input_manager.hpp
+++ b/modules/gui/qt4/input_manager.hpp
@@ -62,6 +62,7 @@ enum {
     LoopChanged_Type,
     RepeatChanged_Type,
     LeafToParent_Type,
+    SDLoading_Type,
 /*    SignalChanged_Type, */
 
     FullscreenControlToggle_Type = QEvent::User + IMEventType + 20,
@@ -296,6 +297,7 @@ signals:
     void randomChanged( bool );
     void repeatLoopChanged( int );
     void leafBecameParent( input_item_t * );
+    void sdLoading( void * );
 };
 
 #endif
diff --git a/modules/misc/lua/libs/sd.c b/modules/misc/lua/libs/sd.c
index 85e1f59..ff7b55f 100644
--- a/modules/misc/lua/libs/sd.c
+++ b/modules/misc/lua/libs/sd.c
@@ -314,6 +314,14 @@ static int vlclua_node_add_node( lua_State *L )
     return 1;
 }
 
+static int vlclua_sd_set_loading( lua_State *L )
+{
+    services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
+    bool isLoading = luaL_checkboolean( L, 1 );
+    services_discovery_SetLoading( p_sd, isLoading );
+    return 1;
+}
+
 /*****************************************************************************
  *
  *****************************************************************************/
@@ -325,6 +333,7 @@ static const luaL_Reg vlclua_sd_reg[] = {
     { "add_node", vlclua_sd_add_node },
     { "add_item", vlclua_sd_add_item },
     { "remove_item", vlclua_sd_remove_item },
+    { "set_loading", vlclua_sd_set_loading },
     { NULL, NULL }
 };
 
diff --git a/modules/misc/lua/services_discovery.c b/modules/misc/lua/services_discovery.c
index d5f3649..70012ab 100644
--- a/modules/misc/lua/services_discovery.c
+++ b/modules/misc/lua/services_discovery.c
@@ -169,8 +169,10 @@ static void* Run( void *data )
                   "function main(): %s", p_sys->psz_filename,
                   lua_tostring( L, lua_gettop( L ) ) );
         lua_pop( L, 1 );
+        var_SetBool( p_sd, "sd-loading-status", false );
         return NULL;
     }
+    var_SetBool( p_sd, "sd-loading-status", false );
     msg_Dbg( p_sd, "LuaSD script loaded: %s", p_sys->psz_filename );
     return NULL;
 }
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 85da6f3..72bf5bb 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -359,6 +359,7 @@ services_discovery_AddItem
 services_discovery_EventManager
 services_discovery_GetLocalizedName
 services_discovery_RemoveItem
+services_discovery_SetLoading
 sout_AccessOutControl
 sout_AccessOutDelete
 sout_AccessOutNew
diff --git a/src/playlist/engine.c b/src/playlist/engine.c
index 0da2997..28303b3 100644
--- a/src/playlist/engine.c
+++ b/src/playlist/engine.c
@@ -308,6 +308,8 @@ static void VariablesInit( playlist_t *p_playlist )
     var_Create( p_playlist, "activity", VLC_VAR_INTEGER );
     var_SetInteger( p_playlist, "activity", 0 );
 
+    var_Create( p_playlist, "sd-loading", VLC_VAR_ADDRESS );
+
     /* Variables to control playback */
     var_Create( p_playlist, "play-and-stop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
     var_Create( p_playlist, "play-and-exit", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
diff --git a/src/playlist/services_discovery.c b/src/playlist/services_discovery.c
index 2afb024..ffe46df 100644
--- a/src/playlist/services_discovery.c
+++ b/src/playlist/services_discovery.c
@@ -122,6 +122,7 @@ services_discovery_t *vlc_sd_Create( vlc_object_t *p_super,
     vlc_event_manager_register_event_type(em, vlc_ServicesDiscoveryItemRemoved);
     vlc_event_manager_register_event_type(em, vlc_ServicesDiscoveryStarted);
     vlc_event_manager_register_event_type(em, vlc_ServicesDiscoveryEnded);
+    vlc_event_manager_register_event_type(em, vlc_ServicesDiscoveryLoadingChanged);
 
     vlc_object_set_destructor( p_sd, services_discovery_Destructor );
     vlc_object_attach( p_sd, p_super );
@@ -170,6 +171,7 @@ void vlc_sd_Destroy( services_discovery_t *p_sd )
 {
     config_ChainDestroy( p_sd->p_cfg );
     free( p_sd->psz_name );
+    free( p_sd->psz_longname );
     vlc_object_release( p_sd );
 }
 
@@ -229,6 +231,19 @@ services_discovery_RemoveItem ( services_discovery_t * p_sd, input_item_t * p_it
     vlc_event_send( &p_sd->event_manager, &event );
 }
 
+/***********************************************************************
+ * SetLoading
+ ***********************************************************************/
+void
+services_discovery_SetLoading ( services_discovery_t * p_sd, bool loading )
+{
+    vlc_event_t event;
+    event.type = vlc_ServicesDiscoveryLoadingChanged;
+    event.u.services_discovery_loading_changed.new_value = loading;
+
+    vlc_event_send( &p_sd->event_manager, &event );
+}
+
 /*
  * Playlist - Services discovery bridge
  */
@@ -300,6 +315,16 @@ static void playlist_sd_item_removed( const vlc_event_t * p_event, void * user_d
     PL_UNLOCK;
 }
 
+/* A certain sd is loading */
+static void playlist_sd_loading_changed( const vlc_event_t *p_event, void *user_data )
+{
+    bool isLoading = p_event->u.services_discovery_loading_changed.new_value;
+    vlc_sd_internal_t *p_sds = user_data;
+    playlist_t *p_playlist = p_sds->p_node->p_playlist;
+    var_SetBool( p_sds->p_sd, "sd-loading-status", isLoading );
+    var_SetAddress( p_playlist, "sd-loading", p_sds->p_sd );
+}
+
 int playlist_ServicesDiscoveryAdd( playlist_t *p_playlist,
                                    const char *psz_name )
 {
@@ -336,6 +361,8 @@ int playlist_ServicesDiscoveryAdd( playlist_t *p_playlist,
             cfg = cfg->p_next;
         }
     }
+    p_sd->psz_longname = strdup( psz_longname );
+    var_Create( p_sd, "sd-loading-status", VLC_VAR_BOOL );
 
     PL_LOCK;
     p_node = playlist_NodeCreate( p_playlist, psz_longname,
@@ -349,6 +376,9 @@ int playlist_ServicesDiscoveryAdd( playlist_t *p_playlist,
     vlc_event_attach( em, vlc_ServicesDiscoveryItemRemoved,
                       playlist_sd_item_removed, p_node );
 
+    vlc_event_attach( em, vlc_ServicesDiscoveryLoadingChanged,
+                     playlist_sd_loading_changed, p_sds );
+
     if( !vlc_sd_Start( p_sd ) )
     {
         vlc_sd_Destroy( p_sd );
@@ -408,6 +438,10 @@ int playlist_ServicesDiscoveryRemove( playlist_t * p_playlist,
                         playlist_sd_item_removed,
                         p_sds->p_node );
 
+    vlc_event_detach( services_discovery_EventManager( p_sd ),
+                      vlc_ServicesDiscoveryLoadingChanged,
+                      playlist_sd_loading_changed, p_sds );
+
     /* Remove the sd playlist node if it exists */
     PL_LOCK;
     playlist_NodeDelete( p_playlist, p_sds->p_node, true, false );
