access.c 34.5 KB
Newer Older
1 2 3
/*****************************************************************************
 * access.c: DVB card input v4l2 only
 *****************************************************************************
David Kaplan's avatar
David Kaplan committed
4
 * Copyright (C) 1998-2010 the VideoLAN team
5 6
 *
 * Authors: Johan Bilien <jobi@via.ecp.fr>
Jean-Paul Saman's avatar
Jean-Paul Saman committed
7
 *          Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
8
 *          Christophe Massiot <massiot@via.ecp.fr>
9
 *          Laurent Aimar <fenrir@via.ecp.fr>
David Kaplan's avatar
David Kaplan committed
10
 *          David Kaplan <david@2of1.org>
11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
22 23 24
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 26 27 28 29 30
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/
31 32 33 34
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

35
#include <vlc_common.h>
36
#include <vlc_plugin.h>
Clément Stenac's avatar
Clément Stenac committed
37
#include <vlc_access.h>
38
#include <vlc_input.h>
Clément Stenac's avatar
Clément Stenac committed
39
#include <vlc_interface.h>
40
#include <vlc_dialog.h>
David Kaplan's avatar
David Kaplan committed
41
#include <vlc_fs.h>
42 43 44 45 46 47

#ifdef HAVE_UNISTD_H
#   include <unistd.h>
#endif

#include <sys/types.h>
48
#include <poll.h>
49

50
#include <errno.h>
51

Christophe Massiot's avatar
Christophe Massiot committed
52 53 54 55 56 57 58 59
/* Include dvbpsi headers */
#ifdef HAVE_DVBPSI_DR_H
#   include <dvbpsi/dvbpsi.h>
#   include <dvbpsi/descriptor.h>
#   include <dvbpsi/pat.h>
#   include <dvbpsi/pmt.h>
#   include <dvbpsi/dr.h>
#   include <dvbpsi/psi.h>
Laurent Aimar's avatar
Laurent Aimar committed
60 61
#   include <dvbpsi/demux.h>
#   include <dvbpsi/sdt.h>
Christophe Massiot's avatar
Christophe Massiot committed
62 63 64 65 66 67 68
#else
#   include "dvbpsi.h"
#   include "descriptor.h"
#   include "tables/pat.h"
#   include "tables/pmt.h"
#   include "descriptors/dr.h"
#   include "psi.h"
Laurent Aimar's avatar
Laurent Aimar committed
69
#   include "demux.h"
70
#   include "tables/sdt.h"
Christophe Massiot's avatar
Christophe Massiot committed
71 72
#endif

73
#ifdef ENABLE_HTTPD
Rémi Duraffort's avatar
Rémi Duraffort committed
74
#   include <vlc_httpd.h>
75 76
#endif

77 78
#include "dvb.h"

79 80 81
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
82 83 84
static int  Open( vlc_object_t *p_this );
static void Close( vlc_object_t *p_this );

85 86
#define CACHING_TEXT N_("Caching value in ms")
#define CACHING_LONGTEXT N_( \
87
    "Caching value for DVB streams. This " \
Clément Stenac's avatar
Clément Stenac committed
88
    "value should be set in milliseconds." )
89

90 91 92 93 94 95 96 97 98 99 100 101 102
#define ADAPTER_TEXT N_("Adapter card to tune")
#define ADAPTER_LONGTEXT N_("Adapter cards have a device file in directory named /dev/dvb/adapter[n] with n>=0.")

#define DEVICE_TEXT N_("Device number to use on adapter")
#define DEVICE_LONGTEXT ""

#define FREQ_TEXT N_("Transponder/multiplex frequency")
#define FREQ_LONGTEXT N_("In kHz for DVB-S or Hz for DVB-C/T")

#define INVERSION_TEXT N_("Inversion mode")
#define INVERSION_LONGTEXT N_("Inversion mode [0=off, 1=on, 2=auto]")

#define PROBE_TEXT N_("Probe DVB card for capabilities")
Clément Stenac's avatar
Clément Stenac committed
103
#define PROBE_LONGTEXT N_("Some DVB cards do not like to be probed for their capabilities, you can disable this feature if you experience some trouble.")
104 105

#define BUDGET_TEXT N_("Budget mode")
Clément Stenac's avatar
Clément Stenac committed
106
#define BUDGET_LONGTEXT N_("This allows you to stream an entire transponder with a \"budget\" card.")
107

108
/* Satellite */
David Kaplan's avatar
David Kaplan committed
109 110 111
#define SATELLITE_TEXT N_("Satellite scanning config")
#define SATELLITE_LONGTEXT N_("filename of config file in share/dvb/dvb-s")

112
#define SATNO_TEXT N_("Satellite number in the Diseqc system")
Clément Stenac's avatar
Clément Stenac committed
113
#define SATNO_LONGTEXT N_("[0=no diseqc, 1-4=satellite number].")
114 115

#define VOLTAGE_TEXT N_("LNB voltage")
Clément Stenac's avatar
Clément Stenac committed
116
#define VOLTAGE_LONGTEXT N_("In Volts [0, 13=vertical, 18=horizontal].")
117

Christophe Massiot's avatar
Christophe Massiot committed
118 119 120 121
#define HIGH_VOLTAGE_TEXT N_("High LNB voltage")
#define HIGH_VOLTAGE_LONGTEXT N_("Enable high voltage if your cables are " \
    "particularly long. This is not supported by all frontends.")

122
#define TONE_TEXT N_("22 kHz tone")
Clément Stenac's avatar
Clément Stenac committed
123
#define TONE_LONGTEXT N_("[0=off, 1=on, -1=auto].")
124 125

#define FEC_TEXT N_("Transponder FEC")
Clément Stenac's avatar
Clément Stenac committed
126
#define FEC_LONGTEXT N_("FEC=Forward Error Correction mode [9=auto].")
127 128 129 130

#define SRATE_TEXT N_("Transponder symbol rate in kHz")
#define SRATE_LONGTEXT ""

131 132 133 134 135 136 137 138 139
#define LNB_LOF1_TEXT N_("Antenna lnb_lof1 (kHz)")
#define LNB_LOF1_LONGTEXT ""

#define LNB_LOF2_TEXT N_("Antenna lnb_lof2 (kHz)")
#define LNB_LOF2_LONGTEXT ""

#define LNB_SLOF_TEXT N_("Antenna lnb_slof (kHz)")
#define LNB_SLOF_LONGTEXT ""

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
/* Cable */
#define MODULATION_TEXT N_("Modulation type")
#define MODULATION_LONGTEXT N_("Modulation type for front-end device.")

/* Terrestrial */
#define CODE_RATE_HP_TEXT N_("Terrestrial high priority stream code rate (FEC)")
#define CODE_RATE_HP_LONGTEXT ""

#define CODE_RATE_LP_TEXT N_("Terrestrial low priority stream code rate (FEC)")
#define CODE_RATE_LP_LONGTEXT ""

#define BANDWIDTH_TEXT N_("Terrestrial bandwidth")
#define BANDWIDTH_LONGTEXT N_("Terrestrial bandwidth [0=auto,6,7,8 in MHz]")

#define GUARD_TEXT N_("Terrestrial guard interval")
#define GUARD_LONGTEXT ""

#define TRANSMISSION_TEXT N_("Terrestrial transmission mode")
#define TRANSMISSION_LONGTEXT ""

#define HIERARCHY_TEXT N_("Terrestrial hierarchy mode")
#define HIERARCHY_LONGTEXT ""

163 164 165 166 167 168
#define HOST_TEXT N_( "HTTP Host address" )
#define HOST_LONGTEXT N_( \
    "To enable the internal HTTP server, set its address and port here." )

#define USER_TEXT N_( "HTTP user name" )
#define USER_LONGTEXT N_( \
Clément Stenac's avatar
Clément Stenac committed
169
    "User name the administrator will use to log into " \
170 171 172 173
    "the internal HTTP server." )

#define PASSWORD_TEXT N_( "HTTP password" )
#define PASSWORD_LONGTEXT N_( \
Clément Stenac's avatar
Clément Stenac committed
174
    "Password the administrator will use to log into " \
175 176 177 178
    "the internal HTTP server." )

#define ACL_TEXT N_( "HTTP ACL" )
#define ACL_LONGTEXT N_( \
Clément Stenac's avatar
Clément Stenac committed
179
    "Access control list (equivalent to .hosts) file path, " \
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    "which will limit the range of IPs entitled to log into the internal " \
    "HTTP server." )

#define CERT_TEXT N_( "Certificate file" )
#define CERT_LONGTEXT N_( "HTTP interface x509 PEM certificate file " \
                          "(enables SSL)" )

#define KEY_TEXT N_( "Private key file" )
#define KEY_LONGTEXT N_( "HTTP interface x509 PEM private key file" )

#define CA_TEXT N_( "Root CA file" )
#define CA_LONGTEXT N_( "HTTP interface x509 PEM trusted root CA " \
                        "certificates file" )

#define CRL_TEXT N_( "CRL file" )
#define CRL_LONGTEXT N_( "HTTP interface Certificates Revocation List file" )

197 198 199 200 201
vlc_module_begin ()
    set_shortname( N_("DVB") )
    set_description( N_("DVB input with v4l2 support") )
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_ACCESS )
202

203
    add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, CACHING_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
204
                 CACHING_LONGTEXT, true )
205
        change_safe()
206
    add_integer( "dvb-adapter", 0, ADAPTER_TEXT, ADAPTER_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
207
                 false )
208
    add_integer( "dvb-device", 0, DEVICE_TEXT, DEVICE_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
209
                 true )
210
    add_integer( "dvb-frequency", 0, FREQ_TEXT, FREQ_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
211
                 false )
212
        change_safe()
213
    add_integer( "dvb-inversion", 2, INVERSION_TEXT, INVERSION_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
214
                 true )
215 216
    add_bool( "dvb-probe", true, PROBE_TEXT, PROBE_LONGTEXT, true )
    add_bool( "dvb-budget-mode", false, BUDGET_TEXT, BUDGET_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
217
              true )
218
    /* DVB-S (satellite) */
219
    add_string( "dvb-satellite", NULL, SATELLITE_TEXT, SATELLITE_LONGTEXT,
David Kaplan's avatar
David Kaplan committed
220
                true )
221
    add_integer( "dvb-satno", 0, SATNO_TEXT, SATNO_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
222
                 true )
223
    add_integer( "dvb-voltage", 13, VOLTAGE_TEXT, VOLTAGE_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
224
                 true )
225
    add_bool( "dvb-high-voltage", false, HIGH_VOLTAGE_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
226
              HIGH_VOLTAGE_LONGTEXT, true )
227
    add_integer( "dvb-tone", -1, TONE_TEXT, TONE_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
228
                 true )
229 230
    add_integer( "dvb-fec", 9, FEC_TEXT, FEC_LONGTEXT, true )
    add_integer( "dvb-srate", 27500000, SRATE_TEXT, SRATE_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
231
                 false )
232
    add_integer( "dvb-lnb-lof1", 0, LNB_LOF1_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
233
                 LNB_LOF1_LONGTEXT, true )
234
    add_integer( "dvb-lnb-lof2", 0, LNB_LOF2_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
235
                 LNB_LOF2_LONGTEXT, true )
236
    add_integer( "dvb-lnb-slof", 0, LNB_SLOF_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
237
                 LNB_SLOF_LONGTEXT, true )
238
    /* DVB-C (cable) */
239
    add_integer( "dvb-modulation", 0, MODULATION_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
240
                 MODULATION_LONGTEXT, true )
241
    /* DVB-T (terrestrial) */
242
    add_integer( "dvb-code-rate-hp", 9, CODE_RATE_HP_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
243
                 CODE_RATE_HP_LONGTEXT, true )
244
    add_integer( "dvb-code-rate-lp", 9, CODE_RATE_LP_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
245
                 CODE_RATE_LP_LONGTEXT, true )
246
    add_integer( "dvb-bandwidth", 0, BANDWIDTH_TEXT, BANDWIDTH_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
247
                 true )
248
        change_safe()
249 250
    add_integer( "dvb-guard", 0, GUARD_TEXT, GUARD_LONGTEXT, true )
    add_integer( "dvb-transmission", 0, TRANSMISSION_TEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
251
                 TRANSMISSION_LONGTEXT, true )
252
    add_integer( "dvb-hierarchy", 0, HIERARCHY_TEXT, HIERARCHY_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
253
                 true )
254 255
#ifdef ENABLE_HTTPD
    /* MMI HTTP interface */
256
    set_section( N_("HTTP server" ), 0 )
257
    add_string( "dvb-http-host", NULL, HOST_TEXT, HOST_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
258
                true )
259
    add_string( "dvb-http-user", NULL, USER_TEXT, USER_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
260
                true )
261
    add_password( "dvb-http-password", NULL, PASSWORD_TEXT,
262
                  PASSWORD_LONGTEXT, true )
263
    add_string( "dvb-http-acl", NULL, ACL_TEXT, ACL_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
264
                true )
265
    add_string( "dvb-http-intf-cert", NULL, CERT_TEXT, CERT_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
266
                true )
267
    add_string( "dvb-http-intf-key",  NULL, KEY_TEXT,  KEY_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
268
                true )
269
    add_string( "dvb-http-intf-ca",   NULL, CA_TEXT,   CA_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
270
                true )
271
    add_string( "dvb-http-intf-crl",  NULL, CRL_TEXT,  CRL_LONGTEXT,
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
272
                true )
273
#endif
274

275
    set_capability( "access", 0 )
276 277 278 279 280
    add_shortcut( "dvb",                        /* Generic name */
                  "dvb-s", "qpsk", "satellite", /* Satellite */
                  "dvb-c", "cable",             /* Cable */
                  "dvb-t", "terrestrial",       /* Terrestrial */
                  "atsc" )                      /* Atsc */
281
    add_shortcut( "usdigital" )
282

283
    set_callbacks( Open, Close )
Laurent Aimar's avatar
Laurent Aimar committed
284

285
vlc_module_end ()
286

287

288
/*****************************************************************************
289
 * Local prototypes
290
 *****************************************************************************/
291 292
static block_t *Block( access_t * );
static int Control( access_t *, int, va_list );
293

Laurent Aimar's avatar
Laurent Aimar committed
294 295
static block_t *BlockScan( access_t * );

296 297
#define DVB_READ_ONCE 20
#define DVB_READ_ONCE_START 2
Laurent Aimar's avatar
Laurent Aimar committed
298
#define DVB_READ_ONCE_SCAN 1
299
#define TS_PACKET_SIZE 188
300

301
#define DVB_SCAN_MAX_SIGNAL_TIME (1000*1000)
Laurent Aimar's avatar
Laurent Aimar committed
302
#define DVB_SCAN_MAX_LOCK_TIME (5000*1000)
303
#define DVB_SCAN_MAX_PROBE_TIME (45000*1000)
Laurent Aimar's avatar
Laurent Aimar committed
304

Laurent Aimar's avatar
Laurent Aimar committed
305 306
static void FilterUnset( access_t *, int i_max );
static void FilterUnsetPID( access_t *, int i_pid );
307
static void FilterSet( access_t *, int i_pid, int i_type );
308

309 310
static void VarInit( access_t * );
static int  ParseMRL( access_t * );
311

312 313 314 315 316 317 318 319 320
/*****************************************************************************
 * Open: open the frontend device
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    access_t     *p_access = (access_t*)p_this;
    access_sys_t *p_sys;

    /* Only if selected */
321
    if( *p_access->psz_access == '\0' )
322 323 324 325 326 327 328
        return VLC_EGENERIC;

    /* Set up access */
    p_access->pf_read = NULL;
    p_access->pf_block = Block;
    p_access->pf_control = Control;
    p_access->pf_seek = NULL;
329 330

    access_InitFields( p_access );
331

332
    p_access->p_sys = p_sys = calloc( 1, sizeof( access_sys_t ) );
333 334 335
    if( !p_sys )
        return VLC_ENOMEM;

336 337 338 339 340
    /* Create all variables */
    VarInit( p_access );

    /* Parse the command line */
    if( ParseMRL( p_access ) )
341
    {
342 343
        free( p_sys );
        return VLC_EGENERIC;
344 345
    }

346
    /* Getting frontend info */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
347
    if( FrontendOpen( p_access) )
348
    {
349 350
        free( p_sys );
        return VLC_EGENERIC;
351 352
    }

Laurent Aimar's avatar
Laurent Aimar committed
353 354 355
    /* */
    p_sys->b_scan_mode = var_GetInteger( p_access, "dvb-frequency" ) == 0;
    if( p_sys->b_scan_mode )
356
    {
Laurent Aimar's avatar
Laurent Aimar committed
357 358 359 360 361 362 363 364 365 366 367 368 369
        msg_Dbg( p_access, "DVB scan mode selected" );
        p_access->pf_block = BlockScan;
    }
    else
    {
        /* Setting frontend parameters for tuning the hardware */
        msg_Dbg( p_access, "trying to tune the frontend...");
        if( FrontendSet( p_access ) < 0 )
        {
            FrontendClose( p_access );
            free( p_sys );
            return VLC_EGENERIC;
        }
370 371
    }

372
    /* Opening DVR device */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
373
    if( DVROpen( p_access ) < 0 )
374
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
375
        FrontendClose( p_access );
376 377
        free( p_sys );
        return VLC_EGENERIC;
378 379
    }

Laurent Aimar's avatar
Laurent Aimar committed
380
    if( p_sys->b_scan_mode )
381
    {
Laurent Aimar's avatar
Laurent Aimar committed
382 383 384 385 386 387 388 389 390 391 392 393 394
        scan_parameter_t parameter;

        msg_Dbg( p_access, "setting filter on PAT/NIT/SDT (DVB only)" );
        FilterSet( p_access, 0x00, OTHER_TYPE );    // PAT
        FilterSet( p_access, 0x10, OTHER_TYPE );    // NIT
        FilterSet( p_access, 0x11, OTHER_TYPE );    // SDT

        if( FrontendGetScanParameter( p_access, &parameter ) ||
            scan_Init( VLC_OBJECT(p_access), &p_sys->scan, &parameter ) )
        {
            Close( VLC_OBJECT(p_access) );
            return VLC_EGENERIC;
        }
395
    }
396
    else
397
    {
Laurent Aimar's avatar
Laurent Aimar committed
398 399 400 401 402 403 404 405 406 407 408
        p_sys->b_budget_mode = var_GetBool( p_access, "dvb-budget-mode" );
        if( p_sys->b_budget_mode )
        {
            msg_Dbg( p_access, "setting filter on all PIDs" );
            FilterSet( p_access, 0x2000, OTHER_TYPE );
        }
        else
        {
            msg_Dbg( p_access, "setting filter on PAT" );
            FilterSet( p_access, 0x0, OTHER_TYPE );
        }
409

Laurent Aimar's avatar
Laurent Aimar committed
410
        CAMOpen( p_access );
411

Laurent Aimar's avatar
Laurent Aimar committed
412 413 414 415 416 417 418 419
#ifdef ENABLE_HTTPD
        HTTPOpen( p_access );
#endif
    }

    if( p_sys->b_scan_mode )
        p_sys->i_read_once = DVB_READ_ONCE_SCAN;
    else if( p_sys->b_budget_mode )
420 421 422 423
        p_sys->i_read_once = DVB_READ_ONCE;
    else
        p_sys->i_read_once = DVB_READ_ONCE_START;

424 425
    free( p_access->psz_demux );
    p_access->psz_demux = strdup( p_sys->b_scan_mode ? "m3u8" : "ts" );
426
    return VLC_SUCCESS;
427 428 429 430 431
}

/*****************************************************************************
 * Close : Close the device
 *****************************************************************************/
432
static void Close( vlc_object_t *p_this )
433
{
434 435
    access_t     *p_access = (access_t*)p_this;
    access_sys_t *p_sys = p_access->p_sys;
436

Laurent Aimar's avatar
Laurent Aimar committed
437
    FilterUnset( p_access, p_sys->b_budget_mode && !p_sys->b_scan_mode ? 1 : MAX_DEMUX );
438

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
439 440
    DVRClose( p_access );
    FrontendClose( p_access );
Laurent Aimar's avatar
Laurent Aimar committed
441 442 443 444
    if( p_sys->b_scan_mode )
        scan_Clean( &p_sys->scan );
    else
        CAMClose( p_access );
445

446
#ifdef ENABLE_HTTPD
Laurent Aimar's avatar
Laurent Aimar committed
447 448
    if( !p_sys->b_scan_mode )
        HTTPClose( p_access );
449 450
#endif

451
    free( p_sys );
452 453 454
}

/*****************************************************************************
455
 * Block:
456
 *****************************************************************************/
457
static block_t *Block( access_t *p_access )
458
{
459 460
    access_sys_t *p_sys = p_access->p_sys;
    block_t *p_block;
461

462
    for ( ; ; )
463
    {
464
        struct pollfd ufds[2];
465 466
        int i_ret;

Christophe Massiot's avatar
Christophe Massiot committed
467
        /* Initialize file descriptor sets */
468 469 470 471
        memset (ufds, 0, sizeof (ufds));
        ufds[0].fd = p_sys->i_handle;
        ufds[0].events = POLLIN;
        ufds[1].fd = p_sys->i_frontend_handle;
472
        ufds[1].events = POLLPRI;
473 474 475

        /* We'll wait 0.5 second if nothing happens */
        /* Find if some data is available */
476
        i_ret = poll( ufds, 2, 500 );
477

478
        if ( !vlc_object_alive (p_access) )
479
            return NULL;
480

481 482
        if ( i_ret < 0 )
        {
483 484 485
            if( errno == EINTR )
                continue;

486
            msg_Err( p_access, "poll error: %m" );
487 488 489 490 491
            return NULL;
        }

        if ( p_sys->i_ca_handle && mdate() > p_sys->i_ca_next_event )
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
492
            CAMPoll( p_access );
493 494 495
            p_sys->i_ca_next_event = mdate() + p_sys->i_ca_timeout;
        }

496
        if ( ufds[1].revents )
Christophe Massiot's avatar
Christophe Massiot committed
497
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
498
            FrontendPoll( p_access );
Christophe Massiot's avatar
Christophe Massiot committed
499 500
        }

501 502 503 504 505 506 507
#ifdef ENABLE_HTTPD
        if ( p_sys->i_httpd_timeout && mdate() > p_sys->i_httpd_timeout )
        {
            vlc_mutex_lock( &p_sys->httpd_mutex );
            if ( p_sys->b_request_frontend_info )
            {
                msg_Warn( p_access, "frontend timeout for HTTP interface" );
508
                p_sys->b_request_frontend_info = false;
509 510 511 512 513
                p_sys->psz_frontend_info = strdup( "Timeout getting info\n" );
            }
            if ( p_sys->b_request_mmi_info )
            {
                msg_Warn( p_access, "MMI timeout for HTTP interface" );
514
                p_sys->b_request_mmi_info = false;
515 516 517 518 519 520 521 522
                p_sys->psz_mmi_info = strdup( "Timeout getting info\n" );
            }
            vlc_cond_signal( &p_sys->httpd_cond );
            vlc_mutex_unlock( &p_sys->httpd_mutex );
        }

        if ( p_sys->b_request_frontend_info )
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
523
            FrontendStatus( p_access );
524 525 526 527
        }

        if ( p_sys->b_request_mmi_info )
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
528
            CAMStatus( p_access );
529 530 531
        }
#endif

532 533 534
        if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
        {
            msg_Warn( p_access, "no lock, tuning again" );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
535
            FrontendSet( p_access );
536 537
        }

538
        if ( ufds[0].revents )
539
        {
540 541
            p_block = block_New( p_access,
                                 p_sys->i_read_once * TS_PACKET_SIZE );
542
            if( ( i_ret = read( p_sys->i_handle, p_block->p_buffer,
543 544
                                p_sys->i_read_once * TS_PACKET_SIZE ) ) <= 0 )
            {
545
                msg_Warn( p_access, "read failed (%m)" );
546 547 548
                block_Release( p_block );
                continue;
            }
549
            p_block->i_buffer = i_ret;
550 551
            break;
        }
552 553
    }

554 555 556
    if( p_sys->i_read_once < DVB_READ_ONCE )
        p_sys->i_read_once++;

557 558 559 560
    /* Update moderatly the signal properties */
    if( (p_sys->i_stat_counter++ % 100) == 0 )
        p_access->info.i_update |= INPUT_UPDATE_SIGNAL;

561
    return p_block;
562 563
}

Laurent Aimar's avatar
Laurent Aimar committed
564 565 566 567 568 569 570 571 572 573
/*****************************************************************************
 * BlockScan:
 *****************************************************************************/
static block_t *BlockScan( access_t *p_access )
{
    access_sys_t *p_sys = p_access->p_sys;
    scan_t *p_scan = &p_sys->scan;
    scan_configuration_t cfg;
    scan_session_t session;

David Kaplan's avatar
David Kaplan committed
574 575 576 577
    /* set satellite config file path */
    if( p_scan->parameter.type == SCAN_DVB_S )
        p_scan->parameter.sat_info.psz_name = var_GetString( p_access, "dvb-satellite" );

Laurent Aimar's avatar
Laurent Aimar committed
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
    /* */
    if( scan_Next( p_scan, &cfg ) )
    {
        const bool b_first_eof = !p_access->info.b_eof;

        if( b_first_eof )
            msg_Warn( p_access, "Scanning finished" );

        /* */
        p_access->info.b_eof = true;
        return b_first_eof ? scan_GetM3U( p_scan ) : NULL;
    }

    /* */

    if( scan_session_Init( VLC_OBJECT(p_access), &session, &cfg ) )
        return NULL;

    /* */
David Kaplan's avatar
David Kaplan committed
597 598 599 600 601 602 603 604 605 606 607 608 609
    if( p_scan->parameter.type == SCAN_DVB_S )
    {
        msg_Dbg( p_access,
                 "Scanning frequency %d, symbol rate = %d, fec = %d",
                 cfg.i_frequency,
                 cfg.i_bandwidth,
                 cfg.i_fec );
    }
    else
        msg_Dbg( p_access, "Scanning frequency %d, bandwidth = %d",
                 cfg.i_frequency,
                 cfg.i_bandwidth );

Laurent Aimar's avatar
Laurent Aimar committed
610 611
    var_SetInteger( p_access, "dvb-frequency", cfg.i_frequency );
    var_SetInteger( p_access, "dvb-bandwidth", cfg.i_bandwidth );
David Kaplan's avatar
David Kaplan committed
612 613 614 615
    if ( cfg.i_fec )
        var_SetInteger( p_access, "dvb-fec", cfg.i_fec );
    if ( cfg.c_polarization )
        var_SetInteger( p_access, "dvb-voltage", cfg.c_polarization == 'H' ? 18 : 13 );
Laurent Aimar's avatar
Laurent Aimar committed
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731

    /* Setting frontend parameters for tuning the hardware */
    if( FrontendSet( p_access ) < 0 )
    {
        msg_Err( p_access, "Failed to tune the frontend" );
        p_access->info.b_eof = true;
        return NULL;
    }

    /* */
    int64_t i_scan_start = mdate();

    bool b_has_dvb_signal = false;
    bool b_has_lock = false;
    int i_best_snr = -1;

    for ( ; ; )
    {
        struct pollfd ufds[2];
        int i_ret;

        /* Initialize file descriptor sets */
        memset (ufds, 0, sizeof (ufds));
        ufds[0].fd = p_sys->i_handle;
        ufds[0].events = POLLIN;
        ufds[1].fd = p_sys->i_frontend_handle;
        ufds[1].events = POLLPRI;

        /* We'll wait 0.1 second if nothing happens */
        /* Find if some data is available */
        i_ret = poll( ufds, 2, 100 );

        if( !vlc_object_alive (p_access) || scan_IsCancelled( p_scan ) )
            break;

        if( i_ret <= 0 )
        {
            const mtime_t i_scan_time = mdate() - i_scan_start;
            frontend_status_t status;

            FrontendGetStatus( p_access, &status );

            b_has_dvb_signal |= status.b_has_carrier;
            b_has_lock |= status.b_has_lock;

            if( ( !b_has_dvb_signal && i_scan_time > DVB_SCAN_MAX_SIGNAL_TIME ) ||
                ( !b_has_lock && i_scan_time > DVB_SCAN_MAX_LOCK_TIME ) ||
                ( i_scan_time > DVB_SCAN_MAX_PROBE_TIME ) )
            {
                msg_Dbg( p_access, "timed out scanning current frequency (s=%d l=%d)", b_has_dvb_signal, b_has_lock );
                break;
            }
        }

        if( i_ret < 0 )
        {
            if( errno == EINTR )
                continue;

            msg_Err( p_access, "poll error: %m" );
            scan_session_Clean( p_scan, &session );

            p_access->info.b_eof = true;
            return NULL;
        }

        if( ufds[1].revents )
        {
            frontend_statistic_t stat;

            FrontendPoll( p_access );

            if( !FrontendGetStatistic( p_access, &stat ) )
            {
                if( stat.i_snr > i_best_snr )
                    i_best_snr = stat.i_snr;
            }
        }

        if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
        {
            msg_Warn( p_access, "no lock, tuning again" );
            FrontendSet( p_access );
        }

        if ( ufds[0].revents )
        {
            const int i_read_once = 1;
            block_t *p_block = block_New( p_access, i_read_once * TS_PACKET_SIZE );

            if( ( i_ret = read( p_sys->i_handle, p_block->p_buffer,
                                i_read_once * TS_PACKET_SIZE ) ) <= 0 )
            {
                msg_Warn( p_access, "read failed (%m)" );
                block_Release( p_block );
                continue;
            }
            p_block->i_buffer = i_ret;

            /* */
            if( scan_session_Push( &session, p_block ) )
            {
                msg_Dbg( p_access, "finished scanning current frequency" );
                break;
            }
        }
    }

    /* */
    if( i_best_snr > 0 )
        scan_service_SetSNR( &session, i_best_snr );

    scan_session_Clean( p_scan, &session );
    return NULL;
}

732
/*****************************************************************************
733
 * Control:
734
 *****************************************************************************/
735
static int Control( access_t *p_access, int i_query, va_list args )
736
{
737
    access_sys_t *p_sys = p_access->p_sys;
738
    bool         *pb_bool, b_bool;
739
    int          i_int;
740
    int64_t      *pi_64;
741
    double       *pf1, *pf2;
Laurent Aimar's avatar
Laurent Aimar committed
742
    dvbpsi_pmt_t *p_pmt;
743
    frontend_statistic_t stat;
744

745
    switch( i_query )
746
    {
747 748 749 750 751
        /* */
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
752 753
            pb_bool = (bool*)va_arg( args, bool* );
            *pb_bool = false;
754 755 756 757
            break;
        /* */
        case ACCESS_GET_PTS_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
758
            *pi_64 = var_GetInteger( p_access, "dvb-caching" ) * 1000;
759
            break;
760 761 762 763 764 765

        /* */
        case ACCESS_SET_PAUSE_STATE:
        case ACCESS_GET_TITLE_INFO:
        case ACCESS_SET_TITLE:
        case ACCESS_SET_SEEKPOINT:
766
        case ACCESS_GET_CONTENT_TYPE:
767 768
            return VLC_EGENERIC;

769 770 771 772 773 774 775 776 777 778 779 780
        case ACCESS_GET_SIGNAL:
            pf1 = (double*)va_arg( args, double * );
            pf2 = (double*)va_arg( args, double * );

            *pf1 = *pf2 = 0;
            if( !FrontendGetStatistic( p_access, &stat ) )
            {
                *pf1 = (double)stat.i_snr / 65535.0;
                *pf2 = (double)stat.i_signal_strenth / 65535.0;
            }
            return VLC_SUCCESS;

781
        case ACCESS_SET_PRIVATE_ID_STATE:
Laurent Aimar's avatar
Laurent Aimar committed
782 783 784
            if( p_sys->b_scan_mode )
                return VLC_EGENERIC;

785
            i_int  = (int)va_arg( args, int );               /* Private data (pid for now)*/
786
            b_bool = (bool)va_arg( args, int ); /* b_selected */
787
            if( !p_sys->b_budget_mode )
788
            {
789 790 791 792
                /* FIXME we may want to give the real type (me ?, I don't ;) */
                if( b_bool )
                    FilterSet( p_access, i_int, OTHER_TYPE );
                else
Laurent Aimar's avatar
Laurent Aimar committed
793
                    FilterUnsetPID( p_access, i_int );
794 795
            }
            break;
796

797
        case ACCESS_SET_PRIVATE_ID_CA:
Laurent Aimar's avatar
Laurent Aimar committed
798 799
            if( p_sys->b_scan_mode )
                return VLC_EGENERIC;
800

Christophe Massiot's avatar
Christophe Massiot committed
801
            p_pmt = (dvbpsi_pmt_t *)va_arg( args, dvbpsi_pmt_t * );
802

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
803
            CAMSet( p_access, p_pmt );
804
            break;
Christophe Massiot's avatar
Christophe Massiot committed
805

806
        default:
807
            msg_Warn( p_access, "unimplemented query in control" );
808
            return VLC_EGENERIC;
809

810 811
    }
    return VLC_SUCCESS;
812 813 814
}

/*****************************************************************************
815
 * FilterSet/FilterUnset:
816
 *****************************************************************************/
817
static void FilterSet( access_t *p_access, int i_pid, int i_type )
818
{
819 820 821 822 823 824 825 826
    access_sys_t *p_sys = p_access->p_sys;
    int i;

    /* Find first free slot */
    for( i = 0; i < MAX_DEMUX; i++ )
    {
        if( !p_sys->p_demux_handles[i].i_type )
            break;
Laurent Aimar's avatar
Laurent Aimar committed
827 828 829

        if( p_sys->p_demux_handles[i].i_pid == i_pid )
            return; /* Already set */
830 831 832 833 834 835 836 837
    }

    if( i >= MAX_DEMUX )
    {
        msg_Err( p_access, "no free p_demux_handles !" );
        return;
    }

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
838
    if( DMXSetFilter( p_access, i_pid,
839 840 841 842 843 844 845
                           &p_sys->p_demux_handles[i].i_handle, i_type ) )
    {
        msg_Err( p_access, "DMXSetFilter failed" );
        return;
    }
    p_sys->p_demux_handles[i].i_type = i_type;
    p_sys->p_demux_handles[i].i_pid = i_pid;
846 847 848

    if( p_sys->i_read_once < DVB_READ_ONCE )
        p_sys->i_read_once++;
849 850
}

Laurent Aimar's avatar
Laurent Aimar committed
851
static void FilterUnset( access_t *p_access, int i_max )
852
{
853 854
    access_sys_t *p_sys = p_access->p_sys;
    int i;
855

Laurent Aimar's avatar
Laurent Aimar committed
856
    for( i = 0; i < i_max; i++ )
857
    {
858
        if( p_sys->p_demux_handles[i].i_type )
859
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
860
            DMXUnsetFilter( p_access, p_sys->p_demux_handles[i].i_handle );
861
            p_sys->p_demux_handles[i].i_type = 0;
862 863 864 865
        }
    }
}

Laurent Aimar's avatar
Laurent Aimar committed
866 867 868 869 870 871 872 873 874 875
static void FilterUnsetPID( access_t *p_access, int i_pid )
{
    access_sys_t *p_sys = p_access->p_sys;
    int i;

    for( i = 0; i < MAX_DEMUX; i++ )
    {
        if( p_sys->p_demux_handles[i].i_type &&
            p_sys->p_demux_handles[i].i_pid == i_pid )
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
876
            DMXUnsetFilter( p_access, p_sys->p_demux_handles[i].i_handle );
Laurent Aimar's avatar
Laurent Aimar committed
877 878 879 880 881
            p_sys->p_demux_handles[i].i_type = 0;
        }
    }
}

882
/*****************************************************************************
883
 * VarInit/ParseMRL:
884
 *****************************************************************************/
885
static void VarInit( access_t *p_access )
886
{
887
    /* */
888
    var_Create( p_access, "dvb-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
889 890

    /* */
891 892 893 894 895
    var_Create( p_access, "dvb-adapter", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-device", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-frequency", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-inversion", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-probe", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
896
    var_Create( p_access, "dvb-budget-mode", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
897 898

    /* */
David Kaplan's avatar
David Kaplan committed
899
    var_Create( p_access, "dvb-satellite", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
900 901
    var_Create( p_access, "dvb-satno", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-voltage", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
Christophe Massiot's avatar
Christophe Massiot committed
902
    var_Create( p_access, "dvb-high-voltage", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
903 904 905
    var_Create( p_access, "dvb-tone", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-fec", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-srate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
906 907 908
    var_Create( p_access, "dvb-lnb-lof1", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-lnb-lof2", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-lnb-slof", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
909 910

    /* */
911
    var_Create( p_access, "dvb-modulation", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
912 913

    /* */
914 915 916 917 918 919
    var_Create( p_access, "dvb-code-rate-hp", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-code-rate-lp", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-bandwidth", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-transmission", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-guard", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-hierarchy", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
920 921 922 923 924 925 926 927 928 929 930

#ifdef ENABLE_HTTPD
    var_Create( p_access, "dvb-http-host", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-user", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-password", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-acl", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-intf-cert", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-intf-key", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-intf-ca", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Create( p_access, "dvb-http-intf-crl", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
#endif
931 932 933 934 935
}

/* */
static int ParseMRL( access_t *p_access )
{
936
    char *psz_dup = strdup( p_access->psz_location );
937 938 939 940 941 942 943
    char *psz_parser = psz_dup;
    char *psz_next;
    vlc_value_t         val;

#define GET_OPTION_INT( option )                                            \
    if ( !strncmp( psz_parser, option "=", strlen(option "=") ) )           \
    {                                                                       \
944 945 946
        val.i_int = strtol( psz_parser + strlen(option "="), &psz_parser,   \
                            0 );                                            \
        var_Set( p_access, "dvb-" option, val );                            \
947 948 949 950 951 952 953
    }

#define GET_OPTION_BOOL( option )                                           \
    if ( !strncmp( psz_parser, option "=", strlen(option "=") ) )           \
    {                                                                       \
        val.b_bool = strtol( psz_parser + strlen(option "="), &psz_parser,  \
                             0 );                                           \
954
        var_Set( p_access, "dvb-" option, val );                            \
955
    }
956

David Kaplan's avatar
David Kaplan committed
957 958 959 960 961 962 963 964 965 966 967 968
#define GET_OPTION_STRING( option )                                         \
    if ( !strncmp( psz_parser, option "=", strlen( option "=" ) ) )         \
    {                                                                       \
        psz_parser += strlen( option "=" );                                 \
        val.psz_string = psz_parser;                                        \
        char *p_save;                                                       \
        char *tok = strtok_r(val.psz_string, ":", &p_save);                 \
        val.psz_string[tok - val.psz_string - 1] = 0;                       \
        var_Set( p_access, "dvb-" option, val );                            \
        psz_parser += strlen( val.psz_string );                             \
    }

969 970 971
    /* Test for old syntax */
    strtol( psz_parser, &psz_next, 10 );
    if( psz_next != psz_parser )
972
    {
973 974
        msg_Err( p_access, "the DVB input old syntax is deprecated, use vlc "
                          "-p dvb to see an explanation of the new syntax" );
975
        dialog_FatalWait( p_access, _("Input syntax is deprecated"), "%s",
976 977
            _("The given syntax is deprecated. Run \"vlc -p dvb\" to see an " \
                "explanation of the new syntax.") );
978 979 980 981 982 983 984 985 986 987 988 989
        free( psz_dup );
        return VLC_EGENERIC;
    }

    while( *psz_parser )
    {
        GET_OPTION_INT("adapter")
        else GET_OPTION_INT("device")
        else GET_OPTION_INT("frequency")
        else GET_OPTION_INT("inversion")
        else GET_OPTION_BOOL("probe")
        else GET_OPTION_BOOL("budget-mode")
990

David Kaplan's avatar
David Kaplan committed
991
        else GET_OPTION_STRING("satellite")
992
        else GET_OPTION_INT("voltage")
Christophe Massiot's avatar
Christophe Massiot committed
993
        else GET_OPTION_BOOL("high-voltage")
994
        else GET_OPTION_INT("tone")
Christophe Massiot's avatar
Christophe Massiot committed
995
        else GET_OPTION_INT("satno")
996 997
        else GET_OPTION_INT("fec")
        else GET_OPTION_INT("srate")
998 999 1000
        else GET_OPTION_INT("lnb-lof1")
        else GET_OPTION_INT("lnb-lof2")
        else GET_OPTION_INT("lnb-slof")
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022

        else GET_OPTION_INT("modulation")

        else GET_OPTION_INT("code-rate-hp")
        else GET_OPTION_INT("code-rate-lp")
        else GET_OPTION_INT("bandwidth")
        else GET_OPTION_INT("transmission")
        else GET_OPTION_INT("guard")
        else GET_OPTION_INT("hierarchy")

        /* Redundant with voltage but much easier to use */
        else if( !strncmp( psz_parser, "polarization=",
                           strlen( "polarization=" ) ) )
        {
            psz_parser += strlen( "polarization=" );
            if ( *psz_parser == 'V' || *psz_parser == 'v' )
                val.i_int = 13;
            else if ( *psz_parser == 'H' || *psz_parser == 'h' )
                val.i_int = 18;
            else
            {
                msg_Err( p_access, "illegal polarization %c", *psz_parser );
1023
                dialog_Fatal( p_access, _("Invalid polarization"),
1024 1025
                                _("The provided polarization \"%c\" is not valid."),
                                *psz_parser );
1026 1027 1028 1029 1030 1031
                free( psz_dup );
                return VLC_EGENERIC;
            }
            var_Set( p_access, "dvb-voltage", val );
        }
        else
1032
        {
1033
            msg_Err( p_access, "unknown option (%s)", psz_parser );
1034 1035
            free( psz_dup );
            return VLC_EGENERIC;
1036
        }
1037

1038 1039
        if ( *psz_parser )
            psz_parser++;
1040
    }
1041 1042
#undef GET_OPTION_INT
#undef GET_OPTION_BOOL
David Kaplan's avatar
David Kaplan committed
1043
#undef GET_OPTION_STRING
1044

1045 1046 1047
    free( psz_dup );
    return VLC_SUCCESS;
}
1048