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