0215eec7dacb92703483de1352ca29d3a0587095
[vlc.git] / src / stream_output / announce.c
1 /*****************************************************************************
2  * announce.c : announce handler
3  *****************************************************************************
4  * Copyright (C) 2002-2007 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 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc/vlc.h>
32 #include <vlc_sout.h>
33 #include "stream_output.h"
34
35 #include <assert.h>
36
37 /* Private functions for the announce handler */
38 static announce_handler_t*  announce_HandlerCreate( vlc_object_t *);
39 static int announce_Register( announce_handler_t *p_announce,
40                               session_descriptor_t *p_session,
41                               announce_method_t *p_method );
42 static int announce_UnRegister( announce_handler_t *p_announce,
43                                 session_descriptor_t *p_session );
44
45 struct announce_method_t
46 {
47 } sap_method;
48
49 /****************************************************************************
50  * Sout-side functions
51  ****************************************************************************/
52
53 /**
54  *  Register a new session with the announce handler, using a pregenerated SDP
55  *
56  * \param p_sout a sout instance structure
57  * \param psz_sdp the SDP to register
58  * \param psz_dst session address (needed for SAP address auto detection)
59  * \param p_method an announce method descriptor
60  * \return the new session descriptor structure
61  */
62 session_descriptor_t *
63 sout_AnnounceRegisterSDP( sout_instance_t *p_sout, const char *cfgpref,
64                           const char *psz_sdp, const char *psz_dst,
65                           announce_method_t *p_method )
66 {
67     session_descriptor_t *p_session;
68     announce_handler_t *p_announce = (announce_handler_t*)
69                                      vlc_object_find( p_sout,
70                                               VLC_OBJECT_ANNOUNCE,
71                                               FIND_ANYWHERE );
72     if( !p_announce )
73     {
74         msg_Dbg( p_sout, "no announce handler found, creating one" );
75         p_announce = announce_HandlerCreate( VLC_OBJECT( p_sout ) );
76         if( !p_announce )
77         {
78             msg_Err( p_sout, "Creation failed" );
79             return NULL;
80         }
81         vlc_object_yield( p_announce );
82     }
83
84     p_session = malloc( sizeof( *p_session ) );
85     memset( p_session, 0, sizeof( *p_session ) );
86     p_session->psz_sdp = strdup( psz_sdp );
87
88     /* GRUIK. We should not convert back-and-forth from string to numbers */
89     struct addrinfo *res;
90     if (vlc_getaddrinfo (VLC_OBJECT (p_sout), psz_dst, 0, NULL, &res) == 0)
91     {
92         if (res->ai_addrlen <= sizeof (p_session->addr))
93             memcpy (&p_session->addr, res->ai_addr,
94                     p_session->addrlen = res->ai_addrlen);
95         vlc_freeaddrinfo (res);
96     }
97
98     announce_Register( p_announce, p_session, p_method );
99
100     vlc_object_release( p_announce );
101     return p_session;
102 }
103
104 /**
105  *  UnRegister an existing session
106  *
107  * \param p_sout a sout instance structure
108  * \param p_session the session descriptor
109  * \return VLC_SUCCESS or an error
110  */
111 int sout_AnnounceUnRegister( sout_instance_t *p_sout,
112                              session_descriptor_t *p_session )
113 {
114     int i_ret;
115     announce_handler_t *p_announce = (announce_handler_t*)
116                               vlc_object_find( p_sout,
117                                               VLC_OBJECT_ANNOUNCE,
118                                               FIND_ANYWHERE );
119     if( !p_announce )
120     {
121         msg_Dbg( p_sout, "unable to remove announce: no announce handler" );
122         return VLC_ENOOBJ;
123     }
124     i_ret  = announce_UnRegister( p_announce, p_session );
125     if( i_ret == 0 )
126         free( p_session );
127
128     vlc_object_release( p_announce );
129
130     return i_ret;
131 }
132
133 /**
134  * \return the SAP announce method
135  */
136 announce_method_t * sout_SAPMethod (void)
137 {
138     return &sap_method;
139 }
140
141 void sout_MethodRelease (announce_method_t *m)
142 {
143     assert (m == &sap_method);
144 }
145
146 /************************************************************************
147  * Announce handler functions (private)
148  ************************************************************************/
149
150 /**
151  * Create the announce handler object
152  *
153  * \param p_this a vlc_object structure
154  * \return the new announce handler or NULL on error
155  */
156 static announce_handler_t *announce_HandlerCreate( vlc_object_t *p_this )
157 {
158     announce_handler_t *p_announce;
159
160     p_announce = vlc_object_create( p_this, VLC_OBJECT_ANNOUNCE );
161
162     if( !p_announce )
163     {
164         msg_Err( p_this, "out of memory" );
165         return NULL;
166     }
167
168     p_announce->p_sap = NULL;
169     vlc_object_attach( p_announce, p_this->p_libvlc);
170
171     return p_announce;
172 }
173
174 /**
175  * Destroy a  announce handler object
176  *
177  * \param p_announce the announce handler to destroy
178  * \return VLC_SUCCESS or an error
179  */
180 int announce_HandlerDestroy( announce_handler_t *p_announce )
181 {
182     if( p_announce->p_sap )
183     {
184         vlc_object_kill ((vlc_object_t *)p_announce->p_sap);
185         /* Wait for the SAP thread to exit */
186         vlc_thread_join( (vlc_object_t *)p_announce->p_sap );
187         announce_SAPHandlerDestroy( p_announce->p_sap );
188     }
189
190     /* Free the structure */
191     vlc_object_destroy( p_announce );
192
193     return VLC_SUCCESS;
194 }
195
196 /* Register an announce */
197 static int announce_Register( announce_handler_t *p_announce,
198                               session_descriptor_t *p_session,
199                               announce_method_t *p_method )
200 {
201     if (p_method == NULL)
202         return VLC_EGENERIC;
203
204     msg_Dbg( p_announce, "registering announce");
205     if( p_method == &sap_method )
206     {
207         /* Do we already have a SAP announce handler ? */
208         if( !p_announce->p_sap )
209         {
210             sap_handler_t *p_sap = announce_SAPHandlerCreate( p_announce );
211             msg_Dbg( p_announce, "creating SAP announce handler");
212             if( !p_sap )
213             {
214                 msg_Err( p_announce, "SAP handler creation failed" );
215                 return VLC_ENOOBJ;
216             }
217             p_announce->p_sap = p_sap;
218         }
219         /* this will set p_session->p_sap for later deletion */
220         msg_Dbg( p_announce, "adding SAP session");
221         p_announce->p_sap->pf_add( p_announce->p_sap, p_session );
222     }
223     else
224     {
225         msg_Err( p_announce, "announce type unsupported" );
226         return VLC_EGENERIC;
227     }
228     return VLC_SUCCESS;
229 }
230
231
232 /* Unregister an announce */
233 static int announce_UnRegister( announce_handler_t *p_announce,
234                                 session_descriptor_t *p_session )
235 {
236     msg_Dbg( p_announce, "unregistering announce" );
237     if( p_announce->p_sap )
238         p_announce->p_sap->pf_del( p_announce->p_sap, p_session );
239     return VLC_SUCCESS;
240 }