1 /*****************************************************************************
2 * scan.c: DVB scanner helpers
3 *****************************************************************************
4 * Copyright (C) 2008,2010 the VideoLAN team
6 * Authors: Laurent Aimar <fenrir@videolan.org>
7 * David Kaplan <david@2of1.org>
8 * Ilkka Ollakka <ileoo@videolan.org>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_block.h>
34 #include <vlc_dialog.h>
36 #include <vlc_charset.h>
37 #include <vlc_access.h>
39 #include <sys/types.h>
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>
57 #include "../../demux/dvb-text.h"
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
;
70 int i_program
; /* program number (service id) */
71 scan_configuration_t cfg
;
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 */
89 struct dialog_progress_bar_t
*p_dialog
;
91 scan_parameter_t parameter
;
95 scan_service_t
**pp_service
;
102 scan_configuration_t cfg
;
112 #ifdef DVBPSI_USE_NIT
116 # warning NIT is not supported by your libdvbpsi version
122 static scan_service_t
*scan_service_New( int i_program
,
123 const scan_configuration_t
*p_cfg
)
125 scan_service_t
*p_srv
= malloc( sizeof(*p_srv
) );
129 p_srv
->i_program
= i_program
;
133 p_srv
->type
= SERVICE_UNKNOWN
;
134 p_srv
->psz_name
= NULL
;
135 p_srv
->i_channel
= -1;
136 p_srv
->b_crypted
= false;
138 p_srv
->i_network_id
= -1;
139 p_srv
->i_nit_version
= -1;
140 p_srv
->i_sdt_version
= -1;
145 static void scan_service_Delete( scan_service_t
*p_srv
)
147 free( p_srv
->psz_name
);
151 static uint32_t decode_BCD( uint32_t input
)
154 for( short index
=28; index
>= 0 ; index
-= 4 )
157 output
+= ((input
>> index
) & 0x0f);
162 static int scan_service_type( int service_type
)
164 switch( service_type
)
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;
175 scan_t
*scan_New( vlc_object_t
*p_obj
, const scan_parameter_t
*p_parameter
)
177 if( p_parameter
->type
== SCAN_DVB_T
)
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" );
186 else if( p_parameter
->type
== SCAN_DVB_C
)
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" );
196 else if( p_parameter
->type
== SCAN_DVB_S
)
198 msg_Dbg( p_obj
, "DVB-S scanning:" );
199 msg_Dbg( p_obj
, " - satellite [%s]", p_parameter
->sat_info
.psz_name
);
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" );
208 scan_t
*p_scan
= malloc( sizeof( *p_scan
) );
209 if( unlikely(p_scan
== NULL
) )
212 p_scan
->p_obj
= VLC_OBJECT(p_obj
);
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();
222 void scan_Destroy( scan_t
*p_scan
)
224 if( p_scan
->p_dialog
!= NULL
)
225 dialog_ProgressDestroy( p_scan
->p_dialog
);
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
);
233 static int ScanDvbSNextFast( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
235 msg_Dbg( p_scan
->p_obj
, "Scan index %"PRId64
, p_scan
->i_index
);
237 int *pi_count
= &p_scan
->parameter
.sat_info
.i_count
;
239 if( !p_scan
->parameter
.sat_info
.psz_name
)
241 msg_Err( p_scan
->p_obj
, "no satellite selected" );
245 /* if there are no transponders in mem, laod from config file */
250 char *psz_dir
= NULL
;
251 char *data_dir
= config_GetDataDir( p_scan
->p_obj
);
253 if( asprintf( &psz_dir
, "%s" DIR_SEP
"dvb" DIR_SEP
"dvb-s", data_dir
) == -1 )
259 free( p_scan
->parameter
.sat_info
.psz_name
);
263 /* open config directory */
264 if( !( p_dir
= vlc_opendir( psz_dir
) ) )
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
);
271 /* find the requested file in the directory */
275 if( ! (psz_filename
= vlc_readdir( p_dir
) ) )
278 if( !strncmp( p_scan
->parameter
.sat_info
.psz_name
, psz_filename
, 20 ) )
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
;
283 free( psz_filename
);
290 if( !p_scan
->parameter
.sat_info
.psz_path
)
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
);
297 msg_Dbg( p_scan
->p_obj
, "using satellite config file (%s)", p_scan
->parameter
.sat_info
.psz_path
);
299 FILE *f
= vlc_fopen( p_scan
->parameter
.sat_info
.psz_path
, "r" );
304 scan_dvbs_transponder_t
*p_transponders
= malloc( sizeof( scan_dvbs_transponder_t
) );
311 if ( ( res
= fscanf( f
, "%c %d %c %d %s\n",
313 &p_transponders
[*pi_count
].i_frequency
,
314 &p_transponders
[*pi_count
].c_polarization
,
315 &p_transponders
[*pi_count
].i_symbol_rate
,
318 msg_Dbg( p_scan
->p_obj
, "error parsing transponder from file" );
323 char psz_fec_list
[] = "1/22/33/44/55/66/77/88/9";
324 char *p_fec
= strstr( psz_fec_list
, psz_fec
);
326 p_transponders
[*pi_count
].i_fec
= 9; /* FEC_AUTO */
328 p_transponders
[*pi_count
].i_fec
= 1 + ( ( p_fec
-psz_fec_list
) / 3 );
332 p_transponders
= realloc(p_transponders
, ( *pi_count
+ 1 ) * sizeof( scan_dvbs_transponder_t
) );
333 } while (res
!= EOF
);
335 msg_Dbg( p_scan
->p_obj
, "parsed %d transponders from config", *pi_count
);
338 p_scan
->parameter
.sat_info
.p_transponders
= p_transponders
;
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
);
347 free( p_scan
->parameter
.sat_info
.psz_name
);
348 free( p_scan
->parameter
.sat_info
.psz_path
);
351 if( p_scan
->i_index
< *pi_count
)
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
;
359 msg_Dbg( p_scan
->p_obj
,
360 "transponder [%"PRId64
"/%d]: frequency=%d, symbolrate=%d, fec=%d, polarization=%c",
364 p_cfg
->i_symbol_rate
,
366 p_cfg
->c_polarization
);
368 *pf_pos
= (double)p_scan
->i_index
/ *pi_count
;
373 if( p_scan
->parameter
.sat_info
.p_transponders
)
375 free( p_scan
->parameter
.sat_info
.p_transponders
);
376 p_scan
->parameter
.sat_info
.p_transponders
= NULL
;
382 static int ScanDvbCNextFast( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
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,
406 enum { num_frequencies
= (sizeof(frequencies
)/sizeof(*frequencies
)) };
408 if( p_scan
->i_index
< num_frequencies
)
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);
420 static int ScanDvbNextExhaustive( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
422 if( p_scan
->i_index
> p_scan
->parameter
.frequency
.i_count
* p_scan
->parameter
.bandwidth
.i_count
)
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
;
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
;
431 *pf_pos
= (double)p_scan
->i_index
/ p_scan
->parameter
.frequency
.i_count
;
435 static int ScanDvbTNextFast( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
437 static const int i_band_count
= 2;
440 const char *psz_name
;
449 const int i_offset_count
= 5;
450 const int i_mhz
= 1000000;
452 /* We will probe the whole band divided in all bandwidth possibility trying
453 * i_offset_count offset around the position
455 for( ;; p_scan
->i_index
++ )
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
;
462 const int i_bandwidth
= p_scan
->parameter
.bandwidth
.i_min
+ i_bi
* p_scan
->parameter
.bandwidth
.i_step
;
465 for( i
= 0; i
< i_band_count
; i
++ )
467 if( i_fi
>= band
[i
].i_min
&& i_fi
<= band
[i
].i_max
)
470 if( i
>=i_band_count
)
472 if( i_fi
> band
[i_band_count
-1].i_max
)
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
;
480 if( i_frequency_base
>= i_frequency_min
&& ( i_frequency_base
- i_frequency_min
) % ( i_bandwidth
*i_mhz
) == 0 )
482 const int i_frequency
= i_frequency_base
+ ( i_oi
- i_offset_count
/2 ) * p_scan
->parameter
.frequency
.i_step
;
484 if( i_frequency
< p_scan
->parameter
.frequency
.i_min
||
485 i_frequency
> p_scan
->parameter
.frequency
.i_max
)
488 p_cfg
->i_frequency
= i_frequency
;
489 p_cfg
->i_bandwidth
= i_bandwidth
;
491 int i_current
= 0, i_total
= 0;
492 for( int i
= 0; i
< i_band_count
; i
++ )
494 const int i_frag
= band
[i
].i_max
-band
[i
].i_min
;
496 if( i_fi
>= band
[i
].i_min
)
497 i_current
+= __MIN( i_fi
- band
[i
].i_min
, i_frag
);
501 *pf_pos
= (double)( i_current
+ (double)i_oi
/ i_offset_count
) / i_total
;
507 static int ScanDvbCNext( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
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
516 for( int i
= 0; i
< p_scan
->i_service
; i
++ )
518 /* We found radio/tv config that doesn't have a name,
519 lets tune to that mux
521 if( !p_scan
->pp_service
[i
]->psz_name
&& ( p_scan
->pp_service
[i
]->type
!= SERVICE_UNKNOWN
) )
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
;
533 /* We should have iterated all channels by now */
534 if( p_scan
->i_service
)
537 /* fallback to old, so when we get one channe, use that
538 symbolrate/modulation until bitter end
540 for( int i
=0; i
< p_scan
->i_service
; i
++ )
542 b_servicefound
= p_scan
->pp_service
[i
]->type
!= SERVICE_UNKNOWN
;
548 if( !b_servicefound
)
551 if( !p_scan
->parameter
.b_modulation_set
)
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)
559 p_scan
->parameter
.i_modulation
= 256;
563 msg_Dbg( p_scan
->p_obj
, "modulation %d ", p_scan
->parameter
.i_modulation
);
565 if( !p_scan
->parameter
.b_symbolrate_set
)
567 /* symbol rates from dvb-tools dvb-c files */
568 static const unsigned short symbolrates
[] = {
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
574 #ifndef _DVBPSI_DR_44_H_
576 6428, 6952, 5900, 5000
580 enum { num_symbols
= (sizeof(symbolrates
)/sizeof(*symbolrates
)) };
582 /* if we rotated modulations, rotate symbolrate */
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
)
590 if( !b_rotate
&& p_scan
->i_index
)
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" );
599 if( p_scan
->parameter
.b_exhaustive
)
600 return ScanDvbNextExhaustive( p_scan
, p_cfg
, pf_pos
);
602 return ScanDvbCNextFast( p_scan
, p_cfg
, pf_pos
);
605 static int ScanDvbTNext( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
607 if( p_scan
->parameter
.b_exhaustive
)
608 return ScanDvbNextExhaustive( p_scan
, p_cfg
, pf_pos
);
610 return ScanDvbTNextFast( p_scan
, p_cfg
, pf_pos
);
613 static int ScanDvbSNext( scan_t
*p_scan
, scan_configuration_t
*p_cfg
, double *pf_pos
)
615 if( p_scan
->parameter
.b_exhaustive
)
616 msg_Dbg( p_scan
->p_obj
, "no exhaustive svb-d scan mode" );
618 return ScanDvbSNextFast( p_scan
, p_cfg
, pf_pos
);
621 int scan_Next( scan_t
*p_scan
, scan_configuration_t
*p_cfg
)
626 if( scan_IsCancelled( p_scan
) )
629 memset( p_cfg
, 0, sizeof(*p_cfg
) );
630 switch( p_scan
->parameter
.type
)
633 i_ret
= ScanDvbTNext( p_scan
, p_cfg
, &f_position
);
636 i_ret
= ScanDvbCNext( p_scan
, p_cfg
, &f_position
);
639 i_ret
= ScanDvbSNext( p_scan
, p_cfg
, &f_position
);
642 i_ret
= VLC_EGENERIC
;
652 for( int i
= 0; i
< p_scan
->i_service
; i
++ )
654 if( p_scan
->pp_service
[i
]->psz_name
)
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
];
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 )
665 msg_Info( p_scan
->p_obj
, "Scan ETA %s | %f", secstotimestr( psz_eta
, i_eta
/1000000 ), f_position
* 100 );
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
);
678 bool scan_IsCancelled( scan_t
*p_scan
)
680 return p_scan
->p_dialog
&& dialog_ProgressCancelled( p_scan
->p_dialog
);
683 static scan_service_t
*ScanFindService( scan_t
*p_scan
, int i_service_start
, int i_program
)
685 for( int i
= i_service_start
; i
< p_scan
->i_service
; i
++ )
687 if( p_scan
->pp_service
[i
]->i_program
== i_program
)
688 return p_scan
->pp_service
[i
];
693 /* FIXME handle properly string (convert to utf8) */
694 static void PATCallBack( scan_session_t
*p_session
, dvbpsi_pat_t
*p_pat
)
696 vlc_object_t
*p_obj
= p_session
->p_obj
;
698 msg_Dbg( p_obj
, "PATCallBack" );
701 if( p_session
->p_pat
&& p_session
->p_pat
->b_current_next
)
703 dvbpsi_DeletePAT( p_session
->p_pat
);
704 p_session
->p_pat
= NULL
;
706 if( p_session
->p_pat
)
708 dvbpsi_DeletePAT( p_pat
);
712 dvbpsi_pat_program_t
*p_program
;
715 p_session
->p_pat
= p_pat
;
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
)
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
;
727 static void SDTCallBack( scan_session_t
*p_session
, dvbpsi_sdt_t
*p_sdt
)
729 vlc_object_t
*p_obj
= p_session
->p_obj
;
731 msg_Dbg( p_obj
, "SDTCallBack" );
733 if( p_session
->p_sdt
&& p_session
->p_sdt
->b_current_next
)
735 dvbpsi_DeleteSDT( p_session
->p_sdt
);
736 p_session
->p_sdt
= NULL
;
738 if( p_session
->p_sdt
)
740 dvbpsi_DeleteSDT( p_sdt
);
745 p_session
->p_sdt
= p_sdt
;
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
);
753 dvbpsi_sdt_service_t
*p_srv
;
754 for( p_srv
= p_sdt
->p_first_service
; p_srv
; p_srv
= p_srv
->p_next
)
756 dvbpsi_descriptor_t
*p_dr
;
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
,
762 for( p_dr
= p_srv
->p_first_descriptor
; p_dr
; p_dr
= p_dr
->p_next
)
764 if( p_dr
->i_tag
== 0x48 )
766 dvbpsi_service_dr_t
*pD
= dvbpsi_DecodeServiceDr( p_dr
);
769 memcpy( str2
, pD
->i_service_name
, pD
->i_service_name_length
);
770 str2
[pD
->i_service_name_length
] = '\0';
772 msg_Dbg( p_obj
, " - type=%d name=%s",
773 pD
->i_service_type
, str2
);
777 msg_Dbg( p_obj
, " * dsc 0x%x", p_dr
->i_tag
);
783 #ifdef DVBPSI_USE_NIT
784 static void NITCallBack( scan_session_t
*p_session
, dvbpsi_nit_t
*p_nit
)
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
;
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
);
796 if( p_session
->p_nit
&& p_session
->p_nit
->b_current_next
)
798 dvbpsi_DeleteNIT( p_session
->p_nit
);
799 p_session
->p_nit
= NULL
;
801 if( p_session
->p_nit
)
803 dvbpsi_DeleteNIT( p_nit
);
808 p_session
->p_nit
= p_nit
;
810 dvbpsi_descriptor_t
*p_dsc
;
811 for( p_dsc
= p_nit
->p_first_descriptor
; p_dsc
!= NULL
; p_dsc
= p_dsc
->p_next
)
813 if( p_dsc
->i_tag
== 0x40 )
815 msg_Dbg( p_obj
, " * network name descriptor" );
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
);
822 else if( p_dsc
->i_tag
== 0x4a )
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];
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
);
837 msg_Dbg( p_obj
, " * dsc 0x%x", p_dsc
->i_tag
);
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
)
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
);
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
)
853 if( p_dsc
->i_tag
== 0x41 )
855 msg_Dbg( p_obj
, " * service list descriptor" );
856 for( int i
= 0; i
< p_dsc
->i_length
/3; i
++ )
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
)
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
);
874 else if( p_dsc
->i_tag
== 0x5a )
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
);
887 #ifdef _DVBPSI_DR_44_H_
888 else if( p_dsc
->i_tag
== 0x44 )
890 dvbpsi_cable_deliv_sys_dr_t
*p_t
= dvbpsi_DecodeCableDelivSysDr( p_dsc
);
891 msg_Dbg( p_obj
, " * Cable delivery system");
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
);
901 else if( p_dsc
->i_tag
== 0x5f )
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
);
907 else if( i_private_data_id
== 0x28 && p_dsc
->i_tag
== 0x83 )
909 msg_Dbg( p_obj
, " * logical channel descriptor (EICTA)" );
910 for( int i
= 0; i
< p_dsc
->i_length
/4; i
++ )
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
;
922 msg_Warn( p_obj
, " * dsc 0x%x", p_dsc
->i_tag
);
929 static void PSINewTableCallBack( scan_session_t
*p_session
, dvbpsi_handle h
, uint8_t i_table_id
, uint16_t i_extension
)
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
);
939 scan_session_t
*scan_session_New( vlc_object_t
*p_obj
,
940 const scan_configuration_t
*p_cfg
)
942 scan_session_t
*p_session
= malloc( sizeof( *p_session
) );
943 if( unlikely(p_session
== 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
;
960 void scan_session_Destroy( scan_t
*p_scan
, scan_session_t
*p_session
)
962 const int i_service_start
= p_scan
->i_service
;
964 dvbpsi_pat_t
*p_pat
= p_session
->p_pat
;
965 dvbpsi_sdt_t
*p_sdt
= p_session
->p_sdt
;
967 #ifdef DVBPSI_USE_NIT
968 dvbpsi_nit_t
*p_nit
= p_session
->p_nit
;
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
)
977 if( p_program
->i_number
== 0 ) /* NIT */
980 scan_service_t
*s
= ScanFindService( p_scan
, 0, p_program
->i_number
);
983 s
= scan_service_New( p_program
->i_number
, &p_session
->cfg
);
984 TAB_APPEND( p_scan
->i_service
, p_scan
->pp_service
, s
);
991 dvbpsi_sdt_service_t
*p_srv
;
992 for( p_srv
= p_sdt
->p_first_service
; p_srv
; p_srv
= p_srv
->p_next
)
994 scan_service_t
*s
= ScanFindService( p_scan
, 0, p_srv
->i_service_id
);
995 dvbpsi_descriptor_t
*p_dr
;
998 s
->b_crypted
= p_srv
->b_free_ca
;
1000 for( p_dr
= p_srv
->p_first_descriptor
; p_dr
; p_dr
= p_dr
->p_next
)
1002 if( p_dr
->i_tag
== 0x48 )
1004 dvbpsi_service_dr_t
*pD
= dvbpsi_DecodeServiceDr( p_dr
);
1009 s
->psz_name
= vlc_from_EIT( pD
->i_service_name
,
1010 pD
->i_service_name_length
);
1012 if( s
->type
== SERVICE_UNKNOWN
)
1013 s
->type
= scan_service_type( pD
->i_service_type
);
1020 #ifdef DVBPSI_USE_NIT
1022 if( p_pat
&& p_nit
)
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
)
1027 uint32_t i_private_data_id
= 0;
1028 dvbpsi_descriptor_t
*p_dsc
;
1030 if( p_ts
->i_orig_network_id
!= p_nit
->i_network_id
|| p_ts
->i_ts_id
!= p_pat
->i_ts_id
)
1033 for( p_dsc
= p_ts
->p_first_descriptor
; p_dsc
!= NULL
; p_dsc
= p_dsc
->p_next
)
1035 if( p_dsc
->i_tag
== 0x5f )
1037 i_private_data_id
= GetDWBE( &p_dsc
->p_data
[0] );
1039 else if( i_private_data_id
== 0x28 && p_dsc
->i_tag
== 0x83 )
1041 for( int i
= 0; i
< p_dsc
->i_length
/4; i
++ )
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;
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
;
1057 for( int i
= i_service_start
; i
< p_scan
->i_service
; i
++ )
1059 scan_service_t
*p_srv
= p_scan
->pp_service
[i
];
1061 p_srv
->i_snr
= p_session
->i_snr
;
1063 p_srv
->i_sdt_version
= p_sdt
->i_version
;
1064 #ifdef DVBPSI_USE_NIT
1067 p_srv
->i_network_id
= p_nit
->i_network_id
;
1068 p_srv
->i_nit_version
= p_nit
->i_version
;
1075 if( p_session
->pat
)
1076 dvbpsi_DetachPAT( p_session
->pat
);
1077 if( p_session
->p_pat
)
1078 dvbpsi_DeletePAT( p_session
->p_pat
);
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
);
1093 static int ScanServiceCmp( const void *a
, const void *b
)
1095 scan_service_t
*sa
= *(scan_service_t
**)a
;
1096 scan_service_t
*sb
= *(scan_service_t
**)b
;
1098 if( sa
->i_channel
== sb
->i_channel
)
1100 if( sa
->psz_name
&& sb
->psz_name
)
1101 return strcmp( sa
->psz_name
, sb
->psz_name
);
1104 if( sa
->i_channel
== -1 )
1106 else if( sb
->i_channel
== -1 )
1109 if( sa
->i_channel
< sb
->i_channel
)
1111 else if( sa
->i_channel
> sb
->i_channel
)
1116 static block_t
*BlockString( const char *psz
)
1118 block_t
*p
= block_Alloc( strlen(psz
) );
1120 memcpy( p
->p_buffer
, psz
, p
->i_buffer
);
1124 block_t
*scan_GetM3U( scan_t
*p_scan
)
1126 vlc_object_t
*p_obj
= p_scan
->p_obj
;
1127 block_t
*p_playlist
= NULL
;
1129 if( p_scan
->i_service
<= 0 )
1133 qsort( p_scan
->pp_service
, p_scan
->i_service
, sizeof(scan_service_t
*), ScanServiceCmp
);
1136 p_playlist
= BlockString( "#EXTM3U\n\n" );/* */
1138 for( int i
= 0; i
< p_scan
->i_service
; i
++ )
1140 scan_service_t
*s
= p_scan
->pp_service
[i
];
1142 if( s
->type
== SERVICE_UNKNOWN
)
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
);
1149 const char *psz_type
;
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;
1157 psz_type
= "Unknown";
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
);
1166 s
->cfg
.i_fec
= 9; /* FEC_AUTO */
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"
1173 s
->psz_name
&& * s
->psz_name
? s
->psz_name
: "Unknown",
1177 s
->cfg
.c_polarization
== 'H' ? 18 : 13,
1179 s
->cfg
.i_modulation
,
1180 s
->cfg
.i_symbolrate
) < 0 )
1184 block_t
*p_block
= BlockString( psz
);
1186 block_ChainAppend( &p_playlist
, p_block
);
1190 return p_playlist
? block_ChainGather( p_playlist
) : NULL
;
1193 bool scan_session_Push( scan_session_t
*p_scan
, block_t
*p_block
)
1195 if( p_block
->i_buffer
< 188 || p_block
->p_buffer
[0] != 0x47 )
1197 block_Release( p_block
);
1202 const int i_pid
= ( (p_block
->p_buffer
[1]&0x1f)<<8) | p_block
->p_buffer
[2];
1206 p_scan
->pat
= dvbpsi_AttachPAT( (dvbpsi_pat_callback
)PATCallBack
, p_scan
);
1209 dvbpsi_PushPacket( p_scan
->pat
, p_block
->p_buffer
);
1211 else if( i_pid
== 0x11 )
1214 p_scan
->sdt
= dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t
)PSINewTableCallBack
, p_scan
);
1217 dvbpsi_PushPacket( p_scan
->sdt
, p_block
->p_buffer
);
1219 else /*if( i_pid == p_scan->i_nit_pid )*/
1221 #ifdef DVBPSI_USE_NIT
1223 p_scan
->nit
= dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t
)PSINewTableCallBack
, p_scan
);
1226 dvbpsi_PushPacket( p_scan
->nit
, p_block
->p_buffer
);
1230 block_Release( p_block
);
1232 return p_scan
->p_pat
&& p_scan
->p_sdt
&&
1233 #ifdef DVBPSI_USE_NIT
1240 void scan_service_SetSNR( scan_session_t
*p_session
, int i_snr
)
1242 p_session
->i_snr
= i_snr
;