1 /*****************************************************************************
2 * scan.c: DVB scanner helpers
3 *****************************************************************************
4 * Copyright (C) 2008,2010 VLC authors and VideoLAN
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 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.
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.
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 *****************************************************************************/
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"
58 #include "../../mux/mpeg/dvbpsi_compat.h"
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;
71 int i_program; /* program number (service id) */
72 scan_configuration_t cfg;
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 */
90 struct dialog_progress_bar_t *p_dialog;
92 scan_parameter_t parameter;
96 scan_service_t **pp_service;
103 scan_configuration_t cfg;
113 #ifdef DVBPSI_USE_NIT
117 # warning NIT is not supported by your libdvbpsi version
123 static scan_service_t *scan_service_New( int i_program,
124 const scan_configuration_t *p_cfg )
126 scan_service_t *p_srv = malloc( sizeof(*p_srv) );
130 p_srv->i_program = i_program;
134 p_srv->type = SERVICE_UNKNOWN;
135 p_srv->psz_name = NULL;
136 p_srv->i_channel = -1;
137 p_srv->b_crypted = false;
139 p_srv->i_network_id = -1;
140 p_srv->i_nit_version = -1;
141 p_srv->i_sdt_version = -1;
146 static void scan_service_Delete( scan_service_t *p_srv )
148 free( p_srv->psz_name );
152 static uint32_t decode_BCD( uint32_t input )
155 for( short index=28; index >= 0 ; index -= 4 )
158 output += ((input >> index) & 0x0f);
163 static int scan_service_type( int service_type )
165 switch( service_type )
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;
176 scan_t *scan_New( vlc_object_t *p_obj, const scan_parameter_t *p_parameter )
178 if( p_parameter->type == SCAN_DVB_T )
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" );
187 else if( p_parameter->type == SCAN_DVB_C )
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" );
197 else if( p_parameter->type == SCAN_DVB_S )
199 msg_Dbg( p_obj, "DVB-S scanning:" );
200 msg_Dbg( p_obj, " - satellite [%s]", p_parameter->sat_info.psz_name );
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" );
209 scan_t *p_scan = malloc( sizeof( *p_scan ) );
210 if( unlikely(p_scan == NULL) )
213 p_scan->p_obj = VLC_OBJECT(p_obj);
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();
223 void scan_Destroy( scan_t *p_scan )
225 if( p_scan->p_dialog != NULL )
226 dialog_ProgressDestroy( p_scan->p_dialog );
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 );
234 static int ScanDvbSNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
236 msg_Dbg( p_scan->p_obj, "Scan index %"PRId64, p_scan->i_index );
238 unsigned *pi_count = &p_scan->parameter.sat_info.i_count;
240 if( !p_scan->parameter.sat_info.psz_name )
242 msg_Err( p_scan->p_obj, "no satellite selected" );
246 /* if there are no transponders in mem, laod from config file */
251 char *psz_dir = NULL;
252 char *data_dir = config_GetDataDir();
254 if( asprintf( &psz_dir, "%s" DIR_SEP "dvb" DIR_SEP "dvb-s", data_dir ) == -1 )
260 free( p_scan->parameter.sat_info.psz_name );
264 /* open config directory */
265 if( !( p_dir = vlc_opendir( psz_dir ) ) )
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 );
272 /* find the requested file in the directory */
274 const char *psz_filename = vlc_readdir( p_dir );
276 if( psz_filename == NULL )
279 if( !strncmp( p_scan->parameter.sat_info.psz_name, psz_filename, 20 ) )
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;
289 if( !p_scan->parameter.sat_info.psz_path )
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 );
296 msg_Dbg( p_scan->p_obj, "using satellite config file (%s)", p_scan->parameter.sat_info.psz_path );
298 FILE *f = vlc_fopen( p_scan->parameter.sat_info.psz_path, "r" );
303 scan_dvbs_transponder_t *p_transponders = malloc( sizeof( scan_dvbs_transponder_t ) );
310 if ( ( res = fscanf( f, "%c %d %c %d %2s\n",
312 &p_transponders[*pi_count].i_frequency,
313 &p_transponders[*pi_count].c_polarization,
314 &p_transponders[*pi_count].i_symbol_rate,
317 msg_Dbg( p_scan->p_obj, "error parsing transponder from file" );
322 char psz_fec_list[] = "1/22/33/44/55/66/77/88/9";
323 char *p_fec = strstr( psz_fec_list, psz_fec );
325 p_transponders[*pi_count].i_fec = 9; /* FEC_AUTO */
327 p_transponders[*pi_count].i_fec = 1 + ( ( p_fec-psz_fec_list ) / 3 );
331 p_transponders = realloc(p_transponders, ( *pi_count + 1 ) * sizeof( scan_dvbs_transponder_t ) );
332 } while (res != EOF);
334 msg_Dbg( p_scan->p_obj, "parsed %d transponders from config", *pi_count);
337 p_scan->parameter.sat_info.p_transponders = p_transponders;
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 );
346 free( p_scan->parameter.sat_info.psz_name );
347 free( p_scan->parameter.sat_info.psz_path );
350 if( p_scan->i_index < *pi_count )
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;
358 msg_Dbg( p_scan->p_obj,
359 "transponder [%"PRId64"/%d]: frequency=%d, symbolrate=%d, fec=%d, polarization=%c",
363 p_cfg->i_symbol_rate,
365 p_cfg->c_polarization );
367 *pf_pos = (double)p_scan->i_index / *pi_count;
372 if( p_scan->parameter.sat_info.p_transponders )
374 free( p_scan->parameter.sat_info.p_transponders );
375 p_scan->parameter.sat_info.p_transponders = NULL;
381 static int ScanDvbCNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
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,
405 enum { num_frequencies = (sizeof(frequencies)/sizeof(*frequencies)) };
407 if( p_scan->i_index < num_frequencies )
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);
419 static int ScanDvbNextExhaustive( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
421 if( p_scan->i_index > p_scan->parameter.frequency.i_count * p_scan->parameter.bandwidth.i_count )
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;
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;
430 *pf_pos = (double)p_scan->i_index / p_scan->parameter.frequency.i_count;
434 static int ScanDvbTNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
436 static const int i_band_count = 2;
439 const char *psz_name;
448 const int i_offset_count = 5;
449 const int i_mhz = 1000000;
451 /* We will probe the whole band divided in all bandwidth possibility trying
452 * i_offset_count offset around the position
454 for( ;; p_scan->i_index++ )
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;
461 const int i_bandwidth = p_scan->parameter.bandwidth.i_min + i_bi * p_scan->parameter.bandwidth.i_step;
464 for( i = 0; i < i_band_count; i++ )
466 if( i_fi >= band[i].i_min && i_fi <= band[i].i_max )
469 if( i >=i_band_count )
471 if( i_fi > band[i_band_count-1].i_max )
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;
479 if( i_frequency_base >= i_frequency_min && ( i_frequency_base - i_frequency_min ) % ( i_bandwidth*i_mhz ) == 0 )
481 const int i_frequency = i_frequency_base + ( i_oi - i_offset_count/2 ) * p_scan->parameter.frequency.i_step;
483 if( i_frequency < p_scan->parameter.frequency.i_min ||
484 i_frequency > p_scan->parameter.frequency.i_max )
487 p_cfg->i_frequency = i_frequency;
488 p_cfg->i_bandwidth = i_bandwidth;
490 int i_current = 0, i_total = 0;
491 for( int i = 0; i < i_band_count; i++ )
493 const int i_frag = band[i].i_max-band[i].i_min;
495 if( i_fi >= band[i].i_min )
496 i_current += __MIN( i_fi - band[i].i_min, i_frag );
500 *pf_pos = (double)( i_current + (double)i_oi / i_offset_count ) / i_total;
506 static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
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
515 for( int i = 0; i < p_scan->i_service; i++ )
517 /* We found radio/tv config that doesn't have a name,
518 lets tune to that mux
520 if( !p_scan->pp_service[i]->psz_name && ( p_scan->pp_service[i]->type != SERVICE_UNKNOWN ) )
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;
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 */
585 p_scan->parameter.i_symbolrate++;
586 p_scan->parameter.i_symbolrate %= num_symbols;
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 )
593 if( !b_rotate && p_scan->i_index )
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" );
600 if( p_scan->parameter.b_exhaustive )
601 return ScanDvbNextExhaustive( p_scan, p_cfg, pf_pos );
603 return ScanDvbCNextFast( p_scan, p_cfg, pf_pos );
606 static int ScanDvbTNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
608 if( p_scan->parameter.b_exhaustive )
609 return ScanDvbNextExhaustive( p_scan, p_cfg, pf_pos );
611 return ScanDvbTNextFast( p_scan, p_cfg, pf_pos );
614 static int ScanDvbSNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
616 if( p_scan->parameter.b_exhaustive )
617 msg_Dbg( p_scan->p_obj, "no exhaustive svb-d scan mode" );
619 return ScanDvbSNextFast( p_scan, p_cfg, pf_pos );
622 int scan_Next( scan_t *p_scan, scan_configuration_t *p_cfg )
627 if( scan_IsCancelled( p_scan ) )
630 memset( p_cfg, 0, sizeof(*p_cfg) );
631 switch( p_scan->parameter.type )
634 i_ret = ScanDvbTNext( p_scan, p_cfg, &f_position );
637 i_ret = ScanDvbCNext( p_scan, p_cfg, &f_position );
640 i_ret = ScanDvbSNext( p_scan, p_cfg, &f_position );
643 i_ret = VLC_EGENERIC;
653 for( int i = 0; i < p_scan->i_service; i++ )
655 if( p_scan->pp_service[i]->psz_name )
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];
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 )
666 msg_Info( p_scan->p_obj, "Scan ETA %s | %f", secstotimestr( psz_eta, i_eta/1000000 ), f_position * 100 );
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 );
679 bool scan_IsCancelled( scan_t *p_scan )
681 return p_scan->p_dialog && dialog_ProgressCancelled( p_scan->p_dialog );
684 static scan_service_t *ScanFindService( scan_t *p_scan, int i_service_start, int i_program )
686 for( int i = i_service_start; i < p_scan->i_service; i++ )
688 if( p_scan->pp_service[i]->i_program == i_program )
689 return p_scan->pp_service[i];
694 /* FIXME handle properly string (convert to utf8) */
695 static void PATCallBack( scan_session_t *p_session, dvbpsi_pat_t *p_pat )
697 vlc_object_t *p_obj = p_session->p_obj;
699 msg_Dbg( p_obj, "PATCallBack" );
702 if( p_session->p_pat && p_session->p_pat->b_current_next )
704 dvbpsi_pat_delete( p_session->p_pat );
705 p_session->p_pat = NULL;
707 if( p_session->p_pat )
709 dvbpsi_pat_delete( p_pat );
713 dvbpsi_pat_program_t *p_program;
716 p_session->p_pat = p_pat;
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 )
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;
728 static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
730 vlc_object_t *p_obj = p_session->p_obj;
732 msg_Dbg( p_obj, "SDTCallBack" );
734 if( p_session->p_sdt && p_session->p_sdt->b_current_next )
736 dvbpsi_sdt_delete( p_session->p_sdt );
737 p_session->p_sdt = NULL;
739 if( p_session->p_sdt )
741 dvbpsi_sdt_delete( p_sdt );
746 p_session->p_sdt = p_sdt;
749 msg_Dbg( p_obj, "new SDT ts_id=%d version=%d current_next=%d network_id=%d",
751 p_sdt->i_version, p_sdt->b_current_next,
752 p_sdt->i_network_id );
755 dvbpsi_sdt_service_t *p_srv;
756 for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
758 dvbpsi_descriptor_t *p_dr;
760 msg_Dbg( p_obj, " * service id=%d eit schedule=%d present=%d running=%d free_ca=%d",
761 p_srv->i_service_id, p_srv->b_eit_schedule,
762 p_srv->b_eit_present, p_srv->i_running_status,
764 for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
766 if( p_dr->i_tag == 0x48 )
768 dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
771 memcpy( str2, pD->i_service_name, pD->i_service_name_length );
772 str2[pD->i_service_name_length] = '\0';
774 msg_Dbg( p_obj, " - type=%d name=%s",
775 pD->i_service_type, str2 );
779 msg_Dbg( p_obj, " * dsc 0x%x", p_dr->i_tag );
785 #ifdef DVBPSI_USE_NIT
786 static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
788 vlc_object_t *p_obj = p_session->p_obj;
789 access_t *p_access = (access_t*)p_obj;
790 access_sys_t *p_sys = p_access->p_sys;
791 scan_t *p_scan = p_sys->scan;
793 msg_Dbg( p_obj, "NITCallBack" );
794 msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d",
795 p_nit->i_network_id, p_nit->i_version, p_nit->b_current_next );
798 if( p_session->p_nit && p_session->p_nit->b_current_next )
800 dvbpsi_nit_delete( p_session->p_nit );
801 p_session->p_nit = NULL;
803 if( p_session->p_nit )
805 dvbpsi_nit_delete( p_nit );
810 p_session->p_nit = p_nit;
812 dvbpsi_descriptor_t *p_dsc;
813 for( p_dsc = p_nit->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
815 if( p_dsc->i_tag == 0x40 )
817 msg_Dbg( p_obj, " * network name descriptor" );
820 memcpy( str1, p_dsc->p_data, p_dsc->i_length );
821 str1[p_dsc->i_length] = '\0';
822 msg_Dbg( p_obj, " * name %s", str1 );
824 else if( p_dsc->i_tag == 0x4a )
826 msg_Dbg( p_obj, " * linkage descriptor" );
827 uint16_t i_ts_id = GetWBE( &p_dsc->p_data[0] );
828 uint16_t i_on_id = GetWBE( &p_dsc->p_data[2] );
829 uint16_t i_service_id = GetWBE( &p_dsc->p_data[4] );
830 int i_linkage_type = p_dsc->p_data[6];
832 msg_Dbg( p_obj, " * ts_id %d", i_ts_id );
833 msg_Dbg( p_obj, " * on_id %d", i_on_id );
834 msg_Dbg( p_obj, " * service_id %d", i_service_id );
835 msg_Dbg( p_obj, " * linkage_type %d", i_linkage_type );
839 msg_Dbg( p_obj, " * dsc 0x%x", p_dsc->i_tag );
843 dvbpsi_nit_ts_t *p_ts;
844 for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
846 msg_Dbg( p_obj, " * ts ts_id=0x%x original_id=0x%x", p_ts->i_ts_id, p_ts->i_orig_network_id );
848 uint32_t i_private_data_id = 0;
849 dvbpsi_descriptor_t *p_dsc;
850 scan_configuration_t cfg, *p_cfg = &cfg;
852 memset(p_cfg,0,sizeof(*p_cfg));
853 for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
855 if( p_dsc->i_tag == 0x41 )
857 msg_Dbg( p_obj, " * service list descriptor" );
858 for( int i = 0; i < p_dsc->i_length/3; i++ )
860 uint16_t i_service_id = GetWBE( &p_dsc->p_data[3*i+0] );
861 uint8_t i_service_type = p_dsc->p_data[3*i+2];
862 msg_Dbg( p_obj, " * service_id=%d type=%d", i_service_id, i_service_type );
863 #ifdef _DVBPSI_DR_44_H_
864 if( (ScanFindService( p_scan, 0, i_service_id ) == NULL) &&
865 scan_service_type( i_service_type ) != SERVICE_UNKNOWN )
867 scan_service_t *s = scan_service_New( i_service_id, p_cfg );
868 s->type = scan_service_type( i_service_type );
869 s->i_network_id = p_nit->i_network_id;
870 s->i_nit_version = p_nit->i_version;
871 TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
876 else if( p_dsc->i_tag == 0x5a )
878 dvbpsi_terr_deliv_sys_dr_t *p_t = dvbpsi_DecodeTerrDelivSysDr( p_dsc );
879 msg_Dbg( p_obj, " * terrestrial delivery system" );
880 msg_Dbg( p_obj, " * centre_frequency 0x%x", p_t->i_centre_frequency );
881 msg_Dbg( p_obj, " * bandwidth %d", 8 - p_t->i_bandwidth );
882 msg_Dbg( p_obj, " * constellation %d", p_t->i_constellation );
883 msg_Dbg( p_obj, " * hierarchy %d", p_t->i_hierarchy_information );
884 msg_Dbg( p_obj, " * code_rate hp %d lp %d", p_t->i_code_rate_hp_stream, p_t->i_code_rate_lp_stream );
885 msg_Dbg( p_obj, " * guard_interval %d", p_t->i_guard_interval );
886 msg_Dbg( p_obj, " * transmission_mode %d", p_t->i_transmission_mode );
887 msg_Dbg( p_obj, " * other_frequency_flag %d", p_t->i_other_frequency_flag );
889 #ifdef _DVBPSI_DR_44_H_
890 else if( p_dsc->i_tag == 0x44 )
892 dvbpsi_cable_deliv_sys_dr_t *p_t = dvbpsi_DecodeCableDelivSysDr( p_dsc );
893 msg_Dbg( p_obj, " * Cable delivery system");
895 p_cfg->i_frequency = decode_BCD( p_t->i_frequency ) * 100;
896 msg_Dbg( p_obj, " * frequency %d", p_cfg->i_frequency );
897 p_cfg->i_symbolrate = decode_BCD( p_t->i_symbol_rate ) * 100;
898 msg_Dbg( p_obj, " * symbolrate %u", p_cfg->i_symbolrate );
899 p_cfg->i_modulation = (8 << p_t->i_modulation);
900 msg_Dbg( p_obj, " * modulation %u", p_cfg->i_modulation );
903 else if( p_dsc->i_tag == 0x5f )
905 msg_Dbg( p_obj, " * private data specifier descriptor" );
906 i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
907 msg_Dbg( p_obj, " * value 0x%8.8x", i_private_data_id );
909 else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
911 msg_Dbg( p_obj, " * logical channel descriptor (EICTA)" );
912 for( int i = 0; i < p_dsc->i_length/4; i++ )
914 uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
915 int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
916 msg_Dbg( p_obj, " * service_id=%d channel_number=%d", i_service_id, i_channel_number );
917 scan_service_t *s = ScanFindService( p_scan, 0, i_service_id );
918 if( s && s->i_channel < 0 ) s->i_channel = i_channel_number;
924 msg_Warn( p_obj, " * dsc 0x%x", p_dsc->i_tag );
931 static void PSINewTableCallBack( dvbpsi_t *h, uint8_t i_table_id, uint16_t i_extension, void *p_data )
933 scan_session_t *p_session = (scan_session_t *)p_data;
935 if( i_table_id == 0x42 )
937 if( !dvbpsi_sdt_attach( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_session ) )
938 msg_Err( p_session->p_obj, "PSINewTableCallback: failed attaching SDTCallback" );
940 else if( i_table_id == 0x40 || i_table_id == 0x41 )
942 if( !dvbpsi_nit_attach( h, i_table_id, i_extension, (dvbpsi_nit_callback)NITCallBack, p_session ) )
943 msg_Err( p_session->p_obj, "PSINewTableCallback: failed attaching NITCallback" );
947 scan_session_t *scan_session_New( vlc_object_t *p_obj,
948 const scan_configuration_t *p_cfg )
950 scan_session_t *p_session = malloc( sizeof( *p_session ) );
951 if( unlikely(p_session == NULL) )
953 p_session->p_obj = p_obj;
954 p_session->cfg = *p_cfg;
955 p_session->i_snr = -1;
956 p_session->pat = NULL;
957 p_session->p_pat = NULL;
958 p_session->i_nit_pid = -1;
959 p_session->sdt = NULL;
960 p_session->p_sdt = NULL;
961 #ifdef DVBPSI_USE_NIT
962 p_session->nit = NULL;
963 p_session->p_nit = NULL;
968 void scan_session_Destroy( scan_t *p_scan, scan_session_t *p_session )
970 const int i_service_start = p_scan->i_service;
972 dvbpsi_pat_t *p_pat = p_session->p_pat;
973 dvbpsi_sdt_t *p_sdt = p_session->p_sdt;
975 #ifdef DVBPSI_USE_NIT
976 dvbpsi_nit_t *p_nit = p_session->p_nit;
982 dvbpsi_pat_program_t *p_program;
983 for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
985 if( p_program->i_number == 0 ) /* NIT */
988 scan_service_t *s = ScanFindService( p_scan, 0, p_program->i_number );
991 s = scan_service_New( p_program->i_number, &p_session->cfg );
992 TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
999 dvbpsi_sdt_service_t *p_srv;
1000 for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
1002 scan_service_t *s = ScanFindService( p_scan, 0, p_srv->i_service_id );
1003 dvbpsi_descriptor_t *p_dr;
1006 s->b_crypted = p_srv->b_free_ca;
1008 for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
1010 if( p_dr->i_tag == 0x48 )
1012 dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
1017 s->psz_name = vlc_from_EIT( pD->i_service_name,
1018 pD->i_service_name_length );
1020 if( s->type == SERVICE_UNKNOWN )
1021 s->type = scan_service_type( pD->i_service_type );
1028 #ifdef DVBPSI_USE_NIT
1030 if( p_pat && p_nit )
1032 dvbpsi_nit_ts_t *p_ts;
1033 for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
1035 uint32_t i_private_data_id = 0;
1036 dvbpsi_descriptor_t *p_dsc;
1038 if( p_ts->i_orig_network_id != p_nit->i_network_id || p_ts->i_ts_id != p_pat->i_ts_id )
1041 for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
1043 if( p_dsc->i_tag == 0x5f )
1045 i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
1047 else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
1049 for( int i = 0; i < p_dsc->i_length/4; i++ )
1051 uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
1052 int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
1054 scan_service_t *s = ScanFindService( p_scan, i_service_start, i_service_id );
1055 if( s && s->i_channel < 0 )
1056 s->i_channel = i_channel_number;
1065 for( int i = i_service_start; i < p_scan->i_service; i++ )
1067 scan_service_t *p_srv = p_scan->pp_service[i];
1069 p_srv->i_snr = p_session->i_snr;
1071 p_srv->i_sdt_version = p_sdt->i_version;
1072 #ifdef DVBPSI_USE_NIT
1075 p_srv->i_network_id = p_nit->i_network_id;
1076 p_srv->i_nit_version = p_nit->i_version;
1082 if( p_session->pat )
1083 dvbpsi_pat_detach( p_session->pat );
1084 if( p_session->p_pat )
1085 dvbpsi_pat_delete( p_session->p_pat );
1087 if( p_session->sdt )
1088 dvbpsi_DetachDemux( p_session->sdt );
1089 if( p_session->p_sdt )
1090 dvbpsi_sdt_delete( p_session->p_sdt );
1092 #ifdef DVBPSI_USE_NIT
1093 if( p_session->nit )
1094 dvbpsi_DetachDemux( p_session->nit );
1095 if( p_session->p_nit )
1096 dvbpsi_nit_delete( p_session->p_nit );
1101 static int ScanServiceCmp( const void *a, const void *b )
1103 scan_service_t *sa = *(scan_service_t**)a;
1104 scan_service_t *sb = *(scan_service_t**)b;
1106 if( sa->i_channel == sb->i_channel )
1108 if( sa->psz_name && sb->psz_name )
1109 return strcmp( sa->psz_name, sb->psz_name );
1112 if( sa->i_channel == -1 )
1114 else if( sb->i_channel == -1 )
1117 if( sa->i_channel < sb->i_channel )
1119 else if( sa->i_channel > sb->i_channel )
1124 static block_t *BlockString( const char *psz )
1126 block_t *p = block_Alloc( strlen(psz) );
1128 memcpy( p->p_buffer, psz, p->i_buffer );
1132 block_t *scan_GetM3U( scan_t *p_scan )
1134 vlc_object_t *p_obj = p_scan->p_obj;
1135 block_t *p_playlist = NULL;
1137 if( p_scan->i_service <= 0 )
1141 qsort( p_scan->pp_service, p_scan->i_service, sizeof(scan_service_t*), ScanServiceCmp );
1144 p_playlist = BlockString( "#EXTM3U\n\n" );/* */
1146 for( int i = 0; i < p_scan->i_service; i++ )
1148 scan_service_t *s = p_scan->pp_service[i];
1150 if( s->type == SERVICE_UNKNOWN )
1152 /* We should only select service that have been described by SDT */
1153 msg_Dbg( p_obj, "scan_GetM3U: ignoring service number %d", s->i_program );
1157 const char *psz_type;
1160 case SERVICE_DIGITAL_TELEVISION: psz_type = "Digital television"; break;
1161 case SERVICE_DIGITAL_TELEVISION_AC_SD: psz_type = "Digital television advanced codec SD"; break;
1162 case SERVICE_DIGITAL_TELEVISION_AC_HD: psz_type = "Digital television advanced codec HD"; break;
1163 case SERVICE_DIGITAL_RADIO: psz_type = "Digital radio"; break;
1165 psz_type = "Unknown";
1168 msg_Warn( p_obj, "scan_GetM3U: service number %d type '%s' name '%s' channel %d cypted=%d| network_id %d (nit:%d sdt:%d)| f=%d bw=%d snr=%d modulation=%d",
1169 s->i_program, psz_type, s->psz_name, s->i_channel, s->b_crypted,
1170 s->i_network_id, s->i_nit_version, s->i_sdt_version,
1171 s->cfg.i_frequency, s->cfg.i_bandwidth, s->i_snr, s->cfg.i_modulation );
1174 s->cfg.i_fec = 9; /* FEC_AUTO */
1177 if( asprintf( &psz, "#EXTINF:,,%s\n"
1178 "#EXTVLCOPT:program=%d\n"
1179 "dvb://frequency=%d:bandwidth=%d:voltage=%d:fec=%d:modulation=%d:srate=%d\n"
1181 s->psz_name && * s->psz_name ? s->psz_name : "Unknown",
1185 s->cfg.c_polarization == 'H' ? 18 : 13,
1187 s->cfg.i_modulation,
1188 s->cfg.i_symbolrate ) < 0 )
1192 block_t *p_block = BlockString( psz );
1194 block_ChainAppend( &p_playlist, p_block );
1198 return p_playlist ? block_ChainGather( p_playlist ) : NULL;
1201 bool scan_session_Push( scan_session_t *p_scan, block_t *p_block )
1203 if( p_block->i_buffer < 188 || p_block->p_buffer[0] != 0x47 )
1205 block_Release( p_block );
1210 const int i_pid = ( (p_block->p_buffer[1]&0x1f)<<8) | p_block->p_buffer[2];
1215 p_scan->pat = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
1218 block_Release( p_block );
1221 p_scan->pat->p_sys = (void *) VLC_OBJECT(p_scan->p_obj);
1222 if( !dvbpsi_pat_attach( p_scan->pat, (dvbpsi_pat_callback)PATCallBack, p_scan ) )
1224 dvbpsi_delete( p_scan->pat );
1226 block_Release( p_block );
1231 dvbpsi_packet_push( p_scan->pat, p_block->p_buffer );
1233 else if( i_pid == 0x11 )
1237 p_scan->sdt = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
1240 block_Release( p_block );
1243 p_scan->sdt->p_sys = (void *) VLC_OBJECT(p_scan->p_obj);
1244 if( !dvbpsi_AttachDemux( p_scan->sdt, (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_scan ) )
1246 dvbpsi_delete( p_scan->sdt );
1248 block_Release( p_block );
1254 dvbpsi_packet_push( p_scan->sdt, p_block->p_buffer );
1256 else /*if( i_pid == p_scan->i_nit_pid )*/
1258 #ifdef DVBPSI_USE_NIT
1261 p_scan->nit = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
1264 block_Release( p_block );
1267 p_scan->nit->p_sys = (void *) VLC_OBJECT(p_scan->p_obj);
1268 if( !dvbpsi_AttachDemux( p_scan->nit, (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_scan ) )
1270 dvbpsi_delete( p_scan->nit );
1272 block_Release( p_block );
1277 dvbpsi_packet_push( p_scan->nit, p_block->p_buffer );
1281 block_Release( p_block );
1283 return p_scan->p_pat && p_scan->p_sdt &&
1284 #ifdef DVBPSI_USE_NIT
1291 void scan_service_SetSNR( scan_session_t *p_session, int i_snr )
1293 p_session->i_snr = i_snr;