* Added a session announcement protol module (enabled by default).
authorArnaud Schauly <gitan@videolan.org>
Tue, 3 Dec 2002 16:29:04 +0000 (16:29 +0000)
committerArnaud Schauly <gitan@videolan.org>
Tue, 3 Dec 2002 16:29:04 +0000 (16:29 +0000)
* Added the PLAYLIST_CHECK_INSERT option to the playlist. That option
checks previously enqueued sessions before enqueing.

configure.ac.in
include/vlc/vlc.h
modules/misc/Modules.am
modules/misc/sap.c [new file with mode: 0644]
src/libvlc.c
src/libvlc.h
src/playlist/playlist.c

index aa8c1f9..863e745 100644 (file)
@@ -625,7 +625,7 @@ PLUGINS="${PLUGINS} wav araw demuxdump demuxsub"
 dnl
 dnl  Network modules
 dnl
-NETWORK_MODULES="access_udp access_http access_rtp ipv4 access_mms"
+NETWORK_MODULES="access_udp access_http access_rtp ipv4 access_mms sap"
 
 dnl
 dnl  Accelerated modules
index 769acc8..7949f0d 100644 (file)
@@ -2,7 +2,7 @@
  * vlc.h: global header for vlc
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vlc.h,v 1.17 2002/10/17 13:15:30 sam Exp $
+ * $Id: vlc.h,v 1.18 2002/12/03 16:29:04 gitan Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -74,10 +74,11 @@ typedef union
  *****************************************************************************/
 
 /* Used by playlist_Add */
-#define PLAYLIST_INSERT      0x0001
-#define PLAYLIST_REPLACE     0x0002
-#define PLAYLIST_APPEND      0x0004
-#define PLAYLIST_GO          0x0008
+#define PLAYLIST_INSERT          0x0001
+#define PLAYLIST_REPLACE         0x0002
+#define PLAYLIST_APPEND          0x0004
+#define PLAYLIST_GO              0x0008
+#define PLAYLIST_CHECK_INSERT    0x0010
 
 #define PLAYLIST_END           -666
 
index b6a1f2b..737f7a3 100644 (file)
@@ -1,2 +1,3 @@
 SOURCES_gtk_main = modules/misc/gtk_main.c
 SOURCES_gnome_main = modules/misc/gtk_main.c
+SOURCES_sap = modules/misc/sap.c
diff --git a/modules/misc/sap.c b/modules/misc/sap.c
new file mode 100644 (file)
index 0000000..e4cd566
--- /dev/null
@@ -0,0 +1,412 @@
+/*****************************************************************************
+ * sap.c :  SAP interface module
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: sap.c,v 1.1 2002/12/03 16:29:04 gitan Exp $
+ *
+ * Authors: Arnaud Schauly <gitan@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>
+
+#include <errno.h>                                                 /* ENOMEM */
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+
+#ifdef HAVE_UNISTD_H
+#    include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#endif
+#include <sys/types.h>
+
+
+#ifdef WIN32
+#   include <winsock2.h>
+#   include <ws2tcpip.h>
+#   ifndef IN_MULTICAST
+#       define IN_MULTICAST(a) IN_CLASSD(a)
+#   endif
+#else
+#   include <sys/socket.h>
+#   include <netinet/in.h>
+#   include <arpa/inet.h>
+#endif
+
+#include "network.h"
+
+#define MAX_LINE_LENGTH 256
+
+#define HELLO_PORT 9875  // SAP is aloways on that port
+#define HELLO_GROUP "239.255.255.255"   // FIX ME !!!!!!!!!!!!!!!
+#define ADD_SESSION 1;
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+
+
+
+static int  Activate     ( vlc_object_t * );
+static void Run          ( intf_thread_t *p_intf );
+static int Kill          ( intf_thread_t * );
+        
+static ssize_t NetRead    ( intf_thread_t*, int , byte_t *, size_t );
+
+typedef struct  sess_descr_s {
+/*    char *psz_version; // v field (protocol version) */
+    char *psz_origin; /* o field (username sess-id sess-version 
+                         nettype addrtype addr*/
+    char *psz_sessionname; 
+    char *psz_information; 
+    char *psz_uri; 
+    char *psz_emails;
+    char *psz_phone;  
+    char *psz_time; /* t start-time stop-time */
+    char *psz_repeat; /* r repeat-interval typed-time */
+    char *psz_attribute; 
+    char *psz_media; /* m media port protocol */
+} sess_descr_t;  
+/* All this informations are not useful yet.  */
+
+static int parse_sap ( char ** );
+static int packet_handle ( char **, intf_thread_t * );
+
+static sess_descr_t *  parse_sdp(char *  psz_pct) ;
+
+
+
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+    add_category_hint( N_("SAP"), NULL );
+        add_string( "sap-addr", NULL, NULL, 
+                     "SAP multicast address", "SAP multicast address" );
+    set_description( _("SAP interface module") );
+    set_capability( "interface", 0 );
+    set_callbacks( Activate, NULL);
+vlc_module_end();
+
+/*****************************************************************************
+ * Activate: initialize and create stuff
+ *****************************************************************************/
+static int Activate( vlc_object_t *p_this )
+{
+    intf_thread_t *p_intf = (intf_thread_t*)p_this;
+
+    p_intf->pf_run = Run;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Run: sap thread
+ *****************************************************************************
+ * Listens to SAP packets, and sends them to packet_handle
+ *****************************************************************************/
+
+static void Run( intf_thread_t *p_intf )
+{
+    char *psz_addr;
+    char *psz_network = NULL;
+    struct sockaddr_in addr;
+    struct ip_mreq mreq;
+    int fd,addrlen;
+    char *psz_buf;
+
+    module_t            *p_network;
+    network_socket_t    socket_desc;
+    
+    
+    if( !(psz_addr = config_GetPsz( p_intf, "sap-addr" ) ) )
+    {
+        psz_addr = strdup( HELLO_GROUP );
+    }
+    
+    /* Prepare the network_socket_t structure */
+    socket_desc.i_type = NETWORK_UDP;
+    socket_desc.psz_bind_addr = psz_addr;
+    socket_desc.i_bind_port   = HELLO_PORT;
+    socket_desc.psz_server_addr   = "";
+    socket_desc.i_server_port     = 0;
+    p_intf->p_private = (void*) &socket_desc;
+
+    psz_network = "ipv4";
+    
+    if( !( p_network = module_Need( p_intf, "network", psz_network ) ) )
+    {
+        msg_Err( p_intf, "failed to open a connection (udp)" );
+        return;
+    }
+    module_Unneed( p_intf, p_network ); 
+
+    fd = socket_desc.i_handle;
+    
+    psz_buf = malloc( 1500 ); // FIXME!!
+
+    /* read SAP packets */
+    while( !p_intf->b_die )
+    {
+        int i_read;
+        
+        addrlen=sizeof(addr);
+    
+    
+        memset(psz_buf, 0, 1500);
+        
+        i_read = NetRead( p_intf, fd, psz_buf, 1500 );
+        
+        if( i_read < 0 )
+        {
+            msg_Err( p_intf, "argggg" );
+        }
+        if( i_read == 0 )
+        {
+            continue;
+        }
+
+
+        msg_Dbg( p_intf, "New packet arrived" );
+        packet_handle( &psz_buf, p_intf  );
+                                   
+    }
+    free( psz_buf );
+
+}
+
+/********************************************************************
+ * Kill 
+ *******************************************************************
+ * Kills the SAP interface. 
+ ********************************************************************/
+static int Kill( intf_thread_t *p_intf )
+{
+
+    p_intf->b_die = VLC_TRUE;
+
+    return VLC_SUCCESS;
+}
+
+/********************************************************************
+ * parse_sap : Takes care of the SAP headers
+ ********************************************************************
+ * checks if the packet has the true headers ; 
+ ********************************************************************/
+
+static int parse_sap( char **  ppsz_sa_packet ) {  /* Dummy Parser : does nothing !*/
+/*   int j;
+   
+   for (j=0;j<255;j++) {
+       fprintf(stderr, "%c",(*ppsz_sa_packet)[j]);
+   }*/
+   
+   return ADD_SESSION; //Add this packet
+}
+
+/***********************************************************************
+ * packet_handle : handle the received packet and enques the 
+ * the understated session
+ * ******************************************************************/
+
+static int packet_handle( char **  ppsz_packet, intf_thread_t * p_intf )  {
+    int j=0;
+    sess_descr_t * sd;
+    playlist_t *p_playlist; 
+    char *  psz_enqueue;
+    char *  psz_udp = "udp://@\0";
+    int i;
+    
+    j=parse_sap( ppsz_packet ); 
+    
+    if(j != 0) {
+        msg_Dbg( p_intf, "SAP packet parsed");
+        sd = parse_sdp( * ppsz_packet ); 
+        
+        i = strlen( psz_udp ) + strlen( sd->psz_uri )+1 ;
+        psz_enqueue = malloc ( i * sizeof (char) );
+        memset( psz_enqueue, '\0',i );
+        strcat ( psz_enqueue,psz_udp );
+        strcat ( psz_enqueue,sd->psz_uri );
+        
+        p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+        playlist_Add ( p_playlist, psz_enqueue, PLAYLIST_CHECK_INSERT, PLAYLIST_END); 
+        msg_Dbg(p_intf,"SAP packet : End of treatment");
+        vlc_object_release( p_playlist );
+        
+        return 1;
+    }
+    free ( sd );
+    return 0; // Invalid Packet 
+}
+        
+
+
+
+/******************************************************
+ * parse_sap : SDP parsing
+ * ****************************************************
+ * Make a sess_descr_t with a psz
+ ******************************************************/
+
+static sess_descr_t *  parse_sdp(char *  psz_pct) 
+{
+    int j,k;
+    char **  ppsz_fill;
+    sess_descr_t *  sd;
+    
+    sd = malloc( sizeof(sess_descr_t) );
+    for (j=0 ; j < 255 ; j++) 
+    {
+       if (psz_pct[j] == '=') 
+       {           
+           switch(psz_pct[(j-1)]) {
+/*               case ('v') : {
+//               ppsz_fill = & sd->psz_version;
+//               break;
+            } */
+            case ('o') : {
+               ppsz_fill = & sd->psz_origin;
+               break;
+            }
+            case ('s') : {
+               ppsz_fill = & sd->psz_sessionname;
+               break;
+            }
+            case ('i') : {
+               ppsz_fill = & sd->psz_information;
+               break;
+            }
+            case ('u') : {
+               ppsz_fill = & sd->psz_uri;
+               break;
+            }
+            case ('e') : {
+               ppsz_fill = & sd->psz_emails;
+               break;
+            }
+            case ('p') : {
+               ppsz_fill = & sd->psz_phone;
+               break;
+            }
+            case ('t') : {
+               ppsz_fill = & sd->psz_time;
+               break;
+            }
+            case ('r') : {
+               ppsz_fill = & sd->psz_repeat;
+               break;
+            }
+            case ('a') : {
+               ppsz_fill = & sd->psz_attribute;
+               break;
+            }
+            case ('m') : {
+               ppsz_fill = & sd->psz_media;
+               break;
+            }
+
+            default : { 
+               fprintf( stderr,"Warning : Ignored field \"%c\" \n",psz_pct[j-1] );
+               ppsz_fill = NULL;
+            }
+
+
+         } 
+      k=0;j++;
+      while (psz_pct[j] != '\n'&& psz_pct[j] != EOF) {
+         k++; j++;
+      }
+      j--;
+      if( ppsz_fill != NULL )
+      {
+         *ppsz_fill= malloc( sizeof(char) * (k+1) );
+         memccpy(*ppsz_fill, &(psz_pct[j-k+1]),'\n',  k ); 
+         (*ppsz_fill)[k]='\0';
+      }
+      ppsz_fill = NULL;
+
+      } // if
+   } //for
+
+   return sd;
+}
+
+
+
+/*****************************************************************************
+ * Read: read on a file descriptor, checking b_die periodically
+ *****************************************************************************
+ * Taken from udp.c
+ ******************************************************************************/
+static ssize_t NetRead( intf_thread_t *p_intf, 
+                        int i_handle, byte_t *p_buffer, size_t i_len)
+{
+#ifdef UNDER_CE
+    return -1;
+    
+#else
+    struct timeval  timeout;
+    fd_set          fds;
+    int             i_ret;
+    
+    /* Initialize file descriptor set */
+    FD_ZERO( &fds );
+    FD_SET( i_handle, &fds );
+    
+    /* We'll wait 0.5 second if nothing happens */
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 500000;
+    
+    /* Find if some data is available */
+    i_ret = select( i_handle + 1, &fds,
+    NULL, NULL, &timeout );
+    
+    if( i_ret == -1 && errno != EINTR )
+    {
+        msg_Err( p_intf, "network select error (%s)", strerror(errno) );
+    }
+    else if( i_ret > 0 )
+    {
+        ssize_t i_recv = recv( i_handle, p_buffer, i_len, 0 );
+    
+        if( i_recv < 0 )
+        {
+           msg_Err( p_intf, "recv failed (%s)", strerror(errno) );
+        }
+    
+        return i_recv;
+    }
+    
+    return 0;
+
+#endif
+}
+
index 9a267ee..2d6679a 100644 (file)
@@ -2,7 +2,7 @@
  * libvlc.c: main libvlc source
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: libvlc.c,v 1.48 2002/11/28 17:35:00 sam Exp $
+ * $Id: libvlc.c,v 1.49 2002/12/03 16:29:04 gitan Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -755,7 +755,15 @@ int VLC_Play( int i_object )
     {
         return VLC_ENOOBJ;
     }
+    
+    /* add pseudo sap interface; non blocking */
+    if( config_GetInt( p_vlc, "sap" ) )
+    {
+        msg_Dbg( p_vlc, "adding sap interface" );
+        VLC_AddIntf( 0, "sap", VLC_FALSE );
+    }
 
+    
     p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_CHILD );
 
     if( !p_playlist )
index ca72062..cfbb9be 100644 (file)
@@ -2,7 +2,7 @@
  * libvlc.h: main libvlc header
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: libvlc.h,v 1.24 2002/12/03 12:59:21 sam Exp $
+ * $Id: libvlc.h,v 1.25 2002/12/03 16:29:04 gitan Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
     "\n  vlc:quit                       quit VLC" \
     "\n")
 
+#define SAP_TEXT N_( "Session Announcement Protocol support" )
+#define SAP_LONGTEXT N_( "Session Announcement Protocol support" )
+
+
 /*
  * Quick usage guide for the configuration options:
  *
@@ -475,6 +479,7 @@ vlc_module_begin();
 
     /* Misc options */
     add_category_hint( N_("Miscellaneous"), NULL );
+    add_bool( "sap", 1, NULL, SAP_TEXT, SAP_LONGTEXT );
     add_module( "memcpy", "memcpy", NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT );
     add_module( "access", "access", NULL, NULL, ACCESS_TEXT, ACCESS_LONGTEXT );
     add_module( "demux", "demux", NULL, NULL, DEMUX_TEXT, DEMUX_LONGTEXT );
index e5c15c1..5345b93 100644 (file)
@@ -2,7 +2,7 @@
  * playlist.c : Playlist management functions
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: playlist.c,v 1.23 2002/11/21 15:51:57 gbazin Exp $
+ * $Id: playlist.c,v 1.24 2002/12/03 16:29:04 gitan Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -105,8 +105,37 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
 {
     playlist_item_t *p_item;
 
-    msg_Dbg( p_playlist, "adding playlist item « %s »", psz_target );
 
+    vlc_mutex_lock( &p_playlist->object_lock );
+
+    /*
+     * CHECK_INSERT : checks if the item is already enqued before 
+     * enqueing it
+     */
+    if ( i_mode & PLAYLIST_CHECK_INSERT )
+    {
+         int j;
+       
+         if ( p_playlist->pp_items )
+         {
+             for ( j = 0; j < p_playlist->i_size; j++ )
+             {
+                 if ( !strcmp( p_playlist->pp_items[j]->psz_name, psz_target ) )
+                 {
+                      msg_Dbg( p_playlist, "item « %s » already enqued", 
+                                        psz_target );
+                      vlc_mutex_unlock( &p_playlist->object_lock );
+                      return 0;   
+                 }
+             }
+         }
+         i_mode &= ~PLAYLIST_CHECK_INSERT;
+         i_mode |= PLAYLIST_APPEND;
+    }
+
+    
+    msg_Dbg( p_playlist, "adding playlist item « %s »", psz_target );
+    
     /* Create the new playlist item */
     p_item = malloc( sizeof( playlist_item_t ) );
     if( p_item == NULL )
@@ -119,7 +148,6 @@ int playlist_Add( playlist_t *p_playlist, const char * psz_target,
     p_item->i_status = 0;
     p_item->b_autodeletion = VLC_FALSE;
 
-    vlc_mutex_lock( &p_playlist->object_lock );
 
     /* Do a few boundary checks and allocate space for the item */
     if( i_pos == PLAYLIST_END )