1 /*****************************************************************************
2 * announce.c : announce handler
3 *****************************************************************************
4 * Copyright (C) 2002-2007 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* free() */
28 #include <stdio.h> /* sprintf() */
29 #include <string.h> /* strerror() */
34 #include "stream_output.h"
36 struct announce_method_t
40 /****************************************************************************
42 ****************************************************************************/
45 * Register a new session with the announce handler
47 * \param p_sout a sout instance structure
48 * \param p_session a session descriptor
49 * \param p_method an announce method descriptor
50 * \return VLC_SUCCESS or an error
52 int sout_AnnounceRegister( sout_instance_t *p_sout,
53 session_descriptor_t *p_session,
54 announce_method_t *p_method )
57 announce_handler_t *p_announce = (announce_handler_t*)
58 vlc_object_find( p_sout,
64 msg_Dbg( p_sout, "No announce handler found, creating one" );
65 p_announce = announce_HandlerCreate( p_sout );
68 msg_Err( p_sout, "Creation failed" );
71 vlc_object_yield( p_announce );
72 msg_Dbg( p_sout, "creation done" );
75 i_ret = announce_Register( p_announce, p_session, p_method );
76 vlc_object_release( p_announce );
82 * Register a new session with the announce handler, using a pregenerated SDP
84 * \param p_sout a sout instance structure
85 * \param psz_sdp the SDP to register
86 * \param psz_uri session address (needed for SAP address auto detection)
87 * \param p_method an announce method descriptor
88 * \return the new session descriptor structure
90 session_descriptor_t *
91 sout_AnnounceRegisterSDP( sout_instance_t *p_sout, const char *cfgpref,
92 const char *psz_sdp, const char *psz_uri,
93 announce_method_t *p_method )
95 session_descriptor_t *p_session;
96 announce_handler_t *p_announce = (announce_handler_t*)
97 vlc_object_find( p_sout,
102 msg_Dbg( p_sout, "no announce handler found, creating one" );
103 p_announce = announce_HandlerCreate( p_sout );
106 msg_Err( p_sout, "Creation failed" );
109 vlc_object_yield( p_announce );
112 p_session = sout_AnnounceSessionCreate(VLC_OBJECT (p_sout), cfgpref);
113 p_session->psz_sdp = strdup( psz_sdp );
115 /* GRUIK. We should not convert back-and-forth from string to numbers */
116 struct addrinfo *res;
117 if (vlc_getaddrinfo (VLC_OBJECT (p_sout), psz_uri, 0, NULL, &res) == 0)
119 if (res->ai_addrlen <= sizeof (p_session->addr))
120 memcpy (&p_session->addr, res->ai_addr,
121 p_session->addrlen = res->ai_addrlen);
122 vlc_freeaddrinfo (res);
125 announce_Register( p_announce, p_session, p_method );
127 vlc_object_release( p_announce );
132 * UnRegister an existing session
134 * \param p_sout a sout instance structure
135 * \param p_session the session descriptor
136 * \return VLC_SUCCESS or an error
138 int sout_AnnounceUnRegister( sout_instance_t *p_sout,
139 session_descriptor_t *p_session )
142 announce_handler_t *p_announce = (announce_handler_t*)
143 vlc_object_find( p_sout,
148 msg_Dbg( p_sout, "unable to remove announce: no announce handler" );
151 i_ret = announce_UnRegister( p_announce, p_session );
153 vlc_object_release( p_announce );
159 * Create and initialize a session descriptor
161 * \return a new session descriptor
163 session_descriptor_t * sout_AnnounceSessionCreate (vlc_object_t *obj,
166 size_t cfglen = strlen (cfgpref);
170 char varname[cfglen + sizeof ("description")], *subvar = varname + cfglen;
171 strcpy (varname, cfgpref);
173 session_descriptor_t *p_session = calloc (1, sizeof (*p_session));
174 if (p_session == NULL)
177 strcpy (subvar, "name");
178 p_session->psz_name = var_GetNonEmptyString (obj, varname);
179 strcpy (subvar, "group");
180 p_session->psz_group = var_GetNonEmptyString (obj, varname);
182 strcpy (subvar, "description");
183 p_session->description = var_GetNonEmptyString (obj, varname);
184 strcpy (subvar, "url");
185 p_session->url = var_GetNonEmptyString (obj, varname);
186 strcpy (subvar, "email");
187 p_session->email = var_GetNonEmptyString (obj, varname);
188 strcpy (subvar, "phone");
189 p_session->phone = var_GetNonEmptyString (obj, varname);
194 int sout_SessionSetMedia (vlc_object_t *obj, session_descriptor_t *p_session,
195 const char *fmt, const char *src, int sport,
196 const char *dst, int dport)
198 if ((p_session->sdpformat = strdup (fmt)) == NULL)
201 /* GRUIK. We should not convert back-and-forth from string to numbers */
202 struct addrinfo *res;
203 if (vlc_getaddrinfo (obj, dst, dport, NULL, &res) == 0)
205 if (res->ai_addrlen > sizeof (p_session->addr))
208 memcpy (&p_session->addr, res->ai_addr,
209 p_session->addrlen = res->ai_addrlen);
210 vlc_freeaddrinfo (res);
212 if (vlc_getaddrinfo (obj, src, sport, NULL, &res) == 0)
214 if (res->ai_addrlen > sizeof (p_session->orig))
216 memcpy (&p_session->orig, res->ai_addr,
217 p_session->origlen = res->ai_addrlen);
218 vlc_freeaddrinfo (res);
223 vlc_freeaddrinfo (res);
228 * Destroy a session descriptor and free all
230 * \param p_session the session to destroy
233 void sout_AnnounceSessionDestroy( session_descriptor_t *p_session )
237 free (p_session->psz_name);
238 free (p_session->psz_group);
239 free (p_session->psz_sdp);
240 free (p_session->description);
241 free (p_session->sdpformat);
242 free (p_session->url);
243 free (p_session->email);
244 free (p_session->phone);
250 * \return the SAP announce method
252 announce_method_t * sout_SAPMethod (void)
257 void sout_MethodRelease (announce_method_t *m)
259 assert (m == &sap_method);
262 /************************************************************************
263 * Announce handler functions (private)
264 ************************************************************************/
267 * Create the announce handler object
269 * \param p_this a vlc_object structure
270 * \return the new announce handler or NULL on error
272 announce_handler_t *__announce_HandlerCreate( vlc_object_t *p_this )
274 announce_handler_t *p_announce;
276 p_announce = vlc_object_create( p_this, VLC_OBJECT_ANNOUNCE );
280 msg_Err( p_this, "out of memory" );
284 p_announce->p_sap = NULL;
285 vlc_object_attach( p_announce, p_this->p_libvlc);
291 * Destroy a announce handler object
293 * \param p_announce the announce handler to destroy
294 * \return VLC_SUCCESS or an error
296 int announce_HandlerDestroy( announce_handler_t *p_announce )
298 if( p_announce->p_sap )
300 vlc_object_kill ((vlc_object_t *)p_announce->p_sap);
301 /* Wait for the SAP thread to exit */
302 vlc_thread_join( (vlc_object_t *)p_announce->p_sap );
303 announce_SAPHandlerDestroy( p_announce->p_sap );
306 /* Free the structure */
307 vlc_object_destroy( p_announce );
312 /* Register an announce */
313 int announce_Register( announce_handler_t *p_announce,
314 session_descriptor_t *p_session,
315 announce_method_t *p_method )
317 if (p_method == NULL)
320 msg_Dbg( p_announce, "registering announce");
321 if( p_method == &sap_method )
323 /* Do we already have a SAP announce handler ? */
324 if( !p_announce->p_sap )
326 sap_handler_t *p_sap = announce_SAPHandlerCreate( p_announce );
327 msg_Dbg( p_announce, "creating SAP announce handler");
330 msg_Err( p_announce, "SAP handler creation failed" );
333 p_announce->p_sap = p_sap;
335 /* this will set p_session->p_sap for later deletion */
336 msg_Dbg( p_announce, "adding SAP session");
337 p_announce->p_sap->pf_add( p_announce->p_sap, p_session );
341 msg_Err( p_announce, "announce type unsupported" );
348 /* Unregister an announce */
349 int announce_UnRegister( announce_handler_t *p_announce,
350 session_descriptor_t *p_session )
352 msg_Dbg( p_announce, "unregistering announce" );
353 if( p_announce->p_sap )
354 p_announce->p_sap->pf_del( p_announce->p_sap, p_session );