]> git.sesse.net Git - vlc/blobdiff - modules/access/slp.c
* include/configuration.h: added a new flag to the configuration stucture to
[vlc] / modules / access / slp.c
index 06b027231e4047afe233cc409534aaf65685013d..45cc05cb3f2953080d34e854b4e2c812ae94afc8 100644 (file)
@@ -2,7 +2,7 @@
  * slp.c: SLP access plugin
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: slp.c,v 1.1 2003/01/10 04:58:23 lool Exp $
+ * $Id: slp.c,v 1.8 2003/02/20 01:52:45 sigmunau Exp $
  *
  * Authors: Loïc Minier <lool@videolan.org>
  *
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
+#include <stdlib.h>                                                /* malloc */
+
 #include <vlc/vlc.h>
 #include <vlc/input.h>
 
+#include <vlc_playlist.h>
+
 #include <slp.h>
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int  Open       ( vlc_object_t * );
-static void Close      ( vlc_object_t * );
+static int  Open  ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static ssize_t Read  ( input_thread_t *, byte_t *, size_t );
+
+static int  Init  ( vlc_object_t * );
+static void End   ( vlc_object_t * );
+static int  Demux ( input_thread_t * );
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
 
-#define SRVTYPE_TEXT "SLP service type"
+#define SRVTYPE_TEXT     "SLP service type"
 #define SRVTYPE_LONGTEXT "The service type string for SLP queries, " \
                          "including the authority string (if any) for the " \
                          "request. May not be empty"
-#define SCOPELIST_TEXT "SLP scopes list"
+#define ATTRIDS_TEXT     "SLP attribute identifiers"
+#define ATTRIDS_LONGTEXT "This string is a comma separated list of " \
+                         "attribute identifiers to search for a playlist "\
+                         "title or empty to use all attributes"
+#define SCOPELIST_TEXT     "SLP scopes list"
 #define SCOPELIST_LONGTEXT "This string is a comma separated list of scope " \
                            "names or empty if you want to use the default "  \
-                           "scopes"
-#define FILTER_TEXT "SLP LDAP filter"
+                           "scopes; it is used in all SLP queries"
+#define NAMINGAUTHORITY_TEXT     "SLP naming authority"
+#define NAMINGAUTHORITY_LONGTEXT "This string is a list of naming " \
+                                 "authorities to search. Use \"*\" for all " \
+                                 "and the empty string for the default of " \
+                                 "IANA"
+#define FILTER_TEXT     "SLP LDAP filter"
 #define FILTER_LONGTEXT "This is a query formulated of attribute pattern " \
                         "matching expressions in the form of an LDAPv3 "   \
                         "search filter or empty for all answers"
-#define LANG_TEXT "language asked in SLP requests"
+#define LANG_TEXT     "language requested in SLP requests"
 #define LANG_LONGTEXT "RFC 1766 Language Tag for the natural language " \
                       "locale of requests, leave empty to use the "     \
-                      "default locale"
+                      "default locale; it is used in all SLP queries"
 
 vlc_module_begin();
     set_description( _("SLP access module") );
-    add_category_hint( N_("slp"), NULL );
-    set_capability( "access", 0 );
-    add_shortcut( "slp" );
-    add_string( "slp-srvtype", "service:vls.services.videolan.org:udpm",
-                NULL, SRVTYPE_TEXT, SRVTYPE_LONGTEXT );
+    add_category_hint( N_("slp"), NULL, VLC_TRUE );
+    add_string( "slp-attrids", "", NULL, ATTRIDS_TEXT, ATTRIDS_LONGTEXT, VLC_TRUE );
     add_string( "slp-scopelist", "", NULL, SCOPELIST_TEXT,
-                SCOPELIST_LONGTEXT );
-    add_string( "slp-filter", "", NULL, FILTER_TEXT, FILTER_LONGTEXT );
-    add_string( "slp-lang", "", NULL, LANG_TEXT, LANG_LONGTEXT );
-    set_callbacks( Open, Close );
+                SCOPELIST_LONGTEXT, VLC_TRUE );
+    add_string( "slp-namingauthority", "*", NULL, NAMINGAUTHORITY_TEXT,
+                NAMINGAUTHORITY_LONGTEXT, VLC_TRUE );
+    add_string( "slp-filter", "", NULL, FILTER_TEXT, FILTER_LONGTEXT, VLC_TRUE );
+    add_string( "slp-lang", "", NULL, LANG_TEXT, LANG_LONGTEXT, VLC_TRUE );
+    add_submodule();
+        set_capability( "access", 0 );
+        set_callbacks( Open, Close );
+    add_submodule();
+        add_shortcut( "demux_slp" );
+        set_capability( "demux", 0 );
+        set_callbacks( Init, End );
 vlc_module_end();
 
+/*****************************************************************************
+ * AttrCallback: updates the description of a playlist item
+ *****************************************************************************/
+static SLPBoolean AttrCallback( SLPHandle slph_slp,
+                           const char * psz_attrlist,
+                           SLPError slpe_errcode,
+                           void * p_cookie )
+{
+    playlist_item_t * p_playlist_item = (playlist_item_t *)p_cookie;
+
+    /* our callback was only called to tell us there's nothing more to read */
+    if( slpe_errcode == SLP_LAST_CALL )
+    {
+        return SLP_TRUE;
+    }
+
+    /* or there was a problem with getting the data we requested */
+    if( (slpe_errcode != SLP_OK) )
+    {
+/*        msg_Err( (vlc_object_t*)NULL,
+                 "AttrCallback got an error %i with attribute %s",
+                 slpe_errcode,
+                 psz_attrlist ); */
+        return SLP_TRUE;
+    }
+
+    p_playlist_item->psz_name = strdup(psz_attrlist);     /* NULL is checked */
+    return SLP_TRUE;
+}
+
 /*****************************************************************************
  * SrvUrlCallback: adds an entry to the playlist
  *****************************************************************************/
-static SLPBoolean SrvUrlCallback( SLPHandle hslp,
+static SLPBoolean SrvUrlCallback( SLPHandle slph_slp,
                            const char * psz_srvurl,
                            uint16_t i_lifetime,
                            SLPError slpe_errcode,
-                           void * p_input )
+                           void * p_cookie )
 {
+    input_thread_t * p_input = (input_thread_t  *)p_cookie;
     playlist_t * p_playlist;
     char psz_item[42] = "udp:@";
-    char * psz_s;
+    char * psz_s;                           /* to hold the uri of the stream */
+    SLPHandle slph_slp3;
+    SLPError slpe_result;
+    playlist_item_t * p_playlist_item;
 
-    if( slpe_errcode == SLP_OK )
+    /* our callback was only called to tell us there's nothing more to read */
+    if( slpe_errcode == SLP_LAST_CALL )
     {
-        p_playlist = vlc_object_find( (input_thread_t *)p_input,
-                                      VLC_OBJECT_PLAYLIST,
-                                      FIND_ANYWHERE );
-        if( p_playlist == NULL )
-        {
-            msg_Dbg( (input_thread_t *)p_input, "could not find playlist" );
-            return SLP_FALSE;
-        }
+        return SLP_TRUE;
+    }
 
-        /* search the returned address after a double-slash */
-        psz_s = strstr( psz_srvurl, "//" );
-        /* skip the slashes */
-        psz_s = &psz_s[2];
-        if( psz_s == NULL )
-        {
-            msg_Dbg( (input_thread_t *)p_input,
-                     "something went wrong with your libslp" );
-            return SLP_FALSE;
-        }
-        /* add udp:@ in front of the address */
-        psz_s = strncat( psz_item,
-                         psz_s,
-                         sizeof(psz_item) - strlen(psz_item) - 1 );
-        playlist_Add( p_playlist, psz_s,
-                      PLAYLIST_APPEND | PLAYLIST_GO,
-                      PLAYLIST_END );
-        vlc_object_release( (vlc_object_t *)p_playlist );
+    /* or there was a problem with getting the data we requested */
+    if( (slpe_errcode != SLP_OK) )
+    {
+        msg_Err( p_input,
+                 "SrvUrlCallback got an error %i with URL %s",
+                 slpe_errcode,
+                 psz_srvurl );
+        return SLP_TRUE;
+    }
+
+    /* search the returned address after a double-slash */
+    psz_s = strstr( psz_srvurl, "//" );
+    if( psz_s == NULL )
+    {
+        msg_Err( (input_thread_t *)p_input,
+                 "SrvUrlCallback got a strange string of your libslp" );
+        return SLP_TRUE;
+    }
+    /* skip the slashes */
+    psz_s = &psz_s[2];
+    /* add udp:@ in front of the address */
+    psz_s = strncat( psz_item,
+                     psz_s,
+                     sizeof(psz_item) - strlen(psz_item) - 1 );
 
-        msg_Dbg( (input_thread_t *)p_input,
-                 "added « %s » (lifetime %i) to playlist",
-                 psz_srvurl,
-                 i_lifetime );
+    /* create a playlist  item */
+    p_playlist_item = malloc( sizeof( playlist_item_t ) );
+    if( p_playlist_item == NULL )
+    {
+        msg_Err( p_input, "out of memory" );
+        return SLP_TRUE;
+    }
+
+    p_playlist_item->psz_name = NULL;
+    p_playlist_item->psz_uri  = strdup( psz_s );
+    p_playlist_item->i_type = 0;
+    p_playlist_item->i_status = 0;
+    p_playlist_item->b_autodeletion = VLC_FALSE;
+
+    /* search the description of the stream */
+    if( SLPOpen( config_GetPsz( p_input, "slp-lang" ),
+                 SLP_FALSE,                              /* synchronous ops */
+                 &slph_slp3 ) == SLP_OK )
+    {
+        /* search all attributes */
+        slpe_result = SLPFindAttrs( slph_slp3,
+                                    psz_srvurl,
+                                    config_GetPsz( p_input, "slp-scopelist" ),
+                                    config_GetPsz( p_input, "slp-attrids" ),
+                                    AttrCallback,
+                                    p_playlist_item
+                                  );
+
+        /* we're done, clean up */
+        SLPClose( slph_slp3 );
+    }
+
+    /* add a default name if we found no attribute */
+    if( p_playlist_item->psz_name == NULL )
+    {
+        p_playlist_item->psz_name = strdup( psz_s );
+    }
+
+    /* search the main playlist object */
+    p_playlist = vlc_object_find( (input_thread_t *)p_input,
+                                  VLC_OBJECT_PLAYLIST,
+                                  FIND_ANYWHERE );
+    if( p_playlist == NULL )
+    {
+        msg_Warn( (input_thread_t *)p_input,
+                  "could not find playlist, not adding entries" );
+        return SLP_TRUE;
     }
 
+    playlist_AddItem( p_playlist,
+                      p_playlist_item,
+                      PLAYLIST_APPEND,
+                      PLAYLIST_END );
+    vlc_object_release( (vlc_object_t *)p_playlist );
+
+    msg_Info( (input_thread_t *)p_input,
+             "added « %s » (lifetime %i) to playlist",
+             psz_srvurl,
+             i_lifetime );
+
     return SLP_TRUE;
 }
 
 /*****************************************************************************
- * Open: initialize library
+ * SrvTypeCallback: searchs all servers of a certain type
  *****************************************************************************/
-static int Open( vlc_object_t * p_this )
+static SLPBoolean SrvTypeCallback( SLPHandle slph_slp,
+                           const char * psz_srvurl,
+                           SLPError slpe_errcode,
+                           void * p_cookie )
 {
-    input_thread_t * p_input = (input_thread_t *)p_this;
-    char *           psz_name = strdup(p_input->psz_name);
-    SLPError         slpe_result;
-    SLPHandle        slph_slp;
+    input_thread_t * p_input = (input_thread_t  *)p_cookie;
+    SLPError slpe_result;
+    SLPHandle slph_slp2;
+
+    /* our callback was only called to tell us there's nothing more to read */
+    if( slpe_errcode == SLP_LAST_CALL )
+    {
+        return SLP_TRUE;
+    }
+
+    /* or there was a problem with getting the data we requested */
+    if( slpe_errcode != SLP_OK )
+    {
+        msg_Err( p_input,
+                 "SrvTypeCallback got an error %i with URL %s",
+                 slpe_errcode,
+                 psz_srvurl );
+        return SLP_TRUE;
+    }
 
     /* get a new handle to the library */
     if( SLPOpen( config_GetPsz( p_input, "slp-lang" ),
                  SLP_FALSE,                              /* synchronous ops */
-                 &slph_slp ) == SLP_OK )
+                 &slph_slp2 ) == SLP_OK )
     {
         /* search for services */
-        slpe_result = SLPFindSrvs( slph_slp,
-                                   config_GetPsz( p_input, "slp-srvtype" ),
+        slpe_result = SLPFindSrvs( slph_slp2,
+                                   psz_srvurl,
                                    config_GetPsz( p_input, "slp-scopelist" ),
                                    config_GetPsz( p_input, "slp-filter" ),
                                    SrvUrlCallback,
                                    p_input );
+
+        SLPClose( slph_slp2 );
+
         if( slpe_result != SLP_OK )
         {
-            msg_Dbg( p_input,
-                     "slp error opening %s: %i",
-                     psz_name,
-                     slpe_result );
+            msg_Err( p_input,
+                     "SLPFindSrvs error %i finding servers of type %s",
+                     slpe_result,
+                     psz_srvurl );
         }
+    }
+
+    return SLP_TRUE;
+}
+
+/*****************************************************************************
+ * Open: initialize library for the access module
+ *****************************************************************************/
+static int Open( vlc_object_t * p_this )
+{
+    input_thread_t * p_input = (input_thread_t *)p_this;
+    SLPError         slpe_result;
+    SLPHandle        slph_slp;
+    playlist_t *     p_playlist;
+
+    /* remove the "slp:" entry of the playlist */
+    p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
+                                                 FIND_ANYWHERE );
+    if( !p_playlist )
+    {
+        msg_Warn( p_input, "hey I can't find the main playlist, I need it" );
+        return VLC_FALSE;
+    }
+
+    p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
+    vlc_object_release( (vlc_object_t *)p_playlist );
+
+    /* get a new handle to the library */
+    if( SLPOpen( config_GetPsz( p_input, "slp-lang" ),
+                 SLP_FALSE,                              /* synchronous ops */
+                 &slph_slp ) == SLP_OK )
+    {
+        /* search all service types */
+        slpe_result =
+            SLPFindSrvTypes( slph_slp,
+                             config_GetPsz( p_input, "slp-namingauthority" ),
+                             config_GetPsz( p_input, "slp-scopelist" ),
+                             SrvTypeCallback,
+                             p_input );
         /* we're done, clean up */
         SLPClose( slph_slp );
     }
 
-    return( -1 );
+    if( !p_input->psz_demux || !*p_input->psz_demux )
+    {
+        p_input->psz_demux = "demux_slp";
+    }
+
+    p_input->pf_read = Read;
+    p_input->pf_set_program = NULL;
+    p_input->pf_set_area = NULL;
+    p_input->pf_seek = NULL;
+
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+    p_input->stream.b_pace_control = VLC_FALSE;
+    p_input->stream.b_seekable = VLC_FALSE;
+    p_input->stream.b_connected = VLC_TRUE;
+    p_input->stream.p_selected_area->i_tell = 0;
+    p_input->stream.p_selected_area->i_size = 0;
+    p_input->stream.i_method = INPUT_METHOD_SLP;
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    p_input->i_mtu = 0;
+
+    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
- * Close: free unused data structures
+ * Close: close access
  *****************************************************************************/
 static void Close( vlc_object_t * p_this )
 {
+    return;
+}
+
+/*****************************************************************************
+ * Read: should fill but zeroes the buffer
+ *****************************************************************************/
+static ssize_t Read  ( input_thread_t *p_input, byte_t *p_buffer, size_t s )
+{
+    memset( p_buffer, 0, s );
+    return s;
+}
+
+/*****************************************************************************
+ * Init: initialize demux
+ *****************************************************************************/
+static int Init ( vlc_object_t *p_this )
+{
+    input_thread_t *p_input = (input_thread_t *)p_this;
 
+    if( p_input->stream.i_method != INPUT_METHOD_SLP )
+    {
+        return VLC_FALSE;
+    }
+
+    p_input->pf_demux  = Demux;
+    p_input->pf_rewind = NULL;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Demux: should demux but does nothing
+ *****************************************************************************/
+static int Demux ( input_thread_t * p_input )
+{
+    return 0;
+}
+
+/*****************************************************************************
+ * End: end demux
+ *****************************************************************************/
+static void End ( vlc_object_t *p_this )
+{
+    return;
 }