]> git.sesse.net Git - vlc/blob - modules/access/dvb/scan.c
Remove WPL module
[vlc] / modules / access / dvb / scan.c
1 /*****************************************************************************
2  * scan.c: DVB scanner helpers
3  *****************************************************************************
4  * Copyright (C) 2008,2010 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@videolan.org>
7  *          David Kaplan <david@2of1.org>
8  *          Ilkka Ollakka <ileoo@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_block.h>
34 #include <vlc_dialog.h>
35 #include <vlc_fs.h>
36 #include <vlc_charset.h>
37 #include <vlc_access.h>
38
39 #include <sys/types.h>
40
41 /* Include dvbpsi headers */
42 #include <dvbpsi/dvbpsi.h>
43 #include <dvbpsi/descriptor.h>
44 #include <dvbpsi/pat.h>
45 #include <dvbpsi/pmt.h>
46 #include <dvbpsi/dr.h>
47 #include <dvbpsi/psi.h>
48 #include <dvbpsi/demux.h>
49 #include <dvbpsi/sdt.h>
50 #ifdef _DVBPSI_DR_43_H_
51 #   define DVBPSI_USE_NIT 1
52 #   include <dvbpsi/nit.h>
53 #endif
54
55 #include "dvb.h"
56 #include "scan.h"
57 #include "../../demux/dvb-text.h"
58 #include "../../mux/mpeg/dvbpsi_compat.h"
59
60 typedef enum
61 {
62     SERVICE_UNKNOWN = 0,
63     SERVICE_DIGITAL_RADIO,
64     SERVICE_DIGITAL_TELEVISION,
65     SERVICE_DIGITAL_TELEVISION_AC_SD,
66     SERVICE_DIGITAL_TELEVISION_AC_HD,
67 } scan_service_type_t;
68
69 typedef struct
70 {
71     int  i_program;     /* program number (service id) */
72     scan_configuration_t cfg;
73     int i_snr;
74
75     scan_service_type_t type;
76     char *psz_name;     /* channel name in utf8 or NULL */
77     int  i_channel;     /* -1 if unknown */
78     bool b_crypted;     /* True if potentially crypted */
79
80     int i_network_id;
81
82     int i_nit_version;
83     int i_sdt_version;
84
85 } scan_service_t;
86
87 struct scan_t
88 {
89     vlc_object_t *p_obj;
90     struct dialog_progress_bar_t *p_dialog;
91     uint64_t i_index;
92     scan_parameter_t parameter;
93     int64_t i_time_start;
94
95     int            i_service;
96     scan_service_t **pp_service;
97 };
98
99 struct scan_session_t
100 {
101     vlc_object_t *p_obj;
102
103     scan_configuration_t cfg;
104     int i_snr;
105
106     dvbpsi_t *pat;
107     dvbpsi_pat_t *p_pat;
108     int i_nit_pid;
109
110     dvbpsi_t *sdt;
111     dvbpsi_sdt_t *p_sdt;
112
113 #ifdef DVBPSI_USE_NIT
114     dvbpsi_t *nit;
115     dvbpsi_nit_t *p_nit;
116 #else
117 #   warning NIT is not supported by your libdvbpsi version
118 #endif
119
120 };
121
122 /* */
123 static scan_service_t *scan_service_New( int i_program,
124                                          const scan_configuration_t *p_cfg )
125 {
126     scan_service_t *p_srv = malloc( sizeof(*p_srv) );
127     if( !p_srv )
128         return NULL;
129
130     p_srv->i_program = i_program;
131     p_srv->cfg = *p_cfg;
132     p_srv->i_snr = -1;
133
134     p_srv->type = SERVICE_UNKNOWN;
135     p_srv->psz_name = NULL;
136     p_srv->i_channel = -1;
137     p_srv->b_crypted = false;
138
139     p_srv->i_network_id = -1;
140     p_srv->i_nit_version = -1;
141     p_srv->i_sdt_version = -1;
142
143     return p_srv;
144 }
145
146 static void scan_service_Delete( scan_service_t *p_srv )
147 {
148     free( p_srv->psz_name );
149     free( p_srv );
150 }
151
152 static uint32_t decode_BCD( uint32_t input )
153 {
154     uint32_t output = 0;
155     for( short index=28; index >= 0 ; index -= 4 )
156     {
157         output *= 10;
158         output += ((input >> index) & 0x0f);
159     };
160     return output;
161 }
162
163 static int scan_service_type( int service_type )
164 {
165     switch( service_type )
166     {
167     case 0x01: return SERVICE_DIGITAL_TELEVISION; break;
168     case 0x02: return SERVICE_DIGITAL_RADIO; break;
169     case 0x16: return SERVICE_DIGITAL_TELEVISION_AC_SD; break;
170     case 0x19: return SERVICE_DIGITAL_TELEVISION_AC_HD; break;
171     default:   return SERVICE_UNKNOWN; break;
172     }
173 }
174
175 /* */
176 scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter )
177 {
178     if( p_parameter->type == SCAN_DVB_T )
179     {
180         msg_Dbg( p_obj, "DVB-T scanning:" );
181         msg_Dbg( p_obj, " - frequency [%d, %d]",
182                  p_parameter->frequency.i_min, p_parameter->frequency.i_max );
183         msg_Dbg( p_obj, " - bandwidth [%d,%d]",
184                  p_parameter->bandwidth.i_min, p_parameter->bandwidth.i_max );
185         msg_Dbg( p_obj, " - exhaustive mode %s", p_parameter->b_exhaustive ? "on" : "off" );
186     }
187     else if( p_parameter->type == SCAN_DVB_C )
188     {
189         msg_Dbg( p_obj, "DVB-C scanning:" );
190         msg_Dbg( p_obj, " - frequency [%d, %d]",
191                  p_parameter->frequency.i_min, p_parameter->frequency.i_max );
192         msg_Dbg( p_obj, " - bandwidth [%d,%d]",
193                  p_parameter->bandwidth.i_min, p_parameter->bandwidth.i_max );
194         msg_Dbg( p_obj, " - exhaustive mode %s", p_parameter->b_exhaustive ? "on" : "off" );
195         msg_Dbg( p_obj, " - scannin modulations %s", p_parameter->b_modulation_set ? "off" : "on" );
196     }
197     else if( p_parameter->type == SCAN_DVB_S )
198     {
199         msg_Dbg( p_obj, "DVB-S scanning:" );
200         msg_Dbg( p_obj, " - satellite [%s]", p_parameter->sat_info.psz_name );
201     }
202     else
203     {
204         return NULL;
205     }
206     msg_Dbg( p_obj, " - use NIT %s", p_parameter->b_use_nit ? "on" : "off" );
207     msg_Dbg( p_obj, " - FTA only %s", p_parameter->b_free_only ? "on" : "off" );
208
209     scan_t *p_scan = malloc( sizeof( *p_scan ) );
210     if( unlikely(p_scan == NULL) )
211         return NULL;
212
213     p_scan->p_obj = VLC_OBJECT(p_obj);
214     p_scan->i_index = 0;
215     p_scan->p_dialog = NULL;
216     TAB_INIT( p_scan->i_service, p_scan->pp_service );
217     p_scan->parameter = *p_parameter;
218     p_scan->i_time_start = mdate();
219
220     return p_scan;
221 }
222
223 void scan_Destroy( scan_t *p_scan )
224 {
225     if( p_scan->p_dialog != NULL )
226         dialog_ProgressDestroy( p_scan->p_dialog );
227
228     for( int i = 0; i < p_scan->i_service; i++ )
229         scan_service_Delete( p_scan->pp_service[i] );
230     TAB_CLEAN( p_scan->i_service, p_scan->pp_service );
231     free( p_scan );
232 }
233
234 static int ScanDvbSNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
235 {
236     msg_Dbg( p_scan->p_obj, "Scan index %"PRId64, p_scan->i_index );
237
238     unsigned *pi_count = &p_scan->parameter.sat_info.i_count;
239
240     if( !p_scan->parameter.sat_info.psz_name )
241     {
242         msg_Err( p_scan->p_obj, "no satellite selected" );
243         return VLC_EGENERIC;
244     }
245
246     /* if there are no transponders in mem, laod from config file */
247     if( !*pi_count )
248     {
249         DIR *p_dir;
250
251         char *psz_dir = NULL;
252         char *data_dir = config_GetDataDir();
253
254         if( asprintf( &psz_dir, "%s" DIR_SEP "dvb" DIR_SEP "dvb-s", data_dir ) == -1 )
255             psz_dir = NULL;
256         free( data_dir );
257
258         if( !psz_dir )
259         {
260             free( p_scan->parameter.sat_info.psz_name );
261             return VLC_EGENERIC;
262         }
263
264         /* open config directory */
265         if( !( p_dir = vlc_opendir( psz_dir ) ) )
266         {
267             msg_Err( p_scan->p_obj, "could not open satellite info directory (%s)", psz_dir );
268             free( p_scan->parameter.sat_info.psz_name );
269             return VLC_EGENERIC;
270         }
271
272         /* find the requested file in the directory */
273         for( ; ; ) {
274             const char *psz_filename = vlc_readdir( p_dir );
275
276             if( psz_filename == NULL )
277                 break;
278
279             if( !strncmp( p_scan->parameter.sat_info.psz_name, psz_filename, 20 ) )
280             {
281                 if( asprintf( &p_scan->parameter.sat_info.psz_path, "%s" DIR_SEP "%s", psz_dir, psz_filename ) == -1 )
282                     p_scan->parameter.sat_info.psz_path = NULL;
283                 break;
284             }
285         }
286
287         closedir( p_dir );
288
289         if( !p_scan->parameter.sat_info.psz_path )
290         {
291             msg_Err( p_scan->p_obj, "could not find satellite config (%s)", p_scan->parameter.sat_info.psz_name );
292             free( p_scan->parameter.sat_info.psz_name );
293             return VLC_EGENERIC;
294         }
295
296         msg_Dbg( p_scan->p_obj, "using satellite config file (%s)", p_scan->parameter.sat_info.psz_path );
297
298         FILE *f = vlc_fopen( p_scan->parameter.sat_info.psz_path, "r" );
299
300         /* parse file */
301         if( f )
302         {
303             scan_dvbs_transponder_t *p_transponders = malloc( sizeof( scan_dvbs_transponder_t ) );
304             char type;
305             char psz_fec[3];
306
307             int res;
308             do
309             {
310                 if ( ( res = fscanf( f, "%c %d %c %d %2s\n",
311                             &type,
312                             &p_transponders[*pi_count].i_frequency,
313                             &p_transponders[*pi_count].c_polarization,
314                             &p_transponders[*pi_count].i_symbol_rate,
315                             psz_fec ) ) != 5 )
316                 {
317                     msg_Dbg( p_scan->p_obj, "error parsing transponder from file" );
318                     continue;
319                 }
320
321                 /* decode fec */
322                 char psz_fec_list[] = "1/22/33/44/55/66/77/88/9";
323                 char *p_fec = strstr( psz_fec_list, psz_fec );
324                 if ( !p_fec )
325                     p_transponders[*pi_count].i_fec = 9;    /* FEC_AUTO */
326                 else
327                     p_transponders[*pi_count].i_fec = 1 + ( ( p_fec-psz_fec_list ) / 3 );
328
329                 (*pi_count)++;
330
331                 p_transponders = realloc(p_transponders, ( *pi_count + 1 ) * sizeof( scan_dvbs_transponder_t ) );
332             } while (res != EOF);
333
334             msg_Dbg( p_scan->p_obj, "parsed %d transponders from config", *pi_count);
335
336             fclose( f );
337             p_scan->parameter.sat_info.p_transponders = p_transponders;
338         }
339         else
340         {
341             msg_Err( p_scan->p_obj, "failed to open satellite file (%s)", p_scan->parameter.sat_info.psz_path );
342             free( p_scan->parameter.sat_info.psz_name );
343             free( p_scan->parameter.sat_info.psz_path );
344             return VLC_EGENERIC;
345         }
346         free( p_scan->parameter.sat_info.psz_name );
347         free( p_scan->parameter.sat_info.psz_path );
348     }
349
350     if( p_scan->i_index < *pi_count )
351     {
352         /* setup params for scan */
353         p_cfg->i_symbol_rate = p_scan->parameter.sat_info.p_transponders[p_scan->i_index].i_symbol_rate / 1000;
354         p_cfg->i_frequency = p_scan->parameter.sat_info.p_transponders[p_scan->i_index].i_frequency;
355         p_cfg->i_fec = p_scan->parameter.sat_info.p_transponders[p_scan->i_index].i_fec;
356         p_cfg->c_polarization = p_scan->parameter.sat_info.p_transponders[p_scan->i_index].c_polarization;
357
358         msg_Dbg( p_scan->p_obj,
359                  "transponder [%"PRId64"/%d]: frequency=%d, symbolrate=%d, fec=%d, polarization=%c",
360                  p_scan->i_index + 1,
361                  *pi_count,
362                  p_cfg->i_frequency,
363                  p_cfg->i_symbol_rate,
364                  p_cfg->i_fec,
365                  p_cfg->c_polarization );
366
367         *pf_pos = (double)p_scan->i_index / *pi_count;
368
369         return VLC_SUCCESS;
370     }
371
372     if( p_scan->parameter.sat_info.p_transponders )
373     {
374         free( p_scan->parameter.sat_info.p_transponders );
375         p_scan->parameter.sat_info.p_transponders = NULL;
376     }
377
378     return VLC_EGENERIC;
379 }
380
381 static int ScanDvbCNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
382 {
383     msg_Dbg( p_scan->p_obj, "Scan index %"PRId64, p_scan->i_index );
384     /* Values taken from dvb-scan utils frequency-files, sorted by how
385      * often they appear. This hopefully speeds up finding services. */
386     static const unsigned int frequencies[] = { 41000, 39400, 40200,
387     38600, 41800, 36200, 44200, 43400, 37000, 35400, 42600, 37800,
388     34600, 45800, 45000, 46600, 32200, 51400, 49000, 33800, 31400,
389     30600, 47400, 71400, 69000, 68200, 58600, 56200, 54600, 49800,
390     48200, 33000, 79400, 72200, 69800, 67400, 66600, 65000, 64200,
391     61000, 55400, 53000, 52200, 50600, 29800, 16200, 15400, 11300,
392     78600, 77000, 76200, 75400, 74600, 73800, 73000, 70600, 57800,
393     57000, 53800, 12100, 81000, 77800, 65800, 63400, 61800, 29000,
394     17000, 85000, 84200, 83400, 81800, 80200, 59400, 36900, 28300,
395     26600, 25800, 25000, 24200, 23400, 85800, 74800, 73200, 72800,
396     72400, 72000, 66000, 65600, 60200, 42500, 41700, 40900, 40100,
397     39300, 38500, 37775, 37700, 37200, 36100, 35600, 35300, 34700,
398     34500, 33900, 33700, 32900, 32300, 32100, 31500, 31300, 30500,
399     29900, 29700, 29100, 28950, 28200, 28000, 27500, 27400, 27200,
400     26700, 25900, 25500, 25100, 24300, 24100, 23500, 23200, 22700,
401     22600, 21900, 21800, 21100, 20300, 19500, 18700, 17900, 17100,
402     16300, 15500, 14700, 14600, 14500, 14300, 13900, 13700, 13100,
403     12900, 12500, 12300
404     };
405     enum { num_frequencies = (sizeof(frequencies)/sizeof(*frequencies)) };
406
407     if( p_scan->i_index < num_frequencies )
408     {
409         p_cfg->i_frequency = 10000 * ( frequencies[ p_scan->i_index ] );
410         *pf_pos = (double)(p_scan->i_index * 1000 +
411                            p_scan->parameter.i_symbolrate * 100 +
412                            (256 - (p_scan->parameter.i_modulation >> 4)) )
413                            / (num_frequencies * 1000 + 900 + 16);
414         return VLC_SUCCESS;
415     }
416     return VLC_EGENERIC;
417 }
418
419 static int ScanDvbNextExhaustive( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
420 {
421     if( p_scan->i_index > p_scan->parameter.frequency.i_count * p_scan->parameter.bandwidth.i_count )
422         return VLC_EGENERIC;
423
424     const int i_bi = p_scan->i_index % p_scan->parameter.bandwidth.i_count;
425     const int i_fi = p_scan->i_index / p_scan->parameter.bandwidth.i_count;
426
427     p_cfg->i_frequency = p_scan->parameter.frequency.i_min + i_fi * p_scan->parameter.frequency.i_step;
428     p_cfg->i_bandwidth = p_scan->parameter.bandwidth.i_min + i_bi * p_scan->parameter.bandwidth.i_step;
429
430     *pf_pos = (double)p_scan->i_index / p_scan->parameter.frequency.i_count;
431     return VLC_SUCCESS;
432 }
433
434 static int ScanDvbTNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
435 {
436     static const int i_band_count = 2;
437     static const struct
438     {
439         const char *psz_name;
440         int i_min;
441         int i_max;
442     }
443     band[2] =
444     {
445         { "VHF", 174, 230 },
446         { "UHF", 470, 862 },
447     };
448     const int i_offset_count = 5;
449     const int i_mhz = 1000000;
450
451     /* We will probe the whole band divided in all bandwidth possibility trying 
452      * i_offset_count offset around the position
453      */
454     for( ;; p_scan->i_index++ )
455     {
456
457         const int i_bi = p_scan->i_index % p_scan->parameter.bandwidth.i_count;
458         const int i_oi = (p_scan->i_index / p_scan->parameter.bandwidth.i_count) % i_offset_count;
459         const int i_fi = (p_scan->i_index / p_scan->parameter.bandwidth.i_count) / i_offset_count;
460
461         const int i_bandwidth = p_scan->parameter.bandwidth.i_min + i_bi * p_scan->parameter.bandwidth.i_step;
462         int i;
463
464         for( i = 0; i < i_band_count; i++ )
465         {
466             if( i_fi >= band[i].i_min && i_fi <= band[i].i_max )
467                 break;
468         }
469         if( i >=i_band_count )
470         {
471             if( i_fi > band[i_band_count-1].i_max )
472                 return VLC_EGENERIC;
473             continue;
474         }
475
476         const int i_frequency_min = band[i].i_min*i_mhz + i_bandwidth*i_mhz/2;
477         const int i_frequency_base = i_fi*i_mhz;
478
479         if( i_frequency_base >= i_frequency_min && ( i_frequency_base - i_frequency_min ) % ( i_bandwidth*i_mhz ) == 0 )
480         {
481             const int i_frequency = i_frequency_base + ( i_oi - i_offset_count/2 ) * p_scan->parameter.frequency.i_step;
482
483             if( i_frequency < p_scan->parameter.frequency.i_min ||
484                 i_frequency > p_scan->parameter.frequency.i_max )
485                 continue;
486
487             p_cfg->i_frequency = i_frequency;
488             p_cfg->i_bandwidth = i_bandwidth;
489
490             int i_current = 0, i_total = 0;
491             for( int i = 0; i < i_band_count; i++ )
492             {
493                 const int i_frag = band[i].i_max-band[i].i_min;
494
495                 if( i_fi >= band[i].i_min )
496                     i_current += __MIN( i_fi - band[i].i_min, i_frag );
497                 i_total += i_frag;
498             }
499
500             *pf_pos = (double)( i_current + (double)i_oi / i_offset_count ) / i_total;
501             return VLC_SUCCESS;
502         }
503     }
504 }
505
506 static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
507 {
508     bool b_servicefound = false;
509 #ifdef _DVBPSI_DR_44_H_
510     /* We iterate frequencies/modulations/symbolrates until we get first hit and find NIT,
511        from that we fill pp_service with configurations and after that we iterate over
512        pp_services for all that doesn't have name yet (tune to that cfg and get SDT and name
513        for channel).
514      */
515     for( int i = 0; i < p_scan->i_service; i++ )
516     {
517         /* We found radio/tv config that doesn't have a name,
518            lets tune to that mux
519          */
520         if( !p_scan->pp_service[i]->psz_name && ( p_scan->pp_service[i]->type != SERVICE_UNKNOWN ) )
521         {
522             p_cfg->i_frequency  = p_scan->pp_service[i]->cfg.i_frequency;
523             p_cfg->i_symbolrate = p_scan->pp_service[i]->cfg.i_symbolrate;
524             p_cfg->i_modulation = p_scan->pp_service[i]->cfg.i_modulation;
525             p_scan->i_index = i+1;
526             msg_Dbg( p_scan->p_obj, "iterating to freq: %u, symbolrate %u, "
527                      "modulation %u index %"PRId64"/%d",
528                      p_cfg->i_frequency, p_cfg->i_symbolrate, p_cfg->i_modulation, p_scan->i_index, p_scan->i_service );
529             *pf_pos = (double)i/p_scan->i_service;
530             return VLC_SUCCESS;
531         }
532     }
533     /* We should have iterated all channels by now */
534     if( p_scan->i_service )
535         return VLC_EGENERIC;
536 #else
537     /* fallback to old, so when we get one channe, use that
538        symbolrate/modulation until bitter end
539      */
540     for( int i=0; i < p_scan->i_service; i++ )
541     {
542         b_servicefound = p_scan->pp_service[i]->type != SERVICE_UNKNOWN;
543         if( b_servicefound )
544             break;
545     }
546 #endif
547
548     if( !b_servicefound )
549     {
550         bool b_rotate=true;
551         if( !p_scan->parameter.b_modulation_set )
552         {
553             p_scan->parameter.i_modulation = (p_scan->parameter.i_modulation >> 1 );
554             /* if we iterated all modulations, move on */
555             /* dvb utils dvb-c channels files seems to have only
556                QAM64...QAM256, so lets just iterate over those */
557             if( p_scan->parameter.i_modulation < 64)
558             {
559                 p_scan->parameter.i_modulation = 256;
560             } else {
561                 b_rotate=false;
562             }
563             msg_Dbg( p_scan->p_obj, "modulation %d ", p_scan->parameter.i_modulation);
564         }
565         if( !p_scan->parameter.b_symbolrate_set )
566         {
567             /* symbol rates from dvb-tools dvb-c files */
568             static const unsigned short symbolrates[] = {
569              6900, 6875, 6950
570              /* With DR_44 we can cover other symbolrates from NIT-info
571                 as all channel-seed files have atleast one channel that
572                 has one of these symbolrate
573               */
574 #ifndef _DVBPSI_DR_44_H_
575              ,7000, 3450, 6111,
576              6428, 6952, 5900, 5000
577 #endif
578              };
579
580             enum { num_symbols = (sizeof(symbolrates)/sizeof(*symbolrates)) };
581
582             /* if we rotated modulations, rotate symbolrate */
583             if( b_rotate )
584             {
585                 p_scan->parameter.i_symbolrate++;
586                 p_scan->parameter.i_symbolrate %= num_symbols;
587             }
588             p_cfg->i_symbolrate = 1000 * (symbolrates[ p_scan->parameter.i_symbolrate ] );
589             msg_Dbg( p_scan->p_obj, "symbolrate %d", p_cfg->i_symbolrate );
590             if( p_scan->parameter.i_symbolrate )
591                 b_rotate=false;
592         }
593         if( !b_rotate && p_scan->i_index )
594             p_scan->i_index--;
595     }
596     p_cfg->i_modulation = p_scan->parameter.i_modulation;
597     if( !p_cfg->i_symbolrate )
598         p_cfg->i_symbolrate = var_GetInteger( p_scan->p_obj, "dvb-srate" );
599
600     if( p_scan->parameter.b_exhaustive )
601         return ScanDvbNextExhaustive( p_scan, p_cfg, pf_pos );
602     else
603         return ScanDvbCNextFast( p_scan, p_cfg, pf_pos );
604 }
605
606 static int ScanDvbTNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
607 {
608     if( p_scan->parameter.b_exhaustive )
609         return ScanDvbNextExhaustive( p_scan, p_cfg, pf_pos );
610     else
611         return ScanDvbTNextFast( p_scan, p_cfg, pf_pos );
612 }
613
614 static int ScanDvbSNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
615 {
616     if( p_scan->parameter.b_exhaustive )
617         msg_Dbg( p_scan->p_obj, "no exhaustive svb-d scan mode" );
618
619     return ScanDvbSNextFast( p_scan, p_cfg, pf_pos );
620 }
621
622 int scan_Next( scan_t *p_scan, scan_configuration_t *p_cfg )
623 {
624     double f_position;
625     int i_ret;
626
627     if( scan_IsCancelled( p_scan ) )
628         return VLC_EGENERIC;
629
630     memset( p_cfg, 0, sizeof(*p_cfg) );
631     switch( p_scan->parameter.type )
632     {
633     case SCAN_DVB_T:
634         i_ret = ScanDvbTNext( p_scan, p_cfg, &f_position );
635         break;
636     case SCAN_DVB_C:
637         i_ret = ScanDvbCNext( p_scan, p_cfg, &f_position );
638         break;
639     case SCAN_DVB_S:
640         i_ret = ScanDvbSNext( p_scan, p_cfg, &f_position );
641         break;
642     default:
643         i_ret = VLC_EGENERIC;
644         break;
645     }
646
647     if( i_ret )
648         return i_ret;
649
650     char *psz_text;
651     int i_service = 0;
652
653     for( int i = 0; i < p_scan->i_service; i++ )
654     {
655         if( p_scan->pp_service[i]->psz_name )
656             i_service++;
657     }
658
659     const mtime_t i_eta = f_position > 0.005 ? (mdate() - p_scan->i_time_start) * ( 1.0 / f_position - 1.0 ) : -1;
660     char psz_eta[MSTRTIME_MAX_SIZE];
661
662     if( asprintf( &psz_text, _("%.1f MHz (%d services)\n~%s remaining"),
663                   (double)p_cfg->i_frequency / 1000000, i_service, secstotimestr( psz_eta, i_eta/1000000 ) ) >= 0 )
664     {
665         if( i_eta >= 0 )
666             msg_Info( p_scan->p_obj, "Scan ETA %s | %f", secstotimestr( psz_eta, i_eta/1000000 ), f_position * 100 );
667
668         if( p_scan->p_dialog == NULL )
669             p_scan->p_dialog = dialog_ProgressCreate( p_scan->p_obj, _("Scanning DVB"), psz_text, _("Cancel") );
670         if( p_scan->p_dialog != NULL )
671             dialog_ProgressSet( p_scan->p_dialog, psz_text, f_position );
672         free( psz_text );
673     }
674
675     p_scan->i_index++;
676     return VLC_SUCCESS;
677 }
678
679 bool scan_IsCancelled( scan_t *p_scan )
680 {
681     return p_scan->p_dialog && dialog_ProgressCancelled( p_scan->p_dialog );
682 }
683
684 static scan_service_t *ScanFindService( scan_t *p_scan, int i_service_start, int i_program )
685 {
686     for( int i = i_service_start; i < p_scan->i_service; i++ )
687     {
688         if( p_scan->pp_service[i]->i_program == i_program )
689             return p_scan->pp_service[i];
690     }
691     return NULL;
692 }
693
694 /* FIXME handle properly string (convert to utf8) */
695 static void PATCallBack( scan_session_t *p_session, dvbpsi_pat_t *p_pat )
696 {
697     vlc_object_t *p_obj = p_session->p_obj;
698
699     msg_Dbg( p_obj, "PATCallBack" );
700
701     /* */
702     if( p_session->p_pat && p_session->p_pat->b_current_next )
703     {
704         dvbpsi_pat_delete( p_session->p_pat );
705         p_session->p_pat = NULL;
706     }
707     if( p_session->p_pat )
708     {
709         dvbpsi_pat_delete( p_pat );
710         return;
711     }
712
713     dvbpsi_pat_program_t *p_program;
714
715     /* */
716     p_session->p_pat = p_pat;
717
718     /* */
719     msg_Dbg( p_obj, "new PAT ts_id=%d version=%d current_next=%d",
720              p_pat->i_ts_id, p_pat->i_version, p_pat->b_current_next );
721     for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
722     {
723         msg_Dbg( p_obj, "  * number=%d pid=%d", p_program->i_number, p_program->i_pid );
724         if( p_program->i_number == 0 )
725             p_session->i_nit_pid = p_program->i_pid;
726     }
727 }
728 static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
729 {
730     vlc_object_t *p_obj = p_session->p_obj;
731
732     msg_Dbg( p_obj, "SDTCallBack" );
733
734     if( p_session->p_sdt && p_session->p_sdt->b_current_next )
735     {
736         dvbpsi_sdt_delete( p_session->p_sdt );
737         p_session->p_sdt = NULL;
738     }
739     if( p_session->p_sdt )
740     {
741         dvbpsi_sdt_delete( p_sdt );
742         return;
743     }
744
745     /* */
746     p_session->p_sdt = p_sdt;
747
748     /* */
749     msg_Dbg( p_obj, "new SDT ts_id=%d version=%d current_next=%d network_id=%d",
750              p_sdt->i_extension,
751              p_sdt->i_version, p_sdt->b_current_next,
752              p_sdt->i_network_id );
753
754
755     dvbpsi_sdt_service_t *p_srv;
756     for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
757     {
758         dvbpsi_descriptor_t *p_dr;
759
760         msg_Dbg( p_obj, "  * service id=%d eit schedule=%d present=%d running=%d free_ca=%d",
761                  p_srv->i_service_id, p_srv->b_eit_schedule,
762                  p_srv->b_eit_present, p_srv->i_running_status,
763                  p_srv->b_free_ca );
764         for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
765         {
766             if( p_dr->i_tag == 0x48 )
767             {
768                 dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
769                 char str2[257];
770
771                 memcpy( str2, pD->i_service_name, pD->i_service_name_length );
772                 str2[pD->i_service_name_length] = '\0';
773
774                 msg_Dbg( p_obj, "    - type=%d name=%s",
775                          pD->i_service_type, str2 );
776             }
777             else
778             {
779                 msg_Dbg( p_obj, "    * dsc 0x%x", p_dr->i_tag );
780             }
781         }
782     }
783 }
784
785 #ifdef DVBPSI_USE_NIT
786 static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
787 {
788     vlc_object_t *p_obj = p_session->p_obj;
789     access_t *p_access = (access_t*)p_obj;
790     access_sys_t *p_sys = p_access->p_sys;
791     scan_t *p_scan = p_sys->scan;
792
793     msg_Dbg( p_obj, "NITCallBack" );
794     msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d",
795              p_nit->i_network_id, p_nit->i_version, p_nit->b_current_next );
796
797     /* */
798     if( p_session->p_nit && p_session->p_nit->b_current_next )
799     {
800         dvbpsi_nit_delete( p_session->p_nit );
801         p_session->p_nit = NULL;
802     }
803     if( p_session->p_nit )
804     {
805         dvbpsi_nit_delete( p_nit );
806         return;
807     }
808
809     /* */
810     p_session->p_nit = p_nit;
811
812     dvbpsi_descriptor_t *p_dsc;
813     for( p_dsc = p_nit->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
814     {
815         if( p_dsc->i_tag == 0x40 )
816         {
817             msg_Dbg( p_obj, "   * network name descriptor" );
818             char str1[257];
819
820             memcpy( str1, p_dsc->p_data, p_dsc->i_length );
821             str1[p_dsc->i_length] = '\0';
822             msg_Dbg( p_obj, "       * name %s", str1 );
823         }
824         else if( p_dsc->i_tag == 0x4a )
825         {
826             msg_Dbg( p_obj, "   * linkage descriptor" );
827             uint16_t i_ts_id = GetWBE( &p_dsc->p_data[0] );
828             uint16_t i_on_id = GetWBE( &p_dsc->p_data[2] );
829             uint16_t i_service_id = GetWBE( &p_dsc->p_data[4] );
830             int i_linkage_type = p_dsc->p_data[6];
831
832             msg_Dbg( p_obj, "       * ts_id %d", i_ts_id );
833             msg_Dbg( p_obj, "       * on_id %d", i_on_id );
834             msg_Dbg( p_obj, "       * service_id %d", i_service_id );
835             msg_Dbg( p_obj, "       * linkage_type %d", i_linkage_type );
836         }
837         else 
838         {
839             msg_Dbg( p_obj, "   * dsc 0x%x", p_dsc->i_tag );
840         }
841     }
842
843     dvbpsi_nit_ts_t *p_ts;
844     for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
845     {
846         msg_Dbg( p_obj, "   * ts ts_id=0x%x original_id=0x%x", p_ts->i_ts_id, p_ts->i_orig_network_id );
847
848         uint32_t i_private_data_id = 0;
849         dvbpsi_descriptor_t *p_dsc;
850         scan_configuration_t cfg, *p_cfg = &cfg;
851
852         memset(p_cfg,0,sizeof(*p_cfg));
853         for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
854         {
855             if( p_dsc->i_tag == 0x41 )
856             {
857                 msg_Dbg( p_obj, "       * service list descriptor" );
858                 for( int i = 0; i < p_dsc->i_length/3; i++ )
859                 {
860                     uint16_t i_service_id = GetWBE( &p_dsc->p_data[3*i+0] );
861                     uint8_t  i_service_type = p_dsc->p_data[3*i+2];
862                     msg_Dbg( p_obj, "           * service_id=%d type=%d", i_service_id, i_service_type );
863 #ifdef _DVBPSI_DR_44_H_
864                     if( (ScanFindService( p_scan, 0, i_service_id ) == NULL) &&
865                          scan_service_type( i_service_type ) != SERVICE_UNKNOWN )
866                     {
867                        scan_service_t *s = scan_service_New( i_service_id, p_cfg );
868                        s->type          = scan_service_type( i_service_type );
869                        s->i_network_id  = p_nit->i_network_id;
870                        s->i_nit_version = p_nit->i_version;
871                        TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
872                     }
873 #endif
874                 }
875             }
876             else if( p_dsc->i_tag == 0x5a )
877             {
878                 dvbpsi_terr_deliv_sys_dr_t *p_t = dvbpsi_DecodeTerrDelivSysDr( p_dsc );
879                 msg_Dbg( p_obj, "       * terrestrial delivery system" );
880                 msg_Dbg( p_obj, "           * centre_frequency 0x%x", p_t->i_centre_frequency  );
881                 msg_Dbg( p_obj, "           * bandwidth %d", 8 - p_t->i_bandwidth );
882                 msg_Dbg( p_obj, "           * constellation %d", p_t->i_constellation );
883                 msg_Dbg( p_obj, "           * hierarchy %d", p_t->i_hierarchy_information );
884                 msg_Dbg( p_obj, "           * code_rate hp %d lp %d", p_t->i_code_rate_hp_stream, p_t->i_code_rate_lp_stream );
885                 msg_Dbg( p_obj, "           * guard_interval %d", p_t->i_guard_interval );
886                 msg_Dbg( p_obj, "           * transmission_mode %d", p_t->i_transmission_mode );
887                 msg_Dbg( p_obj, "           * other_frequency_flag %d", p_t->i_other_frequency_flag );
888             }
889 #ifdef _DVBPSI_DR_44_H_
890             else if( p_dsc->i_tag == 0x44 )
891             {
892                 dvbpsi_cable_deliv_sys_dr_t *p_t = dvbpsi_DecodeCableDelivSysDr( p_dsc );
893                 msg_Dbg( p_obj, "       * Cable delivery system");
894
895                 p_cfg->i_frequency =  decode_BCD( p_t->i_frequency ) * 100;
896                 msg_Dbg( p_obj, "           * frequency %d", p_cfg->i_frequency );
897                 p_cfg->i_symbolrate =  decode_BCD( p_t->i_symbol_rate ) * 100;
898                 msg_Dbg( p_obj, "           * symbolrate %u", p_cfg->i_symbolrate );
899                 p_cfg->i_modulation = (8 << p_t->i_modulation);
900                 msg_Dbg( p_obj, "           * modulation %u", p_cfg->i_modulation );
901             }
902 #endif
903             else if( p_dsc->i_tag == 0x5f )
904             {
905                 msg_Dbg( p_obj, "       * private data specifier descriptor" );
906                 i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
907                 msg_Dbg( p_obj, "           * value 0x%8.8x", i_private_data_id );
908             }
909             else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
910             {
911                 msg_Dbg( p_obj, "       * logical channel descriptor (EICTA)" );
912                 for( int i = 0; i < p_dsc->i_length/4; i++ )
913                 {
914                     uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
915                     int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
916                     msg_Dbg( p_obj, "           * service_id=%d channel_number=%d", i_service_id, i_channel_number );
917                     scan_service_t *s = ScanFindService( p_scan, 0, i_service_id );
918                     if( s && s->i_channel < 0 ) s->i_channel = i_channel_number;
919                 }
920
921             }
922             else
923             {
924                 msg_Warn( p_obj, "       * dsc 0x%x", p_dsc->i_tag );
925             }
926         }
927     }
928 }
929 #endif
930
931 static void PSINewTableCallBack( dvbpsi_t *h, uint8_t i_table_id, uint16_t i_extension, void *p_data )
932 {
933     scan_session_t *p_session = (scan_session_t *)p_data;
934
935     if( i_table_id == 0x42 )
936     {
937         if( !dvbpsi_sdt_attach( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_session ) )
938             msg_Err( p_session->p_obj, "PSINewTableCallback: failed attaching SDTCallback" );
939     }
940     else if( i_table_id == 0x40 || i_table_id == 0x41 )
941     {
942         if( !dvbpsi_nit_attach( h, i_table_id, i_extension, (dvbpsi_nit_callback)NITCallBack, p_session ) )
943             msg_Err( p_session->p_obj, "PSINewTableCallback: failed attaching NITCallback" );
944     }
945 }
946
947 scan_session_t *scan_session_New( vlc_object_t *p_obj,
948                                   const scan_configuration_t *p_cfg )
949 {
950     scan_session_t *p_session = malloc( sizeof( *p_session ) );
951     if( unlikely(p_session == NULL) )
952         return NULL;
953     p_session->p_obj = p_obj;
954     p_session->cfg = *p_cfg;
955     p_session->i_snr = -1;
956     p_session->pat = NULL;
957     p_session->p_pat = NULL;
958     p_session->i_nit_pid = -1;
959     p_session->sdt = NULL;
960     p_session->p_sdt = NULL;
961 #ifdef DVBPSI_USE_NIT
962     p_session->nit = NULL;
963     p_session->p_nit = NULL;
964 #endif
965     return p_session;;
966 }
967
968 void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session )
969 {
970     const int i_service_start = p_scan->i_service;
971
972     dvbpsi_pat_t *p_pat = p_session->p_pat;
973     dvbpsi_sdt_t *p_sdt = p_session->p_sdt;
974
975 #ifdef DVBPSI_USE_NIT
976     dvbpsi_nit_t *p_nit = p_session->p_nit;
977 #endif
978
979     if( p_pat )
980     {
981         /* Parse PAT */
982         dvbpsi_pat_program_t *p_program;
983         for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
984         {
985             if( p_program->i_number == 0 )  /* NIT */
986                 continue;
987
988             scan_service_t *s = ScanFindService( p_scan, 0, p_program->i_number );
989             if( s == NULL )
990             {
991                 s = scan_service_New( p_program->i_number, &p_session->cfg );
992                 TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
993             }
994         }
995     }
996     /* Parse SDT */
997     if( p_pat && p_sdt )
998     {
999         dvbpsi_sdt_service_t *p_srv;
1000         for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
1001         {
1002             scan_service_t *s = ScanFindService( p_scan, 0, p_srv->i_service_id );
1003             dvbpsi_descriptor_t *p_dr;
1004
1005             if( s )
1006                 s->b_crypted = p_srv->b_free_ca;
1007
1008             for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
1009             {
1010                 if( p_dr->i_tag == 0x48 )
1011                 {
1012                     dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
1013
1014                     if( s )
1015                     {
1016                         if( !s->psz_name )
1017                             s->psz_name = vlc_from_EIT( pD->i_service_name,
1018                                                    pD->i_service_name_length );
1019
1020                         if( s->type == SERVICE_UNKNOWN )
1021                             s->type = scan_service_type( pD->i_service_type );
1022                     }
1023                 }
1024             }
1025         }
1026     }
1027
1028 #ifdef DVBPSI_USE_NIT
1029     /* Parse NIT */
1030     if( p_pat && p_nit )
1031     {
1032         dvbpsi_nit_ts_t *p_ts;
1033         for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
1034         {
1035             uint32_t i_private_data_id = 0;
1036             dvbpsi_descriptor_t *p_dsc;
1037
1038             if( p_ts->i_orig_network_id != p_nit->i_network_id || p_ts->i_ts_id != p_pat->i_ts_id )
1039                 continue;
1040
1041             for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
1042             {
1043                 if( p_dsc->i_tag == 0x5f )
1044                 {
1045                     i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
1046                 }
1047                 else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
1048                 {
1049                     for( int i = 0; i < p_dsc->i_length/4; i++ )
1050                     {
1051                         uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
1052                         int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
1053
1054                         scan_service_t *s = ScanFindService( p_scan, i_service_start, i_service_id );
1055                         if( s && s->i_channel < 0 )
1056                             s->i_channel = i_channel_number;
1057                     }
1058                 }
1059             }
1060         }
1061     }
1062 #endif
1063
1064     /* */
1065     for( int i = i_service_start; i < p_scan->i_service; i++ )
1066     {
1067         scan_service_t *p_srv = p_scan->pp_service[i];
1068
1069         p_srv->i_snr = p_session->i_snr;
1070         if( p_sdt )
1071             p_srv->i_sdt_version = p_sdt->i_version;
1072 #ifdef DVBPSI_USE_NIT
1073         if( p_nit )
1074         {
1075             p_srv->i_network_id = p_nit->i_network_id;
1076             p_srv->i_nit_version = p_nit->i_version;
1077         }
1078 #endif
1079     }
1080
1081     /* */
1082     if( p_session->pat )
1083         dvbpsi_pat_detach( p_session->pat );
1084     if( p_session->p_pat )
1085         dvbpsi_pat_delete( p_session->p_pat );
1086
1087     if( p_session->sdt )
1088         dvbpsi_DetachDemux( p_session->sdt );
1089     if( p_session->p_sdt )
1090         dvbpsi_sdt_delete( p_session->p_sdt );
1091
1092 #ifdef DVBPSI_USE_NIT
1093     if( p_session->nit )
1094         dvbpsi_DetachDemux( p_session->nit );
1095     if( p_session->p_nit )
1096         dvbpsi_nit_delete( p_session->p_nit );
1097 #endif
1098     free( p_session );
1099 }
1100
1101 static int ScanServiceCmp( const void *a, const void *b )
1102 {
1103     scan_service_t *sa = *(scan_service_t**)a;
1104     scan_service_t *sb = *(scan_service_t**)b;
1105
1106     if( sa->i_channel == sb->i_channel )
1107     {
1108         if( sa->psz_name && sb->psz_name )
1109             return strcmp( sa->psz_name, sb->psz_name );
1110         return 0;
1111     }
1112     if( sa->i_channel == -1 )
1113         return 1;
1114     else if( sb->i_channel == -1 )
1115         return -1;
1116
1117     if( sa->i_channel < sb->i_channel )
1118         return -1;
1119     else if( sa->i_channel > sb->i_channel )
1120         return 1;
1121     return 0;
1122 }
1123
1124 static block_t *BlockString( const char *psz )
1125 {
1126     block_t *p = block_Alloc( strlen(psz) );
1127     if( p )
1128         memcpy( p->p_buffer, psz, p->i_buffer );
1129     return p;
1130 }
1131
1132 block_t *scan_GetM3U( scan_t *p_scan )
1133 {
1134     vlc_object_t *p_obj = p_scan->p_obj;
1135     block_t *p_playlist = NULL;
1136
1137     if( p_scan->i_service <= 0 )
1138         return NULL;
1139
1140     /* */
1141     qsort( p_scan->pp_service, p_scan->i_service, sizeof(scan_service_t*), ScanServiceCmp );
1142
1143     /* */
1144     p_playlist = BlockString( "#EXTM3U\n\n" );/* */
1145
1146     for( int i = 0; i < p_scan->i_service; i++ )
1147     {
1148         scan_service_t *s = p_scan->pp_service[i];
1149
1150         if( s->type == SERVICE_UNKNOWN )
1151         {
1152             /* We should only select service that have been described by SDT */
1153             msg_Dbg( p_obj, "scan_GetM3U: ignoring service number %d", s->i_program );
1154             continue;
1155         }
1156
1157         const char *psz_type;
1158         switch( s->type )
1159         {
1160         case SERVICE_DIGITAL_TELEVISION:       psz_type = "Digital television"; break;
1161         case SERVICE_DIGITAL_TELEVISION_AC_SD: psz_type = "Digital television advanced codec SD"; break;
1162         case SERVICE_DIGITAL_TELEVISION_AC_HD: psz_type = "Digital television advanced codec HD"; break;
1163         case SERVICE_DIGITAL_RADIO:            psz_type = "Digital radio"; break;
1164         default:
1165             psz_type = "Unknown";
1166             break;
1167         }
1168         msg_Warn( p_obj, "scan_GetM3U: service number %d type '%s' name '%s' channel %d cypted=%d| network_id %d (nit:%d sdt:%d)| f=%d bw=%d snr=%d modulation=%d",
1169                   s->i_program, psz_type, s->psz_name, s->i_channel, s->b_crypted,
1170                   s->i_network_id, s->i_nit_version, s->i_sdt_version,
1171                   s->cfg.i_frequency, s->cfg.i_bandwidth, s->i_snr, s->cfg.i_modulation );
1172
1173         if( !s->cfg.i_fec )
1174             s->cfg.i_fec = 9;   /* FEC_AUTO */
1175
1176         char *psz;
1177         if( asprintf( &psz, "#EXTINF:,,%s\n"
1178                         "#EXTVLCOPT:program=%d\n"
1179                         "dvb://frequency=%d:bandwidth=%d:voltage=%d:fec=%d:modulation=%d:srate=%d\n"
1180                         "\n",
1181                       s->psz_name && * s->psz_name ? s->psz_name : "Unknown",
1182                       s->i_program,
1183                       s->cfg.i_frequency,
1184                       s->cfg.i_bandwidth,
1185                       s->cfg.c_polarization == 'H' ? 18 : 13,
1186                       s->cfg.i_fec,
1187                       s->cfg.i_modulation,
1188                       s->cfg.i_symbolrate ) < 0 )
1189             psz = NULL;
1190         if( psz )
1191         {
1192             block_t *p_block = BlockString( psz );
1193             if( p_block )
1194                 block_ChainAppend( &p_playlist, p_block );
1195         }
1196     }
1197
1198     return p_playlist ? block_ChainGather( p_playlist ) : NULL;
1199 }
1200
1201 bool scan_session_Push( scan_session_t *p_scan, block_t *p_block )
1202 {
1203     if( p_block->i_buffer < 188 || p_block->p_buffer[0] != 0x47 )
1204     {
1205         block_Release( p_block );
1206         return false;
1207     }
1208
1209     /* */
1210     const int i_pid = ( (p_block->p_buffer[1]&0x1f)<<8) | p_block->p_buffer[2];
1211     if( i_pid == 0x00 )
1212     {
1213         if( !p_scan->pat )
1214         {
1215             p_scan->pat = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
1216             if( !p_scan->pat )
1217             {
1218                 block_Release( p_block );
1219                 return false;
1220             }
1221             p_scan->pat->p_sys = (void *) VLC_OBJECT(p_scan->p_obj);
1222             if( !dvbpsi_pat_attach( p_scan->pat, (dvbpsi_pat_callback)PATCallBack, p_scan ) )
1223             {
1224                 dvbpsi_delete( p_scan->pat );
1225                 p_scan->pat = NULL;
1226                 block_Release( p_block );
1227                 return false;
1228             }
1229         }
1230         if( p_scan->pat )
1231             dvbpsi_packet_push( p_scan->pat, p_block->p_buffer );
1232     }
1233     else if( i_pid == 0x11 )
1234     {
1235         if( !p_scan->sdt )
1236         {
1237             p_scan->sdt = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
1238             if( !p_scan->sdt )
1239             {
1240                 block_Release( p_block );
1241                 return false;
1242             }
1243             p_scan->sdt->p_sys = (void *) VLC_OBJECT(p_scan->p_obj);
1244             if( !dvbpsi_AttachDemux( p_scan->sdt, (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_scan ) )
1245             {
1246                 dvbpsi_delete( p_scan->sdt );
1247                 p_scan->sdt = NULL;
1248                 block_Release( p_block );
1249                 return false;
1250             }
1251         }
1252
1253         if( p_scan->sdt )
1254             dvbpsi_packet_push( p_scan->sdt, p_block->p_buffer );
1255     }
1256     else /*if( i_pid == p_scan->i_nit_pid )*/
1257     {
1258 #ifdef DVBPSI_USE_NIT
1259         if( !p_scan->nit )
1260         {
1261             p_scan->nit = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
1262             if( !p_scan->nit )
1263             {
1264                 block_Release( p_block );
1265                 return false;
1266             }
1267             p_scan->nit->p_sys = (void *) VLC_OBJECT(p_scan->p_obj);
1268             if( !dvbpsi_AttachDemux( p_scan->nit, (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_scan ) )
1269             {
1270                 dvbpsi_delete( p_scan->nit );
1271                 p_scan->nit = NULL;
1272                 block_Release( p_block );
1273                 return false;
1274             }
1275         }
1276         if( p_scan->nit )
1277             dvbpsi_packet_push( p_scan->nit, p_block->p_buffer );
1278 #endif
1279     }
1280
1281     block_Release( p_block );
1282
1283     return p_scan->p_pat && p_scan->p_sdt && 
1284 #ifdef DVBPSI_USE_NIT
1285         p_scan->p_nit;
1286 #else
1287         true;
1288 #endif
1289 }
1290
1291 void scan_service_SetSNR( scan_session_t *p_session, int i_snr )
1292 {
1293     p_session->i_snr = i_snr;
1294 }