access.c 26.6 KB
Newer Older
1 2 3
/*****************************************************************************
 * access.c: DVB card input v4l2 only
 *****************************************************************************
4
 * Copyright (C) 1998-2005 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>
10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/input.h>

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

#include <fcntl.h>
#include <sys/types.h>
39

40
#include <errno.h>
41

Christophe Massiot's avatar
Christophe Massiot committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
/* 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>
#else
#   include "dvbpsi.h"
#   include "descriptor.h"
#   include "tables/pat.h"
#   include "tables/pmt.h"
#   include "descriptors/dr.h"
#   include "psi.h"
#endif

59 60 61 62
#ifdef ENABLE_HTTPD
#   include "vlc_httpd.h"
#endif

63 64
#include "dvb.h"

65 66 67
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
68 69 70
static int  Open( vlc_object_t *p_this );
static void Close( vlc_object_t *p_this );

71 72 73 74 75
#define CACHING_TEXT N_("Caching value in ms")
#define CACHING_LONGTEXT N_( \
    "Allows you to modify the default caching value for dvb streams. This " \
    "value should be set in millisecond units." )

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#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")
#define PROBE_LONGTEXT N_("Some DVB cards do not like to be probed for their capabilities.")

#define BUDGET_TEXT N_("Budget mode")
92
#define BUDGET_LONGTEXT N_("This allows you to stream an entire transponder with a budget card.")
93

94
/* Satellite */
95
#define SATNO_TEXT N_("Satellite number in the Diseqc system")
Christophe Massiot's avatar
Christophe Massiot committed
96
#define SATNO_LONGTEXT N_("[0=no diseqc, 1-4=satellite number]")
97 98 99 100

#define VOLTAGE_TEXT N_("LNB voltage")
#define VOLTAGE_LONGTEXT N_("In Volts [0, 13=vertical, 18=horizontal]")

Christophe Massiot's avatar
Christophe Massiot committed
101 102 103 104
#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.")

105 106 107 108 109 110 111 112 113
#define TONE_TEXT N_("22 kHz tone")
#define TONE_LONGTEXT N_("[0=off, 1=on, -1=auto]")

#define FEC_TEXT N_("Transponder FEC")
#define FEC_LONGTEXT N_("FEC=Forward Error Correction mode [9=auto]")

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

114 115 116 117 118 119 120 121 122
#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 ""

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
/* 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 ""

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
#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_( \
    "You can set the user name the administrator will use to log into " \
    "the internal HTTP server." )

#define PASSWORD_TEXT N_( "HTTP password" )
#define PASSWORD_LONGTEXT N_( \
    "You can set the password the administrator will use to log into " \
    "the internal HTTP server." )

#define ACL_TEXT N_( "HTTP ACL" )
#define ACL_LONGTEXT N_( \
    "You can set the access control list (equivalent to .hosts) file path, " \
    "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" )

180
vlc_module_begin();
181
    set_shortname( _("DVB") );
182
    set_description( N_("DVB input with v4l2 support") );
Clément Stenac's avatar
Clément Stenac committed
183 184
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_ACCESS );
185

186 187
    add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
                 CACHING_LONGTEXT, VLC_TRUE );
188 189 190
    add_integer( "dvb-adapter", 0, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT,
                 VLC_FALSE );
    add_integer( "dvb-device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
191
                 VLC_TRUE );
192 193 194 195 196 197
    add_integer( "dvb-frequency", 11954000, NULL, FREQ_TEXT, FREQ_LONGTEXT,
                 VLC_FALSE );
    add_integer( "dvb-inversion", 2, NULL, INVERSION_TEXT, INVERSION_LONGTEXT,
                 VLC_TRUE );
    add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, VLC_TRUE );
    add_bool( "dvb-budget-mode", 0, NULL, BUDGET_TEXT, BUDGET_LONGTEXT,
198
              VLC_TRUE );
199
    /* DVB-S (satellite) */
200 201 202
    add_integer( "dvb-satno", 0, NULL, SATNO_TEXT, SATNO_LONGTEXT,
                 VLC_TRUE );
    add_integer( "dvb-voltage", 13, NULL, VOLTAGE_TEXT, VOLTAGE_LONGTEXT,
203
                 VLC_TRUE );
Christophe Massiot's avatar
Christophe Massiot committed
204 205
    add_bool( "dvb-high-voltage", 0, NULL, HIGH_VOLTAGE_TEXT,
              HIGH_VOLTAGE_LONGTEXT, VLC_TRUE );
206
    add_integer( "dvb-tone", -1, NULL, TONE_TEXT, TONE_LONGTEXT,
207
                 VLC_TRUE );
208 209 210
    add_integer( "dvb-fec", 9, NULL, FEC_TEXT, FEC_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-srate", 27500000, NULL, SRATE_TEXT, SRATE_LONGTEXT,
                 VLC_FALSE );
211 212 213 214 215 216 217
    add_integer( "dvb-lnb-lof1", 0, NULL, LNB_LOF1_TEXT,
                 LNB_LOF1_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-lnb-lof2", 0, NULL, LNB_LOF2_TEXT,
                 LNB_LOF2_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-lnb-slof", 0, NULL, LNB_SLOF_TEXT,
                 LNB_SLOF_LONGTEXT, VLC_TRUE );
    /* DVB-C (cable) */
218 219
    add_integer( "dvb-modulation", 0, NULL, MODULATION_TEXT,
                 MODULATION_LONGTEXT, VLC_TRUE );
220 221 222 223 224 225 226 227 228 229 230 231
    /* DVB-T (terrestrial) */
    add_integer( "dvb-code-rate-hp", 9, NULL, CODE_RATE_HP_TEXT,
                 CODE_RATE_HP_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-code-rate-lp", 9, NULL, CODE_RATE_LP_TEXT,
                 CODE_RATE_LP_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-bandwidth", 0, NULL, BANDWIDTH_TEXT, BANDWIDTH_LONGTEXT,
                 VLC_TRUE );
    add_integer( "dvb-guard", 0, NULL, GUARD_TEXT, GUARD_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-transmission", 0, NULL, TRANSMISSION_TEXT,
                 TRANSMISSION_LONGTEXT, VLC_TRUE );
    add_integer( "dvb-hierarchy", 0, NULL, HIERARCHY_TEXT, HIERARCHY_LONGTEXT,
                 VLC_TRUE );
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
#ifdef ENABLE_HTTPD
    /* MMI HTTP interface */
    set_section( N_("HTTP server" ), 0 );
    add_string( "dvb-http-host", NULL, NULL, HOST_TEXT, HOST_LONGTEXT,
                VLC_TRUE );
    add_string( "dvb-http-user", NULL, NULL, USER_TEXT, USER_LONGTEXT,
                VLC_TRUE );
    add_string( "dvb-http-password", NULL, NULL, PASSWORD_TEXT,
                PASSWORD_LONGTEXT, VLC_TRUE );
    add_string( "dvb-http-acl", NULL, NULL, ACL_TEXT, ACL_LONGTEXT,
                VLC_TRUE );
    add_string( "dvb-http-intf-cert", NULL, NULL, CERT_TEXT, CERT_LONGTEXT,
                VLC_TRUE );
    add_string( "dvb-http-intf-key",  NULL, NULL, KEY_TEXT,  KEY_LONGTEXT,
                VLC_TRUE );
    add_string( "dvb-http-intf-ca",   NULL, NULL, CA_TEXT,   CA_LONGTEXT,
                VLC_TRUE );
    add_string( "dvb-http-intf-crl",  NULL, NULL, CRL_TEXT,  CRL_LONGTEXT,
                VLC_TRUE );
#endif
252

Clément Stenac's avatar
Clément Stenac committed
253
    set_capability( "access2", 0 );
254 255 256 257 258 259 260 261 262 263
    add_shortcut( "dvb" );
    add_shortcut( "dvb-s" );
    add_shortcut( "qpsk" );
    add_shortcut( "dvb-c" );
    add_shortcut( "cable" );
    add_shortcut( "dvb-t" );
    add_shortcut( "terrestrial" );
    add_shortcut( "satellite" );    /* compatibility with the interface. */
    set_callbacks( Open, Close );
vlc_module_end();
264

265

266
/*****************************************************************************
267
 * Local prototypes
268
 *****************************************************************************/
269 270
static block_t *Block( access_t * );
static int Control( access_t *, int, va_list );
271

272 273
#define DVB_READ_ONCE 20
#define DVB_READ_ONCE_START 2
274
#define TS_PACKET_SIZE 188
275

Laurent Aimar's avatar
Laurent Aimar committed
276 277
static void FilterUnset( access_t *, int i_max );
static void FilterUnsetPID( access_t *, int i_pid );
278
static void FilterSet( access_t *, int i_pid, int i_type );
279

280 281
static void VarInit( access_t * );
static int  ParseMRL( access_t * );
282 283


284 285 286 287 288 289 290 291 292
/*****************************************************************************
 * 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 */
293
    if( *p_access->psz_access == '\0' )
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
        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;
    p_access->info.i_update = 0;
    p_access->info.i_size = 0;
    p_access->info.i_pos = 0;
    p_access->info.b_eof = VLC_FALSE;
    p_access->info.i_title = 0;
    p_access->info.i_seekpoint = 0;

    p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
    memset( p_sys, 0, sizeof( access_sys_t ) );

    /* Create all variables */
    VarInit( p_access );

    /* Parse the command line */
    if( ParseMRL( p_access ) )
316
    {
317 318
        free( p_sys );
        return VLC_EGENERIC;
319 320
    }

321
    /* Getting frontend info */
322
    if( E_(FrontendOpen)( p_access) )
323
    {
324 325
        free( p_sys );
        return VLC_EGENERIC;
326 327
    }

328 329 330
    /* Setting frontend parameters for tuning the hardware */
    msg_Dbg( p_access, "trying to tune the frontend...");
    if( E_(FrontendSet)( p_access ) < 0 )
331
    {
332 333 334
        E_(FrontendClose)( p_access );
        free( p_sys );
        return VLC_EGENERIC;
335 336
    }

337 338
    /* Opening DVR device */
    if( E_(DVROpen)( p_access ) < 0 )
339
    {
340 341 342
        E_(FrontendClose)( p_access );
        free( p_sys );
        return VLC_EGENERIC;
343 344
    }

345 346
    p_sys->b_budget_mode = var_GetBool( p_access, "dvb-budget-mode" );
    if( p_sys->b_budget_mode )
347
    {
348
        msg_Dbg( p_access, "setting filter on all PIDs" );
349
        FilterSet( p_access, 0x2000, OTHER_TYPE );
350
    }
351
    else
352
    {
353
        msg_Dbg( p_access, "setting filter on PAT" );
354
        FilterSet( p_access, 0x0, OTHER_TYPE );
355 356
    }

357
    E_(CAMOpen)( p_access );
358

359 360 361 362 363
    if( p_sys->b_budget_mode )
        p_sys->i_read_once = DVB_READ_ONCE;
    else
        p_sys->i_read_once = DVB_READ_ONCE_START;

364 365 366 367
#ifdef ENABLE_HTTPD
    E_(HTTPOpen)( p_access );
#endif

368
    return VLC_SUCCESS;
369 370 371 372 373
}

/*****************************************************************************
 * Close : Close the device
 *****************************************************************************/
374
static void Close( vlc_object_t *p_this )
375
{
376 377
    access_t     *p_access = (access_t*)p_this;
    access_sys_t *p_sys = p_access->p_sys;
378

Laurent Aimar's avatar
Laurent Aimar committed
379
    FilterUnset( p_access, p_sys->b_budget_mode ? 1 : MAX_DEMUX );
380 381 382

    E_(DVRClose)( p_access );
    E_(FrontendClose)( p_access );
383
    E_(CAMClose)( p_access );
384

385 386 387 388
#ifdef ENABLE_HTTPD
    E_(HTTPClose)( p_access );
#endif

389
    free( p_sys );
390 391 392
}

/*****************************************************************************
393
 * Block:
394
 *****************************************************************************/
395
static block_t *Block( access_t *p_access )
396
{
397 398
    access_sys_t *p_sys = p_access->p_sys;
    block_t *p_block;
399

400
    for ( ; ; )
401
    {
402
        struct timeval timeout;
Christophe Massiot's avatar
Christophe Massiot committed
403
        fd_set fds, fde;
404
        int i_ret;
Christophe Massiot's avatar
Christophe Massiot committed
405
        int i_max_handle = p_sys->i_handle;
406

Christophe Massiot's avatar
Christophe Massiot committed
407
        /* Initialize file descriptor sets */
408
        FD_ZERO( &fds );
Christophe Massiot's avatar
Christophe Massiot committed
409
        FD_ZERO( &fde );
410
        FD_SET( p_sys->i_handle, &fds );
Christophe Massiot's avatar
Christophe Massiot committed
411 412 413
        FD_SET( p_sys->i_frontend_handle, &fde );
        if ( p_sys->i_frontend_handle > i_max_handle )
            i_max_handle = p_sys->i_frontend_handle;
414 415

        /* We'll wait 0.5 second if nothing happens */
416 417 418
        timeout.tv_sec = 0;
        timeout.tv_usec = 500000;

419
        /* Find if some data is available */
Christophe Massiot's avatar
Christophe Massiot committed
420
        i_ret = select( i_max_handle + 1, &fds, NULL, &fde, &timeout );
421 422

        if ( p_access->b_die )
423
            return NULL;
424

425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
        if ( i_ret < 0 && errno == EINTR )
            continue;

        if ( i_ret < 0 )
        {
            msg_Err( p_access, "select error (%s)", strerror(errno) );
            return NULL;
        }

        if ( p_sys->i_ca_handle && mdate() > p_sys->i_ca_next_event )
        {
            E_(CAMPoll)( p_access );
            p_sys->i_ca_next_event = mdate() + p_sys->i_ca_timeout;
        }

Christophe Massiot's avatar
Christophe Massiot committed
440 441 442 443 444
        if ( FD_ISSET( p_sys->i_frontend_handle, &fde ) )
        {
            E_(FrontendPoll)( p_access );
        }

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
#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" );
                p_sys->b_request_frontend_info = VLC_FALSE;
                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" );
                p_sys->b_request_mmi_info = VLC_FALSE;
                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 )
        {
            E_(FrontendStatus)( p_access );
        }

        if ( p_sys->b_request_mmi_info )
        {
            E_(CAMStatus)( p_access );
        }
#endif

476 477 478 479 480 481
        if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
        {
            msg_Warn( p_access, "no lock, tuning again" );
            E_(FrontendSet)( p_access );
        }

482 483
        if ( FD_ISSET( p_sys->i_handle, &fds ) )
        {
484 485 486 487 488 489 490 491 492
            p_block = block_New( p_access,
                                 p_sys->i_read_once * TS_PACKET_SIZE );
            if( ( p_block->i_buffer = read( p_sys->i_handle, p_block->p_buffer,
                                p_sys->i_read_once * TS_PACKET_SIZE ) ) <= 0 )
            {
                msg_Warn( p_access, "read failed (%s)", strerror(errno) );
                block_Release( p_block );
                continue;
            }
493 494
            break;
        }
495 496
    }

497 498 499
    if( p_sys->i_read_once < DVB_READ_ONCE )
        p_sys->i_read_once++;

500
    return p_block;
501 502 503
}

/*****************************************************************************
504
 * Control:
505
 *****************************************************************************/
506
static int Control( access_t *p_access, int i_query, va_list args )
507
{
508 509 510 511
    access_sys_t *p_sys = p_access->p_sys;
    vlc_bool_t   *pb_bool, b_bool;
    int          *pi_int, i_int;
    int64_t      *pi_64;
512

513
    switch( i_query )
514
    {
515 516 517 518 519 520 521 522 523 524 525
        /* */
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = VLC_FALSE;
            break;
        /* */
        case ACCESS_GET_MTU:
            pi_int = (int*)va_arg( args, int * );
526
            *pi_int = DVB_READ_ONCE * TS_PACKET_SIZE;
527 528
            break;

529 530 531
        case ACCESS_GET_PTS_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
            *pi_64 = var_GetInteger( p_access, "dvb-caching" ) * 1000;
532
            break;
533 534 535 536 537 538 539 540 541 542

        /* */
        case ACCESS_SET_PAUSE_STATE:
        case ACCESS_GET_TITLE_INFO:
        case ACCESS_SET_TITLE:
        case ACCESS_SET_SEEKPOINT:
            return VLC_EGENERIC;

        case ACCESS_SET_PRIVATE_ID_STATE:
            i_int  = (int)va_arg( args, int );               /* Private data (pid for now)*/
543
            b_bool = (vlc_bool_t)va_arg( args, vlc_bool_t ); /* b_selected */
544
            if( !p_sys->b_budget_mode )
545
            {
546 547 548 549
                /* 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
550
                    FilterUnsetPID( p_access, i_int );
551 552
            }
            break;
553

554
        case ACCESS_SET_PRIVATE_ID_CA:
555
        {
Christophe Massiot's avatar
Christophe Massiot committed
556
            dvbpsi_pmt_t *p_pmt;
557

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

Christophe Massiot's avatar
Christophe Massiot committed
560
            E_(CAMSet)( p_access, p_pmt );
561 562
            break;
        }
Christophe Massiot's avatar
Christophe Massiot committed
563

564
        default:
565
            msg_Warn( p_access, "unimplemented query in control" );
566
            return VLC_EGENERIC;
567

568 569
    }
    return VLC_SUCCESS;
570 571 572
}

/*****************************************************************************
573
 * FilterSet/FilterUnset:
574
 *****************************************************************************/
575
static void FilterSet( access_t *p_access, int i_pid, int i_type )
576
{
577 578 579 580 581 582 583 584
    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
585 586 587

        if( p_sys->p_demux_handles[i].i_pid == i_pid )
            return; /* Already set */
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
    }

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

    if( E_(DMXSetFilter)( p_access, i_pid,
                           &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;
604 605 606

    if( p_sys->i_read_once < DVB_READ_ONCE )
        p_sys->i_read_once++;
607 608
}

Laurent Aimar's avatar
Laurent Aimar committed
609
static void FilterUnset( access_t *p_access, int i_max )
610
{
611 612
    access_sys_t *p_sys = p_access->p_sys;
    int i;
613

Laurent Aimar's avatar
Laurent Aimar committed
614
    for( i = 0; i < i_max; i++ )
615
    {
616
        if( p_sys->p_demux_handles[i].i_type )
617
        {
618 619
            E_(DMXUnsetFilter)( p_access, p_sys->p_demux_handles[i].i_handle );
            p_sys->p_demux_handles[i].i_type = 0;
620 621 622 623
        }
    }
}

Laurent Aimar's avatar
Laurent Aimar committed
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
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 )
        {
            E_(DMXUnsetFilter)( p_access, p_sys->p_demux_handles[i].i_handle );
            p_sys->p_demux_handles[i].i_type = 0;
        }
    }
}

640
/*****************************************************************************
641
 * VarInit/ParseMRL:
642
 *****************************************************************************/
643
static void VarInit( access_t *p_access )
644
{
645
    /* */
646
    var_Create( p_access, "dvb-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
647 648

    /* */
649 650 651 652 653
    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 );
654
    var_Create( p_access, "dvb-budget-mode", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
655 656

    /* */
657 658
    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
659
    var_Create( p_access, "dvb-high-voltage", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
660 661 662
    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 );
663 664 665
    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 );
666 667

    /* */
668
    var_Create( p_access, "dvb-modulation", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
669 670

    /* */
671 672 673 674 675 676
    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 );
677 678 679 680 681 682 683 684 685 686 687

#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
688 689 690 691 692
}

/* */
static int ParseMRL( access_t *p_access )
{
693
    char *psz_dup = strdup( p_access->psz_path );
694 695 696 697 698 699 700
    char *psz_parser = psz_dup;
    char *psz_next;
    vlc_value_t         val;

#define GET_OPTION_INT( option )                                            \
    if ( !strncmp( psz_parser, option "=", strlen(option "=") ) )           \
    {                                                                       \
701 702 703
        val.i_int = strtol( psz_parser + strlen(option "="), &psz_parser,   \
                            0 );                                            \
        var_Set( p_access, "dvb-" option, val );                            \
704 705 706 707 708 709 710
    }

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

714 715 716
    /* Test for old syntax */
    strtol( psz_parser, &psz_next, 10 );
    if( psz_next != psz_parser )
717
    {
718 719 720 721 722 723 724 725 726 727 728 729 730 731
        msg_Err( p_access, "the DVB input old syntax is deprecated, use vlc "
                          "-p dvb to see an explanation of the new syntax" );
        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")
732

733
        else GET_OPTION_INT("voltage")
Christophe Massiot's avatar
Christophe Massiot committed
734
        else GET_OPTION_BOOL("high-voltage")
735
        else GET_OPTION_INT("tone")
Christophe Massiot's avatar
Christophe Massiot committed
736
        else GET_OPTION_INT("satno")
737 738
        else GET_OPTION_INT("fec")
        else GET_OPTION_INT("srate")
739 740 741
        else GET_OPTION_INT("lnb-lof1")
        else GET_OPTION_INT("lnb-lof2")
        else GET_OPTION_INT("lnb-slof")
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769

        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 );
                free( psz_dup );
                return VLC_EGENERIC;
            }
            var_Set( p_access, "dvb-voltage", val );
        }
        else
770
        {
771
            msg_Err( p_access, "unknown option (%s)", psz_parser );
772 773
            free( psz_dup );
            return VLC_EGENERIC;
774
        }
775

776 777
        if ( *psz_parser )
            psz_parser++;
778
    }
779 780
#undef GET_OPTION_INT
#undef GET_OPTION_BOOL
781

782 783 784
    free( psz_dup );
    return VLC_SUCCESS;
}
785