]> git.sesse.net Git - vlc/blob - modules/access/dtv/access.c
DTV: pass FEC parameters as integers internally
[vlc] / modules / access / dtv / access.c
1 /**
2  * @file access.c
3  * @brief Digital broadcasting input module for VLC media player
4  */
5 /*****************************************************************************
6  * Copyright © 2011 Rémi Denis-Courmont
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1
11  * of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  ****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <vlc_common.h>
28 #include <vlc_access.h>
29 #include <vlc_plugin.h>
30 #include <vlc_dialog.h>
31
32 #include "dtv/dtv.h"
33
34 #define CACHING_TEXT N_("Caching value (ms)")
35 #define CACHING_LONGTEXT N_( \
36     "The cache size (delay) for digital broadcasts (in milliseconds).")
37
38 #define ADAPTER_TEXT N_("DVB adapter")
39 #define ADAPTER_LONGTEXT N_( \
40     "If there is more than one digital broadcasting adapter, " \
41     "the adapter number must be selected. Numbering start from zero.")
42
43 #define DEVICE_TEXT N_("DVB device")
44 #define DEVICE_LONGTEXT N_( \
45     "If the selected adapter has more than one tuner, " \
46     "the tuner number must be selected. Numbering start from zero.")
47
48 #define BUDGET_TEXT N_("Do not demultiplex")
49 #define BUDGET_LONGTEXT N_( \
50     "Only useful programs are normally demultiplexed from the transponder. " \
51     "This option will disable demultiplexing and receive all programs.")
52
53 #define FREQ_TEXT N_("Frequency (kHz)")
54 #define FREQ_LONGTEXT N_( \
55     "TV channels are grouped by transponder (a.k.a. multiplex) " \
56     "on a given frequency. This is required to tune the receiver.")
57
58 #define MODULATION_TEXT N_("Modulation / Constellation")
59 #define MODULATION_LONGTEXT N_( \
60     "The digital signal can be modulated according with different " \
61     "constellations (depending on the delivery system). " \
62     "If the demodulator cannot detect the constellation automatically, " \
63     "it needs to be configured manually.")
64 static const char *const modulation_vlc[] = { "",
65     "QAM", "16QAM", "32QAM", "64QAM", "128QAM", "256QAM",
66     "8VSB", "16VSB",
67     "QPSK", "DQPSK", "8PSK", "16APSK", "32APSK",
68 };
69 static const char *const modulation_user[] = { N_("Undefined"),
70     "Auto QAM", "16-QAM", "32-QAM", "64-QAM", "128-QAM", "256-QAM",
71     "8-VSB", "16-VSB",
72     "QPSK", "DQPSK", "8-PSK", "16-APSK", "32-APSK",
73 };
74
75 #define SRATE_TEXT N_("Symbol rate (bauds)")
76 #define SRATE_LONGTEXT N_( \
77     "The symbol rate must be specified manually for some systems, " \
78     "notably DVB-C, DVB-S and DVB-S2.")
79
80 #define INVERSION_TEXT N_("Spectrum inversion")
81 #define INVERSION_LONGTEXT N_( \
82     "If the demodulator cannot detect spectral inversion correctly, " \
83     "it needs to be configured manually.")
84 const int auto_off_on_vlc[] = { -1, 0, 1 };
85 static const char *const auto_off_on_user[] = { N_("Automatic"),
86     N_("Off"), N_("On") };
87
88 #define CODE_RATE_TEXT N_("FEC code rate")
89 #define CODE_RATE_HP_TEXT N_("High-priority code rate")
90 #define CODE_RATE_LP_TEXT N_("Low-priority code rate")
91 #define CODE_RATE_LONGTEXT N_( \
92     "The code rate for Forward Error Correction can be specified.")
93 static const char *const code_rate_vlc[] = { "",
94     "0", /*"1/4", "1/3",*/ "1/2", "3/5", "2/3", "3/4",
95     "4/5", "5/6", "6/7", "7/8", "8/9", "9/10",
96 };
97 static const char *const code_rate_user[] = { N_("Automatic"),
98     N_("None"), /*"1/4", "1/3",*/ "1/2", "3/5", "2/3", "3/4",
99     "4/5", "5/6", "6/7", "7/8", "8/9", "9/10",
100 };
101
102 #define TRANSMISSION_TEXT N_("Transmission mode")
103 const int transmission_vlc[] = { -1,
104     2, 4, 8, /*16, 32,*/
105 };
106 static const char *const transmission_user[] = { N_("Automatic"),
107     "2k", "4k", "8k", /*"16k", "32k", */
108 };
109
110 #define BANDWIDTH_TEXT N_("Bandwidth (MHz)")
111 const int bandwidth_vlc[] = { 0,
112     8, 7, 6,
113 };
114 static const char *const bandwidth_user[] = { N_("Automatic"),
115     N_("8 MHz"), N_("7 MHz"), N_("6 MHz"),
116 };
117
118 #define GUARD_TEXT N_("Guard interval")
119 const char *const guard_vlc[] = { "",
120     /*"1/128",*/ "1/32", "1/16", /*"19/128",*/ "1/8", /*"9/256",*/ "1/4",
121 };
122 static const char *const guard_user[] = { N_("Automatic"),
123     /*"1/128",*/ "1/32", "1/16", /*"19/128",*/ "1/8", /*"9/256",*/ "1/4",
124 };
125
126 #define HIERARCHY_TEXT N_("Hierarchy mode")
127 const int hierarchy_vlc[] = { -1,
128     0, 1, 2, 4,
129 };
130 static const char *const hierarchy_user[] = { N_("Automatic"),
131     N_("None"), "1", "2", "4",
132 };
133
134 #define PILOT_TEXT N_("Pilot")
135
136 #define ROLLOFF_TEXT N_("Roll-off factor")
137 const int rolloff_vlc[] = { -1,
138     35, 20, 25,
139 };
140 static const char *const rolloff_user[] = { N_("Automatic"),
141     N_("0.35 (same as DVB-S)"), N_("0.20"), N_("0.25"),
142 };
143
144 #define POLARIZATION_TEXT N_("Polarization (Voltage)")
145 #define POLARIZATION_LONGTEXT N_( \
146     "To select the polarization of the transponder, a different voltage " \
147     "is normally applied to the low noise block-downconverter (LNB).")
148 static const char *const polarization_vlc[] = { "", "V", "H", "R", "L" };
149 static const char *const polarization_user[] = { N_("Unspecified (0V)"),
150     N_("Vertical (13V)"), N_("Horizontal (18V)"),
151     N_("Circular Right Hand (13V)"), N_("Circular Left Hand (18V)") };
152
153 #define HIGH_VOLTAGE_TEXT N_("High LNB voltage")
154 #define HIGH_VOLTAGE_LONGTEXT N_( \
155     "If the cables between the satellilte low noise block-downconverter and " \
156     "the receiver are long, higher voltage may be required.\n" \
157     "Not all receivers support this.")
158
159 #define LNB_LOW_TEXT N_("Local oscillator low frequency (kHz)")
160 #define LNB_HIGH_TEXT N_("Local oscillator high frequency (kHz)")
161 #define LNB_LONGTEXT N_( \
162     "The downconverter (LNB) will substract the local oscillator frequency " \
163     "from the satellite transmission frequency. " \
164     "The intermediate frequency (IF) on the RF cable is the result.")
165 #define LNB_SWITCH_TEXT N_("Universal LNB switch frequency (kHz)")
166 #define LNB_SWITCH_LONGTEXT N_( \
167     "If the satellite transmission frequency exceeds the switch frequency, " \
168     "the oscillator high frequency will be used as reference. " \
169     "Furthermore the automatic continuous 22kHz tone will be sent.")
170 #define TONE_TEXT N_("Continuous 22kHz tone")
171 #define TONE_LONGTEXT N_( \
172     "A continuous tone at 22kHz can be sent on the cable. " \
173     "This normally selects the higher frequency band from a universal LNB.")
174
175 #define SATNO_TEXT N_("DiSEqC LNB number")
176 #define SATNO_LONGTEXT N_( \
177     "If the satellite receiver is connected to multiple " \
178     "low noise block-downconverters (LNB) through a DiSEqC 1.0 switch, " \
179     "the correct LNB can be selected (1 to 4). " \
180     "If there is no switch, this parameter should be 0.")
181 #ifdef __linux__
182 static const int satno_vlc[] = { 0, 1, 2, 3, 4 };
183 static const char *const satno_user[] = { N_("Unspecified"),
184     "A/1", "B/2", "C/3", "D/4" };
185 #endif
186
187 static int  Open (vlc_object_t *);
188 static void Close (vlc_object_t *);
189
190 vlc_module_begin ()
191     set_shortname (N_("DTV"))
192     set_description (N_("Digital Television and Radio (Linux DVB)"))
193     set_category (CAT_INPUT)
194     set_subcategory (SUBCAT_INPUT_ACCESS)
195     set_capability ("access", 0)
196     set_callbacks (Open, Close)
197     add_shortcut ("dtv", "tv", "dvb", /* "radio", "dab",*/
198                   "cable", "dvb-c", "satellite", "dvb-s", "dvb-s2",
199                   "terrestrial", "dvb-t", "atsc", "cqam")
200
201     /* All options starting with dvb- can be overriden in the MRL, so they
202      * must all be "safe". Nevertheless, we do not mark as safe those that are
203      * really specific to the local system (e.g. device ID...).
204      * It wouldn't make sense to deliver those through a playlist. */
205
206     add_integer ("dvb-caching", DEFAULT_PTS_DELAY / 1000,
207                  CACHING_TEXT, CACHING_LONGTEXT, true)
208         change_integer_range (0, 60000)
209         change_safe ()
210 #ifdef __linux__
211     add_integer ("dvb-adapter", 0, ADAPTER_TEXT, ADAPTER_LONGTEXT, false)
212         change_integer_range (0, 255)
213     add_integer ("dvb-device", 0, DEVICE_TEXT, DEVICE_LONGTEXT, false)
214         change_integer_range (0, 255)
215     add_bool ("dvb-budget-mode", false, BUDGET_TEXT, BUDGET_LONGTEXT, true)
216 #endif
217     add_integer ("dvb-frequency", 0, FREQ_TEXT, FREQ_LONGTEXT, false)
218         change_integer_range (0, 107999999)
219         change_safe ()
220     add_integer ("dvb-inversion", -1, INVERSION_TEXT, INVERSION_LONGTEXT, true)
221         change_integer_list (auto_off_on_vlc, auto_off_on_user)
222         change_safe ()
223
224     set_section (N_("Terrestrial reception parameters"), NULL)
225     add_integer ("dvb-bandwidth", 0, BANDWIDTH_TEXT, BANDWIDTH_TEXT, true)
226         change_integer_list (bandwidth_vlc, bandwidth_user)
227         change_safe ()
228     add_string ("dvb-code-rate-hp", "",
229                 CODE_RATE_HP_TEXT, CODE_RATE_LONGTEXT, false)
230         change_string_list (code_rate_vlc, code_rate_user, NULL)
231         change_safe ()
232     add_string ("dvb-code-rate-lp", "",
233                 CODE_RATE_LP_TEXT, CODE_RATE_LONGTEXT, false)
234         change_string_list (code_rate_vlc, code_rate_user, NULL)
235         change_safe ()
236     add_integer ("dvb-transmission", 0,
237                  TRANSMISSION_TEXT, TRANSMISSION_TEXT, true)
238         change_integer_list (transmission_vlc, transmission_user)
239         change_safe ()
240     add_string ("dvb-guard", "", GUARD_TEXT, GUARD_TEXT, true)
241         change_string_list (guard_vlc, guard_user, NULL)
242         change_safe ()
243     add_integer ("dvb-hierarchy", -1, HIERARCHY_TEXT, HIERARCHY_TEXT, true)
244         change_integer_list (hierarchy_vlc, hierarchy_user)
245         change_safe ()
246
247     set_section (N_("Cable and satellite reception parameters"), NULL)
248     add_string ("dvb-modulation", 0,
249                  MODULATION_TEXT, MODULATION_LONGTEXT, false)
250         change_string_list (modulation_vlc, modulation_user, NULL)
251         change_safe ()
252     add_integer ("dvb-srate", 0, SRATE_TEXT, SRATE_LONGTEXT, false)
253         change_integer_range (0, UINT64_C(0xffffffff))
254         change_safe ()
255     add_string ("dvb-fec", "", CODE_RATE_TEXT, CODE_RATE_LONGTEXT, true)
256         change_string_list (code_rate_vlc, code_rate_user, NULL)
257         change_safe ()
258     set_section (N_("DVB-S2 parameters"), NULL)
259     add_integer ("dvb-pilot", -1, PILOT_TEXT, PILOT_TEXT, true)
260         change_integer_list (auto_off_on_vlc, auto_off_on_user)
261         change_safe ()
262     add_integer ("dvb-rolloff", -1, ROLLOFF_TEXT, ROLLOFF_TEXT, true)
263         change_integer_list (rolloff_vlc, rolloff_user)
264         change_safe ()
265     set_section (N_("Satellite equipment control"), NULL)
266     add_string ("dvb-polarization", "",
267                 POLARIZATION_TEXT, POLARIZATION_LONGTEXT, false)
268         change_string_list (polarization_vlc, polarization_user, NULL)
269         change_safe ()
270     add_integer ("dvb-voltage", 13, " ", " ", true)
271         change_integer_range (0, 18)
272         change_private ()
273         change_safe ()
274 #ifdef __linux__
275     add_bool ("dvb-high-voltage", false,
276               HIGH_VOLTAGE_TEXT, HIGH_VOLTAGE_LONGTEXT, false)
277 #endif
278     add_integer ("dvb-lnb-low", 0, LNB_LOW_TEXT, LNB_LONGTEXT, true)
279         change_integer_range (0, 0x7fffffff)
280         add_deprecated_alias ("dvb-lnb-lof1")
281     add_integer ("dvb-lnb-high", 0, LNB_HIGH_TEXT, LNB_LONGTEXT, true)
282         change_integer_range (0, 0x7fffffff)
283         add_deprecated_alias ("dvb-lnb-lof2")
284     add_integer ("dvb-lnb-switch", 11700000,
285                  LNB_SWITCH_TEXT, LNB_SWITCH_LONGTEXT, true)
286         change_integer_range (0, 0x7fffffff)
287         add_deprecated_alias ("dvb-lnb-slof")
288 #ifdef __linux
289     add_integer ("dvb-satno", 0, SATNO_TEXT, SATNO_LONGTEXT, true)
290         change_integer_list (satno_vlc, satno_user)
291 #endif
292     add_integer ("dvb-tone", -1, TONE_TEXT, TONE_LONGTEXT, true)
293         change_integer_list (auto_off_on_vlc, auto_off_on_user)
294 vlc_module_end ()
295
296 struct access_sys_t
297 {
298     dvb_device_t *dev;
299 };
300
301 struct delsys
302 {
303     int (*setup) (vlc_object_t *, dvb_device_t *, unsigned freq);
304     /* TODO: scan stuff */
305 };
306
307 static block_t *Read (access_t *);
308 static int Control (access_t *, int, va_list);
309 static const delsys_t *GuessSystem (const char *, dvb_device_t *);
310 static int Tune (vlc_object_t *, dvb_device_t *, const delsys_t *, unsigned);
311 static unsigned var_InheritFrequency (vlc_object_t *);
312
313 static int Open (vlc_object_t *obj)
314 {
315     access_t *access = (access_t *)obj;
316     access_sys_t *sys = malloc (sizeof (*sys));
317     if (unlikely(sys == NULL))
318         return VLC_ENOMEM;
319
320     var_LocationParse (obj, access->psz_location, "dvb-");
321     unsigned freq = var_InheritFrequency (obj);
322
323     dvb_device_t *dev = dvb_open (obj, freq != 0);
324     if (dev == NULL)
325     {
326         free (sys);
327         return VLC_EGENERIC;
328     }
329
330     sys->dev = dev;
331     access->p_sys = sys;
332
333     if (freq != 0)
334     {
335         const delsys_t *delsys = GuessSystem (access->psz_access, dev);
336         if (delsys == NULL || Tune (obj, dev, delsys, freq))
337         {
338             msg_Err (obj, "tuning to %u kHz failed", freq);
339             dialog_Fatal (obj, N_("Digital broadcasting"),
340                           N_("The selected digital tuner does not support "
341                              "the specified parameters.\n"
342                              "Please check the preferences."));
343             goto error;
344         }
345     }
346     dvb_add_pid (dev, 0);
347
348     access->pf_block = Read;
349     access->pf_control = Control;
350     if (access->psz_demux == NULL || !access->psz_demux[0])
351     {
352         free (access->psz_demux);
353         access->psz_demux = strdup ("ts");
354     }
355     return VLC_SUCCESS;
356
357 error:
358     Close (obj);
359     access->p_sys = NULL;
360     return VLC_EGENERIC;
361 }
362
363 static void Close (vlc_object_t *obj)
364 {
365     access_t *access = (access_t *)obj;
366     access_sys_t *sys = access->p_sys;
367
368     dvb_close (sys->dev);
369     free (sys);
370 }
371
372 static block_t *Read (access_t *access)
373 {
374 #define BUFSIZE (20*188)
375     block_t *block = block_Alloc (BUFSIZE);
376     if (unlikely(block == NULL))
377         return NULL;
378
379     access_sys_t *sys = access->p_sys;
380     ssize_t val = dvb_read (sys->dev, block->p_buffer, BUFSIZE);
381
382     if (val <= 0)
383     {
384         if (val == 0)
385             access->info.b_eof = true;
386         block_Release (block);
387         return NULL;
388     }
389
390     block->i_buffer = val;
391     return block;
392 }
393
394 static int Control (access_t *access, int query, va_list args)
395 {
396     access_sys_t *sys = access->p_sys;
397     dvb_device_t *dev = sys->dev;
398
399     switch (query)
400     {
401         case ACCESS_CAN_SEEK:
402         case ACCESS_CAN_FASTSEEK:
403         case ACCESS_CAN_PAUSE:
404         case ACCESS_CAN_CONTROL_PACE:
405         {
406             bool *v = va_arg (args, bool *);
407             *v = false;
408             return VLC_SUCCESS;
409         }
410
411         case ACCESS_GET_PTS_DELAY:
412         {
413             int64_t *v = va_arg (args, int64_t *);
414             *v = var_InheritInteger (access, "dvb-caching") * INT64_C(1000);
415             return VLC_SUCCESS;
416         }
417
418         case ACCESS_GET_TITLE_INFO:
419         case ACCESS_GET_META:
420             return VLC_EGENERIC;
421
422         case ACCESS_GET_CONTENT_TYPE:
423         {
424             char **pt = va_arg (args, char **);
425             *pt = strdup ("video/MP2T");
426             return VLC_SUCCESS;
427         }
428
429         case ACCESS_SET_PAUSE_STATE:
430         case ACCESS_SET_TITLE:
431         case ACCESS_SET_SEEKPOINT:
432             return VLC_EGENERIC;
433
434         case ACCESS_GET_SIGNAL:
435             *va_arg (args, double *) = dvb_get_snr (dev);
436             *va_arg (args, double *) = dvb_get_signal_strength (dev);
437             return VLC_SUCCESS;
438
439         case ACCESS_SET_PRIVATE_ID_STATE:
440         {
441             unsigned pid = va_arg (args, unsigned);
442             bool add = va_arg (args, unsigned);
443
444             if (unlikely(pid > 0x1FFF))
445                 return VLC_EGENERIC;
446             if (add)
447             {
448                 if (dvb_add_pid (dev, pid))
449                     return VLC_EGENERIC;
450             }
451             else
452                 dvb_remove_pid (dev, pid);
453             return VLC_SUCCESS;
454         }
455
456         case ACCESS_SET_PRIVATE_ID_CA:
457             /* TODO */
458             return VLC_EGENERIC;
459
460         case ACCESS_GET_PRIVATE_ID_STATE:
461             return VLC_EGENERIC;
462     }
463
464     msg_Warn (access, "unimplemented query %d in control", query);
465     return VLC_EGENERIC;
466 }
467
468
469 /*** Generic tuning ***/
470
471 /** Determines which delivery system to use. */
472 static const delsys_t *GuessSystem (const char *scheme, dvb_device_t *dev)
473 {
474     /* NOTE: We should guess the delivery system for the "cable", "satellite"
475      * and "terrestrial" shortcuts (i.e. DVB, ISDB, ATSC...). But there is
476      * seemingly no sane way to do get the info with Linux DVB version 5.2.
477      * In particular, the frontend infos distinguish only the modulator class
478      * (QPSK, QAM, OFDM or ATSC).
479      *
480      * Furthermore, if the demodulator supports 2G, we cannot guess whether
481      * 1G or 2G is intended. For backward compatibility, 1G is assumed
482      * (this is not a limitation of Linux DVB). We will probably need something
483      * smarter when 2G (semi automatic) scanning is implemented. */
484     if (!strcasecmp (scheme, "cable"))
485         scheme = "dvb-c";
486     else
487     if (!strcasecmp (scheme, "satellite"))
488         scheme = "dvb-s";
489     else
490     if (!strcasecmp (scheme, "terrestrial"))
491         scheme = "dvb-t";
492
493     if (!strcasecmp (scheme, "atsc"))
494         return &atsc;
495     if (!strcasecmp (scheme, "cqam"))
496         return &cqam;
497     if (!strcasecmp (scheme, "dvb-c"))
498         return &dvbc;
499     if (!strcasecmp (scheme, "dvb-s"))
500         return &dvbs;
501     if (!strcasecmp (scheme, "dvb-s2"))
502         return &dvbs2;
503     if (!strcasecmp (scheme, "dvb-t"))
504         return &dvbt;
505
506     return dvb_guess_system (dev);
507 }
508
509 /** Set parameters and tune the device */
510 static int Tune (vlc_object_t *obj, dvb_device_t *dev, const delsys_t *delsys,
511                  unsigned freq)
512 {
513     if (delsys->setup (obj, dev, freq)
514      || dvb_set_inversion (dev, var_InheritInteger (obj, "dvb-inversion"))
515      || dvb_tune (dev))
516         return VLC_EGENERIC;
517     return VLC_SUCCESS;
518 }
519
520 static unsigned var_InheritFrequency (vlc_object_t *obj)
521 {
522     unsigned freq = var_InheritInteger (obj, "dvb-frequency");
523     if (freq >= 108000000)
524     {
525         msg_Err (obj, "%u kHz frequency is too high.", freq);
526         freq /= 1000;
527         msg_Info (obj, "Assuming %u kHz carrier frequency instead.", freq);
528     }
529     return freq;
530 }
531
532 static uint32_t var_InheritCodeRate (vlc_object_t *obj, const char *varname)
533 {
534     char *code_rate = var_InheritString (obj, varname);
535     if (code_rate == NULL)
536         return VLC_FEC_AUTO;
537
538     uint16_t a, b;
539     int v = sscanf (code_rate, "%"SCNu16"/%"SCNu16, &a, &b);
540     free (code_rate);
541     switch (v)
542     {
543         case 2:
544             return VLC_FEC(a, b);
545         case 1:
546             if (a == 0)
547                 return 0;
548             /* Backward compatibility with VLC < 1.2 (= Linux DVBv3 enum) */
549             if (a < 9)
550             {
551                 msg_Warn (obj, "\"%s=%"PRIu16"\" option is obsolete. "
552                           "Use \"%s=%"PRIu16"/%"PRIu16"\" instead.",
553                           varname + 4, a, varname + 4, a, a + 1);
554                 return VLC_FEC(a, a + 1);
555             }
556             else
557                 msg_Warn (obj, "\"fec=9\" option is obsolete.");
558     }
559     return VLC_FEC_AUTO;
560 }
561
562 static char *var_InheritModulation (vlc_object_t *obj)
563 {
564     char *mod = var_InheritString (obj, "dvb-modulation");
565     if (mod == NULL)
566         return mod;
567
568     char *end;
569     unsigned long l = strtol (mod, &end, 0);
570     if (*end != '\0') /* not a number = not from VLC < 1.2 */
571         return mod;
572
573     /* Backward compatibility with VLC < 1.2 */
574     const char *str;
575     switch (l)
576     {
577         case -1:  str = "QPSK";   break;
578         case 0:   str = "QAM";    break;
579         case 8:   str = "8VSB";   break;
580         case 16:  str = "16QAM";  break;
581         case 32:  str = "32QAM";  break;
582         case 64:  str = "64QAM";  break;
583         case 128: str = "128QAM"; break;
584         case 256: str = "256QAM"; break;
585         default:  return mod;
586     }
587
588     msg_Warn (obj, "\"modulation=%ld\" option is obsolete. "
589                    "Use \"modulation=%s\" instead.", l, str);
590     return strdup (str);
591 }
592
593 static unsigned var_InheritGuardInterval (vlc_object_t *obj)
594 {
595     char *guard = var_InheritString (obj, "dvb-guard");
596     if (guard == NULL)
597         return VLC_GUARD_AUTO;
598
599     uint16_t a, b;
600     int v = sscanf (guard, "%"SCNu16"/%"SCNu16, &a, &b);
601     free (guard);
602     switch (v)
603     {
604         case 1:
605             /* Backward compatibility with VLC < 1.2 */
606             if (a == 0)
607                 break;
608             msg_Warn (obj, "\"guard=%"PRIu16"\" option is obsolete. "
609                            "Use \"guard=1/%"PRIu16" instead.", a, a);
610             b = a;
611             a = 1;
612         case 2:
613             return VLC_GUARD(a, b);
614     }
615     return VLC_GUARD_AUTO;
616 }
617
618
619 /*** ATSC ***/
620 static int atsc_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
621 {
622     char *mod = var_InheritModulation (obj);
623
624     int ret = dvb_set_atsc (dev, freq, mod);
625     free (mod);
626     return ret;
627 }
628
629 const delsys_t atsc = { .setup = atsc_setup };
630
631 static int cqam_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
632 {
633     char *mod = var_InheritModulation (obj);
634
635     int ret = dvb_set_cqam (dev, freq, mod);
636     free (mod);
637     return ret;
638 }
639
640 const delsys_t cqam = { .setup = cqam_setup };
641
642
643 /*** DVB-C ***/
644 static int dvbc_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
645 {
646     char *mod = var_InheritModulation (obj);
647     uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
648     unsigned srate = var_InheritInteger (obj, "dvb-srate");
649
650     int ret = dvb_set_dvbc (dev, freq, mod, srate, fec);
651     free (mod);
652     return ret;
653 }
654
655 const delsys_t dvbc = { .setup = dvbc_setup };
656
657
658 /*** DVB-S ***/
659 static char var_InheritPolarization (vlc_object_t *obj)
660 {
661     char pol;
662     char *polstr = var_InheritString (obj, "dvb-polarization");
663     if (polstr != NULL)
664     {
665         pol = *polstr;
666         free (polstr);
667         if (unlikely(pol >= 'a' && pol <= 'z'))
668             pol -= 'a' - 'A';
669         return pol;
670     }
671
672     /* Backward compatibility with VLC for Linux < 1.2 */
673     unsigned voltage = var_InheritInteger (obj, "dvb-voltage");
674     switch (voltage)
675     {
676         case 13:  pol = 'V'; break;
677         case 18:  pol = 'H'; break;
678         default:  return 0;
679     }
680
681     msg_Warn (obj, "\"voltage=%u\" option is obsolete. "
682                    "Use \"polarization=%c\" instead.", voltage, pol);
683     return pol;
684 }
685
686 static int sec_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
687 {
688     char pol = var_InheritPolarization (obj);
689     unsigned lowf = var_InheritInteger (obj, "dvb-lnb-low");
690     unsigned highf = var_InheritInteger (obj, "dvb-lnb-high");
691     unsigned switchf = var_InheritInteger (obj, "dvb-lnb-switch");
692
693     return dvb_set_sec (dev, freq, pol, lowf, highf, switchf);
694 }
695
696 static int dvbs_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
697 {
698     uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
699     uint32_t srate = var_InheritInteger (obj, "dvb-srate");
700
701     int ret = dvb_set_dvbs (dev, freq, srate, fec);
702     if (ret == 0)
703         ret = sec_setup (obj, dev, freq);
704     return ret;
705 }
706
707 static int dvbs2_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
708 {
709     char *mod = var_InheritModulation (obj);
710     uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
711     uint32_t srate = var_InheritInteger (obj, "dvb-srate");
712     int pilot = var_InheritInteger (obj, "dvb-pilot");
713     int rolloff = var_InheritInteger (obj, "dvb-rolloff");
714
715     int ret = dvb_set_dvbs2 (dev, freq, mod, srate, fec, pilot, rolloff);
716     free (mod);
717     if (ret == 0)
718         ret = sec_setup (obj, dev, freq);
719     return ret;
720 }
721
722 const delsys_t dvbs = { .setup = dvbs_setup };
723 const delsys_t dvbs2 = { .setup = dvbs2_setup };
724
725
726 /*** DVB-T ***/
727 static int dvbt_setup (vlc_object_t *obj, dvb_device_t *dev, unsigned freq)
728 {
729     char *mod = var_InheritModulation (obj);
730     uint32_t fec_hp = var_InheritCodeRate (obj, "dvb-code-rate-hp");
731     uint32_t fec_lp = var_InheritCodeRate (obj, "dvb-code-rate-lp");
732     uint32_t guard = var_InheritGuardInterval (obj);
733     uint32_t bw = var_InheritInteger (obj, "dvb-bandwidth");
734     int tx = var_InheritInteger (obj, "dvb-transmission");
735     int h = var_InheritInteger (obj, "dvb-hierarchy");
736
737     int ret = dvb_set_dvbt (dev, freq, mod, fec_hp, fec_lp, bw, tx, guard, h);
738     free (mod);
739     return ret;
740 }
741
742 const delsys_t dvbt = { .setup = dvbt_setup };