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 .
*
2020-04-11 09:22:05 +02:00
* $ Id : channels . c 4.6 2020 / 04 / 11 09 : 22 : 05 kls Exp $
2002-10-06 10:25:42 +02:00
*/
# include "channels.h"
# include <ctype.h>
2005-09-04 14:48:39 +02:00
# include "device.h"
2010-06-05 13:50:56 +02:00
# include "libsi/si.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
// --- 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 ;
2013-12-28 11:37:42 +01:00
int fields = sscanf ( s , " %m[^-]-%d-%d-%d-%d " , & sourcebuf , & nid , & tid , & sid , & rid ) ;
2002-11-24 14:48:38 +01:00
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__ ) ;
2010-05-02 15:09:59 +02:00
parameters = " " ;
2004-01-04 12:30:00 +01:00
modification = CHANNELMOD_NONE ;
2014-01-05 10:41:46 +01:00
seen = 0 ;
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 ;
2015-09-01 11:14:27 +02:00
seen = 0 ;
2005-08-06 12:13:55 +02:00
* this = Channel ;
2004-02-08 11:05:22 +01:00
}
cChannel : : ~ cChannel ( )
{
2015-09-01 11:14:27 +02:00
delete linkChannels ; // any links from other channels pointing to this one have been deleted in cChannels::Del()
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__ ) ;
2012-06-17 12:27:07 +02:00
nameSource = NULL ; // these will be recalculated automatically
2017-06-10 15:34:23 +02:00
nameSourceMode = 0 ;
2012-06-17 12:27:07 +02:00
shortNameSource = NULL ;
2010-02-28 12:19:50 +01:00
parameters = Channel . parameters ;
2002-11-10 15:50:21 +01:00
return * this ;
}
2012-06-17 12:27:07 +02:00
const char * cChannel : : Name ( void ) const
{
2012-07-14 12:15:00 +02:00
if ( Setup . ShowChannelNamesWithSource & & ! groupSep ) {
2017-06-10 15:34:23 +02:00
if ( isempty ( nameSource ) | | nameSourceMode ! = Setup . ShowChannelNamesWithSource ) {
if ( Setup . ShowChannelNamesWithSource = = 1 )
nameSource = cString : : sprintf ( " %s (%c) " , name , cSource : : ToChar ( source ) ) ;
else
nameSource = cString : : sprintf ( " %s (%s) " , name , * cSource : : ToString ( source ) ) ;
}
2012-06-17 12:27:07 +02:00
return nameSource ;
}
return name ;
}
const char * cChannel : : ShortName ( bool OrName ) const
{
if ( OrName & & isempty ( shortName ) )
return Name ( ) ;
2012-07-14 12:15:00 +02:00
if ( Setup . ShowChannelNamesWithSource & & ! groupSep ) {
2012-06-17 12:27:07 +02:00
if ( isempty ( shortNameSource ) )
shortNameSource = cString : : sprintf ( " %s (%c) " , shortName , cSource : : ToChar ( source ) ) ;
return shortNameSource ;
}
return shortName ;
}
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:
2010-02-28 12:19:50 +01:00
switch ( toupper ( 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 ;
2010-02-28 12:19:50 +01:00
if ( IsSat ( ) ) {
const char * p = strpbrk ( parameters , " HVLRhvlr " ) ; // lowercase for backwards compatibility
if ( p )
tf = Transponder ( tf , * p ) ;
}
2004-01-04 12:30:00 +01:00
return tf ;
2002-11-10 15:50:21 +01:00
}
2015-09-01 11:14:27 +02:00
int cChannel : : Modification ( int Mask ) const
2004-01-04 12:30:00 +01:00
{
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 ;
2010-02-28 12:19:50 +01:00
parameters = Channel - > parameters ;
2005-08-06 12:13:55 +02:00
}
}
2010-02-28 12:19:50 +01:00
bool cChannel : : SetTransponderData ( int Source , int Frequency , int Srate , const char * Parameters , bool Quiet )
2004-01-11 15:54:37 +01:00
{
2010-02-28 12:19:50 +01:00
if ( strchr ( Parameters , ' : ' ) ) {
esyslog ( " ERROR: parameter string '%s' contains ':' " , Parameters ) ;
return false ;
}
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
2010-02-28 12:19:50 +01:00
if ( source ! = Source | | frequency ! = Frequency | | srate ! = Srate | | strcmp ( parameters , Parameters ) ) {
2008-04-12 13:52:57 +02:00
cString OldTransponderData = TransponderDataToString ( ) ;
2004-01-11 15:54:37 +01:00
source = Source ;
frequency = Frequency ;
srate = Srate ;
2010-02-28 12:19:50 +01:00
parameters = Parameters ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2012-07-14 12:15:00 +02:00
nameSource = NULL ;
2017-06-10 15:34:23 +02:00
nameSourceMode = 0 ;
2012-07-14 12:15:00 +02:00
shortNameSource = NULL ;
2010-02-28 12:19:50 +01:00
if ( Number ( ) & & ! Quiet ) {
2015-01-14 12:17:39 +01:00
dsyslog ( " changing transponder data of channel %d (%s) from %s to %s " , Number ( ) , name , * OldTransponderData , * TransponderDataToString ( ) ) ;
2008-04-12 13:39:12 +02:00
modification | = CHANNELMOD_TRANSP ;
}
2015-09-01 11:14:27 +02:00
return true ;
2004-01-11 15:54:37 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2004-01-11 15:54:37 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetSource ( int Source )
2015-03-13 12:12:33 +01:00
{
if ( source ! = Source ) {
if ( Number ( ) ) {
dsyslog ( " changing source of channel %d (%s) from %s to %s " , Number ( ) , name , * cSource : : ToString ( source ) , * cSource : : ToString ( Source ) ) ;
modification | = CHANNELMOD_TRANSP ;
}
source = Source ;
2015-09-01 11:14:27 +02:00
return true ;
2015-03-13 12:12:33 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2015-03-13 12:12:33 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetId ( cChannels * Channels , 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 ) {
2015-09-01 11:14:27 +02:00
if ( Channels & & Number ( ) ) {
2015-01-14 12:17:39 +01:00
dsyslog ( " changing id of channel %d (%s) from %d-%d-%d-%d to %d-%d-%d-%d " , Number ( ) , name , nid , tid , sid , rid , Nid , Tid , Sid , Rid ) ;
2004-10-17 12:22:56 +02:00
modification | = CHANNELMOD_ID ;
2015-09-01 11:14:27 +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 ;
2015-09-01 11:14:27 +02:00
if ( Channels )
Channels - > HashChannel ( this ) ;
2006-01-14 15:52:40 +01:00
schedule = NULL ;
2015-09-01 11:14:27 +02:00
return true ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetLcn ( int Lcn )
2015-02-01 13:49:10 +01:00
{
if ( lcn ! = Lcn ) {
if ( Number ( ) )
dsyslog ( " changing lcn of channel %d (%s) from %d to %d \n " , Number ( ) , name , lcn , Lcn ) ;
lcn = Lcn ;
2015-09-01 11:14:27 +02:00
return true ;
2015-02-01 13:49:10 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2015-02-01 13:49:10 +01:00
}
2015-09-01 11:14:27 +02:00
bool 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 ;
}
2012-06-17 12:27:07 +02:00
if ( nn ) {
2004-11-02 18:07:05 +01:00
name = strcpyrealloc ( name , Name ) ;
2012-06-17 12:27:07 +02:00
nameSource = NULL ;
2017-06-10 15:34:23 +02:00
nameSourceMode = 0 ;
2012-06-17 12:27:07 +02:00
}
if ( ns ) {
2004-11-02 18:07:05 +01:00
shortName = strcpyrealloc ( shortName , ShortName ) ;
2012-06-17 12:27:07 +02:00
shortNameSource = NULL ;
}
2004-11-02 18:07:05 +01:00
if ( np )
provider = strcpyrealloc ( provider , Provider ) ;
2015-09-01 11:14:27 +02:00
return true ;
2004-10-17 12:22:56 +02:00
}
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetPortalName ( const char * PortalName )
2004-10-31 13:01:35 +01:00
{
if ( ! isempty ( PortalName ) & & strcmp ( portalName , PortalName ) ! = 0 ) {
if ( Number ( ) ) {
2015-01-14 12:17:39 +01:00
dsyslog ( " changing portal name of channel %d (%s) from '%s' to '%s' " , Number ( ) , name , portalName , PortalName ) ;
2004-10-31 13:01:35 +01:00
modification | = CHANNELMOD_NAME ;
}
portalName = strcpyrealloc ( portalName , PortalName ) ;
2015-09-01 11:14:27 +02:00
return true ;
2004-10-31 13:01:35 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2004-10-31 13:01:35 +01:00
}
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 + + ) {
2010-11-07 12:27:25 +01:00
if ( ! a [ i ] | | ! b [ i ] ) {
result | = VALDIFF ;
break ;
}
if ( na & & nb & & strcmp ( na [ i ] , nb [ i ] ) ! = 0 )
2005-05-07 13:15:34 +02:00
result | = STRDIFF ;
if ( a [ i ] ! = b [ i ] )
result | = VALDIFF ;
}
return result ;
2004-01-25 15:32:08 +01:00
}
2010-05-16 13:36:55 +02:00
static int IntArrayToString ( char * s , const int * a , int Base = 10 , const char n [ ] [ MAXLANGCODE2 ] = NULL , const int * t = 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 ] ) ;
2010-05-16 13:36:55 +02:00
const char * Delim = " = " ;
if ( a [ i ] ) {
if ( n & & * n [ i ] ) {
q + = sprintf ( q , " %s%s " , Delim , n [ i ] ) ;
Delim = " " ;
}
if ( t & & t [ i ] )
q + = sprintf ( q , " %s@%d " , Delim , t [ 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 ;
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetPids ( int Vpid , int Ppid , int Vtype , int * Apids , int * Atypes , char ALangs [ ] [ MAXLANGCODE2 ] , int * Dpids , int * Dtypes , 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 ;
2013-11-04 10:11:51 +01:00
if ( vpid ! = Vpid | | ppid ! = Ppid | | vtype ! = Vtype )
2005-05-07 13:15:34 +02:00
mod | = CHANNELMOD_PIDS ;
2013-11-04 10:11:51 +01:00
if ( tpid ! = Tpid )
mod | = CHANNELMOD_AUX ;
2010-06-05 13:50:56 +02:00
int m = IntArraysDiffer ( apids , Apids , alangs , ALangs ) | IntArraysDiffer ( atypes , Atypes ) | IntArraysDiffer ( dpids , Dpids , dlangs , DLangs ) | IntArraysDiffer ( dtypes , Dtypes ) | 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 ) {
2010-05-16 13:36:55 +02:00
const int BufferSize = ( MAXAPIDS + MAXDPIDS ) * ( 5 + 1 + MAXLANGCODE2 + 5 ) + 10 ; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod@type', +10: paranoia
2005-09-04 14:48:39 +02:00
char OldApidsBuf [ BufferSize ] ;
char NewApidsBuf [ BufferSize ] ;
2004-01-25 15:32:08 +01:00
char * q = OldApidsBuf ;
2010-05-16 13:36:55 +02:00
q + = IntArrayToString ( q , apids , 10 , alangs , atypes ) ;
2004-01-25 15:32:08 +01:00
if ( dpids [ 0 ] ) {
* q + + = ' ; ' ;
2010-06-05 13:50:56 +02:00
q + = IntArrayToString ( q , dpids , 10 , dlangs , dtypes ) ;
2004-01-25 15:32:08 +01:00
}
* q = 0 ;
q = NewApidsBuf ;
2010-05-16 13:36:55 +02:00
q + = IntArrayToString ( q , Apids , 10 , ALangs , Atypes ) ;
2004-01-25 15:32:08 +01:00
if ( Dpids [ 0 ] ) {
* q + + = ' ; ' ;
2010-06-05 13:50:56 +02:00
q + = IntArrayToString ( q , Dpids , 10 , DLangs , Dtypes ) ;
2004-01-25 15:32:08 +01:00
}
* 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 ( ) )
2015-01-14 12:17:39 +01:00
dsyslog ( " changing pids of channel %d (%s) from %d+%d=%d:%s:%s:%d to %d+%d=%d:%s:%s:%d " , Number ( ) , name , 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 ] ;
2010-05-16 13:36:55 +02:00
atypes [ i ] = Atypes [ 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 ] ;
2010-06-05 13:50:56 +02:00
dtypes [ i ] = Dtypes [ 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 ;
2015-09-01 11:14:27 +02:00
return true ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetSubtitlingDescriptors ( uchar * SubtitlingTypes , uint16_t * CompositionPageIds , uint16_t * AncillaryPageIds )
2009-08-16 15:32:39 +02:00
{
2015-09-01 11:14:27 +02:00
bool Modified = false ;
2009-08-16 15:32:39 +02:00
if ( SubtitlingTypes ) {
2015-09-01 11:14:27 +02:00
for ( int i = 0 ; i < MAXSPIDS ; i + + ) {
Modified = subtitlingTypes [ i ] ! = SubtitlingTypes [ i ] ;
2009-08-16 15:32:39 +02:00
subtitlingTypes [ i ] = SubtitlingTypes [ i ] ;
2015-09-01 11:14:27 +02:00
}
2009-08-16 15:32:39 +02:00
}
if ( CompositionPageIds ) {
2015-09-01 11:14:27 +02:00
for ( int i = 0 ; i < MAXSPIDS ; i + + ) {
Modified = compositionPageIds [ i ] ! = CompositionPageIds [ i ] ;
2009-08-16 15:32:39 +02:00
compositionPageIds [ i ] = CompositionPageIds [ i ] ;
2015-09-01 11:14:27 +02:00
}
2009-08-16 15:32:39 +02:00
}
if ( AncillaryPageIds ) {
2015-09-01 11:14:27 +02:00
for ( int i = 0 ; i < MAXSPIDS ; i + + ) {
Modified = ancillaryPageIds [ i ] ! = AncillaryPageIds [ i ] ;
2009-08-16 15:32:39 +02:00
ancillaryPageIds [ i ] = AncillaryPageIds [ i ] ;
2015-09-01 11:14:27 +02:00
}
2009-08-16 15:32:39 +02:00
}
2015-09-01 11:14:27 +02:00
return Modified ;
2009-08-16 15:32:39 +02:00
}
2014-01-05 10:41:46 +01:00
void cChannel : : SetSeen ( void )
{
seen = time ( NULL ) ;
}
2015-09-01 11:14:27 +02:00
void cChannel : : DelLinkChannel ( cChannel * LinkChannel )
{
if ( linkChannels ) {
for ( cLinkChannel * lc = linkChannels - > First ( ) ; lc ; lc = linkChannels - > Next ( lc ) ) {
if ( lc - > Channel ( ) = = LinkChannel ) {
linkChannels - > Del ( lc ) ;
break ;
}
}
if ( linkChannels - > Count ( ) = = 0 ) {
delete linkChannels ;
linkChannels = NULL ;
}
}
}
bool cChannel : : SetCaIds ( const int * CaIds )
2004-01-04 12:30:00 +01:00
{
2009-04-25 13:57:32 +02:00
if ( caids [ 0 ] & & caids [ 0 ] < = CA_USER_MAX )
2015-09-01 11:14:27 +02:00
return false ; // 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 ( ) )
2015-01-14 12:17:39 +01:00
dsyslog ( " changing caids of channel %d (%s) from %s to %s " , Number ( ) , name , 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 ;
2015-09-01 11:14:27 +02:00
return true ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetCaDescriptors ( int Level )
2004-01-04 12:30:00 +01:00
{
if ( Level > 0 ) {
modification | = CHANNELMOD_CA ;
2009-08-30 11:32:39 +02:00
if ( Number ( ) & & Level > 1 )
2015-01-14 12:17:39 +01:00
dsyslog ( " changing ca descriptors of channel %d (%s) " , Number ( ) , name ) ;
2015-09-01 11:14:27 +02:00
return true ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
return false ;
2002-10-06 10:25:42 +02:00
}
2015-09-01 11:14:27 +02:00
bool cChannel : : SetLinkChannels ( cLinkChannels * LinkChannels )
2004-02-08 11:05:22 +01:00
{
if ( ! linkChannels & & ! LinkChannels )
2015-09-01 11:14:27 +02:00
return false ;
2004-02-08 11:05:22 +01:00
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 ;
2015-09-01 11:14:27 +02:00
return false ; // linkage has not changed
2004-02-08 11:05:22 +01:00
}
}
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 ;
2015-01-14 12:17:39 +01:00
q + = sprintf ( q , " linking channel %d (%s) from " , Number ( ) , name ) ;
2004-02-08 11:05:22 +01:00
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 ) ;
2015-09-01 11:14:27 +02:00
return true ;
2004-02-08 11:05:22 +01:00
}
void cChannel : : SetRefChannel ( cChannel * RefChannel )
{
refChannel = RefChannel ;
}
2008-04-12 13:52:57 +02:00
cString cChannel : : TransponderDataToString ( void ) const
{
if ( cSource : : IsTerr ( source ) )
2010-02-28 12:19:50 +01:00
return cString : : sprintf ( " %d:%s:%s " , frequency , * parameters , * cSource : : ToString ( source ) ) ;
return cString : : sprintf ( " %d:%s:%s:%d " , frequency , * parameters , * cSource : : ToString ( source ) , srate ) ;
2002-10-06 10:25:42 +02:00
}
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 ) ;
2013-10-11 11:38:05 +02:00
if ( ! Channel - > groupSep ) {
if ( ! isempty ( Channel - > shortName ) )
q + = sprintf ( q , " ,%s " , Channel - > shortName ) ;
else if ( strchr ( Channel - > name , ' , ' ) )
q + = sprintf ( q , " , " ) ;
if ( ! isempty ( Channel - > provider ) )
q + = sprintf ( q , " ;%s " , Channel - > provider ) ;
}
2004-10-31 12:53:00 +01:00
* 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 )
2015-09-10 10:39:45 +02:00
buffer = cString : : sprintf ( " :@%d %s " , Channel - > number , FullName ) ;
2002-10-19 15:33:37 +02:00
else
2015-09-10 10:39:45 +02:00
buffer = cString : : sprintf ( " :%s " , 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 ;
2011-08-21 14:18:37 +02:00
const int ABufferSize = ( MAXAPIDS + MAXDPIDS ) * ( 5 + 1 + MAXLANGCODE2 + 5 ) + 10 ; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod@type', +10: paranoia
char apidbuf [ ABufferSize ] ;
2003-04-26 11:58:54 +02:00
q = apidbuf ;
2010-05-16 13:36:55 +02:00
q + = IntArrayToString ( q , Channel - > apids , 10 , Channel - > alangs , Channel - > atypes ) ;
2004-01-25 15:32:08 +01:00
if ( Channel - > dpids [ 0 ] ) {
* q + + = ' ; ' ;
2010-06-05 13:50:56 +02:00
q + = IntArrayToString ( q , Channel - > dpids , 10 , Channel - > dlangs , Channel - > dtypes ) ;
2004-01-25 15:32:08 +01:00
}
2002-10-06 10:25:42 +02:00
* q = 0 ;
2011-08-21 14:18:37 +02:00
const int TBufferSize = MAXSPIDS * ( 5 + 1 + MAXLANGCODE2 ) + 10 ; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia and tpid
char tpidbuf [ TBufferSize ] ;
q = tpidbuf ;
q + = snprintf ( q , sizeof ( tpidbuf ) , " %d " , Channel - > tpid ) ;
if ( Channel - > spids [ 0 ] ) {
* q + + = ' ; ' ;
q + = IntArrayToString ( q , Channel - > spids , 10 , Channel - > slangs ) ;
}
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 ;
2015-09-10 10:39:45 +02:00
buffer = cString : : sprintf ( " %s:%d:%s:%s:%d:%s:%s:%s:%s:%d:%d:%d:%d " , FullName , Channel - > frequency , * Channel - > parameters , * cSource : : ToString ( Channel - > source ) , Channel - > srate , vpidbuf , apidbuf , tpidbuf , 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 ;
2011-08-21 14:18:37 +02:00
char * tpidbuf = NULL ;
2004-01-04 12:30:00 +01:00
char * caidbuf = NULL ;
2013-12-28 11:37:42 +01:00
int fields = sscanf ( s , " %m[^:]:%d :%m[^:]:%m[^:] :%d :%m[^:]:%m[^:]:%m[^:]:%m[^:]:%d :%d :%d :%d " , & namebuf , & frequency , & parambuf , & sourcebuf , & srate , & vpidbuf , & apidbuf , & tpidbuf , & 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 ;
2011-08-21 14:18:37 +02:00
if ( sscanf ( tpidbuf , " %d " , & tpid ) ! = 1 )
return false ;
2004-01-04 12:30:00 +01:00
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 ;
2010-05-16 13:36:55 +02:00
atypes [ 0 ] = 0 ;
2004-01-25 15:32:08 +01:00
dpids [ 0 ] = 0 ;
2010-06-05 13:50:56 +02:00
dtypes [ 0 ] = 0 ;
2011-08-21 14:18:37 +02:00
spids [ 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 ) {
2010-02-28 12:19:50 +01:00
parameters = parambuf ;
ok = ( 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 ) {
2010-05-16 13:36:55 +02:00
atypes [ NumApids ] = 4 ; // backwards compatibility
2004-01-25 15:32:08 +01:00
char * l = strchr ( q , ' = ' ) ;
if ( l ) {
* l + + = 0 ;
2010-05-16 13:36:55 +02:00
char * t = strchr ( l , ' @ ' ) ;
if ( t ) {
* t + + = 0 ;
atypes [ NumApids ] = strtol ( t , NULL , 10 ) ;
}
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 ;
2012-03-08 09:37:17 +01:00
if ( ( apids [ NumApids ] = strtol ( q , NULL , 10 ) ) ! = 0 )
NumApids + + ;
2004-01-25 15:32:08 +01:00
}
else
esyslog ( " ERROR: too many APIDs! " ) ; // no need to set ok to 'false'
p = NULL ;
}
apids [ NumApids ] = 0 ;
2010-05-16 13:36:55 +02:00
atypes [ NumApids ] = 0 ;
2004-01-25 15:32:08 +01:00
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 ) {
2010-06-05 13:50:56 +02:00
dtypes [ NumDpids ] = SI : : AC3DescriptorTag ; // backwards compatibility
2004-01-25 15:32:08 +01:00
char * l = strchr ( q , ' = ' ) ;
if ( l ) {
* l + + = 0 ;
2010-06-05 13:50:56 +02:00
char * t = strchr ( l , ' @ ' ) ;
if ( t ) {
* t + + = 0 ;
dtypes [ NumDpids ] = strtol ( t , NULL , 10 ) ;
}
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 ;
2012-03-08 09:37:17 +01:00
if ( ( dpids [ NumDpids ] = strtol ( q , NULL , 10 ) ) ! = 0 )
NumDpids + + ;
2004-01-25 15:32:08 +01:00
}
else
esyslog ( " ERROR: too many DPIDs! " ) ; // no need to set ok to 'false'
p = NULL ;
}
dpids [ NumDpids ] = 0 ;
2010-06-05 13:50:56 +02:00
dtypes [ NumDpids ] = 0 ;
2004-01-25 15:32:08 +01:00
}
2011-08-21 14:18:37 +02:00
int NumSpids = 0 ;
if ( ( p = strchr ( tpidbuf , ' ; ' ) ) ! = NULL ) {
* p + + = 0 ;
char * q ;
char * strtok_next ;
while ( ( q = strtok_r ( p , " , " , & strtok_next ) ) ! = NULL ) {
if ( NumSpids < MAXSPIDS ) {
char * l = strchr ( q , ' = ' ) ;
if ( l ) {
* l + + = 0 ;
strn0cpy ( slangs [ NumSpids ] , l , MAXLANGCODE2 ) ;
}
else
* slangs [ NumSpids ] = 0 ;
spids [ NumSpids + + ] = strtol ( q , NULL , 10 ) ;
}
else
esyslog ( " ERROR: too many SPIDs! " ) ; // no need to set ok to 'false'
p = NULL ;
}
spids [ NumSpids ] = 0 ;
}
2011-08-26 12:44:21 +02:00
if ( sscanf ( tpidbuf , " %d " , & tpid ) ! = 1 )
return false ;
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 ) ;
2011-08-21 14:18:37 +02:00
free ( tpidbuf ) ;
2004-01-04 12:30:00 +01:00
free ( caidbuf ) ;
2002-10-06 10:25:42 +02:00
free ( namebuf ) ;
2012-06-17 12:27:07 +02:00
nameSource = NULL ;
2017-06-10 15:34:23 +02:00
nameSourceMode = 0 ;
2012-06-17 12:27:07 +02:00
shortNameSource = NULL ;
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 )
{
2015-09-10 10:39:45 +02:00
return fprintf ( f , " %s \n " , * 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
2015-09-01 11:14:27 +02:00
cChannels cChannels : : channels ;
int cChannels : : maxNumber = 0 ;
int cChannels : : maxChannelNameLength = 0 ;
int cChannels : : maxShortChannelNameLength = 0 ;
2002-10-06 10:25:42 +02:00
2004-01-04 12:30:00 +01:00
cChannels : : cChannels ( void )
2017-05-28 12:47:54 +02:00
: cConfig < cChannel > ( " 2 Channels " )
2004-01-04 12:30:00 +01:00
{
2015-09-01 11:14:27 +02:00
modifiedByUser = 0 ;
}
const cChannels * cChannels : : GetChannelsRead ( cStateKey & StateKey , int TimeoutMs )
{
return channels . Lock ( StateKey , false , TimeoutMs ) ? & channels : NULL ;
}
cChannels * cChannels : : GetChannelsWrite ( cStateKey & StateKey , int TimeoutMs )
{
return channels . Lock ( StateKey , true , TimeoutMs ) ? & channels : NULL ;
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 ;
2015-09-01 11:14:27 +02:00
for ( cChannel * Channel = First ( ) ; Channel ; Channel = Next ( Channel ) ) {
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 ) {
2015-09-01 11:14:27 +02:00
cChannelSorter * Next = ChannelSorter . Next ( cs ) ;
if ( Next & & cs - > channelID = = Next - > channelID ) {
dsyslog ( " deleting duplicate channel %s " , * Next - > channel - > ToText ( ) ) ;
Del ( Next - > channel ) ;
2005-05-29 10:33:21 +02:00
}
2015-09-01 11:14:27 +02:00
cs = Next ;
2005-05-29 10:33:21 +02:00
}
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
{
2015-09-01 11:14:27 +02:00
LOCK_CHANNELS_WRITE ;
if ( channels . cConfig < cChannel > : : Load ( FileName , AllowComments , MustExist ) ) {
channels . DeleteDuplicateChannels ( ) ;
channels . ReNumber ( ) ;
2002-10-06 10:25:42 +02:00
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 ( ) ) ;
}
2015-09-01 11:14:27 +02:00
int cChannels : : GetNextGroup ( int Idx ) const
2002-10-06 10:25:42 +02:00
{
2015-09-01 11:14:27 +02:00
const cChannel * Channel = Get ( + + Idx ) ;
while ( Channel & & ! ( Channel - > GroupSep ( ) & & * Channel - > Name ( ) ) )
Channel = Get ( + + Idx ) ;
return Channel ? Idx : - 1 ;
2002-10-06 10:25:42 +02:00
}
2015-09-01 11:14:27 +02:00
int cChannels : : GetPrevGroup ( int Idx ) const
2002-10-06 10:25:42 +02:00
{
2015-09-01 11:14:27 +02:00
const cChannel * Channel = Get ( - - Idx ) ;
while ( Channel & & ! ( Channel - > GroupSep ( ) & & * Channel - > Name ( ) ) )
Channel = Get ( - - Idx ) ;
return Channel ? Idx : - 1 ;
2002-10-06 10:25:42 +02:00
}
2015-09-01 11:14:27 +02:00
int cChannels : : GetNextNormal ( int Idx ) const
2002-10-06 10:25:42 +02:00
{
2015-09-01 11:14:27 +02:00
const cChannel * Channel = Get ( + + Idx ) ;
while ( Channel & & Channel - > GroupSep ( ) )
Channel = Get ( + + Idx ) ;
return Channel ? Idx : - 1 ;
2002-10-06 10:25:42 +02:00
}
2015-09-01 11:14:27 +02:00
int cChannels : : GetPrevNormal ( int Idx ) const
2006-05-28 10:48:50 +02:00
{
2015-09-01 11:14:27 +02:00
const cChannel * Channel = Get ( - - Idx ) ;
while ( Channel & & Channel - > GroupSep ( ) )
Channel = Get ( - - Idx ) ;
return Channel ? Idx : - 1 ;
2006-05-28 10:48:50 +02:00
}
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 ;
2015-09-01 11:14:27 +02:00
for ( cChannel * Channel = First ( ) ; Channel ; Channel = Next ( Channel ) ) {
if ( Channel - > GroupSep ( ) ) {
if ( Channel - > Number ( ) > Number )
Number = Channel - > Number ( ) ;
2002-10-19 15:33:37 +02:00
}
2003-10-03 15:16:08 +02:00
else {
2015-09-01 11:14:27 +02:00
HashChannel ( Channel ) ;
2003-10-03 15:16:08 +02:00
maxNumber = Number ;
2015-09-01 11:14:27 +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
}
2020-04-11 09:22:05 +02:00
bool cChannels : : MoveNeedsDecrement ( cChannel * From , cChannel * To )
{
int Number = From - > Number ( ) ;
if ( Number < To - > Number ( ) ) {
for ( cChannel * Channel = Next ( From ) ; Channel ; Channel = Next ( Channel ) ) {
if ( Channel = = To )
break ;
if ( Channel - > GroupSep ( ) ) {
if ( Channel - > Number ( ) > Number )
Number = Channel - > Number ( ) ;
}
else
Number + + ;
}
return Number = = To - > Number ( ) ;
}
return false ;
}
2015-09-01 11:14:27 +02:00
void cChannels : : Del ( cChannel * Channel )
2002-10-06 10:25:42 +02:00
{
2015-09-01 11:14:27 +02:00
UnhashChannel ( Channel ) ;
for ( cChannel * ch = First ( ) ; ch ; ch = Next ( ch ) )
ch - > DelLinkChannel ( Channel ) ;
cList < cChannel > : : Del ( Channel ) ;
}
const cChannel * cChannels : : GetByNumber ( int Number , int SkipGap ) const
{
const cChannel * Previous = NULL ;
for ( const 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-19 15:33:37 +02:00
}
}
2002-10-06 10:25:42 +02:00
return NULL ;
}
2015-09-01 11:14:27 +02:00
const cChannel * cChannels : : GetByServiceID ( int Source , int Transponder , unsigned short ServiceID ) const
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 ) ) {
2015-09-01 11:14:27 +02:00
cChannel * Channel = ( cChannel * ) hobj - > Object ( ) ;
if ( Channel - > Sid ( ) = = ServiceID & & Channel - > Source ( ) = = Source & & ISTRANSPONDER ( Channel - > Transponder ( ) , Transponder ) )
return Channel ;
2005-09-11 13:23:49 +02:00
}
}
2002-11-10 15:50:21 +01:00
return NULL ;
}
2015-09-01 11:14:27 +02:00
const cChannel * cChannels : : GetByChannelID ( tChannelID ChannelID , bool TryWithoutRid , bool TryWithoutPolarization ) const
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 ) ) {
2015-09-01 11:14:27 +02:00
cChannel * Channel = ( cChannel * ) hobj - > Object ( ) ;
if ( Channel - > Sid ( ) = = sid & & Channel - > GetChannelID ( ) = = ChannelID )
return Channel ;
2004-02-13 15:50:26 +01:00
}
2005-09-11 13:23:49 +02:00
if ( TryWithoutRid ) {
ChannelID . ClrRid ( ) ;
for ( cHashObject * hobj = list - > First ( ) ; hobj ; hobj = list - > Next ( hobj ) ) {
2015-09-01 11:14:27 +02:00
cChannel * Channel = ( cChannel * ) hobj - > Object ( ) ;
if ( Channel - > Sid ( ) = = sid & & Channel - > GetChannelID ( ) . ClrRid ( ) = = ChannelID )
return Channel ;
2005-09-11 13:23:49 +02:00
}
}
if ( TryWithoutPolarization ) {
ChannelID . ClrPolarization ( ) ;
for ( cHashObject * hobj = list - > First ( ) ; hobj ; hobj = list - > Next ( hobj ) ) {
2015-09-01 11:14:27 +02:00
cChannel * Channel = ( cChannel * ) hobj - > Object ( ) ;
if ( Channel - > Sid ( ) = = sid & & Channel - > GetChannelID ( ) . ClrPolarization ( ) = = ChannelID )
return Channel ;
2005-09-11 13:23:49 +02:00
}
}
2004-02-13 15:50:26 +01:00
}
2002-10-06 10:25:42 +02:00
return NULL ;
}
2015-09-01 11:14:27 +02:00
const cChannel * cChannels : : GetByTransponderID ( tChannelID ChannelID ) const
2007-07-21 15:05:20 +02:00
{
int source = ChannelID . Source ( ) ;
int nid = ChannelID . Nid ( ) ;
int tid = ChannelID . Tid ( ) ;
2015-09-01 11:14:27 +02:00
for ( const cChannel * Channel = First ( ) ; Channel ; Channel = Next ( Channel ) ) {
if ( Channel - > Tid ( ) = = tid & & Channel - > Nid ( ) = = nid & & Channel - > Source ( ) = = source )
return Channel ;
2007-07-21 15:05:20 +02:00
}
return NULL ;
}
2002-10-06 10:25:42 +02:00
2015-09-01 11:14:27 +02:00
bool cChannels : : HasUniqueChannelID ( const cChannel * NewChannel , const cChannel * OldChannel ) const
2002-11-10 15:50:21 +01:00
{
2002-11-24 14:48:38 +01:00
tChannelID NewChannelID = NewChannel - > GetChannelID ( ) ;
2015-09-01 11:14:27 +02:00
for ( const cChannel * Channel = First ( ) ; Channel ; Channel = Next ( Channel ) ) {
if ( ! Channel - > GroupSep ( ) & & Channel ! = OldChannel & & Channel - > GetChannelID ( ) = = NewChannelID )
2002-11-10 15:50:21 +01:00
return false ;
}
return true ;
}
2015-09-01 11:14:27 +02:00
bool cChannels : : SwitchTo ( int Number ) const
2002-10-06 10:25:42 +02:00
{
2015-09-01 11:14:27 +02:00
const cChannel * Channel = GetByNumber ( Number ) ;
return Channel & & cDevice : : PrimaryDevice ( ) - > SwitchChannel ( Channel , true ) ;
2002-10-06 10:25:42 +02:00
}
2004-01-04 12:30:00 +01:00
2012-03-11 13:29:06 +01:00
int cChannels : : MaxChannelNameLength ( void )
{
if ( ! maxChannelNameLength ) {
2015-09-01 11:14:27 +02:00
LOCK_CHANNELS_READ ;
for ( const cChannel * Channel = Channels - > First ( ) ; Channel ; Channel = Channels - > Next ( Channel ) ) {
if ( ! Channel - > GroupSep ( ) )
maxChannelNameLength = max ( Utf8StrLen ( Channel - > Name ( ) ) , maxChannelNameLength ) ;
2012-03-11 13:29:06 +01:00
}
}
return maxChannelNameLength ;
}
int cChannels : : MaxShortChannelNameLength ( void )
{
if ( ! maxShortChannelNameLength ) {
2015-09-01 11:14:27 +02:00
LOCK_CHANNELS_READ ;
for ( const cChannel * Channel = Channels - > First ( ) ; Channel ; Channel = Channels - > Next ( Channel ) ) {
if ( ! Channel - > GroupSep ( ) )
maxShortChannelNameLength = max ( Utf8StrLen ( Channel - > ShortName ( true ) ) , maxShortChannelNameLength ) ;
2012-03-11 13:29:06 +01:00
}
}
return maxShortChannelNameLength ;
}
2015-09-01 11:14:27 +02:00
void cChannels : : SetModifiedByUser ( void )
2004-01-04 12:30:00 +01:00
{
2015-09-01 11:14:27 +02:00
modifiedByUser + + ;
2012-03-11 13:29:06 +01:00
maxChannelNameLength = maxShortChannelNameLength = 0 ;
2004-01-04 12:30:00 +01:00
}
2015-09-01 11:14:27 +02:00
bool cChannels : : ModifiedByUser ( int & State ) const
2004-01-04 12:30:00 +01:00
{
2015-09-01 11:14:27 +02:00
int Result = State ! = modifiedByUser ;
State = modifiedByUser ;
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 ) ;
2015-09-01 11:14:27 +02:00
NewChannel - > SetId ( this , Nid , Tid , Sid , Rid ) ;
2004-10-31 12:53:00 +01:00
NewChannel - > SetName ( Name , ShortName , Provider ) ;
2014-01-05 10:41:46 +01:00
NewChannel - > SetSeen ( ) ;
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
2014-01-05 10:41:46 +01:00
# define CHANNELMARKOBSOLETE "OBSOLETE"
# define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before)
2015-09-01 11:14:27 +02:00
bool cChannels : : MarkObsoleteChannels ( int Source , int Nid , int Tid )
2014-01-05 10:41:46 +01:00
{
2015-09-01 11:14:27 +02:00
bool ChannelsModified = false ;
for ( cChannel * Channel = First ( ) ; Channel ; Channel = Next ( Channel ) ) {
if ( time ( NULL ) - Channel - > Seen ( ) > CHANNELTIMEOBSOLETE & & Channel - > Source ( ) = = Source & & Channel - > Nid ( ) = = Nid & & Channel - > Tid ( ) = = Tid & & Channel - > Rid ( ) = = 0 ) {
2017-06-10 15:34:23 +02:00
int OldShowChannelNamesWithSource = Setup . ShowChannelNamesWithSource ;
Setup . ShowChannelNamesWithSource = 0 ;
2015-09-01 11:14:27 +02:00
if ( ! endswith ( Channel - > Name ( ) , CHANNELMARKOBSOLETE ) )
ChannelsModified | = Channel - > SetName ( cString : : sprintf ( " %s %s " , Channel - > Name ( ) , CHANNELMARKOBSOLETE ) , Channel - > ShortName ( ) , cString : : sprintf ( " %s %s " , CHANNELMARKOBSOLETE , Channel - > Provider ( ) ) ) ;
2015-01-04 15:11:13 +01:00
Setup . ShowChannelNamesWithSource = OldShowChannelNamesWithSource ;
2014-01-05 10:41:46 +01:00
}
}
2015-09-01 11:14:27 +02:00
return ChannelsModified ;
2014-01-05 10:41:46 +01: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 ;
}