1 /*****************************************************************************
2 * scan.c: DVB scanner helpers
3 *****************************************************************************
4 * Copyright (C) 2008 the VideoLAN team
6 * Authors: Laurent Aimar <fenrir@videolan.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_access.h>
33 #include <vlc_interface.h>
40 #include <sys/types.h>
45 /* Include dvbpsi headers */
46 #ifdef HAVE_DVBPSI_DR_H
47 # include <dvbpsi/dvbpsi.h>
48 # include <dvbpsi/descriptor.h>
49 # include <dvbpsi/pat.h>
50 # include <dvbpsi/pmt.h>
51 # include <dvbpsi/dr.h>
52 # include <dvbpsi/psi.h>
53 # include <dvbpsi/demux.h>
54 # include <dvbpsi/sdt.h>
57 # include "descriptor.h"
58 # include "tables/pat.h"
59 # include "tables/pmt.h"
60 # include "descriptors/dr.h"
63 # include "tables/sdt.h"
67 # include "vlc_httpd.h"
73 scan_service_t *scan_service_New( int i_program, const scan_configuration_t *p_cfg )
75 scan_service_t *p_srv = malloc( sizeof(*p_srv) );
79 p_srv->i_program = i_program;
83 p_srv->type = SERVICE_UNKNOWN;
84 p_srv->psz_name = NULL;
85 p_srv->i_channel = -1;
86 p_srv->b_crypted = false;
88 p_srv->i_network_id = -1;
89 p_srv->i_nit_version = -1;
90 p_srv->i_sdt_version = -1;
95 void scan_service_Delete( scan_service_t *p_srv )
97 free( p_srv->psz_name );
102 int scan_Init( vlc_object_t *p_obj, scan_t *p_scan, const scan_parameter_t *p_parameter )
104 if( p_parameter->type == SCAN_DVB_T )
106 msg_Dbg( p_obj, "DVB-T scanning:" );
107 msg_Dbg( p_obj, " - frequency [%d, %d]",
108 p_parameter->frequency.i_min, p_parameter->frequency.i_max );
109 msg_Dbg( p_obj, " - bandwidth [%d,%d]",
110 p_parameter->bandwidth.i_min, p_parameter->bandwidth.i_max );
111 msg_Dbg( p_obj, " - exhaustive mode %s", p_parameter->b_exhaustive ? "on" : "off" );
113 else if( p_parameter->type == SCAN_DVB_C )
115 msg_Dbg( p_obj, "DVB-C scanning:" );
116 msg_Dbg( p_obj, " - frequency [%d, %d]",
117 p_parameter->frequency.i_min, p_parameter->frequency.i_max );
118 msg_Dbg( p_obj, " - bandwidth [%d,%d]",
119 p_parameter->bandwidth.i_min, p_parameter->bandwidth.i_max );
120 msg_Dbg( p_obj, " - exhaustive mode %s", p_parameter->b_exhaustive ? "on" : "off" );
127 p_scan->p_obj = VLC_OBJECT(p_obj);
129 p_scan->p_dialog = NULL;
130 TAB_INIT( p_scan->i_service, p_scan->pp_service );
131 p_scan->parameter = *p_parameter;
132 p_scan->i_time_start = mdate();
136 void scan_Clean( scan_t *p_scan )
138 if( p_scan->p_dialog != NULL )
139 intf_UserHide( p_scan->p_obj, p_scan->p_dialog );
141 for( int i = 0; i < p_scan->i_service; i++ )
142 scan_service_Delete( p_scan->pp_service[i] );
143 TAB_CLEAN( p_scan->i_service, p_scan->pp_service );
146 static int ScanDvbCNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
148 msg_Dbg( p_scan->p_obj, "Scan index %"PRId64, p_scan->i_index );
149 if( p_scan->i_index <= ( 10 ) )
151 p_cfg->i_frequency = 100500000 + ( ( p_scan->i_index ) * 700000);
153 else if ( p_scan->i_index <= (10 + 9 ) )
155 p_cfg->i_frequency = 97000000 + ( ( p_scan->i_index - 20 ) * 800000);
157 else if ( p_scan->i_index <= (38 + 17 ) )
159 p_cfg->i_frequency = 14250000 + ( ( p_scan->i_index - 33 ) * 700000);
161 else if ( p_scan->i_index <= (72 + (90-21) ) )
163 p_cfg->i_frequency = 13800000 + ( ( p_scan->i_index - (72 + 21 ) ) * 800000);
169 *pf_pos = (double)p_scan->i_index / ( (90-21+22-5+10+9));
174 static int ScanDvbTNextExhaustive( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
176 if( p_scan->i_index > p_scan->parameter.frequency.i_count * p_scan->parameter.bandwidth.i_count )
179 const int i_bi = p_scan->i_index % p_scan->parameter.bandwidth.i_count;
180 const int i_fi = p_scan->i_index / p_scan->parameter.bandwidth.i_count;
182 p_cfg->i_frequency = p_scan->parameter.frequency.i_min + i_fi * p_scan->parameter.frequency.i_step;
183 p_cfg->i_bandwidth = p_scan->parameter.bandwidth.i_min + i_bi * p_scan->parameter.bandwidth.i_step;
185 *pf_pos = (double)p_scan->i_index / p_scan->parameter.frequency.i_count;
189 static int ScanDvbTNextFast( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
191 static const int i_band_count = 2;
194 const char *psz_name;
203 const int i_offset_count = 5;
204 const int i_mhz = 1000000;
206 /* We will probe the whole band divided in all bandwidth possibility trying
207 * i_offset_count offset around the position
209 for( ;; p_scan->i_index++ )
212 const int i_bi = p_scan->i_index % p_scan->parameter.bandwidth.i_count;
213 const int i_oi = (p_scan->i_index / p_scan->parameter.bandwidth.i_count) % i_offset_count;
214 const int i_fi = (p_scan->i_index / p_scan->parameter.bandwidth.i_count) / i_offset_count;
216 const int i_bandwidth = p_scan->parameter.bandwidth.i_min + i_bi * p_scan->parameter.bandwidth.i_step;
219 for( i = 0; i < i_band_count; i++ )
221 if( i_fi >= band[i].i_min && i_fi <= band[i].i_max )
224 if( i >=i_band_count )
226 if( i_fi > band[i_band_count-1].i_max )
231 const int i_frequency_min = band[i].i_min*i_mhz + i_bandwidth*i_mhz/2;
232 const int i_frequency_base = i_fi*i_mhz;
234 if( i_frequency_base >= i_frequency_min && ( i_frequency_base - i_frequency_min ) % ( i_bandwidth*i_mhz ) == 0 )
236 const int i_frequency = i_frequency_base + ( i_oi - i_offset_count/2 ) * p_scan->parameter.frequency.i_step;
238 if( i_frequency < p_scan->parameter.frequency.i_min ||
239 i_frequency > p_scan->parameter.frequency.i_max )
242 p_cfg->i_frequency = i_frequency;
243 p_cfg->i_bandwidth = i_bandwidth;
245 int i_current = 0, i_total = 0;
246 for( int i = 0; i < i_band_count; i++ )
248 const int i_frag = band[i].i_max-band[i].i_min;
250 if( i_fi >= band[i].i_min )
251 i_current += __MIN( i_fi - band[i].i_min, i_frag );
255 *pf_pos = (double)( i_current + (double)i_oi / i_offset_count ) / i_total;
261 static int ScanDvbCNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
263 if( p_scan->parameter.b_exhaustive )
264 return ScanDvbTNextExhaustive( p_scan, p_cfg, pf_pos );
266 return ScanDvbCNextFast( p_scan, p_cfg, pf_pos );
269 static int ScanDvbTNext( scan_t *p_scan, scan_configuration_t *p_cfg, double *pf_pos )
271 if( p_scan->parameter.b_exhaustive )
272 return ScanDvbTNextExhaustive( p_scan, p_cfg, pf_pos );
274 return ScanDvbTNextFast( p_scan, p_cfg, pf_pos );
277 int scan_Next( scan_t *p_scan, scan_configuration_t *p_cfg )
282 if( scan_IsCancelled( p_scan ) )
285 memset( p_cfg, 0, sizeof(*p_cfg) );
286 switch( p_scan->parameter.type )
289 i_ret = ScanDvbTNext( p_scan, p_cfg, &f_position );
292 i_ret = ScanDvbCNext( p_scan, p_cfg, &f_position );
295 i_ret = VLC_EGENERIC;
305 for( int i = 0; i < p_scan->i_service; i++ )
307 if( p_scan->pp_service[i]->type != SERVICE_UNKNOWN )
311 if( asprintf( &psz_text, _("%.1f MHz (%d services)"),
312 (double)p_cfg->i_frequency / 1000000, i_service ) >= 0 )
314 const mtime_t i_eta = f_position > 0.005 ? (mdate() - p_scan->i_time_start) * ( 1.0 / f_position - 1.0 ) : -1;
315 char psz_eta[MSTRTIME_MAX_SIZE];
318 msg_Info( p_scan->p_obj, "Scan ETA %s | %f", secstotimestr( psz_eta, i_eta/1000000 ), f_position * 100 );
320 if( p_scan->p_dialog == NULL )
321 p_scan->p_dialog = intf_UserProgress( p_scan->p_obj, _("Scanning DVB-T"), psz_text, 100.0 * f_position, -1 );
323 intf_ProgressUpdate( p_scan->p_obj, p_scan->p_dialog, psz_text, 100 * f_position, -1 );
331 bool scan_IsCancelled( scan_t *p_scan )
333 return p_scan->p_dialog && intf_ProgressIsCancelled( p_scan->p_obj, p_scan->p_dialog );
336 static scan_service_t *ScanFindService( scan_t *p_scan, int i_service_start, int i_program )
338 for( int i = i_service_start; i < p_scan->i_service; i++ )
340 if( p_scan->pp_service[i]->i_program == i_program )
341 return p_scan->pp_service[i];
346 /* FIXME handle properly string (convert to utf8) */
347 static void PATCallBack( scan_session_t *p_session, dvbpsi_pat_t *p_pat )
349 vlc_object_t *p_obj = p_session->p_obj;
351 msg_Dbg( p_obj, "PATCallBack" );
354 if( p_session->p_pat && p_session->p_pat->b_current_next )
356 dvbpsi_DeletePAT( p_session->p_pat );
357 p_session->p_pat = NULL;
359 if( p_session->p_pat )
361 dvbpsi_DeletePAT( p_pat );
365 dvbpsi_pat_program_t *p_program;
368 p_session->p_pat = p_pat;
371 msg_Dbg( p_obj, "new PAT ts_id=%d version=%d current_next=%d",
372 p_pat->i_ts_id, p_pat->i_version, p_pat->b_current_next );
373 for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
375 msg_Dbg( p_obj, " * number=%d pid=%d", p_program->i_number, p_program->i_pid );
376 if( p_program->i_number == 0 )
377 p_session->i_nit_pid = p_program->i_pid;
380 static void SDTCallBack( scan_session_t *p_session, dvbpsi_sdt_t *p_sdt )
382 vlc_object_t *p_obj = p_session->p_obj;
384 msg_Dbg( p_obj, "SDTCallBack" );
386 if( p_session->p_sdt && p_session->p_sdt->b_current_next )
388 dvbpsi_DeleteSDT( p_session->p_sdt );
389 p_session->p_sdt = NULL;
391 if( p_session->p_sdt )
393 dvbpsi_DeleteSDT( p_sdt );
398 p_session->p_sdt = p_sdt;
401 msg_Dbg( p_obj, "new SDT ts_id=%d version=%d current_next=%d network_id=%d",
402 p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next,
403 p_sdt->i_network_id );
406 dvbpsi_sdt_service_t *p_srv;
407 for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
409 dvbpsi_descriptor_t *p_dr;
411 msg_Dbg( p_obj, " * service id=%d eit schedule=%d present=%d running=%d free_ca=%d",
412 p_srv->i_service_id, p_srv->b_eit_schedule,
413 p_srv->b_eit_present, p_srv->i_running_status,
415 for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
417 if( p_dr->i_tag == 0x48 )
419 dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
422 memcpy( str2, pD->i_service_name, pD->i_service_name_length );
423 str2[pD->i_service_name_length] = '\0';
425 msg_Dbg( p_obj, " - type=%d name=%s",
426 pD->i_service_type, str2 );
430 msg_Dbg( p_obj, " * dsc 0x%x", p_dr->i_tag );
436 #ifdef DVBPSI_USE_NIT
437 static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
439 vlc_object_t *p_obj = p_session->p_obj;
441 msg_Dbg( p_obj, "NITCallBack" );
442 msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d",
443 p_nit->i_network_id, p_nit->i_version, p_nit->b_current_next );
446 if( p_session->p_nit && p_session->p_nit->b_current_next )
448 dvbpsi_DeleteNIT( p_session->p_nit );
449 p_session->p_nit = NULL;
451 if( p_session->p_nit )
453 dvbpsi_DeleteNIT( p_nit );
458 p_session->p_nit = p_nit;
460 dvbpsi_descriptor_t *p_dsc;
461 for( p_dsc = p_nit->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
463 if( p_dsc->i_tag == 0x40 )
465 msg_Dbg( p_obj, " * network name descriptor" );
468 memcpy( str1, p_dsc->p_data, p_dsc->i_length );
469 str1[p_dsc->i_length] = '\0';
470 msg_Dbg( p_obj, " * name %s", str1 );
472 else if( p_dsc->i_tag == 0x4a )
474 msg_Dbg( p_obj, " * linkage descriptor" );
475 uint16_t i_ts_id = GetWBE( &p_dsc->p_data[0] );
476 uint16_t i_on_id = GetWBE( &p_dsc->p_data[2] );
477 uint16_t i_service_id = GetWBE( &p_dsc->p_data[4] );
478 int i_linkage_type = p_dsc->p_data[6];
480 msg_Dbg( p_obj, " * ts_id %d", i_ts_id );
481 msg_Dbg( p_obj, " * on_id %d", i_on_id );
482 msg_Dbg( p_obj, " * service_id %d", i_service_id );
483 msg_Dbg( p_obj, " * linkage_type %d", i_linkage_type );
487 msg_Dbg( p_obj, " * dsc 0x%x", p_dsc->i_tag );
491 dvbpsi_nit_ts_t *p_ts;
492 for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
494 msg_Dbg( p_obj, " * ts ts_id=0x%x original_id=0x%x", p_ts->i_ts_id, p_ts->i_orig_network_id );
496 uint32_t i_private_data_id = 0;
497 dvbpsi_descriptor_t *p_dsc;
498 for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
500 if( p_dsc->i_tag == 0x41 )
502 msg_Dbg( p_obj, " * service list descriptor" );
503 for( int i = 0; i < p_dsc->i_length/3; i++ )
505 uint16_t i_service_id = GetWBE( &p_dsc->p_data[3*i+0] );
506 uint8_t i_service_type = p_dsc->p_data[3*i+2];
507 msg_Dbg( p_obj, " * service_id=%d type=%d", i_service_id, i_service_type );
510 else if( p_dsc->i_tag == 0x5a )
512 dvbpsi_terr_deliv_sys_dr_t *p_t = dvbpsi_DecodeTerrDelivSysDr( p_dsc );
513 msg_Dbg( p_obj, " * terrestrial delivery system" );
514 msg_Dbg( p_obj, " * centre_frequency 0x%x", p_t->i_centre_frequency );
515 msg_Dbg( p_obj, " * bandwidth %d", 8 - p_t->i_bandwidth );
516 msg_Dbg( p_obj, " * constellation %d", p_t->i_constellation );
517 msg_Dbg( p_obj, " * hierarchy %d", p_t->i_hierarchy_information );
518 msg_Dbg( p_obj, " * code_rate hp %d lp %d", p_t->i_code_rate_hp_stream, p_t->i_code_rate_lp_stream );
519 msg_Dbg( p_obj, " * guard_interval %d", p_t->i_guard_interval );
520 msg_Dbg( p_obj, " * transmission_mode %d", p_t->i_transmission_mode );
521 msg_Dbg( p_obj, " * other_frequency_flag %d", p_t->i_other_frequency_flag );
523 else if( p_dsc->i_tag == 0x5f )
525 msg_Dbg( p_obj, " * private data specifier descriptor" );
526 i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
527 msg_Dbg( p_obj, " * value 0x%8.8x", i_private_data_id );
529 else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
531 msg_Dbg( p_obj, " * logical channel descriptor (EICTA)" );
532 for( int i = 0; i < p_dsc->i_length/4; i++ )
534 uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
535 int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
536 msg_Dbg( p_obj, " * service_id=%d channel_number=%d", i_service_id, i_channel_number );
542 msg_Warn( p_obj, " * dsc 0x%x", p_dsc->i_tag );
549 static void PSINewTableCallBack( scan_session_t *p_session, dvbpsi_handle h, uint8_t i_table_id, uint16_t i_extension )
551 if( i_table_id == 0x42 )
552 dvbpsi_AttachSDT( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_session );
553 #ifdef DVBPSI_USE_NIT
554 else if( i_table_id == 0x40 )
555 dvbpsi_AttachNIT( h, i_table_id, i_extension, (dvbpsi_nit_callback)NITCallBack, p_session );
560 int scan_session_Init( vlc_object_t *p_obj, scan_session_t *p_session, const scan_configuration_t *p_cfg )
563 memset( p_session, 0, sizeof(*p_session) );
564 p_session->p_obj = p_obj;
565 p_session->cfg = *p_cfg;
566 p_session->i_snr = -1;
567 p_session->pat = NULL;
568 p_session->p_pat = NULL;
569 p_session->i_nit_pid = -1;
570 p_session->sdt = NULL;
571 p_session->p_sdt = NULL;
572 #ifdef DVBPSI_USE_NIT
573 p_session->nit = NULL;
574 p_session->p_nit = NULL;
579 void scan_session_Clean( scan_t *p_scan, scan_session_t *p_session )
581 const int i_service_start = p_scan->i_service;
583 dvbpsi_pat_t *p_pat = p_session->p_pat;
584 dvbpsi_sdt_t *p_sdt = p_session->p_sdt;
586 #ifdef DVBPSI_USE_NIT
587 dvbpsi_nit_t *p_nit = p_session->p_nit;
593 dvbpsi_pat_program_t *p_program;
594 for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
596 if( p_program->i_number == 0 ) /* NIT */
599 scan_service_t *s = scan_service_New( p_program->i_number, &p_session->cfg );
600 TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
606 dvbpsi_sdt_service_t *p_srv;
607 for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
609 scan_service_t *s = ScanFindService( p_scan, i_service_start, p_srv->i_service_id );
610 dvbpsi_descriptor_t *p_dr;
613 s->b_crypted = p_srv->b_free_ca;
615 for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
617 if( p_dr->i_tag == 0x48 )
619 dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );
624 s->psz_name = dvbsi_to_utf8( pD->i_service_name, pD->i_service_name_length );
626 if( s->type == SERVICE_UNKNOWN )
628 switch( pD->i_service_type )
630 case 0x01: s->type = SERVICE_DIGITAL_TELEVISION; break;
631 case 0x02: s->type = SERVICE_DIGITAL_RADIO; break;
632 case 0x16: s->type = SERVICE_DIGITAL_TELEVISION_AC_SD; break;
633 case 0x19: s->type = SERVICE_DIGITAL_TELEVISION_AC_HD; break;
642 #ifdef DVBPSI_USE_NIT
646 dvbpsi_nit_ts_t *p_ts;
647 for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
649 uint32_t i_private_data_id = 0;
650 dvbpsi_descriptor_t *p_dsc;
652 if( p_ts->i_orig_network_id != p_nit->i_network_id || p_ts->i_ts_id != p_pat->i_ts_id )
655 for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
657 if( p_dsc->i_tag == 0x5f )
659 i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
661 else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
663 for( int i = 0; i < p_dsc->i_length/4; i++ )
665 uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
666 int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
668 scan_service_t *s = ScanFindService( p_scan, i_service_start, i_service_id );
669 if( s && s->i_channel < 0 )
670 s->i_channel = i_channel_number;
679 for( int i = i_service_start; i < p_scan->i_service; i++ )
681 scan_service_t *p_srv = p_scan->pp_service[i];
683 p_srv->i_snr = p_session->i_snr;
685 p_srv->i_sdt_version = p_sdt->i_version;
686 #ifdef DVBPSI_USE_NIT
689 p_srv->i_network_id = p_nit->i_network_id;
690 p_srv->i_nit_version = p_nit->i_version;
698 dvbpsi_DetachPAT( p_session->pat );
699 if( p_session->p_pat )
700 dvbpsi_DeletePAT( p_session->p_pat );
703 dvbpsi_DetachDemux( p_session->sdt );
704 if( p_session->p_sdt )
705 dvbpsi_DeleteSDT( p_session->p_sdt );
706 #ifdef DVBPSI_USE_NIT
708 dvbpsi_DetachDemux( p_session->nit );
709 if( p_session->p_nit )
710 dvbpsi_DeleteNIT( p_session->p_nit );
714 static int ScanServiceCmp( const void *a, const void *b )
716 scan_service_t *sa = *(scan_service_t**)a;
717 scan_service_t *sb = *(scan_service_t**)b;
719 if( sa->i_channel == sb->i_channel )
721 if( sa->psz_name && sb->psz_name )
722 return strcmp( sa->psz_name, sb->psz_name );
725 if( sa->i_channel == -1 )
727 else if( sb->i_channel == -1 )
730 if( sa->i_channel < sb->i_channel )
732 else if( sa->i_channel > sb->i_channel )
737 static block_t *BlockString( const char *psz )
739 block_t *p = block_Alloc( strlen(psz) );
741 memcpy( p->p_buffer, psz, p->i_buffer );
745 block_t *scan_GetM3U( scan_t *p_scan )
747 vlc_object_t *p_obj = p_scan->p_obj;
748 block_t *p_playlist = NULL;
750 if( p_scan->i_service <= 0 )
754 qsort( p_scan->pp_service, p_scan->i_service, sizeof(scan_service_t*), ScanServiceCmp );
757 p_playlist = BlockString( "#EXTM3U\n\n" );/* */
759 for( int i = 0; i < p_scan->i_service; i++ )
761 scan_service_t *s = p_scan->pp_service[i];
763 if( s->type == SERVICE_UNKNOWN )
765 /* We should only select service that have been described by SDT */
766 msg_Dbg( p_obj, "scan_GetM3U: ignoring service number %d", s->i_program );
770 const char *psz_type;
773 case SERVICE_DIGITAL_TELEVISION: psz_type = "Digital television"; break;
774 case SERVICE_DIGITAL_TELEVISION_AC_SD: psz_type = "Digital television advanced codec SD"; break;
775 case SERVICE_DIGITAL_TELEVISION_AC_HD: psz_type = "Digital television advanced codec HD"; break;
776 case SERVICE_DIGITAL_RADIO: psz_type = "Digital radio"; break;
778 psz_type = "Unknown";
781 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",
782 s->i_program, psz_type, s->psz_name, s->i_channel, s->b_crypted,
783 s->i_network_id, s->i_nit_version, s->i_sdt_version,
784 s->cfg.i_frequency, s->cfg.i_bandwidth, s->i_snr );
787 if( asprintf( &psz, "#EXTINF:,,%s\n"
788 "#EXTVLCOPT:program=%d\n"
789 "dvb://frequency=%d:bandwidth=%d\n"
791 s->psz_name && * s->psz_name ? s->psz_name : "Unknown",
793 s->cfg.i_frequency, s->cfg.i_bandwidth ) < 0 )
797 block_t *p_block = BlockString( psz );
799 block_ChainAppend( &p_playlist, p_block );
803 return p_playlist ? block_ChainGather( p_playlist ) : NULL;
806 bool scan_session_Push( scan_session_t *p_scan, block_t *p_block )
808 if( p_block->i_buffer < 188 || p_block->p_buffer[0] != 0x47 )
810 block_Release( p_block );
815 const int i_pid = ( (p_block->p_buffer[1]&0x1f)<<8) | p_block->p_buffer[2];
819 p_scan->pat = dvbpsi_AttachPAT( (dvbpsi_pat_callback)PATCallBack, p_scan );
822 dvbpsi_PushPacket( p_scan->pat, p_block->p_buffer );
824 else if( i_pid == 0x11 )
827 p_scan->sdt = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_scan );
830 dvbpsi_PushPacket( p_scan->sdt, p_block->p_buffer );
832 else if( i_pid == p_scan->i_nit_pid )
834 #ifdef DVBPSI_USE_NIT
836 p_scan->nit = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack, p_scan );
839 dvbpsi_PushPacket( p_scan->nit, p_block->p_buffer );
843 block_Release( p_block );
845 return p_scan->p_pat && p_scan->p_sdt &&
846 #ifdef DVBPSI_USE_NIT
853 void scan_service_SetSNR( scan_session_t *p_session, int i_snr )
855 p_session->i_snr = i_snr;