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