* 2nd review of /src/* \ libvlc.h (refs #438)
[vlc.git] / src / stream_output / announce.c
1 /*****************************************************************************
2  * announce.c : announce handler
3  *****************************************************************************
4  * Copyright (C) 2002-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                                /* free() */
28 #include <stdio.h>                                              /* sprintf() */
29 #include <string.h>                                            /* strerror() */
30
31 #include <vlc/vlc.h>
32 #include <vlc/sout.h>
33
34 /*****************************************************************************
35  * Local prototypes
36  *****************************************************************************/
37 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
38
39
40 /****************************************************************************
41  * Sout-side functions
42  ****************************************************************************/
43
44 /**
45  *  Register a new session with the announce handler
46  *
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
51  */
52 int sout_AnnounceRegister( sout_instance_t *p_sout,
53                        session_descriptor_t *p_session,
54                        announce_method_t *p_method )
55 {
56     int i_ret;
57     announce_handler_t *p_announce = (announce_handler_t*)
58                               vlc_object_find( p_sout,
59                                               VLC_OBJECT_ANNOUNCE,
60                                               FIND_ANYWHERE );
61
62     if( !p_announce )
63     {
64         msg_Dbg( p_sout, "No announce handler found, creating one" );
65         p_announce = announce_HandlerCreate( p_sout );
66         if( !p_announce )
67         {
68             msg_Err( p_sout, "Creation failed" );
69             return VLC_ENOMEM;
70         }
71         vlc_object_yield( p_announce );
72         msg_Dbg( p_sout, "creation done" );
73     }
74
75     i_ret = announce_Register( p_announce, p_session, p_method );
76     vlc_object_release( p_announce );
77
78     return i_ret;
79 }
80
81 /**
82  *  Register a new session with the announce handler, using a pregenerated SDP
83  *
84  * \param p_sout a sout instance structure
85  * \param psz_sdp the SDP to register
86  * \param psz_uri session URI (needed for SAP address auto detection
87  * \param p_method an announce method descriptor
88  * \return the new session descriptor structure
89  */
90 session_descriptor_t *sout_AnnounceRegisterSDP( sout_instance_t *p_sout,
91                           const char *psz_sdp, const char *psz_uri,
92                           announce_method_t *p_method )
93 {
94     session_descriptor_t *p_session;
95     announce_handler_t *p_announce = (announce_handler_t*)
96                                      vlc_object_find( p_sout,
97                                               VLC_OBJECT_ANNOUNCE,
98                                               FIND_ANYWHERE );
99     if( !p_announce )
100     {
101         msg_Dbg( p_sout, "no announce handler found, creating one" );
102         p_announce = announce_HandlerCreate( p_sout );
103         if( !p_announce )
104         {
105             msg_Err( p_sout, "Creation failed" );
106             return NULL;
107         }
108         vlc_object_yield( p_announce );
109     }
110
111     if( p_method->i_type != METHOD_TYPE_SAP )
112     {
113         msg_Warn( p_sout, "forcing SAP announcement");
114     }
115
116     p_session = sout_AnnounceSessionCreate();
117     p_session->psz_sdp = strdup( psz_sdp );
118     p_session->psz_uri = strdup( psz_uri );
119     announce_Register( p_announce, p_session, p_method );
120
121     vlc_object_release( p_announce );
122     return p_session;
123 }
124
125 /**
126  *  UnRegister an existing session
127  *
128  * \param p_sout a sout instance structure
129  * \param p_session the session descriptor
130  * \return VLC_SUCCESS or an error
131  */
132 int sout_AnnounceUnRegister( sout_instance_t *p_sout,
133                              session_descriptor_t *p_session )
134 {
135     int i_ret;
136     announce_handler_t *p_announce = (announce_handler_t*)
137                               vlc_object_find( p_sout,
138                                               VLC_OBJECT_ANNOUNCE,
139                                               FIND_ANYWHERE );
140     if( !p_announce )
141     {
142         msg_Dbg( p_sout, "unable to remove announce: no announce handler" );
143         return VLC_ENOOBJ;
144     }
145     i_ret  = announce_UnRegister( p_announce, p_session );
146
147     vlc_object_release( p_announce );
148
149     return i_ret;
150 }
151
152 /**
153  * Create and initialize a session descriptor
154  *
155  * \return a new session descriptor
156  */
157 session_descriptor_t * sout_AnnounceSessionCreate(void)
158 {
159     session_descriptor_t *p_session;
160
161     p_session = (session_descriptor_t *)malloc( sizeof(session_descriptor_t));
162
163     if( p_session)
164     {
165         p_session->p_sap = NULL;
166         p_session->psz_sdp = NULL;
167         p_session->psz_name = NULL;
168         p_session->psz_uri = NULL;
169         p_session->i_port = 0;
170         p_session->psz_group = NULL;
171     }
172
173     return p_session;
174 }
175
176 /**
177  * Destroy a session descriptor and free all
178  *
179  * \param p_session the session to destroy
180  * \return Nothing
181  */
182 void sout_AnnounceSessionDestroy( session_descriptor_t *p_session )
183 {
184     if( p_session )
185     {
186         FREE( p_session->psz_name );
187         FREE( p_session->psz_group );
188         FREE( p_session->psz_uri );
189         FREE( p_session->psz_sdp );
190         free( p_session );
191     }
192 }
193
194 /**
195  * Create and initialize an announcement method structure
196  *
197  * \param i_type METHOD_TYPE_SAP
198  * \return a new announce_method structure
199  */
200 announce_method_t * sout_AnnounceMethodCreate( int i_type )
201 {
202     announce_method_t *p_method;
203
204     p_method = (announce_method_t *)malloc( sizeof(announce_method_t) );
205     if( p_method == NULL )
206         return NULL;
207
208     p_method->i_type = i_type;
209     return p_method;
210 }
211
212 /************************************************************************
213  * Announce handler functions (private)
214  ************************************************************************/
215
216 /**
217  * Create the announce handler object
218  *
219  * \param p_this a vlc_object structure
220  * \return the new announce handler or NULL on error
221  */
222 announce_handler_t *__announce_HandlerCreate( vlc_object_t *p_this )
223 {
224     announce_handler_t *p_announce;
225
226     p_announce = vlc_object_create( p_this, VLC_OBJECT_ANNOUNCE );
227
228     if( !p_announce )
229     {
230         msg_Err( p_this, "out of memory" );
231         return NULL;
232     }
233
234     p_announce->p_sap = NULL;
235
236     vlc_object_attach( p_announce, p_this->p_vlc);
237
238
239     return p_announce;
240 }
241
242 /**
243  * Destroy a  announce handler object
244  *
245  * \param p_announce the announce handler to destroy
246  * \return VLC_SUCCESS or an error
247  */
248 int announce_HandlerDestroy( announce_handler_t *p_announce )
249 {
250
251     if( p_announce->p_sap )
252     {
253         p_announce->p_sap->b_die = VLC_TRUE;
254         /* Wait for the SAP thread to exit */
255         vlc_thread_join( p_announce->p_sap );
256         announce_SAPHandlerDestroy( p_announce->p_sap );
257     }
258
259     /* Free the structure */
260     vlc_object_destroy( p_announce );
261
262     return VLC_SUCCESS;
263 }
264
265 /* Register an announce */
266 int announce_Register( announce_handler_t *p_announce,
267                        session_descriptor_t *p_session,
268                        announce_method_t *p_method )
269 {
270
271     msg_Dbg( p_announce, "registering announce");
272     if( p_method->i_type == METHOD_TYPE_SAP )
273     {
274         /* Do we already have a SAP announce handler ? */
275         if( !p_announce->p_sap )
276         {
277             sap_handler_t *p_sap = announce_SAPHandlerCreate( p_announce );
278             msg_Dbg( p_announce, "creating SAP announce handler");
279             if( !p_sap )
280             {
281                 msg_Err( p_announce, "SAP handler creation failed" );
282                 return VLC_ENOOBJ;
283             }
284             p_announce->p_sap = p_sap;
285         }
286         /* this will set p_session->p_sap for later deletion */
287         msg_Dbg( p_announce, "adding SAP session");
288         p_announce->p_sap->pf_add( p_announce->p_sap, p_session );
289     }
290     else
291     {
292         msg_Dbg( p_announce, "announce type unsupported" );
293         return VLC_EGENERIC;
294     }
295     return VLC_SUCCESS;;
296 }
297
298
299 /* Unregister an announce */
300 int announce_UnRegister( announce_handler_t *p_announce,
301                   session_descriptor_t *p_session )
302 {
303     msg_Dbg( p_announce, "unregistering announce" );
304     if( p_session->p_sap != NULL ) /* SAP Announce */
305     {
306         if( !p_announce->p_sap )
307         {
308             msg_Err( p_announce, "can't remove announce, no SAP handler");
309             return VLC_ENOOBJ;
310         }
311         p_announce->p_sap->pf_del( p_announce->p_sap, p_session );
312     }
313     return VLC_SUCCESS;
314 }