]> git.sesse.net Git - vlc/blob - plugins/satellite/input_satellite.c
* plugins/satellite/input_satellite.c: cosmetic changes in error messages
[vlc] / plugins / satellite / input_satellite.c
1 /*****************************************************************************
2  * input_satellite.c: Satellite card input
3  *****************************************************************************
4  * Copyright (C) 1998-2002 VideoLAN
5  *
6  * Authors: Johan Bilien <jobi@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 #include <videolan/vlc.h>
31
32 #ifdef HAVE_UNISTD_H
33 #   include <unistd.h>
34 #endif
35
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <string.h>
39 #include <errno.h>
40
41 #ifdef STRNCASECMP_IN_STRINGS_H
42 #   include <strings.h>
43 #endif
44
45 #include "stream_control.h"
46 #include "input_ext-intf.h"
47 #include "input_ext-dec.h"
48 #include "input_ext-plugins.h"
49
50 #include "satellite_tools.h"
51
52 #define SATELLITE_READ_ONCE 3
53
54 /*****************************************************************************
55  * Local prototypes
56  *****************************************************************************/
57 static int     SatelliteOpen       ( input_thread_t * );
58 static void    SatelliteClose      ( input_thread_t * );
59 static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
60                                      size_t i_len );
61 static int     SatelliteSetArea    ( input_thread_t *, input_area_t * );
62 static int     SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
63 static void    SatelliteSeek       ( input_thread_t *, off_t );
64
65 /*****************************************************************************
66  * Functions exported as capabilities. They are declared as static so that
67  * we don't pollute the namespace too much.
68  *****************************************************************************/
69 void _M( access_getfunctions )( function_list_t * p_function_list )
70 {
71 #define access p_function_list->functions.access
72     access.pf_open             = SatelliteOpen;
73     access.pf_close            = SatelliteClose;
74     access.pf_read             = SatelliteRead;
75     access.pf_set_area         = SatelliteSetArea;
76     access.pf_set_program      = SatelliteSetProgram;
77     access.pf_seek             = SatelliteSeek;
78 #undef access
79 }
80
81 /*****************************************************************************
82  * SatelliteOpen : open the dvr device
83  *****************************************************************************/
84 static int SatelliteOpen( input_thread_t * p_input )
85 {
86     input_socket_t *    p_satellite;
87     char *              psz_parser;
88     char *              psz_next;
89     int                 i_fd = 0;
90     int                 i_freq = 0;
91     int                 i_srate = 0;
92     boolean_t           b_pol = 0;
93     int                 i_fec = 0;
94     float               f_fec = 1./2;
95     boolean_t           b_diseqc;
96     int                 i_lnb_lof1;
97     int                 i_lnb_lof2;
98     int                 i_lnb_slof;
99
100     /* parse the options passed in command line : */
101
102     psz_parser = strdup( p_input->psz_name );
103
104     if( !psz_parser )
105     {
106         return( -1 );
107     }
108
109     i_freq = (int)strtol( psz_parser, &psz_next, 10 );
110
111     if( *psz_next )
112     {
113         psz_parser = psz_next + 1;
114         b_pol = (boolean_t)strtol( psz_parser, &psz_next, 10 );
115             if( *psz_next )
116             {
117                 psz_parser = psz_next + 1;
118                 i_fec = (int)strtol( psz_parser, &psz_next, 10 );
119                 if( *psz_next )
120                 {
121                     psz_parser = psz_next + 1;
122                     i_srate = (int)strtol( psz_parser, &psz_next, 10 );
123                 }
124             }
125
126     }
127
128     if( i_freq > 12999 || i_freq < 10000 )
129     {
130         intf_WarnMsg( 1, "input: satellite: invalid frequency, using "\
131                 "default one" );
132         i_freq = config_GetIntVariable( "frequency" );
133         if( i_freq > 12999 || i_freq < 10000 )
134         {
135             intf_ErrMsg( "input: satellite: invalid default frequency" );
136             return -1;
137         }
138     }
139
140     if( i_srate > 30000 || i_srate < 1000 )
141     {
142         intf_WarnMsg( 1, "input: satellite: invalid symbol rate, using "\
143                 "default one" );
144         i_srate = config_GetIntVariable( "symbol-rate" );
145         if( i_srate > 30000 || i_srate < 1000 )
146         {
147             intf_ErrMsg( "input: satellite: invalid default symbol rate" );
148             return -1;
149         }
150     }
151
152     if( b_pol && b_pol != 1 )
153     {
154         intf_WarnMsg( 1, "input: satellite: invalid polarization, using "\
155                 "default one" );
156         b_pol = config_GetIntVariable( "polarization" );
157         fprintf(stderr, "%d\n", b_pol);
158         if( b_pol && b_pol != 1 )
159         {
160             intf_ErrMsg( "input: satellite: invalid default polarization" );
161             return -1;
162         }
163     }
164
165     if( i_fec > 7 || i_fec < 1 )
166     {
167         intf_WarnMsg( 1, "input: satellite: invalid FEC, using default one " );
168         i_fec = config_GetIntVariable( "fec" );
169         if( i_fec > 7 || i_fec < 1 )
170         {
171             intf_ErrMsg( "input: satellite: invalid default FEC" );
172             return -1;
173         }
174     }
175
176     switch( i_fec )
177     {
178         case 1:
179             f_fec = 1./2;
180             break;
181         case 2:
182             f_fec = 2./3;
183             break;
184         case 3:
185             f_fec = 3./4;
186             break;
187         case 4:
188             f_fec = 4./5;
189             break;
190         case 5:
191             f_fec = 5./6;
192             break;
193         case 6:
194             f_fec = 6./7;
195             break;
196         case 7:
197             f_fec = 7./8;
198             break;
199         default:
200             /* cannot happen */
201             break;
202     }
203
204
205     /* Initialise structure */
206     p_satellite = malloc( sizeof( input_socket_t ) );
207
208     if( p_satellite == NULL )
209     {
210         intf_ErrMsg( "input: satellite: Out of memory" );
211         return -1;
212     }
213
214     p_input->p_access_data = (void *)p_satellite;
215
216     /* Open the DVR device */
217
218     intf_WarnMsg( 2, "input: opening file `%s'", DVR);
219
220     if( (p_satellite->i_handle = open( DVR,
221                                    /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
222     {
223         intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
224         free( p_satellite );
225         return -1;
226     }
227
228
229     /* Get antenna configuration options */
230     b_diseqc = config_GetIntVariable( "diseqc" );
231     i_lnb_lof1 = config_GetIntVariable( "lnb-lof1" );
232     i_lnb_lof2 = config_GetIntVariable( "lnb-lof2" );
233     i_lnb_slof = config_GetIntVariable( "lnb-slof" );
234
235     /* Initialize the Satellite Card */
236
237     intf_WarnMsg( 2, "Initializing Sat Card with Freq: %d, Pol: %d, "\
238                         "FEC: %03f, Srate: %d",
239                         i_freq, b_pol, f_fec, i_srate );
240
241     if ( ioctl_SECControl( i_freq * 1000, b_pol, i_lnb_slof * 1000,
242                 b_diseqc ) < 0 )
243     {
244         intf_ErrMsg("input: satellite: An error occured when controling SEC");
245         close( p_satellite->i_handle );
246         free( p_satellite );
247         return -1;
248     }
249
250     intf_WarnMsg( 3, "Initializing Frontend device" );
251     switch (ioctl_SetQPSKFrontend ( i_freq * 1000, i_srate* 1000, f_fec,
252                 i_lnb_lof1 * 1000, i_lnb_lof2 * 1000, i_lnb_slof * 1000))
253     {
254         case -2:
255             intf_ErrMsg( "input: satellite: Frontend returned"\
256                     "an unexpected event" );
257             close( p_satellite->i_handle );
258             free( p_satellite );
259             return -1;
260             break;
261         case -3:
262             intf_ErrMsg( "input: satellite: Frontend returned"\
263                     "no event" );
264             close( p_satellite->i_handle );
265             free( p_satellite );
266             return -1;
267             break;
268         case -4:
269             intf_ErrMsg( "input: satellite: Frontend: time out"\
270                     "when polling for event" );
271             close( p_satellite->i_handle );
272             free( p_satellite );
273             return -1;
274             break;
275         case -5:
276              intf_ErrMsg( "input: satellite: An error occured when polling"\
277                     "Frontend device" );
278             close( p_satellite->i_handle );
279             free( p_satellite );
280             return -1;
281             break;
282         case -1:
283              intf_ErrMsg( "input: satellite: Frontend returned"\
284                     "a failure event" );
285             close( p_satellite->i_handle );
286             free( p_satellite );
287             return -1;
288             break;
289         default:
290             break;
291     }
292
293     intf_WarnMsg( 3, " Setting filter on PAT " );
294
295     if ( ioctl_SetDMXFilter( 0, &i_fd, 3 ) < 0 )
296     {
297         intf_ErrMsg( "input: satellite: An error occured when setting"\
298                 "filter on PAT" );
299         close( p_satellite->i_handle );
300         free( p_satellite );
301         return -1;
302     }
303
304     if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
305     {
306         intf_ErrMsg( "input: satellite: Not enough memory to allow stream"\
307                         "structure" );
308         close( p_satellite->i_handle );
309         free( p_satellite );
310         return( -1 );
311     }
312
313     vlc_mutex_lock( &p_input->stream.stream_lock );
314
315     p_input->stream.b_pace_control = 1;
316     p_input->stream.b_seekable = 0;
317     p_input->stream.p_selected_area->i_tell = 0;
318
319     vlc_mutex_unlock( &p_input->stream.stream_lock );
320
321     p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE;
322     p_input->stream.i_method = INPUT_METHOD_SATELLITE;
323
324     return 0;
325 }
326
327 /*****************************************************************************
328  * SatelliteClose : Closes the device
329  *****************************************************************************/
330 static void SatelliteClose( input_thread_t * p_input )
331 {
332     input_socket_t *    p_satellite;
333     int                 i_es_index;
334
335     if ( p_input->stream.p_selected_program )
336     {
337         for ( i_es_index = 1 ;
338                 i_es_index < p_input->stream.p_selected_program->
339                     i_es_number ;
340                 i_es_index ++ )
341         {
342 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
343             if ( p_es->p_decoder_fifo )
344             {
345                 ioctl_UnsetDMXFilter( p_es->i_demux_fd );
346             }
347 #undef p_es
348         }
349     }
350
351     p_satellite = (input_socket_t *)p_input;
352     close( p_satellite->i_handle );
353 }
354
355
356 /*****************************************************************************
357  * SatelliteRead: reads data from the satellite card
358  *****************************************************************************/
359 static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
360                 size_t i_len )
361 {
362     int i;
363
364     /* if not set, set filters to the PMTs */
365     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
366     {
367         if ( p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 )
368         {
369             intf_WarnMsg( 2, "input: satellite: setting filter on pmt pid %d",
370                         p_input->stream.pp_programs[i]->pp_es[0]->i_id);
371             ioctl_SetDMXFilter( p_input->stream.pp_programs[i]->pp_es[0]->i_id,
372                        &p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd,
373                        3 );
374         }
375     }
376
377     return input_FDRead( p_input, p_buffer, i_len );
378 }
379
380
381
382
383 /*****************************************************************************
384  * SatelliteSetArea : Does nothing
385  *****************************************************************************/
386 static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
387 {
388     return -1;
389 }
390
391 /*****************************************************************************
392  * SatelliteSetProgram : Sets the card filters according to the
393  *                 selected program,
394  *                 and makes the appropriate changes to stream structure.
395  *****************************************************************************/
396 int SatelliteSetProgram( input_thread_t    * p_input,
397                          pgrm_descriptor_t * p_new_prg )
398 {
399     int                 i_es_index;
400
401     if ( p_input->stream.p_selected_program )
402     {
403         for ( i_es_index = 1 ; /* 0 should be the PMT */
404                 i_es_index < p_input->stream.p_selected_program->
405                     i_es_number ;
406                 i_es_index ++ )
407         {
408 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
409             if ( p_es->p_decoder_fifo )
410             {
411                 input_UnselectES( p_input , p_es );
412             }
413             if ( p_es->i_demux_fd )
414             {
415                 ioctl_UnsetDMXFilter( p_es->i_demux_fd );
416                 p_es->i_demux_fd = 0;
417             }
418 #undef p_es
419         }
420     }
421
422     for (i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
423     {
424 #define p_es p_new_prg->pp_es[i_es_index]
425         switch( p_es->i_cat )
426         {
427             case MPEG1_VIDEO_ES:
428             case MPEG2_VIDEO_ES:
429                 if ( p_main->b_video )
430                 {
431                     ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 1);
432                     input_SelectES( p_input , p_es );
433                 }
434                 break;
435             case MPEG1_AUDIO_ES:
436             case MPEG2_AUDIO_ES:
437                 if ( p_main->b_audio )
438                 {
439                     ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 2);
440                     input_SelectES( p_input , p_es );
441                 }
442                 break;
443             default:
444                 ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3);
445                 input_SelectES( p_input , p_es );
446                 break;
447 #undef p_es
448         }
449     }
450
451     p_input->stream.p_selected_program = p_new_prg;
452
453     return( 0 );
454 }
455
456 /*****************************************************************************
457  * SatelliteSeek: does nothing (not a seekable stream
458  *****************************************************************************/
459 static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
460 {
461     return;
462 }