* configure.ac : we need to define HAVE_SLP_H
[vlc.git] / modules / stream_out / standard.c
1 /*****************************************************************************
2  * standard.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: standard.c,v 1.9 2003/08/13 14:17:26 zorglub Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/sout.h>
33 #include <announce.h>
34
35 #define DEFAULT_IPV6_SCOPE "8"
36
37 /*****************************************************************************
38  * Exported prototypes
39  *****************************************************************************/
40 static int      Open    ( vlc_object_t * );
41 static void     Close   ( vlc_object_t * );
42
43 static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
44 static int               Del ( sout_stream_t *, sout_stream_id_t * );
45 static int               Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
46
47 /*****************************************************************************
48  * Module descriptor
49  *****************************************************************************/
50 vlc_module_begin();
51     set_description( _("Standard stream") );
52     set_capability( "sout stream", 50 );
53     add_shortcut( "standard" );
54     add_shortcut( "std" );
55     set_callbacks( Open, Close );
56 vlc_module_end();
57
58 struct sout_stream_sys_t
59 {
60     sout_mux_t           *p_mux;
61     slp_session_t        *p_slp;
62     sap_session_t        *p_sap;
63 };
64
65 /*****************************************************************************
66  * Open:
67  *****************************************************************************/
68 static int Open( vlc_object_t *p_this )
69 {
70     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
71     sout_instance_t     *p_sout = p_stream->p_sout;
72     sout_stream_sys_t   *p_sys = malloc( sizeof( sout_stream_sys_t) );
73
74     char *psz_mux      = sout_cfg_find_value( p_stream->p_cfg, "mux" );
75     char *psz_access   = sout_cfg_find_value( p_stream->p_cfg, "access" );
76     char *psz_url      = sout_cfg_find_value( p_stream->p_cfg, "url" );
77     char *psz_ipv      = sout_cfg_find_value( p_stream->p_cfg, "sap_ipv" );
78     char *psz_v6_scope = sout_cfg_find_value( p_stream->p_cfg, "sap_v6scope" );
79     
80     sout_cfg_t *p_sap_cfg = sout_cfg_find( p_stream->p_cfg, "sap" );
81     sout_cfg_t *p_slp_cfg = sout_cfg_find( p_stream->p_cfg, "slp" );
82     
83     sout_access_out_t   *p_access;
84     sout_mux_t          *p_mux;    
85
86     /* SAP is only valid for UDP or RTP streaming */
87     if( psz_access == NULL ) psz_access = "udp";
88
89     /* Get SAP IP version to use */
90     if(psz_ipv == NULL) psz_ipv = "4";
91     if(psz_v6_scope == NULL) psz_v6_scope = DEFAULT_IPV6_SCOPE;
92     p_sys->p_sap = NULL;
93
94     msg_Dbg( p_this, "creating `%s/%s://%s'",
95              psz_access, psz_mux, psz_url );
96
97     /* *** find and open appropriate access module *** */
98     p_access = sout_AccessOutNew( p_sout, psz_access, psz_url );
99     if( p_access == NULL )
100     {
101         msg_Err( p_stream, "no suitable sout access module for `%s/%s://%s'",
102                  psz_access, psz_mux, psz_url );
103         return( VLC_EGENERIC );
104     }
105     msg_Dbg( p_stream, "access opened" );
106
107     /* *** find and open appropriate mux module *** */
108     p_mux = sout_MuxNew( p_sout, psz_mux, p_access );
109     if( p_mux == NULL )
110     {
111         msg_Err( p_stream, "no suitable sout mux module for `%s/%s://%s'",
112                  psz_access, psz_mux, psz_url );
113
114         sout_AccessOutDelete( p_access );
115         return( VLC_EGENERIC );
116     }
117     msg_Dbg( p_stream, "mux opened" );
118
119     /*  *** Create the SAP Session structure *** */
120     if( p_sap_cfg && ( strstr( psz_access, "udp" ) ||
121                        strstr( psz_access ,  "rtp" ) ) )
122     {
123         msg_Info( p_this, "SAP Enabled");
124         msg_Dbg( p_sout , "Creating SAP with IPv%i", atoi(psz_ipv) );
125
126         p_sys->p_sap = sout_SAPNew( p_sout , psz_url ,
127             p_sap_cfg->psz_value ? p_sap_cfg->psz_value : psz_url,
128             atoi(psz_ipv), psz_v6_scope );
129
130         if( !p_sys->p_sap )
131             msg_Err( p_sout,"Unable to initialize SAP. SAP disabled");
132     }   
133
134     /* *** Register with slp *** */
135     #ifdef HAVE_SLP_H
136     if( p_slp_cfg && ( strstr( psz_access, "udp" ) ||
137                        strstr( psz_access ,  "rtp" ) ) )
138     {
139         p_sys->p_slp = NULL ;
140         msg_Info( p_this, "SLP Enabled");
141         if( sout_SLPReg( p_sout, psz_url, 
142             p_slp_cfg->psz_value ? p_slp_cfg->psz_value : psz_url) )
143         {
144            msg_Warn( p_sout, "SLP Registering failed");
145         }
146         else
147         {
148             p_sys->p_slp = (slp_session_t*)malloc(sizeof(slp_session_t));
149             if(!p_sys->p_slp)
150             {
151                 msg_Warn(p_sout,"Out of memory");
152                 return -1;        
153             }
154             p_sys->p_slp->psz_url= strdup(psz_url);
155             p_sys->p_slp->psz_name = strdup(
156                     p_slp_cfg->psz_value ? p_slp_cfg->psz_value : psz_url);
157         }
158     }        
159     #endif
160     
161     /* XXX beurk */
162     p_sout->i_preheader = __MAX( p_sout->i_preheader, p_mux->i_preheader );
163
164
165     p_sys->p_mux = p_mux;
166
167     p_stream->pf_add    = Add;
168     p_stream->pf_del    = Del;
169     p_stream->pf_send   = Send;
170
171     p_stream->p_sys     = p_sys;
172     return VLC_SUCCESS;
173 }
174
175 /*****************************************************************************
176  * Close:
177  *****************************************************************************/
178
179 static void Close( vlc_object_t * p_this )
180 {
181     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
182     sout_stream_sys_t *p_sys    = p_stream->p_sys;
183     sout_access_out_t *p_access = p_sys->p_mux->p_access;
184
185     if( p_sys->p_sap )
186         sout_SAPDelete( (sout_instance_t *)p_this , p_sys->p_sap ); 
187
188     #ifdef HAVE_SLP_H
189     if( p_sys->p_slp )
190     {
191             sout_SLPDereg( (sout_instance_t *)p_this, 
192                         p_sys->p_slp->psz_url,
193                         p_sys->p_slp->psz_name);
194             free( p_sys->p_slp);
195     }
196     #endif
197     
198     
199     sout_MuxDelete( p_sys->p_mux );
200     sout_AccessOutDelete( p_access );
201
202     free( p_sys );
203 }
204
205 struct sout_stream_id_t
206 {
207     sout_input_t *p_input;
208 };
209
210
211 static sout_stream_id_t * Add( sout_stream_t *p_stream, sout_format_t *p_fmt )
212 {
213     sout_stream_sys_t *p_sys = p_stream->p_sys;
214     sout_stream_id_t  *id;
215
216     id = malloc( sizeof( sout_stream_id_t ) );
217     if( ( id->p_input = sout_MuxAddStream( p_sys->p_mux, p_fmt ) ) == NULL )
218     {
219         free( id );
220
221         return NULL;
222     }
223
224     return id;
225 }
226
227 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
228 {
229     sout_stream_sys_t *p_sys = p_stream->p_sys;
230
231     sout_MuxDeleteStream( p_sys->p_mux, id->p_input );
232
233     free( id );
234
235     return VLC_SUCCESS;
236 }
237
238 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
239                  sout_buffer_t *p_buffer )
240 {
241     sout_stream_sys_t *p_sys = p_stream->p_sys;
242     sout_instance_t   *p_sout = p_stream->p_sout;
243
244     sout_MuxSendBuffer( p_sys->p_mux, id->p_input, p_buffer );
245
246     if( p_sys->p_sap )
247        sout_SAPSend( p_sout , p_sys->p_sap );
248
249     return VLC_SUCCESS;
250 }