* Module descriptor
*****************************************************************************/
#define SAP_ADDR_TEXT N_( "SAP multicast address" )
-#define SAP_ADDR_LONGTEXT N_( "Listen for SAP announcements on another address" )
-#define SAP_IPV4_TEXT N_( "IPv4-SAP listening" )
+#define SAP_ADDR_LONGTEXT N_( "The SAP module normally chooses itself the " \
+ "right addresses to listen to. However, you " \
+ "can specify a specific address." )
+#define SAP_IPV4_TEXT N_( "IPv4 SAP" )
#define SAP_IPV4_LONGTEXT N_( \
- "Set this if you want the SAP module to listen to IPv4 announcements " \
+ "Listen to IPv4 announcements " \
"on the standard address." )
-#define SAP_IPV6_TEXT N_( "IPv6-SAP listening" )
+#define SAP_IPV6_TEXT N_( "IPv6 SAP" )
#define SAP_IPV6_LONGTEXT N_( \
- "Set this if you want the SAP module to listen to IPv6 announcements " \
- "on the standard address." )
+ "Listen to IPv6 announcements " \
+ "on the standard addresses." )
#define SAP_SCOPE_TEXT N_( "IPv6 SAP scope" )
#define SAP_SCOPE_LONGTEXT N_( \
- "Sets the scope for IPv6 announcements (default is 8)." )
+ "Scope for IPv6 announcements (default is 8)." )
#define SAP_TIMEOUT_TEXT N_( "SAP timeout (seconds)" )
#define SAP_TIMEOUT_LONGTEXT N_( \
- "Sets the time before SAP items get deleted if no new announcement " \
+ "Delay after which SAP items get deleted if no new announcement " \
"is received." )
-#define SAP_PARSE_TEXT N_( "Try to parse the SAP" )
+#define SAP_PARSE_TEXT N_( "Try to parse the announce" )
#define SAP_PARSE_LONGTEXT N_( \
- "When SAP can it will try to parse the SAP. If you don't select " \
- "this, all announcements will be parsed by the livedotcom module." )
+ "This enables actual parsing of the announces by the SAP module. " \
+ "Otherwise, all announcements are parsed by the \"livedotcom\" " \
+ "(RTP/RTSP) module." )
#define SAP_STRICT_TEXT N_( "SAP Strict mode" )
#define SAP_STRICT_LONGTEXT N_( \
"When this is set, the SAP parser will discard some non-compliant " \
"announcements." )
#define SAP_CACHE_TEXT N_("Use SAP cache")
#define SAP_CACHE_LONGTEXT N_( \
- "If this option is selected, a SAP caching mechanism will be used. " \
+ "This enables a SAP caching mechanism. " \
"This will result in lower SAP startup time, but you could end up " \
- "with items corresponding to legacy streams." )
+ "with items corresponding to legacy streams." )
#define SAP_TIMESHIFT_TEXT N_("Allow timeshifting")
-#define SAP_TIMESHIFT_LONGTEXT N_( \
- "Enable timeshifting automatically for streams " \
- "discovered through SAP announcements." )
+#define SAP_TIMESHIFT_LONGTEXT N_( "This automatically enables timeshifting " \
+ "for streams discovered through SAP announcements." )
/* Callbacks */
static int Open ( vlc_object_t * );
SAP_PARSE_TEXT,SAP_PARSE_LONGTEXT, VLC_TRUE );
add_bool( "sap-strict", 0 , NULL,
SAP_STRICT_TEXT,SAP_STRICT_LONGTEXT, VLC_TRUE );
+#if 0
add_bool( "sap-cache", 0 , NULL,
SAP_CACHE_TEXT,SAP_CACHE_LONGTEXT, VLC_TRUE );
+#endif
add_bool( "sap-timeshift", 0 , NULL,
SAP_TIMESHIFT_TEXT,SAP_TIMESHIFT_LONGTEXT, VLC_TRUE );
/* SAP annnounces must only contain one SDP */
sdp_t *p_sdp;
- int i_item_id;
-// playlist_item_t *p_item;
+ int i_input_id;
+ int i_item_id_cat;
+ int i_item_id_one;
};
struct services_discovery_sys_t
int *pi_fd;
/* playlist node */
- playlist_item_t *p_node;
+ playlist_item_t *p_node_cat;
+ playlist_item_t *p_node_one;
playlist_t *p_playlist;
/* Table of announces */
#endif
static void FreeSDP( sdp_t *p_sdp );
-
-#define FREE( p ) \
- if( p ) { free( p ); (p) = NULL; }
/*****************************************************************************
* Open: initialize and create stuff
*****************************************************************************/
services_discovery_sys_t *p_sys = (services_discovery_sys_t *)
malloc( sizeof( services_discovery_sys_t ) );
- playlist_view_t *p_view;
- vlc_value_t val;
-
p_sys->i_timeout = var_CreateGetInteger( p_sd, "sap-timeout" );
p_sd->pf_run = Run;
p_sys->b_strict = var_CreateGetInteger( p_sd, "sap-strict");
p_sys->b_parse = var_CreateGetInteger( p_sd, "sap-parse" );
+#if 0
if( var_CreateGetInteger( p_sd, "sap-cache" ) )
{
CacheLoad( p_sd );
}
+#endif
/* Cache sap_timeshift value */
p_sys->b_timeshift = var_CreateGetInteger( p_sd, "sap-timeshift" )
return VLC_EGENERIC;
}
- p_view = playlist_ViewFind( p_sys->p_playlist, VIEW_CATEGORY );
- p_sys->p_node = playlist_NodeCreate( p_sys->p_playlist, VIEW_CATEGORY,
- _("Session Announcements (SAP)"), p_view->p_root );
- p_sys->p_node->i_flags |= PLAYLIST_RO_FLAG;
- p_sys->p_node->i_flags &= ~PLAYLIST_SKIP_FLAG;
- val.b_bool = VLC_TRUE;
- var_Set( p_sys->p_playlist, "intf-change", val );
+ playlist_NodesCreateForSD( p_sys->p_playlist, _("SAP sessions"),
+ &p_sys->p_node_cat, &p_sys->p_node_one );
p_sys->i_announces = 0;
p_sys->pp_announces = NULL;
p_demux->pf_control = Control;
p_demux->pf_demux = Demux;
- free( psz_sdp );
+ FREENULL( psz_sdp );
return VLC_SUCCESS;
error:
- free( psz_sdp );
- if( p_sdp ) FreeSDP( p_sdp );
+ FREENULL( psz_sdp );
+ if( p_sdp ) FreeSDP( p_sdp ); p_sdp = NULL;
stream_Seek( p_demux->s, 0 );
- return VLC_EGENERIC;
+ return VLC_EGENERIC;
}
/*****************************************************************************
{
net_Close( p_sys->pi_fd[i] );
}
- FREE( p_sys->pi_fd );
+ FREENULL( p_sys->pi_fd );
+#if 0
if( config_GetInt( p_sd, "sap-cache" ) )
{
CacheSave( p_sd );
}
+#endif
for( i = p_sys->i_announces - 1; i>= 0; i-- )
{
RemoveAnnounce( p_sd, p_sys->pp_announces[i] );
}
- FREE( p_sys->pp_announces );
+ FREENULL( p_sys->pp_announces );
if( p_sys->p_playlist )
{
- playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node, VLC_TRUE,
+ playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node_cat, VLC_TRUE,
+ VLC_TRUE );
+ playlist_NodeDelete( p_sys->p_playlist, p_sys->p_node_one, VLC_TRUE,
VLC_TRUE );
vlc_object_release( p_sys->p_playlist );
}
*****************************************************************************/
static void CloseDemux( vlc_object_t *p_this )
{
-
+ demux_t *p_demux = (demux_t *)p_this;
+ if( p_demux->p_sys )
+ {
+ if( p_demux->p_sys->p_sdp ) { FreeSDP( p_demux->p_sys->p_sdp ); p_demux->p_sys->p_sdp = NULL; }
+ free( p_demux->p_sys );
+ }
}
/*****************************************************************************
if( psz_addr && *psz_addr )
{
InitSocket( p_sd, psz_addr, SAP_PORT );
+ free( psz_addr );
}
if( p_sd->p_sys->i_fd == 0 )
if( mdate() - p_sd->p_sys->pp_announces[i]->i_last > i_timeout )
{
- struct sap_announce_t *p_announce;
- p_announce = p_sd->p_sys->pp_announces[i];
-
- /* Remove the playlist item */
- playlist_LockDelete( p_sd->p_sys->p_playlist,
- p_announce->i_item_id );
-
- /* Remove the sap_announce from the array */
- REMOVE_ELEM( p_sd->p_sys->pp_announces,
- p_sd->p_sys->i_announces, i );
-
- free( p_announce );
+ RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i] );
}
}
{
sdp_t *p_sdp = p_demux->p_sys->p_sdp;
playlist_t *p_playlist;
+ input_thread_t *p_input;
+ input_item_t *p_parent_input;
p_playlist = (playlist_t *)vlc_object_find( p_demux, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
+ if( !p_playlist )
+ {
+ msg_Err( p_demux, "playlist could not be found" );
+ return VLC_EGENERIC;
+ }
- p_playlist->status.p_item->i_flags |= PLAYLIST_DEL_FLAG;
+ p_input = (input_thread_t *)vlc_object_find( p_demux, VLC_OBJECT_INPUT,
+ FIND_PARENT );
+ if( !p_input )
+ {
+ msg_Err( p_demux, "parent input could not be found" );
+ return VLC_EGENERIC;
+ }
- playlist_Add( p_playlist, p_sdp->psz_uri, p_sdp->psz_sessionname,
- PLAYLIST_APPEND, PLAYLIST_END );
+ p_parent_input = p_input->input.p_item;
+ vlc_mutex_lock( &p_parent_input->lock );
+ FREENULL( p_parent_input->psz_uri );
+ p_parent_input->psz_uri = strdup( p_sdp->psz_uri );
+ FREENULL( p_parent_input->psz_name );
+ p_parent_input->psz_name = strdup( EnsureUTF8( p_sdp->psz_sessionname ) );
+ p_parent_input->i_type = ITEM_TYPE_NET;
+
+ if( p_playlist->status.p_item &&
+ p_playlist->status.p_item->p_input == p_parent_input )
+ {
+ playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+ p_playlist->status.p_node, p_playlist->status.p_item );
+ }
+
+ vlc_mutex_unlock( &p_parent_input->lock );
+ vlc_object_release( p_input );
vlc_object_release( p_playlist );
- if( p_sdp ) FreeSDP( p_sdp );
return VLC_SUCCESS;
}
{
int i_version, i_address_type, i_hash, i;
char *psz_sdp, *psz_foo, *psz_initial_sdp;
+ uint8_t *p_decompressed_buffer = NULL;
sdp_t *p_sdp;
vlc_bool_t b_compressed;
vlc_bool_t b_need_delete = VLC_FALSE;
psz_sdp += 4;
if( i_read <= 9 )
{
- msg_Warn( p_sd, "too short SAP packet\n" );
+ msg_Warn( p_sd, "too short SAP packet" );
return VLC_EGENERIC;
}
}
psz_sdp += 16;
if( i_read <= 21 )
{
- msg_Warn( p_sd, "too short SAP packet\n" );
+ msg_Warn( p_sd, "too short SAP packet" );
return VLC_EGENERIC;
}
}
if( b_compressed )
{
#ifdef HAVE_ZLIB_H
- uint8_t *p_decompressed_buffer = NULL;
int i_decompressed_size;
i_decompressed_size = Decompress( (uint8_t *)psz_sdp,
&p_decompressed_buffer, i_read - ( psz_sdp - (char *)p_buffer ) );
- if( i_decompressed_size > 0 && i_decompressed_size < MAX_SAP_BUFFER )
+ if( i_decompressed_size > 0 )
{
- memcpy( psz_sdp, p_decompressed_buffer, i_decompressed_size );
+ psz_sdp = (char *)p_decompressed_buffer;
+ realloc( p_decompressed_buffer, i_decompressed_size++ );
psz_sdp[i_decompressed_size] = '\0';
- free( p_decompressed_buffer );
+ }
+ else
+ {
+ msg_Warn( p_sd, "decompression of sap packet failed" );
+ return VLC_EGENERIC;
}
#else
- msg_Warn( p_sd, "Ignoring compressed sap packet" );
+ msg_Warn( p_sd, "ignoring compressed sap packet" );
return VLC_EGENERIC;
#endif
}
}
if( ( psz_sdp != psz_foo ) && strcasecmp( psz_foo, "application/sdp" ) )
{
- msg_Dbg( p_sd, "unhandled content type: %s", psz_foo );
+ msg_Dbg( p_sd, "unhandled content type: %s", psz_foo );
}
if( ( psz_sdp - (char *)p_buffer ) >= i_read )
{
if( b_need_delete )
{
RemoveAnnounce( p_sd, p_sd->p_sys->pp_announces[i]);
- return VLC_SUCCESS;
}
else
{
p_sd->p_sys->pp_announces[i]->i_last = mdate();
- FreeSDP( p_sdp );
- return VLC_SUCCESS;
}
+ FreeSDP( p_sdp ); p_sdp = NULL;
+ return VLC_SUCCESS;
}
}
/* Add item */
if( p_sdp->i_media > 1 )
{
- msg_Dbg( p_sd, "passing to LIVE.COM" );
+ msg_Dbg( p_sd, "passing to liveMedia" );
}
CreateAnnounce( p_sd, i_hash, p_sdp );
+ FREENULL( p_decompressed_buffer );
return VLC_SUCCESS;
}
sap_announce_t *CreateAnnounce( services_discovery_t *p_sd, uint16_t i_hash,
sdp_t *p_sdp )
{
+ input_item_t *p_input;
playlist_item_t *p_item, *p_child;
char *psz_value;
sap_announce_t *p_sap = (sap_announce_t *)malloc(
p_sap->i_last = mdate();
p_sap->i_hash = i_hash;
p_sap->p_sdp = p_sdp;
- p_sap->i_item_id = -1;
/* Create the actual playlist item here */
- p_item = playlist_ItemNew( p_sd, p_sap->p_sdp->psz_uri, p_sdp->psz_sessionname );
-
- if( !p_item )
+ p_input = input_ItemNewWithType( VLC_OBJECT(p_sd),
+ p_sap->p_sdp->psz_uri,
+ p_sdp->psz_sessionname,
+ 0, NULL, -1, ITEM_TYPE_NET );
+ p_sap->i_input_id = p_input->i_id;
+ if( !p_input )
{
free( p_sap );
return NULL;
}
if( p_sys->b_timeshift )
- playlist_ItemAddOption( p_item, ":access-filter=timeshift" );
+ vlc_input_item_AddOption( p_input, ":access-filter=timeshift" );
psz_value = GetAttribute( p_sap->p_sdp, "tool" );
if( psz_value != NULL )
{
- vlc_input_item_AddInfo( &p_item->input, _("Session"),
- _("Tool"), psz_value );
+ vlc_input_item_AddInfo( p_input, _("Session"),_("Tool"), psz_value );
}
if( strcmp( p_sdp->psz_username, "-" ) )
{
- vlc_input_item_AddInfo( &p_item->input, _("Session"),
+ vlc_input_item_AddInfo( p_input, _("Session"),
_("User"), p_sdp->psz_username );
}
+ /* Handle group */
psz_value = GetAttribute( p_sap->p_sdp, "x-plgroup" );
-
if( psz_value == NULL )
- {
psz_value = GetAttribute( p_sap->p_sdp, "plgroup" );
- }
- /* Find or Create the group playlist non-playable item */
if( psz_value != NULL )
{
EnsureUTF8( psz_value );
- p_child = playlist_ChildSearchName( p_sys->p_node, psz_value );
+ p_child = playlist_ChildSearchName( p_sys->p_node_cat, psz_value );
if( p_child == NULL )
{
- p_child = playlist_NodeCreate( p_sys->p_playlist,
- VIEW_CATEGORY, psz_value,
- p_sys->p_node );
+ p_child = playlist_NodeCreate( p_sys->p_playlist, psz_value,
+ p_sys->p_node_cat );
p_child->i_flags &= ~PLAYLIST_SKIP_FLAG;
}
}
else
{
- p_child = p_sys->p_node;
+ p_child = p_sys->p_node_cat;
}
+ p_item = playlist_NodeAddInput( p_sys->p_playlist, p_input, p_child,
+ PLAYLIST_APPEND, PLAYLIST_END );
p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;
p_item->i_flags &= ~PLAYLIST_SAVE_FLAG;
+ p_sap->i_item_id_cat = p_item->i_id;
- playlist_NodeAddItem( p_sys->p_playlist, p_item, VIEW_CATEGORY, p_child,
- PLAYLIST_APPEND, PLAYLIST_END );
-
- p_sap->i_item_id = p_item->input.i_id;
+ p_item = playlist_NodeAddInput( p_sys->p_playlist, p_input,
+ p_sys->p_node_one, PLAYLIST_APPEND, PLAYLIST_END );
+ p_item->i_flags &= ~PLAYLIST_SKIP_FLAG;
+ p_item->i_flags &= ~PLAYLIST_SAVE_FLAG;
+ p_sap->i_item_id_one = p_item->i_id;
TAB_APPEND( p_sys->i_announces, p_sys->pp_announces, p_sap );
/* Fill p_sdp->psz_uri */
static int ParseConnection( vlc_object_t *p_obj, sdp_t *p_sdp )
{
- char *psz_eof;
- char *psz_parse;
+ char *psz_eof = NULL;
+ char *psz_parse = NULL;
char *psz_uri = NULL;
char *psz_proto = NULL;
char psz_source[256];
strncmp( psz_parse, "video", 5 ) )
{
msg_Warn( p_obj, "unhandled media type -%s-", psz_parse );
- FREE( psz_uri );
+ FREENULL( psz_uri );
return VLC_EGENERIC;
}
else
{
msg_Warn( p_obj, "unable to parse m field (1)");
- FREE( psz_uri );
+ FREENULL( psz_uri );
return VLC_EGENERIC;
}
else
{
msg_Warn( p_obj, "unable to parse m field (2)");
- FREE( psz_uri );
+ FREENULL( psz_uri );
return VLC_EGENERIC;
}
asprintf( &p_sdp->psz_uri, "%s://%s@%s:%i", psz_proto, psz_source,
psz_uri, i_port );
- FREE( psz_uri );
- FREE( psz_proto );
+ FREENULL( psz_uri );
+ FREENULL( psz_proto );
return VLC_SUCCESS;
}
if( psz_sdp[0] != 'v' || psz_sdp[1] != '=' )
{
- msg_Warn( p_obj, "Bad packet" );
+ msg_Warn( p_obj, "bad packet" );
return NULL;
}
if( psz_sdp[1] != '=' )
{
msg_Warn( p_obj, "invalid packet" ) ;
- FreeSDP( p_sdp );
+ FreeSDP( p_sdp ); p_sdp = NULL;
return NULL;
}
p_sdp->i_session_id = atoll( psz_sess_id );
- FREE( psz_sess_id );
+ FREENULL( psz_sess_id );
GET_FIELD( psz_sess_id );
- FREE( psz_sess_id );
+ FREENULL( psz_sess_id );
GET_FIELD( p_sdp->psz_network_type );
GET_FIELD( p_sdp->psz_address_type );
if( b_invalid )
{
- FreeSDP( p_sdp );
+ FreeSDP( p_sdp ); p_sdp = NULL;
return NULL;
}
printf( "inflateInit() failed. Result: %d\n", i_result );
return( -1 );
}
-#if 0
- p_playlist->pp_items[p_playlist->i_index]->b_autodeletion = VLC_TRUE;
- i_position = p_playlist->i_index;
-
- /* Gather the complete sdp file */
- for( ;; )
- {
- int i_read = stream_Read( p_demux->s, &p_sdp[i_sdp], i_sdp_max - i_sdp - 1 );
-#endif
d_stream.next_in = (Bytef *)psz_src;
d_stream.avail_in = i_len;
n = 0;
static void FreeSDP( sdp_t *p_sdp )
{
int i;
- FREE( p_sdp->psz_sdp );
- FREE( p_sdp->psz_sessionname );
- FREE( p_sdp->psz_connection );
- FREE( p_sdp->psz_media );
- FREE( p_sdp->psz_uri );
- FREE( p_sdp->psz_username );
- FREE( p_sdp->psz_network_type );
+ FREENULL( p_sdp->psz_sdp );
+ FREENULL( p_sdp->psz_sessionname );
+ FREENULL( p_sdp->psz_connection );
+ FREENULL( p_sdp->psz_media );
+ FREENULL( p_sdp->psz_uri );
+ FREENULL( p_sdp->psz_username );
+ FREENULL( p_sdp->psz_network_type );
- FREE( p_sdp->psz_address );
- FREE( p_sdp->psz_address_type );
+ FREENULL( p_sdp->psz_address );
+ FREENULL( p_sdp->psz_address_type );
for( i= p_sdp->i_attributes - 1; i >= 0 ; i-- )
{
struct attribute_t *p_attr = p_sdp->pp_attributes[i];
- FREE( p_sdp->pp_attributes[i]->psz_field );
- FREE( p_sdp->pp_attributes[i]->psz_value );
+ FREENULL( p_sdp->pp_attributes[i]->psz_field );
+ FREENULL( p_sdp->pp_attributes[i]->psz_value );
REMOVE_ELEM( p_sdp->pp_attributes, p_sdp->i_attributes, i);
- FREE( p_attr );
+ FREENULL( p_attr );
}
- free( p_sdp );
+ FREENULL( p_sdp );
}
static int RemoveAnnounce( services_discovery_t *p_sd,
{
int i;
- if( p_announce->p_sdp ) FreeSDP( p_announce->p_sdp );
+ if( p_announce->p_sdp )
+ {
+ FreeSDP( p_announce->p_sdp );
+ p_announce->p_sdp = NULL;
+ }
- if( p_announce->i_item_id > -1 )
+ if( p_announce->i_input_id > -1 )
{
- playlist_LockDelete( p_sd->p_sys->p_playlist, p_announce->i_item_id );
+ playlist_LockDeleteAllFromInput(
+ p_sd->p_sys->p_playlist, p_announce->i_input_id );
}
for( i = 0; i< p_sd->p_sys->i_announces; i++)
static void CacheLoad( services_discovery_t *p_sd )
{
- msg_Warn( p_sd, "Cache not implemented") ;
+ msg_Warn( p_sd, "cache not implemented") ;
}
static void CacheSave( services_discovery_t *p_sd )
{
- msg_Warn( p_sd, "Cache not implemented") ;
+ msg_Warn( p_sd, "cache not implemented") ;
}