]> git.sesse.net Git - vlc/blobdiff - modules/access/dtv/access.c
DTV: deal with "cable", "terrestrial" and "satellite" scheme right
[vlc] / modules / access / dtv / access.c
index 9d718aed34297987766b83164ea1d9b9cd2785e7..c7cbf067698028a6ef8014c45181d6587ce6f253 100644 (file)
@@ -5,20 +5,20 @@
 /*****************************************************************************
  * Copyright © 2011 Rémi Denis-Courmont
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * 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.
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- ****************************************************************************/
+ * You should have received a copy of the GNU Lesser 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.
+ *****************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 
 #include <vlc_common.h>
 #include <vlc_access.h>
+#include <vlc_input.h>
 #include <vlc_plugin.h>
 #include <vlc_dialog.h>
 #include <search.h>
 
 #include "dtv/dtv.h"
 
-#define CACHING_TEXT N_("Caching value (ms)")
-#define CACHING_LONGTEXT N_( \
-    "The cache size (delay) for digital broadcasts (in milliseconds).")
-
 #define ADAPTER_TEXT N_("DVB adapter")
 #define ADAPTER_LONGTEXT N_( \
     "If there is more than one digital broadcasting adapter, " \
@@ -58,6 +55,9 @@
     "on a given frequency. This is required to tune the receiver.")
 
 #define MODULATION_TEXT N_("Modulation / Constellation")
+#define MODULATION_A_TEXT N_("Layer A modulation")
+#define MODULATION_B_TEXT N_("Layer B modulation")
+#define MODULATION_C_TEXT N_("Layer C modulation")
 #define MODULATION_LONGTEXT N_( \
     "The digital signal can be modulated according with different " \
     "constellations (depending on the delivery system). " \
@@ -90,6 +90,9 @@ static const char *const auto_off_on_user[] = { N_("Automatic"),
 #define CODE_RATE_TEXT N_("FEC code rate")
 #define CODE_RATE_HP_TEXT N_("High-priority code rate")
 #define CODE_RATE_LP_TEXT N_("Low-priority code rate")
+#define CODE_RATE_A_TEXT N_("Layer A code rate")
+#define CODE_RATE_B_TEXT N_("Layer B code rate")
+#define CODE_RATE_C_TEXT N_("Layer C code rate")
 #define CODE_RATE_LONGTEXT N_( \
     "The code rate for Forward Error Correction can be specified.")
 static const char *const code_rate_vlc[] = { "",
@@ -134,6 +137,14 @@ static const char *const hierarchy_user[] = { N_("Automatic"),
     N_("None"), "1", "2", "4",
 };
 
+#define SEGMENT_COUNT_A_TEXT N_("Layer A segments count")
+#define SEGMENT_COUNT_B_TEXT N_("Layer B segments count")
+#define SEGMENT_COUNT_C_TEXT N_("Layer C segments count")
+
+#define TIME_INTERLEAVING_A_TEXT N_("Layer A time interleaving")
+#define TIME_INTERLEAVING_B_TEXT N_("Layer B time interleaving")
+#define TIME_INTERLEAVING_C_TEXT N_("Layer C time interleaving")
+
 #define PILOT_TEXT N_("Pilot")
 
 #define ROLLOFF_TEXT N_("Roll-off factor")
@@ -144,6 +155,8 @@ static const char *const rolloff_user[] = { N_("Automatic"),
     N_("0.35 (same as DVB-S)"), N_("0.20"), N_("0.25"),
 };
 
+#define TS_ID_TEXT N_("Transport stream ID")
+
 #define POLARIZATION_TEXT N_("Polarization (Voltage)")
 #define POLARIZATION_LONGTEXT N_( \
     "To select the polarization of the transponder, a different voltage " \
@@ -217,26 +230,21 @@ vlc_module_begin ()
     set_capability ("access", 0)
     set_callbacks (Open, Close)
     add_shortcut ("dtv", "tv", "dvb", /* "radio", "dab",*/
-                  "cable", "dvb-c", "satellite", "dvb-s", "dvb-s2",
-                  "terrestrial", "dvb-t", "dvb-t2", "atsc", "cqam")
+                  "cable", "dvb-c", "cqam", "isdb-c",
+                  "satellite", "dvb-s", "dvb-s2", "isdb-s",
+                  "terrestrial", "dvb-t", "dvb-t2", "isdb-t", "atsc",
+                  "dvbt")
 
-    /* All options starting with dvb- can be overridden in the MRL, so they
-     * must all be "safe". Nevertheless, we do not mark as safe those that are
-     * really specific to the local system (e.g. device ID...).
-     * It wouldn't make sense to deliver those through a playlist. */
-
-    add_integer ("dvb-caching", DEFAULT_PTS_DELAY / 1000,
-                 CACHING_TEXT, CACHING_LONGTEXT, true)
-        change_integer_range (0, 60000)
-        change_safe ()
 #ifdef __linux__
     add_integer ("dvb-adapter", 0, ADAPTER_TEXT, ADAPTER_LONGTEXT, false)
         change_integer_range (0, 255)
+        change_safe ()
     add_obsolete_integer ("dvb-device")
     add_bool ("dvb-budget-mode", false, BUDGET_TEXT, BUDGET_LONGTEXT, true)
 #endif
 #ifdef WIN32
     add_integer ("dvb-adapter", -1, ADAPTER_TEXT, ADAPTER_LONGTEXT, true)
+        change_safe ()
     add_string ("dvb-network-name", "", NAME_TEXT, NAME_LONGTEXT, true)
     /* Hmm: is this one really safe??: */
     add_string ("dvb-create-name", "", CREATE_TEXT, CREATE_LONGTEXT, true)
@@ -253,14 +261,6 @@ vlc_module_begin ()
     add_integer ("dvb-bandwidth", 0, BANDWIDTH_TEXT, BANDWIDTH_TEXT, true)
         change_integer_list (bandwidth_vlc, bandwidth_user)
         change_safe ()
-    add_string ("dvb-code-rate-hp", "",
-                CODE_RATE_HP_TEXT, CODE_RATE_LONGTEXT, false)
-        change_string_list (code_rate_vlc, code_rate_user, NULL)
-        change_safe ()
-    add_string ("dvb-code-rate-lp", "",
-                CODE_RATE_LP_TEXT, CODE_RATE_LONGTEXT, false)
-        change_string_list (code_rate_vlc, code_rate_user, NULL)
-        change_safe ()
     add_integer ("dvb-transmission", 0,
                  TRANSMISSION_TEXT, TRANSMISSION_TEXT, true)
         change_integer_list (transmission_vlc, transmission_user)
@@ -268,10 +268,61 @@ vlc_module_begin ()
     add_string ("dvb-guard", "", GUARD_TEXT, GUARD_TEXT, true)
         change_string_list (guard_vlc, guard_user, NULL)
         change_safe ()
+
+    set_section (N_("DVB-T reception parameters"), NULL)
+    add_string ("dvb-code-rate-hp", "",
+                CODE_RATE_HP_TEXT, CODE_RATE_LONGTEXT, true)
+        change_string_list (code_rate_vlc, code_rate_user, NULL)
+        change_safe ()
+    add_string ("dvb-code-rate-lp", "",
+                CODE_RATE_LP_TEXT, CODE_RATE_LONGTEXT, true)
+        change_string_list (code_rate_vlc, code_rate_user, NULL)
+        change_safe ()
     add_integer ("dvb-hierarchy", -1, HIERARCHY_TEXT, HIERARCHY_TEXT, true)
         change_integer_list (hierarchy_vlc, hierarchy_user)
         change_safe ()
 
+    set_section (N_("ISDB-T reception parameters"), NULL)
+    add_string ("dvb-a-modulation", NULL,
+                MODULATION_A_TEXT, MODULATION_LONGTEXT, true)
+        change_string_list (modulation_vlc, modulation_user, NULL)
+        change_safe ()
+    add_string ("dvb-a-fec", NULL, CODE_RATE_A_TEXT, CODE_RATE_LONGTEXT, true)
+        change_string_list (code_rate_vlc, code_rate_user, NULL)
+        change_safe ()
+    add_integer ("dvb-a-count", 0, SEGMENT_COUNT_A_TEXT, NULL, true)
+        change_integer_range (0, 13)
+        change_safe ()
+    add_integer ("dvb-a-interleaving", 0, TIME_INTERLEAVING_A_TEXT, NULL, true)
+        change_integer_range (0, 3)
+        change_safe ()
+    add_string ("dvb-b-modulation", NULL,
+                MODULATION_B_TEXT, MODULATION_LONGTEXT, true)
+        change_string_list (modulation_vlc, modulation_user, NULL)
+        change_safe ()
+    add_string ("dvb-b-fec", NULL, CODE_RATE_B_TEXT, CODE_RATE_LONGTEXT, true)
+        change_string_list (code_rate_vlc, code_rate_user, NULL)
+        change_safe ()
+    add_integer ("dvb-b-count", 0, SEGMENT_COUNT_B_TEXT, NULL, true)
+        change_integer_range (0, 13)
+        change_safe ()
+    add_integer ("dvb-b-interleaving", 0, TIME_INTERLEAVING_B_TEXT, NULL, true)
+        change_integer_range (0, 3)
+        change_safe ()
+    add_string ("dvb-c-modulation", NULL,
+                MODULATION_C_TEXT, MODULATION_LONGTEXT, true)
+        change_string_list (modulation_vlc, modulation_user, NULL)
+        change_safe ()
+    add_string ("dvb-c-fec", NULL, CODE_RATE_C_TEXT, CODE_RATE_LONGTEXT, true)
+        change_string_list (code_rate_vlc, code_rate_user, NULL)
+        change_safe ()
+    add_integer ("dvb-c-count", 0, SEGMENT_COUNT_C_TEXT, NULL, true)
+        change_integer_range (0, 13)
+        change_safe ()
+    add_integer ("dvb-c-interleaving", 0, TIME_INTERLEAVING_C_TEXT, NULL, true)
+        change_integer_range (0, 3)
+        change_safe ()
+
     set_section (N_("Cable and satellite reception parameters"), NULL)
     add_string ("dvb-modulation", NULL,
                  MODULATION_TEXT, MODULATION_LONGTEXT, false)
@@ -292,6 +343,11 @@ vlc_module_begin ()
         change_integer_list (rolloff_vlc, rolloff_user)
         change_safe ()
 
+    set_section (N_("ISDB-S parameters"), NULL)
+    add_integer ("dvb-ts-id", 0, TS_ID_TEXT, TS_ID_TEXT, false)
+        change_integer_range (0, 0xffff)
+        change_safe ()
+
     set_section (N_("Satellite equipment control"), NULL)
     add_string ("dvb-polarization", "",
                 POLARIZATION_TEXT, POLARIZATION_LONGTEXT, false)
@@ -307,14 +363,14 @@ vlc_module_begin ()
 #endif
     add_integer ("dvb-lnb-low", 0, LNB_LOW_TEXT, LNB_LONGTEXT, true)
         change_integer_range (0, 0x7fffffff)
-        add_deprecated_alias ("dvb-lnb-lof1")
+    add_obsolete_integer ("dvb-lnb-lof1") /* since 2.0.0 */
     add_integer ("dvb-lnb-high", 0, LNB_HIGH_TEXT, LNB_LONGTEXT, true)
         change_integer_range (0, 0x7fffffff)
-        add_deprecated_alias ("dvb-lnb-lof2")
+    add_obsolete_integer ("dvb-lnb-lof2") /* since 2.0.0 */
     add_integer ("dvb-lnb-switch", 11700000,
                  LNB_SWITCH_TEXT, LNB_SWITCH_LONGTEXT, true)
         change_integer_range (0, 0x7fffffff)
-        add_deprecated_alias ("dvb-lnb-slof")
+    add_obsolete_integer ("dvb-lnb-slof") /* since 2.0.0 */
 #ifdef __linux__
     add_integer ("dvb-satno", 0, SATNO_TEXT, SATNO_LONGTEXT, true)
         change_integer_list (satno_vlc, satno_user)
@@ -340,6 +396,7 @@ vlc_module_end ()
 struct access_sys_t
 {
     dvb_device_t *dev;
+    uint8_t signal_poll;
 };
 
 typedef struct delsys
@@ -348,7 +405,9 @@ typedef struct delsys
     /* TODO: scan stuff */
 } delsys_t;
 
-static const delsys_t dvbc, dvbs, dvbs2, dvbt, dvbt2, atsc, cqam;
+static const delsys_t dvbc, dvbs, dvbs2, dvbt, dvbt2;
+static const delsys_t isdbc, isdbs, isdbt;
+static const delsys_t atsc, cqam;
 
 static block_t *Read (access_t *);
 static int Control (access_t *, int, va_list);
@@ -373,6 +432,7 @@ static int Open (vlc_object_t *obj)
     }
 
     sys->dev = dev;
+    sys->signal_poll = 0;
     access->p_sys = sys;
 
     uint64_t freq = var_InheritFrequency (obj);
@@ -434,6 +494,12 @@ static block_t *Read (access_t *access)
     }
 
     block->i_buffer = val;
+
+    /* Fetch the signal levels every so often. Some devices do not like this
+     * to be requested too frequently, e.g. due to low bandwidth I²C bus. */
+    if ((sys->signal_poll++) == 0)
+        access->info.i_update |= INPUT_UPDATE_SIGNAL;
+
     return block;
 }
 
@@ -457,7 +523,7 @@ static int Control (access_t *access, int query, va_list args)
         case ACCESS_GET_PTS_DELAY:
         {
             int64_t *v = va_arg (args, int64_t *);
-            *v = var_InheritInteger (access, "dvb-caching") * INT64_C(1000);
+            *v = var_InheritInteger (access, "live-caching") * INT64_C(1000);
             return VLC_SUCCESS;
         }
 
@@ -523,25 +589,7 @@ static int Control (access_t *access, int query, va_list args)
 /** Determines which delivery system to use. */
 static const delsys_t *GuessSystem (const char *scheme, dvb_device_t *dev)
 {
-    /* NOTE: We should guess the delivery system for the "cable", "satellite"
-     * and "terrestrial" shortcuts (i.e. DVB, ISDB, ATSC...). But there is
-     * seemingly no sane way to do get the info with Linux DVB version 5.2.
-     * In particular, the frontend infos distinguish only the modulator class
-     * (QPSK, QAM, OFDM or ATSC).
-     *
-     * Furthermore, if the demodulator supports 2G, we cannot guess whether
-     * 1G or 2G is intended. For backward compatibility, 1G is assumed
-     * (this is not a limitation of Linux DVB). We will probably need something
-     * smarter when 2G (semi automatic) scanning is implemented. */
-    if (!strcasecmp (scheme, "cable"))
-        scheme = "dvb-c";
-    else
-    if (!strcasecmp (scheme, "satellite"))
-        scheme = "dvb-s";
-    else
-    if (!strcasecmp (scheme, "terrestrial"))
-        scheme = "dvb-t";
-
+    /* Specific delivery system is specified */
     if (!strcasecmp (scheme, "atsc"))
         return &atsc;
     if (!strcasecmp (scheme, "cqam"))
@@ -556,16 +604,55 @@ static const delsys_t *GuessSystem (const char *scheme, dvb_device_t *dev)
         return &dvbt;
     if (!strcasecmp (scheme, "dvb-t2"))
         return &dvbt2;
-
+    if (!strcasecmp (scheme, "isdb-c"))
+        return &isdbc;
+    if (!strcasecmp (scheme, "isdb-s"))
+        return &isdbs;
+    if (!strcasecmp (scheme, "isdb-t"))
+        return &isdbt;
+
+    /* If the demodulator supports 2G, we cannot guess whether
+     * 1G or 2G is intended. For backward compatibility, 1G is assumed
+     * (this is not a limitation of Linux DVB). We will probably need something
+     * smarter when 2G (semi automatic) scanning is implemented. */
     unsigned systems = dvb_enum_systems (dev);
-    if (systems & ATSC)
-        return &atsc;
+
+    /* Only wave carrier is specified */
+    if (!strcasecmp (scheme, "cable"))
+    {
+        if (systems & DVB_C)
+            return &dvbc;
+        if (systems & CQAM)
+            return &cqam;
+        if (systems & ISDB_C)
+            return &isdbc;
+    }
+    if (!strcasecmp (scheme, "satellite"))
+    {
+        if (systems & DVB_S)
+            return &dvbs;
+        if (systems & ISDB_S)
+            return &isdbs;
+    }
+    if (!strcasecmp (scheme, "terrestrial"))
+    {
+        if (systems & DVB_T)
+            return &dvbc;
+        if (systems & ATSC)
+            return &cqam;
+        if (systems & ISDB_T)
+            return &isdbt;
+    }
+
+    /* Only standards family or nothing is specified */
     if (systems & DVB_C)
         return &dvbc;
     if (systems & DVB_S)
         return &dvbc;
     if (systems & DVB_T)
         return &dvbt;
+    if (systems & ATSC)
+        return &atsc;
     return NULL;
 }
 
@@ -627,9 +714,9 @@ static int modcmp (const void *a, const void *b)
     return strcasecmp (a, *(const char *const *)b);
 }
 
-static const char *var_InheritModulation (vlc_object_t *obj)
+static const char *var_InheritModulation (vlc_object_t *obj, const char *var)
 {
-    char *mod = var_InheritString (obj, "dvb-modulation");
+    char *mod = var_InheritString (obj, var);
     if (mod == NULL)
         return "";
 
@@ -691,7 +778,7 @@ static unsigned var_InheritGuardInterval (vlc_object_t *obj)
 /*** ATSC ***/
 static int atsc_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 {
-    const char *mod = var_InheritModulation (obj);
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
 
     return dvb_set_atsc (dev, freq, mod);
 }
@@ -700,7 +787,7 @@ static const delsys_t atsc = { .setup = atsc_setup };
 
 static int cqam_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 {
-    const char *mod = var_InheritModulation (obj);
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
 
     return dvb_set_cqam (dev, freq, mod);
 }
@@ -711,7 +798,7 @@ static const delsys_t cqam = { .setup = cqam_setup };
 /*** DVB-C ***/
 static int dvbc_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 {
-    const char *mod = var_InheritModulation (obj);
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
     uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
     unsigned srate = var_InheritInteger (obj, "dvb-srate");
 
@@ -772,7 +859,7 @@ static int dvbs_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 
 static int dvbs2_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 {
-    const char *mod = var_InheritModulation (obj);
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
     uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
     uint32_t srate = var_InheritInteger (obj, "dvb-srate");
     int pilot = var_InheritInteger (obj, "dvb-pilot");
@@ -791,7 +878,7 @@ static const delsys_t dvbs2 = { .setup = dvbs2_setup };
 /*** DVB-T ***/
 static int dvbt_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 {
-    const char *mod = var_InheritModulation (obj);
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
     uint32_t fec_hp = var_InheritCodeRate (obj, "dvb-code-rate-hp");
     uint32_t fec_lp = var_InheritCodeRate (obj, "dvb-code-rate-lp");
     uint32_t guard = var_InheritGuardInterval (obj);
@@ -804,7 +891,7 @@ static int dvbt_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 
 static int dvbt2_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 {
-    const char *mod = var_InheritModulation (obj);
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
     uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
     uint32_t guard = var_InheritGuardInterval (obj);
     uint32_t bw = var_InheritInteger (obj, "dvb-bandwidth");
@@ -815,3 +902,60 @@ static int dvbt2_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
 
 static const delsys_t dvbt = { .setup = dvbt_setup };
 static const delsys_t dvbt2 = { .setup = dvbt2_setup };
+
+
+/*** ISDB-C ***/
+static int isdbc_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
+{
+    const char *mod = var_InheritModulation (obj, "dvb-modulation");
+    uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
+    unsigned srate = var_InheritInteger (obj, "dvb-srate");
+
+    return dvb_set_isdbc (dev, freq, mod, srate, fec);
+}
+
+static const delsys_t isdbc = { .setup = isdbc_setup };
+
+
+/*** ISDB-S ***/
+static int isdbs_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
+{
+    uint16_t ts_id = var_InheritInteger (obj, "dvb-ts-id");
+
+    int ret = dvb_set_isdbs (dev, freq, ts_id);
+    if (ret == 0)
+        ret = sec_setup (obj, dev, freq);
+    return ret;
+}
+
+static const delsys_t isdbs = { .setup = isdbs_setup };
+
+
+/*** ISDB-T ***/
+static int isdbt_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
+{
+    isdbt_layer_t layers[3];
+    uint32_t guard = var_InheritGuardInterval (obj);
+    uint32_t bw = var_InheritInteger (obj, "dvb-bandwidth");
+    int tx = var_InheritInteger (obj, "dvb-transmission");
+
+    for (unsigned i = 0; i < 3; i++)
+    {
+        char varname[sizeof ("dvb-X-interleaving")];
+        memcpy (varname, "dvb-X-", 4);
+        varname[4] = 'a' + i;
+
+        strcpy (varname + 6, "modulation");
+        layers[i].modulation = var_InheritModulation (obj, varname);
+        strcpy (varname + 6, "fec");
+        layers[i].code_rate = var_InheritCodeRate (obj, varname);
+        strcpy (varname + 6, "count");
+        layers[i].segment_count = var_InheritInteger (obj, varname);
+        strcpy (varname + 6, "interleaving");
+        layers[i].time_interleaving = var_InheritInteger (obj, varname);
+    }
+
+    return dvb_set_isdbt (dev, freq, bw, tx, guard, layers);
+}
+
+static const delsys_t isdbt = { .setup = isdbt_setup };