2002-10-06 10:25:42 +02:00
/*
* channels . c : Channel handling
*
* See the main source file ' vdr . c ' for copyright information and
* how to reach the author .
*
2010-01-03 10:28:08 +01:00
* $ Id : channels . c 2.12 2010 / 01 / 02 17 : 38 : 40 kls Exp $
2002-10-06 10:25:42 +02:00
*/
# include "channels.h"
# include <linux/dvb/frontend.h>
# include <ctype.h>
2005-09-04 14:48:39 +02:00
# include "device.h"
2006-01-14 15:52:40 +01:00
# include "epg.h"
2006-02-28 14:00:28 +01:00
# include "timers.h"
2002-10-06 10:25:42 +02:00
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
// format characters in order to allow any number of blanks after a numeric
// value!
2008-02-10 14:11:47 +01:00
// --- Channel Parameter Maps ------------------------------------------------
2002-10-06 10:25:42 +02:00
const tChannelParameterMap InversionValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 0 , INVERSION_OFF , trNOOP ( " off " ) } ,
{ 1 , INVERSION_ON , trNOOP ( " on " ) } ,
{ 999 , INVERSION_AUTO , trNOOP ( " auto " ) } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
const tChannelParameterMap BandwidthValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 6 , 6000000 , " 6 MHz " } ,
{ 7 , 7000000 , " 7 MHz " } ,
{ 8 , 8000000 , " 8 MHz " } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
const tChannelParameterMap CoderateValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 0 , FEC_NONE , trNOOP ( " none " ) } ,
{ 12 , FEC_1_2 , " 1/2 " } ,
{ 23 , FEC_2_3 , " 2/3 " } ,
{ 34 , FEC_3_4 , " 3/4 " } ,
{ 35 , FEC_3_5 , " 3/5 " } ,
{ 45 , FEC_4_5 , " 4/5 " } ,
{ 56 , FEC_5_6 , " 5/6 " } ,
{ 67 , FEC_6_7 , " 6/7 " } ,
{ 78 , FEC_7_8 , " 7/8 " } ,
{ 89 , FEC_8_9 , " 8/9 " } ,
{ 910 , FEC_9_10 , " 9/10 " } ,
{ 999 , FEC_AUTO , trNOOP ( " auto " ) } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
const tChannelParameterMap ModulationValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 16 , QAM_16 , " QAM16 " } ,
{ 32 , QAM_32 , " QAM32 " } ,
{ 64 , QAM_64 , " QAM64 " } ,
{ 128 , QAM_128 , " QAM128 " } ,
{ 256 , QAM_256 , " QAM256 " } ,
{ 2 , QPSK , " QPSK " } ,
{ 5 , PSK_8 , " 8PSK " } ,
{ 6 , APSK_16 , " 16APSK " } ,
{ 10 , VSB_8 , " VSB8 " } ,
{ 11 , VSB_16 , " VSB16 " } ,
{ 998 , QAM_AUTO , " QAMAUTO " } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2008-04-12 13:39:12 +02:00
} ;
const tChannelParameterMap SystemValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 0 , SYS_DVBS , " DVB-S " } ,
{ 1 , SYS_DVBS2 , " DVB-S2 " } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
const tChannelParameterMap TransmissionValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 2 , TRANSMISSION_MODE_2K , " 2K " } ,
{ 8 , TRANSMISSION_MODE_8K , " 8K " } ,
{ 999 , TRANSMISSION_MODE_AUTO , trNOOP ( " auto " ) } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
const tChannelParameterMap GuardValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 4 , GUARD_INTERVAL_1_4 , " 1/4 " } ,
{ 8 , GUARD_INTERVAL_1_8 , " 1/8 " } ,
{ 16 , GUARD_INTERVAL_1_16 , " 1/16 " } ,
{ 32 , GUARD_INTERVAL_1_32 , " 1/32 " } ,
{ 999 , GUARD_INTERVAL_AUTO , trNOOP ( " auto " ) } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
const tChannelParameterMap HierarchyValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 0 , HIERARCHY_NONE , trNOOP ( " none " ) } ,
{ 1 , HIERARCHY_1 , " 1 " } ,
{ 2 , HIERARCHY_2 , " 2 " } ,
{ 4 , HIERARCHY_4 , " 4 " } ,
{ 999 , HIERARCHY_AUTO , trNOOP ( " auto " ) } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2008-04-12 13:39:12 +02:00
} ;
const tChannelParameterMap RollOffValues [ ] = {
2008-12-13 12:22:36 +01:00
{ 0 , ROLLOFF_AUTO , trNOOP ( " auto " ) } ,
{ 20 , ROLLOFF_20 , " 0.20 " } ,
{ 25 , ROLLOFF_25 , " 0.25 " } ,
{ 35 , ROLLOFF_35 , " 0.35 " } ,
2009-12-06 12:57:45 +01:00
{ - 1 , 0 , NULL }
2002-10-06 10:25:42 +02:00
} ;
int UserIndex ( int Value , const tChannelParameterMap * Map )
{
const tChannelParameterMap * map = Map ;
while ( map & & map - > userValue ! = - 1 ) {
if ( map - > userValue = = Value )
return map - Map ;
map + + ;
}
return - 1 ;
}
int DriverIndex ( int Value , const tChannelParameterMap * Map )
{
const tChannelParameterMap * map = Map ;
while ( map & & map - > userValue ! = - 1 ) {
if ( map - > driverValue = = Value )
return map - Map ;
map + + ;
}
return - 1 ;
}
2008-04-12 13:39:12 +02:00
int MapToUser ( int Value , const tChannelParameterMap * Map , const char * * String )
2002-10-06 10:25:42 +02:00
{
int n = DriverIndex ( Value , Map ) ;
2008-04-12 13:39:12 +02:00
if ( n > = 0 ) {
if ( String )
* String = tr ( Map [ n ] . userString ) ;
2002-10-06 10:25:42 +02:00
return Map [ n ] . userValue ;
2008-04-12 13:39:12 +02:00
}
2002-10-06 10:25:42 +02:00
return - 1 ;
}
int MapToDriver ( int Value , const tChannelParameterMap * Map )
{
int n = UserIndex ( Value , Map ) ;
if ( n > = 0 )
return Map [ n ] . driverValue ;
return - 1 ;
}
2008-02-10 14:11:47 +01:00
// --- tChannelID ------------------------------------------------------------
2002-11-24 14:48:38 +01:00
const tChannelID tChannelID : : InvalidID ;
tChannelID tChannelID : : FromString ( const char * s )
{
char * sourcebuf = NULL ;
int nid ;
int tid ;
int sid ;
int rid = 0 ;
int fields = sscanf ( s , " %a[^-]-%d-%d-%d-%d " , & sourcebuf , & nid , & tid , & sid , & rid ) ;
if ( fields = = 4 | | fields = = 5 ) {
int source = cSource : : FromString ( sourcebuf ) ;
free ( sourcebuf ) ;
if ( source > = 0 )
return tChannelID ( source , nid , tid , sid , rid ) ;
}
return tChannelID : : InvalidID ;
}
2005-05-28 09:53:54 +02:00
cString tChannelID : : ToString ( void ) const
2002-11-24 14:48:38 +01:00
{
2004-12-26 12:45:22 +01:00
char buffer [ 256 ] ;
snprintf ( buffer , sizeof ( buffer ) , rid ? " %s-%d-%d-%d-%d " : " %s-%d-%d-%d " , * cSource : : ToString ( source ) , nid , tid , sid , rid ) ;
2002-11-24 14:48:38 +01:00
return buffer ;
}
2004-02-13 15:50:26 +01:00
tChannelID & tChannelID : : ClrPolarization ( void )
{
while ( tid > 100000 )
tid - = 100000 ;
return * this ;
}
2008-02-10 14:11:47 +01:00
// --- cChannel --------------------------------------------------------------
2002-10-06 10:25:42 +02:00
cChannel : : cChannel ( void )
{
2004-10-31 12:53:00 +01:00
name = strdup ( " " ) ;
shortName = strdup ( " " ) ;
provider = strdup ( " " ) ;
2004-10-31 13:01:35 +01:00
portalName = strdup ( " " ) ;
2004-01-04 12:30:00 +01:00
memset ( & __BeginData__ , 0 , ( char * ) & __EndData__ - ( char * ) & __BeginData__ ) ;
2008-12-13 12:22:36 +01:00
inversion = INVERSION_AUTO ;
bandwidth = 8000000 ;
coderateH = FEC_AUTO ;
coderateL = FEC_AUTO ;
modulation = QPSK ;
system = SYS_DVBS ;
transmission = TRANSMISSION_MODE_AUTO ;
guard = GUARD_INTERVAL_AUTO ;
hierarchy = HIERARCHY_AUTO ;
rollOff = ROLLOFF_AUTO ;
2004-01-04 12:30:00 +01:00
modification = CHANNELMOD_NONE ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2004-02-08 11:05:22 +01:00
linkChannels = NULL ;
refChannel = NULL ;
2004-01-04 12:30:00 +01:00
}
2004-02-08 11:05:22 +01:00
cChannel : : cChannel ( const cChannel & Channel )
2004-01-04 12:30:00 +01:00
{
2005-08-06 12:13:55 +02:00
name = NULL ;
shortName = NULL ;
provider = NULL ;
portalName = NULL ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2004-02-08 11:05:22 +01:00
linkChannels = NULL ;
refChannel = NULL ;
2005-08-06 12:13:55 +02:00
* this = Channel ;
2004-02-08 11:05:22 +01:00
}
cChannel : : ~ cChannel ( )
{
delete linkChannels ;
linkChannels = NULL ; // more than one channel can link to this one, so we need the following loop
for ( cChannel * Channel = Channels . First ( ) ; Channel ; Channel = Channels . Next ( Channel ) ) {
if ( Channel - > linkChannels ) {
for ( cLinkChannel * lc = Channel - > linkChannels - > First ( ) ; lc ; lc = Channel - > linkChannels - > Next ( lc ) ) {
if ( lc - > Channel ( ) = = this ) {
Channel - > linkChannels - > Del ( lc ) ;
break ;
}
}
if ( Channel - > linkChannels - > Count ( ) = = 0 ) {
delete Channel - > linkChannels ;
Channel - > linkChannels = NULL ;
}
}
}
2004-10-31 12:53:00 +01:00
free ( name ) ;
free ( shortName ) ;
free ( provider ) ;
2004-10-31 13:01:35 +01:00
free ( portalName ) ;
2002-10-06 10:25:42 +02:00
}
2002-11-10 15:50:21 +01:00
cChannel & cChannel : : operator = ( const cChannel & Channel )
2002-10-06 10:25:42 +02:00
{
2004-10-31 12:53:00 +01:00
name = strcpyrealloc ( name , Channel . name ) ;
shortName = strcpyrealloc ( shortName , Channel . shortName ) ;
provider = strcpyrealloc ( provider , Channel . provider ) ;
2004-10-31 13:01:35 +01:00
portalName = strcpyrealloc ( portalName , Channel . portalName ) ;
2002-11-10 15:50:21 +01:00
memcpy ( & __BeginData__ , & Channel . __BeginData__ , ( char * ) & Channel . __EndData__ - ( char * ) & Channel . __BeginData__ ) ;
return * this ;
}
2004-02-13 15:50:26 +01:00
int cChannel : : Transponder ( int Frequency , char Polarization )
{
// some satellites have transponders at the same frequency, just with different polarization:
switch ( tolower ( Polarization ) ) {
case ' h ' : Frequency + = 100000 ; break ;
case ' v ' : Frequency + = 200000 ; break ;
case ' l ' : Frequency + = 300000 ; break ;
case ' r ' : Frequency + = 400000 ; break ;
2009-12-06 12:57:45 +01:00
default : esyslog ( " ERROR: invalid value for Polarization '%c' " , Polarization ) ;
2004-02-13 15:50:26 +01:00
}
return Frequency ;
}
2004-01-04 12:30:00 +01:00
int cChannel : : Transponder ( void ) const
2002-11-10 15:50:21 +01:00
{
2004-01-04 12:30:00 +01:00
int tf = frequency ;
while ( tf > 20000 )
tf / = 1000 ;
2004-02-13 15:50:26 +01:00
if ( IsSat ( ) )
tf = Transponder ( tf , polarization ) ;
2004-01-04 12:30:00 +01:00
return tf ;
2002-11-10 15:50:21 +01:00
}
2006-02-28 14:00:28 +01:00
bool cChannel : : HasTimer ( void ) const
{
for ( cTimer * Timer = Timers . First ( ) ; Timer ; Timer = Timers . Next ( Timer ) ) {
if ( Timer - > Channel ( ) = = this )
return true ;
}
return false ;
}
2004-01-04 12:30:00 +01:00
int cChannel : : Modification ( int Mask )
{
int Result = modification & Mask ;
modification = CHANNELMOD_NONE ;
return Result ;
}
2005-08-06 12:13:55 +02:00
void cChannel : : CopyTransponderData ( const cChannel * Channel )
{
if ( Channel ) {
frequency = Channel - > frequency ;
source = Channel - > source ;
srate = Channel - > srate ;
polarization = Channel - > polarization ;
inversion = Channel - > inversion ;
bandwidth = Channel - > bandwidth ;
coderateH = Channel - > coderateH ;
coderateL = Channel - > coderateL ;
modulation = Channel - > modulation ;
2008-04-12 13:39:12 +02:00
system = Channel - > system ;
2005-08-06 12:13:55 +02:00
transmission = Channel - > transmission ;
guard = Channel - > guard ;
hierarchy = Channel - > hierarchy ;
2008-04-12 13:39:12 +02:00
rollOff = Channel - > rollOff ;
2005-08-06 12:13:55 +02:00
}
}
2008-04-12 13:39:12 +02:00
bool cChannel : : SetSatTransponderData ( int Source , int Frequency , char Polarization , int Srate , int CoderateH , int Modulation , int System , int RollOff )
2004-01-11 15:54:37 +01:00
{
// Workarounds for broadcaster stupidity:
// Some providers broadcast the transponder frequency of their channels with two different
// values (like 12551 and 12552), so we need to allow for a little tolerance here
if ( abs ( frequency - Frequency ) < = 1 )
Frequency = frequency ;
// Sometimes the transponder frequency is set to 0, which is just wrong
if ( Frequency = = 0 )
return false ;
2006-04-14 10:48:14 +02:00
// Sometimes the symbol rate is off by one
if ( abs ( srate - Srate ) < = 1 )
2006-04-17 12:19:31 +02:00
Srate = srate ;
2004-01-11 15:54:37 +01:00
2008-04-12 13:39:12 +02:00
if ( source ! = Source | | frequency ! = Frequency | | polarization ! = Polarization | | srate ! = Srate | | coderateH ! = CoderateH | | modulation ! = Modulation | | system ! = System | | rollOff ! = RollOff ) {
2008-04-12 13:52:57 +02:00
cString OldTransponderData = TransponderDataToString ( ) ;
2004-01-11 15:54:37 +01:00
source = Source ;
frequency = Frequency ;
polarization = Polarization ;
srate = Srate ;
coderateH = CoderateH ;
2008-04-12 13:39:12 +02:00
modulation = Modulation ;
system = System ;
rollOff = RollOff ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2008-04-12 13:39:12 +02:00
if ( Number ( ) ) {
2008-04-12 13:52:57 +02:00
dsyslog ( " changing transponder data of channel %d from %s to %s " , Number ( ) , * OldTransponderData , * TransponderDataToString ( ) ) ;
2008-04-12 13:39:12 +02:00
modification | = CHANNELMOD_TRANSP ;
Channels . SetModified ( ) ;
}
2004-01-11 15:54:37 +01:00
}
return true ;
}
2004-10-17 12:22:56 +02:00
bool cChannel : : SetCableTransponderData ( int Source , int Frequency , int Modulation , int Srate , int CoderateH )
2004-01-11 15:54:37 +01:00
{
if ( source ! = Source | | frequency ! = Frequency | | modulation ! = Modulation | | srate ! = Srate | | coderateH ! = CoderateH ) {
2008-04-12 13:52:57 +02:00
cString OldTransponderData = TransponderDataToString ( ) ;
2004-01-11 15:54:37 +01:00
source = Source ;
frequency = Frequency ;
modulation = Modulation ;
srate = Srate ;
coderateH = CoderateH ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2008-04-12 13:39:12 +02:00
if ( Number ( ) ) {
2008-04-12 13:52:57 +02:00
dsyslog ( " changing transponder data of channel %d from %s to %s " , Number ( ) , * OldTransponderData , * TransponderDataToString ( ) ) ;
2008-04-12 13:39:12 +02:00
modification | = CHANNELMOD_TRANSP ;
Channels . SetModified ( ) ;
}
2004-01-11 15:54:37 +01:00
}
return true ;
}
2008-12-13 12:22:36 +01:00
bool cChannel : : SetTerrTransponderData ( int Source , int Frequency , int Bandwidth , int Modulation , int Hierarchy , int CoderateH , int CoderateL , int Guard , int Transmission )
2004-01-11 15:54:37 +01:00
{
2008-12-13 12:22:36 +01:00
if ( source ! = Source | | frequency ! = Frequency | | bandwidth ! = Bandwidth | | modulation ! = Modulation | | hierarchy ! = Hierarchy | | coderateH ! = CoderateH | | coderateL ! = CoderateL | | guard ! = Guard | | transmission ! = Transmission ) {
2008-04-12 13:52:57 +02:00
cString OldTransponderData = TransponderDataToString ( ) ;
2004-01-11 15:54:37 +01:00
source = Source ;
frequency = Frequency ;
bandwidth = Bandwidth ;
modulation = Modulation ;
hierarchy = Hierarchy ;
coderateH = CoderateH ;
coderateL = CoderateL ;
guard = Guard ;
transmission = Transmission ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2008-04-12 13:39:12 +02:00
if ( Number ( ) ) {
2008-04-12 13:52:57 +02:00
dsyslog ( " changing transponder data of channel %d from %s to %s " , Number ( ) , * OldTransponderData , * TransponderDataToString ( ) ) ;
2008-04-12 13:39:12 +02:00
modification | = CHANNELMOD_TRANSP ;
Channels . SetModified ( ) ;
}
2004-01-11 15:54:37 +01:00
}
return true ;
}
2004-10-17 12:22:56 +02:00
void cChannel : : SetId ( int Nid , int Tid , int Sid , int Rid )
2004-01-04 12:30:00 +01:00
{
if ( nid ! = Nid | | tid ! = Tid | | sid ! = Sid | | rid ! = Rid ) {
2004-10-17 12:22:56 +02:00
if ( Number ( ) ) {
2004-01-04 12:30:00 +01:00
dsyslog ( " changing id of channel %d from %d-%d-%d-%d to %d-%d-%d-%d " , Number ( ) , nid , tid , sid , rid , Nid , Tid , Sid , Rid ) ;
2004-10-17 12:22:56 +02:00
modification | = CHANNELMOD_ID ;
Channels . SetModified ( ) ;
2005-09-11 13:23:49 +02:00
Channels . UnhashChannel ( this ) ;
2004-10-17 12:22:56 +02:00
}
2004-01-04 12:30:00 +01:00
nid = Nid ;
tid = Tid ;
sid = Sid ;
rid = Rid ;
2005-09-11 13:23:49 +02:00
if ( Number ( ) )
Channels . HashChannel ( this ) ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2004-01-04 12:30:00 +01:00
}
}
2004-10-31 12:53:00 +01:00
void cChannel : : SetName ( const char * Name , const char * ShortName , const char * Provider )
2004-01-04 12:30:00 +01:00
{
2004-11-02 18:07:05 +01:00
if ( ! isempty ( Name ) ) {
bool nn = strcmp ( name , Name ) ! = 0 ;
bool ns = strcmp ( shortName , ShortName ) ! = 0 ;
bool np = strcmp ( provider , Provider ) ! = 0 ;
if ( nn | | ns | | np ) {
if ( Number ( ) ) {
dsyslog ( " changing name of channel %d from '%s,%s;%s' to '%s,%s;%s' " , Number ( ) , name , shortName , provider , Name , ShortName , Provider ) ;
modification | = CHANNELMOD_NAME ;
Channels . SetModified ( ) ;
}
if ( nn )
name = strcpyrealloc ( name , Name ) ;
if ( ns )
shortName = strcpyrealloc ( shortName , ShortName ) ;
if ( np )
provider = strcpyrealloc ( provider , Provider ) ;
2004-10-17 12:22:56 +02:00
}
2004-01-04 12:30:00 +01:00
}
}
2004-10-31 13:01:35 +01:00
void cChannel : : SetPortalName ( const char * PortalName )
{
if ( ! isempty ( PortalName ) & & strcmp ( portalName , PortalName ) ! = 0 ) {
if ( Number ( ) ) {
dsyslog ( " changing portal name of channel %d from '%s' to '%s' " , Number ( ) , portalName , PortalName ) ;
modification | = CHANNELMOD_NAME ;
Channels . SetModified ( ) ;
}
portalName = strcpyrealloc ( portalName , PortalName ) ;
}
}
2005-05-07 13:15:34 +02:00
# define STRDIFF 0x01
# define VALDIFF 0x02
2005-09-04 14:48:39 +02:00
static int IntArraysDiffer ( const int * a , const int * b , const char na [ ] [ MAXLANGCODE2 ] = NULL , const char nb [ ] [ MAXLANGCODE2 ] = NULL )
2004-01-04 12:30:00 +01:00
{
2005-05-07 13:15:34 +02:00
int result = 0 ;
for ( int i = 0 ; a [ i ] | | b [ i ] ; i + + ) {
if ( a [ i ] & & na & & nb & & strcmp ( na [ i ] , nb [ i ] ) ! = 0 )
result | = STRDIFF ;
if ( a [ i ] ! = b [ i ] )
result | = VALDIFF ;
if ( ! a [ i ] | | ! b [ i ] )
break ;
}
return result ;
2004-01-25 15:32:08 +01:00
}
2005-09-04 14:48:39 +02:00
static int IntArrayToString ( char * s , const int * a , int Base = 10 , const char n [ ] [ MAXLANGCODE2 ] = NULL )
2004-01-25 15:32:08 +01:00
{
char * q = s ;
int i = 0 ;
while ( a [ i ] | | i = = 0 ) {
q + = sprintf ( q , Base = = 16 ? " %s%X " : " %s%d " , i ? " , " : " " , a [ i ] ) ;
2004-01-25 16:10:04 +01:00
if ( a [ i ] & & n & & * n [ i ] )
2004-01-25 15:32:08 +01:00
q + = sprintf ( q , " =%s " , n [ i ] ) ;
2004-01-26 16:28:35 +01:00
if ( ! a [ i ] )
break ;
2004-01-25 15:32:08 +01:00
i + + ;
}
* q = 0 ;
return q - s ;
}
2008-08-15 14:49:34 +02:00
void cChannel : : SetPids ( int Vpid , int Ppid , int Vtype , int * Apids , char ALangs [ ] [ MAXLANGCODE2 ] , int * Dpids , char DLangs [ ] [ MAXLANGCODE2 ] , int * Spids , char SLangs [ ] [ MAXLANGCODE2 ] , int Tpid )
2004-01-25 15:32:08 +01:00
{
2005-05-07 13:15:34 +02:00
int mod = CHANNELMOD_NONE ;
2008-08-15 14:49:34 +02:00
if ( vpid ! = Vpid | | ppid ! = Ppid | | vtype ! = Vtype | | tpid ! = Tpid )
2005-05-07 13:15:34 +02:00
mod | = CHANNELMOD_PIDS ;
2007-10-12 14:52:30 +02:00
int m = IntArraysDiffer ( apids , Apids , alangs , ALangs ) | IntArraysDiffer ( dpids , Dpids , dlangs , DLangs ) | IntArraysDiffer ( spids , Spids , slangs , SLangs ) ;
2005-05-07 13:15:34 +02:00
if ( m & STRDIFF )
mod | = CHANNELMOD_LANGS ;
if ( m & VALDIFF )
mod | = CHANNELMOD_PIDS ;
if ( mod ) {
2005-09-04 14:48:39 +02:00
const int BufferSize = ( MAXAPIDS + MAXDPIDS ) * ( 5 + 1 + MAXLANGCODE2 ) + 10 ; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia
char OldApidsBuf [ BufferSize ] ;
char NewApidsBuf [ BufferSize ] ;
2004-01-25 15:32:08 +01:00
char * q = OldApidsBuf ;
q + = IntArrayToString ( q , apids , 10 , alangs ) ;
if ( dpids [ 0 ] ) {
* q + + = ' ; ' ;
q + = IntArrayToString ( q , dpids , 10 , dlangs ) ;
}
* q = 0 ;
q = NewApidsBuf ;
q + = IntArrayToString ( q , Apids , 10 , ALangs ) ;
if ( Dpids [ 0 ] ) {
* q + + = ' ; ' ;
q + = IntArrayToString ( q , Dpids , 10 , DLangs ) ;
}
* q = 0 ;
2007-10-12 14:52:30 +02:00
const int SBufferSize = MAXSPIDS * ( 5 + 1 + MAXLANGCODE2 ) + 10 ; // 5 digits plus delimiting ',' or ';' plus optional '=cod', +10: paranoia
char OldSpidsBuf [ SBufferSize ] ;
char NewSpidsBuf [ SBufferSize ] ;
q = OldSpidsBuf ;
q + = IntArrayToString ( q , spids , 10 , slangs ) ;
* q = 0 ;
q = NewSpidsBuf ;
q + = IntArrayToString ( q , Spids , 10 , SLangs ) ;
* q = 0 ;
2009-08-30 11:32:39 +02:00
if ( Number ( ) )
dsyslog ( " changing pids of channel %d from %d+%d=%d:%s:%s:%d to %d+%d=%d:%s:%s:%d " , Number ( ) , vpid , ppid , vtype , OldApidsBuf , OldSpidsBuf , tpid , Vpid , Ppid , Vtype , NewApidsBuf , NewSpidsBuf , Tpid ) ;
2004-01-04 12:30:00 +01:00
vpid = Vpid ;
ppid = Ppid ;
2008-08-15 14:49:34 +02:00
vtype = Vtype ;
2005-08-06 12:29:38 +02:00
for ( int i = 0 ; i < MAXAPIDS ; i + + ) {
2004-01-25 15:32:08 +01:00
apids [ i ] = Apids [ i ] ;
2005-09-04 14:48:39 +02:00
strn0cpy ( alangs [ i ] , ALangs [ i ] , MAXLANGCODE2 ) ;
2005-01-16 14:40:47 +01:00
}
2005-08-06 12:29:38 +02:00
apids [ MAXAPIDS ] = 0 ;
for ( int i = 0 ; i < MAXDPIDS ; i + + ) {
2004-01-25 15:32:08 +01:00
dpids [ i ] = Dpids [ i ] ;
2005-09-04 14:48:39 +02:00
strn0cpy ( dlangs [ i ] , DLangs [ i ] , MAXLANGCODE2 ) ;
2004-01-25 15:32:08 +01:00
}
2005-08-06 12:29:38 +02:00
dpids [ MAXDPIDS ] = 0 ;
2007-10-12 14:52:30 +02:00
for ( int i = 0 ; i < MAXSPIDS ; i + + ) {
spids [ i ] = Spids [ i ] ;
strn0cpy ( slangs [ i ] , SLangs [ i ] , MAXLANGCODE2 ) ;
}
spids [ MAXSPIDS ] = 0 ;
2004-01-04 12:30:00 +01:00
tpid = Tpid ;
2005-05-07 13:15:34 +02:00
modification | = mod ;
2004-01-04 12:30:00 +01:00
Channels . SetModified ( ) ;
}
}
2009-08-16 15:32:39 +02:00
void cChannel : : SetSubtitlingDescriptors ( uchar * SubtitlingTypes , uint16_t * CompositionPageIds , uint16_t * AncillaryPageIds )
{
if ( SubtitlingTypes ) {
for ( int i = 0 ; i < MAXSPIDS ; i + + )
subtitlingTypes [ i ] = SubtitlingTypes [ i ] ;
}
if ( CompositionPageIds ) {
for ( int i = 0 ; i < MAXSPIDS ; i + + )
compositionPageIds [ i ] = CompositionPageIds [ i ] ;
}
if ( AncillaryPageIds ) {
for ( int i = 0 ; i < MAXSPIDS ; i + + )
ancillaryPageIds [ i ] = AncillaryPageIds [ i ] ;
}
}
2004-01-04 12:30:00 +01:00
void cChannel : : SetCaIds ( const int * CaIds )
{
2009-04-25 13:57:32 +02:00
if ( caids [ 0 ] & & caids [ 0 ] < = CA_USER_MAX )
2004-01-04 12:30:00 +01:00
return ; // special values will not be overwritten
2004-01-25 15:32:08 +01:00
if ( IntArraysDiffer ( caids , CaIds ) ) {
2004-01-04 12:30:00 +01:00
char OldCaIdsBuf [ MAXCAIDS * 5 + 10 ] ; // 5: 4 digits plus delimiting ',', 10: paranoia
char NewCaIdsBuf [ MAXCAIDS * 5 + 10 ] ;
2004-01-25 15:32:08 +01:00
IntArrayToString ( OldCaIdsBuf , caids , 16 ) ;
IntArrayToString ( NewCaIdsBuf , CaIds , 16 ) ;
2009-08-30 11:32:39 +02:00
if ( Number ( ) )
dsyslog ( " changing caids of channel %d from %s to %s " , Number ( ) , OldCaIdsBuf , NewCaIdsBuf ) ;
2004-01-26 16:28:35 +01:00
for ( int i = 0 ; i < = MAXCAIDS ; i + + ) { // <= to copy the terminating 0
2004-01-25 15:32:08 +01:00
caids [ i ] = CaIds [ i ] ;
2004-01-26 16:28:35 +01:00
if ( ! CaIds [ i ] )
break ;
}
2004-01-04 12:30:00 +01:00
modification | = CHANNELMOD_CA ;
Channels . SetModified ( ) ;
}
}
void cChannel : : SetCaDescriptors ( int Level )
{
if ( Level > 0 ) {
modification | = CHANNELMOD_CA ;
Channels . SetModified ( ) ;
2009-08-30 11:32:39 +02:00
if ( Number ( ) & & Level > 1 )
2004-01-04 12:30:00 +01:00
dsyslog ( " changing ca descriptors of channel %d " , Number ( ) ) ;
}
2002-10-06 10:25:42 +02:00
}
2004-02-08 11:05:22 +01:00
void cChannel : : SetLinkChannels ( cLinkChannels * LinkChannels )
{
if ( ! linkChannels & & ! LinkChannels )
return ;
if ( linkChannels & & LinkChannels ) {
cLinkChannel * lca = linkChannels - > First ( ) ;
cLinkChannel * lcb = LinkChannels - > First ( ) ;
while ( lca & & lcb ) {
if ( lca - > Channel ( ) ! = lcb - > Channel ( ) ) {
lca = NULL ;
break ;
}
lca = linkChannels - > Next ( lca ) ;
lcb = LinkChannels - > Next ( lcb ) ;
}
if ( ! lca & & ! lcb ) {
delete LinkChannels ;
return ; // linkage has not changed
}
}
char buffer [ ( ( linkChannels ? linkChannels - > Count ( ) : 0 ) + ( LinkChannels ? LinkChannels - > Count ( ) : 0 ) ) * 6 + 256 ] ; // 6: 5 digit channel number plus blank, 256: other texts (see below) plus reserve
char * q = buffer ;
q + = sprintf ( q , " linking channel %d from " , Number ( ) ) ;
if ( linkChannels ) {
for ( cLinkChannel * lc = linkChannels - > First ( ) ; lc ; lc = linkChannels - > Next ( lc ) ) {
lc - > Channel ( ) - > SetRefChannel ( NULL ) ;
q + = sprintf ( q , " %d " , lc - > Channel ( ) - > Number ( ) ) ;
}
delete linkChannels ;
}
else
q + = sprintf ( q , " none " ) ;
q + = sprintf ( q , " to " ) ;
linkChannels = LinkChannels ;
if ( linkChannels ) {
for ( cLinkChannel * lc = linkChannels - > First ( ) ; lc ; lc = linkChannels - > Next ( lc ) ) {
lc - > Channel ( ) - > SetRefChannel ( this ) ;
q + = sprintf ( q , " %d " , lc - > Channel ( ) - > Number ( ) ) ;
//dsyslog("link %4d -> %4d: %s", Number(), lc->Channel()->Number(), lc->Channel()->Name());
}
}
else
q + = sprintf ( q , " none " ) ;
2009-08-30 11:32:39 +02:00
if ( Number ( ) )
2010-01-01 15:44:52 +01:00
dsyslog ( " %s " , buffer ) ;
2004-02-08 11:05:22 +01:00
}
void cChannel : : SetRefChannel ( cChannel * RefChannel )
{
refChannel = RefChannel ;
}
2002-10-06 10:25:42 +02:00
static int PrintParameter ( char * p , char Name , int Value )
{
2002-11-01 10:26:45 +01:00
return Value > = 0 & & Value ! = 999 ? sprintf ( p , " %c%d " , Name , Value ) : 0 ;
2002-10-06 10:25:42 +02:00
}
2008-04-12 13:52:57 +02:00
cString cChannel : : TransponderDataToString ( void ) const
{
if ( cSource : : IsTerr ( source ) )
return cString : : sprintf ( " %d:%s:%s " , frequency , * ParametersToString ( ) , * cSource : : ToString ( source ) ) ;
return cString : : sprintf ( " %d:%s:%s:%d " , frequency , * ParametersToString ( ) , * cSource : : ToString ( source ) , srate ) ;
}
2004-12-26 12:45:22 +01:00
cString cChannel : : ParametersToString ( void ) const
2002-10-06 10:25:42 +02:00
{
2004-12-26 12:45:22 +01:00
char type = * * cSource : : ToString ( source ) ;
2002-11-08 14:19:22 +01:00
if ( isdigit ( type ) )
type = ' S ' ;
2002-10-06 10:25:42 +02:00
# define ST(s) if (strchr(s, type))
2004-12-26 12:45:22 +01:00
char buffer [ 64 ] ;
2002-10-06 10:25:42 +02:00
char * q = buffer ;
* q = 0 ;
ST ( " S " ) q + = sprintf ( q , " %c " , polarization ) ;
2008-04-12 13:39:12 +02:00
ST ( " T " ) q + = PrintParameter ( q , ' B ' , MapToUser ( bandwidth , BandwidthValues ) ) ;
2002-10-06 10:25:42 +02:00
ST ( " CST " ) q + = PrintParameter ( q , ' C ' , MapToUser ( coderateH , CoderateValues ) ) ;
ST ( " T " ) q + = PrintParameter ( q , ' D ' , MapToUser ( coderateL , CoderateValues ) ) ;
2008-02-08 13:48:31 +01:00
ST ( " T " ) q + = PrintParameter ( q , ' G ' , MapToUser ( guard , GuardValues ) ) ;
2008-04-12 13:39:12 +02:00
ST ( " CST " ) q + = PrintParameter ( q , ' I ' , MapToUser ( inversion , InversionValues ) ) ;
ST ( " CST " ) q + = PrintParameter ( q , ' M ' , MapToUser ( modulation , ModulationValues ) ) ;
ST ( " S " ) q + = PrintParameter ( q , ' O ' , MapToUser ( rollOff , RollOffValues ) ) ;
ST ( " S " ) q + = PrintParameter ( q , ' S ' , MapToUser ( system , SystemValues ) ) ;
ST ( " T " ) q + = PrintParameter ( q , ' T ' , MapToUser ( transmission , TransmissionValues ) ) ;
2002-10-06 10:25:42 +02:00
ST ( " T " ) q + = PrintParameter ( q , ' Y ' , MapToUser ( hierarchy , HierarchyValues ) ) ;
return buffer ;
}
static const char * ParseParameter ( const char * s , int & Value , const tChannelParameterMap * Map )
{
if ( * + + s ) {
char * p = NULL ;
errno = 0 ;
int n = strtol ( s , & p , 10 ) ;
if ( ! errno & & p ! = s ) {
2002-11-01 10:26:45 +01:00
Value = MapToDriver ( n , Map ) ;
if ( Value > = 0 )
2002-10-06 10:25:42 +02:00
return p ;
}
}
2005-12-30 15:43:21 +01:00
esyslog ( " ERROR: invalid value for parameter '%c' " , * ( s - 1 ) ) ;
2002-10-06 10:25:42 +02:00
return NULL ;
}
2008-12-13 12:22:36 +01:00
static const char * SkipDigits ( const char * s )
{
while ( * + + s & & isdigit ( * s ) )
;
return s ;
}
2002-10-06 10:25:42 +02:00
bool cChannel : : StringToParameters ( const char * s )
{
while ( s & & * s ) {
switch ( toupper ( * s ) ) {
2008-12-13 12:22:36 +01:00
case ' A ' : s = SkipDigits ( s ) ; break ; // for compatibility with the "multiproto" approach - may be removed in future versions
2002-10-06 10:25:42 +02:00
case ' B ' : s = ParseParameter ( s , bandwidth , BandwidthValues ) ; break ;
case ' C ' : s = ParseParameter ( s , coderateH , CoderateValues ) ; break ;
case ' D ' : s = ParseParameter ( s , coderateL , CoderateValues ) ; break ;
case ' G ' : s = ParseParameter ( s , guard , GuardValues ) ; break ;
case ' H ' : polarization = * s + + ; break ;
case ' I ' : s = ParseParameter ( s , inversion , InversionValues ) ; break ;
2004-01-11 15:54:37 +01:00
case ' L ' : polarization = * s + + ; break ;
2002-10-06 10:25:42 +02:00
case ' M ' : s = ParseParameter ( s , modulation , ModulationValues ) ; break ;
2008-04-12 13:39:12 +02:00
case ' O ' : s = ParseParameter ( s , rollOff , RollOffValues ) ; break ;
2008-12-13 12:22:36 +01:00
case ' P ' : s = SkipDigits ( s ) ; break ; // for compatibility with the "multiproto" approach - may be removed in future versions
2004-01-11 15:54:37 +01:00
case ' R ' : polarization = * s + + ; break ;
2008-04-12 13:39:12 +02:00
case ' S ' : s = ParseParameter ( s , system , SystemValues ) ; break ;
2002-10-06 10:25:42 +02:00
case ' T ' : s = ParseParameter ( s , transmission , TransmissionValues ) ; break ;
case ' V ' : polarization = * s + + ; break ;
case ' Y ' : s = ParseParameter ( s , hierarchy , HierarchyValues ) ; break ;
2008-12-13 12:22:36 +01:00
case ' Z ' : s = SkipDigits ( s ) ; break ; // for compatibility with the original DVB-S2 patch - may be removed in future versions
2002-10-06 10:25:42 +02:00
default : esyslog ( " ERROR: unknown parameter key '%c' " , * s ) ;
return false ;
}
}
return true ;
}
2004-12-26 12:45:22 +01:00
cString cChannel : : ToText ( const cChannel * Channel )
2002-10-06 10:25:42 +02:00
{
2004-10-31 12:53:00 +01:00
char FullName [ strlen ( Channel - > name ) + 1 + strlen ( Channel - > shortName ) + 1 + strlen ( Channel - > provider ) + 1 + 10 ] ; // +10: paranoia
char * q = FullName ;
q + = sprintf ( q , " %s " , Channel - > name ) ;
if ( ! isempty ( Channel - > shortName ) )
q + = sprintf ( q , " ,%s " , Channel - > shortName ) ;
2009-12-24 10:49:16 +01:00
else if ( strchr ( Channel - > name , ' , ' ) )
q + = sprintf ( q , " , " ) ;
2004-10-31 12:53:00 +01:00
if ( ! isempty ( Channel - > provider ) )
q + = sprintf ( q , " ;%s " , Channel - > provider ) ;
* q = 0 ;
strreplace ( FullName , ' : ' , ' | ' ) ;
2008-02-15 14:57:48 +01:00
cString buffer ;
2002-10-19 15:33:37 +02:00
if ( Channel - > groupSep ) {
if ( Channel - > number )
2008-02-15 14:57:48 +01:00
buffer = cString : : sprintf ( " :@%d %s \n " , Channel - > number , FullName ) ;
2002-10-19 15:33:37 +02:00
else
2008-02-15 14:57:48 +01:00
buffer = cString : : sprintf ( " :%s \n " , FullName ) ;
2002-10-19 15:33:37 +02:00
}
2002-10-06 10:25:42 +02:00
else {
2003-04-26 11:58:54 +02:00
char vpidbuf [ 32 ] ;
char * q = vpidbuf ;
q + = snprintf ( q , sizeof ( vpidbuf ) , " %d " , Channel - > vpid ) ;
2004-01-04 12:30:00 +01:00
if ( Channel - > ppid & & Channel - > ppid ! = Channel - > vpid )
2003-04-26 11:58:54 +02:00
q + = snprintf ( q , sizeof ( vpidbuf ) - ( q - vpidbuf ) , " +%d " , Channel - > ppid ) ;
2009-04-10 11:34:33 +02:00
if ( Channel - > vpid & & Channel - > vtype )
2008-08-15 14:49:34 +02:00
q + = snprintf ( q , sizeof ( vpidbuf ) - ( q - vpidbuf ) , " =%d " , Channel - > vtype ) ;
2003-04-26 11:58:54 +02:00
* q = 0 ;
2005-09-04 14:48:39 +02:00
const int BufferSize = ( MAXAPIDS + MAXDPIDS ) * ( 5 + 1 + MAXLANGCODE2 ) + 10 ; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia
char apidbuf [ BufferSize ] ;
2003-04-26 11:58:54 +02:00
q = apidbuf ;
2004-01-25 15:32:08 +01:00
q + = IntArrayToString ( q , Channel - > apids , 10 , Channel - > alangs ) ;
if ( Channel - > dpids [ 0 ] ) {
* q + + = ' ; ' ;
q + = IntArrayToString ( q , Channel - > dpids , 10 , Channel - > dlangs ) ;
}
2002-10-06 10:25:42 +02:00
* q = 0 ;
2004-01-04 12:30:00 +01:00
char caidbuf [ MAXCAIDS * 5 + 10 ] ; // 5: 4 digits plus delimiting ',', 10: paranoia
q = caidbuf ;
2004-01-25 15:32:08 +01:00
q + = IntArrayToString ( q , Channel - > caids , 16 ) ;
2004-01-04 12:30:00 +01:00
* q = 0 ;
2008-02-15 14:57:48 +01:00
buffer = cString : : sprintf ( " %s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d \n " , FullName , Channel - > frequency , * Channel - > ParametersToString ( ) , * cSource : : ToString ( Channel - > source ) , Channel - > srate , vpidbuf , apidbuf , Channel - > tpid , caidbuf , Channel - > sid , Channel - > nid , Channel - > tid , Channel - > rid ) ;
2002-10-06 10:25:42 +02:00
}
2008-02-15 14:57:48 +01:00
return buffer ;
2002-10-06 10:25:42 +02:00
}
2004-12-26 12:45:22 +01:00
cString cChannel : : ToText ( void ) const
2002-10-06 10:25:42 +02:00
{
return ToText ( this ) ;
}
2005-05-06 13:49:01 +02:00
bool cChannel : : Parse ( const char * s )
2002-10-06 10:25:42 +02:00
{
2003-09-09 18:55:26 +02:00
bool ok = true ;
2002-10-06 10:25:42 +02:00
if ( * s = = ' : ' ) {
2002-10-19 15:33:37 +02:00
groupSep = true ;
if ( * + + s = = ' @ ' & & * + + s ) {
char * p = NULL ;
errno = 0 ;
int n = strtol ( s , & p , 10 ) ;
if ( ! errno & & p ! = s & & n > 0 ) {
number = n ;
s = p ;
}
2002-10-06 10:25:42 +02:00
}
2004-10-31 12:53:00 +01:00
name = strcpyrealloc ( name , skipspace ( s ) ) ;
strreplace ( name , ' | ' , ' : ' ) ;
2002-10-06 10:25:42 +02:00
}
else {
groupSep = false ;
char * namebuf = NULL ;
char * sourcebuf = NULL ;
char * parambuf = NULL ;
2003-04-26 11:58:54 +02:00
char * vpidbuf = NULL ;
2002-10-06 10:25:42 +02:00
char * apidbuf = NULL ;
2004-01-04 12:30:00 +01:00
char * caidbuf = NULL ;
int fields = sscanf ( s , " %a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%d :%a[^:]:%d :%d :%d :%d " , & namebuf , & frequency , & parambuf , & sourcebuf , & srate , & vpidbuf , & apidbuf , & tpid , & caidbuf , & sid , & nid , & tid , & rid ) ;
2002-10-06 10:25:42 +02:00
if ( fields > = 9 ) {
if ( fields = = 9 ) {
// allow reading of old format
2004-01-04 12:30:00 +01:00
sid = atoi ( caidbuf ) ;
delete caidbuf ;
caidbuf = NULL ;
caids [ 0 ] = tpid ;
caids [ 1 ] = 0 ;
2002-10-06 10:25:42 +02:00
tpid = 0 ;
}
2004-01-25 15:32:08 +01:00
vpid = ppid = 0 ;
2010-01-03 10:28:08 +01:00
vtype = 0 ;
2004-01-25 15:32:08 +01:00
apids [ 0 ] = 0 ;
dpids [ 0 ] = 0 ;
2003-09-09 18:55:26 +02:00
ok = false ;
2003-04-26 11:58:54 +02:00
if ( parambuf & & sourcebuf & & vpidbuf & & apidbuf ) {
2002-10-06 10:25:42 +02:00
ok = StringToParameters ( parambuf ) & & ( source = cSource : : FromString ( sourcebuf ) ) > = 0 ;
2004-01-04 12:30:00 +01:00
2008-08-15 14:49:34 +02:00
char * p ;
if ( ( p = strchr ( vpidbuf , ' = ' ) ) ! = NULL ) {
* p + + = 0 ;
if ( sscanf ( p , " %d " , & vtype ) ! = 1 )
return false ;
}
if ( ( p = strchr ( vpidbuf , ' + ' ) ) ! = NULL ) {
2003-04-26 11:58:54 +02:00
* p + + = 0 ;
2005-03-20 10:10:38 +01:00
if ( sscanf ( p , " %d " , & ppid ) ! = 1 )
return false ;
}
2008-08-15 14:49:34 +02:00
if ( sscanf ( vpidbuf , " %d " , & vpid ) ! = 1 )
return false ;
if ( ! ppid )
2004-01-04 12:30:00 +01:00
ppid = vpid ;
2010-01-03 10:28:08 +01:00
if ( vpid & & ! vtype )
vtype = 2 ; // default is MPEG-2
2004-01-04 12:30:00 +01:00
2004-01-25 15:32:08 +01:00
char * dpidbuf = strchr ( apidbuf , ' ; ' ) ;
if ( dpidbuf )
* dpidbuf + + = 0 ;
p = apidbuf ;
char * q ;
int NumApids = 0 ;
2004-12-19 16:33:34 +01:00
char * strtok_next ;
while ( ( q = strtok_r ( p , " , " , & strtok_next ) ) ! = NULL ) {
2004-01-25 15:32:08 +01:00
if ( NumApids < MAXAPIDS ) {
char * l = strchr ( q , ' = ' ) ;
if ( l ) {
* l + + = 0 ;
2005-09-04 14:48:39 +02:00
strn0cpy ( alangs [ NumApids ] , l , MAXLANGCODE2 ) ;
2004-01-25 15:32:08 +01:00
}
else
* alangs [ NumApids ] = 0 ;
apids [ NumApids + + ] = strtol ( q , NULL , 10 ) ;
}
else
esyslog ( " ERROR: too many APIDs! " ) ; // no need to set ok to 'false'
p = NULL ;
}
apids [ NumApids ] = 0 ;
if ( dpidbuf ) {
char * p = dpidbuf ;
char * q ;
int NumDpids = 0 ;
2004-12-19 16:33:34 +01:00
char * strtok_next ;
while ( ( q = strtok_r ( p , " , " , & strtok_next ) ) ! = NULL ) {
2005-01-16 14:40:47 +01:00
if ( NumDpids < MAXDPIDS ) {
2004-01-25 15:32:08 +01:00
char * l = strchr ( q , ' = ' ) ;
if ( l ) {
* l + + = 0 ;
2005-09-04 14:48:39 +02:00
strn0cpy ( dlangs [ NumDpids ] , l , MAXLANGCODE2 ) ;
2004-01-25 15:32:08 +01:00
}
else
* dlangs [ NumDpids ] = 0 ;
dpids [ NumDpids + + ] = strtol ( q , NULL , 10 ) ;
}
else
esyslog ( " ERROR: too many DPIDs! " ) ; // no need to set ok to 'false'
p = NULL ;
}
dpids [ NumDpids ] = 0 ;
}
2004-01-04 12:30:00 +01:00
if ( caidbuf ) {
char * p = caidbuf ;
char * q ;
int NumCaIds = 0 ;
2004-12-19 16:33:34 +01:00
char * strtok_next ;
while ( ( q = strtok_r ( p , " , " , & strtok_next ) ) ! = NULL ) {
2004-01-04 12:30:00 +01:00
if ( NumCaIds < MAXCAIDS ) {
caids [ NumCaIds + + ] = strtol ( q , NULL , 16 ) & 0xFFFF ;
2009-04-25 13:57:32 +02:00
if ( NumCaIds = = 1 & & caids [ 0 ] < = CA_USER_MAX )
2004-01-04 12:30:00 +01:00
break ;
}
else
esyslog ( " ERROR: too many CA ids! " ) ; // no need to set ok to 'false'
p = NULL ;
}
caids [ NumCaIds ] = 0 ;
}
2002-10-06 10:25:42 +02:00
}
2004-10-31 12:53:00 +01:00
strreplace ( namebuf , ' | ' , ' : ' ) ;
char * p = strchr ( namebuf , ' ; ' ) ;
if ( p ) {
* p + + = 0 ;
provider = strcpyrealloc ( provider , p ) ;
}
2009-12-24 10:49:16 +01:00
p = strrchr ( namebuf , ' , ' ) ; // long name might contain a ',', so search for the rightmost one
2004-10-31 12:53:00 +01:00
if ( p ) {
* p + + = 0 ;
shortName = strcpyrealloc ( shortName , p ) ;
}
name = strcpyrealloc ( name , namebuf ) ;
2002-10-06 10:25:42 +02:00
free ( parambuf ) ;
free ( sourcebuf ) ;
2003-04-26 11:58:54 +02:00
free ( vpidbuf ) ;
2002-10-06 10:25:42 +02:00
free ( apidbuf ) ;
2004-01-04 12:30:00 +01:00
free ( caidbuf ) ;
2002-10-06 10:25:42 +02:00
free ( namebuf ) ;
2003-10-17 15:42:40 +02:00
if ( ! GetChannelID ( ) . Valid ( ) ) {
esyslog ( " ERROR: channel data results in invalid ID! " ) ;
return false ;
}
2002-10-06 10:25:42 +02:00
}
else
return false ;
}
2003-09-09 18:55:26 +02:00
return ok ;
2002-10-06 10:25:42 +02:00
}
bool cChannel : : Save ( FILE * f )
{
2004-12-26 12:45:22 +01:00
return fprintf ( f , " %s " , * ToText ( ) ) > 0 ;
2002-10-06 10:25:42 +02:00
}
2008-02-10 14:11:47 +01:00
// --- cChannelSorter --------------------------------------------------------
2005-05-29 10:33:21 +02:00
class cChannelSorter : public cListObject {
public :
cChannel * channel ;
tChannelID channelID ;
cChannelSorter ( cChannel * Channel ) {
channel = Channel ;
channelID = channel - > GetChannelID ( ) ;
}
virtual int Compare ( const cListObject & ListObject ) const {
cChannelSorter * cs = ( cChannelSorter * ) & ListObject ;
return memcmp ( & channelID , & cs - > channelID , sizeof ( channelID ) ) ;
}
} ;
2008-02-10 14:11:47 +01:00
// --- cChannels -------------------------------------------------------------
2002-10-06 10:25:42 +02:00
cChannels Channels ;
2004-01-04 12:30:00 +01:00
cChannels : : cChannels ( void )
{
maxNumber = 0 ;
2004-10-17 11:50:21 +02:00
modified = CHANNELSMOD_NONE ;
2004-01-04 12:30:00 +01:00
}
2005-05-06 13:49:01 +02:00
void cChannels : : DeleteDuplicateChannels ( void )
{
2005-05-29 10:33:21 +02:00
cList < cChannelSorter > ChannelSorter ;
2005-05-06 13:49:01 +02:00
for ( cChannel * channel = First ( ) ; channel ; channel = Next ( channel ) ) {
2005-05-29 10:33:21 +02:00
if ( ! channel - > GroupSep ( ) )
ChannelSorter . Add ( new cChannelSorter ( channel ) ) ;
2005-05-06 13:49:01 +02:00
}
2005-05-29 10:33:21 +02:00
ChannelSorter . Sort ( ) ;
cChannelSorter * cs = ChannelSorter . First ( ) ;
while ( cs ) {
cChannelSorter * next = ChannelSorter . Next ( cs ) ;
if ( next & & cs - > channelID = = next - > channelID ) {
dsyslog ( " deleting duplicate channel %s " , * next - > channel - > ToText ( ) ) ;
Del ( next - > channel ) ;
}
cs = next ;
}
2005-05-06 13:49:01 +02:00
}
2003-08-16 09:18:52 +02:00
bool cChannels : : Load ( const char * FileName , bool AllowComments , bool MustExist )
2002-10-06 10:25:42 +02:00
{
2003-08-16 09:18:52 +02:00
if ( cConfig < cChannel > : : Load ( FileName , AllowComments , MustExist ) ) {
2005-05-06 13:49:01 +02:00
DeleteDuplicateChannels ( ) ;
2002-10-06 10:25:42 +02:00
ReNumber ( ) ;
return true ;
}
return false ;
}
2005-09-11 13:23:49 +02:00
void cChannels : : HashChannel ( cChannel * Channel )
{
channelsHashSid . Add ( Channel , Channel - > Sid ( ) ) ;
}
void cChannels : : UnhashChannel ( cChannel * Channel )
{
channelsHashSid . Del ( Channel , Channel - > Sid ( ) ) ;
}
2002-10-06 10:25:42 +02:00
int cChannels : : GetNextGroup ( int Idx )
{
cChannel * channel = Get ( + + Idx ) ;
2002-11-29 14:19:08 +01:00
while ( channel & & ! ( channel - > GroupSep ( ) & & * channel - > Name ( ) ) )
2002-10-06 10:25:42 +02:00
channel = Get ( + + Idx ) ;
return channel ? Idx : - 1 ;
}
int cChannels : : GetPrevGroup ( int Idx )
{
cChannel * channel = Get ( - - Idx ) ;
2002-11-29 14:19:08 +01:00
while ( channel & & ! ( channel - > GroupSep ( ) & & * channel - > Name ( ) ) )
2002-10-06 10:25:42 +02:00
channel = Get ( - - Idx ) ;
return channel ? Idx : - 1 ;
}
int cChannels : : GetNextNormal ( int Idx )
{
cChannel * channel = Get ( + + Idx ) ;
while ( channel & & channel - > GroupSep ( ) )
channel = Get ( + + Idx ) ;
return channel ? Idx : - 1 ;
}
2006-05-28 10:48:50 +02:00
int cChannels : : GetPrevNormal ( int Idx )
{
cChannel * channel = Get ( - - Idx ) ;
while ( channel & & channel - > GroupSep ( ) )
channel = Get ( - - Idx ) ;
return channel ? Idx : - 1 ;
}
2008-03-05 16:45:54 +01:00
void cChannels : : ReNumber ( void )
2002-10-06 10:25:42 +02:00
{
2005-09-11 13:23:49 +02:00
channelsHashSid . Clear ( ) ;
2008-03-05 16:45:54 +01:00
maxNumber = 0 ;
2002-10-19 15:33:37 +02:00
int Number = 1 ;
for ( cChannel * channel = First ( ) ; channel ; channel = Next ( channel ) ) {
if ( channel - > GroupSep ( ) ) {
if ( channel - > Number ( ) > Number )
Number = channel - > Number ( ) ;
}
2003-10-03 15:16:08 +02:00
else {
2005-09-11 13:23:49 +02:00
HashChannel ( channel ) ;
2003-10-03 15:16:08 +02:00
maxNumber = Number ;
2002-10-19 15:33:37 +02:00
channel - > SetNumber ( Number + + ) ;
2003-10-03 15:16:08 +02:00
}
2002-10-19 15:33:37 +02:00
}
2002-10-06 10:25:42 +02:00
}
2002-10-19 15:33:37 +02:00
cChannel * cChannels : : GetByNumber ( int Number , int SkipGap )
2002-10-06 10:25:42 +02:00
{
2002-10-19 15:33:37 +02:00
cChannel * previous = NULL ;
for ( cChannel * channel = First ( ) ; channel ; channel = Next ( channel ) ) {
if ( ! channel - > GroupSep ( ) ) {
if ( channel - > Number ( ) = = Number )
return channel ;
else if ( SkipGap & & channel - > Number ( ) > Number )
return SkipGap > 0 ? channel : previous ;
previous = channel ;
}
}
2002-10-06 10:25:42 +02:00
return NULL ;
}
2004-01-04 12:30:00 +01:00
cChannel * cChannels : : GetByServiceID ( int Source , int Transponder , unsigned short ServiceID )
2002-11-10 15:50:21 +01:00
{
2005-09-11 13:23:49 +02:00
cList < cHashObject > * list = channelsHashSid . GetList ( ServiceID ) ;
if ( list ) {
for ( cHashObject * hobj = list - > First ( ) ; hobj ; hobj = list - > Next ( hobj ) ) {
cChannel * channel = ( cChannel * ) hobj - > Object ( ) ;
if ( channel - > Sid ( ) = = ServiceID & & channel - > Source ( ) = = Source & & ISTRANSPONDER ( channel - > Transponder ( ) , Transponder ) )
return channel ;
}
}
2002-11-10 15:50:21 +01:00
return NULL ;
}
2004-02-13 15:50:26 +01:00
cChannel * cChannels : : GetByChannelID ( tChannelID ChannelID , bool TryWithoutRid , bool TryWithoutPolarization )
2002-10-06 10:25:42 +02:00
{
2005-09-11 13:23:49 +02:00
int sid = ChannelID . Sid ( ) ;
cList < cHashObject > * list = channelsHashSid . GetList ( sid ) ;
if ( list ) {
for ( cHashObject * hobj = list - > First ( ) ; hobj ; hobj = list - > Next ( hobj ) ) {
cChannel * channel = ( cChannel * ) hobj - > Object ( ) ;
if ( channel - > Sid ( ) = = sid & & channel - > GetChannelID ( ) = = ChannelID )
2004-02-13 15:50:26 +01:00
return channel ;
}
2005-09-11 13:23:49 +02:00
if ( TryWithoutRid ) {
ChannelID . ClrRid ( ) ;
for ( cHashObject * hobj = list - > First ( ) ; hobj ; hobj = list - > Next ( hobj ) ) {
cChannel * channel = ( cChannel * ) hobj - > Object ( ) ;
if ( channel - > Sid ( ) = = sid & & channel - > GetChannelID ( ) . ClrRid ( ) = = ChannelID )
return channel ;
}
}
if ( TryWithoutPolarization ) {
ChannelID . ClrPolarization ( ) ;
for ( cHashObject * hobj = list - > First ( ) ; hobj ; hobj = list - > Next ( hobj ) ) {
cChannel * channel = ( cChannel * ) hobj - > Object ( ) ;
if ( channel - > Sid ( ) = = sid & & channel - > GetChannelID ( ) . ClrPolarization ( ) = = ChannelID )
return channel ;
}
}
2004-02-13 15:50:26 +01:00
}
2002-10-06 10:25:42 +02:00
return NULL ;
}
2007-07-21 15:05:20 +02:00
cChannel * cChannels : : GetByTransponderID ( tChannelID ChannelID )
{
int source = ChannelID . Source ( ) ;
int nid = ChannelID . Nid ( ) ;
int tid = ChannelID . Tid ( ) ;
for ( cChannel * channel = First ( ) ; channel ; channel = Next ( channel ) ) {
if ( channel - > Tid ( ) = = tid & & channel - > Nid ( ) = = nid & & channel - > Source ( ) = = source )
return channel ;
}
return NULL ;
}
2002-10-06 10:25:42 +02:00
2002-11-10 15:50:21 +01:00
bool cChannels : : HasUniqueChannelID ( cChannel * NewChannel , cChannel * OldChannel )
{
2002-11-24 14:48:38 +01:00
tChannelID NewChannelID = NewChannel - > GetChannelID ( ) ;
2002-11-10 15:50:21 +01:00
for ( cChannel * channel = First ( ) ; channel ; channel = Next ( channel ) ) {
if ( ! channel - > GroupSep ( ) & & channel ! = OldChannel & & channel - > GetChannelID ( ) = = NewChannelID )
return false ;
}
return true ;
}
2002-10-06 10:25:42 +02:00
bool cChannels : : SwitchTo ( int Number )
{
cChannel * channel = GetByNumber ( Number ) ;
return channel & & cDevice : : PrimaryDevice ( ) - > SwitchChannel ( channel , true ) ;
}
2004-01-04 12:30:00 +01:00
2004-10-17 11:50:21 +02:00
void cChannels : : SetModified ( bool ByUser )
2004-01-04 12:30:00 +01:00
{
2004-10-17 11:50:21 +02:00
modified = ByUser ? CHANNELSMOD_USER : ! modified ? CHANNELSMOD_AUTO : modified ;
2004-01-04 12:30:00 +01:00
}
2004-10-17 11:50:21 +02:00
int cChannels : : Modified ( void )
2004-01-04 12:30:00 +01:00
{
2004-10-17 11:50:21 +02:00
int Result = modified ;
modified = CHANNELSMOD_NONE ;
2004-01-04 12:30:00 +01:00
return Result ;
}
2004-10-31 12:53:00 +01:00
cChannel * cChannels : : NewChannel ( const cChannel * Transponder , const char * Name , const char * ShortName , const char * Provider , int Nid , int Tid , int Sid , int Rid )
2004-01-04 12:30:00 +01:00
{
2004-01-11 15:54:37 +01:00
if ( Transponder ) {
2004-12-26 12:45:22 +01:00
dsyslog ( " creating new channel '%s,%s;%s' on %s transponder %d with id %d-%d-%d-%d " , Name , ShortName , Provider , * cSource : : ToString ( Transponder - > Source ( ) ) , Transponder - > Transponder ( ) , Nid , Tid , Sid , Rid ) ;
2005-08-06 12:13:55 +02:00
cChannel * NewChannel = new cChannel ;
NewChannel - > CopyTransponderData ( Transponder ) ;
2004-10-17 12:22:56 +02:00
NewChannel - > SetId ( Nid , Tid , Sid , Rid ) ;
2004-10-31 12:53:00 +01:00
NewChannel - > SetName ( Name , ShortName , Provider ) ;
2004-01-11 15:54:37 +01:00
Add ( NewChannel ) ;
ReNumber ( ) ;
return NewChannel ;
}
2004-01-04 12:30:00 +01:00
return NULL ;
}
2004-05-16 10:35:36 +02:00
2004-12-26 12:45:22 +01:00
cString ChannelString ( const cChannel * Channel , int Number )
2004-05-16 10:35:36 +02:00
{
2004-12-26 12:45:22 +01:00
char buffer [ 256 ] ;
2004-05-16 10:35:36 +02:00
if ( Channel ) {
if ( Channel - > GroupSep ( ) )
snprintf ( buffer , sizeof ( buffer ) , " %s " , Channel - > Name ( ) ) ;
else
snprintf ( buffer , sizeof ( buffer ) , " %d%s %s " , Channel - > Number ( ) , Number ? " - " : " " , Channel - > Name ( ) ) ;
}
else if ( Number )
snprintf ( buffer , sizeof ( buffer ) , " %d- " , Number ) ;
else
snprintf ( buffer , sizeof ( buffer ) , " %s " , tr ( " *** Invalid Channel *** " ) ) ;
return buffer ;
}