From 36620f5af1a14d51bab632554b8ecad6163d596b Mon Sep 17 00:00:00 2001
From: Jakob Leben <jleben@videolan.org>
Date: Tue, 9 Feb 2010 03:01:22 +0100
Subject: [PATCH] services_discovery: implement SD categories and use in Qt

---
 include/vlc_services_discovery.h                 |   20 +++++--
 modules/gui/macosx/playlist.m                    |    2 +-
 modules/gui/qt4/components/playlist/selector.cpp |   59 +++++++++++++--------
 modules/gui/qt4/menus.cpp                        |    2 +-
 modules/misc/lua/libs/sd.c                       |    2 +-
 modules/misc/lua/vlc.c                           |    2 +-
 modules/services_discovery/bonjour.c             |    2 +-
 modules/services_discovery/mediadirs.c           |    6 +-
 modules/services_discovery/mtp.c                 |    2 +-
 modules/services_discovery/podcast.c             |    2 +-
 modules/services_discovery/sap.c                 |    2 +-
 modules/services_discovery/shout.c               |    6 +-
 modules/services_discovery/udev.c                |    4 +-
 modules/services_discovery/upnp_cc.cpp           |    2 +-
 modules/services_discovery/upnp_intel.cpp        |    2 +-
 modules/services_discovery/xcb_apps.c            |    2 +-
 src/playlist/services_discovery.c                |   14 ++++--
 17 files changed, 79 insertions(+), 52 deletions(-)

diff --git a/include/vlc_services_discovery.h b/include/vlc_services_discovery.h
index 06026c7..c983942 100644
--- a/include/vlc_services_discovery.h
+++ b/include/vlc_services_discovery.h
@@ -54,15 +54,23 @@ struct services_discovery_t
     services_discovery_sys_t *p_sys;
 };
 
+enum services_discovery_category_e
+{
+    SD_CAT_DEVICES = 1,
+    SD_CAT_LAN,
+    SD_CAT_INTERNET,
+    SD_CAT_MEDIADIR
+};
+
 /***********************************************************************
  * Service Discovery
  ***********************************************************************/
 
 /* Get the services discovery modules names to use in Create(), in a null
  * terminated string array. Array and string must be freed after use. */
-VLC_EXPORT( char **, vlc_sd_GetNames, ( vlc_object_t *, char *** ) );
-#define vlc_sd_GetNames(obj, pln) \
-        vlc_sd_GetNames(VLC_OBJECT(obj), pln)
+VLC_EXPORT( char **, vlc_sd_GetNames, ( vlc_object_t *, char ***, int ** ) );
+#define vlc_sd_GetNames(obj, pln, pcat ) \
+        vlc_sd_GetNames(VLC_OBJECT(obj), pln, pcat)
 
 /* Creation of a service_discovery object */
 VLC_EXPORT( services_discovery_t *, vlc_sd_Create, ( vlc_object_t *, const char * ) );
@@ -91,18 +99,18 @@ VLC_EXPORT( void,                   services_discovery_RemoveItem, ( services_di
 
 /* SD probing */
 
-VLC_EXPORT(int, vlc_sd_probe_Add, (vlc_probe_t *, const char *, const char *));
+VLC_EXPORT(int, vlc_sd_probe_Add, (vlc_probe_t *, const char *, const char *, int category));
 
 #define VLC_SD_PROBE_SUBMODULE \
     add_submodule() \
         set_capability( "services probe", 100 ) \
         set_callbacks( vlc_sd_probe_Open, NULL )
 
-#define VLC_SD_PROBE_HELPER(name, longname) \
+#define VLC_SD_PROBE_HELPER(name, longname, cat) \
 static int vlc_sd_probe_Open (vlc_object_t *obj) \
 { \
     return vlc_sd_probe_Add ((struct vlc_probe_t *)obj, \
-                             name "{longname=\"" # longname "\"}", longname); \
+                             name "{longname=\"" # longname "\"}", longname, cat); \
 }
 
 /** @} */
diff --git a/modules/gui/macosx/playlist.m b/modules/gui/macosx/playlist.m
index 2d10202..ef55310 100644
--- a/modules/gui/macosx/playlist.m
+++ b/modules/gui/macosx/playlist.m
@@ -419,7 +419,7 @@
     o_tc_sortColumn = nil;
 
     char ** ppsz_name;
-    char ** ppsz_services = vlc_sd_GetNames( VLCIntf, &ppsz_name );
+    char ** ppsz_services = vlc_sd_GetNames( VLCIntf, &ppsz_name, NULL );
     if( !ppsz_services )
     {
         pl_Release( VLCIntf );
diff --git a/modules/gui/qt4/components/playlist/selector.cpp b/modules/gui/qt4/components/playlist/selector.cpp
index 159cac3..2465591 100644
--- a/modules/gui/qt4/components/playlist/selector.cpp
+++ b/modules/gui/qt4/components/playlist/selector.cpp
@@ -249,46 +249,60 @@ void PLSelector::createItems()
                               THEPL->p_media_library );
     ml->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_ML ) );
 
-    QTreeWidgetItem *mfldrs = NULL;
+    QTreeWidgetItem *mfolders = NULL;
 
-    QTreeWidgetItem *shouts = NULL;
+    QTreeWidgetItem *internet = NULL;
+
+    QTreeWidgetItem *devices = NULL;
+
+    QTreeWidgetItem *lan = NULL;
 
     char **ppsz_longnames;
-    char **ppsz_names = vlc_sd_GetNames( THEPL, &ppsz_longnames );
+    int *p_categories;
+    char **ppsz_names = vlc_sd_GetNames( THEPL, &ppsz_longnames, &p_categories );
     if( !ppsz_names )
         return;
 
     char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
-    for( ; *ppsz_name; ppsz_name++, ppsz_longname++ )
+    int *p_category = p_categories;
+    for( ; *ppsz_name; ppsz_name++, ppsz_longname++, p_category++ )
     {
         //msg_Dbg( p_intf, "Adding a SD item: %s", *ppsz_longname );
-#define SD_IS( name ) ( !strcmp( *ppsz_name, name ) )
 
-        if( SD_IS("shoutcast") || SD_IS("shoutcasttv") ||
-            SD_IS("frenchtv") || SD_IS("freebox") )
+        if( *p_category == SD_CAT_INTERNET )
+        {
+            if( !internet ) internet = addItem( CATEGORY_TYPE, qtr( "Internet" ),
+                                            false )->treeItem();
+            PLSelItem *selItem = addItem( SD_TYPE, *ppsz_longname, false, internet );
+            putSDData( selItem, *ppsz_name, *ppsz_longname );
+            if( !strncmp( *ppsz_name, "podcast", 7 ) )
+            {
+                selItem->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_PODCAST ) );
+                selItem->addAction( ADD_ACTION, qtr( "Subscribe to a podcast" ) );
+                CONNECT( selItem, action( PLSelItem* ), this, podcastAdd( PLSelItem* ) );
+                podcastsParent = selItem->treeItem();
+            }
+        }
+        else if( *p_category == SD_CAT_DEVICES )
         {
-            if( !shouts ) shouts = addItem( CATEGORY_TYPE, qtr( "Shoutcast" ),
+            if( !devices ) devices = addItem( CATEGORY_TYPE, qtr( "Devices" ),
                                             false )->treeItem();
-            putSDData( addItem( SD_TYPE, *ppsz_longname, false, shouts ),
+            putSDData( addItem( SD_TYPE, *ppsz_longname, false, devices ),
                        *ppsz_name, *ppsz_longname );
         }
-        else if( SD_IS("video_dir") || SD_IS("audio_dir") || SD_IS("picture_dir") )
+        else if( *p_category == SD_CAT_LAN )
         {
-            if( !mfldrs ) mfldrs = addItem( CATEGORY_TYPE, qtr( "Media Folders" ),
+            if( !lan ) lan = addItem( CATEGORY_TYPE, qtr( "Local Network" ),
                                             false )->treeItem();
-            putSDData( addItem( SD_TYPE, *ppsz_longname, false, mfldrs ),
+            putSDData( addItem( SD_TYPE, *ppsz_longname, false, lan ),
                        *ppsz_name, *ppsz_longname );
         }
-        else if( !strncmp( *ppsz_name, "podcast", 7 ) )
+        else if( *p_category == SD_CAT_MEDIADIR )
         {
-
-            PLSelItem *podItem = addItem( SD_TYPE, qtr( "Podcasts" ), false );
-            putSDData( podItem, *ppsz_name, *ppsz_longname );
-            podItem->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_PODCAST ) );
-            podItem->addAction( ADD_ACTION, qtr( "Subscribe to a podcast" ) );
-            CONNECT( podItem, action( PLSelItem* ), this, podcastAdd( PLSelItem* ) );
-
-            podcastsParent = podItem->treeItem();
+            if( !mfolders ) mfolders = addItem( CATEGORY_TYPE, qtr( "Media folders" ),
+                                            false )->treeItem();
+            putSDData( addItem( SD_TYPE, *ppsz_longname, false, mfolders ),
+                       *ppsz_name, *ppsz_longname );
         }
         else
         {
@@ -296,13 +310,12 @@ void PLSelector::createItems()
                        *ppsz_name, *ppsz_longname );
         }
 
-#undef SD_IS
-
         free( *ppsz_name );
         free( *ppsz_longname );
     }
     free( ppsz_names );
     free( ppsz_longnames );
+    free( p_categories );
 }
 
 QStringList PLSelector::mimeTypes() const
diff --git a/modules/gui/qt4/menus.cpp b/modules/gui/qt4/menus.cpp
index 28be14d..b40351b 100644
--- a/modules/gui/qt4/menus.cpp
+++ b/modules/gui/qt4/menus.cpp
@@ -708,7 +708,7 @@ QMenu *QVLCMenu::SDMenu( intf_thread_t *p_intf, QWidget *parent )
     menu->setTitle( qtr( I_PL_SD ) );
 
     char **ppsz_longnames;
-    char **ppsz_names = vlc_sd_GetNames( p_intf, &ppsz_longnames );
+    char **ppsz_names = vlc_sd_GetNames( p_intf, &ppsz_longnames, NULL );
     if( !ppsz_names )
         return menu;
 
diff --git a/modules/misc/lua/libs/sd.c b/modules/misc/lua/libs/sd.c
index b8f0ef5..25d543f 100644
--- a/modules/misc/lua/libs/sd.c
+++ b/modules/misc/lua/libs/sd.c
@@ -62,7 +62,7 @@ static int vlclua_sd_get_services_names( lua_State *L )
 {
     playlist_t *p_playlist = vlclua_get_playlist_internal( L );
     char **ppsz_longnames;
-    char **ppsz_names = vlc_sd_GetNames( p_playlist, &ppsz_longnames );
+    char **ppsz_names = vlc_sd_GetNames( p_playlist, &ppsz_longnames, NULL );
     vlclua_release_playlist_internal( p_playlist );
     if( !ppsz_names )
         return 0;
diff --git a/modules/misc/lua/vlc.c b/modules/misc/lua/vlc.c
index 8aec82c..6b400d5 100644
--- a/modules/misc/lua/vlc.c
+++ b/modules/misc/lua/vlc.c
@@ -632,7 +632,7 @@ static int vlc_sd_probe_Open( vlc_object_t *obj )
                         free( psz_longname );
                         goto error;
                     }
-                    vlc_sd_probe_Add( probe, psz_name, psz_longname );
+                    vlc_sd_probe_Add( probe, psz_name, psz_longname, SD_CAT_INTERNET );
                     free( psz_name );
                     free( psz_longname );
                 }
diff --git a/modules/services_discovery/bonjour.c b/modules/services_discovery/bonjour.c
index 3c7166d..dadb88b 100644
--- a/modules/services_discovery/bonjour.c
+++ b/modules/services_discovery/bonjour.c
@@ -48,7 +48,7 @@
     static int  Open ( vlc_object_t * );
     static void Close( vlc_object_t * );
 
-VLC_SD_PROBE_HELPER("bonjour", N_("Bonjour services"))
+VLC_SD_PROBE_HELPER("bonjour", N_("Bonjour services"), SD_CAT_LAN)
 
 vlc_module_begin ()
     set_shortname( "Bonjour" )
diff --git a/modules/services_discovery/mediadirs.c b/modules/services_discovery/mediadirs.c
index 946a17e..de64690 100644
--- a/modules/services_discovery/mediadirs.c
+++ b/modules/services_discovery/mediadirs.c
@@ -356,10 +356,10 @@ static int vlc_sd_probe_Open( vlc_object_t *obj )
     vlc_probe_t *probe = (vlc_probe_t *)obj;
 
     vlc_sd_probe_Add( probe, "video_dir{longname=\"My Videos\"}",
-                      N_("My Videos") );
+                      N_("My Videos"), SD_CAT_MEDIADIR );
     vlc_sd_probe_Add( probe, "audio_dir{longname=\"My Music\"}",
-                      N_("My Music") );
+                      N_("My Music"), SD_CAT_MEDIADIR );
     vlc_sd_probe_Add( probe, "picture_dir{longname=\"My Pictures\"}",
-                      N_("My Pictures") );
+                      N_("My Pictures"), SD_CAT_MEDIADIR );
     return VLC_PROBE_CONTINUE;
 }
diff --git a/modules/services_discovery/mtp.c b/modules/services_discovery/mtp.c
index 55d0004..ddb8e0b 100644
--- a/modules/services_discovery/mtp.c
+++ b/modules/services_discovery/mtp.c
@@ -38,7 +38,7 @@
 static int Open( vlc_object_t * );
 static void Close( vlc_object_t * );
 
-VLC_SD_PROBE_HELPER("mtp", N_("MTP devices"))
+VLC_SD_PROBE_HELPER("mtp", N_("MTP devices"), SD_CAT_DEVICES)
 
 vlc_module_begin()
     set_shortname( "MTP" )
diff --git a/modules/services_discovery/podcast.c b/modules/services_discovery/podcast.c
index 07afe5b..0b91ea1 100644
--- a/modules/services_discovery/podcast.c
+++ b/modules/services_discovery/podcast.c
@@ -53,7 +53,7 @@
 static int  Open ( vlc_object_t * );
 static void Close( vlc_object_t * );
 
-VLC_SD_PROBE_HELPER("podcast", N_("Podcasts"))
+VLC_SD_PROBE_HELPER("podcast", N_("Podcasts"), SD_CAT_INTERNET)
 
 #define URLS_TEXT N_("Podcast URLs list")
 #define URLS_LONGTEXT N_("Enter the list of podcasts to retrieve, " \
diff --git a/modules/services_discovery/sap.c b/modules/services_discovery/sap.c
index 03fe887..73fa697 100644
--- a/modules/services_discovery/sap.c
+++ b/modules/services_discovery/sap.c
@@ -114,7 +114,7 @@
     static int  OpenDemux ( vlc_object_t * );
     static void CloseDemux ( vlc_object_t * );
 
-VLC_SD_PROBE_HELPER("sap", N_("Network streams (SAP)"))
+VLC_SD_PROBE_HELPER("sap", N_("Network streams (SAP)"), SD_CAT_LAN)
 
 vlc_module_begin ()
     set_shortname( N_("SAP"))
diff --git a/modules/services_discovery/shout.c b/modules/services_discovery/shout.c
index 276e9b2..378c235 100644
--- a/modules/services_discovery/shout.c
+++ b/modules/services_discovery/shout.c
@@ -283,10 +283,10 @@ static int vlc_sd_probe_Open( vlc_object_t *obj )
     vlc_probe_t *probe = (vlc_probe_t *)obj;
 
     vlc_sd_probe_Add( probe, "shoutcast{longname=\"Shoutcast Radio\"}",
-                      N_("Shoutcast Radio") );
+                      N_("Shoutcast Radio"), SD_CAT_INTERNET );
     vlc_sd_probe_Add( probe, "shoutcasttv{longname=\"Shoutcast TV\"}",
-                      N_("Shoutcast TV") );
+                      N_("Shoutcast TV"), SD_CAT_INTERNET );
     vlc_sd_probe_Add( probe, "frenchtv{longname=\"French TV\"}",
-                      N_("French TV") );
+                      N_("French TV"), SD_CAT_INTERNET );
     return VLC_PROBE_CONTINUE;
 }
diff --git a/modules/services_discovery/udev.c b/modules/services_discovery/udev.c
index 8ed89c3..ffbb109 100644
--- a/modules/services_discovery/udev.c
+++ b/modules/services_discovery/udev.c
@@ -74,8 +74,8 @@ static int vlc_sd_probe_Open (vlc_object_t *obj)
     if (mon != NULL)
     {
         vlc_sd_probe_Add (probe, "v4l{longname=\"Video capture\"}",
-                          N_("Video capture"));
-        vlc_sd_probe_Add (probe, "disc{longname=\"Discs\"}", N_("Discs"));
+                          N_("Video capture"), SD_CAT_DEVICES);
+        vlc_sd_probe_Add (probe, "disc{longname=\"Discs\"}", N_("Discs"), SD_CAT_DEVICES);
         udev_monitor_unref (mon);
     }
     udev_unref (udev);
diff --git a/modules/services_discovery/upnp_cc.cpp b/modules/services_discovery/upnp_cc.cpp
index 7b72db6..f718525 100644
--- a/modules/services_discovery/upnp_cc.cpp
+++ b/modules/services_discovery/upnp_cc.cpp
@@ -58,7 +58,7 @@ using namespace CyberLink;
     static int  Open ( vlc_object_t * );
     static void Close( vlc_object_t * );
 
-VLC_SD_PROBE_HELPER("upnp", N_("Universal Plug'n'Play"))
+VLC_SD_PROBE_HELPER("upnp", N_("Universal Plug'n'Play"), SD_CAT_LAN)
 
 vlc_module_begin ()
     set_shortname( "UPnP")
diff --git a/modules/services_discovery/upnp_intel.cpp b/modules/services_discovery/upnp_intel.cpp
index 427c27e..a936de2 100644
--- a/modules/services_discovery/upnp_intel.cpp
+++ b/modules/services_discovery/upnp_intel.cpp
@@ -55,7 +55,7 @@ struct services_discovery_sys_t
 // VLC callback prototypes
 static int Open( vlc_object_t* );
 static void Close( vlc_object_t* );
-VLC_SD_PROBE_HELPER("upnp", N_("Universal Plug'n'Play"))
+VLC_SD_PROBE_HELPER("upnp", N_("Universal Plug'n'Play"), SD_CAT_LAN)
 
 // Module descriptor
 
diff --git a/modules/services_discovery/xcb_apps.c b/modules/services_discovery/xcb_apps.c
index 19ba85a..1757732 100644
--- a/modules/services_discovery/xcb_apps.c
+++ b/modules/services_discovery/xcb_apps.c
@@ -80,7 +80,7 @@ static int vlc_sd_probe_Open (vlc_object_t *obj)
         return VLC_PROBE_CONTINUE;
     xcb_disconnect (conn);
     return vlc_sd_probe_Add (probe, "xcb_apps{longname=\"Screen capture\"}",
-                             N_("Screen capture"));
+                             N_("Screen capture"), SD_CAT_DEVICES);
 }
 
 /**
diff --git a/src/playlist/services_discovery.c b/src/playlist/services_discovery.c
index 96b79af..88c0361 100644
--- a/src/playlist/services_discovery.c
+++ b/src/playlist/services_discovery.c
@@ -37,12 +37,13 @@ typedef struct
 {
     char *name;
     char *longname;
+    int category;
 } vlc_sd_probe_t;
 
 int vlc_sd_probe_Add (vlc_probe_t *probe, const char *name,
-                      const char *longname)
+                      const char *longname, int category)
 {
-    vlc_sd_probe_t names = { strdup(name), strdup(longname) };
+    vlc_sd_probe_t names = { strdup(name), strdup(longname), category };
 
     if (unlikely (names.name == NULL || names.longname == NULL
                || vlc_probe_add (probe, &names, sizeof (names))))
@@ -59,7 +60,7 @@ int vlc_sd_probe_Add (vlc_probe_t *probe, const char *name,
 /**
  * Gets the list of available services discovery plugins.
  */
-char **vlc_sd_GetNames (vlc_object_t *obj, char ***pppsz_longnames)
+char **vlc_sd_GetNames (vlc_object_t *obj, char ***pppsz_longnames, int **pp_categories)
 {
     size_t count;
     vlc_sd_probe_t *tab = vlc_probe (obj, "services probe", &count);
@@ -72,17 +73,22 @@ char **vlc_sd_GetNames (vlc_object_t *obj, char ***pppsz_longnames)
 
     char **names = malloc (sizeof(char *) * (count + 1));
     char **longnames = malloc (sizeof(char *) * (count + 1));
+    int *categories = malloc(sizeof(int) * (count + 1));
 
-    if (unlikely (names == NULL || longnames == NULL))
+    if (unlikely (names == NULL || longnames == NULL || categories == NULL))
         abort();
     for( size_t i = 0; i < count; i++ )
     {
         names[i] = tab[i].name;
         longnames[i] = tab[i].longname;
+        categories[i] = tab[i].category;
     }
     free (tab);
     names[count] = longnames[count] = NULL;
+    categories[count] = 0;
     *pppsz_longnames = longnames;
+    if( pp_categories ) *pp_categories = categories;
+    else free( categories );
     return names;
 }
 
-- 
1.6.3.3

