1 /*****************************************************************************
2 * input_satellite.c: Satellite card input
3 *****************************************************************************
4 * Copyright (C) 1998-2002 VideoLAN
6 * Authors: Johan Bilien <jobi@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
30 #include <videolan/vlc.h>
37 #include <sys/types.h>
41 #ifdef STRNCASECMP_IN_STRINGS_H
45 #include "stream_control.h"
46 #include "input_ext-intf.h"
47 #include "input_ext-dec.h"
48 #include "input_ext-plugins.h"
52 #include "satellite_tools.h"
54 #define DISEQC 0 /* Wether you should use Diseqc*/
55 #define FEC 2 /* FEC */
56 #define LNB_LOF_1 9750000
57 #define LNB_LOF_2 10600000
58 #define LNB_SLOF 11700000
60 #define SATELLITE_READ_ONCE 3
62 /*****************************************************************************
64 *****************************************************************************/
65 static int SatelliteOpen ( input_thread_t * );
66 static void SatelliteClose ( input_thread_t * );
67 static int SatelliteSetArea ( input_thread_t *, input_area_t * );
68 static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
69 static void SatelliteSeek ( input_thread_t *, off_t );
71 static int SatelliteInit ( input_thread_t * );
72 static void SatelliteEnd ( input_thread_t * );
73 static int SatelliteDemux ( input_thread_t * );
74 static int SatelliteRewind ( input_thread_t * );
76 /*****************************************************************************
77 * Functions exported as capabilities. They are declared as static so that
78 * we don't pollute the namespace too much.
79 *****************************************************************************/
80 void _M( access_getfunctions )( function_list_t * p_function_list )
82 #define access p_function_list->functions.access
83 access.pf_open = SatelliteOpen;
84 access.pf_close = SatelliteClose;
85 access.pf_read = input_FDRead;
86 access.pf_set_area = SatelliteSetArea;
87 access.pf_set_program = SatelliteSetProgram;
88 access.pf_seek = SatelliteSeek;
93 void _M( demux_getfunctions )( function_list_t * p_function_list )
95 #define demux p_function_list->functions.demux
96 demux.pf_init = SatelliteInit;
97 demux.pf_end = SatelliteEnd;
98 demux.pf_demux = SatelliteDemux;
99 demux.pf_rewind = SatelliteRewind;
106 /*****************************************************************************
107 * SatelliteOpen : open the dvr device
108 *****************************************************************************/
109 static int SatelliteOpen( input_thread_t * p_input )
111 input_socket_t * p_satellite;
119 /* parse the options passed in command line : */
121 psz_parser = strdup( p_input->psz_name );
128 i_freq = (int)strtol( psz_parser, &psz_next, 10 );
132 psz_parser = psz_next + 1;
133 b_pol = (boolean_t)strtol( psz_parser, &psz_next, 10 );
136 psz_parser = psz_next + 1;
137 i_srate = (boolean_t)strtol( psz_parser, &psz_next, 10 );
142 i_freq = i_freq ? i_freq : config_GetIntVariable( "sat_frequency" );
143 i_srate = i_srate ? i_srate : config_GetIntVariable( "sat_symbol_rate" );
144 if ( !b_pol && b_pol != 1 )
145 b_pol = config_GetIntVariable( "sat_polarization" );
148 /* Initialise structure */
149 p_satellite = malloc( sizeof( input_socket_t ) );
151 if( p_satellite == NULL )
153 intf_ErrMsg( "input: satellite: Out of memory" );
157 p_input->p_access_data = (void *)p_satellite;
159 /* Open the DVR device */
161 intf_WarnMsg( 2, "input: opening file `%s'", DVR);
163 if( (p_satellite->i_handle = open( DVR,
164 /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
166 intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
171 /* Initialize the Satellite Card */
173 intf_WarnMsg( 2, "Initializing Sat Card with Freq: %d, Pol: %d, Srate: %d",
174 i_freq, b_pol, i_srate );
176 if ( ioctl_SECControl( i_freq * 1000, b_pol, LNB_SLOF, DISEQC ) < 0 )
178 intf_ErrMsg("input: satellite: An error occured when controling SEC");
182 intf_WarnMsg( 3, "Initializing Frontend device" );
183 switch (ioctl_SetQPSKFrontend ( i_freq * 1000, i_srate* 1000, FEC,
184 LNB_LOF_1, LNB_LOF_2, LNB_SLOF))
187 intf_ErrMsg( "input: satellite: Frontend returned\
188 an unexpected event" );
189 close( p_satellite->i_handle );
194 intf_ErrMsg( "input: satellite: Frontend returned\
196 close( p_satellite->i_handle );
201 intf_ErrMsg( "input: satellite: Frontend: time out\
202 when polling for event" );
203 close( p_satellite->i_handle );
208 intf_ErrMsg( "input: satellite: An error occured when polling\
210 close( p_satellite->i_handle );
215 intf_ErrMsg( "input: satellite: Frontend returned\
217 close( p_satellite->i_handle );
225 intf_WarnMsg( 3, " Setting filter on PAT " );
227 if ( ioctl_SetDMXFilter( 0, &i_fd, 3 ) < 0 )
229 intf_ErrMsg( "input: satellite: An error occured when setting\
234 if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
236 intf_ErrMsg( "input: satellite: Not enough memory to allow stream\
241 vlc_mutex_lock( &p_input->stream.stream_lock );
243 p_input->stream.b_pace_control = 1;
244 p_input->stream.b_seekable = 0;
245 p_input->stream.p_selected_area->i_tell = 0;
247 vlc_mutex_unlock( &p_input->stream.stream_lock );
249 p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE;
250 p_input->stream.i_method = INPUT_METHOD_SATELLITE;
251 p_input->psz_demux = "satellite";
257 /*****************************************************************************
258 * SatelliteClose : Closes the device
259 *****************************************************************************/
260 static void SatelliteClose( input_thread_t * p_input )
262 input_socket_t * p_satellite;
265 if ( p_input->stream.p_selected_program )
267 for ( i_es_index = 1 ;
268 i_es_index < p_input->stream.p_selected_program->
272 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
273 if ( p_es->p_decoder_fifo )
275 ioctl_UnsetDMXFilter( p_es->i_dmx_fd );
281 p_satellite = (input_socket_t *)p_input;
282 close( p_satellite->i_handle );
285 /*****************************************************************************
286 * SatelliteSetArea : Does nothing
287 *****************************************************************************/
288 static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
293 /*****************************************************************************
294 * SatelliteSetProgram : Sets the card filters according to the
296 * and makes the appropriate changes to stream structure.
297 *****************************************************************************/
298 int SatelliteSetProgram( input_thread_t * p_input,
299 pgrm_descriptor_t * p_new_prg )
303 if ( p_input->stream.p_selected_program )
305 for ( i_es_index = 1 ; /* 0 should be the PMT */
306 i_es_index < p_input->stream.p_selected_program->
310 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
311 if ( p_es->p_decoder_fifo )
313 input_UnselectES( p_input , p_es );
315 if ( p_es->i_dmx_fd )
317 ioctl_UnsetDMXFilter( p_es->i_dmx_fd );
324 for (i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
326 #define p_es p_new_prg->pp_es[i_es_index]
327 switch( p_es->i_cat )
331 if ( p_main->b_video )
333 ioctl_SetDMXFilter( p_es->i_id, &p_es->i_dmx_fd, 1);
334 input_SelectES( p_input , p_es );
339 if ( p_main->b_audio )
341 ioctl_SetDMXFilter( p_es->i_id, &p_es->i_dmx_fd, 2);
342 input_SelectES( p_input , p_es );
346 ioctl_SetDMXFilter( p_es->i_id, &p_es->i_dmx_fd, 3);
347 input_SelectES( p_input , p_es );
353 p_input->stream.p_selected_program = p_new_prg;
358 /*****************************************************************************
359 * SatelliteSeek: does nothing (not a seekable stream
360 *****************************************************************************/
361 static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
366 /*****************************************************************************
367 * SatelliteInit: initializes TS structures
368 *****************************************************************************/
369 static int SatelliteInit( input_thread_t * p_input )
371 es_descriptor_t * p_pat_es;
372 es_ts_data_t * p_demux_data;
373 stream_ts_data_t * p_stream_data;
375 /* Initialize the stream */
376 input_InitStream( p_input, sizeof( stream_ts_data_t ) );
380 p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;
381 p_stream_data->i_pat_version = PAT_UNINITIALIZED ;
383 /* We'll have to catch the PAT in order to continue
384 * Then the input will catch the PMT and then the others ES
385 * The PAT es is indepedent of any program. */
386 p_pat_es = input_AddES( p_input, NULL,
387 0x00, sizeof( es_ts_data_t ) );
388 p_demux_data=(es_ts_data_t *)p_pat_es->p_demux_data;
389 p_demux_data->b_psi = 1;
390 p_demux_data->i_psi_type = PSI_IS_PAT;
391 p_demux_data->p_psi_section = malloc(sizeof(psi_section_t));
392 p_demux_data->p_psi_section->b_is_complete = 1;
398 /*****************************************************************************
399 * SatelliteEnd: frees unused data
400 *****************************************************************************/
401 static void SatelliteEnd( input_thread_t * p_input )
405 /*****************************************************************************
407 *****************************************************************************/
408 static int SatelliteDemux( input_thread_t * p_input )
410 int i_read_once = (p_input->i_mtu ?
411 p_input->i_bufsize / TS_PACKET_SIZE :
412 SATELLITE_READ_ONCE);
415 /* if not set, set filters to the PMTs */
417 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
419 if ( p_input->stream.pp_programs[i]->pp_es[0]->i_dmx_fd == 0 )
421 intf_WarnMsg( 2, "input: satellite: setting filter on pmt pid %d",
422 p_input->stream.pp_programs[i]->pp_es[0]->i_id);
423 ioctl_SetDMXFilter( p_input->stream.pp_programs[i]->pp_es[0]->i_id,
424 &p_input->stream.pp_programs[i]->pp_es[0]->i_dmx_fd,
430 for( i = 0; i < SATELLITE_READ_ONCE; i++ )
432 data_packet_t * p_data;
435 i_result = input_ReadTS( p_input, &p_data );
442 input_DemuxTS( p_input, p_data );
445 return( i_read_once );
448 /*****************************************************************************
449 * SatelliteRewind: Does nothing
450 *****************************************************************************/
451 static int SatelliteRewind( input_thread_t * p_input )