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