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