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