access.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:33k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * access.c: DVB card input v4l2 only
  3.  *****************************************************************************
  4.  * Copyright (C) 1998-2005 the VideoLAN team
  5.  *
  6.  * Authors: Johan Bilien <jobi@via.ecp.fr>
  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.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  *****************************************************************************/
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_access.h>
  34. #include <vlc_input.h>
  35. #include <vlc_interface.h>
  36. #include <vlc_dialog.h>
  37. #ifdef HAVE_UNISTD_H
  38. #   include <unistd.h>
  39. #endif
  40. #include <fcntl.h>
  41. #include <sys/types.h>
  42. #include <sys/poll.h>
  43. #include <errno.h>
  44. /* Include dvbpsi headers */
  45. #ifdef HAVE_DVBPSI_DR_H
  46. #   include <dvbpsi/dvbpsi.h>
  47. #   include <dvbpsi/descriptor.h>
  48. #   include <dvbpsi/pat.h>
  49. #   include <dvbpsi/pmt.h>
  50. #   include <dvbpsi/dr.h>
  51. #   include <dvbpsi/psi.h>
  52. #   include <dvbpsi/demux.h>
  53. #   include <dvbpsi/sdt.h>
  54. #else
  55. #   include "dvbpsi.h"
  56. #   include "descriptor.h"
  57. #   include "tables/pat.h"
  58. #   include "tables/pmt.h"
  59. #   include "descriptors/dr.h"
  60. #   include "psi.h"
  61. #   include "demux.h"
  62. #   include "tables/sdt.h"
  63. #endif
  64. #ifdef ENABLE_HTTPD
  65. #   include "vlc_httpd.h"
  66. #endif
  67. #include "dvb.h"
  68. /*****************************************************************************
  69.  * Module descriptor
  70.  *****************************************************************************/
  71. static int  Open( vlc_object_t *p_this );
  72. static void Close( vlc_object_t *p_this );
  73. #define CACHING_TEXT N_("Caching value in ms")
  74. #define CACHING_LONGTEXT N_( 
  75.     "Caching value for DVB streams. This " 
  76.     "value should be set in milliseconds." )
  77. #define ADAPTER_TEXT N_("Adapter card to tune")
  78. #define ADAPTER_LONGTEXT N_("Adapter cards have a device file in directory named /dev/dvb/adapter[n] with n>=0.")
  79. #define DEVICE_TEXT N_("Device number to use on adapter")
  80. #define DEVICE_LONGTEXT ""
  81. #define FREQ_TEXT N_("Transponder/multiplex frequency")
  82. #define FREQ_LONGTEXT N_("In kHz for DVB-S or Hz for DVB-C/T")
  83. #define INVERSION_TEXT N_("Inversion mode")
  84. #define INVERSION_LONGTEXT N_("Inversion mode [0=off, 1=on, 2=auto]")
  85. #define PROBE_TEXT N_("Probe DVB card for capabilities")
  86. #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.")
  87. #define BUDGET_TEXT N_("Budget mode")
  88. #define BUDGET_LONGTEXT N_("This allows you to stream an entire transponder with a "budget" card.")
  89. /* Satellite */
  90. #define SATNO_TEXT N_("Satellite number in the Diseqc system")
  91. #define SATNO_LONGTEXT N_("[0=no diseqc, 1-4=satellite number].")
  92. #define VOLTAGE_TEXT N_("LNB voltage")
  93. #define VOLTAGE_LONGTEXT N_("In Volts [0, 13=vertical, 18=horizontal].")
  94. #define HIGH_VOLTAGE_TEXT N_("High LNB voltage")
  95. #define HIGH_VOLTAGE_LONGTEXT N_("Enable high voltage if your cables are " 
  96.     "particularly long. This is not supported by all frontends.")
  97. #define TONE_TEXT N_("22 kHz tone")
  98. #define TONE_LONGTEXT N_("[0=off, 1=on, -1=auto].")
  99. #define FEC_TEXT N_("Transponder FEC")
  100. #define FEC_LONGTEXT N_("FEC=Forward Error Correction mode [9=auto].")
  101. #define SRATE_TEXT N_("Transponder symbol rate in kHz")
  102. #define SRATE_LONGTEXT ""
  103. #define LNB_LOF1_TEXT N_("Antenna lnb_lof1 (kHz)")
  104. #define LNB_LOF1_LONGTEXT ""
  105. #define LNB_LOF2_TEXT N_("Antenna lnb_lof2 (kHz)")
  106. #define LNB_LOF2_LONGTEXT ""
  107. #define LNB_SLOF_TEXT N_("Antenna lnb_slof (kHz)")
  108. #define LNB_SLOF_LONGTEXT ""
  109. /* Cable */
  110. #define MODULATION_TEXT N_("Modulation type")
  111. #define MODULATION_LONGTEXT N_("Modulation type for front-end device.")
  112. /* Terrestrial */
  113. #define CODE_RATE_HP_TEXT N_("Terrestrial high priority stream code rate (FEC)")
  114. #define CODE_RATE_HP_LONGTEXT ""
  115. #define CODE_RATE_LP_TEXT N_("Terrestrial low priority stream code rate (FEC)")
  116. #define CODE_RATE_LP_LONGTEXT ""
  117. #define BANDWIDTH_TEXT N_("Terrestrial bandwidth")
  118. #define BANDWIDTH_LONGTEXT N_("Terrestrial bandwidth [0=auto,6,7,8 in MHz]")
  119. #define GUARD_TEXT N_("Terrestrial guard interval")
  120. #define GUARD_LONGTEXT ""
  121. #define TRANSMISSION_TEXT N_("Terrestrial transmission mode")
  122. #define TRANSMISSION_LONGTEXT ""
  123. #define HIERARCHY_TEXT N_("Terrestrial hierarchy mode")
  124. #define HIERARCHY_LONGTEXT ""
  125. #define HOST_TEXT N_( "HTTP Host address" )
  126. #define HOST_LONGTEXT N_( 
  127.     "To enable the internal HTTP server, set its address and port here." )
  128. #define USER_TEXT N_( "HTTP user name" )
  129. #define USER_LONGTEXT N_( 
  130.     "User name the administrator will use to log into " 
  131.     "the internal HTTP server." )
  132. #define PASSWORD_TEXT N_( "HTTP password" )
  133. #define PASSWORD_LONGTEXT N_( 
  134.     "Password the administrator will use to log into " 
  135.     "the internal HTTP server." )
  136. #define ACL_TEXT N_( "HTTP ACL" )
  137. #define ACL_LONGTEXT N_( 
  138.     "Access control list (equivalent to .hosts) file path, " 
  139.     "which will limit the range of IPs entitled to log into the internal " 
  140.     "HTTP server." )
  141. #define CERT_TEXT N_( "Certificate file" )
  142. #define CERT_LONGTEXT N_( "HTTP interface x509 PEM certificate file " 
  143.                           "(enables SSL)" )
  144. #define KEY_TEXT N_( "Private key file" )
  145. #define KEY_LONGTEXT N_( "HTTP interface x509 PEM private key file" )
  146. #define CA_TEXT N_( "Root CA file" )
  147. #define CA_LONGTEXT N_( "HTTP interface x509 PEM trusted root CA " 
  148.                         "certificates file" )
  149. #define CRL_TEXT N_( "CRL file" )
  150. #define CRL_LONGTEXT N_( "HTTP interface Certificates Revocation List file" )
  151. vlc_module_begin ()
  152.     set_shortname( N_("DVB") )
  153.     set_description( N_("DVB input with v4l2 support") )
  154.     set_category( CAT_INPUT )
  155.     set_subcategory( SUBCAT_INPUT_ACCESS )
  156.     add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
  157.                  CACHING_LONGTEXT, true )
  158.         change_safe()
  159.     add_integer( "dvb-adapter", 0, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT,
  160.                  false )
  161.     add_integer( "dvb-device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
  162.                  true )
  163.     add_integer( "dvb-frequency", 0, NULL, FREQ_TEXT, FREQ_LONGTEXT,
  164.                  false )
  165.     add_integer( "dvb-inversion", 2, NULL, INVERSION_TEXT, INVERSION_LONGTEXT,
  166.                  true )
  167.     add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, true )
  168.     add_bool( "dvb-budget-mode", 0, NULL, BUDGET_TEXT, BUDGET_LONGTEXT,
  169.               true )
  170.     /* DVB-S (satellite) */
  171.     add_integer( "dvb-satno", 0, NULL, SATNO_TEXT, SATNO_LONGTEXT,
  172.                  true )
  173.     add_integer( "dvb-voltage", 13, NULL, VOLTAGE_TEXT, VOLTAGE_LONGTEXT,
  174.                  true )
  175.     add_bool( "dvb-high-voltage", 0, NULL, HIGH_VOLTAGE_TEXT,
  176.               HIGH_VOLTAGE_LONGTEXT, true )
  177.     add_integer( "dvb-tone", -1, NULL, TONE_TEXT, TONE_LONGTEXT,
  178.                  true )
  179.     add_integer( "dvb-fec", 9, NULL, FEC_TEXT, FEC_LONGTEXT, true )
  180.     add_integer( "dvb-srate", 27500000, NULL, SRATE_TEXT, SRATE_LONGTEXT,
  181.                  false )
  182.     add_integer( "dvb-lnb-lof1", 0, NULL, LNB_LOF1_TEXT,
  183.                  LNB_LOF1_LONGTEXT, true )
  184.     add_integer( "dvb-lnb-lof2", 0, NULL, LNB_LOF2_TEXT,
  185.                  LNB_LOF2_LONGTEXT, true )
  186.     add_integer( "dvb-lnb-slof", 0, NULL, LNB_SLOF_TEXT,
  187.                  LNB_SLOF_LONGTEXT, true )
  188.     /* DVB-C (cable) */
  189.     add_integer( "dvb-modulation", 0, NULL, MODULATION_TEXT,
  190.                  MODULATION_LONGTEXT, true )
  191.     /* DVB-T (terrestrial) */
  192.     add_integer( "dvb-code-rate-hp", 9, NULL, CODE_RATE_HP_TEXT,
  193.                  CODE_RATE_HP_LONGTEXT, true )
  194.     add_integer( "dvb-code-rate-lp", 9, NULL, CODE_RATE_LP_TEXT,
  195.                  CODE_RATE_LP_LONGTEXT, true )
  196.     add_integer( "dvb-bandwidth", 0, NULL, BANDWIDTH_TEXT, BANDWIDTH_LONGTEXT,
  197.                  true )
  198.     add_integer( "dvb-guard", 0, NULL, GUARD_TEXT, GUARD_LONGTEXT, true )
  199.     add_integer( "dvb-transmission", 0, NULL, TRANSMISSION_TEXT,
  200.                  TRANSMISSION_LONGTEXT, true )
  201.     add_integer( "dvb-hierarchy", 0, NULL, HIERARCHY_TEXT, HIERARCHY_LONGTEXT,
  202.                  true )
  203. #ifdef ENABLE_HTTPD
  204.     /* MMI HTTP interface */
  205.     set_section( N_("HTTP server" ), 0 )
  206.     add_string( "dvb-http-host", NULL, NULL, HOST_TEXT, HOST_LONGTEXT,
  207.                 true )
  208.     add_string( "dvb-http-user", NULL, NULL, USER_TEXT, USER_LONGTEXT,
  209.                 true )
  210.     add_string( "dvb-http-password", NULL, NULL, PASSWORD_TEXT,
  211.                 PASSWORD_LONGTEXT, true )
  212.     add_string( "dvb-http-acl", NULL, NULL, ACL_TEXT, ACL_LONGTEXT,
  213.                 true )
  214.     add_string( "dvb-http-intf-cert", NULL, NULL, CERT_TEXT, CERT_LONGTEXT,
  215.                 true )
  216.     add_string( "dvb-http-intf-key",  NULL, NULL, KEY_TEXT,  KEY_LONGTEXT,
  217.                 true )
  218.     add_string( "dvb-http-intf-ca",   NULL, NULL, CA_TEXT,   CA_LONGTEXT,
  219.                 true )
  220.     add_string( "dvb-http-intf-crl",  NULL, NULL, CRL_TEXT,  CRL_LONGTEXT,
  221.                 true )
  222. #endif
  223.     set_capability( "access", 0 )
  224.     add_shortcut( "dvb" )      /* Generic name */
  225.     add_shortcut( "dvb-s" )    /* Satellite */
  226.     add_shortcut( "qpsk" )
  227.     add_shortcut( "satellite" )
  228.     add_shortcut( "dvb-c" )    /* Cable */
  229.     add_shortcut( "cable" )
  230.     add_shortcut( "dvb-t" )    /* Terrestrial */
  231.     add_shortcut( "terrestrial" )
  232.     add_shortcut( "atsc" )     /* Atsc */
  233.     add_shortcut( "usdigital" )
  234.     set_callbacks( Open, Close )
  235. vlc_module_end ()
  236. /*****************************************************************************
  237.  * Local prototypes
  238.  *****************************************************************************/
  239. static block_t *Block( access_t * );
  240. static int Control( access_t *, int, va_list );
  241. static block_t *BlockScan( access_t * );
  242. #define DVB_READ_ONCE 20
  243. #define DVB_READ_ONCE_START 2
  244. #define DVB_READ_ONCE_SCAN 1
  245. #define TS_PACKET_SIZE 188
  246. #define DVB_SCAN_MAX_SIGNAL_TIME (300*1000)
  247. #define DVB_SCAN_MAX_LOCK_TIME (5000*1000)
  248. #define DVB_SCAN_MAX_PROBE_TIME (30000*1000)
  249. static void FilterUnset( access_t *, int i_max );
  250. static void FilterUnsetPID( access_t *, int i_pid );
  251. static void FilterSet( access_t *, int i_pid, int i_type );
  252. static void VarInit( access_t * );
  253. static int  ParseMRL( access_t * );
  254. /*****************************************************************************
  255.  * Open: open the frontend device
  256.  *****************************************************************************/
  257. static int Open( vlc_object_t *p_this )
  258. {
  259.     access_t     *p_access = (access_t*)p_this;
  260.     access_sys_t *p_sys;
  261.     /* Only if selected */
  262.     if( *p_access->psz_access == '' )
  263.         return VLC_EGENERIC;
  264.     /* Set up access */
  265.     p_access->pf_read = NULL;
  266.     p_access->pf_block = Block;
  267.     p_access->pf_control = Control;
  268.     p_access->pf_seek = NULL;
  269.     access_InitFields( p_access );
  270.     p_access->p_sys = p_sys = calloc( 1, sizeof( access_sys_t ) );
  271.     if( !p_sys )
  272.         return VLC_ENOMEM;
  273.     /* Create all variables */
  274.     VarInit( p_access );
  275.     /* Parse the command line */
  276.     if( ParseMRL( p_access ) )
  277.     {
  278.         free( p_sys );
  279.         return VLC_EGENERIC;
  280.     }
  281.     /* Getting frontend info */
  282.     if( FrontendOpen( p_access) )
  283.     {
  284.         free( p_sys );
  285.         return VLC_EGENERIC;
  286.     }
  287.     /* */
  288.     p_sys->b_scan_mode = var_GetInteger( p_access, "dvb-frequency" ) == 0;
  289.     if( p_sys->b_scan_mode )
  290.     {
  291.         msg_Dbg( p_access, "DVB scan mode selected" );
  292.         p_access->pf_block = BlockScan;
  293.     }
  294.     else
  295.     {
  296.         /* Setting frontend parameters for tuning the hardware */
  297.         msg_Dbg( p_access, "trying to tune the frontend...");
  298.         if( FrontendSet( p_access ) < 0 )
  299.         {
  300.             FrontendClose( p_access );
  301.             free( p_sys );
  302.             return VLC_EGENERIC;
  303.         }
  304.     }
  305.     /* Opening DVR device */
  306.     if( DVROpen( p_access ) < 0 )
  307.     {
  308.         FrontendClose( p_access );
  309.         free( p_sys );
  310.         return VLC_EGENERIC;
  311.     }
  312.     if( p_sys->b_scan_mode )
  313.     {
  314.         scan_parameter_t parameter;
  315.         msg_Dbg( p_access, "setting filter on PAT/NIT/SDT (DVB only)" );
  316.         FilterSet( p_access, 0x00, OTHER_TYPE );    // PAT
  317.         FilterSet( p_access, 0x10, OTHER_TYPE );    // NIT
  318.         FilterSet( p_access, 0x11, OTHER_TYPE );    // SDT
  319.         if( FrontendGetScanParameter( p_access, &parameter ) ||
  320.             scan_Init( VLC_OBJECT(p_access), &p_sys->scan, &parameter ) )
  321.         {
  322.             Close( VLC_OBJECT(p_access) );
  323.             return VLC_EGENERIC;
  324.         }
  325.     }
  326.     else
  327.     {
  328.         p_sys->b_budget_mode = var_GetBool( p_access, "dvb-budget-mode" );
  329.         if( p_sys->b_budget_mode )
  330.         {
  331.             msg_Dbg( p_access, "setting filter on all PIDs" );
  332.             FilterSet( p_access, 0x2000, OTHER_TYPE );
  333.         }
  334.         else
  335.         {
  336.             msg_Dbg( p_access, "setting filter on PAT" );
  337.             FilterSet( p_access, 0x0, OTHER_TYPE );
  338.         }
  339.         CAMOpen( p_access );
  340. #ifdef ENABLE_HTTPD
  341.         HTTPOpen( p_access );
  342. #endif
  343.     }
  344.     if( p_sys->b_scan_mode )
  345.         p_sys->i_read_once = DVB_READ_ONCE_SCAN;
  346.     else if( p_sys->b_budget_mode )
  347.         p_sys->i_read_once = DVB_READ_ONCE;
  348.     else
  349.         p_sys->i_read_once = DVB_READ_ONCE_START;
  350.     free( p_access->psz_demux );
  351.     p_access->psz_demux = strdup( p_sys->b_scan_mode ? "m3u8" : "ts" );
  352.     return VLC_SUCCESS;
  353. }
  354. /*****************************************************************************
  355.  * Close : Close the device
  356.  *****************************************************************************/
  357. static void Close( vlc_object_t *p_this )
  358. {
  359.     access_t     *p_access = (access_t*)p_this;
  360.     access_sys_t *p_sys = p_access->p_sys;
  361.     FilterUnset( p_access, p_sys->b_budget_mode && !p_sys->b_scan_mode ? 1 : MAX_DEMUX );
  362.     DVRClose( p_access );
  363.     FrontendClose( p_access );
  364.     if( p_sys->b_scan_mode )
  365.         scan_Clean( &p_sys->scan );
  366.     else
  367.         CAMClose( p_access );
  368. #ifdef ENABLE_HTTPD
  369.     if( !p_sys->b_scan_mode )
  370.         HTTPClose( p_access );
  371. #endif
  372.     free( p_sys );
  373. }
  374. /*****************************************************************************
  375.  * Block:
  376.  *****************************************************************************/
  377. static block_t *Block( access_t *p_access )
  378. {
  379.     access_sys_t *p_sys = p_access->p_sys;
  380.     block_t *p_block;
  381.     for ( ; ; )
  382.     {
  383.         struct pollfd ufds[2];
  384.         int i_ret;
  385.         /* Initialize file descriptor sets */
  386.         memset (ufds, 0, sizeof (ufds));
  387.         ufds[0].fd = p_sys->i_handle;
  388.         ufds[0].events = POLLIN;
  389.         ufds[1].fd = p_sys->i_frontend_handle;
  390.         ufds[1].events = POLLPRI;
  391.         /* We'll wait 0.5 second if nothing happens */
  392.         /* Find if some data is available */
  393.         i_ret = poll( ufds, 2, 500 );
  394.         if ( !vlc_object_alive (p_access) )
  395.             return NULL;
  396.         if ( i_ret < 0 )
  397.         {
  398.             if( errno == EINTR )
  399.                 continue;
  400.             msg_Err( p_access, "poll error: %m" );
  401.             return NULL;
  402.         }
  403.         if ( p_sys->i_ca_handle && mdate() > p_sys->i_ca_next_event )
  404.         {
  405.             CAMPoll( p_access );
  406.             p_sys->i_ca_next_event = mdate() + p_sys->i_ca_timeout;
  407.         }
  408.         if ( ufds[1].revents )
  409.         {
  410.             FrontendPoll( p_access );
  411.         }
  412. #ifdef ENABLE_HTTPD
  413.         if ( p_sys->i_httpd_timeout && mdate() > p_sys->i_httpd_timeout )
  414.         {
  415.             vlc_mutex_lock( &p_sys->httpd_mutex );
  416.             if ( p_sys->b_request_frontend_info )
  417.             {
  418.                 msg_Warn( p_access, "frontend timeout for HTTP interface" );
  419.                 p_sys->b_request_frontend_info = false;
  420.                 p_sys->psz_frontend_info = strdup( "Timeout getting infon" );
  421.             }
  422.             if ( p_sys->b_request_mmi_info )
  423.             {
  424.                 msg_Warn( p_access, "MMI timeout for HTTP interface" );
  425.                 p_sys->b_request_mmi_info = false;
  426.                 p_sys->psz_mmi_info = strdup( "Timeout getting infon" );
  427.             }
  428.             vlc_cond_signal( &p_sys->httpd_cond );
  429.             vlc_mutex_unlock( &p_sys->httpd_mutex );
  430.         }
  431.         if ( p_sys->b_request_frontend_info )
  432.         {
  433.             FrontendStatus( p_access );
  434.         }
  435.         if ( p_sys->b_request_mmi_info )
  436.         {
  437.             CAMStatus( p_access );
  438.         }
  439. #endif
  440.         if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
  441.         {
  442.             msg_Warn( p_access, "no lock, tuning again" );
  443.             FrontendSet( p_access );
  444.         }
  445.         if ( ufds[0].revents )
  446.         {
  447.             p_block = block_New( p_access,
  448.                                  p_sys->i_read_once * TS_PACKET_SIZE );
  449.             if( ( i_ret = read( p_sys->i_handle, p_block->p_buffer,
  450.                                 p_sys->i_read_once * TS_PACKET_SIZE ) ) <= 0 )
  451.             {
  452.                 msg_Warn( p_access, "read failed (%m)" );
  453.                 block_Release( p_block );
  454.                 continue;
  455.             }
  456.             p_block->i_buffer = i_ret;
  457.             break;
  458.         }
  459.     }
  460.     if( p_sys->i_read_once < DVB_READ_ONCE )
  461.         p_sys->i_read_once++;
  462.     /* Update moderatly the signal properties */
  463.     if( (p_sys->i_stat_counter++ % 100) == 0 )
  464.         p_access->info.i_update |= INPUT_UPDATE_SIGNAL;
  465.     return p_block;
  466. }
  467. /*****************************************************************************
  468.  * BlockScan:
  469.  *****************************************************************************/
  470. static block_t *BlockScan( access_t *p_access )
  471. {
  472.     access_sys_t *p_sys = p_access->p_sys;
  473.     scan_t *p_scan = &p_sys->scan;
  474.     scan_configuration_t cfg;
  475.     scan_session_t session;
  476.     /* */
  477.     if( scan_Next( p_scan, &cfg ) )
  478.     {
  479.         const bool b_first_eof = !p_access->info.b_eof;
  480.         if( b_first_eof )
  481.             msg_Warn( p_access, "Scanning finished" );
  482.         /* */
  483.         p_access->info.b_eof = true;
  484.         return b_first_eof ? scan_GetM3U( p_scan ) : NULL;
  485.     }
  486.     /* */
  487.     if( scan_session_Init( VLC_OBJECT(p_access), &session, &cfg ) )
  488.         return NULL;
  489.     /* */
  490.     msg_Dbg( p_access, "Scanning frequency %d", cfg.i_frequency );
  491.     var_SetInteger( p_access, "dvb-frequency", cfg.i_frequency );
  492.     var_SetInteger( p_access, "dvb-bandwidth", cfg.i_bandwidth );
  493.     /* Setting frontend parameters for tuning the hardware */
  494.     if( FrontendSet( p_access ) < 0 )
  495.     {
  496.         msg_Err( p_access, "Failed to tune the frontend" );
  497.         p_access->info.b_eof = true;
  498.         return NULL;
  499.     }
  500.     /* */
  501.     int64_t i_scan_start = mdate();
  502.     bool b_has_dvb_signal = false;
  503.     bool b_has_lock = false;
  504.     int i_best_snr = -1;
  505.     for ( ; ; )
  506.     {
  507.         struct pollfd ufds[2];
  508.         int i_ret;
  509.         /* Initialize file descriptor sets */
  510.         memset (ufds, 0, sizeof (ufds));
  511.         ufds[0].fd = p_sys->i_handle;
  512.         ufds[0].events = POLLIN;
  513.         ufds[1].fd = p_sys->i_frontend_handle;
  514.         ufds[1].events = POLLPRI;
  515.         /* We'll wait 0.1 second if nothing happens */
  516.         /* Find if some data is available */
  517.         i_ret = poll( ufds, 2, 100 );
  518.         if( !vlc_object_alive (p_access) || scan_IsCancelled( p_scan ) )
  519.             break;
  520.         if( i_ret <= 0 )
  521.         {
  522.             const mtime_t i_scan_time = mdate() - i_scan_start;
  523.             frontend_status_t status;
  524.             FrontendGetStatus( p_access, &status );
  525.             b_has_dvb_signal |= status.b_has_carrier;
  526.             b_has_lock |= status.b_has_lock;
  527.             if( ( !b_has_dvb_signal && i_scan_time > DVB_SCAN_MAX_SIGNAL_TIME ) ||
  528.                 ( !b_has_lock && i_scan_time > DVB_SCAN_MAX_LOCK_TIME ) ||
  529.                 ( i_scan_time > DVB_SCAN_MAX_PROBE_TIME ) )
  530.             {
  531.                 msg_Dbg( p_access, "timed out scanning current frequency (s=%d l=%d)", b_has_dvb_signal, b_has_lock );
  532.                 break;
  533.             }
  534.         }
  535.         if( i_ret < 0 )
  536.         {
  537.             if( errno == EINTR )
  538.                 continue;
  539.             msg_Err( p_access, "poll error: %m" );
  540.             scan_session_Clean( p_scan, &session );
  541.             p_access->info.b_eof = true;
  542.             return NULL;
  543.         }
  544.         if( ufds[1].revents )
  545.         {
  546.             frontend_statistic_t stat;
  547.             FrontendPoll( p_access );
  548.             if( !FrontendGetStatistic( p_access, &stat ) )
  549.             {
  550.                 if( stat.i_snr > i_best_snr )
  551.                     i_best_snr = stat.i_snr;
  552.             }
  553.         }
  554.         if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
  555.         {
  556.             msg_Warn( p_access, "no lock, tuning again" );
  557.             FrontendSet( p_access );
  558.         }
  559.         if ( ufds[0].revents )
  560.         {
  561.             const int i_read_once = 1;
  562.             block_t *p_block = block_New( p_access, i_read_once * TS_PACKET_SIZE );
  563.             if( ( i_ret = read( p_sys->i_handle, p_block->p_buffer,
  564.                                 i_read_once * TS_PACKET_SIZE ) ) <= 0 )
  565.             {
  566.                 msg_Warn( p_access, "read failed (%m)" );
  567.                 block_Release( p_block );
  568.                 continue;
  569.             }
  570.             p_block->i_buffer = i_ret;
  571.             /* */
  572.             if( scan_session_Push( &session, p_block ) )
  573.             {
  574.                 msg_Dbg( p_access, "finished scanning current frequency" );
  575.                 break;
  576.             }
  577.         }
  578.     }
  579.     /* */
  580.     if( i_best_snr > 0 )
  581.         scan_service_SetSNR( &session, i_best_snr );
  582.     scan_session_Clean( p_scan, &session );
  583.     return NULL;
  584. }
  585. /*****************************************************************************
  586.  * Control:
  587.  *****************************************************************************/
  588. static int Control( access_t *p_access, int i_query, va_list args )
  589. {
  590.     access_sys_t *p_sys = p_access->p_sys;
  591.     bool         *pb_bool, b_bool;
  592.     int          i_int;
  593.     int64_t      *pi_64;
  594.     double       *pf1, *pf2;
  595.     dvbpsi_pmt_t *p_pmt;
  596.     frontend_statistic_t stat;
  597.     switch( i_query )
  598.     {
  599.         /* */
  600.         case ACCESS_CAN_SEEK:
  601.         case ACCESS_CAN_FASTSEEK:
  602.         case ACCESS_CAN_PAUSE:
  603.         case ACCESS_CAN_CONTROL_PACE:
  604.             pb_bool = (bool*)va_arg( args, bool* );
  605.             *pb_bool = false;
  606.             break;
  607.         /* */
  608.         case ACCESS_GET_PTS_DELAY:
  609.             pi_64 = (int64_t*)va_arg( args, int64_t * );
  610.             *pi_64 = var_GetInteger( p_access, "dvb-caching" ) * 1000;
  611.             break;
  612.         /* */
  613.         case ACCESS_SET_PAUSE_STATE:
  614.         case ACCESS_GET_TITLE_INFO:
  615.         case ACCESS_SET_TITLE:
  616.         case ACCESS_SET_SEEKPOINT:
  617.         case ACCESS_GET_CONTENT_TYPE:
  618.             return VLC_EGENERIC;
  619.         case ACCESS_GET_SIGNAL:
  620.             pf1 = (double*)va_arg( args, double * );
  621.             pf2 = (double*)va_arg( args, double * );
  622.             *pf1 = *pf2 = 0;
  623.             if( !FrontendGetStatistic( p_access, &stat ) )
  624.             {
  625.                 *pf1 = (double)stat.i_snr / 65535.0;
  626.                 *pf2 = (double)stat.i_signal_strenth / 65535.0;
  627.             }
  628.             return VLC_SUCCESS;
  629.         case ACCESS_SET_PRIVATE_ID_STATE:
  630.             if( p_sys->b_scan_mode )
  631.                 return VLC_EGENERIC;
  632.             i_int  = (int)va_arg( args, int );               /* Private data (pid for now)*/
  633.             b_bool = (bool)va_arg( args, int ); /* b_selected */
  634.             if( !p_sys->b_budget_mode )
  635.             {
  636.                 /* FIXME we may want to give the real type (me ?, I don't ;) */
  637.                 if( b_bool )
  638.                     FilterSet( p_access, i_int, OTHER_TYPE );
  639.                 else
  640.                     FilterUnsetPID( p_access, i_int );
  641.             }
  642.             break;
  643.         case ACCESS_SET_PRIVATE_ID_CA:
  644.             if( p_sys->b_scan_mode )
  645.                 return VLC_EGENERIC;
  646.             p_pmt = (dvbpsi_pmt_t *)va_arg( args, dvbpsi_pmt_t * );
  647.             CAMSet( p_access, p_pmt );
  648.             break;
  649.         default:
  650.             msg_Warn( p_access, "unimplemented query in control" );
  651.             return VLC_EGENERIC;
  652.     }
  653.     return VLC_SUCCESS;
  654. }
  655. /*****************************************************************************
  656.  * FilterSet/FilterUnset:
  657.  *****************************************************************************/
  658. static void FilterSet( access_t *p_access, int i_pid, int i_type )
  659. {
  660.     access_sys_t *p_sys = p_access->p_sys;
  661.     int i;
  662.     /* Find first free slot */
  663.     for( i = 0; i < MAX_DEMUX; i++ )
  664.     {
  665.         if( !p_sys->p_demux_handles[i].i_type )
  666.             break;
  667.         if( p_sys->p_demux_handles[i].i_pid == i_pid )
  668.             return; /* Already set */
  669.     }
  670.     if( i >= MAX_DEMUX )
  671.     {
  672.         msg_Err( p_access, "no free p_demux_handles !" );
  673.         return;
  674.     }
  675.     if( DMXSetFilter( p_access, i_pid,
  676.                            &p_sys->p_demux_handles[i].i_handle, i_type ) )
  677.     {
  678.         msg_Err( p_access, "DMXSetFilter failed" );
  679.         return;
  680.     }
  681.     p_sys->p_demux_handles[i].i_type = i_type;
  682.     p_sys->p_demux_handles[i].i_pid = i_pid;
  683.     if( p_sys->i_read_once < DVB_READ_ONCE )
  684.         p_sys->i_read_once++;
  685. }
  686. static void FilterUnset( access_t *p_access, int i_max )
  687. {
  688.     access_sys_t *p_sys = p_access->p_sys;
  689.     int i;
  690.     for( i = 0; i < i_max; i++ )
  691.     {
  692.         if( p_sys->p_demux_handles[i].i_type )
  693.         {
  694.             DMXUnsetFilter( p_access, p_sys->p_demux_handles[i].i_handle );
  695.             p_sys->p_demux_handles[i].i_type = 0;
  696.         }
  697.     }
  698. }
  699. static void FilterUnsetPID( access_t *p_access, int i_pid )
  700. {
  701.     access_sys_t *p_sys = p_access->p_sys;
  702.     int i;
  703.     for( i = 0; i < MAX_DEMUX; i++ )
  704.     {
  705.         if( p_sys->p_demux_handles[i].i_type &&
  706.             p_sys->p_demux_handles[i].i_pid == i_pid )
  707.         {
  708.             DMXUnsetFilter( p_access, p_sys->p_demux_handles[i].i_handle );
  709.             p_sys->p_demux_handles[i].i_type = 0;
  710.         }
  711.     }
  712. }
  713. /*****************************************************************************
  714.  * VarInit/ParseMRL:
  715.  *****************************************************************************/
  716. static void VarInit( access_t *p_access )
  717. {
  718.     /* */
  719.     var_Create( p_access, "dvb-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  720.     /* */
  721.     var_Create( p_access, "dvb-adapter", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  722.     var_Create( p_access, "dvb-device", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  723.     var_Create( p_access, "dvb-frequency", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  724.     var_Create( p_access, "dvb-inversion", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  725.     var_Create( p_access, "dvb-probe", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  726.     var_Create( p_access, "dvb-budget-mode", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  727.     /* */
  728.     var_Create( p_access, "dvb-satno", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  729.     var_Create( p_access, "dvb-voltage", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  730.     var_Create( p_access, "dvb-high-voltage", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  731.     var_Create( p_access, "dvb-tone", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  732.     var_Create( p_access, "dvb-fec", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  733.     var_Create( p_access, "dvb-srate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  734.     var_Create( p_access, "dvb-lnb-lof1", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  735.     var_Create( p_access, "dvb-lnb-lof2", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  736.     var_Create( p_access, "dvb-lnb-slof", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  737.     /* */
  738.     var_Create( p_access, "dvb-modulation", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  739.     /* */
  740.     var_Create( p_access, "dvb-code-rate-hp", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  741.     var_Create( p_access, "dvb-code-rate-lp", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  742.     var_Create( p_access, "dvb-bandwidth", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  743.     var_Create( p_access, "dvb-transmission", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  744.     var_Create( p_access, "dvb-guard", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  745.     var_Create( p_access, "dvb-hierarchy", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  746. #ifdef ENABLE_HTTPD
  747.     var_Create( p_access, "dvb-http-host", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  748.     var_Create( p_access, "dvb-http-user", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  749.     var_Create( p_access, "dvb-http-password", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  750.     var_Create( p_access, "dvb-http-acl", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  751.     var_Create( p_access, "dvb-http-intf-cert", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  752.     var_Create( p_access, "dvb-http-intf-key", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  753.     var_Create( p_access, "dvb-http-intf-ca", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  754.     var_Create( p_access, "dvb-http-intf-crl", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  755. #endif
  756. }
  757. /* */
  758. static int ParseMRL( access_t *p_access )
  759. {
  760.     char *psz_dup = strdup( p_access->psz_path );
  761.     char *psz_parser = psz_dup;
  762.     char *psz_next;
  763.     vlc_value_t         val;
  764. #define GET_OPTION_INT( option )                                            
  765.     if ( !strncmp( psz_parser, option "=", strlen(option "=") ) )           
  766.     {                                                                       
  767.         val.i_int = strtol( psz_parser + strlen(option "="), &psz_parser,   
  768.                             0 );                                            
  769.         var_Set( p_access, "dvb-" option, val );                            
  770.     }
  771. #define GET_OPTION_BOOL( option )                                           
  772.     if ( !strncmp( psz_parser, option "=", strlen(option "=") ) )           
  773.     {                                                                       
  774.         val.b_bool = strtol( psz_parser + strlen(option "="), &psz_parser,  
  775.                              0 );                                           
  776.         var_Set( p_access, "dvb-" option, val );                            
  777.     }
  778.     /* Test for old syntax */
  779.     strtol( psz_parser, &psz_next, 10 );
  780.     if( psz_next != psz_parser )
  781.     {
  782.         msg_Err( p_access, "the DVB input old syntax is deprecated, use vlc "
  783.                           "-p dvb to see an explanation of the new syntax" );
  784.         dialog_FatalWait( p_access, _("Input syntax is deprecated"), "%s",
  785.             _("The given syntax is deprecated. Run "vlc -p dvb" to see an " 
  786.                 "explanation of the new syntax.") );
  787.         free( psz_dup );
  788.         return VLC_EGENERIC;
  789.     }
  790.     while( *psz_parser )
  791.     {
  792.         GET_OPTION_INT("adapter")
  793.         else GET_OPTION_INT("device")
  794.         else GET_OPTION_INT("frequency")
  795.         else GET_OPTION_INT("inversion")
  796.         else GET_OPTION_BOOL("probe")
  797.         else GET_OPTION_BOOL("budget-mode")
  798.         else GET_OPTION_INT("voltage")
  799.         else GET_OPTION_BOOL("high-voltage")
  800.         else GET_OPTION_INT("tone")
  801.         else GET_OPTION_INT("satno")
  802.         else GET_OPTION_INT("fec")
  803.         else GET_OPTION_INT("srate")
  804.         else GET_OPTION_INT("lnb-lof1")
  805.         else GET_OPTION_INT("lnb-lof2")
  806.         else GET_OPTION_INT("lnb-slof")
  807.         else GET_OPTION_INT("modulation")
  808.         else GET_OPTION_INT("code-rate-hp")
  809.         else GET_OPTION_INT("code-rate-lp")
  810.         else GET_OPTION_INT("bandwidth")
  811.         else GET_OPTION_INT("transmission")
  812.         else GET_OPTION_INT("guard")
  813.         else GET_OPTION_INT("hierarchy")
  814.         /* Redundant with voltage but much easier to use */
  815.         else if( !strncmp( psz_parser, "polarization=",
  816.                            strlen( "polarization=" ) ) )
  817.         {
  818.             psz_parser += strlen( "polarization=" );
  819.             if ( *psz_parser == 'V' || *psz_parser == 'v' )
  820.                 val.i_int = 13;
  821.             else if ( *psz_parser == 'H' || *psz_parser == 'h' )
  822.                 val.i_int = 18;
  823.             else
  824.             {
  825.                 msg_Err( p_access, "illegal polarization %c", *psz_parser );
  826.                 dialog_Fatal( p_access, _("Invalid polarization"),
  827.                                 _("The provided polarization "%c" is not valid."),
  828.                                 *psz_parser );
  829.                 free( psz_dup );
  830.                 return VLC_EGENERIC;
  831.             }
  832.             var_Set( p_access, "dvb-voltage", val );
  833.         }
  834.         else
  835.         {
  836.             msg_Err( p_access, "unknown option (%s)", psz_parser );
  837.             free( psz_dup );
  838.             return VLC_EGENERIC;
  839.         }
  840.         if ( *psz_parser )
  841.             psz_parser++;
  842.     }
  843. #undef GET_OPTION_INT
  844. #undef GET_OPTION_BOOL
  845.     free( psz_dup );
  846.     return VLC_SUCCESS;
  847. }