]> git.sesse.net Git - vlc/blob - modules/access/dtv/access.c
DTV: factorize tuning and add spectral inversion
[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 (Hz)")
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 inversion_vlc[] = { -1, 0, 1 };
85 static const char *const auto_off_on[] = { 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     "none", /*"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 static int  Open (vlc_object_t *);
135 static void Close (vlc_object_t *);
136
137 vlc_module_begin ()
138     set_shortname (N_("DTV"))
139     set_description (N_("Digital Television and Radio (Linux DVB)"))
140     set_category (CAT_INPUT)
141     set_subcategory (SUBCAT_INPUT_ACCESS)
142     set_capability ("access", 0)
143     set_callbacks (Open, Close)
144     add_shortcut ("dtv", "tv", "dvb", /* "radio", "dab",*/
145                   "cable", "dvb-c", /*"satellite", "dvb-s", "dvb-s2",*/
146                   "terrestrial", "dvb-t", "atsc")
147
148     /* All options starting with dvb- can be overriden in the MRL, so they
149      * must all be "safe". Nevertheless, we do not mark as safe those that are
150      * really specific to the local system (e.g. device ID...).
151      * It wouldn't make sense to deliver those through a playlist. */
152
153     add_integer ("dvb-caching", DEFAULT_PTS_DELAY / 1000,
154                  CACHING_TEXT, CACHING_LONGTEXT, true)
155         change_integer_range (0, 60000)
156         change_safe ()
157 #ifdef __linux__
158     add_integer ("dvb-adapter", 0, ADAPTER_TEXT, ADAPTER_LONGTEXT, false)
159         change_integer_range (0, 255)
160     add_integer ("dvb-device", 0, DEVICE_TEXT, DEVICE_LONGTEXT, false)
161         change_integer_range (0, 255)
162     add_bool ("dvb-budget-mode", false, BUDGET_TEXT, BUDGET_LONGTEXT, true)
163 #endif
164     add_integer ("dvb-frequency", 0, FREQ_TEXT, FREQ_LONGTEXT, false)
165         change_integer_range (0, UINT64_C(0xffffffff) * 1000)
166         change_safe ()
167     add_string ("dvb-modulation", 0,
168                  MODULATION_TEXT, MODULATION_LONGTEXT, false)
169         change_string_list (modulation_vlc, modulation_user, NULL)
170         change_safe ()
171     /* Legacy modulation option for backward compatibility: TODO */
172     /*add_integer ("dvb-modulation", 0, " ", " ", true)
173         change_integer_range (-1, 256)
174         change_private ()
175         change_safe ()*/
176     add_integer ("dvb-inversion", -1, INVERSION_TEXT, INVERSION_LONGTEXT, true)
177         change_integer_list (inversion_vlc, auto_off_on)
178         change_safe ()
179
180     set_section (N_("Terrestrial reception parameters"), NULL)
181     add_integer ("dvb-bandwidth", -1, BANDWIDTH_TEXT, BANDWIDTH_TEXT, true)
182         change_integer_list (bandwidth_vlc, bandwidth_user)
183         change_safe ()
184     add_string ("dvb-code-rate-hp", "",
185                 CODE_RATE_HP_TEXT, CODE_RATE_LONGTEXT, false)
186         change_string_list (code_rate_vlc, code_rate_user, NULL)
187         change_safe ()
188     add_string ("dvb-code-rate-lp", "",
189                 CODE_RATE_LP_TEXT, CODE_RATE_LONGTEXT, false)
190         change_string_list (code_rate_vlc, code_rate_user, NULL)
191         change_safe ()
192     add_integer ("dvb-transmission", 0,
193                  TRANSMISSION_TEXT, TRANSMISSION_TEXT, true)
194         change_integer_list (transmission_vlc, transmission_user)
195         change_safe ()
196     add_string ("dvb-guard", "", GUARD_TEXT, GUARD_TEXT, true)
197         change_string_list (guard_vlc, guard_user, NULL)
198         change_safe ()
199     add_integer ("dvb-hierarchy", -1, HIERARCHY_TEXT, HIERARCHY_TEXT, true)
200         change_integer_list (hierarchy_vlc, hierarchy_user)
201         change_safe ()
202
203     set_section (N_("Cable (DVB-C) and satellite (DVB-S) parameters"), NULL)
204     add_integer ("dvb-srate", 0, SRATE_TEXT, SRATE_LONGTEXT, false)
205         change_integer_range (0, UINT64_C(0xffffffff))
206         change_safe ()
207     add_string ("dvb-code-rate", "", CODE_RATE_TEXT, CODE_RATE_LONGTEXT, true)
208         change_string_list (code_rate_vlc, code_rate_user, NULL)
209         change_safe ()
210     /* Legacy FEC option for backward compatibility: TODO */
211     add_integer ("dvb-fec", 9, " ", " ", true)
212         change_integer_range (0, 9)
213         change_private ()
214         change_safe ()
215 #ifdef FIXME
216     set_section (N_("Satellite (DVB-S) parameters"), NULL)
217     add_integer ("dvb-satno", 0, SATNO_TEXT, SATNO_LONGTEXT, true)
218         change_integer_list (satno_vlc, satno_user)
219         change_safe ()
220     add_integer ("dvb-voltage", 13, VOLTAGE_TEXT, VOLTAGE_LONGTEXT, true)
221         change_integer_list (voltage_vlc, voltage_user)
222         change_safe ()
223     add_bool ("dvb-high-voltage", false,
224               HIGH_VOLTAGE_TEXT, HIGH_VOLTAGE_LONGTEXT, false)
225     add_integer ("dvb-tone", -1, TONE_TEXT, TONE_LONGTEXT, true)
226         change_integer_list (tone_vlc, auto_off_on)
227         change_safe ()
228     add_integer ("dvb-lnb-lof1", 0, LNB_LOF1_TEXT, LNB_LOF1_LONGTEXT, true)
229         change_integer_range (0, 0x7fffffff)
230         change_safe ()
231     add_integer ("dvb-lnb-lof2", 0, LNB_LOF2_TEXT, LNB_LOF2_LONGTEXT, true)
232         change_integer_range (0, 0x7fffffff)
233         change_safe ()
234     add_integer ("dvb-lnb-slof", 0, LNB_SLOF_TEXT, LNB_SLOF_LONGTEXT, true)
235         change_integer_range (0, 0x7fffffff)
236         change_safe ()
237 #endif
238 vlc_module_end ()
239
240 struct access_sys_t
241 {
242     dvb_device_t *dev;
243 };
244
245 struct delsys
246 {
247     int (*setup) (vlc_object_t *, dvb_device_t *, uint64_t freq);
248     /* TODO: scan stuff */
249 };
250
251 static block_t *Read (access_t *);
252 static int Control (access_t *, int, va_list);
253 static const delsys_t *GuessSystem (const char *, dvb_device_t *);
254 static int Tune (vlc_object_t *, dvb_device_t *, const delsys_t *, uint64_t);
255
256 static int Open (vlc_object_t *obj)
257 {
258     access_t *access = (access_t *)obj;
259     access_sys_t *sys = malloc (sizeof (*sys));
260     if (unlikely(sys == NULL))
261         return VLC_ENOMEM;
262
263     var_LocationParse (obj, access->psz_location, "dvb-");
264     uint64_t freq = var_InheritInteger (obj, "dvb-frequency");
265
266     dvb_device_t *dev = dvb_open (obj, freq != 0);
267     if (dev == NULL)
268     {
269         free (sys);
270         return VLC_EGENERIC;
271     }
272
273     sys->dev = dev;
274     access->p_sys = sys;
275
276     if (freq != 0)
277     {
278         const delsys_t *delsys = GuessSystem (access->psz_access, dev);
279         if (delsys == NULL || Tune (obj, dev, delsys, freq))
280         {
281             msg_Err (obj, "tuning to %"PRIu64" Hz failed", freq);
282             dialog_Fatal (obj, N_("Digital broadcasting"),
283                           N_("The selected digital tuner does not support "
284                              "the specified parameters.\n"
285                              "Please check the preferences."));
286             goto error;
287         }
288     }
289     dvb_add_pid (dev, 0);
290
291     access->pf_block = Read;
292     access->pf_control = Control;
293     if (access->psz_demux == NULL || !access->psz_demux[0])
294     {
295         free (access->psz_demux);
296         access->psz_demux = strdup ("ts");
297     }
298     return VLC_SUCCESS;
299
300 error:
301     Close (obj);
302     access->p_sys = NULL;
303     return VLC_EGENERIC;
304 }
305
306 static void Close (vlc_object_t *obj)
307 {
308     access_t *access = (access_t *)obj;
309     access_sys_t *sys = access->p_sys;
310
311     dvb_close (sys->dev);
312     free (sys);
313 }
314
315 static block_t *Read (access_t *access)
316 {
317 #define BUFSIZE (20*188)
318     block_t *block = block_Alloc (BUFSIZE);
319     if (unlikely(block == NULL))
320         return NULL;
321
322     access_sys_t *sys = access->p_sys;
323     ssize_t val = dvb_read (sys->dev, block->p_buffer, BUFSIZE);
324
325     if (val <= 0)
326     {
327         if (val == 0)
328             access->info.b_eof = true;
329         block_Release (block);
330         return NULL;
331     }
332
333     block->i_buffer = val;
334     return block;
335 }
336
337 static int Control (access_t *access, int query, va_list args)
338 {
339     access_sys_t *sys = access->p_sys;
340     dvb_device_t *dev = sys->dev;
341
342     switch (query)
343     {
344         case ACCESS_CAN_SEEK:
345         case ACCESS_CAN_FASTSEEK:
346         case ACCESS_CAN_PAUSE:
347         case ACCESS_CAN_CONTROL_PACE:
348         {
349             bool *v = va_arg (args, bool *);
350             *v = false;
351             return VLC_SUCCESS;
352         }
353
354         case ACCESS_GET_PTS_DELAY:
355         {
356             int64_t *v = va_arg (args, int64_t *);
357             *v = var_InheritInteger (access, "dvb-caching") * INT64_C(1000);
358             return VLC_SUCCESS;
359         }
360
361         case ACCESS_GET_TITLE_INFO:
362         case ACCESS_GET_META:
363             return VLC_EGENERIC;
364
365         case ACCESS_GET_CONTENT_TYPE:
366         {
367             char **pt = va_arg (args, char **);
368             *pt = strdup ("video/MP2T");
369             return VLC_SUCCESS;
370         }
371
372         case ACCESS_SET_PAUSE_STATE:
373         case ACCESS_SET_TITLE:
374         case ACCESS_SET_SEEKPOINT:
375             return VLC_EGENERIC;
376
377         case ACCESS_GET_SIGNAL:
378             *va_arg (args, double *) = dvb_get_snr (dev);
379             *va_arg (args, double *) = dvb_get_signal_strength (dev);
380             return VLC_SUCCESS;
381
382         case ACCESS_SET_PRIVATE_ID_STATE:
383         {
384             unsigned pid = va_arg (args, unsigned);
385             bool add = va_arg (args, unsigned);
386
387             if (unlikely(pid > 0x1FFF))
388                 return VLC_EGENERIC;
389             if (add)
390             {
391                 if (dvb_add_pid (dev, pid))
392                     return VLC_EGENERIC;
393             }
394             else
395                 dvb_remove_pid (dev, pid);
396             return VLC_SUCCESS;
397         }
398
399         case ACCESS_SET_PRIVATE_ID_CA:
400             /* TODO */
401             return VLC_EGENERIC;
402
403         case ACCESS_GET_PRIVATE_ID_STATE:
404             return VLC_EGENERIC;
405     }
406
407     msg_Warn (access, "unimplemented query %d in control", query);
408     return VLC_EGENERIC;
409 }
410
411
412 /*** Generic tuning ***/
413
414 /** Determines which delivery system to use. */
415 static const delsys_t *GuessSystem (const char *scheme, dvb_device_t *dev)
416 {
417     /* NOTE: We should guess the delivery system for the "cable", "satellite"
418      * and "terrestrial" shortcuts (i.e. DVB, ISDB, ATSC...). But there is
419      * seemingly no sane way to do get the info with Linux DVB version 5.2.
420      * In particular, the frontend infos distinguish only the modulator class
421      * (QPSK, QAM, OFDM or ATSC).
422      *
423      * Furthermore, if the demodulator supports 2G, we cannot guess whether
424      * 1G or 2G is intended. For backward compatibility, 1G is assumed
425      * (this is not a limitation of Linux DVB). We will probably need something
426      * smarter when 2G (semi automatic) scanning is implemented. */
427     if (!strcasecmp (scheme, "cable"))
428         scheme = "dvb-c";
429     else
430     if (!strcasecmp (scheme, "satellite"))
431         scheme = "dvb-s";
432     else
433     if (!strcasecmp (scheme, "terrestrial"))
434         scheme = "dvb-t";
435
436     if (!strcasecmp (scheme, "atsc"))
437         return &atsc;
438     if (!strcasecmp (scheme, "dvb-c"))
439         return &dvbc;
440     if (!strcasecmp (scheme, "dvb-s"))
441         return &dvbs;
442     if (!strcasecmp (scheme, "dvb-s2"))
443         return &dvbs2;
444     if (!strcasecmp (scheme, "dvb-t"))
445         return &dvbt;
446
447     return dvb_guess_system (dev);
448 }
449
450 /** Set parameters and tune the device */
451 static int Tune (vlc_object_t *obj, dvb_device_t *dev, const delsys_t *delsys,
452                  uint64_t freq)
453 {
454     if (delsys->setup (obj, dev, freq)
455      || dvb_set_inversion (dev, var_InheritInteger (obj, "dvb-inversion"))
456      || dvb_tune (dev))
457         return VLC_EGENERIC;
458     return VLC_SUCCESS;
459 }
460
461
462 /*** ATSC ***/
463 static int atsc_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
464 {
465     char *mod = var_InheritString (obj, "dvb-modulation");
466
467     int ret = dvb_set_atsc (dev, freq, mod);
468     free (mod);
469     return ret;
470 }
471
472 const delsys_t atsc = { .setup = atsc_setup };
473
474
475 /*** DVB-C ***/
476 static int dvbc_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
477 {
478     char *mod = var_InheritString (obj, "dvb-modulation");
479     char *fec = var_InheritString (obj, "dvb-code-rate");
480     unsigned srate = var_InheritInteger (obj, "dvb-srate");
481
482     int ret = dvb_set_dvbc (dev, freq, mod, srate, fec);
483     free (fec);
484     free (mod);
485     return ret;
486 }
487
488 const delsys_t dvbc = { .setup = dvbc_setup };
489
490
491 /*** DVB-S ***/
492 static int dvbs_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
493 {
494     (void) dev; (void) freq;
495     msg_Err (obj, "DVB-S not implemented");
496     return -1;
497 }
498
499 static int dvbs2_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
500 {
501     (void) dev; (void) freq;
502     msg_Err (obj, "DVB-S2 not implemented");
503     return -1;
504 }
505
506 const delsys_t dvbs = { .setup = dvbs_setup };
507 const delsys_t dvbs2 = { .setup = dvbs2_setup };
508
509
510 /*** DVB-T ***/
511 static int dvbt_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
512 {
513     char *mod = var_InheritString (obj, "dvb-modulation");
514     char *fec_hp = var_InheritString (obj, "dvb-code-rate-hp");
515     char *fec_lp = var_InheritString (obj, "dvb-code-rate-lp");
516     char *guard = var_InheritString (obj, "dvb-guard");
517     uint32_t bw = var_InheritInteger (obj, "dvb-bandwidth");
518     int tx = var_InheritInteger (obj, "dvb-transmission");
519     int h = var_InheritInteger (obj, "dvb-hierarchy");
520
521     int ret = dvb_set_dvbt (dev, freq, mod, fec_hp, fec_lp, bw, tx, guard, h);
522     free (guard);
523     free (fec_lp);
524     free (fec_hp);
525     free (mod);
526     return ret;
527 }
528
529 const delsys_t dvbt = { .setup = dvbt_setup };