]> git.sesse.net Git - vlc/blobdiff - modules/services_discovery/sap.c
* configure.ac: alsa is now really default enabled
[vlc] / modules / services_discovery / sap.c
index fb538325526c47d576bce763c78a4f41fa878d54..a923eae355a3ad9832b0b45ae9d9ad0f418a4543 100644 (file)
@@ -32,6 +32,7 @@
 #include <vlc/input.h>
 
 #include "network.h"
+#include "charset.h"
 
 #include <errno.h>                                                 /* ENOMEM */
 
     static void CloseDemux ( vlc_object_t * );
 
 vlc_module_begin();
-    set_description( _("SAP interface") );
+    set_shortname( _("SAP"));
+    set_description( _("SAP announces") );
     set_category( CAT_PLAYLIST );
     set_subcategory( SUBCAT_PLAYLIST_SD );
 
@@ -201,6 +203,9 @@ struct services_discovery_sys_t
     /* playlist node */
     playlist_item_t *p_node;
 
+    /* charset conversion */
+    vlc_iconv_t iconvHandle;
+
     /* Table of announces */
     int i_announces;
     struct sap_announce_t **pp_announces;
@@ -240,6 +245,8 @@ struct demux_sys_t
 /* Helper functions */
    static char *GetAttribute( sdp_t *p_sdp, const char *psz_search );
    static vlc_bool_t IsSameSession( sdp_t *p_sdp1, sdp_t *p_sdp2 );
+   static char *convert_from_utf8( struct services_discovery_t *p_sd,
+                                   char *psz_unicode );
    static int InitSocket( services_discovery_t *p_sd, char *psz_address, int i_port );
 #ifdef HAVE_ZLIB_H
    static int Decompress( unsigned char *psz_src, unsigned char **_dst, int i_len );
@@ -262,11 +269,19 @@ static int Open( vlc_object_t *p_this )
 
     playlist_t          *p_playlist;
     playlist_view_t     *p_view;
-    char                *psz_addr;
+    char                *psz_addr, *psz_charset;
     vlc_value_t         val;
 
     p_sys->i_timeout = config_GetInt( p_sd,"sap-timeout" );
 
+    vlc_current_charset( &psz_charset );
+    p_sys->iconvHandle = vlc_iconv_open( psz_charset, "UTF-8" );
+    free( psz_charset );
+    if( p_sys->iconvHandle == (vlc_iconv_t)(-1) )
+    {
+        msg_Warn( p_sd, "Unable to do requested conversion" );
+    }
+
     p_sd->pf_run = Run;
     p_sd->p_sys  = p_sys;
 
@@ -350,31 +365,25 @@ static int OpenDemux( vlc_object_t *p_this )
     uint8_t *p_peek;
     int i_max_sdp = 1024;
     int i_sdp = 0;
-    char *psz_sdp = (char *)malloc( i_max_sdp );
+    char *psz_sdp = NULL;
     sdp_t *p_sdp = NULL;
 
-    if( !psz_sdp )
-    {
-        return VLC_EGENERIC;
-    }
-
     /* Probe for SDP */
     if( p_demux->s )
     {
-        if( stream_Peek( p_demux->s, &p_peek, 7 ) < 7 )
-        {
-            msg_Err( p_demux, "cannot peek" );
-            return VLC_EGENERIC;
-        }
+        if( stream_Peek( p_demux->s, &p_peek, 7 ) < 7 ) return VLC_EGENERIC;
+
         if( strncmp( (char*)p_peek, "v=0\r\n", 5 ) &&
             strncmp( (char*)p_peek, "v=0\n", 4 ) &&
             ( p_peek[0] < 'a' || p_peek[0] > 'z' || p_peek[1] != '=' ) )
         {
-            msg_Warn( p_demux, "SDP (UDP) module discarded" );
             return VLC_EGENERIC;
         }
     }
 
+    psz_sdp = (char *)malloc( i_max_sdp );
+    if( !psz_sdp ) return VLC_EGENERIC;
+
     /* Gather the complete sdp file */
     for( ;; )
     {
@@ -416,7 +425,8 @@ static int OpenDemux( vlc_object_t *p_this )
     {
         p_sdp->psz_uri = NULL;
     }
-    if( p_sdp->i_media_type != 33 && p_sdp->i_media_type != 32 && p_sdp->i_media_type != 14 )
+    if( p_sdp->i_media_type != 33 && p_sdp->i_media_type != 32 &&
+        p_sdp->i_media_type != 14 )
         goto error;
 
     if( p_sdp->psz_uri == NULL ) goto error;
@@ -467,10 +477,13 @@ static void Close( vlc_object_t *p_this )
 
     if( p_playlist )
     {
-        playlist_NodeDelete( p_playlist, p_sys->p_node, VLC_TRUE );
+        playlist_NodeDelete( p_playlist, p_sys->p_node, VLC_TRUE , VLC_TRUE );
         vlc_object_release( p_playlist );
     }
 
+    if( p_sys->iconvHandle != (vlc_iconv_t)(-1) )
+        vlc_iconv_close( p_sys->iconvHandle );
+
     free( p_sys );
 }
 
@@ -590,7 +603,7 @@ static int Demux( demux_t *p_demux )
                  PLAYLIST_APPEND, PLAYLIST_END );
 
    vlc_object_release( p_playlist );
-    if( p_sdp ) FreeSDP( p_sdp );
+   if( p_sdp ) FreeSDP( p_sdp );
 
    return VLC_SUCCESS;
 }
@@ -621,7 +634,6 @@ static int ParseSAP( services_discovery_t *p_sd, uint8_t *p_buffer, int i_read )
 
     /* First, check the sap announce is correct */
     i_version = p_buffer[0] >> 5;
-
     if( i_version != 1 )
     {
        msg_Dbg( p_sd, "strange sap version %d found", i_version );
@@ -795,9 +807,13 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
     char                *psz_value;
     sap_announce_t *p_sap = (sap_announce_t *)malloc(
                                         sizeof(sap_announce_t ) );
-    if( !p_sap )
+
+    psz_value = convert_from_utf8( p_sd, p_sdp->psz_sessionname );
+    if( p_sap == NULL || psz_value == NULL )
     {
         msg_Err( p_sd, "out of memory");
+        FREE( p_sap );
+        FREE( psz_value );
         p_sd->b_die = VLC_TRUE;
         return NULL;
     }
@@ -807,14 +823,26 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
     p_sap->p_item = NULL;
 
     /* Create the playlist item here */
-    p_item = playlist_ItemNew( p_sd, p_sap->p_sdp->psz_uri,
-                               p_sap->p_sdp->psz_sessionname );
+    p_item = playlist_ItemNew( p_sd, p_sap->p_sdp->psz_uri, psz_value );
+    free( psz_value );
 
     if( !p_item )
     {
         return NULL;
     }
 
+    psz_value = GetAttribute( p_sap->p_sdp, "tool" );
+    if( psz_value != NULL )
+    {
+        vlc_input_item_AddInfo( &p_item->input, _("Session"),
+                                _("Tool"), psz_value );
+    }
+    if( strcmp( p_sdp->psz_username, "-" ) )
+    {
+        vlc_input_item_AddInfo( &p_item->input, _("Session"),
+                                _("User"), p_sdp->psz_username );
+    }
+
     psz_value = GetAttribute( p_sap->p_sdp, "x-plgroup" );
 
     if( psz_value == NULL )
@@ -834,12 +862,24 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
 
     if( psz_value != NULL )
     {
-        p_child = playlist_ChildSearchName( p_sd->p_sys->p_node, psz_value );
+        char *psz_grp = convert_from_utf8( p_sd, psz_value );
 
-        if( p_child == NULL )
+        if( psz_grp != NULL )
         {
-            p_child = playlist_NodeCreate( p_playlist, VIEW_CATEGORY,
-                                           psz_value, p_sd->p_sys->p_node );
+            p_child = playlist_ChildSearchName( p_sd->p_sys->p_node,
+                                                psz_grp );
+
+            if( p_child == NULL )
+                p_child = playlist_NodeCreate( p_playlist, VIEW_CATEGORY,
+                                               psz_grp, p_sd->p_sys->p_node );
+            free( psz_grp );
+        }
+        else
+        {
+            vlc_object_release( p_playlist );
+            msg_Err( p_sd, "out of memory");
+            free( p_sap );
+            return NULL;
         }
     }
     else
@@ -848,6 +888,7 @@ sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
     }
 
     p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;
+    p_item->i_flags &= ~PLAYLIST_SAVE_FLAG;
 
     playlist_NodeAddItem( p_playlist, p_item, VIEW_CATEGORY, p_child,
                           PLAYLIST_APPEND, PLAYLIST_END );
@@ -938,7 +979,7 @@ static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp )
         }
         else
         {
-            msg_Dbg( p_obj, "incorrect c field");
+            msg_Dbg( p_obj, "incorrect c field, %s", p_sdp->psz_connection );
         }
         psz_uri = strdup( psz_parse );
 
@@ -1008,7 +1049,7 @@ static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp )
         }
         else
         {
-            msg_Dbg( p_obj, "incorrect m field");
+            msg_Dbg( p_obj, "incorrect m field, %s", p_sdp->psz_media );
             p_sdp->i_media_type = 33;
             psz_proto = strdup( psz_parse );
         }
@@ -1024,7 +1065,6 @@ static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp )
         free( psz_proto );
         psz_proto = strdup( "udp" );
     }
-                    
 
     /* FIXME: HTTP support */
 
@@ -1056,7 +1096,6 @@ static sdp_t *  ParseSDP( vlc_object_t *p_obj, char* psz_sdp )
     sdp_t *p_sdp;
     vlc_bool_t b_invalid = VLC_FALSE;
     vlc_bool_t b_end = VLC_FALSE;
-
     if( psz_sdp == NULL )
     {
         return NULL;
@@ -1239,6 +1278,38 @@ static sdp_t *  ParseSDP( vlc_object_t *p_obj, char* psz_sdp )
 }
 
 
+static char *convert_from_utf8( struct services_discovery_t *p_sd,
+                                char *psz_unicode )
+{
+    char *psz_local, *psz_in, *psz_out;
+    size_t ret, i_in, i_out;
+
+    if( psz_unicode == NULL )
+        return NULL;
+    if ( p_sd->p_sys->iconvHandle == (vlc_iconv_t)(-1) )
+        return strdup( psz_unicode );
+
+    psz_in = psz_unicode;
+    i_in = strlen( psz_unicode );
+
+    i_out = 2 * i_in;
+    psz_local = malloc( i_out + 1 );
+    if( psz_local == NULL )
+        return strdup( psz_unicode );
+    psz_out = psz_local;
+
+    ret = vlc_iconv( p_sd->p_sys->iconvHandle,
+                     &psz_in, &i_in, &psz_out, &i_out);
+    if( ret == (size_t)(-1) || i_in )
+    {
+        msg_Warn( p_sd, "Failed to convert \"%s\" from UTF-8", psz_unicode );
+        return strdup( psz_unicode );
+    }
+    *psz_out = '\0';
+    return psz_local;
+}
+
+
 /***********************************************************************
  * ismult: returns true if we have a multicast address
  ***********************************************************************/