Fix a bunch of preferences errors
[vlc.git] / modules / access / rtsp / access.c
1 /*****************************************************************************
2  * access.c: Real rtsp input
3  *****************************************************************************
4  * Copyright (C) 2005 VideoLAN
5  * $Id: file.c 10310 2005-03-11 22:36:40Z anil $
6  *
7  * Authors: Gildas Bazin <gbazin@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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/input.h>
29
30 #include "network.h"
31 #include "rtsp.h"
32 #include "real.h"
33
34 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open ( vlc_object_t * );
38 static void Close( vlc_object_t * );
39
40 #define CACHING_TEXT N_("Caching value (ms)")
41 #define CACHING_LONGTEXT N_( \
42     "Allows you to modify the default caching value for RTSP streams. This " \
43     "value should be set in millisecond units." )
44
45 vlc_module_begin();
46     set_description( _("Real RTSP") );
47     set_shortname( _("Real RTSP") );
48     set_category( CAT_INPUT );
49     set_subcategory( SUBCAT_INPUT_ACCESS );
50     add_integer( "realrtsp-caching", 3000, NULL,
51                  CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
52     set_capability( "access2", 10 );
53     set_callbacks( Open, Close );
54     add_shortcut( "realrtsp" );
55     add_shortcut( "rtsp" );
56 vlc_module_end();
57
58
59 /*****************************************************************************
60  * Exported prototypes
61  *****************************************************************************/
62 static block_t *BlockRead( access_t * );
63 static int     Seek( access_t *, int64_t );
64 static int     Control( access_t *, int, va_list );
65
66 struct access_sys_t
67 {
68     vlc_bool_t b_seekable;
69     vlc_bool_t b_pace_control;
70
71     rtsp_client_t *p_rtsp;
72
73     int fd;
74
75     block_t *p_header;
76 };
77
78 /*****************************************************************************
79  * Network wrappers
80  *****************************************************************************/
81 static int RtspConnect( void *p_userdata, char *psz_server, int i_port )
82 {
83     access_t *p_access = (access_t *)p_userdata;
84     access_sys_t *p_sys = p_access->p_sys;
85
86     /* Open connection */
87     p_sys->fd = net_OpenTCP( p_access, psz_server, i_port );
88     if( p_sys->fd < 0 )
89     {
90         msg_Err( p_access, "cannot connect to %s:%d", psz_server, i_port );
91         return VLC_EGENERIC;
92     }
93
94     return VLC_SUCCESS;
95 }
96
97 static int RtspDisconnect( void *p_userdata )
98 {
99     access_t *p_access = (access_t *)p_userdata;
100     access_sys_t *p_sys = p_access->p_sys;
101
102     net_Close( p_sys->fd );
103     return VLC_SUCCESS;
104 }
105
106 static int RtspRead( void *p_userdata, uint8_t *p_buffer, int i_buffer )
107 {
108     access_t *p_access = (access_t *)p_userdata;
109     access_sys_t *p_sys = p_access->p_sys;
110
111     return net_Read( p_access, p_sys->fd, 0, p_buffer, i_buffer, VLC_TRUE );
112 }
113
114 static int RtspReadLine( void *p_userdata, uint8_t *p_buffer, int i_buffer )
115 {
116     access_t *p_access = (access_t *)p_userdata;
117     access_sys_t *p_sys = p_access->p_sys;
118
119     char *psz = net_Gets( VLC_OBJECT(p_access), p_sys->fd, 0 );
120
121     //fprintf(stderr, "ReadLine: %s\n", psz);
122
123     if( psz ) strncpy( (char *)p_buffer, psz, i_buffer );
124     else *p_buffer = 0;
125
126     if( psz ) free( psz );
127     return 0;
128 }
129
130 static int RtspWrite( void *p_userdata, uint8_t *p_buffer, int i_buffer )
131 {
132     access_t *p_access = (access_t *)p_userdata;
133     access_sys_t *p_sys = p_access->p_sys;
134
135     //fprintf(stderr, "Write: %s", p_buffer);
136
137     net_Printf( VLC_OBJECT(p_access), p_sys->fd, 0, "%s", p_buffer );
138
139     return 0;
140 }
141
142 /*****************************************************************************
143  * Open: open the rtsp connection
144  *****************************************************************************/
145 static int Open( vlc_object_t *p_this )
146 {
147     access_t *p_access = (access_t *)p_this;
148     access_sys_t *p_sys;
149     char *psz_server = 0;
150     int i_result;
151
152     if( !p_access->b_force ) return VLC_EGENERIC;
153
154     p_access->pf_read = NULL;
155     p_access->pf_block = BlockRead;
156     p_access->pf_seek = Seek;
157     p_access->pf_control = Control;
158     p_access->info.i_update = 0;
159     p_access->info.i_size = 0;
160     p_access->info.i_pos = 0;
161     p_access->info.b_eof = VLC_FALSE;
162     p_access->info.i_title = 0;
163     p_access->info.i_seekpoint = 0;
164     p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
165     p_sys->p_rtsp = malloc( sizeof( rtsp_client_t) );
166
167     p_sys->p_header = 0;
168     p_sys->p_rtsp->p_userdata = p_access;
169     p_sys->p_rtsp->pf_connect = RtspConnect;
170     p_sys->p_rtsp->pf_disconnect = RtspDisconnect;
171     p_sys->p_rtsp->pf_read = RtspRead;
172     p_sys->p_rtsp->pf_read_line = RtspReadLine;
173     p_sys->p_rtsp->pf_write = RtspWrite;
174
175     i_result = rtsp_connect( p_sys->p_rtsp, p_access->psz_path, 0 );
176     if( i_result )
177     {
178         msg_Dbg( p_access, "could not connect to: %s", p_access->psz_path );
179         free( p_sys->p_rtsp );
180         p_sys->p_rtsp = 0;
181         goto error;
182     }
183
184     msg_Dbg( p_access, "rtsp connected" );
185
186     /* looking for server type */
187     if( rtsp_search_answers( p_sys->p_rtsp, "Server" ) )
188         psz_server = strdup( rtsp_search_answers( p_sys->p_rtsp, "Server" ) );
189     else
190     {
191         if( rtsp_search_answers( p_sys->p_rtsp, "RealChallenge1" ) )
192             psz_server = strdup("Real");
193         else
194             psz_server = strdup("unknown");
195     }
196
197     if( strstr( psz_server, "Real" ) || strstr( psz_server, "Helix" ) )
198     {
199         uint32_t bandwidth = 10485800;
200         rmff_header_t *h;
201
202         msg_Dbg( p_access, "found a real/helix rtsp server" );
203
204         if( !(h = real_setup_and_get_header( p_sys->p_rtsp, bandwidth )) )
205         {
206             /* Check if we got a redirect */
207             if( rtsp_search_answers( p_sys->p_rtsp, "Location" ) )
208             {
209                 msg_Dbg( p_access, "redirect: %s",
210                          rtsp_search_answers(p_sys->p_rtsp, "Location") );
211                 msg_Warn( p_access, "redirect not supported" );
212                 goto error;
213             }
214
215
216             msg_Err( p_access, "rtsp session can not be established" );
217             goto error;
218         }
219
220         p_sys->p_header = block_New( p_access, 4096 );
221         p_sys->p_header->i_buffer =
222             rmff_dump_header( h, p_sys->p_header->p_buffer, 1024 );
223     }
224     else
225     {
226         msg_Dbg( p_access, "only real/helix rtsp servers supported for now" );
227         goto error;
228     }
229
230     /* Update default_pts to a suitable value for file access */
231     var_Create( p_access, "realrtsp-caching",
232                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
233
234     return VLC_SUCCESS;
235
236  error:
237     if( psz_server ) free( psz_server );
238     Close( p_this );
239     return VLC_EGENERIC;
240 }
241
242 /*****************************************************************************
243  * Close: close the target
244  *****************************************************************************/
245 static void Close( vlc_object_t * p_this )
246 {
247     access_t     *p_access = (access_t*)p_this;
248     access_sys_t *p_sys = p_access->p_sys;
249
250     if( p_sys->p_rtsp ) rtsp_close( p_sys->p_rtsp );
251     if( p_sys->p_rtsp ) free( p_sys->p_rtsp );
252     free( p_sys );
253 }
254
255 /*****************************************************************************
256  * Read: standard read on a file descriptor.
257  *****************************************************************************/
258 static block_t *BlockRead( access_t *p_access )
259 {
260     access_sys_t *p_sys = p_access->p_sys;
261     block_t *p_block;
262     rmff_pheader_t pheader;
263     int i_size;
264
265     if( p_sys->p_header )
266     {
267         p_block = p_sys->p_header;
268         p_sys->p_header = 0;
269         return p_block;
270     }
271
272     i_size = real_get_rdt_chunk_header( p_access->p_sys->p_rtsp, &pheader );
273     if( i_size <= 0 ) return 0;
274
275     p_block = block_New( p_access, i_size );
276     p_block->i_buffer = real_get_rdt_chunk( p_access->p_sys->p_rtsp, &pheader,
277                                             &p_block->p_buffer );
278
279     return p_block;
280 }
281
282 /*****************************************************************************
283  * Seek: seek to a specific location in a file
284  *****************************************************************************/
285 static int Seek( access_t *p_access, int64_t i_pos )
286 {
287     return VLC_SUCCESS;
288 }
289
290 /*****************************************************************************
291  * Control:
292  *****************************************************************************/
293 static int Control( access_t *p_access, int i_query, va_list args )
294 {
295     vlc_bool_t   *pb_bool;
296     int          *pi_int;
297     int64_t      *pi_64;
298
299     switch( i_query )
300     {
301         /* */
302         case ACCESS_CAN_SEEK:
303         case ACCESS_CAN_FASTSEEK:
304             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
305             *pb_bool = VLC_FALSE;//p_sys->b_seekable;
306             break;
307
308         case ACCESS_CAN_PAUSE:
309             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
310             *pb_bool = VLC_FALSE;
311             break;
312
313         case ACCESS_CAN_CONTROL_PACE:
314             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
315             *pb_bool = VLC_TRUE;//p_sys->b_pace_control;
316             break;
317
318         /* */
319         case ACCESS_GET_MTU:
320             pi_int = (int*)va_arg( args, int * );
321             *pi_int = 0;
322             break;
323
324         case ACCESS_GET_PTS_DELAY:
325             pi_64 = (int64_t*)va_arg( args, int64_t * );
326             *pi_64 = var_GetInteger( p_access, "realrtsp-caching" ) * 1000;
327             break;
328
329         /* */
330         case ACCESS_SET_PAUSE_STATE:
331             /* Nothing to do */
332             break;
333
334         case ACCESS_GET_TITLE_INFO:
335         case ACCESS_SET_TITLE:
336         case ACCESS_SET_SEEKPOINT:
337         case ACCESS_SET_PRIVATE_ID_STATE:
338         case ACCESS_GET_META:
339             return VLC_EGENERIC;
340
341         default:
342             msg_Warn( p_access, "unimplemented query in control" );
343             return VLC_EGENERIC;
344     }
345
346     return VLC_SUCCESS;
347 }