From e5daac69bbf814759ffe6ab126aacffe2efb340a Mon Sep 17 00:00:00 2001 From: Arnaud Schauly Date: Tue, 3 Dec 2002 16:29:04 +0000 Subject: [PATCH] * Added a session announcement protol module (enabled by default). * Added the PLAYLIST_CHECK_INSERT option to the playlist. That option checks previously enqueued sessions before enqueing. --- configure.ac.in | 2 +- include/vlc/vlc.h | 11 +- modules/misc/Modules.am | 1 + modules/misc/sap.c | 412 ++++++++++++++++++++++++++++++++++++++++ src/libvlc.c | 10 +- src/libvlc.h | 7 +- src/playlist/playlist.c | 34 +++- 7 files changed, 466 insertions(+), 11 deletions(-) create mode 100644 modules/misc/sap.c diff --git a/configure.ac.in b/configure.ac.in index aa8c1f99b6..863e745d30 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -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 diff --git a/include/vlc/vlc.h b/include/vlc/vlc.h index 769acc894f..7949f0d9cc 100644 --- a/include/vlc/vlc.h +++ b/include/vlc/vlc.h @@ -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 diff --git a/modules/misc/Modules.am b/modules/misc/Modules.am index b6a1f2b3fc..737f7a35e5 100644 --- a/modules/misc/Modules.am +++ b/modules/misc/Modules.am @@ -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 index 0000000000..e4cd566eab --- /dev/null +++ b/modules/misc/sap.c @@ -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 + * + * 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 /* malloc(), free() */ +#include + +#include /* ENOMEM */ +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SYS_TIME_H +# include +#endif +#include + + +#ifdef WIN32 +# include +# include +# ifndef IN_MULTICAST +# define IN_MULTICAST(a) IN_CLASSD(a) +# endif +#else +# include +# include +# include +#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 +} + diff --git a/src/libvlc.c b/src/libvlc.c index 9a267eef97..2d6679aa60 100644 --- a/src/libvlc.c +++ b/src/libvlc.c @@ -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 * Samuel Hocevar @@ -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 ) diff --git a/src/libvlc.h b/src/libvlc.h index ca72062675..cfbb9be627 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -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 * Samuel Hocevar @@ -358,6 +358,10 @@ "\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 ); diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c index e5c15c1118..5345b93808 100644 --- a/src/playlist/playlist.c +++ b/src/playlist/playlist.c @@ -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 * @@ -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 ) -- 2.39.2